@adminforth/bulk-ai-flow 1.2.0 → 1.3.0

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/build.log CHANGED
@@ -11,5 +11,5 @@ custom/tsconfig.json
11
11
  custom/visionAction.vue
12
12
  custom/visionTable.vue
13
13
 
14
- sent 56,260 bytes received 134 bytes 112,788.00 bytes/sec
15
- total size is 55,753 speedup is 0.99
14
+ sent 56,599 bytes received 134 bytes 113,466.00 bytes/sec
15
+ total size is 56,099 speedup is 0.99
@@ -339,7 +339,7 @@ async function getGenerationPrompt() {
339
339
  if(!resp) {
340
340
  emit('error', {
341
341
  isError: true,
342
- errorMessage: "Something went wrong. Check your internet connection and try again."
342
+ errorMessage: "Error getting generation prompts."
343
343
  });
344
344
  }
345
345
  return resp?.generationOptions || null;
@@ -400,7 +400,7 @@ async function generateImages() {
400
400
  });
401
401
  emit('error', {
402
402
  isError: true,
403
- errorMessage: error
403
+ errorMessage: "Error re-generating images"
404
404
  });
405
405
  }
406
406
  return;
@@ -43,7 +43,7 @@
43
43
  />
44
44
  <div class="flex w-full items-end justify-end gap-4">
45
45
  <div class="h-full text-red-600 font-semibold flex items-center justify-center mb-2">
46
- <p v-if="isError === true">{{ "Network error, please try again" }}</p>
46
+ <p v-if="isError === true">{{ errorMessage }}</p>
47
47
  </div>
48
48
  <button type="button" class="py-2.5 px-5 ms-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
49
49
  @click="closeDialog"
@@ -53,7 +53,7 @@
53
53
  <Button
54
54
  class="w-64"
55
55
  @click="saveData"
56
- :disabled="isLoading || checkedCount < 1"
56
+ :disabled="isLoading || checkedCount < 1 || isCriticalError"
57
57
  :loader="isLoading"
58
58
  >
59
59
  {{ checkedCount > 1 ? 'Save fields' : 'Save field' }}
@@ -106,6 +106,7 @@ const primaryKey = props.meta.primaryKey;
106
106
  const openGenerationCarousel = ref([]);
107
107
  const isLoading = ref(false);
108
108
  const isError = ref(false);
109
+ const isCriticalError = ref(false);
109
110
  const errorMessage = ref('');
110
111
  const checkedCount = ref(0);
111
112
 
@@ -143,7 +144,7 @@ const openDialog = async () => {
143
144
  }
144
145
 
145
146
  watch(selected, (val) => {
146
- //console.log('Selected changed:', val);
147
+ console.log('Selected changed:', val);
147
148
  checkedCount.value = val.filter(item => item.isChecked === true).length;
148
149
  }, { deep: true });
149
150
 
@@ -254,7 +255,7 @@ async function getRecords() {
254
255
  } catch (error) {
255
256
  console.error('Failed to get records:', error);
256
257
  isError.value = true;
257
- errorMessage.value = `Failed to get records ${error}. Please, try to re-run the action.`;
258
+ errorMessage.value = `Failed to fetch records. Please, try to re-run the action.`;
258
259
  // Handle error appropriately
259
260
  }
260
261
  }
@@ -272,7 +273,7 @@ async function getImages() {
272
273
  } catch (error) {
273
274
  console.error('Failed to get images:', error);
274
275
  isError.value = true;
275
- errorMessage.value = `Failed to get images ${error}. Please, try to re-run the action.`;
276
+ errorMessage.value = `Failed to fetch images. Please, try to re-run the action.`;
276
277
  // Handle error appropriately
277
278
  }
278
279
  }
@@ -353,9 +354,9 @@ async function analyzeFields() {
353
354
  }
354
355
  })
355
356
  } catch (error) {
356
- console.error('Failed to get records:', error);
357
+ console.error('Failed to analyze image(s):', error);
357
358
  isError.value = true;
358
- errorMessage.value = `Failed to get records ${error}. Please, try to re-run the action.`;
359
+ errorMessage.value = `Failed to fetch analyze image(s). Please, try to re-run the action.`;
359
360
  }
360
361
  }
361
362
 
@@ -388,9 +389,9 @@ async function analyzeFieldsNoImages() {
388
389
  }
389
390
  })
390
391
  } catch (error) {
391
- console.error('Failed to get records:', error);
392
+ console.error('Failed to analyze fields:', error);
392
393
  isError.value = true;
393
- errorMessage.value = `Failed to get records ${error}. Please, try to re-run the action.`;
394
+ errorMessage.value = `Failed to analyze fields. Please, try to re-run the action.`;
394
395
  }
395
396
  }
396
397
 
@@ -428,19 +429,27 @@ async function saveData() {
428
429
  },
429
430
  });
430
431
 
431
- if(res.ok) {
432
+ if(res.ok === true) {
432
433
  confirmDialog.value.close();
433
434
  props.updateList();
434
435
  props.clearCheckboxes();
436
+ } else if (res.ok === false) {
437
+ adminforth.alert({
438
+ message: 'You are not allowed to save.',
439
+ variant: 'danger',
440
+ timeout: 'unlimited',
441
+ });
442
+ isError.value = true;
443
+ errorMessage.value = `Failed to save data. You are not allowed to save.`;
435
444
  } else {
436
445
  console.error('Error saving data:', res);
437
446
  isError.value = true;
438
- errorMessage.value = `Failed to save data ${res}. Please, try to re-run the action.`;
447
+ errorMessage.value = `Failed to save data. Please, try to re-run the action.`;
439
448
  }
440
449
  } catch (error) {
441
450
  console.error('Error saving data:', error);
442
451
  isError.value = true;
443
- errorMessage.value = `Failed to save data ${error}. Please, try to re-run the action.`;
452
+ errorMessage.value = `Failed to save data. Please, try to re-run the action.`;
444
453
  } finally {
445
454
  isLoading.value = false;
446
455
  }
@@ -462,7 +471,8 @@ async function generateImages() {
462
471
  } catch (e) {
463
472
  console.error('Error generating images:', e);
464
473
  isError.value = true;
465
- errorMessage.value = `Failed to generate images ${e}. Please, try to re-run the action.`;
474
+ isCriticalError.value = true;
475
+ errorMessage.value = `Failed to generate images. Please, try to re-run the action.`;
466
476
  }
467
477
  isAiResponseReceivedImage.value = props.checkboxes.map(() => true);
468
478
 
@@ -472,7 +482,8 @@ async function generateImages() {
472
482
  if (!res) {
473
483
  error = 'Error generating images, something went wrong';
474
484
  isError.value = true;
475
- errorMessage.value = `Failed to generate images ${e}. Please, try to re-run the action.`;
485
+ isCriticalError.value = true;
486
+ errorMessage.value = `Failed to generate images. Please, try to re-run the action.`;
476
487
  }
477
488
 
478
489
  if (error) {
@@ -339,7 +339,7 @@ async function getGenerationPrompt() {
339
339
  if(!resp) {
340
340
  emit('error', {
341
341
  isError: true,
342
- errorMessage: "Something went wrong. Check your internet connection and try again."
342
+ errorMessage: "Error getting generation prompts."
343
343
  });
344
344
  }
345
345
  return resp?.generationOptions || null;
@@ -400,7 +400,7 @@ async function generateImages() {
400
400
  });
401
401
  emit('error', {
402
402
  isError: true,
403
- errorMessage: error
403
+ errorMessage: "Error re-generating images"
404
404
  });
405
405
  }
406
406
  return;
@@ -43,7 +43,7 @@
43
43
  />
44
44
  <div class="flex w-full items-end justify-end gap-4">
45
45
  <div class="h-full text-red-600 font-semibold flex items-center justify-center mb-2">
46
- <p v-if="isError === true">{{ "Network error, please try again" }}</p>
46
+ <p v-if="isError === true">{{ errorMessage }}</p>
47
47
  </div>
48
48
  <button type="button" class="py-2.5 px-5 ms-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
49
49
  @click="closeDialog"
@@ -53,7 +53,7 @@
53
53
  <Button
54
54
  class="w-64"
55
55
  @click="saveData"
56
- :disabled="isLoading || checkedCount < 1"
56
+ :disabled="isLoading || checkedCount < 1 || isCriticalError"
57
57
  :loader="isLoading"
58
58
  >
59
59
  {{ checkedCount > 1 ? 'Save fields' : 'Save field' }}
@@ -106,6 +106,7 @@ const primaryKey = props.meta.primaryKey;
106
106
  const openGenerationCarousel = ref([]);
107
107
  const isLoading = ref(false);
108
108
  const isError = ref(false);
109
+ const isCriticalError = ref(false);
109
110
  const errorMessage = ref('');
110
111
  const checkedCount = ref(0);
111
112
 
@@ -143,7 +144,7 @@ const openDialog = async () => {
143
144
  }
144
145
 
145
146
  watch(selected, (val) => {
146
- //console.log('Selected changed:', val);
147
+ console.log('Selected changed:', val);
147
148
  checkedCount.value = val.filter(item => item.isChecked === true).length;
148
149
  }, { deep: true });
149
150
 
@@ -254,7 +255,7 @@ async function getRecords() {
254
255
  } catch (error) {
255
256
  console.error('Failed to get records:', error);
256
257
  isError.value = true;
257
- errorMessage.value = `Failed to get records ${error}. Please, try to re-run the action.`;
258
+ errorMessage.value = `Failed to fetch records. Please, try to re-run the action.`;
258
259
  // Handle error appropriately
259
260
  }
260
261
  }
@@ -272,7 +273,7 @@ async function getImages() {
272
273
  } catch (error) {
273
274
  console.error('Failed to get images:', error);
274
275
  isError.value = true;
275
- errorMessage.value = `Failed to get images ${error}. Please, try to re-run the action.`;
276
+ errorMessage.value = `Failed to fetch images. Please, try to re-run the action.`;
276
277
  // Handle error appropriately
277
278
  }
278
279
  }
@@ -353,9 +354,9 @@ async function analyzeFields() {
353
354
  }
354
355
  })
355
356
  } catch (error) {
356
- console.error('Failed to get records:', error);
357
+ console.error('Failed to analyze image(s):', error);
357
358
  isError.value = true;
358
- errorMessage.value = `Failed to get records ${error}. Please, try to re-run the action.`;
359
+ errorMessage.value = `Failed to fetch analyze image(s). Please, try to re-run the action.`;
359
360
  }
360
361
  }
361
362
 
@@ -388,9 +389,9 @@ async function analyzeFieldsNoImages() {
388
389
  }
389
390
  })
390
391
  } catch (error) {
391
- console.error('Failed to get records:', error);
392
+ console.error('Failed to analyze fields:', error);
392
393
  isError.value = true;
393
- errorMessage.value = `Failed to get records ${error}. Please, try to re-run the action.`;
394
+ errorMessage.value = `Failed to analyze fields. Please, try to re-run the action.`;
394
395
  }
395
396
  }
396
397
 
@@ -428,19 +429,27 @@ async function saveData() {
428
429
  },
429
430
  });
430
431
 
431
- if(res.ok) {
432
+ if(res.ok === true) {
432
433
  confirmDialog.value.close();
433
434
  props.updateList();
434
435
  props.clearCheckboxes();
436
+ } else if (res.ok === false) {
437
+ adminforth.alert({
438
+ message: 'You are not allowed to save.',
439
+ variant: 'danger',
440
+ timeout: 'unlimited',
441
+ });
442
+ isError.value = true;
443
+ errorMessage.value = `Failed to save data. You are not allowed to save.`;
435
444
  } else {
436
445
  console.error('Error saving data:', res);
437
446
  isError.value = true;
438
- errorMessage.value = `Failed to save data ${res}. Please, try to re-run the action.`;
447
+ errorMessage.value = `Failed to save data. Please, try to re-run the action.`;
439
448
  }
440
449
  } catch (error) {
441
450
  console.error('Error saving data:', error);
442
451
  isError.value = true;
443
- errorMessage.value = `Failed to save data ${error}. Please, try to re-run the action.`;
452
+ errorMessage.value = `Failed to save data. Please, try to re-run the action.`;
444
453
  } finally {
445
454
  isLoading.value = false;
446
455
  }
@@ -462,7 +471,8 @@ async function generateImages() {
462
471
  } catch (e) {
463
472
  console.error('Error generating images:', e);
464
473
  isError.value = true;
465
- errorMessage.value = `Failed to generate images ${e}. Please, try to re-run the action.`;
474
+ isCriticalError.value = true;
475
+ errorMessage.value = `Failed to generate images. Please, try to re-run the action.`;
466
476
  }
467
477
  isAiResponseReceivedImage.value = props.checkboxes.map(() => true);
468
478
 
@@ -472,7 +482,8 @@ async function generateImages() {
472
482
  if (!res) {
473
483
  error = 'Error generating images, something went wrong';
474
484
  isError.value = true;
475
- errorMessage.value = `Failed to generate images ${e}. Please, try to re-run the action.`;
485
+ isCriticalError.value = true;
486
+ errorMessage.value = `Failed to generate images. Please, try to re-run the action.`;
476
487
  }
477
488
 
478
489
  if (error) {
package/dist/index.js CHANGED
@@ -293,44 +293,49 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
293
293
  method: 'POST',
294
294
  path: `/plugin/${this.pluginInstanceId}/update_fields`,
295
295
  handler: (body) => __awaiter(this, void 0, void 0, function* () {
296
- const selectedIds = body.body.selectedIds || [];
297
- const fieldsToUpdate = body.body.fields || {};
298
- const outputImageFields = [];
299
- if (this.options.generateImages) {
300
- for (const [key, value] of Object.entries(this.options.generateImages)) {
301
- outputImageFields.push(key);
296
+ if (this.options.isAllowedToSave !== false) {
297
+ const selectedIds = body.body.selectedIds || [];
298
+ const fieldsToUpdate = body.body.fields || {};
299
+ const outputImageFields = [];
300
+ if (this.options.generateImages) {
301
+ for (const [key, value] of Object.entries(this.options.generateImages)) {
302
+ outputImageFields.push(key);
303
+ }
302
304
  }
303
- }
304
- const primaryKeyColumn = this.resourceConfig.columns.find((col) => col.primaryKey);
305
- const updates = selectedIds.map((ID, idx) => __awaiter(this, void 0, void 0, function* () {
306
- const oldRecord = yield this.adminforth.resource(this.resourceConfig.resourceId).get([Filters.EQ(primaryKeyColumn.name, ID)]);
307
- for (const [key, value] of Object.entries(outputImageFields)) {
308
- const columnPlugin = this.adminforth.activatedPlugins.find(p => p.resourceConfig.resourceId === this.resourceConfig.resourceId &&
309
- p.pluginOptions.pathColumnName === value);
310
- if (columnPlugin) {
311
- if (columnPlugin.pluginOptions.storageAdapter.objectCanBeAccesedPublicly()) {
312
- if (oldRecord[value]) {
313
- // put tag to delete old file
314
- try {
315
- yield columnPlugin.pluginOptions.storageAdapter.markKeyForDeletation(oldRecord[value]);
305
+ const primaryKeyColumn = this.resourceConfig.columns.find((col) => col.primaryKey);
306
+ const updates = selectedIds.map((ID, idx) => __awaiter(this, void 0, void 0, function* () {
307
+ const oldRecord = yield this.adminforth.resource(this.resourceConfig.resourceId).get([Filters.EQ(primaryKeyColumn.name, ID)]);
308
+ for (const [key, value] of Object.entries(outputImageFields)) {
309
+ const columnPlugin = this.adminforth.activatedPlugins.find(p => p.resourceConfig.resourceId === this.resourceConfig.resourceId &&
310
+ p.pluginOptions.pathColumnName === value);
311
+ if (columnPlugin) {
312
+ if (columnPlugin.pluginOptions.storageAdapter.objectCanBeAccesedPublicly()) {
313
+ if (oldRecord[value]) {
314
+ // put tag to delete old file
315
+ try {
316
+ yield columnPlugin.pluginOptions.storageAdapter.markKeyForDeletation(oldRecord[value]);
317
+ }
318
+ catch (e) {
319
+ // file might be e.g. already deleted, so we catch error
320
+ console.error(`Error setting tag to true for object ${oldRecord[value]}. File will not be auto-cleaned up`, e);
321
+ }
316
322
  }
317
- catch (e) {
318
- // file might be e.g. already deleted, so we catch error
319
- console.error(`Error setting tag to true for object ${oldRecord[value]}. File will not be auto-cleaned up`, e);
323
+ if (fieldsToUpdate[idx][key] !== null) {
324
+ // remove tag from new file
325
+ // in this case we let it crash if it fails: this is a new file which just was uploaded.
326
+ yield columnPlugin.pluginOptions.storageAdapter.markKeyForNotDeletation(fieldsToUpdate[idx][value]);
320
327
  }
321
328
  }
322
- if (fieldsToUpdate[idx][key] !== null) {
323
- // remove tag from new file
324
- // in this case we let it crash if it fails: this is a new file which just was uploaded.
325
- yield columnPlugin.pluginOptions.storageAdapter.markKeyForNotDeletation(fieldsToUpdate[idx][value]);
326
- }
327
329
  }
328
330
  }
329
- }
330
- return this.adminforth.resource(this.resourceConfig.resourceId).update(ID, fieldsToUpdate[idx]);
331
- }));
332
- yield Promise.all(updates);
333
- return { ok: true };
331
+ return this.adminforth.resource(this.resourceConfig.resourceId).update(ID, fieldsToUpdate[idx]);
332
+ }));
333
+ yield Promise.all(updates);
334
+ return { ok: true };
335
+ }
336
+ else {
337
+ return { ok: false };
338
+ }
334
339
  })
335
340
  });
336
341
  server.endpoint({
package/index.ts CHANGED
@@ -339,45 +339,49 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
339
339
  method: 'POST',
340
340
  path: `/plugin/${this.pluginInstanceId}/update_fields`,
341
341
  handler: async ( body ) => {
342
- const selectedIds = body.body.selectedIds || [];
343
- const fieldsToUpdate = body.body.fields || {};
344
- const outputImageFields = [];
345
- if (this.options.generateImages) {
346
- for (const [key, value] of Object.entries(this.options.generateImages)) {
347
- outputImageFields.push(key);
342
+ if(this.options.isAllowedToSave !== false) {
343
+ const selectedIds = body.body.selectedIds || [];
344
+ const fieldsToUpdate = body.body.fields || {};
345
+ const outputImageFields = [];
346
+ if (this.options.generateImages) {
347
+ for (const [key, value] of Object.entries(this.options.generateImages)) {
348
+ outputImageFields.push(key);
349
+ }
348
350
  }
349
- }
350
- const primaryKeyColumn = this.resourceConfig.columns.find((col) => col.primaryKey);
351
- const updates = selectedIds.map(async (ID, idx) => {
352
- const oldRecord = await this.adminforth.resource(this.resourceConfig.resourceId).get( [Filters.EQ(primaryKeyColumn.name, ID)] );
353
- for (const [key, value] of Object.entries(outputImageFields)) {
354
- const columnPlugin = this.adminforth.activatedPlugins.find(p =>
355
- p.resourceConfig!.resourceId === this.resourceConfig.resourceId &&
356
- p.pluginOptions.pathColumnName === value
357
- );
358
- if (columnPlugin) {
359
- if(columnPlugin.pluginOptions.storageAdapter.objectCanBeAccesedPublicly()) {
360
- if (oldRecord[value]) {
361
- // put tag to delete old file
362
- try {
363
- await columnPlugin.pluginOptions.storageAdapter.markKeyForDeletation(oldRecord[value]);
364
- } catch (e) {
365
- // file might be e.g. already deleted, so we catch error
366
- console.error(`Error setting tag to true for object ${oldRecord[value]}. File will not be auto-cleaned up`, e);
351
+ const primaryKeyColumn = this.resourceConfig.columns.find((col) => col.primaryKey);
352
+ const updates = selectedIds.map(async (ID, idx) => {
353
+ const oldRecord = await this.adminforth.resource(this.resourceConfig.resourceId).get( [Filters.EQ(primaryKeyColumn.name, ID)] );
354
+ for (const [key, value] of Object.entries(outputImageFields)) {
355
+ const columnPlugin = this.adminforth.activatedPlugins.find(p =>
356
+ p.resourceConfig!.resourceId === this.resourceConfig.resourceId &&
357
+ p.pluginOptions.pathColumnName === value
358
+ );
359
+ if (columnPlugin) {
360
+ if(columnPlugin.pluginOptions.storageAdapter.objectCanBeAccesedPublicly()) {
361
+ if (oldRecord[value]) {
362
+ // put tag to delete old file
363
+ try {
364
+ await columnPlugin.pluginOptions.storageAdapter.markKeyForDeletation(oldRecord[value]);
365
+ } catch (e) {
366
+ // file might be e.g. already deleted, so we catch error
367
+ console.error(`Error setting tag to true for object ${oldRecord[value]}. File will not be auto-cleaned up`, e);
368
+ }
369
+ }
370
+ if (fieldsToUpdate[idx][key] !== null) {
371
+ // remove tag from new file
372
+ // in this case we let it crash if it fails: this is a new file which just was uploaded.
373
+ await columnPlugin.pluginOptions.storageAdapter.markKeyForNotDeletation(fieldsToUpdate[idx][value]);
367
374
  }
368
- }
369
- if (fieldsToUpdate[idx][key] !== null) {
370
- // remove tag from new file
371
- // in this case we let it crash if it fails: this is a new file which just was uploaded.
372
- await columnPlugin.pluginOptions.storageAdapter.markKeyForNotDeletation(fieldsToUpdate[idx][value]);
373
375
  }
374
376
  }
375
377
  }
376
- }
377
- return this.adminforth.resource(this.resourceConfig.resourceId).update(ID, fieldsToUpdate[idx])
378
- });
379
- await Promise.all(updates);
380
- return { ok: true };
378
+ return this.adminforth.resource(this.resourceConfig.resourceId).update(ID, fieldsToUpdate[idx])
379
+ });
380
+ await Promise.all(updates);
381
+ return { ok: true };
382
+ } else {
383
+ return { ok: false }
384
+ }
381
385
  }
382
386
  });
383
387
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/bulk-ai-flow",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
package/types.ts CHANGED
@@ -47,4 +47,9 @@ export interface PluginOptions {
47
47
  * As rateLimit on generateImages, but applied to bulk generations
48
48
  **/
49
49
  bulkGenerationRateLimit?: string,
50
+
51
+ /**
52
+ * Whether the user is allowed to save the generated images
53
+ */
54
+ isAllowedToSave?: boolean
50
55
  }