Skip to content

Commit 4184543

Browse files
committed
Support updating of model
1 parent e1307cc commit 4184543

File tree

9 files changed

+371
-91
lines changed

9 files changed

+371
-91
lines changed

components/modal/baseModel.vue

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<script lang="ts" setup>
2+
import { type FieldEntry } from 'vee-validate';
3+
4+
type SchemaRow = { name: string, type: string, immutable: boolean };
5+
6+
defineProps<{
7+
fields: FieldEntry<SchemaRow>[];
8+
isDisabled: boolean;
9+
}>();
10+
11+
const emit = defineEmits<{
12+
(e: 'remove', idx: number): void;
13+
}>();
14+
15+
const DATA_TYPES = {
16+
boolean: 'Boolean',
17+
float: 'Float',
18+
number: 'Number',
19+
string: 'String',
20+
timestamp: 'Timestamp',
21+
uuid: 'UUID'
22+
};
23+
24+
type DataType = keyof typeof DATA_TYPES;
25+
type Dropdown = { text: string, value: string }[];
26+
27+
const dropdownOptions = computed(() =>
28+
Object.keys(DATA_TYPES).reduce<Dropdown>(
29+
(arr, dataType) => {
30+
const list = arr;
31+
list.push(
32+
{
33+
text: DATA_TYPES[dataType as DataType],
34+
value: dataType,
35+
}
36+
)
37+
38+
return list;
39+
},
40+
[]
41+
)
42+
);
43+
</script>
44+
45+
<template>
46+
<section class="form-control mt-2">
47+
<FormInput
48+
:disabled="isDisabled"
49+
:rules="{ required: 'Name is required.' }"
50+
name="name"
51+
placeholder="Enter name"
52+
/>
53+
</section>
54+
<div class="flex gap-x-2" v-for="(sch, idx) in fields" :key="idx">
55+
<section class="form-control mt-2">
56+
<FormInput
57+
:disabled="isDisabled || sch.value.immutable"
58+
:rules="{ required: 'Name is required.' }"
59+
:name="`schema[${idx}].name`"
60+
placeholder="Enter name"
61+
/>
62+
</section>
63+
<section class="form-control mt-2">
64+
<FormSelect
65+
:disabled="isDisabled || sch.value.immutable"
66+
:name="`schema[${idx}].type`"
67+
:rules="{ required: 'Data type is required.' }"
68+
:options="dropdownOptions"
69+
placeholder="Select the data type"
70+
/>
71+
</section>
72+
<section class="form-control mt-2">
73+
<Button
74+
v-show="sch.value.name !== 'id'"
75+
:disabled="isDisabled"
76+
class="mt-2"
77+
color="error"
78+
size="sm"
79+
@click="emit('remove', idx)"
80+
>
81+
X
82+
</Button>
83+
</section>
84+
</div>
85+
</template>

components/modal/createModel.vue

Lines changed: 6 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -35,35 +35,6 @@
3535
emit('close');
3636
};
3737
38-
const DATA_TYPES = {
39-
boolean: 'Boolean',
40-
float: 'Float',
41-
number: 'Number',
42-
string: 'String',
43-
timestamp: 'Timestamp',
44-
uuid: 'UUID'
45-
};
46-
47-
type DataType = keyof typeof DATA_TYPES;
48-
type Dropdown = { text: string, value: string }[];
49-
50-
const dropdownOptions = computed(() =>
51-
Object.keys(DATA_TYPES).reduce<Dropdown>(
52-
(arr, dataType) => {
53-
const list = arr;
54-
list.push(
55-
{
56-
text: DATA_TYPES[dataType as DataType],
57-
value: dataType,
58-
}
59-
)
60-
61-
return list;
62-
},
63-
[]
64-
)
65-
);
66-
6738
const handleAddSchema = () => {
6839
push(
6940
{ name: '', type: '', immutable: false }
@@ -90,45 +61,11 @@
9061
<ModalBase :id="id" @close="handleClose">
9162
<form @submit="onSubmit">
9263
<h3 class="text-lg font-bold">Create a new Model</h3>
93-
<section class="form-control mt-2">
94-
<FormInput
95-
:disabled="isDisabled"
96-
:rules="{ required: 'Name is required.' }"
97-
name="name"
98-
placeholder="Enter name"
99-
/>
100-
</section>
101-
<div class="flex gap-x-2" v-for="(sch, idx) in fields" :key="idx">
102-
<section class="form-control mt-2">
103-
<FormInput
104-
:disabled="isDisabled || sch.value.immutable"
105-
:rules="{ required: 'Name is required.' }"
106-
:name="`schema[${idx}].name`"
107-
placeholder="Enter name"
108-
/>
109-
</section>
110-
<section class="form-control mt-2">
111-
<FormSelect
112-
:disabled="isDisabled || sch.value.immutable"
113-
:name="`schema[${idx}].type`"
114-
:rules="{ required: 'Data type is required.' }"
115-
:options="dropdownOptions"
116-
placeholder="Select the data type"
117-
/>
118-
</section>
119-
<section class="form-control mt-2">
120-
<Button
121-
v-show="!sch.value.immutable"
122-
:disabled="isDisabled"
123-
class="mt-2"
124-
color="error"
125-
size="sm"
126-
@click="remove(idx)"
127-
>
128-
X
129-
</Button>
130-
</section>
131-
</div>
64+
<ModalBaseModel
65+
:is-disabled="form.isSubmitting.value"
66+
:fields="fields"
67+
@remove="remove"
68+
/>
13269
<Button
13370
:disabled="isDisabled"
13471
class="mt-2"
@@ -138,20 +75,7 @@
13875
>
13976
Add field
14077
</Button>
141-
<section class="mt-10">
142-
<Button :disabled="isDisabled" size="sm" @click="handleClose">
143-
Cancel
144-
</Button>
145-
<Button
146-
:loading="isDisabled"
147-
class="float-right"
148-
color="success"
149-
size="sm"
150-
type="submit"
151-
>
152-
Proceed
153-
</Button>
154-
</section>
78+
<ModalFooter :disabled="isDisabled" @close="handleClose()" />
15579
</form>
15680
</ModalBase>
15781
</template>

components/modal/editModel.vue

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<script lang="ts" setup>
2+
import useModel from '~~/stores/useModel';
3+
4+
const emit = defineEmits<{
5+
(e: 'close'): void;
6+
(e: 'success'): void;
7+
}>();
8+
9+
defineProps<{
10+
id: string;
11+
}>();
12+
13+
const model = useModel();
14+
15+
type SchemaRow = { name: string, type: string, immutable: boolean };
16+
const defaultSchema = model.target?.schema
17+
? model.target?.schema?.map((sch) => ({
18+
name: sch.name,
19+
type: sch.type,
20+
immutable: true,
21+
}))
22+
: [{ name: 'id', type: 'uuid', immutable: true }];
23+
24+
const form = useForm({
25+
initialValues: {
26+
name: model.target?.name ?? '',
27+
schema: defaultSchema,
28+
}
29+
});
30+
const isDisabled = computed(() => form.isSubmitting.value === true);
31+
32+
const { remove, push, fields } = useFieldArray<SchemaRow>('schema');
33+
34+
const handleClose = () => {
35+
form.resetForm();
36+
37+
const length = fields.value.length;
38+
for (let i = 1; i <= length; i++) {
39+
remove(i);
40+
}
41+
42+
emit('close');
43+
};
44+
45+
const handleAddSchema = () => {
46+
push(
47+
{ name: '', type: '', immutable: false }
48+
);
49+
};
50+
51+
const onSubmit = form.handleSubmit(async (values) => {
52+
await model.update(
53+
{
54+
name: values.name,
55+
schema: values.schema,
56+
},
57+
{
58+
onSuccess: (updated) => {
59+
if (updated) {
60+
model.setTarget(updated);
61+
}
62+
63+
emit('success');
64+
handleClose();
65+
},
66+
}
67+
);
68+
});
69+
</script>
70+
71+
<template>
72+
<ModalBase :id="id" @close="handleClose">
73+
<form @submit="onSubmit">
74+
<h3 class="text-lg font-bold">Edit the Model</h3>
75+
<ModalBaseModel
76+
:is-disabled="form.isSubmitting.value"
77+
:fields="fields"
78+
@remove="remove"
79+
/>
80+
<Button
81+
:disabled="isDisabled"
82+
class="mt-2"
83+
color="success"
84+
size="sm"
85+
@click="handleAddSchema()"
86+
>
87+
Add field
88+
</Button>
89+
<ModalFooter :disabled="isDisabled" @close="handleClose()" />
90+
</form>
91+
</ModalBase>
92+
</template>

components/model/grid.vue

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { Cog6ToothIcon } from '@heroicons/vue/24/outline';
33
import { NormalizedModel } from '~~/types/models';
44
import useModel from '~~/stores/useModel';
5+
import ModalEditModel from '../modal/editModel.vue';
56
import ModalConfirm from '~~/components/modal/confirm.vue';
67
78
const model = useModel();
@@ -18,16 +19,21 @@
1819
model.setTarget(md);
1920
};
2021
22+
const editModelModal = useModal(ModalEditModel, {
23+
id: 'edit-model',
24+
});
25+
2126
const deleteModelModal = useModal(ModalConfirm, {
2227
id: 'confirm-delete-model',
2328
onConfirm: async (closeModal) => {
2429
const deleteId = model.target?.id;
2530
26-
await model.delete(deleteId);
31+
if (deleteId) {
32+
await model.delete(deleteId);
33+
model.unsetTarget();
34+
}
2735
2836
closeModal();
29-
30-
model.unsetTarget();
3137
},
3238
});
3339
</script>
@@ -46,7 +52,9 @@
4652
<Cog6ToothIcon class="h-4 w-4" />
4753
</template>
4854
<template #options>
49-
<DropdownOption>Edit</DropdownOption>
55+
<DropdownOption @click="editModelModal.open()">
56+
Edit
57+
</DropdownOption>
5058
<DropdownOption @click="deleteModelModal.open()">
5159
Delete
5260
</DropdownOption>
@@ -72,6 +80,7 @@
7280
</a>
7381
</div>
7482
<ClientOnly>
83+
<component :is="editModelModal.component" />
7584
<component
7685
:is="deleteModelModal.component"
7786
content="Are you sure you want to delete this model?"

components/model/table.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
const modelData = useModelData();
1212
const select = useSelect();
1313
14-
const createModelDataModal = useModal(ModalCreateModelData, { id: 'create-model-data' });
14+
const createModelDataModal = useModal(ModalCreateModelData, {id: 'create-model-data' });
1515
1616
const deleteModelDataModal = useModal(ModalConfirm, {
1717
id: 'confirm-delete-model-data',

server/routes/models.post.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export default defineEventHandler(async (event) => {
1111
const body: BodyParams = await readBody<BodyParams>(event);
1212
const { appId } = await extractAppKey(event, body.apiKey);
1313

14-
const created = await new ModelServices(event).create({
14+
const created = await new ModelServices(event).createUnique({
1515
appId,
1616
name: body.name,
1717
schema: body.schema,

server/routes/models/[id].put.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import ModelServices from '../../services/modelServices';
2+
import extractAppKey from '~~/server/lib/extractAppKey';
3+
4+
type BodyParams = {
5+
name: string;
6+
schema: { name: string; type: string }[];
7+
apiKey: string;
8+
};
9+
10+
export default defineEventHandler(async (event) => {
11+
const body: BodyParams = await readBody<BodyParams>(event);
12+
const { appId } = await extractAppKey(event, body.apiKey);
13+
const modelId = event.context.params?.id ?? '';
14+
15+
const updated = await new ModelServices(event).updateUnique({
16+
id: modelId,
17+
appId,
18+
name: body.name,
19+
schema: body.schema,
20+
});
21+
22+
return updated;
23+
});

0 commit comments

Comments
 (0)