mirror of
https://github.com/strapi/strapi.git
synced 2026-01-04 19:23:29 +00:00
Add loading button to ctm and to upload && modify design
This commit is contained in:
parent
71e4009317
commit
3e32741114
@ -15,9 +15,11 @@ import {
|
||||
ON_CANCEL,
|
||||
RESET_PROPS,
|
||||
SET_FILE_RELATIONS,
|
||||
SET_LOADER,
|
||||
SET_FORM_ERRORS,
|
||||
SUBMIT,
|
||||
SUBMIT_SUCCESS,
|
||||
UNSET_LOADER,
|
||||
} from './constants';
|
||||
|
||||
export function changeData({ target }) {
|
||||
@ -87,6 +89,12 @@ export function setFormErrors(formErrors) {
|
||||
};
|
||||
}
|
||||
|
||||
export function setLoader() {
|
||||
return {
|
||||
type: SET_LOADER,
|
||||
};
|
||||
}
|
||||
|
||||
export function submit() {
|
||||
return {
|
||||
type: SUBMIT,
|
||||
@ -98,3 +106,9 @@ export function submitSuccess() {
|
||||
type: SUBMIT_SUCCESS,
|
||||
};
|
||||
}
|
||||
|
||||
export function unsetLoader() {
|
||||
return {
|
||||
type: UNSET_LOADER,
|
||||
};
|
||||
}
|
||||
|
||||
@ -11,6 +11,8 @@ export const INIT_MODEL_PROPS = 'ContentManager/EditPage/INIT_MODEL_PROPS';
|
||||
export const ON_CANCEL = 'ContentManager/EditPage/ON_CANCEL';
|
||||
export const RESET_PROPS = 'ContentManager/EditPage/RESET_PROPS';
|
||||
export const SET_FILE_RELATIONS = 'ContentManager/EditPage/SET_FILE_RELATIONS';
|
||||
export const SET_LOADER = 'ContentManager/EditPage/SET_LOADER';
|
||||
export const SET_FORM_ERRORS = 'ContentManager/EditPage/SET_FORM_ERRORS';
|
||||
export const SUBMIT = 'ContentManager/EditPage/SUBMIT';
|
||||
export const SUBMIT_SUCCESS = 'ContentManager/EditPage/SUBMIT_SUCCESS';
|
||||
export const UNSET_LOADER = 'ContentManager/EditPage/UNSET_LOADER';
|
||||
|
||||
@ -191,31 +191,34 @@ export class EditPage extends React.Component {
|
||||
}, {})
|
||||
)
|
||||
|
||||
pluginHeaderActions = [
|
||||
{
|
||||
label: 'content-manager.containers.Edit.reset',
|
||||
kind: 'secondary',
|
||||
onClick: this.props.onCancel,
|
||||
type: 'button',
|
||||
},
|
||||
{
|
||||
kind: 'primary',
|
||||
label: 'content-manager.containers.Edit.submit',
|
||||
onClick: this.handleSubmit,
|
||||
type: 'submit',
|
||||
},
|
||||
];
|
||||
pluginHeaderActions = () => (
|
||||
[
|
||||
{
|
||||
label: 'content-manager.containers.Edit.reset',
|
||||
kind: 'secondary',
|
||||
onClick: this.props.onCancel,
|
||||
type: 'button',
|
||||
},
|
||||
{
|
||||
kind: 'primary',
|
||||
label: 'content-manager.containers.Edit.submit',
|
||||
onClick: this.handleSubmit,
|
||||
type: 'submit',
|
||||
loader: this.props.editPage.showLoader,
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
render() {
|
||||
const { editPage } = this.props;
|
||||
|
||||
console.log(editPage.showLoader);
|
||||
return (
|
||||
<div>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<BackHeader onClick={() => this.props.history.goBack()} />
|
||||
<div className={cn('container-fluid', styles.containerFluid)}>
|
||||
<PluginHeader
|
||||
actions={this.pluginHeaderActions}
|
||||
actions={this.pluginHeaderActions()}
|
||||
title={{ id: toString(editPage.pluginHeaderTitle) }}
|
||||
/>
|
||||
<div className="row">
|
||||
|
||||
@ -13,7 +13,9 @@ import {
|
||||
RESET_PROPS,
|
||||
SET_FILE_RELATIONS,
|
||||
SET_FORM_ERRORS,
|
||||
SET_LOADER,
|
||||
SUBMIT_SUCCESS,
|
||||
UNSET_LOADER,
|
||||
} from './constants';
|
||||
|
||||
const initialState = fromJS({
|
||||
@ -27,6 +29,7 @@ const initialState = fromJS({
|
||||
modelName: '',
|
||||
pluginHeaderTitle: 'New Entry',
|
||||
record: Map({}),
|
||||
showLoader: false,
|
||||
source: 'content-manager',
|
||||
submitSuccess: false,
|
||||
});
|
||||
@ -60,8 +63,13 @@ function editPageReducer(state = initialState, action) {
|
||||
return state
|
||||
.update('didCheckErrors', (v) => v = !v)
|
||||
.update('formErrors', () => List(action.formErrors));
|
||||
case SET_LOADER:
|
||||
return state
|
||||
.update('showLoader', () => true);
|
||||
case SUBMIT_SUCCESS:
|
||||
return state.update('submitSuccess', (v) => v = !v);
|
||||
case UNSET_LOADER:
|
||||
return state.update('showLoader', () => false);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
@ -15,7 +15,13 @@ import cleanData from 'utils/cleanData';
|
||||
import request from 'utils/request';
|
||||
import templateObject from 'utils/templateObject';
|
||||
|
||||
import { getDataSucceeded, setFormErrors, submitSuccess } from './actions';
|
||||
import {
|
||||
getDataSucceeded,
|
||||
setFormErrors,
|
||||
setLoader,
|
||||
submitSuccess,
|
||||
unsetLoader,
|
||||
} from './actions';
|
||||
import { GET_DATA,SUBMIT } from './constants';
|
||||
import {
|
||||
makeSelectFileRelations,
|
||||
@ -50,6 +56,8 @@ export function* submit() {
|
||||
const source = yield select(makeSelectSource());
|
||||
|
||||
try {
|
||||
// Show button loader
|
||||
yield put(setLoader());
|
||||
const recordCleaned = Object.keys(record).reduce((acc, current) => {
|
||||
const cleanedData = cleanData(record[current], 'value', 'id');
|
||||
|
||||
@ -126,6 +134,8 @@ export function* submit() {
|
||||
yield put(setFormErrors([{ name, errors }]));
|
||||
}
|
||||
strapi.notification.error(isCreating ? 'content-manager.error.record.create' : 'content-manager.error.record.update');
|
||||
} finally {
|
||||
yield put(unsetLoader());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
height: 100%;
|
||||
margin-left: 32px;
|
||||
margin-right: 32px;
|
||||
line-height: 54px;
|
||||
line-height: 48px;
|
||||
border-bottom: 1px solid rgba(14,22,34,0.04);
|
||||
justify-content: space-between;
|
||||
|
||||
|
||||
@ -11,6 +11,12 @@
|
||||
width: 100%;
|
||||
padding: 0 !important;
|
||||
list-style: none;
|
||||
> li:nth-child(2) {
|
||||
height: 57px;
|
||||
> div {
|
||||
line-height: 54px !important;
|
||||
}
|
||||
}
|
||||
> li {
|
||||
width: 100%;
|
||||
margin-top: 0;
|
||||
|
||||
@ -30,6 +30,7 @@ class PluginInputFile extends React.PureComponent {
|
||||
const {
|
||||
name,
|
||||
onChange,
|
||||
showLoader,
|
||||
} = this.props;
|
||||
const { isDraging } = this.state;
|
||||
const link = (
|
||||
@ -40,7 +41,7 @@ class PluginInputFile extends React.PureComponent {
|
||||
|
||||
return (
|
||||
<label
|
||||
className={cn(styles.pluginInputFile, isDraging && styles.pluginInputFileHover)}
|
||||
className={cn(styles.pluginInputFile, isDraging && styles.pluginInputFileHover, showLoader && styles.pluginInputFileHover)}
|
||||
onDragEnter={this.handleDragEnter}
|
||||
onDragOver={(e) => {
|
||||
e.preventDefault();
|
||||
@ -49,7 +50,8 @@ class PluginInputFile extends React.PureComponent {
|
||||
onDrop={this.handleDrop}
|
||||
>
|
||||
<p className={styles.textWrapper}>
|
||||
<FormattedMessage id="upload.PluginInputFile.text" values={{ link }} />
|
||||
{!showLoader && <FormattedMessage id="upload.PluginInputFile.text" values={{ link }} /> }
|
||||
{showLoader && <FormattedMessage id="upload.PluginInputFile.loading" />}
|
||||
</p>
|
||||
<div
|
||||
onDragLeave={this.handleDragLeave}
|
||||
@ -74,6 +76,7 @@ PluginInputFile.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
onChange: PropTypes.func,
|
||||
onDrop: PropTypes.func.isRequired,
|
||||
showLoader: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
export default PluginInputFile;
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
}
|
||||
|
||||
.pluginInputFileHover {
|
||||
background: rgba(28,93,231,0.01) !important;
|
||||
background-color: rgba(28,93,231,0.01) !important;
|
||||
border: 2px dashed rgba(28,93,231,0.10) !important;
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,9 @@ import {
|
||||
ON_DROP,
|
||||
ON_SEARCH,
|
||||
ON_SEARCH_SUCCESS,
|
||||
SET_LOADING,
|
||||
SET_PARAMS,
|
||||
UNSET_LOADING,
|
||||
} from './constants';
|
||||
|
||||
export function changeParams({ target }) {
|
||||
@ -78,6 +80,12 @@ export function onSearch({ target }) {
|
||||
};
|
||||
}
|
||||
|
||||
export function setLoading() {
|
||||
return {
|
||||
type: SET_LOADING,
|
||||
};
|
||||
}
|
||||
|
||||
export function setParams(params) {
|
||||
return {
|
||||
type: SET_PARAMS,
|
||||
@ -91,3 +99,9 @@ export function onSearchSuccess(data) {
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
export function unsetLoading() {
|
||||
return {
|
||||
type: UNSET_LOADING,
|
||||
};
|
||||
}
|
||||
|
||||
@ -13,4 +13,6 @@ export const GET_DATA_SUCCESS = 'Upload/HomePage/GET_DATA_SUCCESS';
|
||||
export const ON_DROP = 'Upload/HomePage/ON_DROP';
|
||||
export const ON_SEARCH = 'Upload/HomePage/ON_SEARCH';
|
||||
export const ON_SEARCH_SUCCESS = 'Upload/HomePage/ON_SEARCH_SUCCESS';
|
||||
export const SET_LOADING = 'Upload/HomePage/SET_LOADING';
|
||||
export const SET_PARAMS = 'Upload/HomePage/SET_PARAMS';
|
||||
export const UNSET_LOADING = 'Upload/HomePage/UNSET_LOADING';
|
||||
|
||||
@ -137,6 +137,7 @@ export class HomePage extends React.Component {
|
||||
<PluginInputFile
|
||||
name="files"
|
||||
onDrop={this.props.onDrop}
|
||||
showLoader={this.props.uploadFilesLoading}
|
||||
/>
|
||||
<div className={styles.entriesWrapper}>
|
||||
<div>
|
||||
@ -199,6 +200,7 @@ HomePage.propTypes = {
|
||||
search: PropTypes.string.isRequired,
|
||||
setParams: PropTypes.func.isRequired,
|
||||
uploadedFiles: PropTypes.arrayOf(PropTypes.object),
|
||||
uploadFilesLoading: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
|
||||
@ -13,13 +13,16 @@ import {
|
||||
GET_DATA_SUCCESS,
|
||||
ON_SEARCH,
|
||||
ON_SEARCH_SUCCESS,
|
||||
SET_LOADING,
|
||||
SET_PARAMS,
|
||||
UNSET_LOADING,
|
||||
} from './constants';
|
||||
|
||||
const initialState = fromJS({
|
||||
deleteSuccess: false,
|
||||
dataToDelete: '',
|
||||
entriesNumber: 0,
|
||||
uploadFilesLoading: false,
|
||||
search: '',
|
||||
uploadedFiles: List([]),
|
||||
params: Map({
|
||||
@ -46,8 +49,12 @@ function homePageReducer(state = initialState, action) {
|
||||
return state.update('search', () => action.value);
|
||||
case ON_SEARCH_SUCCESS:
|
||||
return state.update('uploadedFiles', () => List(action.data));
|
||||
case SET_LOADING:
|
||||
return state.update('uploadFilesLoading', () => true);
|
||||
case SET_PARAMS:
|
||||
return state.set('params', Map(action.params));
|
||||
case UNSET_LOADING:
|
||||
return state.update('uploadFilesLoading', () => false);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
@ -9,6 +9,8 @@ import {
|
||||
dropSuccess,
|
||||
getDataSuccess,
|
||||
onSearchSuccess,
|
||||
setLoading,
|
||||
unsetLoading,
|
||||
} from './actions';
|
||||
import {
|
||||
DELETE_DATA,
|
||||
@ -55,6 +57,7 @@ function* dataGet() {
|
||||
|
||||
function* uploadFiles(action) {
|
||||
try {
|
||||
yield put(setLoading());
|
||||
const headers = {
|
||||
'X-Forwarded-Host': 'strapi',
|
||||
};
|
||||
@ -71,6 +74,8 @@ function* uploadFiles(action) {
|
||||
|
||||
} catch(err) {
|
||||
strapi.notification.error('notification.error');
|
||||
} finally {
|
||||
yield put(unsetLoading());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
|
||||
"PluginInputFile.text": "Drag & drop your files into this area or {link} from a file to upload",
|
||||
"PluginInputFile.link": "browse",
|
||||
"PluginInputFile.loading": "Your files are being uploaded",
|
||||
|
||||
"notification.delete.success": "The file has been deleted",
|
||||
"notification.dropFile.success": "Your file has been uploaded",
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
|
||||
"PluginInputFile.text": "Drag & drop vos fichiers dans cette zone ou {link} un fichier à télécharger",
|
||||
"PluginInputFile.link": "recherchez",
|
||||
"PluginInputFile.loading": "Vos fichiers sont en train d'être téléchargés",
|
||||
|
||||
"notification.delete.success": "Le fichier a bien été supprimé",
|
||||
"notification.dropFile.success": "Votre fichier a été téléchargé",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user