enhance(client): improve widgets component
This commit is contained in:
		
							parent
							
								
									a5648fb07f
								
							
						
					
					
						commit
						d8264b11e2
					
				
					 1 changed files with 70 additions and 58 deletions
				
			
		|  | @ -4,7 +4,7 @@ | |||
| 		<header> | ||||
| 			<MkSelect v-model="widgetAdderSelected" style="margin-bottom: var(--margin)" class="mk-widget-select"> | ||||
| 				<template #label>{{ $ts.selectWidget }}</template> | ||||
| 				<option v-for="widget in widgetDefs" :key="widget" :value="widget">{{ $t(`_widgets.${widget}`) }}</option> | ||||
| 				<option v-for="widget in widgetDefs" :key="widget" :value="widget">{{ i18n.t(`_widgets.${widget}`) }}</option> | ||||
| 			</MkSelect> | ||||
| 			<MkButton inline primary class="mk-widget-add" @click="addWidget"><i class="fas fa-plus"></i> {{ $ts.add }}</MkButton> | ||||
| 			<MkButton inline @click="$emit('exit')">{{ $ts.close }}</MkButton> | ||||
|  | @ -26,79 +26,91 @@ | |||
| 			</template> | ||||
| 		</XDraggable> | ||||
| 	</template> | ||||
| 	<component :is="`mkw-${widget.name}`" v-for="widget in widgets" v-else :key="widget.id" class="widget" :widget="widget" @updateProps="updateWidget(widget.id, $event)"/> | ||||
| 	<component :is="`mkw-${widget.name}`" v-for="widget in widgets" v-else :key="widget.id" :ref="el => widgetRefs[widget.id] = el" class="widget" :widget="widget" @updateProps="updateWidget(widget.id, $event)" @contextmenu.stop="onContextmenu(widget, $event)"/> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, defineAsyncComponent, reactive, ref, computed } from 'vue'; | ||||
| <script lang="ts" setup> | ||||
| import { defineAsyncComponent, reactive, ref, computed } from 'vue'; | ||||
| import { v4 as uuid } from 'uuid'; | ||||
| import MkSelect from '@/components/form/select.vue'; | ||||
| import MkButton from '@/components/ui/button.vue'; | ||||
| import { widgets as widgetDefs } from '@/widgets'; | ||||
| import * as os from '@/os'; | ||||
| import { i18n } from '@/i18n'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		XDraggable: defineAsyncComponent(() => import('vuedraggable')), | ||||
| 		MkSelect, | ||||
| 		MkButton, | ||||
| 	}, | ||||
| const XDraggable = defineAsyncComponent(() => import('vuedraggable')); | ||||
| 
 | ||||
| 	props: { | ||||
| 		widgets: { | ||||
| 			type: Array, | ||||
| 			required: true, | ||||
| 		}, | ||||
| 		edit: { | ||||
| 			type: Boolean, | ||||
| 			required: true, | ||||
| 		}, | ||||
| 	}, | ||||
| type Widget = { | ||||
| 	name: string; | ||||
| 	id: string; | ||||
| 	data: Record<string, any>; | ||||
| }; | ||||
| 
 | ||||
| 	emits: ['updateWidgets', 'addWidget', 'removeWidget', 'updateWidget', 'exit'], | ||||
| const props = defineProps<{ | ||||
| 	widgets: Widget[]; | ||||
| 	edit: boolean; | ||||
| }>(); | ||||
| 
 | ||||
| 	setup(props, context) { | ||||
| 		const widgetRefs = reactive({}); | ||||
| 		const configWidget = (id: string) => { | ||||
| 			widgetRefs[id].configure(); | ||||
| 		}; | ||||
| 		const widgetAdderSelected = ref(null); | ||||
| 		const addWidget = () => { | ||||
| 			if (widgetAdderSelected.value == null) return; | ||||
| const emit = defineEmits<{ | ||||
| 	(ev: 'updateWidgets', widgets: Widget[]): void; | ||||
| 	(ev: 'addWidget', widget: Widget): void; | ||||
| 	(ev: 'removeWidget', widget: Widget): void; | ||||
| 	(ev: 'updateWidget', widget: Partial<Widget>): void; | ||||
| 	(ev: 'exit'): void; | ||||
| }>(); | ||||
| 
 | ||||
| 			context.emit('addWidget', { | ||||
| 				name: widgetAdderSelected.value, | ||||
| 				id: uuid(), | ||||
| 				data: {}, | ||||
| 			}); | ||||
| const widgetRefs = {}; | ||||
| const configWidget = (id: string) => { | ||||
| 	widgetRefs[id].configure(); | ||||
| }; | ||||
| const widgetAdderSelected = ref(null); | ||||
| const addWidget = () => { | ||||
| 	if (widgetAdderSelected.value == null) return; | ||||
| 
 | ||||
| 			widgetAdderSelected.value = null; | ||||
| 		}; | ||||
| 		const removeWidget = (widget) => { | ||||
| 			context.emit('removeWidget', widget); | ||||
| 		}; | ||||
| 		const updateWidget = (id, data) => { | ||||
| 			context.emit('updateWidget', { id, data }); | ||||
| 		}; | ||||
| 		const widgets_ = computed({ | ||||
| 			get: () => props.widgets, | ||||
| 			set: (value) => { | ||||
| 				context.emit('updateWidgets', value); | ||||
| 			}, | ||||
| 		}); | ||||
| 	emit('addWidget', { | ||||
| 		name: widgetAdderSelected.value, | ||||
| 		id: uuid(), | ||||
| 		data: {}, | ||||
| 	}); | ||||
| 
 | ||||
| 		return { | ||||
| 			widgetRefs, | ||||
| 			configWidget, | ||||
| 			widgetAdderSelected, | ||||
| 			widgetDefs, | ||||
| 			addWidget, | ||||
| 			removeWidget, | ||||
| 			updateWidget, | ||||
| 			widgets_, | ||||
| 		}; | ||||
| 	widgetAdderSelected.value = null; | ||||
| }; | ||||
| const removeWidget = (widget) => { | ||||
| 	emit('removeWidget', widget); | ||||
| }; | ||||
| const updateWidget = (id, data) => { | ||||
| 	emit('updateWidget', { id, data }); | ||||
| }; | ||||
| const widgets_ = computed({ | ||||
| 	get: () => props.widgets, | ||||
| 	set: (value) => { | ||||
| 		emit('updateWidgets', value); | ||||
| 	}, | ||||
| }); | ||||
| 
 | ||||
| function onContextmenu(widget: Widget, ev: MouseEvent) { | ||||
| 	const isLink = (el: HTMLElement) => { | ||||
| 		if (el.tagName === 'A') return true; | ||||
| 		if (el.parentElement) { | ||||
| 			return isLink(el.parentElement); | ||||
| 		} | ||||
| 	}; | ||||
| 	if (isLink(ev.target)) return; | ||||
| 	if (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO', 'CANVAS'].includes(ev.target.tagName) || ev.target.attributes['contenteditable']) return; | ||||
| 	if (window.getSelection()?.toString() !== '') return; | ||||
| 
 | ||||
| 	os.contextMenu([{ | ||||
| 		type: 'label', | ||||
| 		text: i18n.t(`_widgets.${widget.name}`), | ||||
| 	}, { | ||||
| 		icon: 'fas fa-cog', | ||||
| 		text: i18n.ts.settings, | ||||
| 		action: () => { | ||||
| 			configWidget(widget.id); | ||||
| 		}, | ||||
| 	}], ev); | ||||
| } | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue