@stoker-platform/web-app 0.5.28 → 0.5.29

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @stoker-platform/web-app
2
2
 
3
+ ## 0.5.29
4
+
5
+ ### Patch Changes
6
+
7
+ - feat: skip file permissions selection when no optional permissions present
8
+
3
9
  ## 0.5.28
4
10
 
5
11
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stoker-platform/web-app",
3
- "version": "0.5.28",
3
+ "version": "0.5.29",
4
4
  "type": "module",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "scripts": {
package/src/Form.tsx CHANGED
@@ -2322,6 +2322,36 @@ function RecordForm({
2322
2322
  [collectionPath, record, path],
2323
2323
  )
2324
2324
 
2325
+ const getUserRoleAssignment = useCallback(() => {
2326
+ const userRole = permissions?.Role
2327
+ if (!userRole) return null
2328
+ // eslint-disable-next-line security/detect-object-injection
2329
+ const assignment = collection.access?.files?.assignment?.[userRole]
2330
+ return assignment || null
2331
+ }, [collection, permissions])
2332
+
2333
+ const shouldSkipPermissionsDialog = useCallback(() => {
2334
+ const assignment = getUserRoleAssignment()
2335
+ if (!assignment) return false
2336
+ const optional = assignment.optional || {}
2337
+ const hasOptional = Boolean(
2338
+ (optional.read && optional.read.length) ||
2339
+ (optional.update && optional.update.length) ||
2340
+ (optional.delete && optional.delete.length),
2341
+ )
2342
+ return !hasOptional
2343
+ }, [getUserRoleAssignment])
2344
+
2345
+ const getDefaultPermissions = useCallback((): FilePermissions => {
2346
+ const assignment = getUserRoleAssignment()
2347
+ const required = assignment?.required || {}
2348
+ return {
2349
+ read: (required.read || []).join(","),
2350
+ update: (required.update || []).join(","),
2351
+ delete: (required.delete || []).join(","),
2352
+ }
2353
+ }, [getUserRoleAssignment])
2354
+
2325
2355
  const uploadFilesToRecord = useCallback(
2326
2356
  async (targetId: string, files: File[] | FileList, permissions: FilePermissions, customFilename?: string) => {
2327
2357
  if (!files || !currentUser) return
@@ -2407,56 +2437,6 @@ function RecordForm({
2407
2437
  [computeBasePath, currentUser, path, record],
2408
2438
  )
2409
2439
 
2410
- const enqueueImageForCreate = useCallback((fieldName: string, file: File) => {
2411
- setPermissionsContext("image-create")
2412
- setPendingImageFieldName(fieldName)
2413
- setPendingUploadFile(file)
2414
- setPendingUploadField(fieldName)
2415
- setEditingFilename(file.name)
2416
- setIsMultipleFileUpload(false)
2417
- setShowPermissionsDialog(true)
2418
- }, [])
2419
-
2420
- const uploadImageForUpdate = useCallback(async (fieldName: string, file: File) => {
2421
- return await new Promise<void>((resolve) => {
2422
- setPermissionsContext("image-update")
2423
- setPendingImageForUpdate({ fieldName, file })
2424
- setEditingFilename(file.name)
2425
- setIsMultipleFileUpload(false)
2426
- setShowPermissionsDialog(true)
2427
- setImageUpdateResolver(() => resolve)
2428
- })
2429
- }, [])
2430
-
2431
- const handleFormFileUpload = useCallback(async (event: React.ChangeEvent<HTMLInputElement>) => {
2432
- const files = event.target.files
2433
- if (!files) return
2434
- if (files.length === 1) {
2435
- const file = files[0]
2436
- setPendingUploadFile(file)
2437
- setPendingUploadField(null)
2438
- setEditingFilename(file.name)
2439
- setIsMultipleFileUpload(false)
2440
- setShowFilenameDialog(true)
2441
- } else {
2442
- setPendingUploadFiles(Array.from(files))
2443
- setIsMultipleFileUpload(true)
2444
- setShowPermissionsDialog(true)
2445
- }
2446
- event.target.value = ""
2447
- }, [])
2448
-
2449
- const handleConfirmFilename = useCallback(() => {
2450
- if (!pendingUploadFile) return
2451
- const trimmed = editingFilename.trim()
2452
- const validationError = validateStorageName(trimmed)
2453
- if (validationError) {
2454
- toast({ title: "Invalid file name", description: validationError, variant: "destructive" })
2455
- return
2456
- }
2457
- setShowPermissionsDialog(true)
2458
- }, [pendingUploadFile, editingFilename])
2459
-
2460
2440
  const handlePermissionsConfirm = useCallback(
2461
2441
  async (selectedPermissions: FilePermissions) => {
2462
2442
  if (permissionsContext === "files") {
@@ -2620,6 +2600,91 @@ function RecordForm({
2620
2600
  ],
2621
2601
  )
2622
2602
 
2603
+ const enqueueImageForCreate = useCallback(
2604
+ (fieldName: string, file: File) => {
2605
+ if (shouldSkipPermissionsDialog()) {
2606
+ setQueuedImageUploads((prev) => ({
2607
+ ...prev,
2608
+ [fieldName]: { file, permissions: getDefaultPermissions() },
2609
+ }))
2610
+ } else {
2611
+ setPermissionsContext("image-create")
2612
+ setPendingImageFieldName(fieldName)
2613
+ setPendingUploadFile(file)
2614
+ setEditingFilename(file.name)
2615
+ setIsMultipleFileUpload(false)
2616
+ setShowPermissionsDialog(true)
2617
+ }
2618
+ },
2619
+ [shouldSkipPermissionsDialog, getDefaultPermissions],
2620
+ )
2621
+
2622
+ const uploadImageForUpdate = useCallback(
2623
+ async (fieldName: string, file: File) => {
2624
+ return await new Promise<void>((resolve) => {
2625
+ setPermissionsContext("image-update")
2626
+ setPendingImageForUpdate({ fieldName, file })
2627
+ setEditingFilename(file.name)
2628
+ setIsMultipleFileUpload(false)
2629
+ setImageUpdateResolver(() => resolve)
2630
+ if (shouldSkipPermissionsDialog()) {
2631
+ setTimeout(() => handlePermissionsConfirm(getDefaultPermissions()), 0)
2632
+ } else {
2633
+ setShowPermissionsDialog(true)
2634
+ }
2635
+ })
2636
+ },
2637
+ [shouldSkipPermissionsDialog, getDefaultPermissions, handlePermissionsConfirm],
2638
+ )
2639
+
2640
+ const handleFormFileUpload = useCallback(
2641
+ async (event: React.ChangeEvent<HTMLInputElement>) => {
2642
+ const files = event.target.files
2643
+ if (!files) return
2644
+ if (files.length === 1) {
2645
+ const file = files[0]
2646
+ setPendingUploadFile(file)
2647
+ setPendingUploadField(null)
2648
+ setEditingFilename(file.name)
2649
+ setIsMultipleFileUpload(false)
2650
+ setShowFilenameDialog(true)
2651
+ } else {
2652
+ const fileList = Array.from(files)
2653
+ if (shouldSkipPermissionsDialog()) {
2654
+ setQueuedUploads((prev) => [...prev, { files: fileList, permissions: getDefaultPermissions() }])
2655
+ } else {
2656
+ setPendingUploadFiles(fileList)
2657
+ setIsMultipleFileUpload(true)
2658
+ setShowPermissionsDialog(true)
2659
+ }
2660
+ }
2661
+ event.target.value = ""
2662
+ },
2663
+ [shouldSkipPermissionsDialog, getDefaultPermissions],
2664
+ )
2665
+
2666
+ const handleConfirmFilename = useCallback(() => {
2667
+ if (!pendingUploadFile) return
2668
+ const trimmed = editingFilename.trim()
2669
+ const validationError = validateStorageName(trimmed)
2670
+ if (validationError) {
2671
+ toast({ title: "Invalid file name", description: validationError, variant: "destructive" })
2672
+ return
2673
+ }
2674
+ if (shouldSkipPermissionsDialog()) {
2675
+ setQueuedUploads((prev) => [
2676
+ ...prev,
2677
+ { files: [pendingUploadFile], permissions: getDefaultPermissions(), customFilename: trimmed },
2678
+ ])
2679
+ setShowFilenameDialog(false)
2680
+ setPendingUploadFile(null)
2681
+ setPendingUploadField(null)
2682
+ setEditingFilename("")
2683
+ } else {
2684
+ setShowPermissionsDialog(true)
2685
+ }
2686
+ }, [pendingUploadFile, editingFilename, shouldSkipPermissionsDialog, getDefaultPermissions])
2687
+
2623
2688
  const handlePermissionsCancel = useCallback(() => {
2624
2689
  if (permissionsContext === "image-create" && pendingImageFieldName) {
2625
2690
  setTimeout(() => {
@@ -79,7 +79,7 @@ export const getFormattedFieldValue = (
79
79
  if (badge) {
80
80
  if (badge === true) {
81
81
  return (
82
- <Badge variant="outline" className="text-center">
82
+ <Badge variant="outline" className="text-xs text-center">
83
83
  {value}
84
84
  </Badge>
85
85
  )