Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Buffetjs in the filter picker #4830

Merged
merged 9 commits into from
Jan 13, 2020
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;