row-grid-button.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import { useState, useRef } from 'react';
  2. import { Platform } from 'react-native';
  3. import { NeoButton, NeoButtonLink } from 'app/design/controls';
  4. import DropdownMenu from 'app/ui/atoms/dropdown-menu';
  5. import Redirect from 'app/ui/atoms/redirect';
  6. import { getDataForMenu } from 'app/lib/util';
  7. import { getActionButtonIcon } from './actions';
  8. import { useGrid } from './context';
  9. /** Row actions UNA should not render as icon buttons. */
  10. const EXCLUDED_ROW_ACTIONS = new Set(['clear_reports', 'set_acl_level']);
  11. /**
  12. * One control in a grid row's actions cell (link / modal / menu / callback / object).
  13. * Everything it needs comes from the grid store, so rows pass ids only.
  14. */
  15. export default function RowGridButton({ id, itemAction }) {
  16. const [hide, setHide] = useState(false);
  17. const [menuData, setMenuData] = useState(false);
  18. const redirectRef = useRef();
  19. const openRowAction = useGrid((state) => state.openRowAction);
  20. const runRowCallback = useGrid((state) => state.runRowCallback);
  21. const runMenuCallback = useGrid((state) => state.runMenuCallback);
  22. const icon = getActionButtonIcon(itemAction.name, itemAction.icon);
  23. if (EXCLUDED_ROW_ACTIONS.has(itemAction.name) || hide) {
  24. return <></>;
  25. }
  26. const commonProps = {
  27. style: 'borderless',
  28. controlSize: 'small',
  29. label: icon ? undefined : itemAction.title,
  30. image: icon || undefined,
  31. accessibilityLabel: itemAction.title,
  32. };
  33. if (itemAction.type === 'link') {
  34. return (
  35. <NeoButtonLink href={itemAction.url} {...commonProps} />
  36. );
  37. }
  38. if (itemAction.type === 'modal' || itemAction.type === 'object') {
  39. return (
  40. <NeoButton
  41. {...commonProps}
  42. onPress={() => {
  43. openRowAction(itemAction);
  44. }}
  45. />
  46. );
  47. }
  48. if (itemAction.type === 'menu') {
  49. return (
  50. <>
  51. {!menuData ? <NeoButton
  52. style="borderless"
  53. controlSize="small"
  54. image="Ellipsis"
  55. accessibilityLabel={itemAction.title || 'Actions'}
  56. onPress={() => {
  57. if (Platform.OS === 'web')
  58. setMenuData({
  59. ...itemAction,
  60. items: [{ name: 'loader' }],
  61. })
  62. getDataForMenu(itemAction, setMenuData)
  63. }}
  64. /> : <DropdownMenu
  65. mode="popup"
  66. items={menuData.items}
  67. defaultOpen={true}
  68. onSelect={(oItem) => runMenuCallback(oItem, id, setHide)}
  69. >
  70. <NeoButton
  71. style="borderless"
  72. controlSize="small"
  73. image="Ellipsis"
  74. accessibilityLabel={itemAction.title || 'Actions'}
  75. interactive
  76. />
  77. </DropdownMenu>}
  78. </>
  79. );
  80. }
  81. if (itemAction.type === 'callback') {
  82. return (
  83. <>
  84. <Redirect ref={redirectRef} />
  85. <NeoButton
  86. {...commonProps}
  87. onPress={() => runRowCallback(itemAction, id, redirectRef)}
  88. />
  89. </>
  90. );
  91. }
  92. return null;
  93. }