Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions amoro-web/src/components/Sidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ export default defineComponent({
icon: 'catalogs',
},
{
key: 'optimizing',
title: t('optimizing'),
key: 'execution',
title: t('execution'),
icon: 'optimizers',
},
{
Expand Down
2 changes: 2 additions & 0 deletions amoro-web/src/hooks/usePlaceholder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export function usePlaceholder() {
const passwordPh = computed(() => t('password')).value
const filterDBPh = computed(() => t('database', 2)).value
const filterTablePh = computed(() => t('table', 2)).value
const filterDbTblPh = computed(() => t('dbTbl', 2)).value
const namePh = computed(() => t('name')).value
const containerPh = computed(() => t('container')).value
return {
Expand All @@ -48,6 +49,7 @@ export function usePlaceholder() {
passwordPh: t('inputPlaceholder', { inputPh: passwordPh }),
filterDBPh: t('filterPlaceholder', { inputPh: filterDBPh }),
filterTablePh: t('filterPlaceholder', { inputPh: filterTablePh }),
filterDbTblPh: t('filterPlaceholder', { inputPh: filterDbTblPh }),
groupNamePh: t('inputPlaceholder', { inputPh: namePh }),
groupContainer: t('selectPlaceholder', { selectPh: containerPh }),
}
Expand Down
5 changes: 5 additions & 0 deletions amoro-web/src/language/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ export default {
catalogs: 'Catalogs',
catalog: 'Catalog',
tables: 'Tables',
dbTbl: 'DB Table',
processes: 'Processes',
activeProcesses: 'Active Processes',
summary: 'Summary',
optimizing: 'Optimizing',
execution: 'Execution',
terminal: 'Terminal',
settings: 'Settings',
systemSetting: 'System Settings',
Expand Down
5 changes: 5 additions & 0 deletions amoro-web/src/language/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ export default {
catalogs: '目录',
catalog: '目录',
tables: '表',
dbTbl: '数据库表',
optimizing: '优化',
execution: '执行',
terminal: '终端',
settings: '设置',
systemSetting: '系统设置',
Expand All @@ -44,6 +46,9 @@ export default {
database: '库',
tableSize: '表大小',
table: '表',
processes: '进程',
activeProcesses: '活跃进程',
summary: '摘要',
size: '大小',
file: '文件',
files: '文件',
Expand Down
7 changes: 4 additions & 3 deletions amoro-web/src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const Settings = () => import('@/views/settings/index.vue')
const Terminal = () => import('@/views/terminal/index.vue')
const Login = () => import('@/views/login/index.vue')
const Resource = () => import('@/views/resource/index.vue')
const Execution = () => import('@/views/execution/index.vue')
const Overview = () => import('@/views/overview/index.vue')

const routes: Array<RouteRecordRaw> = [
Expand Down Expand Up @@ -70,9 +71,9 @@ const routes: Array<RouteRecordRaw> = [
],
},
{
path: 'optimizing',
name: 'Optimizing',
component: Resource,
path: 'execution',
name: 'Execution',
component: Execution,
},
{
path: 'settings',
Expand Down
125 changes: 125 additions & 0 deletions amoro-web/src/views/execution/components/CreateOptimizerModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
/ -->

<script lang="ts" setup>
import { onMounted, reactive, ref } from 'vue'
import { Modal as AModal } from 'ant-design-vue'
import { usePlaceholder } from '@/hooks/usePlaceholder'
import { createOptimizerResource, getOptimizerGroups } from '@/services/optimize.service'

interface FormState {
resourceGroup: string
parallelism: number
}

const emit = defineEmits<{ (e: 'cancel'): void, (e: 'refresh'): void }>()

const confirmLoading = ref<boolean>(false)
const placeholder = reactive(usePlaceholder())
const formRef = ref()
const formState: FormState = reactive({
resourceGroup: '',
parallelism: 1,
})

const resourceGroupOptions = ref<{ label: string, value: string }[]>([])

async function loadResourceGroups() {
try {
const response = await getOptimizerGroups()
resourceGroupOptions.value = response.map((group: any) => ({
label: group.optimizerGroupName,
value: group.optimizerGroupName,
}))
}
catch (error) {
console.error('Failed to load resource groups:', error)
}
}

function handleOk() {
formRef.value
.validateFields()
.then(async () => {
confirmLoading.value = true
await createOptimizerResource({
optimizerGroup: formState.resourceGroup || '',
parallelism: Number(formState.parallelism),
})
formRef.value.resetFields()
emit('cancel')
emit('refresh')
confirmLoading.value = false
})
.catch(() => {
confirmLoading.value = false
})
}

function handleCancel() {
formRef.value.resetFields()
emit('cancel')
}

onMounted(() => {
loadResourceGroups()
})
</script>

<template>
<AModal
:open="true"
:title="$t('createOptimizer')"
:confirm-loading="confirmLoading"
:closable="false"
@ok="handleOk"
@cancel="handleCancel"
>
<a-form ref="formRef" :model="formState" class="label-120">
<a-form-item
name="resourceGroup"
:label="$t('resourceGroup')"
:rules="[{ required: true, message: `${placeholder.resourceGroupPh}` }]"
>
<a-select
v-model:value="formState.resourceGroup"
:placeholder="placeholder.resourceGroupPh"
>
<a-select-option
v-for="option in resourceGroupOptions"
:key="option.value"
:value="option.value"
>
{{ option.label }}
</a-select-option>
</a-select>
</a-form-item>
<a-form-item
name="parallelism"
:label="$t('parallelism')"
:rules="[{ required: true, message: `${placeholder.parallelismPh}` }]"
>
<a-input
v-model:value="formState.parallelism"
type="number"
:placeholder="placeholder.parallelismPh"
/>
</a-form-item>
</a-form>
</AModal>
</template>
148 changes: 148 additions & 0 deletions amoro-web/src/views/execution/components/GroupModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
/ -->

<script lang="ts" setup>
import { onMounted, reactive, ref } from 'vue'
import { Modal as AModal, message } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import { usePlaceholder } from '@/hooks/usePlaceholder'
import type { IIOptimizeGroupItem } from '@/types/common.type'
import {
addResourceGroupsAPI,
getGroupContainerListAPI,
updateResourceGroupsAPI,
} from '@/services/optimize.service'
import Properties from '@/views/catalogs/Properties.vue'

const props = defineProps<{
edit: boolean
editRecord: IIOptimizeGroupItem | null
}>()

const emit = defineEmits<{
(e: 'cancel'): void
(e: 'refresh'): void
}>()

const { t } = useI18n()

interface FormState {
name: string
container: undefined | string
properties: { [prop: string]: string }
}

const placeholder = reactive(usePlaceholder())
const selectList = ref<{ containerList: any }>({ containerList: [] })
async function getContainerList() {
const result = await getGroupContainerListAPI()
const list = (result || []).map((item: string) => ({
label: item,
value: item,
}))
selectList.value.containerList = list
}

const formState: FormState = reactive({
name: '',
container: undefined,
properties: {},
})

const confirmLoading = ref<boolean>(false)
function handleCancel() {
emit('cancel')
}

const formRef = ref()
const propertiesRef = ref()
function handleOk() {
formRef.value.validateFields().then(async () => {
try {
const properties = await propertiesRef.value.getProperties()
const params = {
name: formState.name,
container: formState.container as string,
properties,
}
if (props.edit) {
await updateResourceGroupsAPI(params)
}
else {
await addResourceGroupsAPI(params)
}
message.success(`${t('save')} ${t('success')}`)
emit('refresh')
}
catch (error) {
message.error(`${t('save')} ${t('failed')}`)
}
})
}

onMounted(() => {
getContainerList()
if (props.edit) {
formState.name = props.editRecord?.name as string
formState.container = props.editRecord?.container
formState.properties = props.editRecord?.resourceGroup.properties as {
[props: string]: string
}
}
})
</script>

<template>
<AModal
:open="true"
:title="edit ? $t('editGroup') : $t('addGroup')"
:confirm-loading="confirmLoading"
:closable="false"
class="group-modal"
@ok="handleOk"
@cancel="handleCancel"
>
<a-form ref="formRef" :model="formState" class="label-120">
<a-form-item name="name" :label="$t('name')" :rules="[{ required: true, message: `${placeholder.groupNamePh}` }]">
<a-input v-model:value="formState.name" :placeholder="placeholder.groupNamePh" :disabled="edit" />
</a-form-item>
<a-form-item
name="container" :label="$t('container')"
:rules="[{ required: true, message: `${placeholder.groupContainer}` }]"
>
<a-select
v-model:value="formState.container" :show-search="true" :options="selectList.containerList"
:placeholder="placeholder.groupContainer"
/>
</a-form-item>
<a-form-item :label="$t('properties')" />
<a-form-item>
<Properties ref="propertiesRef" :properties-obj="formState.properties" :is-edit="true" />
</a-form-item>
</a-form>
</AModal>
</template>

<style lang="less">
.group-modal {
.ant-modal-body {
max-height: 600px;
overflow: auto;
}
}
</style>
Loading