Skip to content

Commit

Permalink
Add support for creating entities from lookup modal
Browse files Browse the repository at this point in the history
  • Loading branch information
mythz committed Jan 8, 2025
1 parent 21ad366 commit 3191cf2
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 11 deletions.
3 changes: 2 additions & 1 deletion src/components/AutoCreateForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@
</div>
</div>

<ModalLookup v-if="modal?.name == 'ModalLookup' && modal.ref" :ref-info="modal.ref" @done="openModalDone" />
<ModalLookup v-if="modal?.name == 'ModalLookup' && modal.ref" :ref-info="modal.ref" @done="openModalDone"
:configureField="configureField"/>
</div>
</template>

Expand Down
3 changes: 2 additions & 1 deletion src/components/AutoEditForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@
</div>
</div>

<ModalLookup v-if="modal?.name == 'ModalLookup' && modal.ref" :ref-info="modal.ref" @done="openModalDone" />
<ModalLookup v-if="modal?.name == 'ModalLookup' && modal.ref" :ref-info="modal.ref" @done="openModalDone"
:configureField="configureField"/>
</div>
</template>

Expand Down
3 changes: 2 additions & 1 deletion src/components/AutoForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@
</div>
</div>
</div>
<ModalLookup v-if="modal?.name == 'ModalLookup' && modal.ref" :ref-info="modal.ref" @done="openModalDone" />
<ModalLookup v-if="modal?.name == 'ModalLookup' && modal.ref" :ref-info="modal.ref" @done="openModalDone"
:configureField="configureField"/>
</div>
</template>

Expand Down
6 changes: 4 additions & 2 deletions src/components/ModalDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@
</div>
</div>

<ModalLookup v-if="modal?.name == 'ModalLookup' && modal.ref" :ref-info="modal.ref" @done="openModalDone" />
<ModalLookup v-if="modal?.name == 'ModalLookup' && modal.ref" :ref-info="modal.ref" @done="openModalDone"
:configureField="configureField"/>
</div>
</template>

<script setup lang="ts">
import type { ModalProvider } from "@/types"
import type { ModalProvider, InputProp } from "@/types"
import { onMounted, onUnmounted, watch, ref, provide, useSlots } from "vue"
import { transition } from '@/use/utils'
import * as css from "./css"
Expand All @@ -44,6 +45,7 @@ const props = withDefaults(defineProps<{
modalClass?: string
sizeClass?: string
closeButtonClass?: string
configureField?: (field:InputProp) => void
}>(), {
id: 'ModalDialog',
modalClass: css.modal.modalClass,
Expand Down
63 changes: 57 additions & 6 deletions src/components/ModalLookup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,20 @@
<span v-else-if="api.completed">No Results</span>
</div>
</div>
<div v-if="apis.Create && canCreate" class="pl-2 mt-1">
<button type="button" @click="onShowNewItem()" title="modelTitle" :class="grid.toolbarButtonClass">
<svg class="w-5 h-5 mr-1 text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" fill="currentColor"></path></svg>
<span class="whitespace-nowrap">{{ newButtonLabel }}</span>
</button>
<AutoCreateForm v-if="create" ref="createForm" :type="apis.Create.request.name" :configure="configureField" @done="createDone" @save="createSave">
<template #header>
<slot name="formheader" form="create" :formInstance="createForm" :apis="apis" :type="dataModelName" :updateModel="setCreate"></slot>
</template>
<template #footer>
<slot name="formfooter" form="create" :formInstance="createForm" :apis="apis" :type="dataModelName" :updateModel="setCreate"></slot>
</template>
</AutoCreateForm>
</div>

<div v-if="hasPrefs && showResetPreferences" class="pl-2">
<button type="button" @click="resetPreferences" title="Reset Preferences & Filters" :class="toolbarButtonClass">
Expand Down Expand Up @@ -111,13 +125,14 @@
</template>

<script setup lang="ts">
import type { ApiPrefs, ApiResponse, Column, ColumnSettings, MetadataPropertyType, RefInfo } from '@/types'
import { computed, inject, nextTick, onMounted, ref, useSlots } from 'vue'
import type { ApiPrefs, ApiResponse, Column, ColumnSettings, InputProp, MetadataPropertyType, RefInfo } from '@/types'
import { computed, getCurrentInstance, inject, nextTick, onMounted, ref, useSlots } from 'vue'
import { ApiResult, delaySet, humanize, JsonServiceClient, mapGet } from '@servicestack/client'
import { parseJson } from '@/use/utils'
import { parseJson, getTypeName } from '@/use/utils'
import { useConfig } from '@/use/config'
import { createDto, Crud, getPrimaryKey, typeOf, typeProperties, useMetadata } from '@/use/metadata'
import { Apis, createDto, Crud, getPrimaryKey, typeOf, typeProperties, useMetadata } from '@/use/metadata'
import { grid } from './css'
import { canAccess } from '@/use/auth'
import FilterColumn from './grids/FilterColumn.vue'
import FilterViews from './grids/FilterViews.vue'
Expand All @@ -139,6 +154,11 @@ const props = withDefaults(defineProps<{
toolbarButtonClass?: string
canFilter?:(column:string) => boolean
type?: string|InstanceType<any>|Function
modelTitle?: string
newButtonLabel?: string
configureField?: (field:InputProp) => void
}>(), {
id: 'ModalLookup',
skip: 0,
Expand Down Expand Up @@ -224,6 +244,39 @@ const modalDialog = ref()
const showQueryPrefs = ref(false)
const showFilters = ref<{ column:Column, topLeft:{x:number,y:number}}|null>()
const typeName = computed(() => getTypeName(props.refInfo.model))
const apis = computed(() => Apis.forType(typeName.value, metadataApi.value))
const dataModelName = computed(() => typeName.value || queryOp.value?.dataModel.name)
const modelTitle = computed(() => props.modelTitle || dataModelName.value)
const newButtonLabel = computed(() => props.newButtonLabel || `New ${modelTitle.value}`)
const canCreate = computed(() => canAccess(apis.value.Create))
const createForm = ref()
const create = ref(false)
function onShowNewItem() {
create.value = true
}
function createDone() {
create.value = false
}
async function createSave(result:any) {
createDone()
emit('done', result)
}
function setCreate(props:any) {
if (!createForm.value) return
Object.assign(createForm.value?.model, props)
console.log('setCreate', JSON.stringify(props, null, 2))
forceUpdate()
}
function forceUpdate() {
createForm.value?.forceUpdate()
const instance = getCurrentInstance()
instance?.proxy?.$forceUpdate()
}
const prefsCacheKey = () => `${props.id}/ApiPrefs/${props.refInfo.model}`
const columnCacheKey = (name:string) => `Column/${props.id}:${props.refInfo.model}.${name}`
Expand Down Expand Up @@ -267,7 +320,6 @@ function onHeaderSelected(name:string, e:MouseEvent) {
}
}
function onFilterDone() {
showFilters.value = null
}
Expand Down Expand Up @@ -354,7 +406,6 @@ async function resetPreferences() {
await update()
}
onMounted(async () => {
//console.debug('ModalLookup.onMounted', props.id, props.refInfo?.model, props.refInfo)
const prefs = props.prefs || parseJson(storage.getItem(prefsCacheKey()))
Expand Down

0 comments on commit 3191cf2

Please sign in to comment.