import/export templates

This commit is contained in:
Qiuxia Fan 2022-03-16 18:11:59 +08:00
parent 1af4adcb96
commit 3ffdc0cf08
6 changed files with 139 additions and 9 deletions

View File

@ -100,6 +100,8 @@ const msg = {
id: "ID", id: "ID",
setRoot: "Set this to root", setRoot: "Set this to root",
setNormal: "Set this to normal", setNormal: "Set this to normal",
export: "Export Dashboard Templates",
import: "Import Dashboard Templates",
hourTip: "Select Hour", hourTip: "Select Hour",
minuteTip: "Select Minute", minuteTip: "Select Minute",
secondTip: "Select Second", secondTip: "Select Second",

View File

@ -100,6 +100,8 @@ const msg = {
id: "编号", id: "编号",
setRoot: "设置成为根", setRoot: "设置成为根",
setNormal: "设置成为普通", setNormal: "设置成为普通",
export: "导出仪表板模板",
import: "导入仪表板模板",
hourTip: "选择小时", hourTip: "选择小时",
minuteTip: "选择分钟", minuteTip: "选择分钟",
secondTip: "选择秒数", secondTip: "选择秒数",

View File

@ -413,8 +413,8 @@ export const dashboardStore = defineStore({
this.dashboards.push({ this.dashboards.push({
id: json.id, id: json.id,
name: this.currentDashboard.name, name: this.currentDashboard.name,
layer: this.layerId, layer: this.currentDashboard.layer,
entity: this.entity, entity: this.currentDashboard.entity,
isRoot: true, isRoot: true,
}); });
const key = [ const key = [

View File

@ -16,7 +16,7 @@
*/ */
export type DashboardItem = { export type DashboardItem = {
id: string; id?: string;
entity: string; entity: string;
layer: string; layer: string;
isRoot: string; isRoot: string;

44
src/utils/file.ts Normal file
View File

@ -0,0 +1,44 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export const readFile = (event: any) => {
return new Promise((resolve) => {
const { files } = event.target;
if (files.length < 1) {
return;
}
const file = files[0];
const reader: FileReader = new FileReader();
reader.readAsText(file);
reader.onload = function () {
if (typeof this.result === "string") {
resolve(JSON.parse(this.result));
}
};
});
};
export const saveFile = (data: any, name: string) => {
const newData = JSON.stringify(data);
const tagA = document.createElement("a");
tagA.download = name;
tagA.style.display = "none";
const blob = new Blob([newData]);
tagA.href = URL.createObjectURL(blob);
document.body.appendChild(tagA);
tagA.click();
document.body.removeChild(tagA);
};

View File

@ -36,12 +36,13 @@ limitations under the License. -->
</div> </div>
<div class="table"> <div class="table">
<el-table <el-table
:border="true"
:data="dashboards" :data="dashboards"
:style="{ width: '100%', fontSize: '13px' }" :style="{ width: '100%', fontSize: '13px' }"
max-height="550"
v-loading="loading" v-loading="loading"
ref="multipleTableRef"
@selection-change="handleSelectionChange"
> >
<el-table-column type="selection" width="35" />
<el-table-column fixed prop="name" label="Name" /> <el-table-column fixed prop="name" label="Name" />
<el-table-column prop="layer" label="Layer" width="200" /> <el-table-column prop="layer" label="Layer" width="200" />
<el-table-column prop="entity" label="Entity" width="200" /> <el-table-column prop="entity" label="Entity" width="200" />
@ -59,7 +60,7 @@ limitations under the License. -->
@confirm="setRoot(scope.row)" @confirm="setRoot(scope.row)"
> >
<template #reference> <template #reference>
<el-button size="small"> <el-button size="small" style="width: 120px">
{{ scope.row.isRoot ? t("setNormal") : t("setRoot") }} {{ scope.row.isRoot ? t("setNormal") : t("setRoot") }}
</el-button> </el-button>
</template> </template>
@ -77,6 +78,27 @@ limitations under the License. -->
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div class="toggle-selection">
<el-button size="default" class="btn" @click="exportTemplates">
<Icon class="mr-5" iconName="save_alt" />
{{ t("export") }}
</el-button>
<el-button class="ml-10 btn" size="default">
<input
id="dashboard-file"
class="import-template"
type="file"
name="file"
title=""
accept=".json"
@change="importTemplates"
/>
<label for="dashboard-file" class="input-label">
<Icon class="mr-5" iconName="folder_open" />
{{ t("import") }}
</label>
</el-button>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -89,6 +111,7 @@ import { useAppStoreWithOut } from "@/store/modules/app";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import router from "@/router"; import router from "@/router";
import { DashboardItem } from "@/types/dashboard"; import { DashboardItem } from "@/types/dashboard";
import { saveFile, readFile } from "@/utils/file";
const appStore = useAppStoreWithOut(); const appStore = useAppStoreWithOut();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
@ -109,19 +132,58 @@ const dashboards = ref<DashboardItem[]>([]);
const searchText = ref<string>(""); const searchText = ref<string>("");
const loading = ref<boolean>(false); const loading = ref<boolean>(false);
const multipleTableRef = ref<InstanceType<typeof ElTable>>(); const multipleTableRef = ref<InstanceType<typeof ElTable>>();
const multipleSelection = ref<DashboardItem[]>([]);
const handleSelectionChange = (val: DashboardItem[]) => {
multipleSelection.value = val;
};
setList(); setList();
async function setList() { async function setList() {
await dashboardStore.setDashboards(); await dashboardStore.setDashboards();
dashboards.value = dashboardStore.dashboards; dashboards.value = dashboardStore.dashboards;
} }
const handleView = (row: DashboardItem) => { async function importTemplates(event: any) {
const arr: any = await readFile(event);
loading.value = true;
for (const item of arr) {
const { layer, name, entity, isRoot, children } = item.configuration;
const index = dashboardStore.dashboards.findIndex(
(d: DashboardItem) => d.id === item.id
);
const p: DashboardItem = {
name: name,
layer: layer,
entity: entity,
isRoot: isRoot,
};
if (index > -1) {
p.id = item.id;
}
dashboardStore.setCurrentDashboard(p);
dashboardStore.setLayout(children);
await dashboardStore.saveDashboard();
}
dashboards.value = dashboardStore.dashboards;
loading.value = false;
const el: any = document.getElementById("dashboard-file");
el!.value = "";
}
function exportTemplates() {
const templates = multipleSelection.value.map((d: DashboardItem) => {
const key = [d.layer, d.entity, d.name.split(" ").join("-")].join("_");
const layout = JSON.parse(sessionStorage.getItem(key) || "{}");
return layout;
});
const name = `dashboards.json`;
saveFile(templates, name);
}
function handleView(row: DashboardItem) {
dashboardStore.setCurrentDashboard(row); dashboardStore.setCurrentDashboard(row);
router.push( router.push(
`/dashboard/${row.layer}/${row.entity}/${row.name.split(" ").join("-")}` `/dashboard/${row.layer}/${row.entity}/${row.name.split(" ").join("-")}`
); );
}; }
async function setRoot(row: DashboardItem) { async function setRoot(row: DashboardItem) {
const items: any[] = []; const items: any[] = [];
loading.value = true; loading.value = true;
@ -285,4 +347,24 @@ function searchDashboards() {
box-shadow: 0px 1px 4px 0px #00000029; box-shadow: 0px 1px 4px 0px #00000029;
border-radius: 5px; border-radius: 5px;
} }
.toggle-selection {
margin-top: 20px;
background-color: #fff;
}
.btn {
width: 220px;
font-size: 13px;
}
.import-template {
display: none;
}
.input-label {
display: inline;
line-height: inherit;
cursor: pointer;
}
</style> </style>