@simitgroup/simpleapp-generator 1.1.2 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generate.js +7 -2
- package/dist/generate.js.map +1 -1
- package/package.json +1 -1
- package/src/generate.ts +7 -2
- package/templates/basic/nuxt/pages.[id].vue.eta +3 -2
- package/templates/basic/nuxt/pages.form.vue.eta +226 -0
- package/templates/basic/nuxt/pages.landing.vue.eta +3 -20
- package/templates/basic/nuxt/pages.new.vue.eta +7 -211
- package/templates/basic/nuxt/pages.viewer.vue.eta +10 -2
- package/templates/basic/nuxt/simpleapp.generate.client.ts.eta +2 -1
- package/templates/nuxt/components/docPage/DocPageList.vue.eta +14 -9
- package/templates/nuxt/components/event/EventDocumentViewer.vue.eta +8 -5
- package/templates/nuxt/components/list/ListView.vue.eta +4 -2
- package/templates/nuxt/components/simpleApp/SimpleAppAutocomplete.vue.eta +137 -56
- package/templates/nuxt/components/table/TableDocuments.vue.eta +3 -3
- package/templates/nuxt/lang/df.ts.eta +4 -0
- package/templates/nuxt/simpleapp/generate/clients/SimpleAppClient.ts.eta +5 -4
- package/templates/nuxt/types/events.ts.eta +1 -0
- package/templates/nuxt/types/index.ts.eta +2 -1
- package/templates/nuxt/types/others.ts.eta +1 -1
- package/templates/nuxt/types/schema.ts.eta +183 -0
- package/templates/nuxt/types/simpleappinput.ts.eta +1 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -6,8 +6,16 @@
|
|
|
6
6
|
* last change 2023-09-09
|
|
7
7
|
* author: Ks Tan
|
|
8
8
|
*/
|
|
9
|
-
import Crud from './
|
|
9
|
+
import Crud from './form.vue'
|
|
10
|
+
|
|
11
|
+
const emits = defineEmits(['afterCreate'])
|
|
12
|
+
const afterCreate = (data:any)=>{
|
|
13
|
+
emits('afterCreate',data)
|
|
14
|
+
}
|
|
15
|
+
|
|
10
16
|
</script>
|
|
17
|
+
|
|
18
|
+
|
|
11
19
|
<template>
|
|
12
|
-
<Crud/>
|
|
20
|
+
<Crud _id="new" @after-create="afterCreate"/>
|
|
13
21
|
</template>
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* Author: Ks Tan
|
|
7
7
|
*/
|
|
8
8
|
import _ from 'lodash'
|
|
9
|
+
import {SchemaType} from './types'
|
|
9
10
|
import * as sharelibs from '../sharelibs'
|
|
10
11
|
import * as jsonpath from 'jsonpath'
|
|
11
12
|
import { SimpleAppClient } from "./SimpleAppClient";
|
|
@@ -46,7 +47,7 @@ export type {
|
|
|
46
47
|
} from '../openapi'
|
|
47
48
|
|
|
48
49
|
export class <%= it.typename%>Client extends SimpleAppClient<<%= it.typename%>,<%= it.doctype.toUpperCase()%>Api>{
|
|
49
|
-
public readonly schema= <%~ JSON.stringify(it.jsonschema)
|
|
50
|
+
public readonly schema= <%~ JSON.stringify(it.jsonschema) %> as SchemaType;
|
|
50
51
|
protected documentIdentityCode='<%~ it.autocompletecode %>'
|
|
51
52
|
protected documentIdentityName='<%~ it.autocompletename %>'
|
|
52
53
|
<%if(it.jsonschema['x-simpleapp-config']['generateDocumentNumber']){%>
|
|
@@ -10,11 +10,18 @@ import _ from 'lodash'
|
|
|
10
10
|
import { SimpleAppClient } from '~/simpleapp/generate/clients/SimpleAppClient' //'../SimpleAppClient';
|
|
11
11
|
|
|
12
12
|
import {SearchBody,CellSetting} from '~/types'
|
|
13
|
-
const props = defineProps<{
|
|
13
|
+
const props = withDefaults(defineProps<{
|
|
14
14
|
document:SimpleAppClient<any,any>
|
|
15
15
|
columns:CellSetting[]
|
|
16
|
+
layoutClass?:string
|
|
17
|
+
col1Class?:string
|
|
18
|
+
col2Class?:string
|
|
16
19
|
sorts?: string[][]
|
|
17
|
-
}>()
|
|
20
|
+
}>(),{
|
|
21
|
+
layoutClass:'grid grid-cols-2',
|
|
22
|
+
col1Class:'p-4',
|
|
23
|
+
col2Class:'p-4'
|
|
24
|
+
})
|
|
18
25
|
const resourcename = ref( _.upperFirst(props.document.getDocName()))
|
|
19
26
|
const visible = ref(false)
|
|
20
27
|
const doc = props.document
|
|
@@ -86,9 +93,9 @@ const selectRow = (data:any) =>{
|
|
|
86
93
|
<template>
|
|
87
94
|
<div class="simpleapp-crudsimple">
|
|
88
95
|
<h1 v-if="systemwindows" class="error-text text-center">* system administration screen</h1>
|
|
89
|
-
<div class="
|
|
90
|
-
<div v-if="recordlist" class="
|
|
91
|
-
<TableDocuments :value="recordlist" :columns="columns" :title="
|
|
96
|
+
<div :class="layoutClass">
|
|
97
|
+
<div v-if="recordlist" :class="col1Class">
|
|
98
|
+
<TableDocuments :value="recordlist" :columns="columns" :title="doc.getDocName()" @select-row="selectRow">
|
|
92
99
|
<template #toolbar>
|
|
93
100
|
<div class="w-full text-left">
|
|
94
101
|
<Button class=" btn-primary" @click="newData" v-tooltip="'Add new(ctrl+enter)'" v-if="canPerform(resourcename,'create')">{{ t('new') }}</Button>
|
|
@@ -100,13 +107,11 @@ const selectRow = (data:any) =>{
|
|
|
100
107
|
</TableDocuments>
|
|
101
108
|
|
|
102
109
|
</div>
|
|
103
|
-
<div class="
|
|
110
|
+
<div :class="col2Class">
|
|
104
111
|
<slot>
|
|
105
112
|
undefine page content
|
|
106
113
|
</slot>
|
|
107
114
|
</div>
|
|
108
|
-
</div>
|
|
109
|
-
|
|
110
|
-
<DebugDocumentData v-model="data" :label="doc.getDocName()"/>
|
|
115
|
+
</div>
|
|
111
116
|
</div>
|
|
112
117
|
</template>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
</template>
|
|
12
12
|
<template #default>
|
|
13
13
|
<div v-for="(v,index) in allview">
|
|
14
|
-
<component v-if="index == allview.length-1" :is="defineAsyncComponent(v.viewer)" :_id="v._id" :readonly="v.readonly"></component>
|
|
14
|
+
<component v-if="index == allview.length-1" :is="defineAsyncComponent(v.viewer)" :_id="v._id" :readonly="v.readonly" @after-create="callback(v,$event)"></component>
|
|
15
15
|
</div>
|
|
16
16
|
</template>
|
|
17
17
|
</Dialog>
|
|
@@ -36,7 +36,12 @@ const ViewRecordComponent = ref()
|
|
|
36
36
|
const readonly = ref<boolean>()
|
|
37
37
|
const allview = ref<ViewRecord[]>([])
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
const callback = (v:ViewRecord,data:any)=>{
|
|
40
|
+
if(v.afterCreate){
|
|
41
|
+
v.afterCreate(data)
|
|
42
|
+
}
|
|
43
|
+
deleteTab()
|
|
44
|
+
}
|
|
40
45
|
onKeyStroke('Escape', (e) => {
|
|
41
46
|
e.preventDefault()
|
|
42
47
|
deleteTab()
|
|
@@ -58,9 +63,7 @@ const closeDialog = ()=>{
|
|
|
58
63
|
allview.value=[]
|
|
59
64
|
}
|
|
60
65
|
$listen('ViewRecord',(setting)=>{
|
|
61
|
-
|
|
62
|
-
visible.value=true
|
|
63
|
-
|
|
66
|
+
visible.value=true
|
|
64
67
|
allview.value.push(setting)
|
|
65
68
|
activetabindex.value = allview.value.length-1
|
|
66
69
|
|
|
@@ -13,8 +13,10 @@
|
|
|
13
13
|
<li v-for="item in filterlist">
|
|
14
14
|
<div :class="getSelectedCSS(item)">
|
|
15
15
|
<NuxtLink :to="`${url}/${item[idField]}`">
|
|
16
|
-
<
|
|
17
|
-
|
|
16
|
+
<slot>
|
|
17
|
+
<div class="mr-2">{{item[titleField] }}</div>
|
|
18
|
+
<div class="font font-bold text-right">{{item[subTitleField]}}</div>
|
|
19
|
+
</slot>
|
|
18
20
|
</NuxtLink>
|
|
19
21
|
</div>
|
|
20
22
|
|
|
@@ -1,82 +1,163 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
|
|
3
|
-
forceSelection optionLabel="label"
|
|
1
|
+
<template>
|
|
2
|
+
<AutoComplete v-model="modelValue" v-if="!readonly" ref="autocompleteinput"
|
|
3
|
+
forceSelection optionLabel="label"
|
|
4
4
|
@item-select="pickAutoComplete"
|
|
5
|
-
@complete="getListFromAutocompleteApi"
|
|
6
|
-
:
|
|
5
|
+
@complete="getListFromAutocompleteApi"
|
|
6
|
+
:placeholder="t('keyword')"
|
|
7
|
+
:dropdown="true"
|
|
8
|
+
:dropdown-icon="buttonClass"
|
|
9
|
+
@before-show="beforeShow"
|
|
10
|
+
@clear = "clear"
|
|
11
|
+
:dropdown-mode="'current'"
|
|
12
|
+
:pt="pt"
|
|
13
|
+
:delay="500"
|
|
7
14
|
:disabled="readonly"
|
|
8
15
|
:suggestions="list"
|
|
9
16
|
@blur="onBlurAutocomplete"
|
|
10
17
|
:inputId="inputId" :path="setting.instancepath"
|
|
11
18
|
:readonly="readonly"
|
|
12
19
|
/>
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
20
|
+
<div v-else class="p-3 border rounded-lg border-gray-300 dark:border-blue-900/40 ">
|
|
21
|
+
<span :readonly="readonly" class="cursor-pointer text-primary-600 dark:text-primary-400 "
|
|
22
|
+
tabindex="0" @click="openViewer(true)">{{ modelValue && modelValue.label ? modelValue.label:'-' }}</span>
|
|
23
|
+
</div>
|
|
17
24
|
</template>
|
|
18
25
|
<script setup lang="ts">
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const autocompleteitem = ref<autocompletetype>(emptyautocomplete())
|
|
26
|
-
const props = defineProps<{
|
|
27
|
-
setting:any
|
|
28
|
-
readonly?:boolean
|
|
29
|
-
inputId:string
|
|
30
|
-
pt?:any
|
|
31
|
-
}>()
|
|
32
|
-
const modelValue = defineModel<{_id:string,label:string}>()
|
|
33
|
-
const onBlurAutocomplete = ()=>{
|
|
34
|
-
|
|
35
|
-
if( autocompleteitem.value === null){
|
|
36
|
-
autocompleteitem.value = emptyautocomplete()
|
|
37
|
-
}
|
|
38
|
-
if(isNull(modelValue.value )){
|
|
39
|
-
modelValue.value = autocompleteitem.value
|
|
40
|
-
}
|
|
41
|
-
else if(typeof modelValue.value =='object'){
|
|
42
|
-
|
|
43
|
-
}else{
|
|
44
|
-
modelValue.value = autocompleteitem.value
|
|
45
|
-
}
|
|
26
|
+
import { isNull } from 'lodash';
|
|
27
|
+
import {autocompletetype,SchemaConfig,SchemaType} from '~/types'
|
|
28
|
+
const autocompleteinput = ref()
|
|
29
|
+
const {$event} = useNuxtApp()
|
|
30
|
+
const list = ref<any[]>([])
|
|
31
|
+
const emptyautocomplete =():autocompletetype=> ({_id:'',code:'',label:''})
|
|
46
32
|
|
|
33
|
+
const props = withDefaults(defineProps<{
|
|
34
|
+
setting:any
|
|
35
|
+
allowAddNew?:boolean
|
|
36
|
+
showNull?:boolean
|
|
37
|
+
readonly?:boolean
|
|
38
|
+
inputId:string
|
|
39
|
+
pt?:any
|
|
40
|
+
}>(),{
|
|
41
|
+
allowAddNew:true,showNull:true
|
|
42
|
+
})
|
|
43
|
+
const autocompleteitem = ref<autocompletetype>(emptyautocomplete())
|
|
44
|
+
const modelValue = defineModel<autocompletetype>()
|
|
45
|
+
if(modelValue.value && modelValue.value._id){
|
|
46
|
+
autocompleteitem.value={...modelValue.value}
|
|
47
|
+
}
|
|
48
|
+
//clear auto complete auto set value = empty
|
|
49
|
+
const clear = ()=>{
|
|
50
|
+
autocompleteitem.value = emptyautocomplete()
|
|
51
|
+
modelValue.value = emptyautocomplete()
|
|
47
52
|
}
|
|
53
|
+
const buttonClass=computed(()=>modelValue.value?._id ? 'pi pi-link' : 'pi pi-angle-down')
|
|
54
|
+
|
|
55
|
+
//if record picked, click button show record info instead
|
|
56
|
+
const beforeShow = ()=>{
|
|
57
|
+
if(modelValue.value?._id ){
|
|
58
|
+
openViewer(true)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//recorrect data if lose focus
|
|
63
|
+
const onBlurAutocomplete = ()=>{
|
|
64
|
+
if( autocompleteitem.value === null){
|
|
65
|
+
autocompleteitem.value = emptyautocomplete()
|
|
66
|
+
}
|
|
67
|
+
if(isNull(modelValue.value )){
|
|
68
|
+
modelValue.value = autocompleteitem.value
|
|
69
|
+
}
|
|
70
|
+
else if(typeof modelValue.value =='object'){
|
|
71
|
+
|
|
72
|
+
}else{
|
|
73
|
+
modelValue.value = autocompleteitem.value
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
//obtain remote data
|
|
48
78
|
const getListFromAutocompleteApi = (event:any)=>{
|
|
49
79
|
const keyword = event.query??''
|
|
50
|
-
//props.setting.document.getDocType()
|
|
51
80
|
const targetDocument = props.setting.fieldsetting['x-foreignkey']
|
|
52
81
|
getDocumentApi(targetDocument).autoComplete(keyword).then((res:any)=>{
|
|
53
|
-
|
|
82
|
+
|
|
83
|
+
list.value = res.data
|
|
84
|
+
|
|
85
|
+
if(props.allowAddNew){
|
|
86
|
+
list.value = list.value.concat({_id:'new',label:'<'+t('new')+'>'})
|
|
87
|
+
}
|
|
54
88
|
})
|
|
55
89
|
}
|
|
90
|
+
|
|
91
|
+
//on select
|
|
56
92
|
const pickAutoComplete = (event:any)=>{
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
93
|
+
console.log("event",event,'event.value._id',"'"+event.value._id+"'")
|
|
94
|
+
if(event.value._id===''){
|
|
95
|
+
|
|
96
|
+
modelValue.value = emptyautocomplete()
|
|
97
|
+
autocompleteitem.value = emptyautocomplete()
|
|
98
|
+
console.log(modelValue.value )
|
|
99
|
+
} else if(event.value._id==='new'){
|
|
100
|
+
|
|
101
|
+
modelValue.value = emptyautocomplete()
|
|
102
|
+
autocompleteitem.value = emptyautocomplete()
|
|
103
|
+
openViewer(false)
|
|
104
|
+
}
|
|
105
|
+
else if(typeof event.value.query == 'undefined'){
|
|
106
|
+
modelValue.value=event.value
|
|
107
|
+
autocompleteitem.value = event.value
|
|
108
|
+
}
|
|
61
109
|
}
|
|
62
110
|
|
|
63
111
|
const emits = defineEmits(['change','update:modelValue','update:docNoFormat'])
|
|
64
112
|
watch(modelValue ,(newvalue:any)=>{
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
emits('update:modelValue',modelValue.value)
|
|
113
|
+
|
|
114
|
+
emitChanges()
|
|
115
|
+
|
|
69
116
|
})
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
eventId: crypto.randomUUID(),
|
|
75
|
-
label: modelValue.value?.label as string,
|
|
76
|
-
readonly:true,
|
|
77
|
-
viewer : getDocument(props.setting.fieldsetting['x-foreignkey'])?.viewer,
|
|
78
|
-
documentName: props.setting.fieldsetting['x-foreignkey'],
|
|
79
|
-
})
|
|
117
|
+
const emitChanges = () =>{
|
|
118
|
+
|
|
119
|
+
emits('change',modelValue.value)
|
|
120
|
+
|
|
80
121
|
}
|
|
81
122
|
|
|
123
|
+
//pop up records
|
|
124
|
+
const openViewer = (readonly:boolean) =>{
|
|
125
|
+
const remotedoc = getDocument(props.setting.fieldsetting['x-foreignkey'])
|
|
126
|
+
|
|
127
|
+
if(remotedoc){
|
|
128
|
+
const schema:SchemaType = remotedoc.docClass.getSchema()
|
|
129
|
+
const labelfield = schema['x-simpleapp-config'].documentTitle as string
|
|
130
|
+
const codefield = schema['x-simpleapp-config'].uniqueKey as string
|
|
131
|
+
$event('ViewRecord',{
|
|
132
|
+
_id: modelValue.value?._id as string,
|
|
133
|
+
eventId: crypto.randomUUID(),
|
|
134
|
+
label: modelValue.value?.label as string,
|
|
135
|
+
readonly:readonly,
|
|
136
|
+
viewer : getDocument(props.setting.fieldsetting['x-foreignkey'])?.viewer,
|
|
137
|
+
documentName: props.setting.fieldsetting['x-foreignkey'],
|
|
138
|
+
|
|
139
|
+
//after create, auto copy value into auto complete
|
|
140
|
+
afterCreate:(data:any)=>{
|
|
141
|
+
autocompleteitem.value = {
|
|
142
|
+
_id: data._id,
|
|
143
|
+
code: data[codefield],
|
|
144
|
+
label: data[labelfield],
|
|
145
|
+
}
|
|
146
|
+
if(schema['x-simpleapp-config'].additionalAutoCompleteFields){
|
|
147
|
+
const addfields = schema['x-simpleapp-config'].additionalAutoCompleteFields
|
|
148
|
+
for(let i=0;i<addfields.length;i++){
|
|
149
|
+
const fieldname = addfields[i] as string
|
|
150
|
+
autocompleteitem.value[fieldname] = data[fieldname]
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
modelValue.value = {...autocompleteitem.value}
|
|
154
|
+
emitChanges()
|
|
155
|
+
console.log("autocompleteitem.value",autocompleteitem.value ,modelValue.value)
|
|
156
|
+
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
82
163
|
</script>
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
</div>
|
|
23
23
|
<div class="flex-1">
|
|
24
24
|
<slot name="title">
|
|
25
|
-
<h1 class="text text-2xl pt-2 text-center">{{ title }}</h1>
|
|
25
|
+
<h1 class="text text-2xl pt-2 text-center">{{ t(title) }}</h1>
|
|
26
26
|
</slot>
|
|
27
27
|
|
|
28
28
|
</div>
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
<template #empty>
|
|
37
37
|
<div class="text-center ">
|
|
38
38
|
<div class="text-3xl text-gray-400 pi pi-exclamation-circle"></div>
|
|
39
|
-
<div class="text-3xl text-gray-400">
|
|
39
|
+
<div class="text-3xl text-gray-400">{{t('noDataFound')}}</div>
|
|
40
40
|
|
|
41
41
|
</div>
|
|
42
42
|
</template>
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
<p >{{ t(col) }}</p>
|
|
49
49
|
</template>
|
|
50
50
|
<template v-else-if="typeof col =='object'" #header>
|
|
51
|
-
<span>{{ col.title }} </span>
|
|
51
|
+
<span>{{ t(col.title) }} </span>
|
|
52
52
|
</template>
|
|
53
53
|
<template v-else #header>
|
|
54
54
|
<span class="text-danger-600">unknown</span>
|
|
@@ -8,6 +8,10 @@ export default {
|
|
|
8
8
|
welcomeSimpleApp: 'Welcome To SimpleApp',
|
|
9
9
|
changeHomePageMsg: '{fullName}, it is product front page and by right you shall replace it with something else.',
|
|
10
10
|
realman:'Real man code with simpleapp',
|
|
11
|
+
new:'New',
|
|
12
|
+
keyword: 'Keyword',
|
|
13
|
+
empty: 'Empty',
|
|
14
|
+
noDataFound:'No Data Found',
|
|
11
15
|
|
|
12
16
|
//auto generate from schema
|
|
13
17
|
<% for(let i=0; i< it.allfields.length; i++){ %>
|
|
@@ -10,7 +10,8 @@ import addErrors from 'ajv-errors';
|
|
|
10
10
|
import { ref } from 'vue';
|
|
11
11
|
import type { Ref } from 'vue';
|
|
12
12
|
import type { AxiosResponse } from 'axios';
|
|
13
|
-
import {SearchBody,Notification,NotificationStatus} from '~/types'
|
|
13
|
+
import {SearchBody,Notification,NotificationStatus,SchemaType} from '~/types'
|
|
14
|
+
|
|
14
15
|
// import { useToast, } from 'primevue/usetoast';
|
|
15
16
|
// import type { ToastMessageOptions } from 'primevue/toast';
|
|
16
17
|
// const toast = useToast();
|
|
@@ -31,7 +32,7 @@ export class SimpleAppClient<
|
|
|
31
32
|
public event:Function|null=null;
|
|
32
33
|
public listen:Function|null=null;
|
|
33
34
|
protected data = <Ref<TData>>ref({} as TData);
|
|
34
|
-
public schema = {}; //cant define data type, cause it make autocomplete gone.
|
|
35
|
+
public schema = {} as SchemaType; //cant define data type, cause it make autocomplete gone.
|
|
35
36
|
protected doctype = '';
|
|
36
37
|
protected docname = '';
|
|
37
38
|
protected errorlist = ref({});
|
|
@@ -46,8 +47,8 @@ export class SimpleAppClient<
|
|
|
46
47
|
getDocName = () => this.docname;
|
|
47
48
|
setNew = ()=>{}
|
|
48
49
|
isNew = () => this.data.value['created']==''
|
|
49
|
-
setSchema = (schema:
|
|
50
|
-
getSchema = ()
|
|
50
|
+
setSchema = (schema: SchemaType) => (this.schema = schema);
|
|
51
|
+
getSchema = ():SchemaType=> this.schema;
|
|
51
52
|
getErrors = () => this.errorlist;
|
|
52
53
|
getData = () => this.data.value;
|
|
53
54
|
getApi = () =>this.docapi;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { JSONSchema7,JSONSchema7Type,JSONSchema7Version, JSONSchema7TypeName,JSONSchema7Definition } from 'json-schema';
|
|
2
|
+
export type DocumentStatus = {
|
|
3
|
+
status:string //'CO', 'V', 'CL', 'D' and etc
|
|
4
|
+
statusName:string
|
|
5
|
+
readOnly:boolean
|
|
6
|
+
actions: string[] //api name ['confirm','revert','close','void' and etc]
|
|
7
|
+
}
|
|
8
|
+
export enum RESTMethods {'post'='post','get'='get', 'delete'='delete','put'='put', 'patch'='patch'}
|
|
9
|
+
export type DocumentApi = {
|
|
10
|
+
action:string //api action name
|
|
11
|
+
entryPoint:string //api entry point example:':id', ':id/confirm'
|
|
12
|
+
queryPara?:string[] //what query parameter wish to accept, example: ['description','date']
|
|
13
|
+
requiredRole?: string[] // what special user role wish to allow for this api, example: ['SuperUser']
|
|
14
|
+
method:RESTMethods
|
|
15
|
+
execute:string, //what service class method name to execute, example: 'ping','getDocumentName'
|
|
16
|
+
description:string //description of api
|
|
17
|
+
}
|
|
18
|
+
export enum IsolationType {"none"="none" , "tenant"="tenant","org"="org", "branch"="branch"}
|
|
19
|
+
// export type ImportLibs = {"lib":string,"as":string}
|
|
20
|
+
export type Formula = {
|
|
21
|
+
jsonPath:string //example: "$.subtotal","$.details[*]"
|
|
22
|
+
formula:string //example "jslib.getDocumentSubTotal(@F{$.details})"
|
|
23
|
+
}
|
|
24
|
+
export type SchemaConfig = {
|
|
25
|
+
isolationType: IsolationType
|
|
26
|
+
requiredRoles?:string[]
|
|
27
|
+
pageType?: string
|
|
28
|
+
uniqueKey?:string
|
|
29
|
+
uniqueKeys?:string[][]
|
|
30
|
+
documentTitle?:string
|
|
31
|
+
generateDocumentNumber?:boolean
|
|
32
|
+
documentDate?:string
|
|
33
|
+
allStatus?:DocumentStatus[]
|
|
34
|
+
additionalApis?:DocumentApi[]
|
|
35
|
+
additionalAutoCompleteFields ?: string[]
|
|
36
|
+
// libs?:ImportLibs[] // both process class and frontend client class will import same lib
|
|
37
|
+
formulas?: Formula[]
|
|
38
|
+
documentType: string
|
|
39
|
+
documentName: string
|
|
40
|
+
collectionName?: string
|
|
41
|
+
foreignKeys?:MyForeignKey,
|
|
42
|
+
}
|
|
43
|
+
export type MyForeignKey = {
|
|
44
|
+
[collectionname:string]:string[]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type SchemaType = {
|
|
48
|
+
type:string
|
|
49
|
+
definitions?:SimpleAppJSONSchema7
|
|
50
|
+
required?:string[]
|
|
51
|
+
|
|
52
|
+
"x-simpleapp-config":SchemaConfig
|
|
53
|
+
properties: SchemaFields
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
export type SchemaFields = {
|
|
58
|
+
_id: SimpleAppJSONSchema7
|
|
59
|
+
tenantId: SimpleAppJSONSchema7
|
|
60
|
+
orgId: SimpleAppJSONSchema7
|
|
61
|
+
branchId: SimpleAppJSONSchema7
|
|
62
|
+
created: SimpleAppJSONSchema7
|
|
63
|
+
updated: SimpleAppJSONSchema7
|
|
64
|
+
createdBy: SimpleAppJSONSchema7
|
|
65
|
+
updatedBy: SimpleAppJSONSchema7
|
|
66
|
+
[key:string]:SimpleAppJSONSchema7 | SimpleAppJSONSchema7[] | undefined
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
// modified from jsonschemas
|
|
73
|
+
export type SimpleAppJSONSchema7Definition = SimpleAppJSONSchema7 | boolean;
|
|
74
|
+
export interface SimpleAppJSONSchema7 {
|
|
75
|
+
|
|
76
|
+
'x-foreignkey' ?:string
|
|
77
|
+
$id?: string | undefined;
|
|
78
|
+
$ref?: string | undefined;
|
|
79
|
+
$schema?: JSONSchema7Version | undefined;
|
|
80
|
+
$comment?: string | undefined;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @see https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-00#section-8.2.4
|
|
84
|
+
* @see https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-validation-00#appendix-A
|
|
85
|
+
*/
|
|
86
|
+
$defs?: {
|
|
87
|
+
[key: string]: JSONSchema7Definition;
|
|
88
|
+
} | undefined;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.1
|
|
92
|
+
*/
|
|
93
|
+
type?: JSONSchema7TypeName | JSONSchema7TypeName[] | undefined;
|
|
94
|
+
enum?: JSONSchema7Type[] | undefined;
|
|
95
|
+
const?: JSONSchema7Type | undefined;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.2
|
|
99
|
+
*/
|
|
100
|
+
multipleOf?: number | undefined;
|
|
101
|
+
maximum?: number | undefined;
|
|
102
|
+
exclusiveMaximum?: number | undefined;
|
|
103
|
+
minimum?: number | undefined;
|
|
104
|
+
exclusiveMinimum?: number | undefined;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.3
|
|
108
|
+
*/
|
|
109
|
+
maxLength?: number | undefined;
|
|
110
|
+
minLength?: number | undefined;
|
|
111
|
+
pattern?: string | undefined;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.4
|
|
115
|
+
*/
|
|
116
|
+
items?: SimpleAppJSONSchema7Definition | SimpleAppJSONSchema7Definition[] | undefined;
|
|
117
|
+
additionalItems?: JSONSchema7Definition | undefined;
|
|
118
|
+
maxItems?: number | undefined;
|
|
119
|
+
minItems?: number | undefined;
|
|
120
|
+
uniqueItems?: boolean | undefined;
|
|
121
|
+
contains?: SimpleAppJSONSchema7Definition | undefined;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.5
|
|
125
|
+
*/
|
|
126
|
+
maxProperties?: number | undefined;
|
|
127
|
+
minProperties?: number | undefined;
|
|
128
|
+
required?: string[] | undefined;
|
|
129
|
+
properties?: {
|
|
130
|
+
[key: string]: SimpleAppJSONSchema7Definition;
|
|
131
|
+
} | undefined;
|
|
132
|
+
patternProperties?: {
|
|
133
|
+
[key: string]: SimpleAppJSONSchema7Definition;
|
|
134
|
+
} | undefined;
|
|
135
|
+
additionalProperties?: SimpleAppJSONSchema7Definition | undefined;
|
|
136
|
+
dependencies?: {
|
|
137
|
+
[key: string]: SimpleAppJSONSchema7Definition | string[];
|
|
138
|
+
} | undefined;
|
|
139
|
+
propertyNames?: SimpleAppJSONSchema7Definition | undefined;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.6
|
|
143
|
+
*/
|
|
144
|
+
if?: SimpleAppJSONSchema7Definition | undefined;
|
|
145
|
+
then?: SimpleAppJSONSchema7Definition | undefined;
|
|
146
|
+
else?: SimpleAppJSONSchema7Definition | undefined;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.7
|
|
150
|
+
*/
|
|
151
|
+
allOf?: SimpleAppJSONSchema7Definition[] | undefined;
|
|
152
|
+
anyOf?: SimpleAppJSONSchema7Definition[] | undefined;
|
|
153
|
+
oneOf?: SimpleAppJSONSchema7Definition[] | undefined;
|
|
154
|
+
not?: SimpleAppJSONSchema7Definition | undefined;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-7
|
|
158
|
+
*/
|
|
159
|
+
format?: string | undefined;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-8
|
|
163
|
+
*/
|
|
164
|
+
contentMediaType?: string | undefined;
|
|
165
|
+
contentEncoding?: string | undefined;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-9
|
|
169
|
+
*/
|
|
170
|
+
definitions?: {
|
|
171
|
+
[key: string]: JSONSchema7Definition;
|
|
172
|
+
} | undefined;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-10
|
|
176
|
+
*/
|
|
177
|
+
title?: string | undefined;
|
|
178
|
+
description?: string | undefined;
|
|
179
|
+
default?: JSONSchema7Type | undefined;
|
|
180
|
+
readOnly?: boolean | undefined;
|
|
181
|
+
writeOnly?: boolean | undefined;
|
|
182
|
+
examples?: JSONSchema7Type | undefined;
|
|
183
|
+
}
|