mirror of
https://github.com/harvester/harvester-ui-extension.git
synced 2026-08-16 04:39:15 +00:00
feat: add migration steps tooltip when mouse hover on progress bar (#994)
* feat: add progress bar tooltip Signed-off-by: Andy Lee <andy.lee@suse.com> * refactor: copilot review Signed-off-by: Andy Lee <andy.lee@suse.com> --------- Signed-off-by: Andy Lee <andy.lee@suse.com>
This commit is contained in:
parent
219f39ae52
commit
e0436bff28
@ -38,6 +38,65 @@ const allPlans = computed(() => store.getters[`${ inStore.value }/all`](HCI.FORK
|
|||||||
const allNetworkMaps = computed(() => store.getters[`${ inStore.value }/all`](HCI.FORKLIFT_NETWORK_MAP));
|
const allNetworkMaps = computed(() => store.getters[`${ inStore.value }/all`](HCI.FORKLIFT_NETWORK_MAP));
|
||||||
const allStorageMaps = computed(() => store.getters[`${ inStore.value }/all`](HCI.FORKLIFT_STORAGE_MAP));
|
const allStorageMaps = computed(() => store.getters[`${ inStore.value }/all`](HCI.FORKLIFT_STORAGE_MAP));
|
||||||
|
|
||||||
|
const escapeHtml = (value = '') => String(value)
|
||||||
|
.replaceAll('&', '&')
|
||||||
|
.replaceAll('<', '<')
|
||||||
|
.replaceAll('>', '>')
|
||||||
|
.replaceAll('"', '"')
|
||||||
|
.replaceAll("'", ''');
|
||||||
|
|
||||||
|
const getPipelineStepMeta = (step = {}) => {
|
||||||
|
const phase = String(step.phase || '').toLowerCase();
|
||||||
|
const hasProgress = typeof step.progress?.completed === 'number' && typeof step.progress?.total === 'number' && step.progress.total > 0;
|
||||||
|
const progressPct = hasProgress ? Math.round((step.progress.completed / step.progress.total) * 1000) / 10 : null;
|
||||||
|
|
||||||
|
if (phase === 'completed' || phase === 'succeeded') {
|
||||||
|
return {
|
||||||
|
icon: '✓',
|
||||||
|
color: 'var(--success)',
|
||||||
|
text: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phase === 'running' || phase === 'inprogress' || phase === 'progressing' || phase === 'started' || (hasProgress && progressPct > 0)) {
|
||||||
|
return {
|
||||||
|
icon: '↻',
|
||||||
|
color: 'var(--primary)',
|
||||||
|
text: progressPct !== null ? `${ step.phase || t('generic.inProgress') } (${ progressPct }%)` : (step.phase || t('generic.inProgress'))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phase === 'failed' || phase === 'error') {
|
||||||
|
return {
|
||||||
|
icon: '✕',
|
||||||
|
color: 'var(--error)',
|
||||||
|
text: step.phase || t('harvester.addons.vmMigration.dashboard.progress.failed')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
icon: '○',
|
||||||
|
color: 'var(--muted)',
|
||||||
|
text: ''
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatPipelineTooltip = (pipeline = []) => {
|
||||||
|
if (!pipeline.length) {
|
||||||
|
return `<div style="display:flex;align-items:center;gap:8px;"><span style="color:var(--muted);font-weight:700;">○</span><span>${ escapeHtml(t('harvester.addons.vmMigration.dashboard.progress.initializingMigration')) }</span></div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pipeline
|
||||||
|
.map((step, idx) => {
|
||||||
|
const stepName = step.name || t('harvester.addons.vmMigration.dashboard.progress.step', { index: idx + 1 });
|
||||||
|
const meta = getPipelineStepMeta(step);
|
||||||
|
const lineText = meta.text ? `${ escapeHtml(stepName) } : ${ escapeHtml(meta.text) }` : escapeHtml(stepName);
|
||||||
|
|
||||||
|
return `<div style="display:flex;align-items:center;gap:8px;"><span style="color:${ meta.color };font-weight:700;">${ meta.icon }</span><span>${ lineText }</span></div>`;
|
||||||
|
})
|
||||||
|
.join('');
|
||||||
|
};
|
||||||
|
|
||||||
const rows = computed(() => {
|
const rows = computed(() => {
|
||||||
return allPlans.value.map((plan) => {
|
return allPlans.value.map((plan) => {
|
||||||
const netMapName = plan.spec?.map?.network?.name;
|
const netMapName = plan.spec?.map?.network?.name;
|
||||||
@ -107,6 +166,7 @@ const rows = computed(() => {
|
|||||||
vmId: vm.id || '',
|
vmId: vm.id || '',
|
||||||
progress: overallProgress,
|
progress: overallProgress,
|
||||||
currentStep,
|
currentStep,
|
||||||
|
pipelineTooltip: formatPipelineTooltip(pipeline),
|
||||||
errorMsg,
|
errorMsg,
|
||||||
canceled: plan.planCanceled,
|
canceled: plan.planCanceled,
|
||||||
};
|
};
|
||||||
@ -119,6 +179,7 @@ const rows = computed(() => {
|
|||||||
vmId: vm.id || '',
|
vmId: vm.id || '',
|
||||||
progress: 0,
|
progress: 0,
|
||||||
currentStep: t('harvester.addons.vmMigration.dashboard.progress.initializingMigration'),
|
currentStep: t('harvester.addons.vmMigration.dashboard.progress.initializingMigration'),
|
||||||
|
pipelineTooltip: formatPipelineTooltip([]),
|
||||||
errorMsg: '',
|
errorMsg: '',
|
||||||
canceled: false,
|
canceled: false,
|
||||||
}));
|
}));
|
||||||
@ -266,12 +327,16 @@ init();
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="vm-pct-block">
|
<div class="vm-pct-block">
|
||||||
|
<div
|
||||||
|
v-clean-tooltip="{ content: vm.pipelineTooltip, html: true }"
|
||||||
|
class="vm-bar"
|
||||||
|
>
|
||||||
<PercentageBar
|
<PercentageBar
|
||||||
:model-value="vm.progress"
|
:model-value="vm.progress"
|
||||||
:color-stops="vm.errorMsg ? { 100: '--error' } : vm.canceled ? { 100: '--darker' } : vm.progress >= 100 ? { 100: '--success' } : { 100: '--primary' }"
|
:color-stops="vm.errorMsg ? { 100: '--error' } : vm.canceled ? { 100: '--darker' } : vm.progress >= 100 ? { 100: '--success' } : { 100: '--primary' }"
|
||||||
preferred-direction="MORE"
|
preferred-direction="MORE"
|
||||||
class="vm-bar"
|
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
<span class="vm-pct text-muted mr-10">{{ vm.progress }}%</span>
|
<span class="vm-pct text-muted mr-10">{{ vm.progress }}%</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user