-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Maxime Rainville
committed
Jul 11, 2023
1 parent
469ad24
commit dd4cf68
Showing
48 changed files
with
1,279 additions
and
295 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,4 @@ | ||
/* eslint-disable */ | ||
import Injector from 'lib/Injector'; | ||
import { combineReducers } from 'redux'; | ||
// import gallery from 'state/gallery/GalleryReducer'; | ||
// import queuedFiles from 'state/queuedFiles/QueuedFilesReducer'; | ||
// import uploadField from 'state/uploadField/UploadFieldReducer'; | ||
// import previewField from 'state/previewField/PreviewFieldReducer'; | ||
// import imageLoad from 'state/imageLoad/ImageLoadReducer'; | ||
// import displaySearch from 'state/displaySearch/DisplaySearchReducer'; | ||
// import confirmDeletion from 'state/confirmDeletion/ConfirmDeletionReducer'; | ||
// import modal from 'state/modal/ModalReducer'; | ||
|
||
const registerReducers = () => { | ||
// Injector.reducer.register('assetAdmin', combineReducers({ | ||
// gallery, | ||
// queuedFiles, | ||
// uploadField, | ||
// previewField, | ||
// imageLoad, | ||
// displaySearch, | ||
// confirmDeletion, | ||
// modal | ||
// })); | ||
}; | ||
|
||
export default registerReducers; |
106 changes: 106 additions & 0 deletions
106
client/src/components/AbstractLinkField/AbstractLinkField.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import React, { Fragment, useState } from 'react'; | ||
import { loadComponent } from 'lib/Injector'; | ||
import PropTypes from 'prop-types'; | ||
import LinkType from '../../types/LinkType'; | ||
import LinkSummary from '../../types/LinkSummary'; | ||
|
||
/** | ||
* Underlying implementation of the LinkField. This is used for both the Single LinkField | ||
* and MultiLinkField. It should not be used directly. | ||
*/ | ||
const AbstractLinkField = ({ | ||
id, loading, Loading, Picker, onChange, types, | ||
clearLinkData, buildLinkProps, updateLinkData, selectLinkData | ||
}) => { | ||
// Render a loading indicator if we're still fetching some data from the server | ||
if (loading) { | ||
return <Loading />; | ||
} | ||
|
||
// When editing is true, wu display a modal to let the user edit the link data | ||
const [editingId, setEditingId] = useState(false); | ||
// newTypeKey define what link type we are using for brand new links | ||
const [newTypeKey, setNewTypeKey] = useState(''); | ||
|
||
const selectedLinkData = selectLinkData(editingId); | ||
const modalType = types[(selectedLinkData && selectedLinkData.typeKey) || newTypeKey]; | ||
|
||
// When the use clears the link data, we call onchange with an empty object | ||
const onClear = (event, linkId) => { | ||
if (typeof onChange === 'function') { | ||
onChange(event, { id, value: clearLinkData(linkId) }); | ||
} | ||
}; | ||
|
||
const linkProps = { | ||
...buildLinkProps(), | ||
onEdit: (linkId) => { setEditingId(linkId); }, | ||
onClear, | ||
onSelect: (key) => { | ||
setNewTypeKey(key); | ||
setEditingId(true); | ||
}, | ||
types: Object.values(types) | ||
}; | ||
|
||
const onModalSubmit = (submittedData) => { | ||
// Remove unneeded keys from submitted data | ||
// eslint-disable-next-line camelcase | ||
const { SecurityID, action_insert, ...newLinkData } = submittedData; | ||
if (typeof onChange === 'function') { | ||
// onChange expect an event object which we don't have | ||
onChange(undefined, { id, value: updateLinkData(newLinkData) }); | ||
} | ||
// Close the modal | ||
setEditingId(false); | ||
setNewTypeKey(''); | ||
return Promise.resolve(); | ||
}; | ||
|
||
const modalProps = { | ||
type: modalType, | ||
editing: editingId !== false, | ||
onSubmit: onModalSubmit, | ||
onClosed: () => { | ||
setEditingId(false); | ||
return Promise.resolve(); | ||
}, | ||
data: selectedLinkData | ||
}; | ||
|
||
// Different link types might have different Link modal | ||
const handlerName = modalType ? modalType.handlerName : 'FormBuilderModal'; | ||
const LinkModal = loadComponent(`LinkModal.${handlerName}`); | ||
|
||
return ( | ||
<Fragment> | ||
<Picker {...linkProps} /> | ||
<LinkModal {...modalProps} /> | ||
</Fragment> | ||
); | ||
}; | ||
|
||
/** | ||
* These props are expected to be passthrough from tho parent component. | ||
*/ | ||
export const linkFieldPropTypes = { | ||
id: PropTypes.string.isRequired, | ||
loading: PropTypes.bool, | ||
Loading: PropTypes.elementType, | ||
data: PropTypes.any, | ||
Picker: PropTypes.elementType, | ||
onChange: PropTypes.func, | ||
types: PropTypes.objectOf(LinkType), | ||
linkDescriptions: PropTypes.arrayOf(LinkSummary), | ||
}; | ||
|
||
AbstractLinkField.propTypes = { | ||
...linkFieldPropTypes, | ||
// These props need to be provided by the specific implementation | ||
clearLinkData: PropTypes.func.isRequired, | ||
buildLinkProps: PropTypes.func.isRequired, | ||
updateLinkData: PropTypes.func.isRequired, | ||
selectLinkData: PropTypes.func.isRequired, | ||
}; | ||
|
||
export default AbstractLinkField; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import React from 'react'; | ||
import { compose } from 'redux'; | ||
import { withApollo } from '@apollo/client/react/hoc'; | ||
import { injectGraphql } from 'lib/Injector'; | ||
import fieldHolder from 'components/FieldHolder/FieldHolder'; | ||
|
||
/** | ||
* When getting data from entwine, we might get it in a plain JSON string. | ||
* This method rewrites tho data to a normalise format. | ||
*/ | ||
const stringifyData = (Component) => (({ data, value, ...props }) => { | ||
let dataValue = value || data; | ||
if (typeof dataValue === 'string') { | ||
dataValue = JSON.parse(dataValue); | ||
} | ||
return <Component dataStr={JSON.stringify(dataValue)} {...props} data={dataValue} />; | ||
}); | ||
|
||
|
||
/** | ||
* Wires a Link field into GraphQL normalise the initial data to a proper objects | ||
*/ | ||
const linkFieldHOC = compose( | ||
stringifyData, | ||
injectGraphql('readLinkTypes'), | ||
injectGraphql('readLinkDescription'), | ||
withApollo, | ||
fieldHolder | ||
); | ||
|
||
export default linkFieldHOC; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import classnames from 'classnames'; | ||
|
||
/** | ||
* Wraps children in a bok with rounder corners and a form control style. | ||
*/ | ||
const LinkBox = ({ className, children }) => ( | ||
<div className={classnames('link-box', 'form-control', className)}> | ||
{ children } | ||
</div> | ||
); | ||
|
||
LinkBox.propTypes = { | ||
className: PropTypes.string, | ||
}; | ||
|
||
export default LinkBox; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
.link-box { | ||
display: flex; | ||
height: 54px; | ||
background: white; | ||
width: 100%; | ||
align-items: stretch; | ||
cursor: pointer; | ||
padding: 0; | ||
box-shadow: none; | ||
|
||
&.font-icon-link::before { | ||
margin: $spacer-xs; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,90 +1,51 @@ | ||
import React, { Fragment, useState } from 'react'; | ||
import React from 'react'; | ||
import { compose } from 'redux'; | ||
import { inject, injectGraphql, loadComponent } from 'lib/Injector'; | ||
import fieldHolder from 'components/FieldHolder/FieldHolder'; | ||
|
||
const LinkField = ({ id, loading, Loading, data, LinkPicker, onChange, types, linkDescription, ...props }) => { | ||
if (loading) { | ||
return <Loading />; | ||
} | ||
|
||
const [editing, setEditing] = useState(false); | ||
const [newTypeKey, setNewTypeKey] = useState(''); | ||
|
||
const onClear = (event) => { | ||
if (typeof onChange !== 'function') { | ||
return; | ||
} | ||
|
||
onChange(event, { id, value: {} }); | ||
}; | ||
|
||
const { typeKey } = data; | ||
const type = types[typeKey]; | ||
const modalType = newTypeKey ? types[newTypeKey] : type; | ||
|
||
let title = data ? data.Title : ''; | ||
|
||
if (!title) { | ||
title = data ? data.TitleRelField : ''; | ||
} | ||
|
||
const linkProps = { | ||
title, | ||
link: type ? { type, title, description: linkDescription } : undefined, | ||
onEdit: () => { setEditing(true); }, | ||
onClear, | ||
onSelect: (key) => { | ||
setNewTypeKey(key); | ||
setEditing(true); | ||
import { inject } from 'lib/Injector'; | ||
import PropTypes from 'prop-types'; | ||
import LinkData from '../../types/LinkData'; | ||
import AbstractLinkField, { linkFieldPropTypes } from '../AbstractLinkField/AbstractLinkField'; | ||
import linkFieldHOC from '../AbstractLinkField/linkFieldHOC'; | ||
|
||
/** | ||
* Renders a Field allowing the selection of a single link. | ||
*/ | ||
const LinkField = (props) => { | ||
const staticProps = { | ||
buildLinkProps: () => { | ||
const { data, linkDescriptions, types } = props; | ||
|
||
// Try to read the link type from the link data or use newTypeKey | ||
const { typeKey } = data; | ||
const type = types[typeKey]; | ||
|
||
// Read link title and description | ||
const linkDescription = linkDescriptions.length > 0 ? linkDescriptions[0] : {}; | ||
const { title, description } = linkDescription; | ||
return { | ||
title, | ||
description, | ||
type: type || undefined, | ||
}; | ||
}, | ||
types: Object.values(types) | ||
clearLinkData: () => ({}), | ||
updateLinkData: newLinkData => newLinkData, | ||
selectLinkData: () => (props.data), | ||
}; | ||
|
||
const onModalSubmit = (modalData, action, submitFn) => { | ||
const { SecurityID, action_insert: actionInsert, ...value } = modalData; | ||
|
||
if (typeof onChange === 'function') { | ||
onChange(event, { id, value }); | ||
} | ||
|
||
setEditing(false); | ||
setNewTypeKey(''); | ||
|
||
return Promise.resolve(); | ||
}; | ||
|
||
const modalProps = { | ||
type: modalType, | ||
editing, | ||
onSubmit: onModalSubmit, | ||
onClosed: () => { | ||
setEditing(false); | ||
}, | ||
data | ||
}; | ||
|
||
const handlerName = modalType ? modalType.handlerName : 'FormBuilderModal'; | ||
const LinkModal = loadComponent(`LinkModal.${handlerName}`); | ||
return <AbstractLinkField {...props} {...staticProps} />; | ||
}; | ||
|
||
return <Fragment> | ||
<LinkPicker {...linkProps} /> | ||
<LinkModal {...modalProps} /> | ||
</Fragment>; | ||
LinkField.propTypes = { | ||
...linkFieldPropTypes, | ||
data: LinkData | ||
}; | ||
|
||
const stringifyData = (Component) => (({ data, value, ...props }) => { | ||
let dataValue = value || data; | ||
if (typeof dataValue === 'string') { | ||
dataValue = JSON.parse(dataValue); | ||
} | ||
return <Component dataStr={JSON.stringify(dataValue)} {...props} data={dataValue} />; | ||
}); | ||
export { LinkField as Component }; | ||
|
||
export default compose( | ||
inject(['LinkPicker', 'Loading']), | ||
injectGraphql('readLinkTypes'), | ||
stringifyData, | ||
injectGraphql('readLinkDescription'), | ||
fieldHolder | ||
inject( | ||
['LinkPicker', 'Loading'], | ||
(LinkPicker, Loading) => ({ Picker: LinkPicker, Loading }) | ||
), | ||
linkFieldHOC | ||
)(LinkField); |
Oops, something went wrong.