diff --git a/packages/controlled-vocabulary/package.json b/packages/controlled-vocabulary/package.json index 914221726..980ef2f67 100644 --- a/packages/controlled-vocabulary/package.json +++ b/packages/controlled-vocabulary/package.json @@ -1,6 +1,6 @@ { "name": "@performant-software/controlled-vocabulary", - "version": "2.2.12", + "version": "2.2.13", "description": "A package of components to allow user to configure dropdown elements. Use with the \"controlled_vocabulary\" gem.", "license": "MIT", "main": "./dist/index.cjs.js", @@ -23,8 +23,8 @@ "underscore": "^1.13.2" }, "peerDependencies": { - "@performant-software/semantic-components": "^2.2.12", - "@performant-software/shared-components": "^2.2.12", + "@performant-software/semantic-components": "^2.2.13", + "@performant-software/shared-components": "^2.2.13", "react": ">= 16.13.1 < 19.0.0", "react-dom": ">= 16.13.1 < 19.0.0" }, diff --git a/packages/core-data/package.json b/packages/core-data/package.json index 8fbb34f2a..429cf38dc 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@performant-software/core-data", - "version": "2.2.12", + "version": "2.2.13", "description": "A package of components used with the Core Data platform.", "license": "MIT", "main": "./dist/index.cjs.js", @@ -40,8 +40,8 @@ "underscore": "^1.13.2" }, "peerDependencies": { - "@performant-software/geospatial": "^2.2.12", - "@performant-software/shared-components": "^2.2.12", + "@performant-software/geospatial": "^2.2.13", + "@performant-software/shared-components": "^2.2.13", "@peripleo/maplibre": "^0.5.2", "@peripleo/peripleo": "^0.5.2", "react": ">= 16.13.1 < 19.0.0", diff --git a/packages/geospatial/package.json b/packages/geospatial/package.json index 8156aa35f..7ed495eab 100644 --- a/packages/geospatial/package.json +++ b/packages/geospatial/package.json @@ -1,6 +1,6 @@ { "name": "@performant-software/geospatial", - "version": "2.2.12", + "version": "2.2.13", "description": "A package of components for all things map-related.", "license": "MIT", "main": "./dist/index.cjs.js", diff --git a/packages/semantic-ui/package.json b/packages/semantic-ui/package.json index 3209e1952..be80dc5a5 100644 --- a/packages/semantic-ui/package.json +++ b/packages/semantic-ui/package.json @@ -1,6 +1,6 @@ { "name": "@performant-software/semantic-components", - "version": "2.2.12", + "version": "2.2.13", "description": "A package of shared components based on the Semantic UI Framework.", "license": "MIT", "main": "./dist/index.cjs.js", @@ -35,7 +35,7 @@ "zotero-translation-client": "^5.0.1" }, "peerDependencies": { - "@performant-software/shared-components": "^2.2.12", + "@performant-software/shared-components": "^2.2.13", "@samvera/clover-iiif": "^2.3.2", "react": ">= 16.13.1 < 19.0.0", "react-dnd": "^11.1.3", diff --git a/packages/semantic-ui/src/components/DataTable.js b/packages/semantic-ui/src/components/DataTable.js index 013e790a2..cea9169be 100644 --- a/packages/semantic-ui/src/components/DataTable.js +++ b/packages/semantic-ui/src/components/DataTable.js @@ -14,11 +14,9 @@ import _ from 'underscore'; import i18n from '../i18n/i18n'; import ColumnResize from './ColumnResize'; import useColumnSelector, { type Props as ColumnSelectorProps } from './DataTableColumnSelector'; -import useList, { type Props as ListProps } from './List'; +import useList, { type Action, type Props as ListProps } from './List'; import './DataTable.css'; -import type { Action } from './List'; - type Props = ListProps & ColumnSelectorProps & { /** * If <code>true</code>, the rows of the table can be expanded and collapsed. @@ -302,9 +300,13 @@ class DataTable extends Component<Props, State> { return action.render(item, index); } + const { asProps = () => ({}) } = action; + const actionButton = ( <Button aria-label={action.name} + as={action.as} + {...asProps(item)} basic compact color={action.color} @@ -348,36 +350,7 @@ class DataTable extends Component<Props, State> { return null; } - const actions = this.props.actions - .filter((action) => !action.accept || action.accept(item)) - .map((action) => { - let defaults = {}; - - if (action.name === 'edit') { - defaults = { - popup: { - title: i18n.t('DataTable.actions.edit.title'), - content: i18n.t('DataTable.actions.edit.content') - } - }; - } else if (action.name === 'copy') { - defaults = { - popup: { - title: i18n.t('DataTable.actions.copy.title'), - content: i18n.t('DataTable.actions.copy.content') - } - }; - } else if (action.name === 'delete') { - defaults = { - popup: { - title: i18n.t('DataTable.actions.delete.title'), - content: i18n.t('DataTable.actions.delete.content') - } - }; - } - - return _.defaults(action, defaults); - }); + const actions = this.props.actions.filter((action) => !action.accept || action.accept(item)); return ( <Table.Cell diff --git a/packages/semantic-ui/src/components/Items.js b/packages/semantic-ui/src/components/Items.js index f65d01fa0..752a74456 100644 --- a/packages/semantic-ui/src/components/Items.js +++ b/packages/semantic-ui/src/components/Items.js @@ -8,6 +8,7 @@ import { Header, Icon, Item, + Popup, Segment } from 'semantic-ui-react'; import _ from 'underscore'; @@ -267,17 +268,7 @@ class ItemsClass extends Component<Props, {}> { extra textAlign='center' > - { _.map(actions, (action, actionIndex) => ( - <Button - aria-label={action.name} - basic - color={action.resolveColor ? action.resolveColor(item) : action.color} - icon={action.resolveIcon ? action.resolveIcon(item) : action.icon} - key={actionIndex} - onClick={action.onClick.bind(this, item)} - size={action.size} - /> - ))} + { _.map(actions, this.renderCardAction.bind(this, item)) } { this.isSelectable() && ( <Button aria-label='Select' @@ -309,6 +300,49 @@ class ItemsClass extends Component<Props, {}> { return card; } + /** + * Renders the action button for the passed item. + * + * @param action + * @param index + * @param item + * + * @returns {JSX.Element} + */ + renderCardAction(item, action, index) { + const actionButton = ( + <Button + as={action.as} + {...((action.asProps && action.asProps(item)) || {})} + aria-label={action.name} + basic + color={action.resolveColor ? action.resolveColor(item) : action.color} + icon={action.resolveIcon ? action.resolveIcon(item) : action.icon} + key={index} + onClick={action.onClick && action.onClick.bind(this, item)} + size={action.size} + /> + ); + + // Wrap the button in a popup if the action specifies a popup attribute + if (action.popup) { + const { content, title } = action.popup; + + return ( + <Popup + content={content} + header={title} + hideOnScroll + mouseEnterDelay={500} + position='top right' + trigger={actionButton} + /> + ); + } + + return actionButton; + } + /** * Renders the empty list. * @@ -405,12 +439,14 @@ class ItemsClass extends Component<Props, {}> { )} { _.map(this.getActions(item), (action, actionIndex) => ( <Button + as={action.as} + {...((action.asProps && action.asProps(item)) || {})} basic={action.basic} color={action.resolveColor ? action.resolveColor(item) : action.color} content={action.resolveName ? action.resolveName(item) : action.label} key={actionIndex} icon={action.resolveIcon ? action.resolveIcon(item) : action.icon} - onClick={action.onClick.bind(this, item)} + onClick={action.onClick && action.onClick.bind(this, item)} size={action.size} /> ))} diff --git a/packages/semantic-ui/src/components/List.js b/packages/semantic-ui/src/components/List.js index 1f38135f9..e4ae02c0b 100644 --- a/packages/semantic-ui/src/components/List.js +++ b/packages/semantic-ui/src/components/List.js @@ -20,6 +20,8 @@ import './List.css'; type Action = { accept: (item: any) => boolean, + as: ComponentType, + asProps: () => any, color?: string, icon?: string, name: string, @@ -525,17 +527,29 @@ const useList = (WrappedComponent: ComponentType<any>) => ( if (action.name === 'edit') { defaults = { icon: 'edit outline', - onClick: this.onEditButton.bind(this) + onClick: this.onEditButton.bind(this), + popup: { + title: i18n.t('Common.actions.edit.title'), + content: i18n.t('Common.actions.edit.content') + } }; } else if (action.name === 'copy') { defaults = { icon: 'copy outline', - onClick: this.onCopyButton.bind(this) + onClick: this.onCopyButton.bind(this), + popup: { + title: i18n.t('Common.actions.copy.title'), + content: i18n.t('Common.actions.copy.content') + } }; } else if (action.name === 'delete') { defaults = { icon: 'times circle outline', - onClick: this.onDeleteButton.bind(this) + onClick: this.onDeleteButton.bind(this), + popup: { + title: i18n.t('Common.actions.delete.title'), + content: i18n.t('Common.actions.delete.content') + } }; } diff --git a/packages/semantic-ui/src/i18n/en.json b/packages/semantic-ui/src/i18n/en.json index bb944a165..57e33bdbe 100644 --- a/packages/semantic-ui/src/i18n/en.json +++ b/packages/semantic-ui/src/i18n/en.json @@ -42,6 +42,20 @@ } }, "Common": { + "actions": { + "copy": { + "content": "Creates an editable copy to be saved as a new record", + "title": "Copy" + }, + "delete": { + "content": "Removes the record, permanently", + "title": "Remove" + }, + "edit": { + "content": "Opens the modal to edit the record", + "title": "Edit" + } + }, "buttons": { "add": "Add", "cancel": "Cancel", diff --git a/packages/shared/package.json b/packages/shared/package.json index 4bd71f5b7..b176437ed 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,6 +1,6 @@ { "name": "@performant-software/shared-components", - "version": "2.2.12", + "version": "2.2.13", "description": "A package of shared, framework agnostic, components.", "license": "MIT", "main": "./dist/index.cjs.js", diff --git a/packages/storybook/src/semantic-ui/DataTable.stories.js b/packages/storybook/src/semantic-ui/DataTable.stories.js index 75b226551..f1088bf8e 100644 --- a/packages/storybook/src/semantic-ui/DataTable.stories.js +++ b/packages/storybook/src/semantic-ui/DataTable.stories.js @@ -208,6 +208,14 @@ export const CustomActions = useDragDrop(() => ( name: 'coffee', icon: 'coffee', onClick: action('coffee-click') + }, { + as: 'a', + asProps: () => ({ + href: 'https://performantsoftware.com', + target: '_blank' + }), + name: 'link', + icon: 'linkify' }]} columns={columns} items={items} diff --git a/packages/storybook/src/semantic-ui/Items.stories.js b/packages/storybook/src/semantic-ui/Items.stories.js index aca473536..a723ebdc8 100644 --- a/packages/storybook/src/semantic-ui/Items.stories.js +++ b/packages/storybook/src/semantic-ui/Items.stories.js @@ -90,6 +90,19 @@ export const CustomActions = useDragDrop(() => ( name: 'coffee', icon: 'coffee', onClick: action('coffee-click') + }, { + as: 'a', + asProps: () => ({ + href: 'https://performantsoftware.com', + target: '_blank' + }), + basic: true, + icon: 'linkify', + label: 'Link', + popup: { + content: 'Testing popup', + title: 'POPUP!' + } }]} items={items} onCopy={action('copy')} @@ -197,4 +210,4 @@ export const ButtonSize = useDragDrop(() => ( renderHeader={(item) => <Header content={item.header} />} renderMeta={(item) => item.id} /> -)); \ No newline at end of file +)); diff --git a/packages/user-defined-fields/package.json b/packages/user-defined-fields/package.json index 1a84a5751..d540db937 100644 --- a/packages/user-defined-fields/package.json +++ b/packages/user-defined-fields/package.json @@ -1,6 +1,6 @@ { "name": "@performant-software/user-defined-fields", - "version": "2.2.12", + "version": "2.2.13", "description": "A package of components used for allowing end users to define fields on models. Use with the \"user_defined_fields\" gem.", "license": "MIT", "main": "./dist/index.cjs.js", @@ -23,8 +23,8 @@ "underscore": "^1.13.2" }, "peerDependencies": { - "@performant-software/semantic-components": "^2.2.12", - "@performant-software/shared-components": "^2.2.12", + "@performant-software/semantic-components": "^2.2.13", + "@performant-software/shared-components": "^2.2.13", "react": ">= 16.13.1 < 19.0.0", "react-dom": ">= 16.13.1 < 19.0.0" }, diff --git a/packages/visualize/package.json b/packages/visualize/package.json index 647623881..e1ec9dade 100644 --- a/packages/visualize/package.json +++ b/packages/visualize/package.json @@ -1,6 +1,6 @@ { "name": "@performant-software/visualize", - "version": "2.2.12", + "version": "2.2.13", "description": "A package of components used for data visualization", "license": "MIT", "main": "./dist/index.cjs.js", diff --git a/react-components.json b/react-components.json index 0c39ff0d8..044205b5f 100644 --- a/react-components.json +++ b/react-components.json @@ -8,5 +8,5 @@ "packages/user-defined-fields", "packages/visualize" ], - "version": "2.2.12" + "version": "2.2.13" }