nextjs-cms 0.6.6 → 0.6.8
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/api/lib/serverActions.js +8 -8
- package/dist/api/routers/accountSettings.js +4 -4
- package/dist/api/trpc.js +1 -1
- package/dist/auth/lib/actions.d.ts.map +1 -1
- package/dist/auth/lib/actions.js +6 -5
- package/dist/core/config/config-loader.d.ts +4 -4
- package/dist/core/config/config-loader.d.ts.map +1 -1
- package/dist/core/config/config-loader.js +6 -5
- package/dist/core/factories/FieldFactory.d.ts.map +1 -1
- package/dist/core/factories/FieldFactory.js +10 -1
- package/dist/core/fields/color.d.ts.map +1 -1
- package/dist/core/fields/color.js +3 -2
- package/dist/core/fields/date.d.ts.map +1 -1
- package/dist/core/fields/date.js +3 -2
- package/dist/core/fields/document.d.ts.map +1 -1
- package/dist/core/fields/document.js +14 -13
- package/dist/core/fields/field-group.d.ts +3 -2
- package/dist/core/fields/field-group.d.ts.map +1 -1
- package/dist/core/fields/field.d.ts +6 -2
- package/dist/core/fields/field.d.ts.map +1 -1
- package/dist/core/fields/field.js +12 -0
- package/dist/core/fields/index.d.ts +1 -1
- package/dist/core/fields/index.d.ts.map +1 -1
- package/dist/core/fields/map.d.ts.map +1 -1
- package/dist/core/fields/map.js +3 -2
- package/dist/core/fields/number.d.ts.map +1 -1
- package/dist/core/fields/number.js +8 -7
- package/dist/core/fields/password.d.ts.map +1 -1
- package/dist/core/fields/password.js +5 -4
- package/dist/core/fields/photo.d.ts +6 -6
- package/dist/core/fields/photo.d.ts.map +1 -1
- package/dist/core/fields/photo.js +18 -17
- package/dist/core/fields/richText.d.ts +9 -9
- package/dist/core/fields/select.js +3 -3
- package/dist/core/fields/slug.d.ts +4 -21
- package/dist/core/fields/slug.d.ts.map +1 -1
- package/dist/core/fields/slug.js +8 -50
- package/dist/core/fields/text.d.ts.map +1 -1
- package/dist/core/fields/text.js +4 -3
- package/dist/core/fields/video.d.ts.map +1 -1
- package/dist/core/fields/video.js +13 -12
- package/dist/core/sections/category.d.ts +4 -4
- package/dist/core/sections/category.js +3 -3
- package/dist/core/sections/hasItems.d.ts +10 -10
- package/dist/core/sections/section.d.ts +2 -2
- package/dist/core/sections/simple.d.ts +4 -4
- package/dist/core/submit/ItemEditSubmit.d.ts +6 -0
- package/dist/core/submit/ItemEditSubmit.d.ts.map +1 -1
- package/dist/core/submit/ItemEditSubmit.js +8 -0
- package/dist/core/submit/submit.d.ts +25 -5
- package/dist/core/submit/submit.d.ts.map +1 -1
- package/dist/core/submit/submit.js +119 -21
- package/dist/translations/dictionaries/ar.d.ts +68 -0
- package/dist/translations/dictionaries/ar.d.ts.map +1 -1
- package/dist/translations/dictionaries/ar.js +81 -0
- package/dist/translations/dictionaries/en.d.ts +68 -0
- package/dist/translations/dictionaries/en.d.ts.map +1 -1
- package/dist/translations/dictionaries/en.js +81 -0
- package/dist/translations/index.d.ts +3 -2
- package/dist/translations/index.d.ts.map +1 -1
- package/dist/translations/index.js +11 -3
- package/dist/validators/checkbox.d.ts +1 -1
- package/dist/validators/checkbox.d.ts.map +1 -1
- package/dist/validators/checkbox.js +7 -3
- package/dist/validators/color.d.ts +1 -1
- package/dist/validators/color.d.ts.map +1 -1
- package/dist/validators/color.js +6 -4
- package/dist/validators/date.d.ts +1 -1
- package/dist/validators/date.d.ts.map +1 -1
- package/dist/validators/date.js +5 -3
- package/dist/validators/document.d.ts +1 -1
- package/dist/validators/document.d.ts.map +1 -1
- package/dist/validators/document.js +10 -8
- package/dist/validators/index.d.ts +7 -7
- package/dist/validators/index.d.ts.map +1 -1
- package/dist/validators/index.js +7 -7
- package/dist/validators/map.d.ts +1 -1
- package/dist/validators/map.d.ts.map +1 -1
- package/dist/validators/map.js +7 -3
- package/dist/validators/number.d.ts +1 -1
- package/dist/validators/number.d.ts.map +1 -1
- package/dist/validators/number.js +19 -10
- package/dist/validators/password.d.ts +1 -1
- package/dist/validators/password.d.ts.map +1 -1
- package/dist/validators/password.js +13 -5
- package/dist/validators/photo.d.ts +1 -1
- package/dist/validators/photo.d.ts.map +1 -1
- package/dist/validators/photo.js +15 -13
- package/dist/validators/richText.d.ts +1 -1
- package/dist/validators/richText.d.ts.map +1 -1
- package/dist/validators/richText.js +14 -6
- package/dist/validators/select-multiple.d.ts +1 -1
- package/dist/validators/select-multiple.d.ts.map +1 -1
- package/dist/validators/select-multiple.js +8 -6
- package/dist/validators/select.d.ts +1 -1
- package/dist/validators/select.d.ts.map +1 -1
- package/dist/validators/select.js +8 -3
- package/dist/validators/slug.d.ts +1 -1
- package/dist/validators/slug.d.ts.map +1 -1
- package/dist/validators/slug.js +14 -8
- package/dist/validators/text.d.ts +1 -1
- package/dist/validators/text.d.ts.map +1 -1
- package/dist/validators/text.js +13 -3
- package/dist/validators/textarea.d.ts +1 -1
- package/dist/validators/textarea.d.ts.map +1 -1
- package/dist/validators/textarea.js +13 -3
- package/dist/validators/types.d.ts +7 -0
- package/dist/validators/types.d.ts.map +1 -0
- package/dist/validators/types.js +0 -0
- package/dist/validators/video.d.ts +1 -1
- package/dist/validators/video.d.ts.map +1 -1
- package/dist/validators/video.js +10 -8
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"video.d.ts","sourceRoot":"","sources":["../../../src/core/fields/video.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAIhD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE1C,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"video.d.ts","sourceRoot":"","sources":["../../../src/core/fields/video.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAIhD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE1C,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAGxB,QAAA,MAAM,YAAY;IACd;;OAEG;;;;;;;;IAQH;;;OAGG;;;;;;kBAKL,CAAA;AAEF,KAAK,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAA;AAE1C,qBAAa,UAAW,SAAQ,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IACtD,gBAAyB,CAAC,UAAU,CAAC,EAAE,MAAM,CAAe;IAC5D,QAAQ,CAAC,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;KAAE,CAAA;IACzD,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAA;IAE7B;;;OAGG;IACH,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,kBAAkB,CAAU;gBACxB,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI;IA6BxC,eAAe;;kBAzCD,MAAM;kBAAQ,IAAI,GAAG,IAAI;;;;;;;;;;;;;IAkDjD,iBAAiB,CAAC,EACpB,WAAW,EACX,MAAM,EACN,aAAiB,GACpB,EAAE;QACC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;QACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;QACvB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAClC,GAAG,OAAO,CAAC,UAAU,CAAC;IAgBvB;;OAEG;IACG,WAAW;IA2BK,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKzC,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IAanC,mBAAmB,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMpG;;OAEG;IACH,QAAQ,IAAI,MAAM;IAIX,WAAW,CAAC,KAAK,EAAE,MAAM;IAIvB,QAAQ,CAAC,KAAK,EAAE,GAAG;IAQnB,OAAO,CAAC,IAAI,EAAE,IAAI;IAK3B,aAAa;IAYb;;OAEG;IACG,oBAAoB;CAoD7B;AAED,MAAM,MAAM,sBAAsB,GAAG,UAAU,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAA;AAE9E,QAAA,MAAM,aAAa;IAvPf;;OAEG;;;;;;;;IAQH;;;OAGG;;;;;;;;;;;;;kBA6OL,CAAA;AAEF,QAAA,MAAM,sBAAsB;;;IA5PxB;;OAEG;;;;;;;;IAQH;;;OAGG;;;;;;;;;;;;;kBAmPL,CAAA;AAEF;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAErE;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,GAAG,gBAAgB,CAmBjF"}
|
|
@@ -6,6 +6,7 @@ import path from 'path';
|
|
|
6
6
|
import { FileField } from './fileField.js';
|
|
7
7
|
import { getCMSConfig } from '../config/index.js';
|
|
8
8
|
import * as z from 'zod';
|
|
9
|
+
import getString from '../../translations/index.js';
|
|
9
10
|
const configSchema = z.strictObject({
|
|
10
11
|
/**
|
|
11
12
|
* Maximum file size
|
|
@@ -75,13 +76,13 @@ export class VideoField extends FileField {
|
|
|
75
76
|
}
|
|
76
77
|
async readChunkFromFile({ arrayBuffer, length, startPosition = 0, }) {
|
|
77
78
|
if (!arrayBuffer) {
|
|
78
|
-
throw new Error('
|
|
79
|
+
throw new Error(getString('errorReadingFile', this.locale));
|
|
79
80
|
}
|
|
80
81
|
const buffer = new Uint8Array(arrayBuffer);
|
|
81
82
|
const start = Math.max(0, startPosition);
|
|
82
83
|
const end = Math.min(start + length, buffer.length);
|
|
83
84
|
if (start >= end) {
|
|
84
|
-
throw new Error('
|
|
85
|
+
throw new Error(getString('errorReadingFile', this.locale));
|
|
85
86
|
}
|
|
86
87
|
return buffer.subarray(start, end);
|
|
87
88
|
}
|
|
@@ -90,10 +91,10 @@ export class VideoField extends FileField {
|
|
|
90
91
|
*/
|
|
91
92
|
async writeToFile() {
|
|
92
93
|
if (!this._folder) {
|
|
93
|
-
throw new Error(
|
|
94
|
+
throw new Error(getString('videoFolderNotSet', this.locale, { field: this.getLocalizedLabel() }));
|
|
94
95
|
}
|
|
95
96
|
if (!this._buffer) {
|
|
96
|
-
throw new Error(
|
|
97
|
+
throw new Error(getString('videoBufferNotSet', this.locale, { field: this.getLocalizedLabel() }));
|
|
97
98
|
}
|
|
98
99
|
try {
|
|
99
100
|
/**
|
|
@@ -110,7 +111,7 @@ export class VideoField extends FileField {
|
|
|
110
111
|
await fs.promises.writeFile(path.join(uploadsFolder, '.videos', this._folder, this.value), this._buffer);
|
|
111
112
|
}
|
|
112
113
|
catch (error) {
|
|
113
|
-
throw new Error(
|
|
114
|
+
throw new Error(getString('videoWriteError', this.locale, { field: this.getLocalizedLabel() }) + ` ${error.message}`);
|
|
114
115
|
}
|
|
115
116
|
}
|
|
116
117
|
async postSubmit(folder) {
|
|
@@ -119,7 +120,7 @@ export class VideoField extends FileField {
|
|
|
119
120
|
}
|
|
120
121
|
async postSubmitRollback() {
|
|
121
122
|
if (!this._folder) {
|
|
122
|
-
throw new Error(
|
|
123
|
+
throw new Error(getString('videoFolderNotSet', this.locale, { field: this.getLocalizedLabel() }));
|
|
123
124
|
}
|
|
124
125
|
try {
|
|
125
126
|
const uploadsFolder = (await getCMSConfig()).media.upload.path;
|
|
@@ -127,7 +128,7 @@ export class VideoField extends FileField {
|
|
|
127
128
|
await fs.promises.unlink(pathToFile);
|
|
128
129
|
}
|
|
129
130
|
catch (error) {
|
|
130
|
-
throw new Error(
|
|
131
|
+
throw new Error(getString('fileDeleteError', this.locale, { field: this.getLocalizedLabel() }));
|
|
131
132
|
}
|
|
132
133
|
}
|
|
133
134
|
async cleanupReplacedFile(previousValue, sectionName) {
|
|
@@ -165,7 +166,7 @@ export class VideoField extends FileField {
|
|
|
165
166
|
* Note: Those values are coming from the browser (not safe)
|
|
166
167
|
*/
|
|
167
168
|
if ((this.required && !this._file) || !this._file?.type || !this._file?.name || !this._file?.size) {
|
|
168
|
-
throw new Error(
|
|
169
|
+
throw new Error(getString('fieldIsRequired', this.locale, { field: this.getLocalizedLabel() }));
|
|
169
170
|
}
|
|
170
171
|
}
|
|
171
172
|
/**
|
|
@@ -180,14 +181,14 @@ export class VideoField extends FileField {
|
|
|
180
181
|
const arrayBuffer = await this._file.arrayBuffer();
|
|
181
182
|
this._buffer = Buffer.from(arrayBuffer);
|
|
182
183
|
if (!this._buffer.length) {
|
|
183
|
-
throw new Error(
|
|
184
|
+
throw new Error(getString('fieldIsRequired', this.locale, { field: this.getLocalizedLabel() }));
|
|
184
185
|
}
|
|
185
186
|
/**
|
|
186
187
|
* Check extension
|
|
187
188
|
*/
|
|
188
189
|
const ext = this._file.name.split('.').pop();
|
|
189
190
|
if (!ext || !this.extensions.includes(ext)) {
|
|
190
|
-
throw new Error(
|
|
191
|
+
throw new Error(getString('invalidFileTypeOrExtension', this.locale, { field: this.getLocalizedLabel(), extensions: this.extensions.join(', ') }));
|
|
191
192
|
}
|
|
192
193
|
/**
|
|
193
194
|
* Read the first 4100 bytes of the file
|
|
@@ -202,14 +203,14 @@ export class VideoField extends FileField {
|
|
|
202
203
|
* If the file type is invalid, return an error
|
|
203
204
|
*/
|
|
204
205
|
if (!fileType) {
|
|
205
|
-
throw new Error(
|
|
206
|
+
throw new Error(getString('invalidDocumentFileType', this.locale, { field: this.getLocalizedLabel() }));
|
|
206
207
|
}
|
|
207
208
|
/**
|
|
208
209
|
* Don't just trust the file extension
|
|
209
210
|
* Check the `fileType.ext` against the allowed extensions
|
|
210
211
|
*/
|
|
211
212
|
if (!fileType.ext || !this.extensions.includes(fileType.ext)) {
|
|
212
|
-
throw new Error(
|
|
213
|
+
throw new Error(getString('invalidFileTypeOrExtension', this.locale, { field: this.getLocalizedLabel(), extensions: this.extensions.join(', ') }));
|
|
213
214
|
}
|
|
214
215
|
/**
|
|
215
216
|
* Generate a random name for the file
|
|
@@ -119,9 +119,8 @@ declare const optionsSchema: z.ZodObject<{
|
|
|
119
119
|
allowRecursiveDelete: z.ZodOptional<z.ZodBoolean>;
|
|
120
120
|
fields: z.ZodUnion<[z.ZodArray<z.ZodCustom<FieldConfig, FieldConfig>>, z.ZodArray<z.ZodCustom<FieldGroupConfig, FieldGroupConfig>>]>;
|
|
121
121
|
readonly: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
122
|
-
name: z.ZodString;
|
|
123
|
-
order: z.ZodNumber;
|
|
124
122
|
icon: z.ZodOptional<z.ZodString>;
|
|
123
|
+
name: z.ZodString;
|
|
125
124
|
db: z.ZodObject<{
|
|
126
125
|
table: z.ZodString;
|
|
127
126
|
identifier: z.ZodOptional<z.ZodCustom<FieldConfig, FieldConfig>>;
|
|
@@ -146,6 +145,7 @@ declare const optionsSchema: z.ZodObject<{
|
|
|
146
145
|
}, z.core.$strict>>>;
|
|
147
146
|
}, z.core.$strict>;
|
|
148
147
|
variants: z.ZodOptional<z.ZodArray<z.ZodCustom<import("../types/index.js").Variant, import("../types/index.js").Variant>>>;
|
|
148
|
+
order: z.ZodNumber;
|
|
149
149
|
gallery: z.ZodOptional<z.ZodObject<{
|
|
150
150
|
db: z.ZodObject<{
|
|
151
151
|
tableName: z.ZodString;
|
|
@@ -216,9 +216,8 @@ export declare const categorySectionConfigSchema: z.ZodObject<{
|
|
|
216
216
|
*/
|
|
217
217
|
allowRecursiveDelete: z.ZodOptional<z.ZodBoolean>;
|
|
218
218
|
readonly: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
219
|
-
name: z.ZodString;
|
|
220
|
-
order: z.ZodNumber;
|
|
221
219
|
icon: z.ZodOptional<z.ZodString>;
|
|
220
|
+
name: z.ZodString;
|
|
222
221
|
db: z.ZodObject<{
|
|
223
222
|
table: z.ZodString;
|
|
224
223
|
identifier: z.ZodOptional<z.ZodCustom<FieldConfig, FieldConfig>>;
|
|
@@ -243,6 +242,7 @@ export declare const categorySectionConfigSchema: z.ZodObject<{
|
|
|
243
242
|
}, z.core.$strict>>>;
|
|
244
243
|
}, z.core.$strict>;
|
|
245
244
|
variants: z.ZodOptional<z.ZodArray<z.ZodCustom<import("../types/index.js").Variant, import("../types/index.js").Variant>>>;
|
|
245
|
+
order: z.ZodNumber;
|
|
246
246
|
gallery: z.ZodOptional<z.ZodObject<{
|
|
247
247
|
db: z.ZodObject<{
|
|
248
248
|
tableName: z.ZodString;
|
|
@@ -57,14 +57,14 @@ export class CategorySection extends Section {
|
|
|
57
57
|
if (this.depth > 1) {
|
|
58
58
|
const levelConfig = numberField({
|
|
59
59
|
name: 'level',
|
|
60
|
-
label: 'Level',
|
|
60
|
+
label: { en: 'Level', ar: 'المستوى' },
|
|
61
61
|
required: false,
|
|
62
62
|
order: 0,
|
|
63
63
|
});
|
|
64
64
|
if (this.db.identifier.type === 'number') {
|
|
65
65
|
this._fieldConfigs?.push(numberField({
|
|
66
66
|
name: 'parent_id',
|
|
67
|
-
label: 'Parent ID',
|
|
67
|
+
label: { en: 'Parent ID', ar: 'معرف الأب' },
|
|
68
68
|
required: false,
|
|
69
69
|
order: 0,
|
|
70
70
|
}), levelConfig);
|
|
@@ -72,7 +72,7 @@ export class CategorySection extends Section {
|
|
|
72
72
|
else if (this.db.identifier.type === 'text') {
|
|
73
73
|
this._fieldConfigs?.push(textField({
|
|
74
74
|
name: 'parent_id',
|
|
75
|
-
label: 'Parent ID',
|
|
75
|
+
label: { en: 'Parent ID', ar: 'معرف الأب' },
|
|
76
76
|
required: false,
|
|
77
77
|
order: 0,
|
|
78
78
|
}), levelConfig);
|
|
@@ -147,7 +147,7 @@ declare const configSchema: z.ZodObject<{
|
|
|
147
147
|
size: number;
|
|
148
148
|
unit: "kb" | "mb";
|
|
149
149
|
} | undefined;
|
|
150
|
-
fileType?: ("
|
|
150
|
+
fileType?: ("webp" | "jpg" | "jpeg" | "png")[] | undefined;
|
|
151
151
|
removeExtension?: boolean | undefined;
|
|
152
152
|
label?: string | Record<string, string> | undefined;
|
|
153
153
|
required?: boolean | undefined;
|
|
@@ -188,7 +188,7 @@ declare const configSchema: z.ZodObject<{
|
|
|
188
188
|
size: number;
|
|
189
189
|
unit: "kb" | "mb";
|
|
190
190
|
} | undefined;
|
|
191
|
-
fileType?: ("
|
|
191
|
+
fileType?: ("webp" | "jpg" | "jpeg" | "png")[] | undefined;
|
|
192
192
|
removeExtension?: boolean | undefined;
|
|
193
193
|
label?: string | Record<string, string> | undefined;
|
|
194
194
|
required?: boolean | undefined;
|
|
@@ -365,7 +365,7 @@ declare const optionsSchema: z.ZodObject<{
|
|
|
365
365
|
size: number;
|
|
366
366
|
unit: "kb" | "mb";
|
|
367
367
|
} | undefined;
|
|
368
|
-
fileType?: ("
|
|
368
|
+
fileType?: ("webp" | "jpg" | "jpeg" | "png")[] | undefined;
|
|
369
369
|
removeExtension?: boolean | undefined;
|
|
370
370
|
label?: string | Record<string, string> | undefined;
|
|
371
371
|
required?: boolean | undefined;
|
|
@@ -406,7 +406,7 @@ declare const optionsSchema: z.ZodObject<{
|
|
|
406
406
|
size: number;
|
|
407
407
|
unit: "kb" | "mb";
|
|
408
408
|
} | undefined;
|
|
409
|
-
fileType?: ("
|
|
409
|
+
fileType?: ("webp" | "jpg" | "jpeg" | "png")[] | undefined;
|
|
410
410
|
removeExtension?: boolean | undefined;
|
|
411
411
|
label?: string | Record<string, string> | undefined;
|
|
412
412
|
required?: boolean | undefined;
|
|
@@ -418,9 +418,8 @@ declare const optionsSchema: z.ZodObject<{
|
|
|
418
418
|
generateQR: z.ZodOptional<z.ZodBoolean>;
|
|
419
419
|
fields: z.ZodUnion<[z.ZodArray<z.ZodCustom<FieldConfig, FieldConfig>>, z.ZodArray<z.ZodCustom<FieldGroupConfig, FieldGroupConfig>>]>;
|
|
420
420
|
readonly: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
421
|
-
name: z.ZodString;
|
|
422
|
-
order: z.ZodNumber;
|
|
423
421
|
icon: z.ZodOptional<z.ZodString>;
|
|
422
|
+
name: z.ZodString;
|
|
424
423
|
db: z.ZodObject<{
|
|
425
424
|
table: z.ZodString;
|
|
426
425
|
identifier: z.ZodOptional<z.ZodCustom<FieldConfig, FieldConfig>>;
|
|
@@ -445,6 +444,7 @@ declare const optionsSchema: z.ZodObject<{
|
|
|
445
444
|
}, z.core.$strict>>>;
|
|
446
445
|
}, z.core.$strict>;
|
|
447
446
|
variants: z.ZodOptional<z.ZodArray<z.ZodCustom<import("../types/index.js").Variant, import("../types/index.js").Variant>>>;
|
|
447
|
+
order: z.ZodNumber;
|
|
448
448
|
gallery: z.ZodOptional<z.ZodObject<{
|
|
449
449
|
db: z.ZodObject<{
|
|
450
450
|
tableName: z.ZodString;
|
|
@@ -607,7 +607,7 @@ declare const hasItemsSectionConfigSchema: z.ZodObject<{
|
|
|
607
607
|
size: number;
|
|
608
608
|
unit: "kb" | "mb";
|
|
609
609
|
} | undefined;
|
|
610
|
-
fileType?: ("
|
|
610
|
+
fileType?: ("webp" | "jpg" | "jpeg" | "png")[] | undefined;
|
|
611
611
|
removeExtension?: boolean | undefined;
|
|
612
612
|
label?: string | Record<string, string> | undefined;
|
|
613
613
|
required?: boolean | undefined;
|
|
@@ -648,7 +648,7 @@ declare const hasItemsSectionConfigSchema: z.ZodObject<{
|
|
|
648
648
|
size: number;
|
|
649
649
|
unit: "kb" | "mb";
|
|
650
650
|
} | undefined;
|
|
651
|
-
fileType?: ("
|
|
651
|
+
fileType?: ("webp" | "jpg" | "jpeg" | "png")[] | undefined;
|
|
652
652
|
removeExtension?: boolean | undefined;
|
|
653
653
|
label?: string | Record<string, string> | undefined;
|
|
654
654
|
required?: boolean | undefined;
|
|
@@ -659,9 +659,8 @@ declare const hasItemsSectionConfigSchema: z.ZodObject<{
|
|
|
659
659
|
}>>;
|
|
660
660
|
generateQR: z.ZodOptional<z.ZodBoolean>;
|
|
661
661
|
readonly: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
662
|
-
name: z.ZodString;
|
|
663
|
-
order: z.ZodNumber;
|
|
664
662
|
icon: z.ZodOptional<z.ZodString>;
|
|
663
|
+
name: z.ZodString;
|
|
665
664
|
db: z.ZodObject<{
|
|
666
665
|
table: z.ZodString;
|
|
667
666
|
identifier: z.ZodOptional<z.ZodCustom<FieldConfig, FieldConfig>>;
|
|
@@ -686,6 +685,7 @@ declare const hasItemsSectionConfigSchema: z.ZodObject<{
|
|
|
686
685
|
}, z.core.$strict>>>;
|
|
687
686
|
}, z.core.$strict>;
|
|
688
687
|
variants: z.ZodOptional<z.ZodArray<z.ZodCustom<import("../types/index.js").Variant, import("../types/index.js").Variant>>>;
|
|
688
|
+
order: z.ZodNumber;
|
|
689
689
|
gallery: z.ZodOptional<z.ZodObject<{
|
|
690
690
|
db: z.ZodObject<{
|
|
691
691
|
tableName: z.ZodString;
|
|
@@ -63,9 +63,8 @@ export declare const baseSectionOptionsSchema: z.ZodObject<{
|
|
|
63
63
|
export declare const baseHelperFunctionOptionsSchema: z.ZodObject<{
|
|
64
64
|
fields: z.ZodUnion<[z.ZodArray<z.ZodCustom<FieldConfig, FieldConfig>>, z.ZodArray<z.ZodCustom<FieldGroupConfig, FieldGroupConfig>>]>;
|
|
65
65
|
readonly: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
66
|
-
name: z.ZodString;
|
|
67
|
-
order: z.ZodNumber;
|
|
68
66
|
icon: z.ZodOptional<z.ZodString>;
|
|
67
|
+
name: z.ZodString;
|
|
69
68
|
db: z.ZodObject<{
|
|
70
69
|
table: z.ZodString;
|
|
71
70
|
identifier: z.ZodOptional<z.ZodCustom<FieldConfig, FieldConfig>>;
|
|
@@ -90,6 +89,7 @@ export declare const baseHelperFunctionOptionsSchema: z.ZodObject<{
|
|
|
90
89
|
}, z.core.$strict>>>;
|
|
91
90
|
}, z.core.$strict>;
|
|
92
91
|
variants: z.ZodOptional<z.ZodArray<z.ZodCustom<Variant, Variant>>>;
|
|
92
|
+
order: z.ZodNumber;
|
|
93
93
|
gallery: z.ZodOptional<z.ZodObject<{
|
|
94
94
|
db: z.ZodObject<{
|
|
95
95
|
tableName: z.ZodString;
|
|
@@ -24,10 +24,10 @@ declare const optionsSchema: z.ZodObject<{
|
|
|
24
24
|
}, z.core.$strict>;
|
|
25
25
|
fields: z.ZodUnion<[z.ZodArray<z.ZodCustom<FieldConfig, FieldConfig>>, z.ZodArray<z.ZodCustom<FieldGroupConfig, FieldGroupConfig>>]>;
|
|
26
26
|
readonly: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
27
|
-
name: z.ZodString;
|
|
28
|
-
order: z.ZodNumber;
|
|
29
27
|
icon: z.ZodOptional<z.ZodString>;
|
|
28
|
+
name: z.ZodString;
|
|
30
29
|
variants: z.ZodOptional<z.ZodArray<z.ZodCustom<import("../types/index.js").Variant, import("../types/index.js").Variant>>>;
|
|
30
|
+
order: z.ZodNumber;
|
|
31
31
|
gallery: z.ZodOptional<z.ZodObject<{
|
|
32
32
|
db: z.ZodObject<{
|
|
33
33
|
tableName: z.ZodString;
|
|
@@ -55,10 +55,10 @@ declare const simpleSectionConfigSchema: z.ZodObject<{
|
|
|
55
55
|
table: z.ZodString;
|
|
56
56
|
}, z.core.$strict>;
|
|
57
57
|
readonly: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
58
|
-
name: z.ZodString;
|
|
59
|
-
order: z.ZodNumber;
|
|
60
58
|
icon: z.ZodOptional<z.ZodString>;
|
|
59
|
+
name: z.ZodString;
|
|
61
60
|
variants: z.ZodOptional<z.ZodArray<z.ZodCustom<import("../types/index.js").Variant, import("../types/index.js").Variant>>>;
|
|
61
|
+
order: z.ZodNumber;
|
|
62
62
|
gallery: z.ZodOptional<z.ZodObject<{
|
|
63
63
|
db: z.ZodObject<{
|
|
64
64
|
tableName: z.ZodString;
|
|
@@ -74,6 +74,12 @@ export declare class EditSubmit extends Submit {
|
|
|
74
74
|
* Item id value is already assigned in the constructor
|
|
75
75
|
*/
|
|
76
76
|
assignItemIdValue(): void;
|
|
77
|
+
/**
|
|
78
|
+
* Return the current item's ID for exclusion in uniqueness checks.
|
|
79
|
+
* This ensures that when editing an item, it doesn't conflict with itself.
|
|
80
|
+
* @override
|
|
81
|
+
*/
|
|
82
|
+
protected getExcludedItemId(): string;
|
|
77
83
|
/**
|
|
78
84
|
* Set field value override
|
|
79
85
|
* @param field
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ItemEditSubmit.d.ts","sourceRoot":"","sources":["../../../src/core/submit/ItemEditSubmit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAItC,OAAO,KAAK,EAAuB,KAAK,EAAE,MAAM,WAAW,CAAA;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC,OAAO,EAAE,UAAU,EAAM,MAAM,YAAY,CAAA;AAC3C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAO3E,KAAK,eAAe,GAAG;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,IAAI,CAAA;IACV,QAAQ,EAAE,QAAQ,CAAA;IAClB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,eAAe,CAAC,EAAE,eAAe,CAAA;CACpC,CAAA;AAED,qBAAa,UAAW,SAAQ,MAAM;IAClC,gBAAyB,CAAC,UAAU,CAAC,EAAE,MAAM,CAAe;IAC5D,mBAA4B,OAAO,EAAE,MAAM,CAAA;IAC3C,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAK;cAExB,eAAe,IAAI,YAAY;IAIlD;;OAEG;gBACS,MAAM,EAAE,eAAe;IAKnC;;;OAGG;IACmB,UAAU;IASV,MAAM;YAQd,qBAAqB;cAuBhB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;cAIjD,gBAAgB,IAAI,MAAM,EAAE;IAO/C,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,iBAAiB;IAczB;;;OAGG;YACW,aAAa;YAQb,sBAAsB;IAoBpC;;;;;OAKG;cACsB,kBAAkB;IAI3C;;;;;OAKG;cACsB,cAAc;YAUzB,oBAAoB;IAoBlC;;;OAGG;cACgB,aAAa,IAAI,GAAG,GAAG,SAAS;IAmBnD;;;;OAIG;IACM,aAAa,CAAC,KAAK,EAAE,KAAK;IAmBnC;;;;OAIG;IACY,WAAW,CAAC,KAAK,EAAE,KAAK;IAQvC;;OAEG;IACM,iBAAiB;IAI1B;;;;OAIG;IACM,aAAa,CAAC,KAAK,EAAE,KAAK;CAgBtC"}
|
|
1
|
+
{"version":3,"file":"ItemEditSubmit.d.ts","sourceRoot":"","sources":["../../../src/core/submit/ItemEditSubmit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAItC,OAAO,KAAK,EAAuB,KAAK,EAAE,MAAM,WAAW,CAAA;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC,OAAO,EAAE,UAAU,EAAM,MAAM,YAAY,CAAA;AAC3C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAO3E,KAAK,eAAe,GAAG;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,IAAI,CAAA;IACV,QAAQ,EAAE,QAAQ,CAAA;IAClB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,eAAe,CAAC,EAAE,eAAe,CAAA;CACpC,CAAA;AAED,qBAAa,UAAW,SAAQ,MAAM;IAClC,gBAAyB,CAAC,UAAU,CAAC,EAAE,MAAM,CAAe;IAC5D,mBAA4B,OAAO,EAAE,MAAM,CAAA;IAC3C,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAK;cAExB,eAAe,IAAI,YAAY;IAIlD;;OAEG;gBACS,MAAM,EAAE,eAAe;IAKnC;;;OAGG;IACmB,UAAU;IASV,MAAM;YAQd,qBAAqB;cAuBhB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;cAIjD,gBAAgB,IAAI,MAAM,EAAE;IAO/C,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,iBAAiB;IAczB;;;OAGG;YACW,aAAa;YAQb,sBAAsB;IAoBpC;;;;;OAKG;cACsB,kBAAkB;IAI3C;;;;;OAKG;cACsB,cAAc;YAUzB,oBAAoB;IAoBlC;;;OAGG;cACgB,aAAa,IAAI,GAAG,GAAG,SAAS;IAmBnD;;;;OAIG;IACM,aAAa,CAAC,KAAK,EAAE,KAAK;IAmBnC;;;;OAIG;IACY,WAAW,CAAC,KAAK,EAAE,KAAK;IAQvC;;OAEG;IACM,iBAAiB;IAI1B;;;;OAIG;cACgB,iBAAiB,IAAI,MAAM;IAI9C;;;;OAIG;IACM,aAAa,CAAC,KAAK,EAAE,KAAK;CAgBtC"}
|
|
@@ -219,6 +219,14 @@ export class EditSubmit extends Submit {
|
|
|
219
219
|
assignItemIdValue() {
|
|
220
220
|
return;
|
|
221
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* Return the current item's ID for exclusion in uniqueness checks.
|
|
224
|
+
* This ensures that when editing an item, it doesn't conflict with itself.
|
|
225
|
+
* @override
|
|
226
|
+
*/
|
|
227
|
+
getExcludedItemId() {
|
|
228
|
+
return this._itemId;
|
|
229
|
+
}
|
|
222
230
|
/**
|
|
223
231
|
* Set field value override
|
|
224
232
|
* @param field
|
|
@@ -109,14 +109,34 @@ export declare abstract class Submit {
|
|
|
109
109
|
* @protected
|
|
110
110
|
*/
|
|
111
111
|
protected handleField(field: Field): Promise<void>;
|
|
112
|
+
protected handleFields(): Promise<void>;
|
|
112
113
|
/**
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
114
|
+
* Get the ID of the item to exclude from uniqueness checks.
|
|
115
|
+
* Returns undefined in the base class (NewSubmit behavior).
|
|
116
|
+
* Override in EditSubmit to return the current item's ID.
|
|
116
117
|
* @protected
|
|
117
118
|
*/
|
|
118
|
-
protected
|
|
119
|
-
|
|
119
|
+
protected getExcludedItemId(): number | string | undefined;
|
|
120
|
+
/**
|
|
121
|
+
* Get a user-friendly label for a field config.
|
|
122
|
+
* Resolves localized strings to English.
|
|
123
|
+
* @param fieldConfig - The field configuration
|
|
124
|
+
* @private
|
|
125
|
+
*/
|
|
126
|
+
private getFieldLabel;
|
|
127
|
+
/**
|
|
128
|
+
* Check all uniqueness constraints defined in the section.
|
|
129
|
+
* Stops on the first violation.
|
|
130
|
+
* @protected
|
|
131
|
+
*/
|
|
132
|
+
protected checkUniqueness(): Promise<void>;
|
|
133
|
+
/**
|
|
134
|
+
* Check a single uniqueness constraint.
|
|
135
|
+
* Handles both single-column and composite (multi-column) constraints.
|
|
136
|
+
* @param constraint - The constraint to check
|
|
137
|
+
* @private
|
|
138
|
+
*/
|
|
139
|
+
private checkUniqueConstraint;
|
|
120
140
|
/**
|
|
121
141
|
* Execute the sql query.
|
|
122
142
|
* @param sqlQuery
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"submit.d.ts","sourceRoot":"","sources":["../../../src/core/submit/submit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAGtC,OAAO,KAAK,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"submit.d.ts","sourceRoot":"","sources":["../../../src/core/submit/submit.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,10 +2,13 @@ import { sql } from 'drizzle-orm';
|
|
|
2
2
|
import { db } from '../../db/client';
|
|
3
3
|
import { SectionFactory } from '../factories';
|
|
4
4
|
import { entityKind, is } from '../helpers';
|
|
5
|
-
import { NumberField, PhotoField, SelectField,
|
|
5
|
+
import { NumberField, PhotoField, SelectField, TextField } from '../fields';
|
|
6
6
|
import { MysqlTableChecker } from '../db';
|
|
7
7
|
import { recordLog } from '../../logging/index.js';
|
|
8
8
|
import getString from '../../translations';
|
|
9
|
+
import { resolveLocalizedString } from '../../translations/localization.js';
|
|
10
|
+
import { resolveLocale } from '../../translations/locale-utils.js';
|
|
11
|
+
import { getCMSConfig } from '../config/index.js';
|
|
9
12
|
export class Submit {
|
|
10
13
|
static [entityKind] = 'Submit';
|
|
11
14
|
user;
|
|
@@ -177,6 +180,14 @@ export class Submit {
|
|
|
177
180
|
* Build the fields from the field configs
|
|
178
181
|
*/
|
|
179
182
|
this._sectionInfo.buildFields();
|
|
183
|
+
/**
|
|
184
|
+
* Set locale for fields so validation errors are localized
|
|
185
|
+
*/
|
|
186
|
+
const cmsConfig = await getCMSConfig();
|
|
187
|
+
const locale = resolveLocale(user.locale, cmsConfig.i18n.supportedLanguages, cmsConfig.i18n.fallbackLanguage);
|
|
188
|
+
for (const field of this._sectionInfo.fields) {
|
|
189
|
+
field.setLocale(locale, cmsConfig.i18n.fallbackLanguage);
|
|
190
|
+
}
|
|
180
191
|
}
|
|
181
192
|
/**
|
|
182
193
|
* Perform post submit operations
|
|
@@ -352,7 +363,7 @@ export class Submit {
|
|
|
352
363
|
* Prepare the field for submission,
|
|
353
364
|
* this will throw an error if the checks fail
|
|
354
365
|
*/
|
|
355
|
-
await
|
|
366
|
+
await field.prepareForSubmission();
|
|
356
367
|
}
|
|
357
368
|
catch (e) {
|
|
358
369
|
this._error = true;
|
|
@@ -368,22 +379,6 @@ export class Submit {
|
|
|
368
379
|
*/
|
|
369
380
|
this.assignItemIdValue(field);
|
|
370
381
|
}
|
|
371
|
-
/**
|
|
372
|
-
* Call prepareForSubmission on a field with appropriate context.
|
|
373
|
-
* SlugField requires table name for duplicate checking.
|
|
374
|
-
* @param field
|
|
375
|
-
* @protected
|
|
376
|
-
*/
|
|
377
|
-
async callPrepareForSubmission(field) {
|
|
378
|
-
if (is(field, SlugField)) {
|
|
379
|
-
await field.prepareForSubmission({
|
|
380
|
-
tableName: this._sectionInfo.db.table,
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
else {
|
|
384
|
-
await field.prepareForSubmission();
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
382
|
async handleFields() {
|
|
388
383
|
if (this._error)
|
|
389
384
|
return;
|
|
@@ -395,6 +390,99 @@ export class Submit {
|
|
|
395
390
|
}
|
|
396
391
|
}
|
|
397
392
|
}
|
|
393
|
+
/**
|
|
394
|
+
* Get the ID of the item to exclude from uniqueness checks.
|
|
395
|
+
* Returns undefined in the base class (NewSubmit behavior).
|
|
396
|
+
* Override in EditSubmit to return the current item's ID.
|
|
397
|
+
* @protected
|
|
398
|
+
*/
|
|
399
|
+
getExcludedItemId() {
|
|
400
|
+
return undefined;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Get a user-friendly label for a field config.
|
|
404
|
+
* Resolves localized strings to English.
|
|
405
|
+
* @param fieldConfig - The field configuration
|
|
406
|
+
* @private
|
|
407
|
+
*/
|
|
408
|
+
getFieldLabel(fieldConfig) {
|
|
409
|
+
const label = fieldConfig.label;
|
|
410
|
+
if (!label) {
|
|
411
|
+
return fieldConfig.name
|
|
412
|
+
.replace(/_/g, ' ')
|
|
413
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
414
|
+
.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
415
|
+
}
|
|
416
|
+
return resolveLocalizedString(label, 'en', 'en');
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Check all uniqueness constraints defined in the section.
|
|
420
|
+
* Stops on the first violation.
|
|
421
|
+
* @protected
|
|
422
|
+
*/
|
|
423
|
+
async checkUniqueness() {
|
|
424
|
+
if (this._error)
|
|
425
|
+
return;
|
|
426
|
+
if (!this._sectionInfo?.db.unique?.length)
|
|
427
|
+
return;
|
|
428
|
+
for (const constraint of this._sectionInfo.db.unique) {
|
|
429
|
+
await this.checkUniqueConstraint(constraint);
|
|
430
|
+
if (this._error)
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Check a single uniqueness constraint.
|
|
436
|
+
* Handles both single-column and composite (multi-column) constraints.
|
|
437
|
+
* @param constraint - The constraint to check
|
|
438
|
+
* @private
|
|
439
|
+
*/
|
|
440
|
+
async checkUniqueConstraint(constraint) {
|
|
441
|
+
const columnNames = constraint.columns.map((col) => col.name);
|
|
442
|
+
// Check if ALL columns have values in sqlNamesAndValues
|
|
443
|
+
// Skip if any column has null/undefined value
|
|
444
|
+
const columnValues = [];
|
|
445
|
+
for (const fieldConfig of constraint.columns) {
|
|
446
|
+
const value = this.sqlNamesAndValues[fieldConfig.name];
|
|
447
|
+
if (value === null || value === undefined) {
|
|
448
|
+
// Skip this constraint if any column is null/undefined
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
columnValues.push({ name: fieldConfig.name, value, fieldConfig });
|
|
452
|
+
}
|
|
453
|
+
// Build the WHERE clause
|
|
454
|
+
const whereConditions = columnValues.map(({ name, value }) => sql `${sql.raw(`\`${name}\``)} = ${value}`);
|
|
455
|
+
// Add exclusion for the current item if editing
|
|
456
|
+
const excludedId = this.getExcludedItemId();
|
|
457
|
+
if (excludedId !== undefined) {
|
|
458
|
+
const identifierName = this._sectionInfo.db.identifier.name;
|
|
459
|
+
whereConditions.push(sql `${sql.raw(`\`${identifierName}\``)} != ${excludedId}`);
|
|
460
|
+
}
|
|
461
|
+
// Combine conditions with AND
|
|
462
|
+
const whereClause = sql.join(whereConditions, sql ` AND `);
|
|
463
|
+
// Execute the query
|
|
464
|
+
const query = sql `SELECT 1 FROM ${sql.raw(`\`${this._sectionInfo.db.table}\``)} WHERE ${whereClause} LIMIT 1`;
|
|
465
|
+
try {
|
|
466
|
+
const [rows] = await db.execute(query);
|
|
467
|
+
if (Array.isArray(rows) && rows.length > 0) {
|
|
468
|
+
// Violation found - build error message
|
|
469
|
+
this._error = true;
|
|
470
|
+
const firstColumn = columnValues[0];
|
|
471
|
+
if (columnValues.length === 1 && firstColumn) {
|
|
472
|
+
const label = this.getFieldLabel(firstColumn.fieldConfig);
|
|
473
|
+
this._errorMessage = getString('recordWithFieldExists', this.user.locale, { field: label });
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
const labels = columnValues.map(({ fieldConfig }) => this.getFieldLabel(fieldConfig));
|
|
477
|
+
this._errorMessage = getString('recordWithCombinationExists', this.user.locale, { fields: labels.join(', ') });
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
catch (e) {
|
|
482
|
+
// Log but don't fail on query errors - let the actual insert/update handle it
|
|
483
|
+
console.error('Uniqueness check query failed:', e);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
398
486
|
/**
|
|
399
487
|
* Execute the sql query.
|
|
400
488
|
* @param sqlQuery
|
|
@@ -408,7 +496,7 @@ export class Submit {
|
|
|
408
496
|
*/
|
|
409
497
|
if (!sqlQuery) {
|
|
410
498
|
this._error = true;
|
|
411
|
-
this._errorMessage = '
|
|
499
|
+
this._errorMessage = getString('sqlQueryNotDefined', this.user.locale);
|
|
412
500
|
return;
|
|
413
501
|
}
|
|
414
502
|
try {
|
|
@@ -438,12 +526,22 @@ export class Submit {
|
|
|
438
526
|
* Assign the values to the fields
|
|
439
527
|
*/
|
|
440
528
|
await this.handleFields();
|
|
529
|
+
/**
|
|
530
|
+
* Check uniqueness constraints
|
|
531
|
+
*/
|
|
532
|
+
await this.checkUniqueness();
|
|
441
533
|
/**
|
|
442
534
|
* If this is a pre-submit operation, don't submit the form
|
|
443
535
|
*/
|
|
444
536
|
if (this.preSubmit) {
|
|
445
537
|
return;
|
|
446
538
|
}
|
|
539
|
+
/**
|
|
540
|
+
* Return early if there was an error (including uniqueness violations)
|
|
541
|
+
*/
|
|
542
|
+
if (this._error) {
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
447
545
|
/**
|
|
448
546
|
* Run pre-submit hooks (beforeUpdate)
|
|
449
547
|
*/
|
|
@@ -525,7 +623,7 @@ export class Submit {
|
|
|
525
623
|
/**
|
|
526
624
|
* The gallery table is not set up correctly, add it to the notices array
|
|
527
625
|
*/
|
|
528
|
-
this.addNotice('
|
|
626
|
+
this.addNotice(getString('galleryTableNotSetUp', this.user.locale));
|
|
529
627
|
return;
|
|
530
628
|
}
|
|
531
629
|
const columns = await MysqlTableChecker.getColumns(gallery.db.tableName);
|
|
@@ -535,7 +633,7 @@ export class Submit {
|
|
|
535
633
|
/**
|
|
536
634
|
* The gallery table is not set up correctly, add it to the notices array
|
|
537
635
|
*/
|
|
538
|
-
this.addNotice('
|
|
636
|
+
this.addNotice(getString('galleryTableNotSetUp', this.user.locale));
|
|
539
637
|
return;
|
|
540
638
|
}
|
|
541
639
|
/**
|