mirror of
https://github.com/directus/directus.git
synced 2026-02-02 02:45:01 -05:00
Add edit existing
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
<template #activator>
|
||||
<v-input
|
||||
:disabled="disabled"
|
||||
:placeholder="$t('interfaces.color.placeholder')"
|
||||
:placeholder="$t('interfaces.select-color.placeholder')"
|
||||
v-model="hex"
|
||||
:pattern="/#([a-f\d]{2}){3}/i"
|
||||
class="color-input"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</template>
|
||||
|
||||
<template #actions>
|
||||
<v-button v-if="editMode" rounded icon outlined :to="`/insights/${currentDashboard.id}/panel/+`">
|
||||
<v-button v-if="editMode" rounded icon outlined :to="`/insights/${currentDashboard.id}/+`">
|
||||
<v-icon name="add" />
|
||||
</v-button>
|
||||
|
||||
@@ -22,18 +22,34 @@
|
||||
</template>
|
||||
|
||||
<div class="workspace" :class="{ editing: editMode }">
|
||||
<!-- <div class="dummy" /> -->
|
||||
<router-link
|
||||
v-for="panel in panels"
|
||||
:to="`/insights/${currentDashboard.id}/${panel.id || panel.$tempID}`"
|
||||
:key="panel.id || panel.$tempID"
|
||||
>
|
||||
{{ panel.id || panel.$tempID }}
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
<router-view name="detail" :dashboard-key="primaryKey" />
|
||||
<router-view
|
||||
name="detail"
|
||||
:dashboard-key="primaryKey"
|
||||
:panel="panels.find((panel) => panel.id === panelKey || panel.$tempID === panelKey)"
|
||||
@save="stagePanelEdits"
|
||||
@cancel="$router.push(`/insights/${primaryKey}`)"
|
||||
/>
|
||||
</private-view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import InsightsNavigation from '../components/navigation.vue';
|
||||
import { defineComponent, computed, ref } from '@vue/composition-api';
|
||||
import { useInsightsStore } from '@/stores';
|
||||
import InsightsNotFound from './not-found.vue';
|
||||
import { Panel } from '@/types';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { merge } from 'lodash';
|
||||
import router from '@/router';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'InsightsDashboard',
|
||||
@@ -43,6 +59,10 @@ export default defineComponent({
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
panelKey: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const editMode = ref(false);
|
||||
@@ -52,13 +72,60 @@ export default defineComponent({
|
||||
insightsStore.state.dashboards.find((dashboard) => dashboard.id === props.primaryKey)
|
||||
);
|
||||
|
||||
const stagedPanels = ref([]);
|
||||
const stagedPanels = ref<Partial<Panel & { $tempID?: string }>[]>([]);
|
||||
|
||||
const panels = computed(() => {
|
||||
return currentDashboard.value?.panels || [];
|
||||
const savedPanels = currentDashboard.value?.panels || [];
|
||||
|
||||
return [
|
||||
...savedPanels.map((panel) => {
|
||||
const updates = stagedPanels.value.find((updatedPanel) => updatedPanel.id === panel.id);
|
||||
|
||||
if (updates) {
|
||||
return merge({}, panel, updates);
|
||||
}
|
||||
|
||||
return panel;
|
||||
}),
|
||||
...stagedPanels.value.filter((panel) => '$tempID' in panel),
|
||||
];
|
||||
});
|
||||
|
||||
return { currentDashboard, editMode, panels };
|
||||
return { currentDashboard, editMode, panels, stagePanelEdits, stagedPanels };
|
||||
|
||||
function stagePanelEdits(edits: Partial<Panel>) {
|
||||
if (props.panelKey === '+') {
|
||||
stagedPanels.value = [
|
||||
...stagedPanels.value,
|
||||
{
|
||||
$tempID: nanoid(),
|
||||
...edits,
|
||||
},
|
||||
];
|
||||
} else {
|
||||
if (stagedPanels.value.some((panel) => panel.id === props.panelKey || panel.$tempID === props.panelKey)) {
|
||||
stagedPanels.value = stagedPanels.value.map((panel) => {
|
||||
if (panel.id === props.panelKey) {
|
||||
return {
|
||||
id: props.panelKey,
|
||||
...edits,
|
||||
};
|
||||
}
|
||||
|
||||
if (panel.$tempID === props.panelKey) {
|
||||
return {
|
||||
$tempID: props.panelKey,
|
||||
...edits,
|
||||
};
|
||||
}
|
||||
|
||||
return panel;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
router.push(`/insights/${props.primaryKey}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
<template>
|
||||
<v-drawer active :title="values.name || $t('panel')">
|
||||
<v-drawer active :title="(panel && panel.name) || $t('panel')" @cancel="$emit('cancel')">
|
||||
<template #actions>
|
||||
<v-button :disabled="!edits.type" @click="emitSave" icon rounded v-tooltip.bottom="$t('done')">
|
||||
<v-icon name="check" />
|
||||
</v-button>
|
||||
</template>
|
||||
|
||||
<div class="content">
|
||||
<p class="type-label panel-type-label">{{ $t('type') }}</p>
|
||||
|
||||
<v-fancy-select class="select" :items="selectItems" v-model="values.type" />
|
||||
<v-fancy-select class="select" :items="selectItems" v-model="edits.type" />
|
||||
|
||||
<template v-if="values.type && selectedPanel">
|
||||
<template v-if="edits.type && selectedPanel">
|
||||
<v-notice v-if="!selectedPanel.options || selectedPanel.options.length === 0">
|
||||
{{ $t('no_options_available') }}
|
||||
</v-notice>
|
||||
@@ -14,10 +20,10 @@
|
||||
v-else-if="Array.isArray(selectedPanel.options)"
|
||||
:fields="selectedPanel.options"
|
||||
primary-key="+"
|
||||
v-model="values.options"
|
||||
v-model="edits.options"
|
||||
/>
|
||||
|
||||
<component v-model="values.options" :collection="collection" :is="`panel-options-${selectedPanel.id}`" v-else />
|
||||
<component v-model="edits.options" :collection="collection" :is="`panel-options-${selectedPanel.id}`" v-else />
|
||||
</template>
|
||||
|
||||
<v-divider />
|
||||
@@ -25,22 +31,22 @@
|
||||
<div class="form-grid">
|
||||
<div class="field half-left">
|
||||
<p class="type-label">{{ $t('show_header') }}</p>
|
||||
<v-checkbox block v-model="values.show_header" :label="$t('enabled')" />
|
||||
<v-checkbox block v-model="edits.show_header" :label="$t('enabled')" />
|
||||
</div>
|
||||
|
||||
<div class="field half-right">
|
||||
<p class="type-label">{{ $t('name') }}</p>
|
||||
<v-input v-model="values.name" :disabled="values.show_header !== true" />
|
||||
<v-input v-model="edits.name" :disabled="edits.show_header !== true" />
|
||||
</div>
|
||||
|
||||
<div class="field half-left">
|
||||
<p class="type-label">{{ $t('icon') }}</p>
|
||||
<interface-select-icon v-model="values.icon" :disabled="values.show_header !== true" />
|
||||
<interface-select-icon v-model="edits.icon" :disabled="edits.show_header !== true" />
|
||||
</div>
|
||||
|
||||
<div class="field half-right">
|
||||
<p class="type-label">{{ $t('color') }}</p>
|
||||
<interface-select-color v-model="values.color" :disabled="values.show_header !== true" width="half" />
|
||||
<interface-select-color v-model="edits.color" :disabled="edits.show_header !== true" width="half" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -48,8 +54,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, ref } from '@vue/composition-api';
|
||||
import { useInsightsStore } from '@/stores';
|
||||
import { computed, defineComponent, reactive, watch, PropType } from '@vue/composition-api';
|
||||
import { getPanels } from '@/panels';
|
||||
import { FancySelectItem } from '@/components/v-fancy-select/types';
|
||||
import { Panel } from '@/types';
|
||||
@@ -57,31 +62,23 @@ import { Panel } from '@/types';
|
||||
export default defineComponent({
|
||||
name: 'PanelConfiguration',
|
||||
props: {
|
||||
primaryKey: {
|
||||
type: String,
|
||||
default: '+',
|
||||
},
|
||||
dashboardKey: {
|
||||
type: String,
|
||||
panel: {
|
||||
type: Object as PropType<Partial<Panel>>,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
setup(props, { emit }) {
|
||||
const { panels } = getPanels();
|
||||
|
||||
const insightsStore = useInsightsStore();
|
||||
|
||||
const existing = computed(() =>
|
||||
insightsStore.state.dashboards
|
||||
.find((dashboard) => dashboard.id === props.dashboardKey)!
|
||||
.panels.find((panel) => panel.id === props.primaryKey)
|
||||
);
|
||||
|
||||
const edits = ref<Partial<Panel>>({});
|
||||
|
||||
const values = computed<Partial<Panel>>(() => {
|
||||
if (existing.value) return { ...existing.value, ...edits.value };
|
||||
return edits.value;
|
||||
const edits = reactive<Partial<Panel>>({
|
||||
show_header: false,
|
||||
type: undefined,
|
||||
name: undefined,
|
||||
icon: undefined,
|
||||
color: undefined,
|
||||
width: undefined,
|
||||
height: undefined,
|
||||
...(props.panel || {}),
|
||||
});
|
||||
|
||||
const selectItems = computed<FancySelectItem[]>(() => {
|
||||
@@ -98,10 +95,30 @@ export default defineComponent({
|
||||
});
|
||||
|
||||
const selectedPanel = computed(() => {
|
||||
return panels.value.find((panel) => panel.id === values.value.type);
|
||||
return panels.value.find((panel) => panel.id === edits.type);
|
||||
});
|
||||
|
||||
return { existing, values, selectItems, selectedPanel };
|
||||
watch(selectedPanel, (newPanel) => {
|
||||
if (newPanel) {
|
||||
edits.width = newPanel.minWidth;
|
||||
edits.height = newPanel.minHeight;
|
||||
} else {
|
||||
edits.width = undefined;
|
||||
edits.height = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
selectItems,
|
||||
selectedPanel,
|
||||
close,
|
||||
emitSave,
|
||||
edits,
|
||||
};
|
||||
|
||||
function emitSave() {
|
||||
emit('save', edits);
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -121,14 +138,3 @@ export default defineComponent({
|
||||
margin: 48px 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--
|
||||
|
||||
type
|
||||
options
|
||||
--
|
||||
toggle name
|
||||
icon color
|
||||
note
|
||||
|
||||
-->
|
||||
|
||||
@@ -10,6 +10,7 @@ export type Dashboard = {
|
||||
export type Panel = {
|
||||
id: string;
|
||||
dashboard: string;
|
||||
show_header: boolean;
|
||||
name: string;
|
||||
icon: string;
|
||||
color: string;
|
||||
|
||||
Reference in New Issue
Block a user