This is an automated email from the ASF dual-hosted git repository.
wuzhiguo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/bigtop-manager.git
The following commit(s) were added to refs/heads/main by this push:
new b207d9e0 BIGTOP-4390: Add service creation page for infra (#190)
b207d9e0 is described below
commit b207d9e032e596192bc10fb2b3ef3c3109b75b90
Author: Fdefined <[email protected]>
AuthorDate: Fri Mar 21 11:52:24 2025 +0800
BIGTOP-4390: Add service creation page for infra (#190)
---
bigtop-manager-ui/src/api/hosts/types.ts | 4 +-
bigtop-manager-ui/src/api/service/types.ts | 1 +
.../components/component-assigner.vue | 38 +++++++---
.../components/component-installer.vue | 8 +-
.../components/service-configurator.vue | 22 ++++--
.../create-service/components/service-selector.vue | 87 ++++++++++++++++++++--
.../create-service/components/tree-selector.vue | 1 +
.../components/use-create-service.ts | 56 +++++++++-----
.../src/components/create-service/create.vue | 20 +++--
.../src/composables/use-base-table.ts | 5 +-
bigtop-manager-ui/src/layouts/header.vue | 1 +
bigtop-manager-ui/src/layouts/index.vue | 13 +++-
bigtop-manager-ui/src/locales/en_US/cluster.ts | 2 +-
bigtop-manager-ui/src/locales/en_US/service.ts | 2 +-
bigtop-manager-ui/src/locales/zh_CN/cluster.ts | 2 +-
.../cluster/components/host-config.vue | 4 +-
.../cluster/components/set-source.vue | 5 +-
.../src/pages/cluster-manage/cluster/create.vue | 28 +++----
.../src/pages/cluster-manage/cluster/host.vue | 2 +-
.../src/pages/cluster-manage/cluster/index.vue | 10 +--
.../src/pages/cluster-manage/cluster/service.vue | 14 ++--
.../pages/cluster-manage/infrastructures/index.vue | 7 ++
.../src/router/routes/modules/clusters.ts | 11 ++-
bigtop-manager-ui/src/store/cluster/index.ts | 19 +++--
bigtop-manager-ui/src/store/installed/index.ts | 75 +++++++++++++++++++
bigtop-manager-ui/src/store/menu/index.ts | 2 +-
bigtop-manager-ui/src/store/service/index.ts | 19 ++++-
bigtop-manager-ui/src/store/stack/index.ts | 3 +-
28 files changed, 354 insertions(+), 107 deletions(-)
diff --git a/bigtop-manager-ui/src/api/hosts/types.ts
b/bigtop-manager-ui/src/api/hosts/types.ts
index 06e67b0a..dfbd53e6 100644
--- a/bigtop-manager-ui/src/api/hosts/types.ts
+++ b/bigtop-manager-ui/src/api/hosts/types.ts
@@ -91,12 +91,12 @@ export enum Status {
Installing = 'INSTALLING',
Success = 'SUCCESS',
Failed = 'FAILED',
- Unknown = 'UNKNOW'
+ Unknown = 'UNKNOWN'
}
export enum BaseStatus {
'INSTALLING',
'SUCCESS',
'FAILED',
- 'UNKNOW'
+ 'UNKNOWN'
}
diff --git a/bigtop-manager-ui/src/api/service/types.ts
b/bigtop-manager-ui/src/api/service/types.ts
index 9ecd25a8..7d81c6aa 100644
--- a/bigtop-manager-ui/src/api/service/types.ts
+++ b/bigtop-manager-ui/src/api/service/types.ts
@@ -44,6 +44,7 @@ export interface ServiceVO {
status: ServiceStatusType
user?: string
version?: string
+ isInstalled?: boolean
}
export interface ServiceConfig {
diff --git
a/bigtop-manager-ui/src/components/create-service/components/component-assigner.vue
b/bigtop-manager-ui/src/components/create-service/components/component-assigner.vue
index 2175959c..df9574b1 100644
---
a/bigtop-manager-ui/src/components/create-service/components/component-assigner.vue
+++
b/bigtop-manager-ui/src/components/create-service/components/component-assigner.vue
@@ -19,14 +19,13 @@
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
- import { useRoute } from 'vue-router'
import { computed, onActivated, reactive, ref, shallowRef } from 'vue'
import { TableColumnType, Empty } from 'ant-design-vue'
import { HostVO } from '@/api/hosts/types'
import { getHosts } from '@/api/hosts'
import useCreateService from './use-create-service'
- import TreeSelector from './tree-selector.vue'
import useBaseTable from '@/composables/use-base-table'
+ import TreeSelector from './tree-selector.vue'
import type { FilterConfirmProps, FilterResetProps, TableRowSelection } from
'ant-design-vue/es/table/interface'
import type { Key } from 'ant-design-vue/es/_util/type'
@@ -37,7 +36,6 @@
}
const { t } = useI18n()
- const route = useRoute()
const searchInputRef = ref()
const currComp = ref<string>('')
const fieldNames = shallowRef({
@@ -50,8 +48,14 @@
searchedColumn: '',
selectedRowKeys: []
})
- const { allComps, selectedServices, updateHostsForComponent } =
useCreateService()
- const serviceList = computed(() => selectedServices.value.map((v) => ({
...v, selectable: false })))
+ const { clusterId, installedStore, allComps, selectedServices,
updateHostsForComponent } = useCreateService()
+ const serviceList = computed(() =>
+ selectedServices.value.map((v) => ({
+ ...v,
+ selectable: false
+ }))
+ )
+
const hostsOfCurrComp = computed((): HostVO[] => {
const temp = currComp.value.split('/').at(-1)
return allComps.value.has(temp) ? allComps.value.get(temp)?.hosts : []
@@ -93,13 +97,12 @@
const getHostList = async () => {
loading.value = true
- const clusterId = route.params.id as unknown as number
if (!paginationProps.value) {
loading.value = false
return
}
try {
- const res = await getHosts({ ...filtersParams.value, clusterId })
+ const res = await getHosts({ ...filtersParams.value, clusterId:
clusterId.value })
dataSource.value = res.content.map((v) => ({ ...v, name: v.id,
displayName: v.hostname }))
paginationProps.value.total = res.total
loading.value = false
@@ -116,13 +119,20 @@
onChangeCallback: getHostList
})
+ const getCheckboxProps: TableRowSelection['getCheckboxProps'] = (record) =>
({
+ disabled: installedStore
+ .getInstalledNamesOrIdsOfServiceByKey(`${clusterId.value}`)
+ .includes(currComp.value.split('/')[0]),
+ name: record.hostname
+ })
+
const onSelectChange: TableRowSelection['onChange'] = (selectedRowKeys,
selectedRows) => {
allComps.value.has(currComp.value.split('/').at(-1)) &&
updateHostsForComponent(currComp.value, selectedRows)
state.selectedRowKeys = selectedRowKeys
}
const resetSelectedRowKeys = (key: string) => {
- state.selectedRowKeys = allComps.value.has(key) ?
allComps.value.get(key)?.hosts.map((v: HostVO) => v.id) : []
+ state.selectedRowKeys = allComps.value.has(key) ?
allComps.value.get(key)?.hosts.map((v: HostVO) => v.hostname) : []
}
const treeSelectedChange = (keyPath: string) => {
@@ -149,12 +159,16 @@
<div>{{ $t('service.select_host') }}</div>
</div>
<a-table
- row-key="id"
+ row-key="hostname"
:loading="loading"
:data-source="dataSource"
:columns="columns"
:pagination="paginationProps"
- :row-selection="{ selectedRowKeys: state.selectedRowKeys, onChange:
onSelectChange }"
+ :row-selection="{
+ selectedRowKeys: state.selectedRowKeys,
+ getCheckboxProps: getCheckboxProps,
+ onChange: onSelectChange
+ }"
@change="onChange"
>
<template #customFilterDropdown="{ setSelectedKeys, selectedKeys,
confirm, clearFilters, column }">
@@ -199,6 +213,7 @@
.component-assigner {
display: grid;
grid-template-columns: 1fr auto 3fr auto 1fr;
+
.list-title {
display: flex;
height: 32px;
@@ -208,6 +223,7 @@
padding-bottom: 16px;
margin-bottom: 16px;
}
+
.divider {
height: 100%;
margin-inline: 16px;
@@ -224,11 +240,13 @@
display: grid;
gap: $space-sm;
padding: $space-sm;
+
&-option {
width: 100%;
display: grid;
gap: $space-sm;
grid-template-columns: 1fr 1fr;
+
button {
width: 100%;
}
diff --git
a/bigtop-manager-ui/src/components/create-service/components/component-installer.vue
b/bigtop-manager-ui/src/components/create-service/components/component-installer.vue
index 90cbed7f..825533af 100644
---
a/bigtop-manager-ui/src/components/create-service/components/component-installer.vue
+++
b/bigtop-manager-ui/src/components/create-service/components/component-installer.vue
@@ -26,7 +26,6 @@
import type { JobVO, StageVO, StateType, TaskVO } from '@/api/job/types'
const props = defineProps<{ stepData: CommandVO }>()
- const emits = defineEmits(['updateData'])
const { stepData } = toRefs(props)
const activeKey = ref<number[]>([])
const jobDetail = ref<JobVO>({})
@@ -57,7 +56,6 @@
const data = await getJobDetails({ jobId, clusterId: 0 })
jobDetail.value = data
activeKey.value = data.stages ? data.stages?.map((v) => v.id!) : []
- emits('updateData', { ...stepData.value, ...data })
return ['Successful', 'Failed'].includes(data.state as StateType)
} catch (error) {
console.log('error :>> ', error)
@@ -124,9 +122,9 @@
<a-empty v-if="stages.length == 0" :image="Empty.PRESENTED_IMAGE_SIMPLE" />
<div v-else class="component-installer">
<div class="retry">
- <a-button v-if="stepData.state === 'Failed'" type="link"
@click="handleRetryJob">{{
- $t('common.retry')
- }}</a-button>
+ <a-button v-if="jobDetail.state === 'Failed'" type="link"
@click="handleRetryJob">
+ {{ $t('common.retry') }}
+ </a-button>
</div>
<a-collapse v-model:active-key="activeKey" :bordered="false"
:ghost="true">
<a-collapse-panel v-for="stage in stages" :key="stage.id">
diff --git
a/bigtop-manager-ui/src/components/create-service/components/service-configurator.vue
b/bigtop-manager-ui/src/components/create-service/components/service-configurator.vue
index 0d0f0609..446d8a30 100644
---
a/bigtop-manager-ui/src/components/create-service/components/service-configurator.vue
+++
b/bigtop-manager-ui/src/components/create-service/components/service-configurator.vue
@@ -18,7 +18,7 @@
-->
<script setup lang="ts">
- import { onActivated, onDeactivated, ref, shallowRef, watch } from 'vue'
+ import { computed, onActivated, onDeactivated, ref, shallowRef, watch } from
'vue'
import { debounce } from 'lodash'
import { Empty } from 'ant-design-vue'
import TreeSelector from './tree-selector.vue'
@@ -35,7 +35,7 @@
isView: false
})
- const { selectedServices } = useCreateService()
+ const { clusterId, installedStore, selectedServices } = useCreateService()
const searchStr = ref('')
const currService = ref<Key>('')
const configs = ref<ServiceConfigReq[]>([])
@@ -61,6 +61,13 @@
lg: { span: 18 }
}
})
+ const serviceList = computed(() => selectedServices.value)
+
+ const disabled = computed(() =>
+ installedStore
+ .getInstalledNamesOrIdsOfServiceByKey(`${clusterId.value}`)
+ .includes(currService.value.toString().split('/').at(-1)!)
+ )
watch(
() => props.isView,
@@ -118,7 +125,7 @@
// }
onActivated(() => {
- debouncedOnSearch.value = debounce(filterConfigurations, 500)
+ debouncedOnSearch.value = debounce(filterConfigurations, 300)
filterConfigs.value = [...configs.value]
})
@@ -133,7 +140,7 @@
<div class="list-title">
<div>{{ $t('service.service_list') }}</div>
</div>
- <tree-selector :tree="selectedServices" :field-names="fieldNames"
@change="handleChange" />
+ <tree-selector :tree="serviceList" :field-names="fieldNames"
@change="handleChange" />
</section>
<a-divider type="vertical" class="divider" />
<section>
@@ -146,7 +153,7 @@
/>
</div>
<a-empty v-if="filterConfigs.length === 0"
:image="Empty.PRESENTED_IMAGE_SIMPLE" />
- <a-form v-else :disabled="$props.isView" :label-wrap="true">
+ <a-form v-else :disabled="$props.isView || disabled" :label-wrap="true">
<a-collapse v-model:active-key="activeKey" :bordered="false"
:ghost="true">
<a-collapse-panel v-for="config in filterConfigs" :key="config.id">
<template #extra>
@@ -212,9 +219,11 @@
background-color: rgb(255, 192, 105);
padding: 0px;
}
+
.service-configurator-view {
grid-template-columns: 1fr auto 4fr auto 1fr !important;
}
+
.service-configurator {
display: grid;
grid-template-columns: 1fr auto 4fr;
@@ -225,6 +234,7 @@
background-color: $color-fill-quaternary;
border-bottom: 1px solid $color-border-secondary;
}
+
:deep(.ant-collapse-content-box) {
padding-inline: 24px !important;
}
@@ -243,10 +253,12 @@
border-bottom: 1px solid $color-border;
padding-bottom: 16px;
margin-bottom: 16px;
+
.ant-input {
flex: 0 1 160px;
}
}
+
.divider {
height: 100%;
margin-inline: 16px;
diff --git
a/bigtop-manager-ui/src/components/create-service/components/service-selector.vue
b/bigtop-manager-ui/src/components/create-service/components/service-selector.vue
index 83997dfb..f8b47788 100644
---
a/bigtop-manager-ui/src/components/create-service/components/service-selector.vue
+++
b/bigtop-manager-ui/src/components/create-service/components/service-selector.vue
@@ -18,23 +18,36 @@
-->
<script setup lang="ts">
- import { computed, onActivated, reactive, ref, toRefs } from 'vue'
+ import { computed, onActivated, reactive, ref, toRefs, useAttrs } from 'vue'
import { usePngImage } from '@/utils/tools'
import useCreateService from './use-create-service'
- import { ExpandServiceVO } from '@/store/stack'
+ import type { ExpandServiceVO } from '@/store/stack'
+ import { ComponentVO } from '@/api/component/types.ts'
interface State {
isAddableData: ExpandServiceVO[]
selectedData: ExpandServiceVO[]
}
+ const { creationMode } = useAttrs()
const searchStr = ref('')
const state = reactive<State>({
isAddableData: [],
selectedData: []
})
- const { selectedServices, servicesOfExcludeInfra,
confirmServiceDependencies, setDataByCurrent } = useCreateService()
+ const {
+ clusterId,
+ selectedServices,
+ servicesOfInfra,
+ servicesOfExcludeInfra,
+ installedStore,
+ confirmServiceDependencies,
+ setDataByCurrent
+ } = useCreateService()
const { isAddableData } = toRefs(state)
+ const checkSelectedServicesOnlyInstalled = computed(
+ () => selectedServices.value.filter((v: ExpandServiceVO) =>
!v.isInstalled).length === 0
+ )
const filterAddableData = computed(() =>
isAddableData.value.filter(
(v) =>
@@ -95,10 +108,62 @@
return splitStr.toString().split(new
RegExp(`(?<=${searchStr.value})|(?=${searchStr.value})`, 'i'))
}
- onActivated(() => {
- selectedServices.value.length > 0
- ? (state.selectedData = [...selectedServices.value])
- : (state.isAddableData = [...(servicesOfExcludeInfra.value as
ExpandServiceVO[])])
+ const mergeComponents = (components: ComponentVO[]) => {
+ return Object.values(
+ components.reduce((acc, item) => {
+ const { name, hostname } = item
+ if (!acc[name!]) {
+ acc[name!] = {
+ ...item,
+ hosts: [{ hostname, name: hostname, displayName: hostname }]
+ }
+ } else {
+ acc[name!].hosts.push({ hostname, name: hostname, displayName:
hostname })
+ }
+ return acc
+ }, {})
+ )
+ }
+
+ const initInstalledServicesDetail = async () => {
+ const detailRes = await
installedStore.getInstalledServicesDetailByKey(`${clusterId.value}`)
+ const detailMap = new Map<string, ExpandServiceVO>()
+ if (!detailRes) {
+ return detailMap
+ } else {
+ return detailRes.reduce(
+ (pre, val) =>
+ pre.set(val.name!, {
+ ...val,
+ components: mergeComponents(val.components || [])
+ } as ExpandServiceVO),
+ detailMap
+ )
+ }
+ }
+
+ const addInstalledSymbolForSelectedServices = async (onlyInstalled: boolean)
=> {
+ if (onlyInstalled) {
+ const installedServiceMap = await initInstalledServicesDetail()
+ const installedServiceNames =
installedStore.getInstalledNamesOrIdsOfServiceByKey(`${clusterId.value}`)
+ const data = creationMode === 'internal' ? servicesOfExcludeInfra.value
: servicesOfInfra.value
+ data.forEach((v) => {
+ if (installedServiceNames.includes(v.name || '')) {
+ Object.assign(v, installedServiceMap.get(v.name!))
+ v.isInstalled = true
+ state.selectedData.push(v as ExpandServiceVO)
+ } else {
+ state.isAddableData.push(v as ExpandServiceVO)
+ }
+ })
+ setDataByCurrent(state.selectedData)
+ } else {
+ state.selectedData = [...selectedServices.value]
+ }
+ }
+
+ onActivated(async () => {
+ await
addInstalledSymbolForSelectedServices(checkSelectedServicesOnlyInstalled.value)
})
defineExpose({
@@ -162,7 +227,7 @@
<template #renderItem="{ item }">
<a-list-item>
<template #actions>
- <a-button danger type="primary" @click="removeInstallItem(item)">
+ <a-button danger :disabled="item.isInstalled" type="primary"
@click="removeInstallItem(item)">
{{ $t('common.remove') }}
</a-button>
</template>
@@ -208,6 +273,7 @@
grid-template-columns: 1fr auto 1fr;
grid-template-rows: auto;
justify-content: space-between;
+
.list-title {
display: flex;
height: 32px;
@@ -216,21 +282,26 @@
font-weight: 500;
border-bottom: 1px solid $color-border;
padding-bottom: 16px;
+
.ant-input {
flex: 0 1 160px;
}
}
+
.ant-list {
max-height: 500px;
overflow: auto;
}
}
+
.divider {
height: 100%;
margin-inline: 16px;
}
+
:deep(.ant-avatar) {
border-radius: 4px;
+
img {
object-fit: contain !important;
}
diff --git
a/bigtop-manager-ui/src/components/create-service/components/tree-selector.vue
b/bigtop-manager-ui/src/components/create-service/components/tree-selector.vue
index e3924cef..4e1a0650 100644
---
a/bigtop-manager-ui/src/components/create-service/components/tree-selector.vue
+++
b/bigtop-manager-ui/src/components/create-service/components/tree-selector.vue
@@ -97,6 +97,7 @@
<div class="sidebar">
<a-tree
v-if="$props.tree.length > 0"
+ :default-expand-all="true"
:selected-keys="checkSelectedKeys"
:selectable="$props.selectable"
:tree-data="$props.tree"
diff --git
a/bigtop-manager-ui/src/components/create-service/components/use-create-service.ts
b/bigtop-manager-ui/src/components/create-service/components/use-create-service.ts
index 702cd8d7..021c8fd5 100644
---
a/bigtop-manager-ui/src/components/create-service/components/use-create-service.ts
+++
b/bigtop-manager-ui/src/components/create-service/components/use-create-service.ts
@@ -17,16 +17,17 @@
* under the License.
*/
-import { computed, createVNode, ref, watch, effectScope, Ref, ComputedRef }
from 'vue'
+import { computed, ComputedRef, createVNode, effectScope, Ref, ref, watch }
from 'vue'
import { message, Modal } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import { useRoute } from 'vue-router'
import { ExpandServiceVO, useStackStore } from '@/store/stack'
+import { useInstalledStore } from '@/store/installed'
import { execCommand } from '@/api/command'
import useSteps from '@/composables/use-steps'
import SvgIcon from '@/components/common/svg-icon/index.vue'
import type { HostVO } from '@/api/hosts/types'
-import type { CommandVO, CommandRequest, ServiceCommandReq } from
'@/api/command/types'
+import type { CommandRequest, CommandVO, ServiceCommandReq } from
'@/api/command/types'
import type { ServiceVO } from '@/api/service/types'
interface ProcessResult {
@@ -63,10 +64,13 @@ const useCreateService = () => {
setupStore()
isChange = true
}
+ const installedStore = useInstalledStore()
const route = useRoute()
const { t } = useI18n()
const processedServices = ref(new Set())
const { current, stepsLimit, previousStep, nextStep } = useSteps(steps.value)
+ const clusterId = computed(() => Number(route.params.id))
+ const creationMode = computed(() => route.params.creationMode as 'internal'
| 'public')
watch(
() => selectedServices.value,
@@ -81,7 +85,7 @@ const useCreateService = () => {
const commandRequest = ref<CommandRequest>({
command: 'Add',
commandLevel: 'service',
- clusterId: parseInt(route.params.id as string)
+ clusterId: clusterId.value
})
const allComps = computed(() => {
@@ -104,9 +108,10 @@ const useCreateService = () => {
const transformServiceData = (services: ExpandServiceVO[]) => {
return services.map((service) => ({
serviceName: service.name,
- componentHosts: service.components!.map((component) => ({
+ installed: service.isInstalled === undefined ? false :
service.isInstalled,
+ componentHosts: (service.components || []).map((component) => ({
componentName: component.name,
- hostnames: component.hosts.map((host: HostVO) => host.hostname)
+ hostnames: (component.hosts || []).map((host: HostVO) => host.hostname)
})),
configs: service.configs
})) as ServiceCommandReq[]
@@ -114,12 +119,16 @@ const useCreateService = () => {
// Validate services from infra
const validServiceFromInfra = (targetService: ExpandServiceVO,
requiredServices: string[]) => {
- const filterServiceNames = servicesOfInfra.value
- .filter((service) => requiredServices?.includes(service.name!))
- .map((service) => service.displayName)
-
- if (!filterServiceNames.length) return false
- message.error(t('service.dependencies_conflict_msg',
[targetService.displayName!, filterServiceNames.join(',')]))
+ const servicesOfInfraNames = servicesOfInfra.value.map((v) => v.name)
+ const installedServicesOfInfra =
installedStore.getInstalledNamesOrIdsOfServiceByKey('0', 'names')
+ const set = new Set(installedServicesOfInfra)
+ const missServices = requiredServices.reduce((acc, name) => {
+ !set.has(name) && servicesOfInfraNames.includes(name) && acc.push(name)
+ return acc
+ }, [] as string[])
+
+ if (missServices.length === 0) return false
+ message.error(t('service.dependencies_conflict_msg',
[targetService.displayName!, missServices.join(',')]))
return true
}
@@ -131,7 +140,7 @@ const useCreateService = () => {
): Promise<ProcessResult> => {
const dependencies = targetService.requiredServices || []
- if (validServiceFromInfra(targetService, dependencies)) {
+ if (creationMode.value === 'internal' &&
validServiceFromInfra(targetService, dependencies)) {
return {
success: false,
conflictService: targetService
@@ -142,6 +151,8 @@ const useCreateService = () => {
const dependency = serviceMap.get(serviceName)
if (!dependency || processedServices.value.has(dependency.name!))
continue
+ if (dependency.isInstalled) continue
+
const shouldAdd = await confirmRequiredServicesToInstall(targetService,
dependency)
if (!shouldAdd) return { success: false }
@@ -158,8 +169,16 @@ const useCreateService = () => {
return { success: true }
}
+ const getServiceMap = (services: ServiceVO[]) => {
+ return new Map(services.map((s) => [s.name as string, s as
ExpandServiceVO]))
+ }
+
const handlePreSelectedServiceDependencies = async (preSelectedService:
ExpandServiceVO) => {
- const serviceMap = new Map(servicesOfExcludeInfra.value.map((s) => [s.name
as string, s as ExpandServiceVO]))
+ const serviceMap =
+ creationMode.value == 'public'
+ ? getServiceMap(servicesOfInfra.value)
+ : getServiceMap(servicesOfExcludeInfra.value)
+
const result: ExpandServiceVO[] = []
const dependenciesSuccess = await processDependencies(preSelectedService,
serviceMap, servicesOfInfra.value, result)
if (dependenciesSuccess.success) {
@@ -174,7 +193,7 @@ const useCreateService = () => {
if (!requiredServices) {
return [preSelectedService]
}
- if (validServiceFromInfra(preSelectedService, requiredServices)) {
+ if (creationMode.value === 'internal' &&
validServiceFromInfra(preSelectedService, requiredServices)) {
return []
} else {
return await handlePreSelectedServiceDependencies(preSelectedService)
@@ -199,8 +218,7 @@ const useCreateService = () => {
const createService = async () => {
try {
- const formatData = transformServiceData(selectedServices.value)
- commandRequest.value.serviceCommands = formatData
+ commandRequest.value.serviceCommands =
transformServiceData(selectedServices.value)
afterCreateRes.value = await execCommand(commandRequest.value)
return true
} catch (error) {
@@ -211,10 +229,13 @@ const useCreateService = () => {
return {
steps,
+ clusterId,
current,
stepsLimit,
selectedServices,
servicesOfExcludeInfra,
+ servicesOfInfra,
+ installedStore,
allComps,
afterCreateRes,
setDataByCurrent,
@@ -223,7 +244,8 @@ const useCreateService = () => {
createService,
previousStep,
nextStep,
- scope
+ scope,
+ creationMode
}
}
diff --git a/bigtop-manager-ui/src/components/create-service/create.vue
b/bigtop-manager-ui/src/components/create-service/create.vue
index 7459dffd..48f7e7cb 100644
--- a/bigtop-manager-ui/src/components/create-service/create.vue
+++ b/bigtop-manager-ui/src/components/create-service/create.vue
@@ -47,7 +47,7 @@
const currComp = computed(() => components.value[current.value])
const validateServiceSelection = async () => {
- if (selectedServices.value.length === 0) {
+ if (selectedServices.value.filter((v) => !v.isInstalled).length === 0) {
message.error(t('service.service_selection'))
return false
} else {
@@ -80,7 +80,7 @@
return isValid
}
- const stepValidators = [validateServiceSelection,
validateComponentAssignments, () => true]
+ const stepValidators = [validateServiceSelection,
validateComponentAssignments, () => true, () => true]
const proceedToNextStep = async () => {
if (current.value < 3) {
@@ -116,11 +116,16 @@
<template v-for="stepItem in steps" :key="stepItem.title">
<div v-show="steps[current] === stepItem" class="step-title">
<h5>{{ $t(stepItem) }}</h5>
- <section :class="{ 'step-content': current < stepsLimit }">
</section>
+ <section :class="{ 'step-content': current < stepsLimit }"></section>
</div>
</template>
<keep-alive>
- <component :is="currComp" ref="compRef" :is-view="current === 3" />
+ <component
+ :is="currComp"
+ ref="compRef"
+ :is-view="current === 3"
+ v-bind="{ creationMode: $route.params.creationMode || 'internal' }"
+ />
</keep-alive>
<component-installer v-if="current == stepsLimit"
:step-data="afterCreateRes" />
<div class="step-action">
@@ -146,27 +151,32 @@
<style lang="scss" scoped>
.infra-creation {
min-width: 600px;
+
.header-card {
min-height: 80px;
}
+
.steps-wrp {
width: 100%;
height: 100%;
padding-inline: 6%;
}
}
+
.step-title {
h5 {
margin: 0;
font-size: 16px;
font-weight: 500;
letter-spacing: 0px;
- line-height: 16px;
+ line-height: 24px;
}
}
+
.step-content {
padding-block: $space-md;
}
+
.step-action {
text-align: end;
margin-top: $space-md;
diff --git a/bigtop-manager-ui/src/composables/use-base-table.ts
b/bigtop-manager-ui/src/composables/use-base-table.ts
index 2354c63d..851aedb9 100644
--- a/bigtop-manager-ui/src/composables/use-base-table.ts
+++ b/bigtop-manager-ui/src/composables/use-base-table.ts
@@ -24,12 +24,14 @@ import type { PaginationProps, TableColumnType, TableProps
} from 'ant-design-vu
import type { FilterValue } from 'ant-design-vue/es/table/interface'
type PaginationType = PaginationProps | false | undefined
+
export interface UseBaseTableProps<T = any> {
columns: TableColumnType[]
rows?: T[]
pagination?: PaginationType
onChangeCallback?: () => void
}
+
const useBaseTable = <T>(props: UseBaseTableProps<T>) => {
const { columns, rows, pagination } = props
const { t } = useI18n()
@@ -87,9 +89,6 @@ const useBaseTable = <T>(props: UseBaseTableProps<T>) => {
pageSizeOptions: ['10', '20', '30', '40', '50'],
showTotal: (total) => `${t('common.total', [total])}`
}
- if (props.onChangeCallback) {
- props.onChangeCallback()
- }
}
onUnmounted(() => {
diff --git a/bigtop-manager-ui/src/layouts/header.vue
b/bigtop-manager-ui/src/layouts/header.vue
index eeaf0090..1ce93fc3 100644
--- a/bigtop-manager-ui/src/layouts/header.vue
+++ b/bigtop-manager-ui/src/layouts/header.vue
@@ -103,6 +103,7 @@
.header-left {
width: $layout-sider-width;
margin: 0;
+ flex-shrink: 0;
:deep(.svg-icon) {
width: 180px;
height: 30px;
diff --git a/bigtop-manager-ui/src/layouts/index.vue
b/bigtop-manager-ui/src/layouts/index.vue
index f36aca0a..37bb1ed5 100644
--- a/bigtop-manager-ui/src/layouts/index.vue
+++ b/bigtop-manager-ui/src/layouts/index.vue
@@ -23,18 +23,19 @@
import LayoutHeader from '@/layouts/header.vue'
import LayoutSider from '@/layouts/sider.vue'
import { useUserStore } from '@/store/user'
- // import { useClusterStore } from '@/store/cluster'
- import { useMenuStore } from '@/store/menu/index'
+ import { useMenuStore } from '@/store/menu'
import { useStackStore } from '@/store/stack'
+ import { useInstalledStore } from '@/store/installed'
import { storeToRefs } from 'pinia'
const userStore = useUserStore()
const menuStore = useMenuStore()
- // const clusterStore = useClusterStore()
+ const installedStore = useInstalledStore()
const stackStore = useStackStore()
const { headerSelectedKey, headerMenus, siderMenuSelectedKey, siderMenus } =
storeToRefs(menuStore)
- onMounted(async () => {
+ onMounted(() => {
+ installedStore.getServicesOfInfra()
userStore.getUserInfo()
menuStore.setUpMenu()
stackStore.loadStacks()
@@ -65,7 +66,11 @@
<style lang="scss" scoped>
.layout {
height: 100vh;
+
&-inner {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
padding: $space-lg $space-md;
overflow: auto;
}
diff --git a/bigtop-manager-ui/src/locales/en_US/cluster.ts
b/bigtop-manager-ui/src/locales/en_US/cluster.ts
index a05ff116..05612202 100644
--- a/bigtop-manager-ui/src/locales/en_US/cluster.ts
+++ b/bigtop-manager-ui/src/locales/en_US/cluster.ts
@@ -19,7 +19,7 @@
export default {
base_info: 'Basic Information',
cluster_config: 'Cluster Configuration',
- cluster_management: 'Cluster',
+ cluster_info: 'Cluster',
component_info: 'Stack',
host_config: 'Hosts',
create: 'Create',
diff --git a/bigtop-manager-ui/src/locales/en_US/service.ts
b/bigtop-manager-ui/src/locales/en_US/service.ts
index 6b14adcb..9e281799 100644
--- a/bigtop-manager-ui/src/locales/en_US/service.ts
+++ b/bigtop-manager-ui/src/locales/en_US/service.ts
@@ -23,7 +23,7 @@ export default {
assign_component: 'Assign Component',
configure_service: 'Configure Service',
service_overview: 'Service Overview',
- install_component: 'Install Component',
+ install_component: 'Install',
service_list: 'Service List',
pending_installation_services: 'Selected Services',
select_host: 'Select Host',
diff --git a/bigtop-manager-ui/src/locales/zh_CN/cluster.ts
b/bigtop-manager-ui/src/locales/zh_CN/cluster.ts
index eb9ba504..29a9cd70 100644
--- a/bigtop-manager-ui/src/locales/zh_CN/cluster.ts
+++ b/bigtop-manager-ui/src/locales/zh_CN/cluster.ts
@@ -19,7 +19,7 @@
export default {
base_info: '基本信息',
cluster_config: '集群配置',
- cluster_management: '集群管理',
+ cluster_info: '集群信息',
component_info: '组件信息',
host_config: '主机管理',
create: '创建集群',
diff --git
a/bigtop-manager-ui/src/pages/cluster-manage/cluster/components/host-config.vue
b/bigtop-manager-ui/src/pages/cluster-manage/cluster/components/host-config.vue
index a222bc43..a04074c3 100644
---
a/bigtop-manager-ui/src/pages/cluster-manage/cluster/components/host-config.vue
+++
b/bigtop-manager-ui/src/pages/cluster-manage/cluster/components/host-config.vue
@@ -165,7 +165,7 @@
...item,
key: generateRandomId(),
hostname: v,
- status: 'UNKNOW'
+ status: 'UNKNOWN'
}
}) as HostReq[]
dataSource.value?.unshift(...items)
@@ -230,7 +230,7 @@
<svg-icon :name="record.status.toLowerCase()" />
<span :title="`${record.message ? record.message : ''}`">
{{ `${$t(`common.${record.status.toLowerCase()}`)}` }}
- {{ record.message ? `: ${record.message}` : '' }}
+ {{ record.message && record.status.toLowerCase() === 'failed' ? `:
${record.message}` : '' }}
</span>
</template>
<template v-if="column.key === 'operation'">
diff --git
a/bigtop-manager-ui/src/pages/cluster-manage/cluster/components/set-source.vue
b/bigtop-manager-ui/src/pages/cluster-manage/cluster/components/set-source.vue
index 4c8d996a..b2449ee0 100644
---
a/bigtop-manager-ui/src/pages/cluster-manage/cluster/components/set-source.vue
+++
b/bigtop-manager-ui/src/pages/cluster-manage/cluster/components/set-source.vue
@@ -20,7 +20,7 @@
<script setup lang="ts">
import { computed, reactive, ref, toRefs } from 'vue'
import { getRepoList, updateRepo } from '@/api/repo'
- import { message, type FormInstance, type TableColumnType } from
'ant-design-vue'
+ import { type FormInstance, message, type TableColumnType } from
'ant-design-vue'
import { useI18n } from 'vue-i18n'
import type { RepoVO } from '@/api/repo/types'
@@ -62,8 +62,7 @@
const getSource = async () => {
loading.value = true
try {
- const data = await getRepoList()
- list.value = data
+ list.value = await getRepoList()
} catch (error) {
console.log('error :>> ', error)
} finally {
diff --git a/bigtop-manager-ui/src/pages/cluster-manage/cluster/create.vue
b/bigtop-manager-ui/src/pages/cluster-manage/cluster/create.vue
index 9d809340..37134201 100644
--- a/bigtop-manager-ui/src/pages/cluster-manage/cluster/create.vue
+++ b/bigtop-manager-ui/src/pages/cluster-manage/cluster/create.vue
@@ -30,7 +30,7 @@
import ComponentInfo from './components/component-info.vue'
import HostConfig from './components/host-config.vue'
import CheckWorkflow from './components/check-workflow.vue'
- import { ClusterCommandReq, HostReq, type CommandRequest, type CommandVO }
from '@/api/command/types'
+ import { ClusterCommandReq, type CommandRequest, type CommandVO, HostReq }
from '@/api/command/types'
const { t } = useI18n()
const menuStore = useMenuStore()
@@ -44,16 +44,16 @@
const installStatus = shallowRef<InstalledStatusVO[]>([])
const components = shallowRef<any[]>([ClusterBase, ComponentInfo,
HostConfig, CheckWorkflow])
const isInstall = computed(() => current.value === 2)
- const hasUnknowHost = computed(() => stepData.value[2].filter((v) =>
v.status === Status.Unknown).length == 0)
+ const hasUnknownHost = computed(() => stepData.value[2].filter((v) =>
v.status === Status.Unknown).length == 0)
const allInstallSuccess = computed(
() =>
stepData.value[2].length != 0 &&
stepData.value[2].every((v) => v.status === Status.Success) &&
- hasUnknowHost.value
+ hasUnknownHost.value
)
const isDone = computed(() => ['Successful',
'Failed'].includes(stepData.value[stepData.value.length - 1].state))
const steps = computed(() => [
- 'cluster.cluster_management',
+ 'cluster.cluster_info',
'cluster.component_info',
'cluster.host_config',
'cluster.create'
@@ -119,12 +119,7 @@
const data = await getInstalledStatus()
installStatus.value = data
stepData.value[current.value] =
mergeByHostname(stepData.value[current.value], data)
- const allResolved = data.every((item) => item.status !=
Status.Installing)
- if (allResolved) {
- return true
- } else {
- return false
- }
+ return data.every((item) => item.status != Status.Installing)
} catch (error) {
console.log('error :>> ', error)
}
@@ -196,7 +191,7 @@
<template v-for="stepItem in steps" :key="stepItem.title">
<div v-show="steps[current] === stepItem" class="step-title">
<h5>{{ $t(stepItem) }}</h5>
- <section :class="{ 'step-content': current < stepsLimit }">
</section>
+ <section :class="{ 'step-content': current < stepsLimit }"></section>
</div>
</template>
<component :is="getCompName" ref="compRef"
:step-data="stepData[current]" @update-data="updateData" />
@@ -219,9 +214,9 @@
{{ $t('common.next') }}
</a-button>
</template>
- <a-button v-show="current === stepsLimit && isDone" type="primary"
@click="onSave">{{
- $t('common.done')
- }}</a-button>
+ <a-button v-show="current === stepsLimit && isDone" type="primary"
@click="onSave"
+ >{{ $t('common.done') }}
+ </a-button>
</a-space>
</div>
</main-card>
@@ -231,15 +226,18 @@
<style lang="scss" scoped>
.cluster-create {
min-width: 600px;
+
.header-card {
min-height: 80px;
}
+
.steps-wrp {
width: 100%;
height: 100%;
padding-inline: 6%;
}
}
+
.step-title {
h5 {
margin: 0;
@@ -249,9 +247,11 @@
line-height: 16px;
}
}
+
.step-content {
padding-block: $space-md;
}
+
.step-action {
text-align: end;
margin-top: $space-md;
diff --git a/bigtop-manager-ui/src/pages/cluster-manage/cluster/host.vue
b/bigtop-manager-ui/src/pages/cluster-manage/cluster/host.vue
index ca7a6616..2dddd13e 100644
--- a/bigtop-manager-ui/src/pages/cluster-manage/cluster/host.vue
+++ b/bigtop-manager-ui/src/pages/cluster-manage/cluster/host.vue
@@ -38,7 +38,7 @@
const { t } = useI18n()
const attrs = useAttrs() as ClusterVO
const searchInputRef = ref()
- const hostStatus = ref(['INSTALLING', 'SUCCESS', 'FAILED', 'UNKNOW'])
+ const hostStatus = ref(['INSTALLING', 'SUCCESS', 'FAILED', 'UNKNOWN'])
const state = reactive<TableState>({
searchText: '',
searchedColumn: '',
diff --git a/bigtop-manager-ui/src/pages/cluster-manage/cluster/index.vue
b/bigtop-manager-ui/src/pages/cluster-manage/cluster/index.vue
index 9baf3300..4c42360a 100644
--- a/bigtop-manager-ui/src/pages/cluster-manage/cluster/index.vue
+++ b/bigtop-manager-ui/src/pages/cluster-manage/cluster/index.vue
@@ -97,8 +97,8 @@
])
const getCompName = computed(() => {
- const componnts = [Overview, Service, Host, User, Job]
- return componnts[parseInt(activeKey.value) - 1]
+ const components = [Overview, Service, Host, User, Job]
+ return components[parseInt(activeKey.value) - 1]
})
const dropdownMenuClick: GroupItem['dropdownMenuClickEvent'] = async ({ key
}) => {
@@ -108,15 +108,15 @@
clusterId: currCluster.value.id,
commandLevel: 'cluster'
})
- clusterStore.loadClusters()
- clusterStore.getClusterDetail()
+ await clusterStore.loadClusters()
+ await clusterStore.getClusterDetail()
} catch (error) {
console.log('error :>> ', error)
}
}
const addService: GroupItem['clickEvent'] = () => {
- router.push({ name: 'CreateService' })
+ router.push({ name: 'CreateService', params: { creationMode: 'internal' }
})
}
onMounted(() => {
diff --git a/bigtop-manager-ui/src/pages/cluster-manage/cluster/service.vue
b/bigtop-manager-ui/src/pages/cluster-manage/cluster/service.vue
index 80b2cc56..8e0c606e 100644
--- a/bigtop-manager-ui/src/pages/cluster-manage/cluster/service.vue
+++ b/bigtop-manager-ui/src/pages/cluster-manage/cluster/service.vue
@@ -74,7 +74,7 @@
const filterFormItems = computed((): FilterFormItem[] => [
{
type: 'search',
- key: 'serviceName',
+ key: 'name',
label: t('service.name')
},
{
@@ -84,11 +84,11 @@
options: [
{
label: t('common.required'),
- value: 1
+ value: true
},
{
label: t('common.not_required'),
- value: 2
+ value: false
}
]
},
@@ -126,7 +126,7 @@
<a-spin :spinning="loading" class="service">
<filter-form :filter-items="filterFormItems" @filter="getServices" />
<a-empty v-if="services.length == 0" style="width: 100%"
:image="Empty.PRESENTED_IMAGE_SIMPLE" />
- <template v-else>
+ <div v-else class="service-item-wrp">
<a-card v-for="item in services" :key="item.id" :hoverable="true"
class="service-item">
<div class="header">
<div class="header-base-wrp">
@@ -158,7 +158,7 @@
</button-group>
</div>
</a-card>
- </template>
+ </div>
</a-spin>
</template>
@@ -173,10 +173,10 @@
color: rgba(0, 0, 0, 0.45);
}
- .service {
+ .service-item-wrp {
display: flex;
flex-wrap: wrap;
- gap: 16px;
+ gap: 19px;
}
.service-item {
diff --git
a/bigtop-manager-ui/src/pages/cluster-manage/infrastructures/index.vue
b/bigtop-manager-ui/src/pages/cluster-manage/infrastructures/index.vue
index 6cfb5856..2fc14d22 100644
--- a/bigtop-manager-ui/src/pages/cluster-manage/infrastructures/index.vue
+++ b/bigtop-manager-ui/src/pages/cluster-manage/infrastructures/index.vue
@@ -21,6 +21,13 @@
<template>
<div>
+ <a-button
+ @click="
+ () => $router.push({ name: 'CreateInfraService', params: { id: 0,
cluster: '', creationMode: 'public' } })
+ "
+ >
+ add Service
+ </a-button>
<span> infra list </span>
</div>
</template>
diff --git a/bigtop-manager-ui/src/router/routes/modules/clusters.ts
b/bigtop-manager-ui/src/router/routes/modules/clusters.ts
index 54ce44ae..1c9ecd9f 100644
--- a/bigtop-manager-ui/src/router/routes/modules/clusters.ts
+++ b/bigtop-manager-ui/src/router/routes/modules/clusters.ts
@@ -65,7 +65,7 @@ const routes: RouteRecordRaw[] = [
},
{
name: 'CreateService',
- path: `${RouteExceptions.DYNAMIC_ROUTE_MATCH}/create-service`,
+ path:
`${RouteExceptions.DYNAMIC_ROUTE_MATCH}/create-service/:creationMode`,
component: () => import('@/components/create-service/create.vue'),
meta: {
hidden: true
@@ -90,6 +90,15 @@ const routes: RouteRecordRaw[] = [
hidden: true,
activeMenu: '/cluster-manage/infrastructures'
}
+ },
+ {
+ name: 'CreateInfraService',
+ path: 'create-infra-service/:id/:creationMode',
+ component: () => import('@/components/create-service/create.vue'),
+ meta: {
+ hidden: true,
+ activeMenu: '/cluster-manage/infrastructures'
+ }
}
]
},
diff --git a/bigtop-manager-ui/src/store/cluster/index.ts
b/bigtop-manager-ui/src/store/cluster/index.ts
index f994d139..365b9fb7 100644
--- a/bigtop-manager-ui/src/store/cluster/index.ts
+++ b/bigtop-manager-ui/src/store/cluster/index.ts
@@ -17,23 +17,34 @@
* under the License.
*/
-import { computed, ref } from 'vue'
+import { computed, ref, watch } from 'vue'
import { defineStore } from 'pinia'
import { useRoute } from 'vue-router'
import { getCluster, getClusterList } from '@/api/cluster'
import { useServiceStore } from '@/store/service'
+import { useInstalledStore } from '@/store/installed'
import type { ClusterVO } from '@/api/cluster/types.ts'
export const useClusterStore = defineStore(
'cluster',
() => {
const route = useRoute()
+ const installedStore = useInstalledStore()
const serviceStore = useServiceStore()
const clusters = ref<ClusterVO[]>([])
const loading = ref(false)
const currCluster = ref<ClusterVO>({})
const clusterId = computed(() => (route.params.id as string) || undefined)
+ watch(
+ () => clusters.value,
+ (val) => {
+ val.forEach((cluster) => {
+ installedStore.setInstalledMapKey(`${cluster.id}`)
+ })
+ }
+ )
+
const addCluster = async () => {
await loadClusters()
}
@@ -49,7 +60,7 @@ export const useClusterStore = defineStore(
try {
loading.value = true
currCluster.value = await getCluster(parseInt(clusterId.value))
- currCluster.value.id != undefined &&
serviceStore.getServices(currCluster.value.id)
+ currCluster.value.id != undefined && (await
serviceStore.getServices(currCluster.value.id))
} catch (error) {
console.log('error :>> ', error)
} finally {
@@ -73,9 +84,5 @@ export const useClusterStore = defineStore(
},
{
persist: false
- // persist: {
- // storage: sessionStorage,
- // paths: ['clusters',]
- // }
}
)
diff --git a/bigtop-manager-ui/src/store/installed/index.ts
b/bigtop-manager-ui/src/store/installed/index.ts
new file mode 100644
index 00000000..4a417345
--- /dev/null
+++ b/bigtop-manager-ui/src/store/installed/index.ts
@@ -0,0 +1,75 @@
+/*
+ * 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
+ *
+ * https://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.
+ */
+
+import { defineStore } from 'pinia'
+import { ref } from 'vue'
+import { useServiceStore } from '@/store/service'
+import { ServiceVO } from '@/api/service/types.ts'
+
+export const useInstalledStore = defineStore(
+ 'installed',
+ () => {
+ const serviceStore = useServiceStore()
+ const installedMap = ref<Record<string, string[]>>({})
+
+ const getInstalledNamesOrIdsOfServiceByKey = (key: string, flag: 'names' |
'ids' = 'names') => {
+ return installedMap.value[key].map((value) => value.split('-')[flag ===
'names' ? 1 : 0])
+ }
+
+ const setInstalledMapKey = (key: string) => {
+ installedMap.value[key] = []
+ }
+
+ const setInstalledMapKeyOfValue = (key: string, value: string[]) => {
+ installedMap.value[key] = value
+ }
+
+ const getServicesOfInfra = async () => {
+ await serviceStore.getServices(0)
+ }
+
+ const getInstalledServicesDetailByKey = async (key: string):
Promise<ServiceVO[] | undefined> => {
+ try {
+ const serviceIds = getInstalledNamesOrIdsOfServiceByKey(key, 'ids')
+ const allDetail = serviceIds?.map((id) =>
+ serviceStore.getServiceDetail(Number(key), Number(id))
+ ) as Promise<ServiceVO>[]
+ return await Promise.all(allDetail)
+ } catch (error) {
+ console.log(error)
+ }
+ }
+
+ return {
+ installedMap,
+ getServicesOfInfra,
+ setInstalledMapKey,
+ setInstalledMapKeyOfValue,
+ getInstalledNamesOrIdsOfServiceByKey,
+ getInstalledServicesDetailByKey
+ }
+ },
+ {
+ persist: {
+ storage: sessionStorage,
+ key: 'installed',
+ paths: ['installedMap']
+ }
+ }
+)
diff --git a/bigtop-manager-ui/src/store/menu/index.ts
b/bigtop-manager-ui/src/store/menu/index.ts
index 5fbfb470..492c4901 100644
--- a/bigtop-manager-ui/src/store/menu/index.ts
+++ b/bigtop-manager-ui/src/store/menu/index.ts
@@ -65,7 +65,7 @@ export const useMenuStore = defineStore(
// resolve highlight menu
let activeMenu = route.meta.activeMenu || route.path
if (route.name === 'CreateService') {
- activeMenu = route.path.split('/').slice(0, -1).join('/')
+ activeMenu = route.path.split('/').slice(0, -2).join('/')
}
const matchedNames = [RouteExceptions.SPECIAL_ROUTE_NAME,
RouteExceptions.DEFAULT_ROUTE_NAME] as string[]
headerSelectedKey.value = route.matched[0].path
diff --git a/bigtop-manager-ui/src/store/service/index.ts
b/bigtop-manager-ui/src/store/service/index.ts
index 910bbf88..47d45a15 100644
--- a/bigtop-manager-ui/src/store/service/index.ts
+++ b/bigtop-manager-ui/src/store/service/index.ts
@@ -19,20 +19,23 @@
import { defineStore, storeToRefs } from 'pinia'
import { computed, ref } from 'vue'
-import { getServiceList } from '@/api/service'
-import { useStackStore } from '@/store/stack/index'
+import { getService, getServiceList } from '@/api/service'
+import { useStackStore } from '@/store/stack'
+import { useInstalledStore } from '@/store/installed'
import type { ServiceListParams, ServiceVO } from '@/api/service/types'
export const useServiceStore = defineStore(
'service',
() => {
const stackStore = useStackStore()
+ const installedStore = useInstalledStore()
const services = ref<ServiceVO[]>([])
const total = ref(0)
const loading = ref(false)
const { stacks } = storeToRefs(stackStore)
const serviceNames = computed(() => services.value.map((v) => v.name))
+ const serviceMap = computed(() => services.value.map((v) =>
`${v.id}-${v.name}`))
const locateStackWithService = computed(() => {
return stacks.value.filter((item) =>
item.services.some((service) => service.name &&
serviceNames.value.includes(service.name))
@@ -42,9 +45,10 @@ export const useServiceStore = defineStore(
const getServices = async (clusterId: number, filterParams?:
ServiceListParams) => {
try {
loading.value = true
- const data = await getServiceList(clusterId, { ...filterParams,
pageNum: 1, pageSize: 50 })
+ const data = await getServiceList(clusterId, { ...filterParams,
pageNum: 1, pageSize: 100 })
services.value = data.content
total.value = data.total
+ installedStore.setInstalledMapKeyOfValue(`${clusterId}`,
serviceMap.value)
} catch (error) {
console.log('error :>> ', error)
} finally {
@@ -52,10 +56,19 @@ export const useServiceStore = defineStore(
}
}
+ const getServiceDetail = async (clusterId: number, serviceId: number) => {
+ try {
+ return await getService({ clusterId, id: serviceId })
+ } catch (error) {
+ console.log(error)
+ }
+ }
+
return {
services,
loading,
getServices,
+ getServiceDetail,
serviceNames,
locateStackWithService
}
diff --git a/bigtop-manager-ui/src/store/stack/index.ts
b/bigtop-manager-ui/src/store/stack/index.ts
index c667ad3d..bee272c2 100644
--- a/bigtop-manager-ui/src/store/stack/index.ts
+++ b/bigtop-manager-ui/src/store/stack/index.ts
@@ -32,8 +32,7 @@ export const useStackStore = defineStore(
const loadStacks = async () => {
try {
- const data = await getStacks()
- stacks.value = data
+ stacks.value = await getStacks()
} catch (error) {
console.log('error :>> ', error)
}