+
-
+
diff --git a/static_source/admin/src/views/Automation/components/TriggersSearch.vue b/static_source/admin/src/views/Automation/components/TriggersSearch.vue
index ef6a1c21a..ae9777d9a 100644
--- a/static_source/admin/src/views/Automation/components/TriggersSearch.vue
+++ b/static_source/admin/src/views/Automation/components/TriggersSearch.vue
@@ -22,6 +22,9 @@ watch(
(val?: number[]) => {
if (val === unref(value)) return
value.value = val || [] ;
+ if (val) {
+ getList(val)
+ }
},
)
@@ -40,7 +43,7 @@ watch(
}
)
-const remoteMethod = async (query: string) => {
+const searchMethod = async (query: string) => {
loading.value = true
const params = {query: query, limit: 25, offset: 0}
const {data} = await api.v1.triggerServiceSearchTrigger(params)
@@ -53,7 +56,27 @@ const remoteMethod = async (query: string) => {
options.value = items
}
-remoteMethod("")
+interface Params {
+ page?: number;
+ limit?: number;
+ sort?: string;
+ ids?: [];
+}
+
+const getList = async (ids: number[]) => {
+ let params: Params = {
+ ids: ids,
+ }
+ const res = await api.v1.triggerServiceGetTriggerList(params)
+ .catch(() => {
+ })
+ .finally(() => {
+ })
+ if (res) {
+ const {items, meta} = res.data;
+ options.value = items || [];
+ }
+}
const handleSelect = (val: ApiTrigger) => {
emit('change', val)
@@ -70,7 +93,7 @@ const handleSelect = (val: ApiTrigger) => {
remote
reserve-keyword
placeholder="Please enter a keyword"
- :remote-method="remoteMethod"
+ :remote-method="searchMethod"
:loading="loading"
@select="handleSelect"
>
@@ -79,7 +102,9 @@ const handleSelect = (val: ApiTrigger) => {
:key="item.id"
:label="item.name"
:value="item.id"
- />
+ >
+
{{ item.name }} (id: {{ item.id }})
+
diff --git a/static_source/admin/src/views/Backups/index.vue b/static_source/admin/src/views/Backups/index.vue
index ae6886b46..81bc7a9bf 100644
--- a/static_source/admin/src/views/Backups/index.vue
+++ b/static_source/admin/src/views/Backups/index.vue
@@ -100,51 +100,53 @@ const getList = async () => {
}
const addNew = async () => {
- api.v1.backupServiceNewBackup({})
+ const res = await api.v1.backupServiceNewBackup({})
.catch(() => {
})
.finally(() => {
})
- ElMessage({
- title: t('Success'),
- message: t('message.createdSuccessfully'),
- type: 'success',
- duration: 2000
- });
+ if (res.status == 200) {
+ ElMessage({
+ title: t('Success'),
+ message: t('message.createdSuccessfully'),
+ type: 'success',
+ duration: 2000
+ });
+ }
}
const restore = async (backup: ApiBackup) => {
- api.v1.backupServiceRestoreBackup(backup.name)
+ const res = await api.v1.backupServiceRestoreBackup(backup.name)
.catch(() => {
})
.finally(() => {
})
- setTimeout(async () => {
+ if (res.status == 200) {
ElMessage({
title: t('Success'),
message: t('message.callSuccessful'),
type: 'success',
duration: 2000
});
- }, 2000)
+ }
}
const remove = async (backup: ApiBackup) => {
- api.v1.backupServiceDeleteBackup(backup.name)
+ const res = await api.v1.backupServiceDeleteBackup(backup.name)
.catch(() => {
})
.finally(() => {
})
- setTimeout(async () => {
+ if (res.status == 200) {
ElMessage({
title: t('Success'),
message: t('message.callSuccessful'),
type: 'success',
duration: 2000
});
- }, 2000)
+ }
}
const getUploadURL = () => {
@@ -178,6 +180,16 @@ const onSuccess: UploadProps['onSuccess'] = (file: ApiBackup, uploadFile) => {
})
}
+const onError: UploadProps['onError'] = (error, uploadFile, uploadFiles) => {
+ const body = JSON.parse(error.message)
+ const {message, code} = body.error;
+ ElMessage({
+ message: message,
+ type: 'error',
+ duration: 0
+ })
+}
+
const forceFileDownload = (file: ApiBackup) => {
const link = document.createElement('a')
link.href = getDownloadURL(file)
@@ -244,6 +256,7 @@ getList()
:action="getUploadURL()"
:multiple="true"
:on-success="onSuccess"
+ :on-error="onError"
:auto-upload="true"
>
diff --git a/static_source/admin/src/views/Dashboard/bus.ts b/static_source/admin/src/views/Dashboard/bus.ts
index b0c6e8c16..3b8c12ba4 100644
--- a/static_source/admin/src/views/Dashboard/bus.ts
+++ b/static_source/admin/src/views/Dashboard/bus.ts
@@ -18,6 +18,9 @@ export const useBus = (option?: Option) => {
}
return {
- bus
+ on: bus.on,
+ off: bus.off,
+ emit: bus.emit,
+ all: bus.all
}
}
diff --git a/static_source/admin/src/views/Dashboard/card_items/chart/index.vue b/static_source/admin/src/views/Dashboard/card_items/chart/index.vue
index 23cc16d5b..4e73756b2 100644
--- a/static_source/admin/src/views/Dashboard/card_items/chart/index.vue
+++ b/static_source/admin/src/views/Dashboard/card_items/chart/index.vue
@@ -13,7 +13,7 @@ import {Cache, GetTokens, RenderText} from "@/views/Dashboard/render";
import {UUID} from "uuid-generator-ts";
import stream from "@/api/stream";
-const {bus} = useBus()
+const {emit} = useBus()
// ---------------------------------
// common
@@ -522,7 +522,7 @@ const prepareData = debounce( async () => {
case 'doughnut':
loaded.value = true;
fistTime.value = false
- bus.emit('updateChart', props.item.payload.chart.type)
+ emit('updateChart', props.item.payload.chart.type)
return
}
@@ -545,7 +545,7 @@ const prepareData = debounce( async () => {
console.warn(`unknown chart type ${props.item.entity.metrics[props.item.payload.chart?.metric_index || 0].type}`);
}
- bus.emit('updateChart', props.item.payload.chart.type)
+ emit('updateChart', props.item.payload.chart.type)
loaded.value = true;
fistTime.value = false
diff --git a/static_source/admin/src/views/Dashboard/card_items/chart_custom/editor.vue b/static_source/admin/src/views/Dashboard/card_items/chart_custom/editor.vue
index 1ea55d08b..764b462d1 100644
--- a/static_source/admin/src/views/Dashboard/card_items/chart_custom/editor.vue
+++ b/static_source/admin/src/views/Dashboard/card_items/chart_custom/editor.vue
@@ -33,8 +33,8 @@ import {useI18n} from "@/hooks/web/useI18n";
import {Infotip} from "@/components/Infotip";
import {debounce} from "lodash-es";
import {EChartsOption} from "echarts";
-import ImageSearch from "@/views/Images/components/ImageSearch.vue";
import {ApiImage} from "@/api/stub";
+import JsonEditor from "@/components/JsonEditor/JsonEditor.vue";
const {t} = useI18n()
@@ -125,14 +125,22 @@ const removeAttrItem = (prop: SeriesItem, index: number) => {
// attributes item
-const editorHandler = debounce((val: string) => {
+const editorHandler = debounce((val: any) => {
if (!val) {
- val = defaultData;
+ val = {
+ text: defaultData,
+ }
}
try {
- var options: EChartsOption = parsedObject(val) as EChartsOption;
+ let options: EChartsOption;
+
+ if (val.json) {
+ options = val.json as EChartsOption
+ } else if(val.text) {
+ options = parsedObject(val.text) as EChartsOption
+ }
if (!options.grid) {
options['grid'] = {
@@ -225,7 +233,7 @@ const onSelectImage = (image: ApiImage) => {
-
+
diff --git a/static_source/admin/src/views/Dashboard/card_items/common/editor.vue b/static_source/admin/src/views/Dashboard/card_items/common/editor.vue
index 2acff3b1f..7f13ad243 100644
--- a/static_source/admin/src/views/Dashboard/card_items/common/editor.vue
+++ b/static_source/admin/src/views/Dashboard/card_items/common/editor.vue
@@ -148,7 +148,7 @@ const removeAction = (index: number) => {
-
+
{{$t('dashboard.editor.buttonOptions') }}
@@ -157,7 +157,7 @@ const removeAction = (index: number) => {
-
+
diff --git a/static_source/admin/src/views/Dashboard/card_items/common/show-on.vue b/static_source/admin/src/views/Dashboard/card_items/common/show-on.vue
index 9332c6a6c..ba144c879 100644
--- a/static_source/admin/src/views/Dashboard/card_items/common/show-on.vue
+++ b/static_source/admin/src/views/Dashboard/card_items/common/show-on.vue
@@ -81,7 +81,7 @@ const removeShowOnProp = (index: number) => {
-
+
{
if (props.item?.payload.entityStorage?.entityIds?.length ) {
if (selectedEntities.value.length == 0) {
- params.entityId = props.item?.payload.entityStorage?.entityIds.join(",")
+ params.entityId = props.item?.payload.entityStorage?.entityIds || []
} else {
- params.entityId = selectedEntities.value.join(",")
+ params.entityId = selectedEntities.value
}
}
@@ -211,7 +211,7 @@ const getList = debounce( async () => {
} else {
tableObject.tableList = [];
}
-}, 100)
+}, 1000)
const onStateChanged = (event: EventStateChange) => {
diff --git a/static_source/admin/src/views/Dashboard/card_items/index.ts b/static_source/admin/src/views/Dashboard/card_items/index.ts
index f2e31b286..ffd763753 100644
--- a/static_source/admin/src/views/Dashboard/card_items/index.ts
+++ b/static_source/admin/src/views/Dashboard/card_items/index.ts
@@ -30,6 +30,8 @@ import joystick from './joystick/index.vue';
import joystickEditor from './joystick/editor.vue';
import icon from './icon/index.vue';
import iconEditor from './icon/editor.vue';
+import tiles from './tiles/index.vue';
+import tilesEditor from './tiles/editor.vue';
export const CardItemName = (name: string): any => {
switch (name) {
@@ -63,6 +65,8 @@ export const CardItemName = (name: string): any => {
return joystick;
case 'icon':
return icon;
+ case 'tiles':
+ return tiles;
default:
// console.error(`unknown card name "${name}"`);
return dummy;
@@ -101,6 +105,8 @@ export const CardEditorName = (name: string): any => {
return joystickEditor;
case 'icon':
return iconEditor;
+ case 'tiles':
+ return tilesEditor;
default:
// console.error(`unknown card name "${name}"`);
return dummyEditor;
@@ -127,5 +133,6 @@ export const CardItemList: ItemsType[] = [
{label: 'COLOR_PICKER', value: 'colorPicker'},
{label: 'STREAM_PLAYER', value: 'streamPlayer'},
{label: 'JOYSTICK', value: 'joystick'},
- {label: 'ICON', value: 'icon'}
+ {label: 'ICON', value: 'icon'},
+ {label: 'TILES', value: 'tiles'}
];
diff --git a/static_source/admin/src/views/Dashboard/card_items/joystick/types.ts b/static_source/admin/src/views/Dashboard/card_items/joystick/types.ts
index a96c64f7c..a824c0655 100644
--- a/static_source/admin/src/views/Dashboard/card_items/joystick/types.ts
+++ b/static_source/admin/src/views/Dashboard/card_items/joystick/types.ts
@@ -117,12 +117,12 @@ export class JoystickController {
this.active = false;
}
- _stick._value.addEventListener('mousedown', handleDown);
- _stick._value.addEventListener('touchstart', handleDown);
+ _stick._value.addEventListener('mousedown', handleDown, {passive: false});
+ _stick._value.addEventListener('touchstart', handleDown, {passive: false});
document.addEventListener('mousemove', handleMove, {passive: false});
document.addEventListener('touchmove', handleMove, {passive: false});
- document.addEventListener('mouseup', handleUp);
- document.addEventListener('touchend', handleUp);
+ document.addEventListener('mouseup', handleUp, {passive: false});
+ document.addEventListener('touchend', handleUp, {passive: false});
}
}
diff --git a/static_source/admin/src/views/Dashboard/card_items/state/editor.vue b/static_source/admin/src/views/Dashboard/card_items/state/editor.vue
index a3f361d57..4b9691174 100644
--- a/static_source/admin/src/views/Dashboard/card_items/state/editor.vue
+++ b/static_source/admin/src/views/Dashboard/card_items/state/editor.vue
@@ -101,13 +101,13 @@ const onSelectIconForState = (index: number, icon: string) => {
const reloadKeyDefaultImage = 0;
const onSelectDefaultImage = (image: ApiImage) => {
- console.log('select image', image);
+ // console.log('select image', image);
if (!props.item.payload.state) {
initDefaultValue();
}
- current_item.value.payload.state.defaultImage = image as ApiImage || undefined;
+ currentItem.value.payload.state.defaultImage = image as ApiImage || undefined;
// this.reloadKeyDefaultImage += 1
props.item.update();
}
diff --git a/static_source/admin/src/views/Dashboard/card_items/text/editor.vue b/static_source/admin/src/views/Dashboard/card_items/text/editor.vue
index ad63417e9..bf1da288d 100644
--- a/static_source/admin/src/views/Dashboard/card_items/text/editor.vue
+++ b/static_source/admin/src/views/Dashboard/card_items/text/editor.vue
@@ -117,6 +117,7 @@ const updateCurrentState = () => {
+
{{ $t('dashboard.editor.textOptions') }}
@@ -285,6 +286,7 @@ const updateCurrentState = () => {
+
diff --git a/static_source/admin/src/views/Dashboard/card_items/tiles/editor.vue b/static_source/admin/src/views/Dashboard/card_items/tiles/editor.vue
new file mode 100644
index 000000000..435946b45
--- /dev/null
+++ b/static_source/admin/src/views/Dashboard/card_items/tiles/editor.vue
@@ -0,0 +1,424 @@
+
+
+
+
+
+
+ {{ $t('dashboard.editor.tilesOptions') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('dashboard.editor.tiles.items') }}
+
+
+
+
+
+
+ {{ $t('dashboard.editor.addNewProp') }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ prop.key }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('dashboard.editor.tiles.preview') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('main.remove') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('dashboard.editor.image') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('dashboard.editor.tiles.preview') }}
+
+
+
+
+
+
+
+
+ {{ $t('dashboard.editor.action') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('dashboard.editor.getEvent') }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/static_source/admin/src/views/Dashboard/card_items/tiles/index.vue b/static_source/admin/src/views/Dashboard/card_items/tiles/index.vue
new file mode 100644
index 000000000..9a1fb02c3
--- /dev/null
+++ b/static_source/admin/src/views/Dashboard/card_items/tiles/index.vue
@@ -0,0 +1,150 @@
+
+
+
+
+
+
+
diff --git a/static_source/admin/src/views/Dashboard/card_items/tiles/tilePreview.vue b/static_source/admin/src/views/Dashboard/card_items/tiles/tilePreview.vue
new file mode 100644
index 000000000..36010f0da
--- /dev/null
+++ b/static_source/admin/src/views/Dashboard/card_items/tiles/tilePreview.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
diff --git a/static_source/admin/src/views/Dashboard/card_items/tiles/tileView.vue b/static_source/admin/src/views/Dashboard/card_items/tiles/tileView.vue
new file mode 100644
index 000000000..78dc13ab7
--- /dev/null
+++ b/static_source/admin/src/views/Dashboard/card_items/tiles/tileView.vue
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
diff --git a/static_source/admin/src/views/Dashboard/card_items/tiles/types.ts b/static_source/admin/src/views/Dashboard/card_items/tiles/types.ts
new file mode 100644
index 000000000..7def63965
--- /dev/null
+++ b/static_source/admin/src/views/Dashboard/card_items/tiles/types.ts
@@ -0,0 +1,27 @@
+import {ApiEntity, ApiImage} from '@/api/stub'
+
+export interface TileProp {
+ image?: ApiImage
+ key: string
+ position?: boolean
+ top?: number
+ left?: number
+ height?: number
+ width?: number
+}
+
+export interface ItemPayloadTiles {
+ items: TileProp[]
+ image?: ApiImage
+ columns: number
+ rows: number
+ tileHeight: number
+ tileWidth: number
+ attribute: string
+ entity?: ApiEntity
+ entityId?: string
+ actionName?: string
+ position?: boolean
+ top?: number
+ left?: number
+}
diff --git a/static_source/admin/src/views/Dashboard/card_items/video/VideoMse.vue b/static_source/admin/src/views/Dashboard/card_items/video/VideoMse.vue
index 6ee9112d3..1f79e0221 100644
--- a/static_source/admin/src/views/Dashboard/card_items/video/VideoMse.vue
+++ b/static_source/admin/src/views/Dashboard/card_items/video/VideoMse.vue
@@ -102,7 +102,7 @@ const startPlay = () => {
startPlay();
}, 1000);
};
- }, false)
+ }, {passive: false})
}
const stopPlay = () => {
diff --git a/static_source/admin/src/views/Dashboard/components/KeystrokeCapture.vue b/static_source/admin/src/views/Dashboard/components/KeystrokeCapture.vue
new file mode 100644
index 000000000..713957f5b
--- /dev/null
+++ b/static_source/admin/src/views/Dashboard/components/KeystrokeCapture.vue
@@ -0,0 +1,263 @@
+
+
+
+
+
+
+
+
+
+ {{ $t('dashboard.editor.addAction') }}
+
+
+
+
+
+
+
+
+ ID: {{ index }}
+
+
+
+ {{ prop.entityId }}
+
+
+
+
+ {{ prop.action }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('dashboard.editor.addNewButton') }}
+
+
+
+
+
+
+
+
+ {{ value }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('main.remove') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/static_source/admin/src/views/Dashboard/components/KeystrokeCaptureViewer.vue b/static_source/admin/src/views/Dashboard/components/KeystrokeCaptureViewer.vue
new file mode 100644
index 000000000..c0a10f47b
--- /dev/null
+++ b/static_source/admin/src/views/Dashboard/components/KeystrokeCaptureViewer.vue
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
diff --git a/static_source/admin/src/views/Dashboard/core.ts b/static_source/admin/src/views/Dashboard/core.ts
index 6a3e99cc5..2c4de1c72 100644
--- a/static_source/admin/src/views/Dashboard/core.ts
+++ b/static_source/admin/src/views/Dashboard/core.ts
@@ -33,8 +33,9 @@ import {ItemPayloadJoystick} from "@/views/Dashboard/card_items/joystick/types";
import {ItemPayloadVideo} from "@/views/Dashboard/card_items/video/types";
import {ItemPayloadEntityStorage} from "@/views/Dashboard/card_items/entity_storage/types";
import {prepareUrl} from "@/utils/serverId";
+import {ItemPayloadTiles} from "@/views/Dashboard/card_items/tiles/types";
-const {bus} = useBus()
+const {emit} = useBus()
export interface ButtonAction {
entityId: string;
@@ -82,6 +83,13 @@ export interface CompareProp {
entityId?: string;
}
+export interface KeysProp {
+ keys?: Map;
+ entity?: { id?: string };
+ entityId?: string;
+ action?: string;
+}
+
export interface ItemPayloadImage {
attrField?: string;
image?: ApiImage;
@@ -111,6 +119,7 @@ export interface ItemPayload {
joystick?: ItemPayloadJoystick;
video?: ItemPayloadVideo;
entityStorage?: ItemPayloadEntityStorage;
+ tiles?: ItemPayloadTiles;
}
export interface ItemParams {
@@ -122,6 +131,7 @@ export interface ItemParams {
transform: string;
showOn: CompareProp[];
hideOn: CompareProp[];
+ keysCapture?: KeysProp[];
asButton: boolean;
buttonActions: ButtonAction[];
}
@@ -235,7 +245,7 @@ export class CardItem {
if (!this.payload.text) {
this.payload.text = {
items: [],
- default_text: 'default text',
+ default_text: 'default text
',
current_text: ''
} as ItemPayloadText;
}
@@ -298,6 +308,17 @@ export class CardItem {
if (!this.payload.entityStorage) {
this.payload.entityStorage = {} as ItemPayloadEntityStorage;
}
+ if (!this.payload.tiles) {
+ this.payload.tiles = {
+ items: [],
+ defaultImage: undefined,
+ columns: 5,
+ rows: 5,
+ tileHeight: 25,
+ tileWidth: 25,
+ attribute: '',
+ } as ItemPayloadTiles;
+ }
}
}
@@ -363,7 +384,7 @@ export class CardItem {
payload: {
text: {
items: [],
- default_text: 'default text',
+ default_text: 'default text
',
current_text: ''
} as ItemPayloadText
},
@@ -638,6 +659,7 @@ export class Card {
hidden: boolean
showOn: CompareProp[] = [];
hideOn: CompareProp[] = [];
+ keysCapture: KeysProp[] = [];
selectedItem = -1;
@@ -675,6 +697,9 @@ export class Card {
if (payload.hideOn) {
this.hideOn = payload.hideOn;
}
+ if (payload.keysCapture) {
+ this.keysCapture = payload.keysCapture;
+ }
}
for (const index in card.items) {
@@ -759,9 +784,10 @@ export class Card {
items.push(this.items[index].serialize());
}
- const payload = btoa(unescape(encodeURIComponent(JSON.stringify({
+ const payload = btoa(unescape(encodeURIComponent(serializedObject({
showOn: this.showOn,
hideOn: this.hideOn,
+ keysCapture: this.keysCapture,
}))));
const card = {
id: this.id,
@@ -858,7 +884,7 @@ export class Card {
this.updateItemList()
- bus.emit('selected_card_item', -1);
+ emit('selected_card_item', -1);
}
async copyItem(index: number) {
@@ -888,6 +914,36 @@ export class Card {
this.items.sort(sortCardItems);
}
+ sortCardItemUp(item: CardItem, index: number) {
+ if (!this.items[index - 1]) {
+ return;
+ }
+
+ const rows = [this.items[index - 1], this.items[index]];
+ this.items.splice(index - 1, 2, rows[1], rows[0]);
+
+ let counter = 0
+ for (const index in this.items) {
+ this.items[index].weight = counter;
+ counter++;
+ }
+ }
+
+ sortCardItemDown(item: CardItem, index: number) {
+ if (!this.items[index + 1]) {
+ return;
+ }
+
+ const rows = [this.items[index], this.items[index + 1]];
+ this.items.splice(index, 2, rows[1], rows[0]);
+
+ let counter = 0
+ for (const index in this.items) {
+ this.items[index].weight = counter;
+ counter++;
+ }
+ }
+
// ---------------------------------
// events
// ---------------------------------
@@ -961,7 +1017,6 @@ export class Tab {
cards: Card[] = [];
columnWidth: number;
dashboardId: number;
- dragEnabled: boolean;
enabled: boolean;
entities: Map;
gap: boolean;
@@ -975,7 +1030,6 @@ export class Tab {
this.cards = [];
this.columnWidth = tab.columnWidth;
this.dashboardId = tab.dashboardId;
- this.dragEnabled = tab.dragEnabled;
this.enabled = tab.enabled;
this.entities = tab.entities;
this.gap = tab.gap;
@@ -997,7 +1051,7 @@ export class Tab {
icon: '',
columnWidth: columnWidth,
gap: false,
- background: 'inherit',
+ background: '',
enabled: true,
weight: weight,
dashboardId: boardId
@@ -1036,7 +1090,6 @@ export class Tab {
background: this.background,
icon: this.icon,
enabled: this.enabled,
- dragEnabled: this.dragEnabled,
weight: this.weight,
dashboardId: this.dashboardId,
cards: cards,
@@ -1052,6 +1105,39 @@ export class Tab {
this.cards.sort(sortCards);
}
+ sortCardUp(card: Card, index: number) {
+ if (!this.cards[index - 1]) {
+ return;
+ }
+
+ const rows = [this.cards[index - 1], this.cards[index]];
+ this.cards.splice(index - 1, 2, rows[1], rows[0]);
+
+ let counter = 0
+ for (const index in this.cards) {
+ this.cards[index].weight = counter;
+ this.cards[index].update();
+ counter++;
+ }
+
+ }
+
+ sortCardDown(card: Card, index: number) {
+ if (!this.cards[index + 1]) {
+ return;
+ }
+
+ const rows = [this.cards[index], this.cards[index + 1]];
+ this.cards.splice(index, 2, rows[1], rows[0]);
+
+ let counter = 0
+ for (const index in this.cards) {
+ this.cards[index].weight = counter;
+ this.cards[index].update();
+ counter++;
+ }
+ }
+
get cards2(): Card[] {
//todo fix items sort
const cards: Card[] = [];
@@ -1077,8 +1163,7 @@ export class Tab {
export class Core {
current: ApiDashboard = {} as ApiDashboard;
- activeTab = 0; // index
- currentTabId: number | undefined;
+ private _activeTabIdx = 0; // index
activeCard: number | undefined = undefined; // index
currentCardId: number | undefined;
@@ -1095,17 +1180,11 @@ export class Core {
currentBoard(current: ApiDashboard) {
this.current = current;
this.tabs = [];
- this.activeTab = 0;
- this.currentTabId = undefined;
+ this._activeTabIdx = 0;
if (current.tabs && current.tabs.length > 0) {
for (const index in current.tabs) {
this.tabs.push(new Tab(current.tabs[index]));
}
- this.currentTabId = this.tabs[this.activeTab].id;
-
- if (this.tabs[this.activeTab].cards.length > 0) {
- this.activeCard = 0;
- }
}
// get entity for card item
@@ -1122,8 +1201,16 @@ export class Core {
}
}
+ if (!this.getActiveTab) {
+ return
+ }
+
this.sortTabs();
+ if (this.getActiveTab.cards.length > 0) {
+ this.onSelectedCard(this.getActiveTab.cards[0].id)
+ }
+
this.updateCurrentTab();
}
@@ -1204,106 +1291,144 @@ export class Core {
// ---------------------------------
// tabs
// ---------------------------------
+
+ set activeTabIdx(idx: number) {
+ if (this._activeTabIdx == idx) {
+ return
+ }
+ this._activeTabIdx = idx;
+ }
+ get activeTabIdx(): number {
+ return this._activeTabIdx;
+ }
+ get getActiveTab(): Tab | undefined {
+ if (this._activeTabIdx === undefined || this._activeTabIdx < 0) {
+ this._activeTabIdx = 0
+ }
+ return this.tabs[this._activeTabIdx] || undefined;
+ }
+
+ selectTabInMenu(idx: number) {
+ if (this._activeTabIdx === idx) return;
+ this._activeTabIdx = idx;
+ this.updateCurrentTab();
+ }
+
async createTab() {
const tab = await Tab.createNew(this.current.id, 'NEW_TAB' + (this.tabs.length + 1), 300, this.tabs.length);
this.tabs.push(tab);
- this.activeTab = (this.tabs.length - 1);
- this.currentTabId = tab.id;
+ this._activeTabIdx = (this.tabs.length - 1);
this.currentCardId = undefined;
+ this.activeCard = -1
}
async updateTab() {
- if (this.activeTab < 0) {
+ const tab = this.getActiveTab
+ if (!tab) {
return;
}
- bus.emit('update_tab', this.currentTabId)
- if (this.tabs[this.activeTab]) {
- return this.tabs[this.activeTab].update();
+ emit('update_tab', tab.id)
+ if (this.getActiveTab) {
+ return this.getActiveTab.update();
}
}
async removeTab() {
- if (!this.currentTabId) {
+ const tab = this.getActiveTab
+ if (!tab) {
return;
}
+ this.tabs.splice(this._activeTabIdx, 1);
+ this._activeTabIdx = this.tabs.length - 1;
+
this.currentCardId = undefined;
this.activeCard = undefined;
- bus.emit('remove_tab', this.currentTabId)
- return api.v1.dashboardTabServiceDeleteDashboardTab(this.currentTabId);
+ this.updateCurrentTab();
+
+ return api.v1.dashboardTabServiceDeleteDashboardTab(tab.id);
}
updateCurrentTab() {
- if (!this.tabs.length) {
- this.currentTabId = undefined;
+ const tab = this.getActiveTab
+ if (!tab) {
return;
}
- this.currentTabId = this.tabs[this.activeTab].id;
- console.log(`select tab id:${this.currentTabId}`);
- // this.activeCard = -1
- // this.currentCardId = undefined
-
- bus.emit('update_tab', this.currentTabId)
+ console.log(`select tab id:${tab.id}`);
+ emit('update_tab', tab.id)
}
// ---------------------------------
// cards
// ---------------------------------
onSelectedCard(id: number) {
- if (this.activeTab < 0) {
+ const tab = this.getActiveTab
+ if (!tab) {
return;
}
+
// console.log(`select card id:${id}`);
- for (const index in this.tabs[this.activeTab].cards) {
- const cardId = this.tabs[this.activeTab].cards[index].id;
- if (cardId === id) {
+ for (const index in tab.cards) {
+ const cardId = tab.cards[index].id;
+ if (cardId == id) {
this.activeCard = index as unknown as number;
this.currentCardId = id;
- this.tabs[this.activeTab].cards[index].active = true
+ tab.cards[index].active = true
} else {
// console.log(`disable id:${cardId}`)
- this.tabs[this.activeTab].cards[index].active = false
+ tab.cards[index].active = false
}
}
}
async createCard() {
- if (this.activeTab < 0 || !this.currentTabId) {
+ const tab = this.getActiveTab
+ if (!tab) {
return;
}
const card = await Card.createNew(
- 'new card' + this.tabs[this.activeTab].cards.length,
+ 'new card' + tab.cards.length,
randColor(),
- this.tabs[this.activeTab].columnWidth,
+ tab.columnWidth,
getSize(),
- this.tabs[this.activeTab].id,
- 10 * this.tabs[this.activeTab].cards.length || 0
+ tab.id,
+ 10 * tab.cards.length || 0
);
- this.tabs[this.activeTab].cards.push(card);
- this.activeCard = this.tabs[this.activeTab].cards.length - 1;
+ tab.cards.push(card);
+ this.activeCard = tab.cards.length - 1;
this.currentCardId = card.id;
- bus.emit('update_tab', this.currentTabId);
+ emit('update_tab', tab.id);
}
async updateCard() {
- if (this.activeTab < 0 || this.activeCard == undefined) {
+ const tab = this.getActiveTab
+ if (!tab) {
+ return;
+ }
+
+ if (this.activeCard == undefined) {
return;
}
// move to direct call
- // bus.emit('update_tab', this.currentTabId);
+ // emit('update_tab', this.currentTabId);
- return this.tabs[this.activeTab].cards[this.activeCard].update();
+ return tab.cards[this.activeCard].update();
}
async removeCard() {
- if (this.activeTab < 0 || !this.currentCardId) {
+ const tab = this.getActiveTab
+ if (!tab) {
+ return;
+ }
+
+ if (!this.currentCardId) {
return;
}
@@ -1311,9 +1436,9 @@ export class Core {
const {data} = await api.v1.dashboardCardServiceDeleteDashboardCard(this.currentCardId);
if (data) {
- for (const index: number in this.tabs[this.activeTab].cards) {
- if (this.tabs[this.activeTab].cards[index].id == this.currentCardId) {
- this.tabs[this.activeTab].cards.splice(index, 1);
+ for (const index: number in tab.cards) {
+ if (tab.cards[index].id == this.currentCardId) {
+ tab.cards.splice(index, 1);
}
}
@@ -1321,22 +1446,24 @@ export class Core {
this.activeCard = undefined;
}
- if (this.currentTabId) {
- bus.emit('update_tab', this.currentTabId);
- }
+ emit('update_tab', tab.id);
}
async importCard(card: ApiDashboardCard) {
- if (this.activeTab < 0 || !this.currentTabId) {
+ const tab = this.getActiveTab
+ if (!tab) {
return;
}
- card.dashboardTabId = this.currentTabId;
+
+ card.dashboardTabId = tab.id;
+ card.id = undefined
+
const {data} = await api.v1.dashboardCardServiceImportDashboardCard(card);
if (data) {
- this.tabs[this.activeTab].cards.push(new Card(data));
+ this.getActiveTab.cards.push(new Card(data));
}
- bus.emit('update_tab', this.currentTabId);
+ emit('update_tab', tab.id);
return data;
}
@@ -1345,28 +1472,38 @@ export class Core {
// Card item
// ---------------------------------
async createCardItem() {
- if (this.activeTab < 0 || this.activeCard == undefined) {
+ const tab = this.getActiveTab
+ if (!tab) {
return;
}
- const card = await this.tabs[this.activeTab].cards[this.activeCard];
+ if (this.activeCard == undefined) {
+ return;
+ }
+
+ const card = await tab.cards[this.activeCard];
if (!card) {
return;
}
- await this.tabs[this.activeTab].cards[this.activeCard].createCardItem();
+ await tab.cards[this.activeCard].createCardItem();
- // bus.emit('update_tab', this.currentTabId);
+ // emit('update_tab', this.currentTabId);
}
async removeCardItem(index: number) {
- if (this.activeTab < 0 || this.activeCard == undefined) {
+ const tab = this.getActiveTab
+ if (!tab) {
+ return;
+ }
+
+ if (this.activeCard == undefined) {
return;
}
- await this.tabs[this.activeTab].cards[this.activeCard].removeItem(index);
+ await tab.cards[this.activeCard].removeItem(index);
- // bus.emit('update_tab', this.currentTabId);
+ // emit('update_tab', this.currentTabId);
}
} // \Core
@@ -1436,6 +1573,12 @@ export function serializedObject(obj: any): string {
if (typeof value === 'function') {
return value.toString(); // Convert function to string
}
+ if(value instanceof Map) {
+ return {
+ dataType: 'Map',
+ value: Array.from(value.entries()), // or with spread: value: [...value]
+ };
+ }
return value;
});
}
@@ -1445,6 +1588,11 @@ export function parsedObject(str): any {
if (typeof value === 'string' && value.indexOf('function') === 0) {
return new Function('return ' + value)(); // Create a function using Function constructor
}
+ if(typeof value === 'object' && value !== null) {
+ if (value.dataType === 'Map') {
+ return new Map(value.value);
+ }
+ }
return value;
});
}
diff --git a/static_source/admin/src/views/Dashboard/editor/TabCard.vue b/static_source/admin/src/views/Dashboard/editor/TabCard.vue
index 283c83baa..11b7bbf76 100644
--- a/static_source/admin/src/views/Dashboard/editor/TabCard.vue
+++ b/static_source/admin/src/views/Dashboard/editor/TabCard.vue
@@ -1,25 +1,44 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
@@ -253,5 +320,10 @@ const onSnap = e => {
.movable {
position: absolute;
}
-
+.item-card {
+ position: relative;
+ overflow: hidden;
+ width: 100%;
+ height: 100%;
+}
diff --git a/static_source/admin/src/views/Dashboard/editor/ViewTab.vue b/static_source/admin/src/views/Dashboard/editor/ViewTab.vue
index de63aa84a..42884a041 100644
--- a/static_source/admin/src/views/Dashboard/editor/ViewTab.vue
+++ b/static_source/admin/src/views/Dashboard/editor/ViewTab.vue
@@ -27,18 +27,6 @@ const reload = debounce(() => {
reloadKey.value += 1
}, 100)
-watch(
- () => props.tab,
- (val?: Tab) => {
- if (!val) return;
- reload()
- },
- {
- deep: false,
- immediate: true
- }
-)
-
useBus({
name: 'update_tab',
callback: (tabId: number) => {
@@ -89,11 +77,12 @@ const cards = computed(() => props.tab?.cards2)
diff --git a/static_source/admin/src/views/Dashboard/editor/editor.vue b/static_source/admin/src/views/Dashboard/editor/editor.vue
index 2cfd8b32f..8cea6a760 100644
--- a/static_source/admin/src/views/Dashboard/editor/editor.vue
+++ b/static_source/admin/src/views/Dashboard/editor/editor.vue
@@ -1,7 +1,7 @@
-
+
+ class="ml-20px"
+ :lazy="true">
@@ -178,19 +173,39 @@ const elContainerHeight = computed(()=> {
-
+
+
+
+ {{ t('dashboard.addNewTab') }}
+
+
+
+
+ {{ t('dashboard.addNewTab') }}
+
+
+
+
+ {{ t('dashboard.addNewTab') }}
+
+
+
+
+ {{ t('dashboard.addNewCard') }}
+
+
@@ -239,6 +254,10 @@ const elContainerHeight = computed(()=> {
padding: 0 20px;
}
+.splitpanes.default-theme .splitpanes__pane.bottom-container {
+ background-color: var(--el-bg-color);
+}
+
p {
display: block;
margin-block-start: 1em;
@@ -293,4 +312,9 @@ html {
padding: 0 20px 0 0;
}
+.prevent-select {
+ -webkit-user-select: none; /* Safari */
+ -ms-user-select: none; /* IE 10 and IE 11 */
+ user-select: none; /* Standard syntax */
+}
diff --git a/static_source/admin/src/views/Dashboard/index.vue b/static_source/admin/src/views/Dashboard/index.vue
index cdb4b97d7..aa5960158 100644
--- a/static_source/admin/src/views/Dashboard/index.vue
+++ b/static_source/admin/src/views/Dashboard/index.vue
@@ -11,8 +11,10 @@ import {parseTime} from "@/utils";
import ContentWrap from "@/components/ContentWrap/src/ContentWrap.vue";
import { Dialog } from '@/components/Dialog'
import JsonViewer from "@/components/JsonViewer/JsonViewer.vue";
-import {Core} from "@/views/Dashboard/core";
+import {Core, parsedObject} from "@/views/Dashboard/core";
import {useCache} from "@/hooks/web/useCache";
+import JsonEditor from "@/components/JsonEditor/JsonEditor.vue";
+import {EChartsOption} from "echarts";
const {push} = useRouter()
const counter = ref(0);
@@ -187,9 +189,9 @@ const showDashboard = (row: ApiDashboard) => {
}
const dialogVisible = ref(false)
-const importValue = ref("")
+const importValue = ref(null)
-const importHandler = (val: string) => {
+const importHandler = (val: any) => {
if (importValue.value == val) {
return
}
@@ -199,10 +201,14 @@ const importHandler = (val: string) => {
const importDashboard = async () => {
let dashboard: ApiDashboard
try {
- dashboard = JSON.parse(importValue.value);
+ if (importValue.value?.json) {
+ dashboard = importValue.value.json as ApiDashboard;
+ } else if(importValue.value.text) {
+ dashboard = JSON.parse(importValue.value.text) as ApiDashboard;
+ }
} catch {
ElMessage({
- title: t('Success'),
+ title: t('Error'),
message: t('message.corruptedJsonFormat'),
type: 'error',
duration: 2000
@@ -266,7 +272,7 @@ const importDashboard = async () => {