@live-change/frontend-auto-form 0.9.10 → 0.9.12

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.
@@ -13,7 +13,7 @@
13
13
  </div>
14
14
  </div>
15
15
 
16
- <div class="surface-card p-3 shadow-1 border-round">
16
+ <div class="surface-card p-3 shadow-1 border-round" v-if="modelsPathRangeFunction">
17
17
  <range-viewer :key="JSON.stringify(modelsPathRangeConfig)"
18
18
  :pathFunction="modelsPathRangeFunction"
19
19
  :canLoadTop="false" canDropBottom
@@ -24,13 +24,20 @@
24
24
  </div>
25
25
  </template>
26
26
  <template #default="{ item: object }">
27
- <div class="flex flex-row align-items-center justify-content-between">
28
- <ObjectIdentification
29
- :objectType="service + '_' + model"
30
- :object="object.to ?? object.id"
31
- :data="object"
32
- />
27
+ <div class="flex flex-row align-items-center justify-content-between my-3">
28
+ <router-link :to="viewRoute(object)" class="no-underline text-color">
29
+ <ObjectIdentification
30
+ :objectType="service + '_' + model"
31
+ :object="object.to ?? object.id"
32
+ :data="object"
33
+ class="text-xl"
34
+ />
35
+ </router-link>
33
36
  <div class="flex flex-row">
37
+ <router-link :to="viewRoute(object)" class="no-underline">
38
+ <Button icon="pi pi-eye" severity="primary" label="View" class="mr-2" />
39
+ </router-link>
40
+
34
41
  <router-link :to="editRoute(object)" class="no-underline">
35
42
  <Button icon="pi pi-pencil" severity="primary" label="Edit" class="mr-2" />
36
43
  </router-link>
@@ -41,6 +48,15 @@
41
48
  </template>
42
49
  </range-viewer>
43
50
  </div>
51
+ <div v-else class="flex align-items-start p-4 bg-pink-100 border-round border-1 border-pink-300 mb-4">
52
+ <i class="pi pi-times-circle text-pink-900 text-2xl mr-3" />
53
+ <div class="mr-3">
54
+ <div class="text-pink-900 font-medium text-xl mb-3 line-height-1">Not authorized</div>
55
+ <p class="m-0 p-0 text-pink-700">
56
+ You do not have sufficient privileges to use this feature of this object.
57
+ </p>
58
+ </div>
59
+ </div>
44
60
 
45
61
  <div class="mt-3 flex flex-row justify-content-end mr-2">
46
62
  <router-link :to="createRoute" class="no-underline2">
@@ -48,7 +64,6 @@
48
64
  </router-link>
49
65
  </div>
50
66
 
51
-
52
67
  </div>
53
68
  </template>
54
69
 
@@ -100,7 +115,9 @@
100
115
  const modelsPathRangeFunction = computed(() => {
101
116
  const config = modelsPathRangeConfig.value
102
117
  const rangeView = config.definition?.crud?.range
103
- return (range) => path[config.service][rangeView]({
118
+ if(!path[config.service]) return null
119
+ if(!path[config.service][rangeView]) return null
120
+ return (range) => path[config.service][rangeView]({
104
121
  ...(config.reverse ? reverseRange(range) : range),
105
122
  })
106
123
  })
@@ -132,6 +149,17 @@
132
149
  }
133
150
  }
134
151
 
152
+ function viewRoute(object) {
153
+ return {
154
+ name: 'auto-form:view',
155
+ params: {
156
+ serviceName: service.value,
157
+ modelName: model.value,
158
+ identifiers: Object.values(objectIdentifiers(object))
159
+ }
160
+ }
161
+ }
162
+
135
163
  const createRoute = computed(() => ({
136
164
  name: 'auto-form:editor',
137
165
  params: {
@@ -0,0 +1,98 @@
1
+ <template>
2
+ <div>
3
+ <h4>identifiers</h4>
4
+ <pre>{{ identifiers }}</pre>
5
+
6
+ <h4>definition</h4>
7
+ <pre>{{ modelDefinition }}</pre>
8
+
9
+ <div class="">
10
+ Service <strong>{{ service }}</strong>
11
+ </div>
12
+ <div class="text-2xl mb-4">
13
+ <strong>{{ model }}</strong>
14
+ <ObjectIdentification
15
+ :objectType="service + '_' + model"
16
+ :object="object.to ?? object.id"
17
+ :data="object"
18
+ class="ml-2"
19
+ />
20
+ </div>
21
+
22
+ </div>
23
+ </template>
24
+
25
+ <script setup>
26
+
27
+
28
+ import { ref, computed, onMounted, defineProps, defineEmits, toRefs } from 'vue'
29
+ import { RangeViewer, injectComponent } from "@live-change/vue3-components"
30
+
31
+ const props = defineProps({
32
+ service: {
33
+ type: String,
34
+ required: true,
35
+ },
36
+ model: {
37
+ type: String,
38
+ required: true,
39
+ },
40
+ identifiers: {
41
+ type: Object,
42
+ default: []
43
+ },
44
+ draft: {
45
+ type: Boolean,
46
+ default: false
47
+ },
48
+ options: {
49
+ type: Object,
50
+ default: () => ({})
51
+ },
52
+ i18n: {
53
+ type: String,
54
+ default: ''
55
+ }
56
+ })
57
+ const { service, model, identifiers, draft, options, i18n } = toRefs(props)
58
+
59
+ const emit = defineEmits(['saved', 'draftSaved', 'draftDiscarded', 'saveError', 'created' ])
60
+
61
+
62
+ import AutoObjectIdentification from './AutoObjectIdentification.vue'
63
+ const ObjectIdentification = computed(() =>
64
+ injectComponent({
65
+ name: 'ObjectIdentification',
66
+ type: service.value + '_' + model.value,
67
+ service: service.value,
68
+ model: model.value
69
+ }, AutoObjectIdentification)
70
+ )
71
+
72
+ import { useApi, usePath, live } from '@live-change/vue3-ssr'
73
+ const api = useApi()
74
+ const path = usePath()
75
+
76
+ const modelDefinition = computed(() => {
77
+ return api.services?.[service.value]?.models?.[model.value]
78
+ })
79
+
80
+ import viewData from '../../logic/viewData.js'
81
+
82
+ const viewDataPromise = viewData({
83
+ service: service.value,
84
+ model: model.value,
85
+ identifiers: identifiers.value,
86
+ path, api
87
+ })
88
+
89
+ const [object] = await Promise.all([
90
+ viewDataPromise
91
+ ])
92
+
93
+
94
+ </script>
95
+
96
+ <style scoped>
97
+
98
+ </style>
@@ -0,0 +1,55 @@
1
+ <template>
2
+ <div v-if="definition" class="grid formgrid p-fluid mt-2 mb-2">
3
+ <auto-field-view v-for="property in propertiesList" :key="property"
4
+ :value="value?.[property]"
5
+ :definition="definition.properties[property]"
6
+ :label="property"
7
+ :rootValue="props.rootValue" :propName="(propName ? propName + '.' : '') + property"
8
+ :i18n="i18n"
9
+ class="col-12" />
10
+ </div>
11
+ </template>
12
+
13
+ <script setup>
14
+ //import AutoFieldView from "./AutoFieldView.vue"
15
+
16
+ import { computed, inject, getCurrentInstance, toRefs } from 'vue'
17
+
18
+ const props = defineProps({
19
+ value: {},
20
+ definition: {
21
+ type: Object
22
+ },
23
+ rootValue: {
24
+ type: Object,
25
+ default: () => ({})
26
+ },
27
+ propName: {
28
+ type: String,
29
+ default: ''
30
+ },
31
+ i18n: {
32
+ type: String,
33
+ default: ''
34
+ },
35
+ visibleProperties: {
36
+ type: Array,
37
+ items: {
38
+ type: String
39
+ }
40
+ }
41
+ })
42
+
43
+ const { value, definition, propName, visibleProperties } = toRefs(props)
44
+
45
+ const propertiesList = computed(() =>
46
+ visibleProperties.value ??
47
+ props.definition.visibleProperties ??
48
+ Object.keys(props.definition.properties).filter(key => props.definition.properties[key])
49
+ )
50
+
51
+ </script>
52
+
53
+ <style scoped>
54
+
55
+ </style>
@@ -0,0 +1,34 @@
1
+ import { usePath, live, useApi } from '@live-change/vue3-ssr'
2
+
3
+ export default function viewData(options) {
4
+ if(!options) throw new Error('options must be provided')
5
+
6
+ const {
7
+ identifiers,
8
+ service: serviceName,
9
+ model: modelName,
10
+
11
+ path = usePath(),
12
+ api = useApi(),
13
+ } = options
14
+
15
+ if(!identifiers) throw new Error('identifiers must be defined')
16
+ if(!serviceName || !modelName) throw new Error('service and model must be defined')
17
+
18
+ const service = api.services[serviceName]
19
+ const model = service.models[modelName]
20
+ const {
21
+ crudMethods = model.crud,
22
+ identifiersNames = model.identifiers,
23
+ //editableProperties = model.editableProperties ?? Object.keys(model.properties)
24
+ } = options
25
+
26
+ if(!crudMethods) throw new Error('crud methods must be defined in model or options')
27
+ if(!identifiersNames) throw new Error('identifiers names must be defined in model or options')
28
+ // if(!editableProperties) throw new Error('editableProperties must be defined in model or options')
29
+
30
+ const savedDataPath = path[serviceName][crudMethods.read](identifiers)
31
+
32
+ return live(savedDataPath)
33
+
34
+ }
@@ -13,8 +13,6 @@
13
13
 
14
14
  import ModelEditor from "../components/crud/ModelEditor.vue"
15
15
 
16
-
17
-
18
16
  import { ref, computed, onMounted, defineProps, toRefs } from 'vue'
19
17
 
20
18
  const props = defineProps({
@@ -0,0 +1,62 @@
1
+ <template>
2
+ <div class="w-full lg:w-8 md:w-11">
3
+ <div class="surface-card p-3 shadow-1 border-round">
4
+
5
+ <ModelView :service="serviceName" :model="modelName" :identifiers="identifiersObject" />
6
+
7
+ </div>
8
+ </div>
9
+ </template>
10
+
11
+ <script setup>
12
+
13
+ import ModelView from "../components/crud/ModelView.vue"
14
+
15
+ import { ref, computed, onMounted, defineProps, toRefs } from 'vue'
16
+
17
+ const props = defineProps({
18
+ serviceName: {
19
+ type: String,
20
+ required: true,
21
+ },
22
+ modelName: {
23
+ type: String,
24
+ required: true,
25
+ },
26
+ identifiers: {
27
+ type: Array,
28
+ default: []
29
+ }
30
+ })
31
+ const { serviceName, modelName, identifiers } = toRefs(props)
32
+
33
+ import { useApi, usePath, live } from '@live-change/vue3-ssr'
34
+ const api = useApi()
35
+ const path = usePath()
36
+
37
+ const modelDefinition = computed(() => {
38
+ const service = api.services[serviceName.value]
39
+ if(!service) return null
40
+ const model = service.models[modelName.value]
41
+ if(!model) return null
42
+ return model
43
+ })
44
+
45
+ const identifiersObject = computed(() => {
46
+ const result = {}
47
+ for(const [i, identifier] of Object.entries(identifiers.value)) {
48
+ const identifierDefinition = modelDefinition.value.identifiers[i]
49
+ if(typeof identifierDefinition === 'string') {
50
+ result[identifierDefinition] = identifier
51
+ } else {
52
+ result[identifierDefinition.name] = identifier
53
+ }
54
+ }
55
+ return result
56
+ })
57
+
58
+ </script>
59
+
60
+ <style scoped>
61
+
62
+ </style>
@@ -14,13 +14,18 @@ export function autoFormRoutes(config = {}) {
14
14
  props: true
15
15
  }),
16
16
 
17
+ route({
18
+ name: 'auto-form:view', path: prefix + '/view/:serviceName/:modelName/:identifiers*', meta: { },
19
+ component: () => import("./pages/View.vue"),
20
+ props: true
21
+ }),
22
+
17
23
  route({
18
24
  name: 'auto-form:list', path: prefix + '/models/:serviceName/:modelName', meta: { },
19
25
  component: () => import("./pages/List.vue"),
20
26
  props: true
21
27
  }),
22
28
 
23
-
24
29
  ]
25
30
  }
26
31
 
package/index.js CHANGED
@@ -9,11 +9,20 @@ export { inputConfig }
9
9
 
10
10
  import editorData from './front/src/logic/editorData.js'
11
11
  export { editorData }
12
+ import viewData from './front/src/logic/viewData.js'
12
13
 
13
14
  export * from './front/src/logic/relations.js'
14
15
 
15
16
  import ModelEditor from './front/src/components/crud/ModelEditor.vue'
16
17
  export { ModelEditor }
18
+ import ModelView from './front/src/components/crud/ModelView.vue'
19
+ export { ModelView }
20
+ import ModelList from './front/src/components/crud/ModelList.vue'
21
+ export { ModelList }
22
+ import EditorButtons from './front/src/components/crud/EditorButtons.vue'
23
+ export { EditorButtons }
24
+ import AutoObjectIdentification from './front/src/components/crud/AutoObjectIdentification.vue'
25
+ export { AutoObjectIdentification }
17
26
 
18
27
  export * from './front/src/router.js'
19
28
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@live-change/frontend-auto-form",
3
- "version": "0.9.10",
3
+ "version": "0.9.12",
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.10",
26
- "@live-change/dao": "^0.9.10",
27
- "@live-change/dao-vue3": "^0.9.10",
28
- "@live-change/dao-websocket": "^0.9.10",
29
- "@live-change/framework": "^0.9.10",
30
- "@live-change/image-frontend": "^0.9.10",
31
- "@live-change/image-service": "^0.9.10",
32
- "@live-change/session-service": "^0.9.10",
33
- "@live-change/vue3-components": "^0.9.10",
34
- "@live-change/vue3-ssr": "^0.9.10",
25
+ "@live-change/cli": "^0.9.12",
26
+ "@live-change/dao": "^0.9.12",
27
+ "@live-change/dao-vue3": "^0.9.12",
28
+ "@live-change/dao-websocket": "^0.9.12",
29
+ "@live-change/framework": "^0.9.12",
30
+ "@live-change/image-frontend": "^0.9.12",
31
+ "@live-change/image-service": "^0.9.12",
32
+ "@live-change/session-service": "^0.9.12",
33
+ "@live-change/vue3-components": "^0.9.12",
34
+ "@live-change/vue3-ssr": "^0.9.12",
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.10",
55
+ "@live-change/codeceptjs-helper": "^0.9.12",
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": "d41e404c1933e9ed6e3927d85a5dadf66da0f951"
66
+ "gitHead": "1dba75a1fc90c5b796f7a8dab2895e6085ddce22"
67
67
  }