@vue-skuilder/edit-ui 0.1.1

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.
Files changed (28) hide show
  1. package/dist/assets/index.css +1 -0
  2. package/dist/edit-ui.es.js +71090 -0
  3. package/dist/edit-ui.es.js.map +1 -0
  4. package/dist/edit-ui.umd.js +83 -0
  5. package/dist/edit-ui.umd.js.map +1 -0
  6. package/package.json +67 -0
  7. package/src/components/BulkImport/CardPreviewList.vue +345 -0
  8. package/src/components/BulkImportView.vue +633 -0
  9. package/src/components/CourseEditor.vue +164 -0
  10. package/src/components/ViewableDataInputForm/DataInputForm.vue +533 -0
  11. package/src/components/ViewableDataInputForm/FieldInput.types.ts +33 -0
  12. package/src/components/ViewableDataInputForm/FieldInputs/AudioInput.vue +188 -0
  13. package/src/components/ViewableDataInputForm/FieldInputs/ChessPuzzleInput.vue +79 -0
  14. package/src/components/ViewableDataInputForm/FieldInputs/FieldInput.css +12 -0
  15. package/src/components/ViewableDataInputForm/FieldInputs/ImageInput.vue +231 -0
  16. package/src/components/ViewableDataInputForm/FieldInputs/IntegerInput.vue +49 -0
  17. package/src/components/ViewableDataInputForm/FieldInputs/MarkdownInput.vue +34 -0
  18. package/src/components/ViewableDataInputForm/FieldInputs/MediaDragDropUploader.vue +246 -0
  19. package/src/components/ViewableDataInputForm/FieldInputs/MidiInput.vue +113 -0
  20. package/src/components/ViewableDataInputForm/FieldInputs/NumberInput.vue +49 -0
  21. package/src/components/ViewableDataInputForm/FieldInputs/OptionsFieldInput.ts +161 -0
  22. package/src/components/ViewableDataInputForm/FieldInputs/StringInput.vue +49 -0
  23. package/src/components/ViewableDataInputForm/FieldInputs/typeValidators.ts +49 -0
  24. package/src/components/index.ts +21 -0
  25. package/src/index.ts +6 -0
  26. package/src/stores/useDataInputFormStore.ts +49 -0
  27. package/src/stores/useFieldInputStore.ts +191 -0
  28. package/src/vue-shims.d.ts +5 -0
@@ -0,0 +1,49 @@
1
+ import { defineStore } from 'pinia';
2
+ import { DataShape } from '@vue-skuilder/common';
3
+ import { CourseConfig } from '@vue-skuilder/common';
4
+ import { FieldInputInstance } from '../components/ViewableDataInputForm/FieldInput.types';
5
+ import { useFieldInputStore } from './useFieldInputStore';
6
+ import { ViewComponent } from '@vue-skuilder/common-ui';
7
+
8
+ interface DataInputForm {
9
+ // current props
10
+ dataShape: DataShape | null;
11
+ course: CourseConfig | null;
12
+
13
+ shapeViews: ViewComponent[];
14
+ fields: FieldInputInstance[];
15
+
16
+ fieldStore: ReturnType<typeof useFieldInputStore>;
17
+
18
+ uploading: boolean;
19
+ }
20
+
21
+ export interface DataInputFormState {
22
+ dataInputForm: DataInputForm;
23
+ }
24
+
25
+ export const useDataInputFormStore = defineStore('dataInputForm', {
26
+ state: (): DataInputFormState => ({
27
+ dataInputForm: {
28
+ dataShape: null,
29
+ course: null,
30
+ shapeViews: [],
31
+
32
+ fields: [],
33
+ fieldStore: useFieldInputStore(),
34
+ uploading: false,
35
+ },
36
+ }),
37
+ // actions or getters if needed
38
+ actions: {
39
+ setDataShape(ds: DataShape) {
40
+ this.dataInputForm.dataShape = ds;
41
+ this.dataInputForm.fieldStore.dataShape = ds;
42
+ this.dataInputForm.fieldStore.$reset();
43
+ },
44
+ setCourse(course: CourseConfig) {
45
+ this.dataInputForm.course = course;
46
+ },
47
+ // etc. create any convenience setters or methods you wish
48
+ },
49
+ });
@@ -0,0 +1,191 @@
1
+ import { DataShape, FieldType, Status, fieldConverters } from '@vue-skuilder/common';
2
+ import { defineStore } from 'pinia';
3
+
4
+ export interface MediaInputs {
5
+ [key: `audio-${number}`]: unknown;
6
+ [key: `image-${number}`]: unknown;
7
+ }
8
+
9
+ export interface FieldInputStore {
10
+ // [key: string]: unknown;
11
+
12
+ // // Raw field values by field name
13
+ //
14
+ //
15
+
16
+ /**
17
+ * The
18
+ */
19
+ dataShape: DataShape | null;
20
+
21
+ /**
22
+ * Raw input field values by field name - the user-edited submissions
23
+ */
24
+ inputs: Record<string, unknown>;
25
+
26
+ /**
27
+ * additions from the MediaDragDrop editor.
28
+ */
29
+ mediaInputs: MediaInputs;
30
+
31
+ inputIsValid: boolean;
32
+
33
+ /**
34
+ * Validation status of each field - all must be true for the form to be valid and the data to be submissable
35
+ */
36
+ validation: Record<string, boolean>;
37
+ /**
38
+ * Input prepared for sending to the database
39
+ */
40
+ convertedInput: Record<string, unknown>;
41
+ /**
42
+ * Input prepared for local rendering in a preview
43
+ */
44
+ previewInput: Record<string, unknown>;
45
+
46
+ // getFieldValue(fieldName: string): unknown;
47
+ }
48
+
49
+ export const useFieldInputStore = defineStore('fieldStore', {
50
+ state: (): FieldInputStore => ({
51
+ dataShape: null as DataShape | null,
52
+ inputs: {},
53
+ mediaInputs: {} as MediaInputs,
54
+ inputIsValid: false,
55
+
56
+ validation: {},
57
+ convertedInput: {},
58
+ previewInput: {},
59
+ }),
60
+
61
+ getters: {
62
+ isValidated(): boolean {
63
+ return this.inputIsValid;
64
+ },
65
+
66
+ getPreview: (state) => {
67
+ if (state.inputIsValid) return state.previewInput;
68
+ else return {};
69
+ },
70
+ getConverted: (state) => {
71
+ if (state.inputIsValid) return state.convertedInput;
72
+ else return {};
73
+ },
74
+ },
75
+
76
+ actions: {
77
+ $reset() {
78
+ console.log(`[FieldInputStore].reset()`);
79
+ this.inputs = {};
80
+ this.mediaInputs = {};
81
+ this.validation = {};
82
+ this.convertedInput = {};
83
+ this.previewInput = {};
84
+ this.inputIsValid = false;
85
+
86
+ // Clear all media entries
87
+ const MAX_MEDIA_INPUTS = 10;
88
+ for (let i = 1; i <= MAX_MEDIA_INPUTS; i++) {
89
+ const audioKey = `audio-${i}` as keyof MediaInputs;
90
+ const imageKey = `image-${i}` as keyof MediaInputs;
91
+
92
+ delete this.mediaInputs[audioKey];
93
+ delete this.mediaInputs[imageKey];
94
+ }
95
+ },
96
+
97
+ setFieldValue(fieldName: string, value: unknown) {
98
+ this.inputs[fieldName] = value;
99
+ this.validate();
100
+ this.convert();
101
+ },
102
+
103
+ setMedia(
104
+ fieldName: keyof MediaInputs,
105
+ media: {
106
+ content_type: string;
107
+ data: Blob;
108
+ }
109
+ ) {
110
+ console.log(`[FieldInputStore].setMedia: ${fieldName}`);
111
+ this.mediaInputs[fieldName] = media;
112
+ this.convert();
113
+ },
114
+
115
+ validate() {
116
+ this.validation = {};
117
+
118
+ if (this.dataShape === null) {
119
+ this.inputIsValid = false;
120
+ return;
121
+ }
122
+
123
+ this.inputIsValid = true;
124
+
125
+ for (const field of this.dataShape.fields) {
126
+ if (field.validator) {
127
+ const result = field.validator.test(this.inputs[field.name] as unknown as string);
128
+ if (result.status === Status.ok) {
129
+ this.validation[field.name] = true;
130
+ } else {
131
+ this.inputIsValid = false;
132
+ this.validation[field.name] = false;
133
+ }
134
+ }
135
+ }
136
+ },
137
+
138
+ convert() {
139
+ this.convertedInput = {};
140
+
141
+ this.dataShape?.fields.forEach((f) => {
142
+ this.convertedInput[f.name] = fieldConverters[f.type].databaseConverter(
143
+ this.inputs[f.name]
144
+ );
145
+ this.previewInput[f.name] = fieldConverters[f.type].previewConverter(this.inputs[f.name]);
146
+ });
147
+
148
+ // Check for media entries
149
+ for (let i = 1; i < 11; i++) {
150
+ const index = `audio-${i}` as keyof MediaInputs;
151
+ const value = this.mediaInputs[index];
152
+ if (value) {
153
+ this.convertedInput[index] = fieldConverters[FieldType.AUDIO].databaseConverter(value);
154
+ this.previewInput[index] = fieldConverters[FieldType.AUDIO].previewConverter(value);
155
+ } else {
156
+ break;
157
+ }
158
+ }
159
+
160
+ for (let i = 1; i < 11; i++) {
161
+ const index = `image-${i}` as keyof MediaInputs;
162
+ const value = this.mediaInputs[index];
163
+ if (value) {
164
+ this.convertedInput[index] = fieldConverters[FieldType.IMAGE].databaseConverter(value);
165
+ this.previewInput[index] = fieldConverters[FieldType.IMAGE].previewConverter(value);
166
+ } else {
167
+ break;
168
+ }
169
+ }
170
+ },
171
+
172
+ clearMediaEntries() {
173
+ // Clear all media entries up to a reasonable limit
174
+ for (let i = 1; i <= 10; i++) {
175
+ delete this.mediaInputs[`audio-${i}`];
176
+ delete this.mediaInputs[`image-${i}`];
177
+ delete this.convertedInput[`audio-${i}`];
178
+ delete this.convertedInput[`image-${i}`];
179
+ delete this.previewInput[`audio-${i}`];
180
+ delete this.previewInput[`image-${i}`];
181
+ }
182
+ },
183
+
184
+ clearField(fieldName: string) {
185
+ delete this.inputs[fieldName];
186
+ delete this.validation[fieldName];
187
+ delete this.convertedInput[fieldName];
188
+ delete this.previewInput[fieldName];
189
+ },
190
+ },
191
+ });
@@ -0,0 +1,5 @@
1
+ declare module '*.vue' {
2
+ import type { DefineComponent } from 'vue'
3
+ const component: DefineComponent<{}, {}, any>
4
+ export default component
5
+ }