@strapi/content-manager 5.17.0-beta.0 → 5.17.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.
@@ -13,6 +13,8 @@ var reactWindow = require('react-window');
13
13
  var styledComponents = require('styled-components');
14
14
  var collections = require('../../../../../constants/collections.js');
15
15
  var dragAndDrop = require('../../../../../constants/dragAndDrop.js');
16
+ var plugin = require('../../../../../constants/plugin.js');
17
+ var DocumentRBAC = require('../../../../../features/DocumentRBAC.js');
16
18
  var useDebounce = require('../../../../../hooks/useDebounce.js');
17
19
  var useDocument = require('../../../../../hooks/useDocument.js');
18
20
  var useDocumentContext = require('../../../../../hooks/useDocumentContext.js');
@@ -328,7 +330,6 @@ const ONE_WAY_RELATIONS = [
328
330
  * @description Contains all the logic for the combobox that can search
329
331
  * for relations and then add them to the field's connect array.
330
332
  */ const RelationsInput = ({ hint, id, model, label, labelAction, name, mainField, placeholder, required, unique: _unique, 'aria-label': _ariaLabel, onChange, isRelatedToCurrentDocument, ...props })=>{
331
- const [textValue, setTextValue] = React__namespace.useState('');
332
333
  const [searchParams, setSearchParams] = React__namespace.useState({
333
334
  _q: '',
334
335
  page: 1
@@ -336,7 +337,6 @@ const ONE_WAY_RELATIONS = [
336
337
  const { toggleNotification } = strapiAdmin.useNotification();
337
338
  const { currentDocumentMeta } = useDocumentContext.useDocumentContext('RelationsInput');
338
339
  const { formatMessage } = reactIntl.useIntl();
339
- const fieldRef = strapiAdmin.useFocusInputField(name);
340
340
  const field = strapiAdmin.useField(name);
341
341
  const searchParamsDebounced = useDebounce.useDebounce(searchParams, 300);
342
342
  const [searchForTrigger, { data, isLoading }] = relations.useLazySearchRelationsQuery();
@@ -377,13 +377,6 @@ const ONE_WAY_RELATIONS = [
377
377
  isRelatedToCurrentDocument,
378
378
  currentDocumentMeta.params
379
379
  ]);
380
- const handleSearch = async (search)=>{
381
- setSearchParams((s)=>({
382
- ...s,
383
- _q: search,
384
- page: 1
385
- }));
386
- };
387
380
  const hasNextPage = data?.pagination ? data.pagination.page < data.pagination.pageCount : false;
388
381
  const options = data?.results ?? [];
389
382
  const handleChange = (relationId)=>{
@@ -411,21 +404,6 @@ const ONE_WAY_RELATIONS = [
411
404
  *
412
405
  */ onChange(relation);
413
406
  };
414
- const handleLoadMore = ()=>{
415
- if (!data || !data.pagination) {
416
- return;
417
- } else if (data.pagination.page < data.pagination.pageCount) {
418
- setSearchParams((s)=>({
419
- ...s,
420
- page: s.page + 1
421
- }));
422
- }
423
- };
424
- React__namespace.useLayoutEffect(()=>{
425
- setTextValue('');
426
- }, [
427
- field.value
428
- ]);
429
407
  const relation = {
430
408
  collectionType: collections.COLLECTION_TYPES,
431
409
  // @ts-expect-error – targetModel does exist on the attribute. But it's not typed.
@@ -433,9 +411,26 @@ const ONE_WAY_RELATIONS = [
433
411
  documentId: '',
434
412
  params: currentDocumentMeta.params
435
413
  };
436
- const { componentUID } = ComponentContext.useComponent('RelationsField', ({ uid })=>({
437
- componentUID: uid
438
- }));
414
+ const { permissions = [], isLoading: isLoadingPermissions, error } = strapiAdmin.useRBAC(plugin.PERMISSIONS.map((action)=>({
415
+ action,
416
+ subject: relation.model
417
+ })));
418
+ if (error) {
419
+ return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
420
+ alignItems: "center",
421
+ height: "100%",
422
+ justifyContent: "center",
423
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.EmptyStateLayout, {
424
+ icon: /*#__PURE__*/ jsxRuntime.jsx(Icons.WarningCircle, {
425
+ width: "16rem"
426
+ }),
427
+ content: formatMessage({
428
+ id: 'anErrorOccurred',
429
+ defaultMessage: 'Whoops! Something went wrong. Please, try again.'
430
+ })
431
+ })
432
+ });
433
+ }
439
434
  return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Field.Root, {
440
435
  error: field.error,
441
436
  hint: hint,
@@ -446,90 +441,143 @@ const ONE_WAY_RELATIONS = [
446
441
  action: labelAction,
447
442
  children: label
448
443
  }),
449
- /*#__PURE__*/ jsxRuntime.jsx(RelationModal.RelationModalRenderer, {
450
- children: ({ dispatch })=>/*#__PURE__*/ jsxRuntime.jsx(designSystem.Combobox, {
451
- ref: fieldRef,
452
- creatable: "visible",
453
- createMessage: ()=>formatMessage({
454
- id: translations.getTranslation('relation.create'),
455
- defaultMessage: 'Create a relation'
456
- }),
457
- onCreateOption: ()=>{
458
- dispatch({
459
- type: 'GO_TO_RELATION',
460
- payload: {
461
- document: relation,
462
- shouldBypassConfirmation: false,
463
- fieldToConnect: name,
464
- fieldToConnectUID: componentUID
465
- }
466
- });
467
- },
468
- creatableStartIcon: /*#__PURE__*/ jsxRuntime.jsx(Icons.Plus, {
469
- fill: "neutral500"
470
- }),
471
- name: name,
472
- autocomplete: "list",
473
- placeholder: placeholder || formatMessage({
474
- id: translations.getTranslation('relation.add'),
475
- defaultMessage: 'Add relation'
476
- }),
477
- hasMoreItems: hasNextPage,
478
- loading: isLoading,
479
- onOpenChange: ()=>{
480
- handleSearch(textValue ?? '');
481
- },
482
- noOptionsMessage: ()=>formatMessage({
483
- id: translations.getTranslation('relation.notAvailable'),
484
- defaultMessage: 'No relations available'
485
- }),
486
- loadingMessage: formatMessage({
487
- id: translations.getTranslation('relation.isLoading'),
488
- defaultMessage: 'Relations are loading'
489
- }),
490
- onLoadMore: handleLoadMore,
444
+ /*#__PURE__*/ jsxRuntime.jsx(DocumentRBAC.DocumentRBAC, {
445
+ permissions: permissions,
446
+ model: relation.model,
447
+ children: /*#__PURE__*/ jsxRuntime.jsx(RelationModalWithContext, {
448
+ relation: relation,
449
+ name: name,
450
+ placeholder: placeholder,
451
+ hasNextPage: hasNextPage,
452
+ isLoadingPermissions: isLoadingPermissions,
453
+ isLoadingSearchRelations: isLoading,
454
+ handleChange: handleChange,
455
+ setSearchParams: setSearchParams,
456
+ data: data,
457
+ mainField: mainField,
458
+ fieldValue: field.value,
459
+ ...props
460
+ })
461
+ }),
462
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Error, {}),
463
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Hint, {})
464
+ ]
465
+ });
466
+ };
467
+ const RelationModalWithContext = ({ relation, name, placeholder, hasNextPage, isLoadingSearchRelations, isLoadingPermissions, handleChange, mainField, setSearchParams, fieldValue, data, ...props })=>{
468
+ const [textValue, setTextValue] = React__namespace.useState('');
469
+ const { formatMessage } = reactIntl.useIntl();
470
+ const canCreate = DocumentRBAC.useDocumentRBAC('RelationModalWrapper', (state)=>state.canCreate);
471
+ const fieldRef = strapiAdmin.useFocusInputField(name);
472
+ const { componentUID } = ComponentContext.useComponent('RelationsField', ({ uid })=>({
473
+ componentUID: uid
474
+ }));
475
+ const handleLoadMore = ()=>{
476
+ if (!data || !data.pagination) {
477
+ return;
478
+ } else if (data.pagination.page < data.pagination.pageCount) {
479
+ setSearchParams((s)=>({
480
+ ...s,
481
+ page: s.page + 1
482
+ }));
483
+ }
484
+ };
485
+ const options = data?.results ?? [];
486
+ React__namespace.useLayoutEffect(()=>{
487
+ setTextValue('');
488
+ }, [
489
+ fieldValue
490
+ ]);
491
+ const handleSearch = async (search)=>{
492
+ setSearchParams((s)=>({
493
+ ...s,
494
+ _q: search,
495
+ page: 1
496
+ }));
497
+ };
498
+ return /*#__PURE__*/ jsxRuntime.jsx(RelationModal.RelationModalRenderer, {
499
+ children: ({ dispatch })=>/*#__PURE__*/ jsxRuntime.jsx(designSystem.Combobox, {
500
+ ref: fieldRef,
501
+ creatable: "visible",
502
+ creatableDisabled: !canCreate,
503
+ createMessage: ()=>formatMessage({
504
+ id: translations.getTranslation('relation.create'),
505
+ defaultMessage: 'Create a relation'
506
+ }),
507
+ onCreateOption: ()=>{
508
+ if (canCreate) {
509
+ dispatch({
510
+ type: 'GO_TO_RELATION',
511
+ payload: {
512
+ document: relation,
513
+ shouldBypassConfirmation: false,
514
+ fieldToConnect: name,
515
+ fieldToConnectUID: componentUID
516
+ }
517
+ });
518
+ }
519
+ },
520
+ creatableStartIcon: /*#__PURE__*/ jsxRuntime.jsx(Icons.Plus, {
521
+ fill: "neutral500"
522
+ }),
523
+ name: name,
524
+ autocomplete: "list",
525
+ placeholder: placeholder || formatMessage({
526
+ id: translations.getTranslation('relation.add'),
527
+ defaultMessage: 'Add relation'
528
+ }),
529
+ hasMoreItems: hasNextPage,
530
+ loading: isLoadingSearchRelations || isLoadingPermissions,
531
+ onOpenChange: ()=>{
532
+ handleSearch(textValue ?? '');
533
+ },
534
+ noOptionsMessage: ()=>formatMessage({
535
+ id: translations.getTranslation('relation.notAvailable'),
536
+ defaultMessage: 'No relations available'
537
+ }),
538
+ loadingMessage: formatMessage({
539
+ id: translations.getTranslation('relation.isLoading'),
540
+ defaultMessage: 'Relations are loading'
541
+ }),
542
+ onLoadMore: handleLoadMore,
543
+ textValue: textValue,
544
+ onChange: handleChange,
545
+ onTextValueChange: (text)=>{
546
+ setTextValue(text);
547
+ },
548
+ onInputChange: (event)=>{
549
+ handleSearch(event.currentTarget.value);
550
+ },
551
+ ...props,
552
+ children: options?.map((opt)=>{
553
+ const textValue = relations$1.getRelationLabel(opt, mainField);
554
+ return /*#__PURE__*/ jsxRuntime.jsx(designSystem.ComboboxOption, {
555
+ value: opt.id.toString(),
491
556
  textValue: textValue,
492
- onChange: handleChange,
493
- onTextValueChange: (text)=>{
494
- setTextValue(text);
495
- },
496
- onInputChange: (event)=>{
497
- handleSearch(event.currentTarget.value);
498
- },
499
- ...props,
500
- children: options.map((opt)=>{
501
- const textValue = relations$1.getRelationLabel(opt, mainField);
502
- return /*#__PURE__*/ jsxRuntime.jsx(designSystem.ComboboxOption, {
503
- value: opt.id.toString(),
504
- textValue: textValue,
505
- children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
557
+ children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
558
+ gap: 2,
559
+ justifyContent: "space-between",
560
+ children: [
561
+ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
506
562
  gap: 2,
507
- justifyContent: "space-between",
508
563
  children: [
509
- /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
510
- gap: 2,
511
- children: [
512
- /*#__PURE__*/ jsxRuntime.jsx(Icons.Link, {
513
- fill: "neutral500"
514
- }),
515
- /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
516
- ellipsis: true,
517
- children: textValue
518
- })
519
- ]
564
+ /*#__PURE__*/ jsxRuntime.jsx(Icons.Link, {
565
+ fill: "neutral500"
520
566
  }),
521
- opt.status ? /*#__PURE__*/ jsxRuntime.jsx(DocumentStatus.DocumentStatus, {
522
- status: opt.status
523
- }) : null
567
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
568
+ ellipsis: true,
569
+ children: textValue
570
+ })
524
571
  ]
525
- })
526
- }, opt.id);
572
+ }),
573
+ opt.status ? /*#__PURE__*/ jsxRuntime.jsx(DocumentStatus.DocumentStatus, {
574
+ status: opt.status
575
+ }) : null
576
+ ]
527
577
  })
528
- })
529
- }),
530
- /*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Error, {}),
531
- /*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Hint, {})
532
- ]
578
+ }, opt.id);
579
+ })
580
+ })
533
581
  });
534
582
  };
535
583
  /* -------------------------------------------------------------------------------------------------