Last active
July 9, 2021 19:28
-
-
Save taxilian/f4747451671285c4d836e7dab00605b3 to your computer and use it in GitHub Desktop.
Dialog abstraction example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type Vue from 'vue'; | |
type HSGenericDialogConstructor<PropNames extends string, RetType> = | |
new(...args: any[]) => HSGenericDialog<PropNames, RetType>; | |
export interface HSGenericDialog<PropNames extends string = string, RetType = any> { | |
submit(...args: any[]): RetType; | |
settableProperties: PropNames[] | readonly PropNames[]; | |
} | |
type DialogReturnType<T extends HSGenericDialogConstructor<any, any>> = | |
T extends HSGenericDialogConstructor<any, infer R> ? R : never; | |
type DialogPropertiesList<T extends HSGenericDialogConstructor<any, any>> = | |
T extends HSGenericDialogConstructor<infer R, any> ? R : never; | |
type DialogPropertiesType<T extends HSGenericDialogConstructor<any, any>> = Pick<InstanceType<T>, DialogPropertiesList<T>>; | |
/** | |
* This relies on vuetify-dialog to work | |
*/ | |
export async function showDialog<DialogType extends HSGenericDialogConstructor<any, any>>(v: Vue, dlg: DialogType, props: DialogPropertiesType<DialogType>) { | |
type RType = DialogReturnType<DialogType>; | |
const dialogDisplay = await v.$dialog.show(dlg, props); | |
const result: RType | null = await dialogDisplay.wait(); | |
return result; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script lang="ts"> | |
import {showDialog} from './dialogMgr'; | |
@Component() | |
export default class MyOtherComponent extends Vue { | |
markdown = '(some loaded markdown here)'; | |
async openDialog() { | |
const dlgModule = await import(/* webpackChunkName: "common_markdownEditor" */ './MarkdownRichEditDialog.vue'); | |
const dlg = dlgModule.default; | |
const result = await showDialog(this, dlg, { | |
title: "Edit markdown", | |
markdown: this.markdown, | |
}); | |
if (result) { | |
this.markdown = result; | |
} | |
} | |
} | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<v-card class="mx-auto"> | |
<v-card-title v-text="title"></v-card-title> | |
<v-card-text cols="8" class="py-5 px-7"> | |
<vue-editor id="mdEditor" v-model="markdown" :editorToolbar="simpleToolbar"></vue-editor> | |
</v-card-text> | |
<v-card-actions class="justify-space-around pb-6"> | |
<v-btn | |
class="col-5 mx-1" | |
color="primary" | |
@click="accept" | |
> | |
<v-icon left>$vuetify.icons.fasCheckCircle</v-icon> | |
<i18next path="shared:accept" /> | |
</v-btn> | |
<v-btn | |
class="col-5 mx-1" | |
color="secondary" | |
@click="cancel" | |
> | |
<v-icon left>$vuetify.icons.fasTimesCircle</v-icon> | |
<i18next path="shared:cancel" /> | |
</v-btn> | |
</v-card-actions> | |
</v-card> | |
</template> | |
<script lang="ts"> | |
import { HSGenericDialog } from './dialogMgr'; | |
import Vue from 'vue'; | |
import {Component, Prop, Emit} from 'vue-property-decorator'; | |
import { VueEditor } from "vue2-editor"; | |
@Component({ | |
components: { | |
VueEditor, | |
}, | |
}) | |
export default class MarkdownRichEditDialog extends Vue implements HSGenericDialog { | |
@Prop({required: true}) | |
title!: string; | |
@Prop({required: true}) | |
markdown!: string; | |
readonly settableProperties = <const>['title', 'markdown']; | |
simpleToolbar = [ | |
[{header: [false, 2, 3, 4]}], | |
["bold", "italic", "underline", "strike"], | |
['blockquote', {header: 1}, {header: 2}], | |
[{list: 'ordered'}, {list: 'bullet'}, {indent: '-1'}, {indent: '+1'}], | |
['link', 'image'], | |
['clean'], | |
]; | |
cancel() { | |
this.submit(); | |
} | |
accept() { | |
this.submit(this.markdown); | |
} | |
@Emit('submit') | |
submit(v?: string) { return v; } | |
} | |
</script> | |
<style lang="scss" scoped> | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment