mirror of
https://github.com/harvester/harvester-ui-extension.git
synced 2026-10-01 03:36:04 +08:00
Add Dashboard page
Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
This commit is contained in:
@@ -0,0 +1,235 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { allHash } from '@shell/utils/promise';
|
||||
import { Checkbox } from '@components/Form/Checkbox';
|
||||
import ModalWithCard from '@shell/components/ModalWithCard';
|
||||
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
||||
import { Banner } from '@components/Banner';
|
||||
import { HCI } from '../types';
|
||||
import UpgradeInfo from './UpgradeInfo';
|
||||
export default {
|
||||
name: 'HarvesterUpgrade',
|
||||
|
||||
components: {
|
||||
Checkbox, ModalWithCard, LabeledSelect, Banner, UpgradeInfo
|
||||
},
|
||||
|
||||
async fetch() {
|
||||
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||
|
||||
const res = await allHash({
|
||||
upgradeVersion: this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.SETTING }),
|
||||
versions: this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.VERSION }),
|
||||
upgrade: this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.UPGRADE }),
|
||||
});
|
||||
|
||||
this.upgrade = res.upgrade;
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
upgrade: [],
|
||||
upgradeMessage: [],
|
||||
errors: '',
|
||||
selectMode: true,
|
||||
version: '',
|
||||
enableLogging: true,
|
||||
readyReleaseNote: false
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters(['currentCluster']),
|
||||
|
||||
versionOptions() {
|
||||
const versions = this.$store.getters['harvester/all'](HCI.VERSION);
|
||||
|
||||
return versions.map(V => V.metadata.name);
|
||||
},
|
||||
|
||||
currentVersion() {
|
||||
const serverVersion = this.$store.getters['harvester/byId'](HCI.SETTING, 'server-version');
|
||||
|
||||
return serverVersion.currentVersion || '';
|
||||
},
|
||||
|
||||
canEnableLogging() {
|
||||
return this.$store.getters['harvester/schemaFor'](HCI.UPGRADE_LOG);
|
||||
},
|
||||
|
||||
releaseLink() {
|
||||
return `https://github.com/harvester/harvester/releases/tag/${ this.version }`;
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
upgrade: {
|
||||
handler(neu) {
|
||||
let upgradeMessage = [];
|
||||
const list = neu || [];
|
||||
|
||||
const currentResource = list.find( O => !!O.isLatestUpgrade);
|
||||
|
||||
upgradeMessage = currentResource ? currentResource.upgradeMessage : [];
|
||||
|
||||
this.$set(this, 'upgradeMessage', upgradeMessage);
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
|
||||
version() {
|
||||
this.readyReleaseNote = false;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
async handleUpgrade() {
|
||||
const upgradeValue = {
|
||||
type: HCI.UPGRADE,
|
||||
metadata: {
|
||||
generateName: 'hvst-upgrade-',
|
||||
namespace: 'harvester-system'
|
||||
},
|
||||
spec: { version: this.version }
|
||||
};
|
||||
|
||||
if (this.canEnableLogging) {
|
||||
upgradeValue.spec.logEnabled = this.enableLogging;
|
||||
}
|
||||
|
||||
const proxyResource = await this.$store.dispatch('harvester/create', upgradeValue);
|
||||
|
||||
try {
|
||||
await proxyResource.save();
|
||||
|
||||
this.cancel();
|
||||
} catch (err) {
|
||||
if (err?.message !== '') {
|
||||
this.errors = err.message;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
cancel() {
|
||||
this.$refs.deleteTip.hide();
|
||||
this.errors = '';
|
||||
},
|
||||
|
||||
open() {
|
||||
this.$refs.deleteTip.open();
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="currentCluster">
|
||||
<header class="header-layout header mb-0">
|
||||
<h1>
|
||||
<t
|
||||
k="harvester.dashboard.header"
|
||||
:cluster="currentCluster.nameDisplay"
|
||||
/>
|
||||
</h1>
|
||||
<button v-if="versionOptions.length" type="button" class="btn bg-warning btn-sm" @click="open">
|
||||
<t k="harvester.upgradePage.upgrade" />
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<ModalWithCard ref="deleteTip" name="deleteTip" :width="850">
|
||||
<template #title>
|
||||
<t k="harvester.upgradePage.upgradeApp" />
|
||||
</template>
|
||||
|
||||
<template #content>
|
||||
<UpgradeInfo :version="version" />
|
||||
|
||||
<div class="currentVersion mb-15">
|
||||
<span> <t k="harvester.upgradePage.currentVersion" /> </span>
|
||||
<span class="version">{{ currentVersion }}</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<LabeledSelect
|
||||
v-model="version"
|
||||
class="mb-10"
|
||||
:label="t('harvester.upgradePage.versionLabel')"
|
||||
:options="versionOptions"
|
||||
:clearable="true"
|
||||
/>
|
||||
|
||||
<div v-if="canEnableLogging" class="mb-5">
|
||||
<Checkbox v-model="enableLogging" class="check" type="checkbox" :label="t('harvester.upgradePage.enableLogging')" />
|
||||
</div>
|
||||
|
||||
<div v-if="version">
|
||||
<p v-clean-html="t('harvester.upgradePage.releaseTip', {url: releaseLink}, true)" class="mb-10"></p>
|
||||
|
||||
<Checkbox v-model="readyReleaseNote" class="check" type="checkbox" label-key="harvester.upgradePage.checkReady" />
|
||||
</div>
|
||||
|
||||
<Banner v-if="errors.length" color="warning">
|
||||
{{ errors }}
|
||||
</Banner>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<div class="footer">
|
||||
<button class="btn role-secondary mr-20" @click.prevent="cancel">
|
||||
<t k="generic.close" />
|
||||
</button>
|
||||
<button :disabled="!readyReleaseNote" class="btn role-tertiary bg-primary" @click.prevent="handleUpgrade">
|
||||
<t k="harvester.upgradePage.upgrade" />
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</ModalWithCard>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.banner-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.banner-content {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.banner-message {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-size: 20px;
|
||||
width: 20px;
|
||||
line-height: 23px;
|
||||
}
|
||||
|
||||
.currentVersion {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.version {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,348 @@
|
||||
<script>
|
||||
import { NODE } from '@shell/config/types';
|
||||
import { allHash } from '@shell/utils/promise';
|
||||
import { HCI as HCI_ANNOTATIONS } from '@pkg/harvester/config/labels-annotations';
|
||||
import PercentageBar from '@shell/components/PercentageBar';
|
||||
import BadgeStateFormatter from '@shell/components/formatter/BadgeStateFormatter';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { PRODUCT_NAME as HARVESTER } from '../config/harvester';
|
||||
import { HCI } from '../types';
|
||||
import ProgressBarList from './HarvesterUpgradeProgressBarList';
|
||||
|
||||
export default {
|
||||
name: 'HarvesterUpgradeHeader',
|
||||
components: {
|
||||
PercentageBar, ProgressBarList, BadgeStateFormatter
|
||||
},
|
||||
|
||||
async fetch() {
|
||||
const hash = {};
|
||||
|
||||
if (this.$store.getters['harvester/schemaFor'](HCI.IMAGE)) {
|
||||
hash.images = this.$store.dispatch('harvester/findAll', { type: HCI.IMAGE });
|
||||
}
|
||||
|
||||
if (this.$store.getters['harvester/schemaFor'](HCI.UPGRADE)) {
|
||||
hash.upgrades = this.$store.dispatch('harvester/findAll', { type: HCI.UPGRADE });
|
||||
}
|
||||
|
||||
if (this.$store.getters['harvester/schemaFor'](NODE)) {
|
||||
hash.nodes = this.$store.dispatch('harvester/findAll', { type: NODE });
|
||||
}
|
||||
|
||||
if (this.$store.getters['harvester/schemaFor'](HCI.UPGRADE_LOG)) {
|
||||
hash.upgradeLogs = this.$store.dispatch('harvester/findAll', { type: HCI.UPGRADE_LOG });
|
||||
}
|
||||
|
||||
await allHash(hash);
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
filename: '',
|
||||
logDownloading: false
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters(['currentProduct', 'isVirtualCluster']),
|
||||
|
||||
enabled() {
|
||||
return this.isVirtualCluster && this.currentProduct.name === HARVESTER;
|
||||
},
|
||||
|
||||
latestResource() {
|
||||
return this.$store.getters['harvester/all'](HCI.UPGRADE).find( U => U.isLatestUpgrade);
|
||||
},
|
||||
|
||||
latestUpgradeLogResource() {
|
||||
const upgradeLogId = `${ this.latestResource.id }-upgradelog`;
|
||||
|
||||
return this.$store.getters['harvester/all'](HCI.UPGRADE_LOG).find( U => U.id === upgradeLogId);
|
||||
},
|
||||
|
||||
downloadLogFailReason() {
|
||||
if (!this.filename) {
|
||||
const filename = this.latestUpgradeLogResource?.latestArchivesFileName;
|
||||
|
||||
return this.latestUpgradeLogResource?.downloadArchivesStatus(filename);
|
||||
}
|
||||
|
||||
return this.latestUpgradeLogResource?.downloadArchivesStatus(this.filename);
|
||||
},
|
||||
|
||||
canStartedDownload() {
|
||||
return this.latestUpgradeLogResource?.canStartedDownload || false;
|
||||
},
|
||||
|
||||
overallMessage() {
|
||||
return this.latestResource?.overallMessage;
|
||||
},
|
||||
|
||||
upgradeImage() {
|
||||
const id = this.latestResource?.upgradeImage;
|
||||
|
||||
return this.$store.getters['harvester/all'](HCI.IMAGE).find(I => I.id === id);
|
||||
},
|
||||
|
||||
imageProgress() {
|
||||
return this.upgradeImage?.progress || 0;
|
||||
},
|
||||
|
||||
showImage() {
|
||||
return !this.latestResource.isUpgradeSucceeded;
|
||||
},
|
||||
|
||||
imageMessage() {
|
||||
return this.latestResource?.upgradeImageMessage;
|
||||
},
|
||||
|
||||
repoReady() {
|
||||
return this.latestResource.createRepo;
|
||||
},
|
||||
|
||||
isShow() {
|
||||
return this.latestResource && !this.latestResource.hasReadMessage;
|
||||
},
|
||||
|
||||
nodesStatus() {
|
||||
return this.latestResource?.nodeUpgradeMessage;
|
||||
},
|
||||
|
||||
sysServiceUpgradeMessage() {
|
||||
return this.latestResource?.sysServiceUpgradeMessage;
|
||||
},
|
||||
|
||||
sysServiceTotal() {
|
||||
return this.sysServiceUpgradeMessage?.[0].percent || 0;
|
||||
},
|
||||
|
||||
nodesPercent() {
|
||||
return this.latestResource?.nodeTotalPercent || 0;
|
||||
},
|
||||
|
||||
repoInfo() {
|
||||
return this.latestResource.repoInfo;
|
||||
},
|
||||
|
||||
releaseLink() {
|
||||
return `https://github.com/harvester/harvester/releases/tag/${ this.latestResource?.spec?.version }`;
|
||||
},
|
||||
|
||||
upgradeVersion() {
|
||||
return this.latestResource?.spec?.version;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
ignoreMessage() {
|
||||
this.latestResource.setLabel(HCI_ANNOTATIONS.REAY_MESSAGE, 'true');
|
||||
this.latestResource.save();
|
||||
},
|
||||
|
||||
async generateLogFileName() {
|
||||
const res = await this.latestUpgradeLogResource.doActionGrowl('generate');
|
||||
|
||||
this.filename = res?.data;
|
||||
},
|
||||
|
||||
waitFileGeneratedReady() {
|
||||
const id = this.latestUpgradeLogResource.id;
|
||||
|
||||
return new Promise((resolve) => {
|
||||
let log;
|
||||
|
||||
const timer = setInterval(async() => {
|
||||
log = await this.$store.dispatch('harvester/find', {
|
||||
type: HCI.UPGRADE_LOG,
|
||||
id,
|
||||
opt: { force: true }
|
||||
}, { root: true });
|
||||
|
||||
if (log.fileIsReady(this.filename)) {
|
||||
this.logDownloading = false;
|
||||
clearInterval(timer);
|
||||
resolve();
|
||||
}
|
||||
}, 2500);
|
||||
});
|
||||
},
|
||||
|
||||
async downloadLog() {
|
||||
this.logDownloading = true;
|
||||
await this.generateLogFileName();
|
||||
this.waitFileGeneratedReady().then(() => {
|
||||
if (!this.downloadLogFailReason) {
|
||||
this.latestUpgradeLogResource.downloadLog(this.filename);
|
||||
}
|
||||
this.logDownloading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div v-if="enabled && isShow" class="upgrade">
|
||||
<v-popover
|
||||
v-clean-tooltip="{
|
||||
placement: 'bottom-left',
|
||||
}"
|
||||
class="hand"
|
||||
>
|
||||
<slot name="button-content">
|
||||
<i class="warning icon-fw icon icon-dot-open dot-icon" />
|
||||
</slot>
|
||||
|
||||
<template slot="popover">
|
||||
<div class="upgrade-info mb-10">
|
||||
<div v-if="repoInfo" class="repoInfo">
|
||||
<div class="row">
|
||||
<div class="col span-12">
|
||||
<a :href="releaseLink" target="_blank">{{ upgradeVersion }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="latestResource" class="row mb-5">
|
||||
<div class="col span-12">
|
||||
<p class="state">
|
||||
{{ t('harvester.upgradePage.repoInfo.upgradeStatus') }}: <BadgeStateFormatter class="ml-5" :row="latestResource" />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="downloadLogFailReason" class="row mb-5">
|
||||
<div class="col span-12">
|
||||
<p class="state">
|
||||
{{ t('harvester.upgradePage.repoInfo.logStatus') }}: <span class="error ml-5">{{ downloadLogFailReason }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="bordered-section"></p>
|
||||
|
||||
<div class="row mb-5">
|
||||
<div class="col span-6">
|
||||
{{ t('harvester.upgradePage.repoInfo.os') }}: <span class="text-muted">{{ repoInfo.release.os }}</span>
|
||||
</div>
|
||||
|
||||
<div class="col span-6">
|
||||
{{ t('harvester.productLabel') }}: <span class="text-muted">{{ repoInfo.release.harvester }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-5">
|
||||
<div class="col span-6">
|
||||
{{ t('harvester.upgradePage.repoInfo.harvesterChart') }}: <span class="text-muted">{{ repoInfo.release.harvesterChart }}</span>
|
||||
</div>
|
||||
|
||||
<div class="col span-6">
|
||||
{{ t('harvester.upgradePage.repoInfo.monitoringChart') }}: <span class="text-muted">{{ repoInfo.release.monitoringChart }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-5">
|
||||
<div class="col span-6">
|
||||
{{ t('harvester.upgradePage.repoInfo.kubernetes') }}: <span class="text-muted">{{ repoInfo.release.kubernetes }}</span>
|
||||
</div>
|
||||
|
||||
<div class="col span-6">
|
||||
{{ t('product.rancher') }}: <span class="text-muted">{{ repoInfo.release.rancher }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="bordered-section"></p>
|
||||
</div>
|
||||
|
||||
<p v-if="overallMessage" class="text-warning mb-20">
|
||||
{{ overallMessage }}
|
||||
</p>
|
||||
|
||||
<div v-if="showImage">
|
||||
<h4>{{ t('harvester.upgradePage.upgradeImage') }}<span class="float-r text-info">{{ imageProgress }}%</span></h4>
|
||||
<PercentageBar :value="imageProgress" preferred-direction="MORE" />
|
||||
<p class="text-warning">
|
||||
{{ imageMessage }}
|
||||
</p>
|
||||
<p class="bordered-section"></p>
|
||||
</div>
|
||||
|
||||
<h4>{{ t('harvester.upgradePage.createRepository') }} <span class="float-r text-info">{{ repoReady.isReady ? t('harvester.upgradePage.succeeded') : t('harvester.upgradePage.pending') }}</span></h4>
|
||||
<p v-if="repoReady.message" class="text-warning">
|
||||
{{ repoReady.message }}
|
||||
</p>
|
||||
<p class="bordered-section"></p>
|
||||
|
||||
<ProgressBarList :title="t('harvester.upgradePage.upgradeNode')" :precent="nodesPercent" :list="nodesStatus" />
|
||||
<p class="bordered-section"></p>
|
||||
|
||||
<ProgressBarList :title="t('harvester.upgradePage.upgradeSysService')" :precent="sysServiceTotal" :list="sysServiceUpgradeMessage" />
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<button v-if="canStartedDownload" :disabled="logDownloading" class="btn role-primary mr-10" @click="downloadLog()">
|
||||
<i class="icon mr-10" :class="[logDownloading ? 'icon-spinner icon-spin' : 'icon-download']"></i> {{ t('harvester.upgradePage.repoInfo.downloadLog') }}
|
||||
</button>
|
||||
|
||||
<button v-if="latestResource.isUpgradeSucceeded" class="btn role-primary" @click="ignoreMessage()">
|
||||
{{ t('harvester.upgradePage.dismissMessage') }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</v-popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
a {
|
||||
float: right;
|
||||
color: var(--link) !important;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.upgrade {
|
||||
height: 100%;
|
||||
min-width: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.dot-icon {
|
||||
font-size: 24px;
|
||||
vertical-align: middle;
|
||||
color: #00a483;
|
||||
}
|
||||
}
|
||||
|
||||
.upgrade-info {
|
||||
min-width: 550px;
|
||||
max-height: 90vh;
|
||||
overflow-y: scroll;
|
||||
|
||||
.repoInfo {
|
||||
.col span {
|
||||
word-break: break-all
|
||||
}
|
||||
|
||||
p.state {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.error {
|
||||
color: var(--error);
|
||||
}
|
||||
|
||||
.float-r {
|
||||
float: right;
|
||||
}
|
||||
|
||||
p {
|
||||
word-break: break-word;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,109 @@
|
||||
<script>
|
||||
import Collapse from '@shell/components/Collapse';
|
||||
import PercentageBar from '@shell/components/PercentageBar';
|
||||
|
||||
export default {
|
||||
name: 'HarvesterUpgradeProgressList',
|
||||
components: { PercentageBar, Collapse },
|
||||
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
precent: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return { open: true };
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleSwitch() {
|
||||
this.open = !this.open;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="bar-list">
|
||||
<h4>{{ title }} <span class="float-r text-info">{{ precent }}%</span></h4>
|
||||
<div>
|
||||
<div>
|
||||
<Collapse :open.sync="open">
|
||||
<template #title>
|
||||
<div class="total-bar">
|
||||
<span class="bar"><PercentageBar :value="precent" preferred-direction="MORE" /></span>
|
||||
<span class="on-off" @click="handleSwitch"> {{ open ? t('harvester.generic.close') : t('harvester.generic.open') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template>
|
||||
<div class="custom-content">
|
||||
<div v-for="item in list" :key="item.name" class="item">
|
||||
<p>{{ item.name }} <span class="status" :class="{ [item.state]: true }">{{ item.state }}</span></p>
|
||||
<PercentageBar :value="item.percent" preferred-direction="MORE" />
|
||||
<p class="warning">
|
||||
{{ item.message }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Collapse>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.bar-list {
|
||||
.float-r {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.total-bar {
|
||||
display: flex;
|
||||
user-select: none;
|
||||
.bar {
|
||||
width: 85%;
|
||||
}
|
||||
.on-off {
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.custom-content {
|
||||
.item {
|
||||
margin-bottom: 14px;
|
||||
p {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.status {
|
||||
float: right;
|
||||
}
|
||||
.Succeeded, .Upgrading, .Pending {
|
||||
color: var(--success);
|
||||
}
|
||||
.failed {
|
||||
color: var(--error)
|
||||
}
|
||||
.warning {
|
||||
color: var(--error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,42 @@
|
||||
<script>
|
||||
import { Banner } from '@components/Banner';
|
||||
|
||||
export default {
|
||||
name: 'HarvesterUpgradeInfo',
|
||||
|
||||
components: { Banner },
|
||||
|
||||
props: {
|
||||
version: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
releaseVersion() {
|
||||
return !!this.version ? `https://github.com/harvester/harvester/releases/tag/${ this.version }` : `https://github.com/harvester/harvester/releases`;
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<Banner color="warning">
|
||||
<div>
|
||||
<strong>{{ t('harvester.upgradePage.upgradeInfo.warning') }}:</strong>
|
||||
<p v-clean-html="t('harvester.upgradePage.upgradeInfo.doc', {}, true)" class="mb-5">
|
||||
</p>
|
||||
|
||||
<p class="mb-5">
|
||||
{{ t('harvester.upgradePage.upgradeInfo.tip') }}
|
||||
</p>
|
||||
|
||||
<p class="mb-5">
|
||||
{{ t('harvester.upgradePage.upgradeInfo.moreNotes') }} <a :href="releaseVersion" target="_blank">{{ t('generic.moreInfo') }} </a>
|
||||
</p>
|
||||
</div>
|
||||
</Banner>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user