Skip to content

Commit

Permalink
Merge pull request #156 from performant-software/feature/udcsl28_media
Browse files Browse the repository at this point in the history
UDCSL #28 - Media
  • Loading branch information
dleadbetter authored Jul 26, 2022
2 parents 9ff7076 + 2474a2f commit 3e87376
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 0 deletions.
79 changes: 79 additions & 0 deletions packages/semantic-ui/src/components/KeyValuePairs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// @flow

import React, { type ComponentType } from 'react';
import { Button, Grid, Input } from 'semantic-ui-react';
import _ from 'underscore';
import i18n from '../i18n/i18n';
import withBatchEdit, { type BatchEditProps } from '../hooks/BatchEdit';

type Item = {
key: string,
value: string
};

type Props = BatchEditProps & {
items: Array<Item>,
onChange: (items: Array<Item>) => void
};

const KeyValuePairs: ComponentType<any> = withBatchEdit((props: Props) => (
<div>
<Button
basic
content={i18n.t('Common.buttons.add')}
icon='plus'
onClick={props.onAddItem.bind(this)}
type='button'
/>
<Grid
padded='vertically'
>
{ _.map(props.items, (item, index) => (
<Grid.Row
columns={3}
>
<Grid.Column
width={8}
>
<Input
fluid
onChange={props.onUpdateItem.bind(this, index, 'key')}
placeholder={i18n.t('KeyValuePairs.labels.key')}
value={item.key}
/>
</Grid.Column>
<Grid.Column
width={7}
>
<Input
fluid
onChange={props.onUpdateItem.bind(this, index, 'value')}
placeholder={i18n.t('KeyValuePairs.labels.value')}
value={item.value}
/>
</Grid.Column>
<Grid.Column
width={1}
>
<Button
color='red'
icon='trash'
onClick={props.onRemoveItem.bind(this, index)}
/>
</Grid.Column>
</Grid.Row>
))}
{ _.isEmpty(props.items) && (
<Grid.Row
columns={1}
>
<Grid.Column>
{ i18n.t('Common.labels.noRecords') }
</Grid.Column>
</Grid.Row>
)}
</Grid>
</div>
));

export default KeyValuePairs;
57 changes: 57 additions & 0 deletions packages/semantic-ui/src/hooks/BatchEdit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// @flow

import React, { useCallback, type ComponentType } from 'react';
import _ from 'underscore';

type Props = {
items: Array<any>,
onChange: (items: Array<any>) => void
};

const withBatchEdit = (WrappedComponent: ComponentType<any>): any => (props: Props) => {
/**
* Adds a new item to the list.
*
* @type {(function(): void)|*}
*/
const onAddItem = useCallback(() => {
props.onChange([...props.items, {}]);
}, [props.items]);

/**
* Removes the item at the passed index from the list.
*
* @type {(function(*): void)|*}
*/
const onRemoveItem = useCallback((findIndex) => {
props.onChange(_.reject(props.items, (item, index) => index === findIndex));
}, [props.items]);

/**
* Updates the passed attribute of the item at the passed index.
*
* @type {(function(number, string, ?Event, {value: *}): void)|*}
*/
const onUpdateItem = useCallback((findIndex: number, attribute: string, e: ?Event, { value }) => {
props.onChange(_.map(props.items, (item, index) => (
index !== findIndex ? item : ({ ...item, [attribute]: value })
)));
}, [props.items]);

return (
<WrappedComponent
{...props}
onAddItem={onAddItem}
onRemoveItem={onRemoveItem}
onUpdateItem={onUpdateItem}
/>
);
};

export default withBatchEdit;

export type BatchEditProps = {
onAddItem: () => void,
onRemoveItem: (index: number) => void,
onUpdateItem: (index: number, attribute: string, e: Event, data: any) => void
};
9 changes: 9 additions & 0 deletions packages/semantic-ui/src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
"errors": {
"title": "Oops!"
},
"labels": {
"noRecords": "No records."
},
"messages": {
"error": {
"header": "Oops!"
Expand Down Expand Up @@ -126,6 +129,12 @@
"showKeyboard": "Show Keyboard"
}
},
"KeyValuePairs": {
"labels": {
"key": "Key",
"value": "Value"
}
},
"LazyDocument": {
"buttons": {
"download": "Download"
Expand Down
5 changes: 5 additions & 0 deletions packages/semantic-ui/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export { default as ItemCollection } from './components/ItemCollection';
export { default as ItemList } from './components/ItemList';
export { default as Items } from './components/Items';
export { default as KeyboardField } from './components/KeyboardField';
export { default as KeyValuePairs } from './components/KeyValuePairs';
export { default as LazyDocument } from './components/LazyDocument';
export { default as LazyImage } from './components/LazyImage';
export { default as LazyVideo } from './components/LazyVideo';
Expand Down Expand Up @@ -77,10 +78,14 @@ export { default as VideoPlayer } from './components/VideoPlayer';
export { default as VideoPlayerButton } from './components/VideoPlayerButton';
export { default as ViewXML } from './components/ViewXML';

// Hooks
export { default as BatchEdit } from './hooks/BatchEdit';

// Types
export type { EditPageProps } from './components/EditPage';
export type { FileUploadProps } from './components/FileUploadModal';
export type { Props as ListProps } from './components/List';
export type { BatchEditProps } from './hooks/BatchEdit';

// Constants
export { SORT_ASCENDING, SORT_DESCENDING } from './components/DataList';
Expand Down
39 changes: 39 additions & 0 deletions packages/storybook/src/semantic-ui/KeyValuePairs.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// @flow

import React, { useState } from 'react';
import { withA11y } from '@storybook/addon-a11y';
import { withKnobs } from '@storybook/addon-knobs';
import KeyValuePairs from '../../../semantic-ui/src/components/KeyValuePairs';

export default {
title: 'Components/Semantic UI/KeyValuePairs',
decorators: [withA11y, withKnobs]
};

export const Default = () => {
const [value, setValue] = useState('[]');

return (
<KeyValuePairs
items={JSON.parse(value)}
onChange={(items) => setValue(JSON.stringify(items))}
/>
);
};

export const withExistingValue = () => {
const [value, setValue] = useState(JSON.stringify([{
key: 'One',
value: 'First record'
}, {
key: 'Two',
value: 'Second record'
}]));

return (
<KeyValuePairs
items={JSON.parse(value)}
onChange={(items) => setValue(JSON.stringify(items))}
/>
);
};

0 comments on commit 3e87376

Please sign in to comment.