mirror of
https://github.com/harvester/harvester-ui-extension.git
synced 2026-08-16 12:49:14 +00:00
feat(forklift): small changes before rebase
Signed-off-by: Marcelo Fukumoto <marcelo.fukumoto@suse.com>
This commit is contained in:
parent
fbcc235fa7
commit
77d80051c9
@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, watch } from 'vue';
|
import { ref, computed, watch, toRefs } from 'vue';
|
||||||
import { useStore } from 'vuex';
|
import { useStore } from 'vuex';
|
||||||
import Loading from '@shell/components/Loading';
|
import Loading from '@shell/components/Loading';
|
||||||
import { Banner } from '@components/Banner';
|
import { Banner } from '@components/Banner';
|
||||||
@ -28,20 +28,12 @@ const { t } = useI18n(store);
|
|||||||
const vms = ref([]);
|
const vms = ref([]);
|
||||||
const harvesterNetworks = ref([]);
|
const harvesterNetworks = ref([]);
|
||||||
const storageClasses = ref([]);
|
const storageClasses = ref([]);
|
||||||
const networkEntries = ref([]);
|
|
||||||
const storageEntries = ref([]);
|
|
||||||
const allNetworkMaps = ref([]);
|
const allNetworkMaps = ref([]);
|
||||||
const allStorageMaps = ref([]);
|
const allStorageMaps = ref([]);
|
||||||
const errors = ref([]);
|
const errors = ref([]);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
|
|
||||||
// Restore from stepData
|
const { networkEntries, storageEntries } = toRefs(props.stepData);
|
||||||
if (props.stepData.networkEntries.length > 0) {
|
|
||||||
networkEntries.value = props.stepData.networkEntries;
|
|
||||||
}
|
|
||||||
if (props.stepData.storageEntries.length > 0) {
|
|
||||||
storageEntries.value = props.stepData.storageEntries;
|
|
||||||
}
|
|
||||||
|
|
||||||
const NAMESPACE = FORKLIFT_NAMESPACE;
|
const NAMESPACE = FORKLIFT_NAMESPACE;
|
||||||
|
|
||||||
@ -152,13 +144,6 @@ if (canSave.value) {
|
|||||||
emit('ready', true);
|
emit('ready', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync state back to stepData
|
|
||||||
watch(networkEntries, (val) => {
|
|
||||||
props.stepData.networkEntries = val;
|
|
||||||
}, { deep: true });
|
|
||||||
watch(storageEntries, (val) => {
|
|
||||||
props.stepData.storageEntries = val;
|
|
||||||
}, { deep: true });
|
|
||||||
const buildNetworkEntries = () => {
|
const buildNetworkEntries = () => {
|
||||||
const networkMap = {};
|
const networkMap = {};
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, watch } from 'vue';
|
import { ref, computed, watch, toRefs } from 'vue';
|
||||||
import { useStore } from 'vuex';
|
import { useStore } from 'vuex';
|
||||||
|
|
||||||
import { LabeledInput } from '@components/Form/LabeledInput';
|
import { LabeledInput } from '@components/Form/LabeledInput';
|
||||||
@ -28,69 +28,24 @@ const { t } = useI18n(store);
|
|||||||
|
|
||||||
const allProviders = ref([]);
|
const allProviders = ref([]);
|
||||||
const allSecrets = ref([]);
|
const allSecrets = ref([]);
|
||||||
const selectedProvider = ref(CREATE_NEW);
|
|
||||||
const providerName = ref('');
|
|
||||||
const url = ref('');
|
|
||||||
const username = ref('');
|
|
||||||
const password = ref('');
|
|
||||||
const skipTlsVerify = ref(false);
|
|
||||||
const testResult = ref(null);
|
|
||||||
const testError = ref(null);
|
|
||||||
const errors = ref([]);
|
const errors = ref([]);
|
||||||
const testBtnRef = ref(null);
|
const testBtnRef = ref(null);
|
||||||
const createdProvider = ref(null);
|
|
||||||
const createdSecret = ref(null);
|
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const testPassed = ref(false);
|
|
||||||
const testing = ref(false);
|
const testing = ref(false);
|
||||||
|
|
||||||
// Restore state from stepData on mount
|
const {
|
||||||
selectedProvider.value = props.stepData.selectedProvider;
|
selectedProvider,
|
||||||
providerName.value = props.stepData.providerName;
|
providerName,
|
||||||
url.value = props.stepData.url;
|
url,
|
||||||
username.value = props.stepData.username;
|
username,
|
||||||
password.value = props.stepData.password;
|
password,
|
||||||
skipTlsVerify.value = props.stepData.skipTlsVerify;
|
skipTlsVerify,
|
||||||
testPassed.value = props.stepData.testPassed;
|
testPassed,
|
||||||
testResult.value = props.stepData.testResult;
|
testResult,
|
||||||
testError.value = props.stepData.testError;
|
testError,
|
||||||
createdProvider.value = props.stepData.createdProvider;
|
createdProvider,
|
||||||
createdSecret.value = props.stepData.createdSecret;
|
createdSecret,
|
||||||
|
} = toRefs(props.stepData);
|
||||||
// Sync state back to stepData
|
|
||||||
watch(selectedProvider, (val) => {
|
|
||||||
props.stepData.selectedProvider = val;
|
|
||||||
});
|
|
||||||
watch(providerName, (val) => {
|
|
||||||
props.stepData.providerName = val;
|
|
||||||
});
|
|
||||||
watch(url, (val) => {
|
|
||||||
props.stepData.url = val;
|
|
||||||
});
|
|
||||||
watch(username, (val) => {
|
|
||||||
props.stepData.username = val;
|
|
||||||
});
|
|
||||||
watch(password, (val) => {
|
|
||||||
props.stepData.password = val;
|
|
||||||
});
|
|
||||||
watch(skipTlsVerify, (val) => {
|
|
||||||
props.stepData.skipTlsVerify = val;
|
|
||||||
});
|
|
||||||
watch(testPassed, (val) => {
|
|
||||||
props.stepData.testPassed = val;
|
|
||||||
});
|
|
||||||
watch(testResult, (val) => {
|
|
||||||
props.stepData.testResult = val;
|
|
||||||
});
|
|
||||||
watch(testError, (val) => {
|
|
||||||
props.stepData.testError = val;
|
|
||||||
});
|
|
||||||
watch(createdProvider, (val) => {
|
|
||||||
props.stepData.createdProvider = val;
|
|
||||||
});
|
|
||||||
watch(createdSecret, (val) => {
|
|
||||||
props.stepData.createdSecret = val;
|
|
||||||
});
|
|
||||||
|
|
||||||
const isExistingProvider = computed(() => selectedProvider.value !== CREATE_NEW);
|
const isExistingProvider = computed(() => selectedProvider.value !== CREATE_NEW);
|
||||||
const isFormValid = computed(() => !!providerName.value && !!url.value && !!username.value && !!password.value);
|
const isFormValid = computed(() => !!providerName.value && !!url.value && !!username.value && !!password.value);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import {
|
||||||
ref, computed, watch, nextTick, onBeforeUnmount
|
ref, computed, watch, nextTick, onBeforeUnmount, toRefs
|
||||||
} from 'vue';
|
} from 'vue';
|
||||||
import { useStore } from 'vuex';
|
import { useStore } from 'vuex';
|
||||||
import Loading from '@shell/components/Loading';
|
import Loading from '@shell/components/Loading';
|
||||||
@ -20,15 +20,14 @@ const emit = defineEmits(['complete', 'loading']);
|
|||||||
const store = useStore();
|
const store = useStore();
|
||||||
const { t } = useI18n(store);
|
const { t } = useI18n(store);
|
||||||
|
|
||||||
const discoveredVMs = ref([]);
|
const { discoveredVMs, selectedVMIds, tableRows } = toRefs(props.stepData);
|
||||||
|
|
||||||
const selectedVMs = ref([]);
|
const selectedVMs = ref([]);
|
||||||
const tableRows = ref([]);
|
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const networkMap = ref({});
|
const networkMap = ref({});
|
||||||
const datastoreMap = ref({});
|
const datastoreMap = ref({});
|
||||||
const sortableTableRef = ref(null);
|
const sortableTableRef = ref(null);
|
||||||
const allVMsSelected = ref(false);
|
const allVMsSelected = ref(false);
|
||||||
const selectedVMIds = ref(new Set());
|
|
||||||
const errors = ref([]);
|
const errors = ref([]);
|
||||||
let skipNextSelectionEvent = false;
|
let skipNextSelectionEvent = false;
|
||||||
|
|
||||||
@ -67,29 +66,11 @@ onBeforeUnmount(() => {
|
|||||||
clearInterval(nowTimer);
|
clearInterval(nowTimer);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Restore from stepData
|
// Restore selection state from stepData
|
||||||
if (props.stepData.discoveredVMs.length > 0) {
|
if (selectedVMIds.value.size > 0) {
|
||||||
discoveredVMs.value = props.stepData.discoveredVMs;
|
|
||||||
}
|
|
||||||
if (props.stepData.selectedVMIds.size > 0) {
|
|
||||||
selectedVMIds.value = props.stepData.selectedVMIds;
|
|
||||||
selectedVMs.value = discoveredVMs.value.filter((vm) => selectedVMIds.value.has(vm.id));
|
selectedVMs.value = discoveredVMs.value.filter((vm) => selectedVMIds.value.has(vm.id));
|
||||||
allVMsSelected.value = selectedVMIds.value.size === discoveredVMs.value.length;
|
allVMsSelected.value = selectedVMIds.value.size === discoveredVMs.value.length;
|
||||||
}
|
}
|
||||||
if (props.stepData.tableRows.length > 0) {
|
|
||||||
tableRows.value = props.stepData.tableRows;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sync back to stepData
|
|
||||||
watch(discoveredVMs, (val) => {
|
|
||||||
props.stepData.discoveredVMs = val;
|
|
||||||
});
|
|
||||||
watch(selectedVMIds, (val) => {
|
|
||||||
props.stepData.selectedVMIds = val;
|
|
||||||
});
|
|
||||||
watch(tableRows, (val) => {
|
|
||||||
props.stepData.tableRows = val;
|
|
||||||
});
|
|
||||||
|
|
||||||
const vmCount = computed(() => discoveredVMs.value.length);
|
const vmCount = computed(() => discoveredVMs.value.length);
|
||||||
const selectedCount = computed(() => selectedVMs.value.length);
|
const selectedCount = computed(() => selectedVMs.value.length);
|
||||||
|
|||||||
@ -2,13 +2,14 @@
|
|||||||
import { reactive, ref, computed, watch } from 'vue';
|
import { reactive, ref, computed, watch } from 'vue';
|
||||||
import { useStore } from 'vuex';
|
import { useStore } from 'vuex';
|
||||||
import CruResource from '@shell/components/CruResource';
|
import CruResource from '@shell/components/CruResource';
|
||||||
|
import Loading from '@shell/components/Loading';
|
||||||
import { SECRET } from '@shell/config/types';
|
import { SECRET } from '@shell/config/types';
|
||||||
import { useI18n } from '@shell/composables/useI18n';
|
import { useI18n } from '@shell/composables/useI18n';
|
||||||
import ConfigureProviderStep from '../../../../components/vm-migration/ConfigureProviderStep';
|
import ConfigureProviderStep from '@pkg/harvester/components/vm-migration/ConfigureProviderStep.vue';
|
||||||
import ConfigureMappingsStep from '../../../../components/vm-migration/ConfigureMappingsStep';
|
import ConfigureMappingsStep from '@pkg/harvester/components/vm-migration/ConfigureMappingsStep.vue';
|
||||||
import { PRODUCT_NAME } from '../../../../config/harvester';
|
import { PRODUCT_NAME } from '@pkg/harvester/config/harvester';
|
||||||
import { currentRouter, currentRoute } from '../../../../utils/router';
|
import { currentRouter, currentRoute } from '@pkg/harvester/utils/router';
|
||||||
import { HCI } from '../../../../types';
|
import { HCI } from '@pkg/harvester/types';
|
||||||
|
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
const route = currentRoute();
|
const route = currentRoute();
|
||||||
@ -59,23 +60,18 @@ const stepData = reactive({
|
|||||||
const steps = reactive([
|
const steps = reactive([
|
||||||
{
|
{
|
||||||
name: 'configure-provider',
|
name: 'configure-provider',
|
||||||
label: '',
|
label: t('harvester.addons.vmMigration.wizard.steps.configureProvider.label'),
|
||||||
subtext: '',
|
subtext: t('harvester.addons.vmMigration.wizard.steps.configureProvider.description'),
|
||||||
ready: false,
|
ready: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'configure-mappings',
|
name: 'configure-mappings',
|
||||||
label: '',
|
label: t('harvester.addons.vmMigration.wizard.steps.configureMappings.label'),
|
||||||
subtext: '',
|
subtext: t('harvester.addons.vmMigration.wizard.steps.configureMappings.description'),
|
||||||
ready: false,
|
ready: false,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
steps[0].label = t('harvester.addons.vmMigration.wizard.steps.configureProvider.label');
|
|
||||||
steps[0].subtext = t('harvester.addons.vmMigration.wizard.steps.configureProvider.description');
|
|
||||||
steps[1].label = t('harvester.addons.vmMigration.wizard.steps.configureMappings.label');
|
|
||||||
steps[1].subtext = t('harvester.addons.vmMigration.wizard.steps.configureMappings.description');
|
|
||||||
|
|
||||||
watch([providerFormValid, providerTesting], () => {
|
watch([providerFormValid, providerTesting], () => {
|
||||||
steps[0].ready = providerFormValid.value && !providerTesting.value;
|
steps[0].ready = providerFormValid.value && !providerTesting.value;
|
||||||
}, { immediate: true });
|
}, { immediate: true });
|
||||||
@ -243,7 +239,7 @@ init();
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="initialLoading" />
|
<Loading v-if="initialLoading" />
|
||||||
<CruResource
|
<CruResource
|
||||||
v-else
|
v-else
|
||||||
ref="cruRef"
|
ref="cruRef"
|
||||||
|
|||||||
@ -3,12 +3,12 @@ import { reactive, ref, computed, watch } from 'vue';
|
|||||||
import { useStore } from 'vuex';
|
import { useStore } from 'vuex';
|
||||||
import CruResource from '@shell/components/CruResource';
|
import CruResource from '@shell/components/CruResource';
|
||||||
import { useI18n } from '@shell/composables/useI18n';
|
import { useI18n } from '@shell/composables/useI18n';
|
||||||
import ConfigureProviderStep from '../../../../components/vm-migration/ConfigureProviderStep';
|
import ConfigureProviderStep from '@pkg/harvester/components/vm-migration/ConfigureProviderStep.vue';
|
||||||
import SelectVmsStep from '../../../../components/vm-migration/SelectVmsStep';
|
import SelectVmsStep from '@pkg/harvester/components/vm-migration/SelectVmsStep.vue';
|
||||||
import ConfigureMappingsStep from '../../../../components/vm-migration/ConfigureMappingsStep';
|
import ConfigureMappingsStep from '@pkg/harvester/components/vm-migration/ConfigureMappingsStep.vue';
|
||||||
import ReviewMigrationStep from '../../../../components/vm-migration/ReviewMigrationStep';
|
import ReviewMigrationStep from '@pkg/harvester/components/vm-migration/ReviewMigrationStep.vue';
|
||||||
import { PRODUCT_NAME } from '../../../../config/harvester';
|
import { PRODUCT_NAME } from '@pkg/harvester/config/harvester';
|
||||||
import { currentRouter } from '../../../../utils/router';
|
import { currentRouter } from '@pkg/harvester/utils/router';
|
||||||
|
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
const { t } = useI18n(store);
|
const { t } = useI18n(store);
|
||||||
@ -61,39 +61,30 @@ const stepData = reactive({
|
|||||||
const steps = reactive([
|
const steps = reactive([
|
||||||
{
|
{
|
||||||
name: 'configure-provider',
|
name: 'configure-provider',
|
||||||
label: '',
|
label: t('harvester.addons.vmMigration.wizard.steps.configureProvider.label'),
|
||||||
subtext: '',
|
subtext: t('harvester.addons.vmMigration.wizard.steps.configureProvider.description'),
|
||||||
ready: false,
|
ready: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'select-vms',
|
name: 'select-vms',
|
||||||
label: '',
|
label: t('harvester.addons.vmMigration.wizard.steps.selectVms.label'),
|
||||||
subtext: '',
|
subtext: t('harvester.addons.vmMigration.wizard.steps.selectVms.description'),
|
||||||
ready: false,
|
ready: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'configure-mappings',
|
name: 'configure-mappings',
|
||||||
label: '',
|
label: t('harvester.addons.vmMigration.wizard.steps.configureMappings.label'),
|
||||||
subtext: '',
|
subtext: t('harvester.addons.vmMigration.wizard.steps.configureMappings.description'),
|
||||||
ready: false,
|
ready: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'review-migration',
|
name: 'review-migration',
|
||||||
label: '',
|
label: t('harvester.addons.vmMigration.wizard.steps.reviewMigration.label'),
|
||||||
subtext: '',
|
subtext: t('harvester.addons.vmMigration.wizard.steps.reviewMigration.description'),
|
||||||
ready: false,
|
ready: false,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
steps[0].label = t('harvester.addons.vmMigration.wizard.steps.configureProvider.label');
|
|
||||||
steps[0].subtext = t('harvester.addons.vmMigration.wizard.steps.configureProvider.description');
|
|
||||||
steps[1].label = t('harvester.addons.vmMigration.wizard.steps.selectVms.label');
|
|
||||||
steps[1].subtext = t('harvester.addons.vmMigration.wizard.steps.selectVms.description');
|
|
||||||
steps[2].label = t('harvester.addons.vmMigration.wizard.steps.configureMappings.label');
|
|
||||||
steps[2].subtext = t('harvester.addons.vmMigration.wizard.steps.configureMappings.description');
|
|
||||||
steps[3].label = t('harvester.addons.vmMigration.wizard.steps.reviewMigration.label');
|
|
||||||
steps[3].subtext = t('harvester.addons.vmMigration.wizard.steps.reviewMigration.description');
|
|
||||||
|
|
||||||
watch([providerFormValid, providerTesting], () => {
|
watch([providerFormValid, providerTesting], () => {
|
||||||
steps[0].ready = providerFormValid.value && !providerTesting.value;
|
steps[0].ready = providerFormValid.value && !providerTesting.value;
|
||||||
}, { immediate: true });
|
}, { immediate: true });
|
||||||
@ -130,6 +121,12 @@ watch(providerReady, (val) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(providerTesting, (testing) => {
|
||||||
|
if (!testing && pendingProceed.value && !providerReady.value) {
|
||||||
|
pendingProceed.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const onProviderComplete = (data) => {
|
const onProviderComplete = (data) => {
|
||||||
providerName.value = data.providerName;
|
providerName.value = data.providerName;
|
||||||
provider.value = data.provider;
|
provider.value = data.provider;
|
||||||
@ -185,7 +182,11 @@ watch(() => stepData.provider.providerName, (newVal, oldVal) => {
|
|||||||
|
|
||||||
// Clear mappings and review when VM selection changes
|
// Clear mappings and review when VM selection changes
|
||||||
watch(selectedVMs, (newVal, oldVal) => {
|
watch(selectedVMs, (newVal, oldVal) => {
|
||||||
if (oldVal.length > 0 && JSON.stringify(newVal.map((v) => v.id).sort()) !== JSON.stringify(oldVal.map((v) => v.id).sort())) {
|
const newIds = new Set(newVal.map((v) => v.id));
|
||||||
|
const oldIds = new Set(oldVal.map((v) => v.id));
|
||||||
|
const changed = newIds.size !== oldIds.size || [...newIds].some((id) => !oldIds.has(id));
|
||||||
|
|
||||||
|
if (oldVal.length > 0 && changed) {
|
||||||
stepData.mappings.networkEntries = [];
|
stepData.mappings.networkEntries = [];
|
||||||
stepData.mappings.storageEntries = [];
|
stepData.mappings.storageEntries = [];
|
||||||
mappingsReady.value = false;
|
mappingsReady.value = false;
|
||||||
@ -195,18 +196,19 @@ watch(selectedVMs, (newVal, oldVal) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const onFinish = async(buttonCb) => {
|
const migrationListLocation = {
|
||||||
try {
|
|
||||||
await reviewStepRef.value.startMigration();
|
|
||||||
buttonCb(true);
|
|
||||||
|
|
||||||
currentRouter().push({
|
|
||||||
name: `${ PRODUCT_NAME }-c-cluster-vm-migration`,
|
name: `${ PRODUCT_NAME }-c-cluster-vm-migration`,
|
||||||
params: {
|
params: {
|
||||||
product: store.getters['productId'],
|
product: store.getters['productId'],
|
||||||
cluster: store.getters['clusterId'],
|
cluster: store.getters['clusterId'],
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
const onFinish = async(buttonCb) => {
|
||||||
|
try {
|
||||||
|
await reviewStepRef.value.startMigration();
|
||||||
|
buttonCb(true);
|
||||||
|
currentRouter().push(migrationListLocation);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
errors.value = [err instanceof Error ? err.message : String(err)];
|
errors.value = [err instanceof Error ? err.message : String(err)];
|
||||||
buttonCb(false);
|
buttonCb(false);
|
||||||
@ -214,13 +216,7 @@ const onFinish = async(buttonCb) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onCancel = () => {
|
const onCancel = () => {
|
||||||
currentRouter().push({
|
currentRouter().push(migrationListLocation);
|
||||||
name: `${ PRODUCT_NAME }-c-cluster-vm-migration`,
|
|
||||||
params: {
|
|
||||||
product: store.getters['productId'],
|
|
||||||
cluster: store.getters['clusterId'],
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user