Skip to content

Commit

Permalink
Merge pull request #157 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 27, 2022
2 parents 3e87376 + 5ad3f47 commit 6fe68d1
Show file tree
Hide file tree
Showing 12 changed files with 313 additions and 0 deletions.
81 changes: 81 additions & 0 deletions packages/semantic-ui/src/components/ReferenceCodeFormDropdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// @flow

import { ReferenceTablesService } from '@performant-software/shared-components';
import React, { type ComponentType, useEffect, useState } from 'react';
import { Form } from 'semantic-ui-react';
import EditModal from './EditModal';
import ReferenceCodeDropdown from './ReferenceCodeDropdown';
import ReferenceCodeFormLabel from './ReferenceCodeFormLabel';
import ReferenceTableModal from './ReferenceTableModal';

type Props = {
error?: boolean,
label?: string,
required?: boolean,
referenceTable: string
};

const ReferenceCodeFormDropdown: ComponentType<any> = (props: Props) => {
const {
error,
label,
required,
referenceTable: key,
...rest
} = props;

const [modal, setModal] = useState(false);
const [dropdownKey, setDropdownKey] = useState(0);
const [referenceTable, setReferenceTable] = useState({ key });

/**
* Looks up the existing reference table base on the passed key.
*/
useEffect(() => (
ReferenceTablesService
.fetchByKey(key)
.then(({ data }) => setReferenceTable((prevTable) => ({
...prevTable,
...data.reference_table
})))
), [key]);

return (
<>
<Form.Input
error={error}
label={(
<ReferenceCodeFormLabel
label={label}
onClick={() => setModal(true)}
referenceTable={referenceTable.key}
/>
)}
required={required}
>
<ReferenceCodeDropdown
{...rest}
id={referenceTable}
referenceTable={referenceTable.key}
key={dropdownKey}
/>
</Form.Input>
{ modal && (
<EditModal
component={ReferenceTableModal}
item={referenceTable}
onClose={() => setModal(false)}
onSave={(record) => (
ReferenceTablesService
.save(record)
.then(({ data }) => data.reference_table)
.then(() => setDropdownKey((prevKey) => prevKey + 1))
.finally(() => setModal(false))
)}
/>
)}
</>
);
};

export default ReferenceCodeFormDropdown;
51 changes: 51 additions & 0 deletions packages/semantic-ui/src/components/ReferenceCodeFormLabel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// @flow

import React, { type ComponentType } from 'react';
import { withTranslation } from 'react-i18next';
import {
Button,
Header,
Icon,
Popup
} from 'semantic-ui-react';
import i18n from '../i18n/i18n';

type Props = {
label: string,
onClick: () => void,
referenceTable: string
};

const ReferenceCodeFormLabel: ComponentType<any> = withTranslation()((props: Props) => (
<div>
<label
htmlFor={props.referenceTable}
>
{ props.label }
</label>
<Popup
hoverable
trigger={(
<Icon
name='info circle'
style={{
marginLeft: '0.3em'
}}
/>
)}
>
<Header
content={props.label}
/>
<p>{ i18n.t('ReferenceCodeFormLabel.content', { name: props.label })}</p>
<Button
content={i18n.t('Common.buttons.edit')}
icon='edit'
primary
onClick={props.onClick}
/>
</Popup>
</div>
));

export default ReferenceCodeFormLabel;
3 changes: 3 additions & 0 deletions packages/semantic-ui/src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@
"loginErrorHeader": "Invalid Credentials",
"password": "Password"
},
"ReferenceCodeFormLabel": {
"content": "The values in this list can be edited via the {{name}} reference table."
},
"ReferenceCodeModal": {
"labels": {
"name": "Name"
Expand Down
2 changes: 2 additions & 0 deletions packages/semantic-ui/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ export { default as NestedAccordion } from './components/NestedAccordion';
export { default as PlayButton } from './components/PlayButton';
export { default as PhotoViewer } from './components/PhotoViewer';
export { default as ReferenceCodeDropdown } from './components/ReferenceCodeDropdown';
export { default as ReferenceCodeFormDropdown } from './components/ReferenceCodeFormDropdown';
export { default as ReferenceCodeFormLabel } from './components/ReferenceCodeFormLabel';
export { default as ReferenceCodeModal } from './components/ReferenceCodeModal';
export { default as ReferenceTableModal } from './components/ReferenceTableModal';
export { default as ReferenceTablesList } from './components/ReferenceTablesList';
Expand Down
1 change: 1 addition & 0 deletions packages/shared/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export { default as Attachments } from './transforms/Attachments';
export { default as BaseTransform } from './transforms/BaseTransform';
export { default as FormDataTransform } from './transforms/FormDataTransform';
export { default as NestedAttributesTransform } from './transforms/NestedAttributesTransform';
export { default as References } from './transforms/References';

// Utils
export { default as Browser } from './utils/Browser';
Expand Down
11 changes: 11 additions & 0 deletions packages/shared/src/services/ReferenceTables.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ import ReferenceTable from '../transforms/ReferenceTable';
* Class responsible for handling all reference table API requests.
*/
class ReferenceTables extends BaseService {
/**
* Calls the find_by_key API end point for reference tables.
*
* @param key
*
* @returns {Promise<AxiosResponse<any>>}
*/
fetchByKey(key) {
return this.getAxios().get(`${this.getBaseUrl()}/find_by_key`, { params: { key } });
}

/**
* Returns the reference tables base URL.
*
Expand Down
14 changes: 14 additions & 0 deletions packages/shared/src/transforms/References.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// @flow

import NestedAttributesTransform from './NestedAttributesTransform';

class References extends NestedAttributesTransform {
getPayloadKeys(): Array<string> {
return [
'reference_code_id'
];
}
}

const ReferencesTransform: References = new References();
export default ReferencesTransform;
13 changes: 13 additions & 0 deletions packages/storybook/.storybook/middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// @flow

const bodyParser = require('body-parser');
const ControlledVocabulary = require('./routes/ControlledVocabulary');

const expressMiddleWare = (router) => {
router.use(bodyParser.urlencoded({ extended: false }));
router.use(bodyParser.json());

ControlledVocabulary.addRoutes(router);
};

module.exports = expressMiddleWare;
51 changes: 51 additions & 0 deletions packages/storybook/.storybook/routes/ControlledVocabulary.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// @flow

const addRoutes = (router) => {
const codes = [{
id: 1,
reference_table_id: 1,
name: 'Boston, MA'
}, {
id: 2,
reference_table_id: 1,
name: 'New York, NY'
}, {
id: 3,
reference_table_id: 1,
name: 'Los Angeles, CA'
}];

router.get('/controlled_vocabulary/reference_codes', (request, response) => {
response.send({
list: {
count: codes.length,
page: 1,
pages: 1
},
reference_codes: codes
});

response.end();
});

router.get('/controlled_vocabulary/reference_tables/:id', (request, response) => {
response.send({
reference_table: {
id: 1,
name: 'Locations',
key: 'locations',
reference_codes: codes
}
})

response.end();
});

router.put('/controlled_vocabulary/reference_tables/:id', (request, response) => {
response.end();
});
};

module.exports = {
addRoutes
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// @flow

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

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

export const Default = () => (
<ReferenceCodeDropdown
fluid
label='Locations'
required
onChange={action('change')}
referenceTable='locations'
value=''
/>
);

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

return (
<ReferenceCodeDropdown
fluid
label='Locations'
multiple
required
onChange={(selected) => setValue(selected)}
referenceTable='locations'
value={value}
/>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// @flow

import React from 'react';
import { withA11y } from '@storybook/addon-a11y';
import { withKnobs } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
import { Form } from 'semantic-ui-react';
import ReferenceCodeFormDropdown from '../../../semantic-ui/src/components/ReferenceCodeFormDropdown';
import useDragDrop from '../../../shared/src/utils/DragDrop';

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

export const Default = useDragDrop(() => (
<Form>
<ReferenceCodeFormDropdown
fluid
label='Locations'
required
onChange={action('change')}
referenceTable='locations'
value=''
/>
</Form>
));
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// @flow

import React from 'react';
import { withA11y } from '@storybook/addon-a11y';
import { withKnobs } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
import ReferenceCodeFormLabel from '../../../semantic-ui/src/components/ReferenceCodeFormLabel';

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

export const Default = () => (
<ReferenceCodeFormLabel
label='Locations'
onClick={action('click')}
referenceTable='locations'
/>
);

0 comments on commit 6fe68d1

Please sign in to comment.