Sitemap editor: Small fixes & Add duplicate element functionality (#3184)

This fixes:
- Scrollbar for sitemap tree not visible on narrow screens
- Details sheet not closed resulting in browser error
- Sitemap marked dirty when no icon defined on one of the sitemap
elements

This adds a sitemap element duplicate function. This will duplicate a
sitemap element with all of its sitemap children elements and can
drastically speeds up sitemap creation or editing. Before, the easiest
way was doing this in the code editor. With this change it can easily be
done in the treeview.

---------

Signed-off-by: Mark Herwege <mark.herwege@telenet.be>
pull/3192/head
Mark Herwege 2025-05-16 11:31:11 +02:00 committed by GitHub
parent 7133f9e79d
commit 1ae5fc6ec5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 28 additions and 10 deletions

View File

@ -10,7 +10,7 @@
<f7-list-input ref="icon" label="Icon" autocomplete="off" type="text" placeholder="temperature, firstfloor..." :value="widget.config.icon" <f7-list-input ref="icon" label="Icon" autocomplete="off" type="text" placeholder="temperature, firstfloor..." :value="widget.config.icon"
@input="updateParameter('icon', $event)" clear-button> @input="updateParameter('icon', $event)" clear-button>
<div slot="root-end" style="margin-left: calc(35% + 8px)"> <div slot="root-end" style="margin-left: calc(35% + 8px)">
<oh-icon :icon="widget.config.icon" height="32" width="32" /> <oh-icon :icon="widget.config.icon || ''" height="32" width="32" />
</div> </div>
</f7-list-input> </f7-list-input>
<f7-list-item title="Static icon"> <f7-list-item title="Static icon">
@ -82,6 +82,9 @@
<f7-button color="blue" @click="$emit('moveup', widget)" icon-f7="chevron_up" /> <f7-button color="blue" @click="$emit('moveup', widget)" icon-f7="chevron_up" />
<f7-button color="blue" @click="$emit('movedown', widget)" icon-f7="chevron_down" /> <f7-button color="blue" @click="$emit('movedown', widget)" icon-f7="chevron_down" />
</f7-segmented> </f7-segmented>
<f7-button v-if="widget.component !== 'Sitemap'" color="blue" @click="$emit('duplicate', widget)">
Duplicate
</f7-button>
<f7-button v-if="widget.component !== 'Sitemap'" color="red" @click="$emit('remove', widget)"> <f7-button v-if="widget.component !== 'Sitemap'" color="red" @click="$emit('remove', widget)">
Remove Remove
</f7-button> </f7-button>
@ -149,7 +152,6 @@ export default {
}, },
mounted () { mounted () {
if (!this.widget) return if (!this.widget) return
if (!this.widget.config.icon) this.$set(this.widget.config, 'icon', '')
const iconControl = this.$refs.icon const iconControl = this.$refs.icon
if (!iconControl || !iconControl.$el) return if (!iconControl || !iconControl.$el) return
const inputElement = this.$$(iconControl.$el).find('input') const inputElement = this.$$(iconControl.$el).find('input')

View File

@ -44,7 +44,7 @@
</f7-col> </f7-col>
<f7-col class="details-pane"> <f7-col class="details-pane">
<f7-block v-if="selectedWidget" no-gap> <f7-block v-if="selectedWidget" no-gap>
<widget-details :widget="selectedWidget" :createMode="createMode" @remove="removeWidget" @movedown="moveWidgetDown" @moveup="moveWidgetUp" /> <widget-details :widget="selectedWidget" :createMode="createMode" @duplicate="duplicateWidget" @remove="removeWidget" @movedown="moveWidgetDown" @moveup="moveWidgetUp" />
</f7-block> </f7-block>
<f7-block v-else> <f7-block v-else>
<div class="padding text-align-center"> <div class="padding text-align-center">
@ -134,7 +134,7 @@
<f7-icon ios="f7:plus" md="material:add" aurora="f7:plus" /> <f7-icon ios="f7:plus" md="material:add" aurora="f7:plus" />
<f7-icon ios="f7:multiply" md="material:close" aurora="f7:multiply" /> <f7-icon ios="f7:multiply" md="material:close" aurora="f7:multiply" />
</f7-fab> </f7-fab>
<f7-sheet v-if="currentTab === 'tree'" class="sitemap-details-sheet" :backdrop="false" :close-on-escape="true" :opened="detailsOpened" @sheet:closed="detailsOpened = false"> <f7-sheet v-if="currentTab === 'tree'" ref="detailsSheet" class="sitemap-details-sheet" :backdrop="false" :close-on-escape="true" :opened="detailsOpened" @sheet:closed="detailsOpened = false">
<f7-page> <f7-page>
<f7-toolbar tabbar bottom scrollable> <f7-toolbar tabbar bottom scrollable>
<div class="left"> <div class="left">
@ -163,7 +163,7 @@
</f7-link> </f7-link>
</f7-toolbar> </f7-toolbar>
<f7-block style="margin-bottom: 6rem" v-if="selectedWidget && detailsTab === 'widget'"> <f7-block style="margin-bottom: 6rem" v-if="selectedWidget && detailsTab === 'widget'">
<widget-details :widget="selectedWidget" :createMode="createMode" @remove="removeWidget" @movedown="moveWidgetDown" @moveup="moveWidgetUp" /> <widget-details :widget="selectedWidget" :createMode="createMode" @duplicate="duplicateWidget" @remove="removeWidget" @movedown="moveWidgetDown" @moveup="moveWidgetUp" />
</f7-block> </f7-block>
<f7-block style="margin-bottom: 6rem" v-if="selectedWidget && detailsTab === 'visibility'"> <f7-block style="margin-bottom: 6rem" v-if="selectedWidget && detailsTab === 'visibility'">
<attribute-details :widget="selectedWidget" attribute="visibility" placeholder="item_name operator value" /> <attribute-details :widget="selectedWidget" attribute="visibility" placeholder="item_name operator value" />
@ -198,17 +198,18 @@
<style lang="stylus"> <style lang="stylus">
.sitemap-editor-tabs .sitemap-editor-tabs
height calc(100%) height 100%
overflow hidden overflow hidden
.tab .tab
height 100% height 100%
.design .design
--f7-grid-gap 0px --f7-grid-gap 0px
height calc(100% - var(--f7-toolbar-height)) overflow auto
.sitemap-tree-wrapper .sitemap-tree-wrapper
padding 0 padding 0
margin-bottom 0 margin-bottom 0
height calc(100% - var(--f7-toolbar-height))
.col .col
width 100% /* manually set column width because of https://github.com/openhab/openhab-webui/issues/2574 */ width 100% /* manually set column width because of https://github.com/openhab/openhab-webui/issues/2574 */
.sitemap-tree .sitemap-tree
@ -246,7 +247,6 @@
@media (min-width: 768px) @media (min-width: 768px)
.sitemap-tree-wrapper .sitemap-tree-wrapper
height 100%
.row .row
height 100% height 100%
.col .col
@ -272,19 +272,24 @@
@media (max-width: 767px) @media (max-width: 767px)
.details-pane .details-pane
display none display none
.sitemap-tree-wrapper
margin-top 0 !important
.sitemap-tree-wrapper.sheet-opened .sitemap-tree-wrapper.sheet-opened
margin-bottom var(--f7-sheet-height) margin-bottom calc(var(--f7-sheet-height) - var(--f7-toolbar-height))
height auto
.details-sheet .details-sheet
height calc(1.4*var(--f7-sheet-height)) height calc(1.4*var(--f7-sheet-height))
</style> </style>
<script> <script>
import cloneDeep from 'lodash/cloneDeep'
import SitemapCode from '@/components/pagedesigner/sitemap/sitemap-code.vue' import SitemapCode from '@/components/pagedesigner/sitemap/sitemap-code.vue'
import WidgetDetails from '@/components/pagedesigner/sitemap/widget-details.vue' import WidgetDetails from '@/components/pagedesigner/sitemap/widget-details.vue'
import AttributeDetails from '@/components/pagedesigner/sitemap/attribute-details.vue' import AttributeDetails from '@/components/pagedesigner/sitemap/attribute-details.vue'
import SitemapTreeviewItem from '@/components/pagedesigner/sitemap/treeview-item.vue' import SitemapTreeviewItem from '@/components/pagedesigner/sitemap/treeview-item.vue'
import SitemapMixin from '@/components/pagedesigner/sitemap/sitemap-mixin' import SitemapMixin from '@/components/pagedesigner/sitemap/sitemap-mixin'
import DirtyMixin from '../../dirty-mixin' import DirtyMixin from '@/pages/settings/dirty-mixin'
export default { export default {
mixins: [DirtyMixin, SitemapMixin], mixins: [DirtyMixin, SitemapMixin],
@ -349,6 +354,11 @@ export default {
} }
}, },
deep: true deep: true
},
currentTab (newTab, oldTab) {
if (oldTab === 'tree' && this.$refs.detailsSheet) {
this.$refs.detailsSheet.close()
}
} }
}, },
methods: { methods: {
@ -721,6 +731,12 @@ export default {
}, },
stopEventSource () { stopEventSource () {
},
duplicateWidget () {
const duplicate = cloneDeep(this.selectedWidget)
const index = this.selectedWidgetParent.slots.widgets.indexOf(this.selectedWidget) + 1
this.selectedWidgetParent.slots.widgets.splice(index, 0, duplicate)
this.$set(this, 'selectedWidget', this.selectedWidgetParent.slots.widgets[index])
}, },
removeWidget () { removeWidget () {
this.selectedWidgetParent.slots.widgets.splice(this.selectedWidgetParent.slots.widgets.indexOf(this.selectedWidget), 1) this.selectedWidgetParent.slots.widgets.splice(this.selectedWidgetParent.slots.widgets.indexOf(this.selectedWidget), 1)