@live-change/frontend-auto-form 0.9.13 → 0.9.14

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.
@@ -69,7 +69,10 @@
69
69
 
70
70
  import { validateData } from "@live-change/vue3-components"
71
71
  const validationResult = computed(() => {
72
- const currentValue = editor.value.value.value
72
+ const currentValue = {
73
+ ...(editor.value.identifiers),
74
+ ...(editor.value.value.value),
75
+ }
73
76
  const validationResult = validateData(model.value, currentValue, 'validation', appContext,
74
77
  props.propName, props.rootValue, true)
75
78
  const softValidationResult = validateData(model.value, currentValue, 'softValidation', appContext,
@@ -1,16 +1,18 @@
1
1
  <template>
2
- <div class="w-full lg:w-8 md:w-11">
2
+ <div>
3
3
  <!-- <h4>definition</h4>
4
4
  <pre>{{ modelDefinition }}</pre>-->
5
5
 
6
6
  <div class="surface-card w-full p-3 shadow-1 border-round mb-2">
7
- <div class="">
8
- Service <strong>{{ service }}</strong>
9
- </div>
10
- <div class="text-2xl">
11
- <strong>{{ pluralize(model) }}</strong>
12
- <span class="ml-1">list</span>
13
- </div>
7
+ <slot name="header">
8
+ <div class="">
9
+ Service <strong>{{ service }}</strong>
10
+ </div>
11
+ <div class="text-2xl">
12
+ <strong>{{ pluralize(model) }}</strong>
13
+ <span class="ml-1">list</span>
14
+ </div>
15
+ </slot>
14
16
  </div>
15
17
 
16
18
  <div class="surface-card p-3 shadow-1 border-round" v-if="modelsPathRangeFunction">
@@ -58,7 +60,7 @@
58
60
  </div>
59
61
  </div>
60
62
 
61
- <div class="mt-3 flex flex-row justify-content-end mr-2">
63
+ <div v-if="modelDefinition.value?.crud?.create" class="mt-3 flex flex-row justify-content-end mr-2">
62
64
  <router-link :to="createRoute" class="no-underline2">
63
65
  <Button icon="pi pi-plus" :label="'Create new '+model" />
64
66
  </router-link>
@@ -69,6 +71,8 @@
69
71
 
70
72
  <script setup>
71
73
 
74
+ import Button from "primevue/button"
75
+
72
76
  import { ref, computed, onMounted, defineProps, toRefs } from 'vue'
73
77
  import { RangeViewer, injectComponent } from "@live-change/vue3-components"
74
78
  import pluralize from 'pluralize'
@@ -81,9 +85,13 @@
81
85
  model: {
82
86
  type: String,
83
87
  required: true,
84
- }
88
+ },
89
+ identifiers: {
90
+ type: Object,
91
+ default: () => ({})
92
+ },
85
93
  })
86
- const { service, model } = toRefs(props)
94
+ const { service, model, identifiers } = toRefs(props)
87
95
 
88
96
  import AutoObjectIdentification from './AutoObjectIdentification.vue'
89
97
 
@@ -118,6 +126,7 @@
118
126
  if(!path[config.service]) return null
119
127
  if(!path[config.service][rangeView]) return null
120
128
  return (range) => path[config.service][rangeView]({
129
+ ...identifiers.value,
121
130
  ...(config.reverse ? reverseRange(range) : range),
122
131
  })
123
132
  })
@@ -164,7 +173,8 @@
164
173
  name: 'auto-form:editor',
165
174
  params: {
166
175
  serviceName: service.value,
167
- modelName: model.name
176
+ modelName: model.value,
177
+ identifiers: Object.values(identifiers.value)
168
178
  }
169
179
  }))
170
180
 
@@ -10,21 +10,56 @@
10
10
  <h4>object</h4>
11
11
  <pre>{{ object }}</pre>-->
12
12
 
13
- <div class="">
14
- Service <strong>{{ service }}</strong>
13
+ <div class="surface-card p-3 shadow-1 border-round mb-4">
14
+
15
+ <div class="">
16
+ Service <strong>{{ service }}</strong>
17
+ </div>
18
+ <div class="text-2xl mb-4">
19
+ <strong>{{ model }}</strong>
20
+ <ObjectIdentification
21
+ :objectType="service + '_' + model"
22
+ :object="object.to ?? object.id"
23
+ :data="object"
24
+ class="ml-2"
25
+ />
26
+ </div>
27
+
28
+ <AutoView :value="object" :root-value="object" :i18n="i18n" :attributes="attributes"
29
+ :definition="modelDefinition" />
30
+
15
31
  </div>
16
- <div class="text-2xl mb-4">
17
- <strong>{{ model }}</strong>
18
- <ObjectIdentification
19
- :objectType="service + '_' + model"
20
- :object="object.to ?? object.id"
21
- :data="object"
22
- class="ml-2"
23
- />
32
+
33
+ <div v-for="itemRelation of itemRelations">
34
+ <ModelList :service="itemRelation.from.serviceName" :model="itemRelation.from.name"
35
+ :identifiers="relatedIdentifiers">
36
+ <template #header>
37
+ <div class="text-xl">
38
+ <ObjectIdentification
39
+ :objectType="service + '_' + model"
40
+ :object="object.to ?? object.id"
41
+ :data="object"
42
+ class="mr-2"
43
+ />
44
+ <span class="mr-2 font-medium">{{ model }}'s</span>
45
+ <span class="font-bold">{{ pluralize(itemRelation.from.name) }}</span>:
46
+ </div>
47
+ </template>
48
+
49
+ </ModelList>
50
+
51
+ <pre>{{ relatedIdentifiers }}</pre>
52
+
53
+ <pre>{{ itemRelation }}</pre>
54
+
24
55
  </div>
25
56
 
26
- <AutoView :value="object" :root-value="object" :i18n="i18n" :attributes="attributes"
27
- :definition="modelDefinition" />
57
+ <!-- <div class="surface-card p-3 shadow-1 border-round">
58
+
59
+ <h4>Backward relations</h4>
60
+ <pre>{{ backwardRelations }}</pre>
61
+
62
+ </div>-->
28
63
 
29
64
  </div>
30
65
  </template>
@@ -32,7 +67,9 @@
32
67
  <script setup>
33
68
 
34
69
  import AutoView from '../view/AutoView.vue'
70
+ import ModelList from './ModelList.vue'
35
71
 
72
+ import pluralize from 'pluralize'
36
73
  import { ref, computed, onMounted, defineProps, defineEmits, toRefs } from 'vue'
37
74
  import { RangeViewer, injectComponent } from "@live-change/vue3-components"
38
75
 
@@ -47,11 +84,7 @@
47
84
  },
48
85
  identifiers: {
49
86
  type: Object,
50
- default: []
51
- },
52
- draft: {
53
- type: Boolean,
54
- default: false
87
+ default: () => ({})
55
88
  },
56
89
  attributes: {
57
90
  type: Object,
@@ -62,7 +95,7 @@
62
95
  default: ''
63
96
  }
64
97
  })
65
- const { service, model, identifiers, draft, attributes, i18n } = toRefs(props)
98
+ const { service, model, identifiers, attributes, i18n } = toRefs(props)
66
99
 
67
100
  const emit = defineEmits(['saved', 'draftSaved', 'draftDiscarded', 'saveError', 'created' ])
68
101
 
@@ -85,6 +118,14 @@
85
118
  return api.services?.[service.value]?.models?.[model.value]
86
119
  })
87
120
 
121
+ import { getForwardRelations, getBackwardRelations } from '../../logic/relations.js'
122
+ const forwardRelations = computed(() => getForwardRelations(modelDefinition.value, () => true, api))
123
+ const backwardRelations = computed(() => getBackwardRelations(modelDefinition.value, api))
124
+
125
+ const itemRelations = computed(
126
+ () => backwardRelations.value.filter(relation => relation.relation === 'itemOf')
127
+ )
128
+
88
129
  import viewData from '../../logic/viewData.js'
89
130
 
90
131
  const viewDataPromise = viewData({
@@ -98,6 +139,10 @@
98
139
  viewDataPromise
99
140
  ])
100
141
 
142
+ const relatedIdentifiers = computed(() => ({
143
+ [model.value[0].toLowerCase() + model.value.slice(1)]: object.value.to ?? object.value.id
144
+ }))
145
+
101
146
  </script>
102
147
 
103
148
  <style scoped>
@@ -1,4 +1,5 @@
1
1
  <template>
2
+ <!-- <pre>{{ viewComponentRequest }}</pre>-->
2
3
  <component v-if="viewComponent && visible" :is="viewComponent" v-bind="attributes" :i18n="i18n" />
3
4
  </template>
4
5
 
@@ -76,18 +77,20 @@
76
77
  return undefined
77
78
  })
78
79
 
80
+ const viewComponentRequest = computed(() => (definition.value?.view?.componentRequest ?? {
81
+ ...(definition.value?.view?.componentRequestProperties),
82
+ name: 'AutoView',
83
+ type: definition.value.type ?? 'Object',
84
+ view: definition?.view?.name ?? definition?.view,
85
+ filter: viewFilter.value
86
+ }))
87
+
79
88
  const viewComponent = computed(() => {
80
89
  const type = definition.value.type ?? 'Object'
81
90
  const defaultComponent = (type === 'Object')
82
91
  ? defineAsyncComponent(() => import('./ObjectView.vue'))
83
92
  : defineAsyncComponent(() => import('./JsonView.vue'))
84
- return injectComponent(definition.value?.view?.componentRequest ?? {
85
- ...(definition.value?.view?.componentRequestProperties),
86
- name: 'AutoView',
87
- type,
88
- view: definition?.view?.name ?? definition?.view,
89
- filter: viewFilter.value
90
- }, defaultComponent)
93
+ return injectComponent(viewComponentRequest.value, defineAsyncComponent(() => import('./JsonView.vue')))
91
94
  })
92
95
 
93
96
  const viewClass = computed(() => [definition.value?.view?.class, props.class])
@@ -2,7 +2,7 @@
2
2
  <div class="field" :class="fieldClass" :style="fieldStyle">
3
3
  <slot name="label"
4
4
  v-bind="{ uid, value, definition, viewClass, viewStyle, attributes, propName, rootValue, i18n }">
5
- <label :for="uid">{{ t( label ) }}</label>
5
+ <label :for="uid" class="font-medium text-lg">{{ t( label ) }}</label>
6
6
  </slot>
7
7
  <slot v-bind="{ uid, value, definition, viewClass, viewStyle, attributes, propName, rootValue, i18n }">
8
8
  <AutoView :value="value" :definition="definition"
@@ -70,7 +70,7 @@
70
70
 
71
71
  const label = computed(() => props.i18n + (props.label || definition.value.label || props.name))
72
72
 
73
- const viewClass = computed(() => [definition.value?.view?.class, props.viewClass])
73
+ const viewClass = computed(() => [definition.value?.view?.class, props.viewClass, 'ml-1'])
74
74
  const viewStyle = computed(() => [definition.value?.view?.style, props.viewStyle])
75
75
  const fieldClass = computed(() => [definition.value?.view?.class, props.class])
76
76
  const fieldStyle = computed(() => [definition.value?.view?.style, props.style])
@@ -29,8 +29,6 @@
29
29
  type: String,
30
30
  default: ''
31
31
  },
32
- class: {},
33
- style: {},
34
32
  i18n: {
35
33
  type: String,
36
34
  default: ''
@@ -0,0 +1,36 @@
1
+ <template>
2
+ <div>
3
+ {{ value }}
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+
9
+ import { computed, inject, getCurrentInstance, toRefs } from 'vue'
10
+
11
+ const props = defineProps({
12
+ value: {},
13
+ definition: {
14
+ type: Object
15
+ },
16
+ rootValue: {
17
+ type: Object,
18
+ default: () => ({})
19
+ },
20
+ propName: {
21
+ type: String,
22
+ default: ''
23
+ },
24
+ i18n: {
25
+ type: String,
26
+ default: ''
27
+ },
28
+ })
29
+
30
+ const { value, definition, propName } = toRefs(props)
31
+
32
+ </script>
33
+
34
+ <style scoped>
35
+
36
+ </style>
@@ -0,0 +1,14 @@
1
+ import { provideComponent } from '@live-change/vue3-components'
2
+ import { defineAsyncComponent } from 'vue'
3
+
4
+ export default function provideAutoViewComponents() {
5
+ provideComponent({
6
+ name: 'AutoView',
7
+ type: 'Object'
8
+ }, defineAsyncComponent(() => import('./ObjectView.vue')))
9
+
10
+ provideComponent({
11
+ name: 'AutoView',
12
+ type: 'String'
13
+ }, defineAsyncComponent(() => import('./StringView.vue')))
14
+ }
@@ -77,7 +77,11 @@ export default function editorData(options) {
77
77
 
78
78
  const updateAction = api.actions[serviceName][crudMethods.update]
79
79
  const createOrUpdateAction = api.actions[serviceName][crudMethods.createOrUpdate]
80
+ if(!updateAction && !createOrUpdateAction)
81
+ throw new Error('update or createOrUpdate action must be defined in model or options')
80
82
  const createAction = api.actions[serviceName][crudMethods.create]
83
+ if(isNew && !createAction && !createOrUpdateAction)
84
+ throw new Error('create action must be defined in model or options')
81
85
  const createOrUpdateDraftAction = draft && api.actions.draft.setOrUpdateMyDraft
82
86
  const removeDraftAction = draft && api.actions.draft.resetMyDraft
83
87
 
@@ -184,6 +188,7 @@ export default function editorData(options) {
184
188
  }
185
189
 
186
190
  return {
191
+ identifiers,
187
192
  value: synchronizedData.value,
188
193
  changed,
189
194
  save,
@@ -228,6 +233,7 @@ export default function editorData(options) {
228
233
  }
229
234
 
230
235
  return {
236
+ identifiers,
231
237
  value: synchronizedData.value,
232
238
  changed: synchronizedData.changed,
233
239
  save: synchronizedData.save,
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <ModelList :service="serviceName" :model="modelName" />
2
+ <ModelList :service="serviceName" :model="modelName" class="w-full lg:w-8 md:w-11" />
3
3
  </template>
4
4
 
5
5
  <script setup>
@@ -1,10 +1,8 @@
1
1
  <template>
2
2
  <div class="w-full lg:w-8 md:w-11">
3
- <div class="surface-card p-3 shadow-1 border-round">
4
3
 
5
- <ModelView :service="serviceName" :model="modelName" :identifiers="identifiersObject" />
4
+ <ModelView :service="serviceName" :model="modelName" :identifiers="identifiersObject" />
6
5
 
7
- </div>
8
6
  </div>
9
7
  </template>
10
8
 
package/index.js CHANGED
@@ -9,7 +9,20 @@ export { inputConfig }
9
9
 
10
10
  import editorData from './front/src/logic/editorData.js'
11
11
  export { editorData }
12
+
13
+
14
+ import AutoView from './front/src/components/view/AutoView.vue'
15
+ import AutoViewField from './front/src/components/view/AutoViewField.vue'
16
+ import DefaultFieldView from './front/src/components/view/DefaultFieldView.vue'
17
+ import JsonView from './front/src/components/view/JsonView.vue'
18
+ import ObjectView from './front/src/components/view/ObjectView.vue'
19
+ export { AutoView, AutoViewField, DefaultFieldView, JsonView, ObjectView }
20
+
21
+ import provideAutoViewComponents from './front/src/components/view/provideAutoViewComponents.js'
22
+ export { provideAutoViewComponents }
23
+
12
24
  import viewData from './front/src/logic/viewData.js'
25
+ export { viewData }
13
26
 
14
27
  export * from './front/src/logic/relations.js'
15
28
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@live-change/frontend-auto-form",
3
- "version": "0.9.13",
3
+ "version": "0.9.14",
4
4
  "scripts": {
5
5
  "memDev": "node server/start.js memDev --enableSessions --initScript ./init.js --dbAccess",
6
6
  "localDevInit": "rm tmp.db; lcli localDev --enableSessions --initScript ./init.js",
@@ -22,16 +22,16 @@
22
22
  "type": "module",
23
23
  "dependencies": {
24
24
  "@fortawesome/fontawesome-free": "^6.5.2",
25
- "@live-change/cli": "^0.9.13",
26
- "@live-change/dao": "^0.9.13",
27
- "@live-change/dao-vue3": "^0.9.13",
28
- "@live-change/dao-websocket": "^0.9.13",
29
- "@live-change/framework": "^0.9.13",
30
- "@live-change/image-frontend": "^0.9.13",
31
- "@live-change/image-service": "^0.9.13",
32
- "@live-change/session-service": "^0.9.13",
33
- "@live-change/vue3-components": "^0.9.13",
34
- "@live-change/vue3-ssr": "^0.9.13",
25
+ "@live-change/cli": "^0.9.14",
26
+ "@live-change/dao": "^0.9.14",
27
+ "@live-change/dao-vue3": "^0.9.14",
28
+ "@live-change/dao-websocket": "^0.9.14",
29
+ "@live-change/framework": "^0.9.14",
30
+ "@live-change/image-frontend": "^0.9.14",
31
+ "@live-change/image-service": "^0.9.14",
32
+ "@live-change/session-service": "^0.9.14",
33
+ "@live-change/vue3-components": "^0.9.14",
34
+ "@live-change/vue3-ssr": "^0.9.14",
35
35
  "@vueuse/core": "^10.11.0",
36
36
  "codeceptjs-assert": "^0.0.5",
37
37
  "compression": "^1.7.4",
@@ -52,7 +52,7 @@
52
52
  "vue3-scroll-border": "0.1.6"
53
53
  },
54
54
  "devDependencies": {
55
- "@live-change/codeceptjs-helper": "^0.9.13",
55
+ "@live-change/codeceptjs-helper": "^0.9.14",
56
56
  "codeceptjs": "^3.6.5",
57
57
  "generate-password": "1.7.1",
58
58
  "playwright": "1.48.1",
@@ -63,5 +63,5 @@
63
63
  "author": "Michał Łaszczewski <michal@laszczewski.pl>",
64
64
  "license": "ISC",
65
65
  "description": "",
66
- "gitHead": "b0b18e7a8e253195c6df4b25c6bb5c407b1a2450"
66
+ "gitHead": "5d0f137a1a16f892868719d919f4a76584fa879f"
67
67
  }