Skip to content

Commit

Permalink
Merge pull request #4830 from strapi/ctm/improve-listview
Browse files Browse the repository at this point in the history
Use Buffetjs in the filter picker
  • Loading branch information
virginieky committed Jan 13, 2020
2 parents f45c176 + f2918e1 commit 6fccb74
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 61 deletions.
4 changes: 3 additions & 1 deletion docs/3.0.0-beta.x/plugins/users-permissions.md
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,9 @@ You can update these template in the **Email Templates** tab in the admin panel.
- `URL` is the Strapi backend URL that confirm the code (by default `/auth/email-confirmation`).

## Security configuration
JWT tokens can be verified and trusted because the information is digitally signed. To sign a token a *secret* is required. By default Strapi generates one that is stored in `./your-app/extensions/users-permissions/config/jwt.json`. This is useful during development but for security reasons it is **recommended** to set a custom token via an environment variable `JWT_SECRET` when deploying to production. It is also possible to modify `jwt.json` file to accept `JWT_TOKEN` automatically by doing following ([docs](https://strapi.io/documentation/3.0.0-beta.x/concepts/configurations.html#dynamic-configurations)).

JWT tokens can be verified and trusted because the information is digitally signed. To sign a token a _secret_ is required. By default Strapi generates one that is stored in `./your-app/extensions/users-permissions/config/jwt.json`. This is useful during development but for security reasons it is **recommended** to set a custom token via an environment variable `JWT_SECRET` when deploying to production. It is also possible to modify `jwt.json` file to accept `JWT_TOKEN` automatically by doing following ([docs](https://strapi.io/documentation/3.0.0-beta.x/concepts/configurations.html#dynamic-configurations)).

```
"jwtSecret": "${process.env.JWT_SECRET}"
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const DATE_FORMATS = {
date: 'dddd, MMMM Do YYYY',
datetime: 'dddd, MMMM Do YYYY HH:mm',
time: 'HH:mm A',
timestamp: 'dddd, MMMM Do YYYY',
};

export default DATE_FORMATS;
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import { get, isEmpty, isNull, isObject, toLower, toString } from 'lodash';
import moment from 'moment';
import { IcoContainer, useGlobalContext } from 'strapi-helper-plugin';
import useListView from '../../hooks/useListView';

import CustomInputCheckbox from '../CustomInputCheckbox';
import MediaPreviewList from '../MediaPreviewList';

import { ActionContainer, Truncate, Truncated } from './styledComponents';
import DATE_FORMATS from './DATE_FORMATS';

const dateToUtcTime = date => moment.parseZone(date).utc();

const getDisplayedValue = (type, value, name) => {
switch (toLower(type)) {
Expand All @@ -28,7 +29,6 @@ const getDisplayedValue = (type, value, name) => {
case 'boolean':
return value !== null ? toString(value) : '-';
case 'date':
case 'time':
case 'datetime':
case 'timestamp': {
if (value == null) {
Expand All @@ -40,17 +40,24 @@ const getDisplayedValue = (type, value, name) => {
? JSON.stringify(value)
: value;

return moment
.parseZone(date)
.utc()
.format('dddd, MMMM Do YYYY');
return dateToUtcTime(date).format(DATE_FORMATS[type]);
}
case 'password':
return '••••••••';
case 'media':
case 'file':
case 'files':
return value;
case 'time': {
const [hour, minute, second] = value.split(':');
const timeObj = {
hour,
minute,
second,
};
const date = moment().set(timeObj);
return date.format(DATE_FORMATS.time);
}
default:
return '-';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function reducer(state, action) {

return state
.updateIn(['modifiedData', ...action.keys], () => {
if (action.value._isAMomentObject === true) {
if (action.value && action.value._isAMomentObject === true) {
return moment(action.value, 'YYYY-MM-DD HH:mm:ss').format();
}
return action.value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,53 @@

import React, { memo } from 'react';
import PropTypes from 'prop-types';

import { DateTime } from '@buffetjs/custom';
import {
InputDate,
InputNumber,
InputSelect,
DatePicker,
InputText,
} from 'strapi-helper-plugin';
InputNumber,
Select,
TimePicker,
} from '@buffetjs/core';
import { InputWrapperDate } from './components';

const getInputType = attrType => {
switch (attrType) {
case 'boolean':
return InputSelect;
return Select;
case 'date':
case 'datetime':
case 'timestamp':
case 'timestampUpdate':
return InputDate;
return DatePicker;
case 'datetime':
return DateTime;
case 'integer':
case 'biginteger':
case 'decimal':
case 'float':
return InputNumber;
case 'time':
return TimePicker;
default:
return InputText;
}
};

function Input({ type, ...rest }) {
const Component = getInputType(type);
const style = { width: '210px', paddingTop: '4px' };
let style = type !== 'time' ? { width: '210px', paddingTop: '4px' } : {};

if (['integer', 'biginteger', 'float', 'decimal'].includes(type)) {
style = { marginRight: '20px' };
}
const styles =
type === 'boolean' ? { minWidth: '100px', maxWidth: '200px' } : style;
const wrapperStyle = type == 'boolean' ? { marginRight: '20px' } : {};
const wrapperStyle =
type == 'boolean' ||
['date', 'timestamp', 'time', 'datetime'].includes(type)
? { marginRight: '20px' }
: { marginRight: '10px' };

return (
<InputWrapperDate type={type || 'text'} style={wrapperStyle}>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import PropTypes from 'prop-types';

const Option = ({ id, value }) => {
return (
<FormattedMessage id={id}>
{msg => <option value={value}>{msg}</option>}
</FormattedMessage>
);
};

Option.propTypes = {
id: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
};

export default Option;
Original file line number Diff line number Diff line change
Expand Up @@ -53,39 +53,27 @@ const Button = styled.button`

const InputWrapperDate = styled.div`
margin-right: 10px;
span {
left: 5px;
}
.rc-input-number-handler-wrap {
right: -5px !important;
}
.rc-input-number-input-wrap {
max-width: 210px;
overflow: visible;
}
> div {
width: 210px;
}
${({ type }) => {
if (
type.includes('date') ||
type === 'timestampUpdate' ||
type === 'timestamp'
) {
return css`
position: relative;
&:before {
content: '\f073';
position: absolute;
left: 6px;
top: 1px;
width: 32px;
height: 32px;
border-radius: 3px 0px 0px 3px;
background: #fafafb;
color: #b3b5b9;
text-align: center;
font-family: 'FontAwesome';
font-size: 1.4rem;
line-height: 32px;
z-index: 999;
-webkit-font-smoothing: none;
}
input {
width: 100%;
padding-left: 42px;
box-shadow: 0px 1px 1px rgba(104, 118, 142, 0.05);
&:focus {
outline: none;
}
}
if (type === 'datetime') {
return `
> div {
width: 300px;
}
`;
}
}}
Expand All @@ -103,5 +91,4 @@ const Input = styled.input`
font-family: 'Lato' !important;
box-shadow: 0px 1px 1px rgba(104, 118, 142, 0.05);
`;

export { Button, InputWrapper, Wrapper, InputWrapperDate, Input };
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, { memo } from 'react';
import { get, isEmpty } from 'lodash';
import PropTypes from 'prop-types';

import { InputSelect } from 'strapi-helper-plugin';
import { Select } from '@buffetjs/core';
import { Button, InputWrapper, Wrapper } from './components';
import Input from './Input';
import Option from './Option';
import getFilters from './utils';

const styles = {
Expand Down Expand Up @@ -46,7 +46,7 @@ function FilterPickerOption({
isRemoveButton
onClick={() => onRemoveFilter(index)}
/>
<InputSelect
<Select
onChange={e => {
// Change the attribute
onChange(e);
Expand All @@ -55,21 +55,23 @@ function FilterPickerOption({
}}
name={`${index}.name`}
value={get(modifiedData, [index, 'name'], '')}
selectOptions={allowedAttributes.map(attr => attr.name)}
options={allowedAttributes.map(attr => attr.name)}
style={styles.select}
/>
<InputSelect
<Select
onChange={onChange}
name={`${index}.filter`}
selectOptions={filtersOptions}
options={filtersOptions.map(option => (
<Option {...option} key={option.value} />
))}
style={styles.selectMiddle}
value={get(modifiedData, [index, 'filter'], '')}
/>
<Input
type={type}
name={`${index}.value`}
value={get(modifiedData, [index, 'value'], '')}
selectOptions={['true', 'false']}
options={['true', 'false']}
onChange={onChange}
/>
{showAddButton && <Button type="button" onClick={onClickAddFilter} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,4 @@ EditViewButton.propTypes = {
push: PropTypes.func.isRequired,
};

export default EditViewButton;
export default EditViewButton;
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ EditViewLink.propTypes = {
getModelName: PropTypes.func.isRequired,
};

export default EditViewLink;
export default EditViewLink;
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ const RESERVED_NAMES = [
...JS_BUILT_IN_OBJECTS,
];

export default RESERVED_NAMES;
export default RESERVED_NAMES;

0 comments on commit 6fccb74

Please sign in to comment.