Skip to content

Commit

Permalink
Modify Read template to match with API call changed
Browse files Browse the repository at this point in the history
  • Loading branch information
dtrucs committed Oct 8, 2019
1 parent e2deb39 commit 61de6d5
Show file tree
Hide file tree
Showing 5 changed files with 299 additions and 231 deletions.
3 changes: 2 additions & 1 deletion public/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,8 @@
"noAccess": "Vous n'avez pas les droits pour accéder à cette ressource.",
"geometry": "Géométrie",
"true": "Oui",
"false": "Non"
"false": "Non",
"other": "Autre"
}
},
"help": {
Expand Down
4 changes: 2 additions & 2 deletions src/modules/CRUD/components/Details/Details.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ class Details extends React.Component {
...list,
[prop]: {
...schema.properties[prop],
...(properties && paramId !== ACTION_CREATE)
...(properties && paramId !== ACTION_CREATE && typeof properties[prop] !== 'object')
? { default: properties[prop] }
: {},
},
Expand Down Expand Up @@ -167,7 +167,7 @@ class Details extends React.Component {
/>
);
}
return <Read schema={schema} view={view} feature={feature} />;
return <Read feature={feature} />;
}

onSizeChange = () => {
Expand Down
171 changes: 109 additions & 62 deletions src/modules/CRUD/components/Details/Read/Read.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Redirect } from 'react-router-dom';
import { Tab, Tabs } from '@blueprintjs/core';
import { Redirect, Link } from 'react-router-dom';
import classnames from 'classnames';
import { orderProperties } from 'react-jsonschema-form/lib/utils';

import { toast } from '../../../../../utils/toast';
import { generateURI } from '../../../config';
import DownloadButtons from '../DownloadButtons';
import Actions from '../Actions';

const NO_FEATURE = 'CRUD.details.noFeature';
const emptyStringOrUndef = value => ['', undefined].includes(value);

const emptyStringNullOrUndef = value => ['', null, undefined].includes(value);

const isHTML = value => {
const div = document.createElement('div');
Expand All @@ -30,7 +30,7 @@ const formattedProp = ({ value, t }) => {
: t('CRUD.details.false');
}

if (emptyStringOrUndef(value)) {
if (emptyStringNullOrUndef(value)) {
return t(NO_FEATURE);
}

Expand All @@ -53,58 +53,107 @@ const formattedProp = ({ value, t }) => {
return value;
};

const Read = ({
t,
match: { params: { layer: paramLayer, id: paramId } },
schema: { title: schemaTitle, properties = {} },
displayViewFeature,
view: { uiSchema: { 'ui:order': order } = {} },
feature: { documents },
}) => {
if (!displayViewFeature) {
toast.displayError(t('CRUD.details.noAccess'));
return (<Redirect to={generateURI('layer', { layer: paramLayer })} />);

class Read extends React.Component {
state = {
tabs: [],
}

componentDidMount () {
this.generatesTabs();
}

const { name: { default: title } = {} } = properties;
const hasProperties = !!Object.keys(properties).length;
componentDidUpdate ({
feature: { display_properties: prevDisplayProperties },
}) {
const {
feature: { display_properties: displayProperties },
} = this.props;
if (prevDisplayProperties !== displayProperties) {
this.generatesTabs();
}
}

const orderedProperties = orderProperties(Object.keys(properties), order);
generatesTabs = () => {
const {
feature: { display_properties: displayProperties },
} = this.props;
this.setState({
tabs: Object.keys(displayProperties)
.map(tabs => ({ ...displayProperties[tabs] }))
.sort((a, b) => a.order - b.order),
});
}

return (
<div className="details">
<div className="details__header">
<h2 className="details__title">{title || t(NO_FEATURE)}</h2>
<DownloadButtons
className="details__templates"
documents={documents}
/>
</div>
{hasProperties && (
<div className="details__content">
{schemaTitle && (
<h3 className="details__subtitle">{schemaTitle}</h3>
)}
<ul className="details__list">
{orderedProperties.map(prop => (
<li key={prop} className="details__list-item">
<strong className="details__list-label">{properties[prop].title || prop}</strong>
<span className={classnames(
'details__list-value',
{ 'details__list-value--empty': emptyStringOrUndef(properties[prop].default) },
)}
>
{formattedProp({ value: properties[prop].default, t })}
</span>
</li>
))}
</ul>
renderPanel = properties => {
const { t } = this.props;
return (
<ul className="details__list">
{Object.keys(properties).map(name => (
<li key={name} className="details__list-item">
<strong className="details__list-label">{name}</strong>
<span className={classnames(
'details__list-value',
{ 'details__list-value--empty': emptyStringNullOrUndef(properties[name]) },
)}
>
{formattedProp({ value: properties[name], t })}
</span>
</li>
))}
</ul>
);
}

render () {
const {
t,
match: { params: { layer: paramLayer, id: paramId } },
location: { hash },
displayViewFeature,
feature: { title: featureTitle, documents },
} = this.props;

if (!displayViewFeature) {
toast.displayError(t('CRUD.details.noAccess'));
return (<Redirect to={generateURI('layer', { layer: paramLayer })} />);
}

const { tabs } = this.state;
const hasProperties = !!tabs.length;

return (
<div className="details">
<div className="details__header">
<h2 className="details__title">{featureTitle || t(NO_FEATURE)}</h2>
<DownloadButtons
className="details__templates"
documents={documents}
/>
</div>
)}
<Actions paramId={paramId} paramLayer={paramLayer} displayUpdate displayDelete />
</div>
);
};
{hasProperties && (
<div className="details__content">
<Tabs
id="tabs"
selectedTabId={hash.substring(1) || tabs[0].slug}
>
{tabs.map(({ title, slug = 'other', properties }) => (
<Tab
key={slug}
id={slug}
title={<Link to={`#${slug}`}>{title || t('CRUD.details.other')}</Link>}
panel={this.renderPanel(properties)}
/>
))}
<Tabs.Expander />
</Tabs>
</div>
)}
<Actions paramId={paramId} paramLayer={paramLayer} displayUpdate displayDelete />
</div>
);
}
}

Read.propTypes = {
match: PropTypes.shape({
Expand All @@ -113,15 +162,14 @@ Read.propTypes = {
id: PropTypes.string,
}),
}),
schema: PropTypes.shape({
properties: PropTypes.shape({}),
location: PropTypes.shape({
hash: PropTypes.string,
}),
displayViewFeature: PropTypes.bool,
view: PropTypes.shape({
uiSchema: PropTypes.shape({}),
}),
feature: PropTypes.shape({
title: PropTypes.string,
documents: PropTypes.array,
display_properties: PropTypes.shape({}),
}),
t: PropTypes.func,
};
Expand All @@ -133,15 +181,14 @@ Read.defaultProps = {
id: undefined,
},
},
schema: {
properties: {},
},
location: PropTypes.shape({
hash: undefined,
}),
displayViewFeature: true,
view: {
uiSchema: {},
},
feature: {
title: '',
documents: [],
display_properties: {},
},
t: text => text,
};
Expand Down
90 changes: 39 additions & 51 deletions src/modules/CRUD/components/Details/Read/Read.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,20 @@ import renderer from 'react-test-renderer';
import Read from './Read';


jest.mock('@blueprintjs/core', () => {
const Tabs = ({ children }) => <ul>{children}</ul>;
const Tab = ({ title, panel }) => <li>{title}{panel}</li>;
Tabs.Expander = () => null;

return {
Tabs,
Tab,
};
});

jest.mock('react-router-dom', () => ({
Redirect: () => <div>Error because Redirect</div>,
Link: ({ children }) => <span>{children}</span>,
}));

jest.mock('../../../../../utils/toast', () => ({
Expand All @@ -25,62 +37,38 @@ jest.mock('../Actions', () => () => (<div>Actions</div>));
const props = {
t: text => text,
match: { params: { layer: 'layerFoo', id: 'layerId' } },
schema: {
title: 'Foo Title',
properties: {
city: {
type: 'string',
title: 'Ville',
default: 'Agen, Lot-et-Garonne, Nouvelle-Aquitaine',
},
name: {
type: 'string',
title: 'Nom',
default: 'Cathedrale Saint-Caprais',
},
description: {
type: 'string',
title: 'Description',
default: '',
},
numero: {
type: 'integer',
title: 'Numéro',
default: 2,
},
validation: {
type: 'boolean',
title: 'Validation',
default: true,
},
available: {
type: 'boolean',
title: 'Validation',
default: false,
displayViewFeature: true,
location: {
hash: '',
},
feature: {
title: 'Title of the feature',
display_properties: {
'Group 1': {
title: 'Name of the group',
slug: 'slug-group',
order: 1,
pictogram: null,
properties: {
Numéro: 2,
Validation: true,
Available: false,
Array: [1, 2, 3],
EmptyValue: ' ',
},
},
labels: {
type: 'array',
items: {
enum: [
'VPAH',
'PM 1979',
'PM 1981',
'PM 1991',
'PM 1992',
],
type: 'string',
__default__: {
title: '',
pictogram: null,
order: 9999,
properties: {
'key without value': null,
'Hello foo bar': 'Value hello foo bar',
Contact: 'Foo contact',
},
title: 'Labels',
uniqueItems: true,
default: ['PM 1979', 'PM 1981'],
},
},
},
displayViewFeature: true,
layer: {},
feature: {
id: undefined,
},
};


Expand Down
Loading

0 comments on commit 61de6d5

Please sign in to comment.