Skip to content

Commit

Permalink
feat: rework modals mechanism
Browse files Browse the repository at this point in the history
Display only one modal component
Introduce ModalDefinition

Tidy components and stuff

Relative to #9
  • Loading branch information
ojacquemart committed Oct 10, 2021
1 parent f3e192d commit 90574c0
Show file tree
Hide file tree
Showing 34 changed files with 330 additions and 286 deletions.
7 changes: 5 additions & 2 deletions samples/ui/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<Suspense>
<router-view></router-view>
</Suspense>
<rtdb-modal v-if="$store.getters['modals/hasSelection']"></rtdb-modal>
</div>
<rtdb-footer></rtdb-footer>
</div>
Expand All @@ -13,13 +14,15 @@
<script lang="ts">
import { defineComponent } from 'vue'
import Header from '@/components/Header.vue'
import Footer from '@/components/Footer.vue'
import Header from '@/components/shared/Header.vue'
import Footer from '@/components/shared/Footer.vue'
import DynamicModal from '@/components/modal/DynamicModal.vue'
export default defineComponent({
name: 'App',
components: {
'rtdb-header': Header,
'rtdb-modal': DynamicModal,
'rtdb-footer': Footer,
},
})
Expand Down
69 changes: 0 additions & 69 deletions samples/ui/src/components/ModalConfirmDelete.vue

This file was deleted.

68 changes: 0 additions & 68 deletions samples/ui/src/components/ModalNewText.vue

This file was deleted.

24 changes: 0 additions & 24 deletions samples/ui/src/components/NewCollection.vue

This file was deleted.

26 changes: 0 additions & 26 deletions samples/ui/src/components/Settings.vue

This file was deleted.

27 changes: 0 additions & 27 deletions samples/ui/src/components/SocketNewEntry.vue

This file was deleted.

68 changes: 68 additions & 0 deletions samples/ui/src/components/modal/DynamicModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<template>
<rtdb-modal :modal-id="modal.id">
<template v-slot:header>
{{ $t(modal.title) }}
</template>
<template v-slot:body>
<div v-for="(input, index) of modal.controls"
:class="{'mb-4': index < modal.controls.length - 1}">
<p v-if="input.label" v-html="input.label"></p>
<p v-else v-html="$t(input.i18nLabel)"></p>
<input v-if="input.type === 'text'" v-model="input.value"
class="relative outline-none rounded py-3 px-3 w-full bg-primary shadow text-sm text-white placeholder-gray-400 focus:ring-1 focus:border-gray-300"
type="text"/>
<textarea v-if="input.type === 'textarea'"
v-model="input.value"
class="relative outline-none rounded py-3 px-3 w-full h-60 bg-primary shadow text-sm text-white placeholder-gray-400 focus:ring-1 focus:border-gray-300"/>
</div>
</template>
<template v-slot:buttons>
<button :disabled="!modal.validate()"
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-primary-light text-base font-medium text-white focus:outline-none focus:ring-2 focus:ring-offset-0 focus:ring-gray-500 disabled:opacity-50 sm:ml-3 sm:w-auto sm:text-sm"
type="button" @click="save">
{{ $t('common.ok') }}
</button>
<button ref="cancelButtonRef"
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-gray-100 text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-0 focus:ring-gray-300 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
type="button" @click="$store.commit('modals/close', modal.id)">
{{ $t('common.cancel') }}
</button>
</template>
</rtdb-modal>
</template>

<script lang="ts">
import { defineComponent, reactive } from 'vue'
import { useI18n } from 'vue-i18n'
import { useStore } from 'vuex'
import Modal from '@/components/modal/Modal.vue'
import { ModalDefinitionFactory } from '@/components/modal/ModalDefinitionFactory'
export default defineComponent({
components: {
'rtdb-modal': Modal,
},
props: [
'modal',
],
setup: () => {
const store = useStore()
const i18n = useI18n()
const id = store.getters['modals/id']
const modal = ModalDefinitionFactory.get({store, i18n: {t: i18n.t}, id})
if (!modal) {
throw Error('Modal definition not found: ' + id)
}
return {
modal: reactive(modal),
save: () => {
modal.save(store)
},
}
},
})
</script>
36 changes: 36 additions & 0 deletions samples/ui/src/components/modal/FormControl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Ref } from 'vue'
import exp from 'constants'

export type FormControlTye = 'text' | 'textarea'

export interface FormControl {
key: string
label?: string
// i18n key label
i18nLabel?: string
type: FormControlTye
value?: Ref<string | null>
required?: boolean
}

export class FormControlValidators {

static requiredNotEmpty(controls: FormControl[]) {
return this.required(controls)
.filter((it: string) => it.length > 0)
.length > 0
}

static equalsFirstRequired(controls: FormControl[], expected: string) {
const first = this.required(controls)[0]

return first === expected
}

private static required(controls: FormControl[]) {
return controls
.filter((it: FormControl) => it.required)
.map((it: FormControl) => (it.value || '') as string)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
leave-from="opacity-100 translate-y-0 sm:scale-100"
leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
<div
class="inline-block align-bottom bg-primary rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
class="inline-block align-bottom bg-primary rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-primary px-4 pt-5 pb-4 sm:p-6 sm:pb-4 bg-primary">
<div class="sm:flex sm:items-start flex-col">
<div class="mt-3 text-center sm:mt-0 sm:text-left w-full">
Expand Down
32 changes: 32 additions & 0 deletions samples/ui/src/components/modal/ModalDefinition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Store } from 'vuex'

import { FormControl, FormControlValidators } from '@/components/modal/FormControl'

export class ModalDefinition {
id: string
title: string
dispatch: string
validator: (controls: FormControl[]) => boolean
controls: FormControl[]

constructor(
id: string, title: string, dispatch: string, controls: FormControl[],
validator?: (controls: FormControl[]) => boolean,
) {
this.id = id
this.title = title
this.dispatch = dispatch
this.validator = validator ?? FormControlValidators.requiredNotEmpty
this.controls = controls
}

validate(): boolean {
return this.validator(this.controls || []);
}

async save(store: Store<any>) {
await store.dispatch(this.dispatch || '', this.controls?.[0]?.value?.value || '')
store.commit('modals/close', this.id)
}
}

Loading

0 comments on commit 90574c0

Please sign in to comment.