Commit 6f064ed8 authored by Maksym Tishchenko's avatar Maksym Tishchenko
Browse files

Refreshing current display

parent b1131e96
......@@ -18,6 +18,7 @@
"read": "Read",
"remove": "Remove",
"replace": "Replace",
"refresh": "Refresh",
"save": "Save",
"saveAsNew": "Save as new",
"search": "Search",
......
import * as React from 'react';
import { withTranslation } from 'react-i18next';
// UI
import { withStyles } from '@material-ui/core/styles';
import IconButton from "@material-ui/core/IconButton";
import RefreshIcon from '@material-ui/icons/Refresh';
const styles = (theme) => ({
/* eslint-disable*/
icon: {
transform: 'rotate(720deg)',
transition: '300ms transform',
color: 'white'
},
iconSelected: {
animation: '$spin 300ms',
transform: 'rotate(360deg)'
},
'@keyframes spin': {
'0%': {
transform: 'rotate(0deg)'
},
'100%': {
transform: 'rotate(360deg)'
}
}
/* eslint-enable */
});
interface IRefreshButtonProps extends React.ClassAttributes<any> {
classes: any;
t: any;
action: () => void;
disabled?: boolean;
className?: string;
color?: string;
}
class RefreshButton extends React.Component<IRefreshButtonProps, any> {
public constructor(props) {
super(props);
this.state = {
clicked: false
}
}
private handleClick = () => {
this.setState({ clicked: !this.state.clicked })
this.props.action()
};
public render() {
const { classes, color, className, disabled, t } = this.props;
const { clicked } = this.state;
return (
<IconButton
type="button"
aria-label="Refresh"
disabled={ disabled }
title={ t('common:action.refresh') }
onClick={ this.handleClick }
style={{ color: color ?? 'white' }}
className={ `${ classes.icon } ${ clicked ? classes.iconSelected : '' } ${ className ?? '' }` }
>
<RefreshIcon/>
</IconButton>
);
}
}
export default withStyles(styles)(withTranslation()(RefreshButton));
......@@ -4,6 +4,7 @@ import Hidden from '@material-ui/core/Hidden';
import { useTranslation } from 'react-i18next';
import { ClassNameMap, CSSProperties } from '@material-ui/styles';
import { makeStyles } from '@material-ui/core';
import RefreshButton from "@gringlobal-ce/client/ui/common/button/RefreshButton";
const useStyles = makeStyles((theme): Record<string, CSSProperties> => ({
root: {
......@@ -21,16 +22,21 @@ const useStyles = makeStyles((theme): Record<string, CSSProperties> => ({
fontSize: '0.8571rem',
color: theme.palette.secondary.contrastText,
},
childrenWrap: {
display: 'flex',
alignItems: 'center',
}
}));
interface IContentHeader extends React.ClassAttributes<any> {
title: string | JSX.Element;
subTitle?: string;
children?: React.ReactNode;
onRefresh?: () => void;
}
function ContentHeader(props: IContentHeader): JSX.Element {
const { title, subTitle, children } = props;
const { title, subTitle, children, onRefresh } = props;
const classes: ClassNameMap = useStyles();
const { t } = useTranslation();
......@@ -46,7 +52,10 @@ function ContentHeader(props: IContentHeader): JSX.Element {
</h3>
</Hidden>
</Grid>
<Grid item>
<Grid item className={ classes.childrenWrap }>
{ onRefresh && <div className={ `${ children ? "mr-1rem" : "" }` }>
<RefreshButton action={ onRefresh }/>
</div> }
{ children }
</Grid>
</Grid>
......
......@@ -2,16 +2,26 @@
import * as React from 'react';
import Tabs from '@material-ui/core/Tabs';
import { withStyles, WithStyles } from '@material-ui/core/styles';
import RefreshButton from "@gringlobal-ce/client/ui/common/button/RefreshButton";
const styles = (theme) => ({
root: {
backgroundColor: theme.palette.secondary.main,
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between'
},
spaceForFilter: {
width: "calc(100% - 110px)",
[theme.breakpoints.down('sm')]: {
width: "calc(100% - 55px)",
},
},
refreshButtonSpace: {
marginRight: '110px',
[theme.breakpoints.down('sm')]: {
marginRight: '55px',
},
}
});
......@@ -20,10 +30,11 @@ interface IProps {
indicatorColor: string;
textColor: string;
withFilters?: boolean
onRefresh?: () => void;
}
const HeaderTabs = (props: IProps & WithStyles & any) => {
const { classes, indicatorColor, textColor, withFilters, ...other } = props;
const { classes, indicatorColor, onRefresh, textColor, withFilters, ...other } = props;
return (
<div id="header" className={ classes.root }>
......@@ -38,6 +49,9 @@ const HeaderTabs = (props: IProps & WithStyles & any) => {
} }
{ ...other }
/>
{ onRefresh && <div className={ withFilters ? classes.refreshButtonSpace : '' }>
<RefreshButton action={ onRefresh }/>
</div> }
</div>
);
}
......
......@@ -9,7 +9,7 @@ import Tab from '@material-ui/core/Tab';
import { listAccessionActionsAction, loadMoreAccessionActionsAction } from 'accession/action/public';
// model
import { IPageRequest } from '@gringlobal-ce/client/model/page';
import { IPageRequest, Page } from '@gringlobal-ce/client/model/page';
import { AccessionAction, AccessionActionFilter, ActionState } from '@gringlobal-ce/client/model/gringlobal';
// UI
import PageTitle from '@gringlobal-ce/client/ui/common/PageTitle';
......@@ -67,6 +67,9 @@ const AccessionActionsPage = ({ loadableData, listAction, loadMoreData, routingP
dataDependencies: [selectedTab],
});
const refreshData = () => {
listAction(data.filter, { ...Page.nextPage(data), page: 0 })
}
return (
<>
......@@ -80,6 +83,7 @@ const AccessionActionsPage = ({ loadableData, listAction, loadMoreData, routingP
scrollButtons="auto"
aria-label="Accession actions tabs"
withFilters
onRefresh={ refreshData }
>
{ Object.values(AccessionActionsTabs).map((tabConfig) => (
<Tab value={ tabConfig.index } label={ t(tabConfig.label) } key={ tabConfig.index }/>
......
......@@ -28,6 +28,7 @@ import AccessionForm from 'accession/ui/c/AccessionForm';
import ScheduleOutlinedIcon from '@material-ui/icons/ScheduleOutlined';
import FABMenu from '@gringlobal-ce/client/ui/common/button/FABMenu';
import AccessionActionDialog from 'accession/ui/c/AccessionActionDialog';
import { Page } from "@gringlobal-ce/client/model/page";
export const AccessionTableDefaultConfig = {
defaultColumns: [
......@@ -153,6 +154,14 @@ class BrowsePage extends React.Component<PropsFromRedux & WithBrowsePage & WithT
this.setState({ accessionActionDialogIsOpen: false });
};
private onRefresh = () => {
const { data, listAction } = this.props;
listAction(data.filter, { ...Page.nextPage(data), page: 0 })
if (data.number > 0) {
this.setState({ selected: [] })
}
}
public render() {
const { data, t, onSortChange, applyFilter, loadMore } = this.props;
const { accessionDialogIsOpen, accessionActionDialogIsOpen, selected, error } = this.state;
......@@ -169,7 +178,7 @@ class BrowsePage extends React.Component<PropsFromRedux & WithBrowsePage & WithT
return (
<>
<PageTitle title={ data ? t('accession.browse.title', { count: data?.totalElements }) : t('accession.browse.loading') }/>
<ContentHeader title={ data ? t('accession.browse.title', { count: data?.totalElements }) : t('accession.browse.loading') }>
<ContentHeader onRefresh={ this.onRefresh } title={ data ? t('accession.browse.title', { count: data?.totalElements }) : t('accession.browse.loading') }>
<FiltersButton>
<Filters
onSubmit={ applyFilter }
......
......@@ -188,19 +188,17 @@ class AccessionDetailsPage extends React.Component<PropsFromRedux & WithBrowsePa
}
public componentDidMount(): void {
const { getAccessionAction, id, getAccessionInventories, accessionCall } = this.props;
const { id, accessionCall } = this.props;
if (id && !accessionCall || accessionCall.data.id !== +id) {
getAccessionAction(id);
getAccessionInventories(id);
this.refreshData();
}
}
public componentDidUpdate(prevProps, prevState) {
const { accessionCall, id, getAccessionAction, getAccessionInventories, currentTab } = this.props;
const { accessionCall, id, currentTab } = this.props;
const { actions, selected, sourceDescObservations } = this.state;
if (!accessionCall || !accessionCall.loading && (!accessionCall.error && id && +id !== accessionCall.data.id)) {
getAccessionAction(id);
getAccessionInventories(id);
this.refreshData();
}
if (prevState.actions.length === 0 && actions.length === 0 && accessionCall?.data?.actions.length > 0) {
......@@ -610,6 +608,12 @@ class AccessionDetailsPage extends React.Component<PropsFromRedux & WithBrowsePa
this.setState({ descObservationDialogIsOpen: false, createNew: true });
};
private refreshData = () => {
const { getAccessionAction, id, getAccessionInventories } = this.props;
getAccessionAction(id);
getAccessionInventories(id);
}
public render(): React.ReactNode {
const {
......@@ -668,6 +672,7 @@ class AccessionDetailsPage extends React.Component<PropsFromRedux & WithBrowsePa
variant="scrollable"
scrollButtons="auto"
aria-label="Inventory tabs"
onRefresh={ this.refreshData }
>
<Tab value={ AccessionDetailsTabs.INFO } label={ accession ? <>{ accession.accessionNumber }</> : t('accession.public.p.details.title') } />
<Tab value={ AccessionDetailsTabs.INVENTORIES } label={ t('client:model.name.Inventory_plural') } />
......
......@@ -28,6 +28,7 @@ import UploadProgressData from '@gringlobal-ce/client/model/genesys/UploadProgre
import LinearProgress from '@material-ui/core/LinearProgress';
import { Button, debounce, DialogActions, DialogContentText } from '@material-ui/core';
import Loading from '@gringlobal-ce/client/ui/common/Loading';
import { Page } from "@gringlobal-ce/client/model/page";
const AccessionMCPDTableConfigProps = {
defaultColumns: [
......@@ -165,6 +166,11 @@ class BrowsePage extends React.Component<PropsFromRedux & WithTranslation & With
},
]
private onRefresh = () => {
const { data, listAction } = this.props;
listAction(data.filter, { ...Page.nextPage(data), page: 0 })
}
public render() {
const { data, t, onSortChange, applyFilter, loadMore } = this.props;
const { uploadProgress } = this.state;
......@@ -173,7 +179,7 @@ class BrowsePage extends React.Component<PropsFromRedux & WithTranslation & With
return (
<>
<PageTitle title={ data ? t('accession.browse.title', { count: data?.totalElements }) : t('accession.browse.loading') }/>
<ContentHeader title={ data ? t('accession.browse.title', { count: data?.totalElements }) : t('accession.browse.loading') }>
<ContentHeader onRefresh={ this.onRefresh } title={ data ? t('accession.browse.title', { count: data?.totalElements }) : t('accession.browse.loading') }>
<FiltersButton>
<Filters
onSubmit={ applyFilter }
......
......@@ -287,7 +287,7 @@ class SchedulePage extends React.Component<PropsFromRedux & WithTranslation & Wi
return (
<>
<PageTitle title={ t('accession.public.p.schedule.title') } />
<ContentHeader title={ t('accession.public.p.schedule.title') }>
<ContentHeader onRefresh={ this.loadOverview } title={ t('accession.public.p.schedule.title') }>
<FiltersButton>
<Filters
onSubmit={ (filter) => this.setState({ filter }) }
......
......@@ -29,6 +29,7 @@ import { AccessionLink } from 'ui/common/Links';
import TranslatedSourceDescObservation from '@gringlobal-ce/client/model/gringlobal/TranslatedSourceDescObservation';
import TranslatedSourceDescriptor from '@gringlobal-ce/client/model/gringlobal/TranslatedSourceDescriptor';
import TranslatedSourceDescriptorCode from '@gringlobal-ce/client/model/gringlobal/TranslatedSourceDescriptorCode';
import { Page } from "@gringlobal-ce/client/model/page";
export const SourceDescObservationTableDefaultConfig = {
......@@ -138,6 +139,11 @@ class BrowsePage extends React.Component<PropsFromRedux & WithBrowsePage & WithT
return this.setState({ error: null });
}
private onRefresh = () => {
const { data, listAction } = this.props;
listAction(data.filter, { ...Page.nextPage(data), page: 0 })
}
public render() {
const { t, onSortChange, applyFilter, loadMore, data } = this.props;
const { selected, descriptorDialogIsOpen, createNew, error } = this.state;
......@@ -162,7 +168,7 @@ class BrowsePage extends React.Component<PropsFromRedux & WithBrowsePage & WithT
return (
<>
<PageTitle title={ t('accession.public.p.sourceDescObservation.browse.title', { count: data?.totalElements }) }/>
<ContentHeader title={ t('accession.public.p.sourceDescObservation.browse.title', { count: data?.totalElements }) }>
<ContentHeader onRefresh={ this.onRefresh } title={ t('accession.public.p.sourceDescObservation.browse.title', { count: data?.totalElements }) }>
<FiltersButton>
<Filters
onSubmit={ applyFilter }
......
......@@ -25,6 +25,7 @@ import SourceDescriptorForm from 'accession/ui/c/SourceDescriptorForm';
import { SourceDescriptorService } from '@gringlobal-ce/client/service';
import TranslatedSourceDescriptor from '@gringlobal-ce/client/model/gringlobal/TranslatedSourceDescriptor';
import { Link } from 'react-router-dom';
import { Page } from "@gringlobal-ce/client/model/page";
export const SourceDescriptorTableDefaultConfig = {
defaultColumns: [
......@@ -128,6 +129,11 @@ class BrowsePage extends React.Component<PropsFromRedux & WithBrowsePage & WithT
return this.setState({ error: null });
}
private onRefresh = () => {
const { data, listAction } = this.props;
listAction(data.filter, { ...Page.nextPage(data), page: 0 })
}
public render() {
const { t, onSortChange, applyFilter, loadMore, data } = this.props;
const { selected, descriptorDialogIsOpen, createNew, error } = this.state;
......@@ -150,7 +156,7 @@ class BrowsePage extends React.Component<PropsFromRedux & WithBrowsePage & WithT
return (
<>
<PageTitle title={ t('accession.public.p.sourceDescriptor.browse.title', { count: data?.totalElements }) }/>
<ContentHeader title={ t('accession.public.p.sourceDescriptor.browse.title', { count: data?.totalElements }) }>
<ContentHeader onRefresh={ this.onRefresh } title={ t('accession.public.p.sourceDescriptor.browse.title', { count: data?.totalElements }) }>
<FiltersButton>
<Filters
onSubmit={ applyFilter }
......
......@@ -135,6 +135,16 @@ class SourceDescriptorDetailsPage extends React.Component<PropsFromRedux & WithT
}).catch((e) => console.log('Loading translations error: ', e));
}
private refreshData = () => {
const { id, getSourceDescriptorAction } = this.props;
getSourceDescriptorAction(id);
this.loadCodes();
this.loadLangs().then((languages) => {
this.setState({ languages })
}).catch((e) => console.log('Loading translations error: ', e));
}
public componentDidUpdate(prevProps, prevState: ISourceDescriptorDetailsPageState) {
const { sourceDescriptorCall, id, getSourceDescriptorAction } = this.props;
const { codes } = this.state;
......@@ -437,7 +447,7 @@ class SourceDescriptorDetailsPage extends React.Component<PropsFromRedux & WithT
return (
<>
<PageTitle title={ sourceDescriptor && (sourceDescriptor.title || sourceDescriptor.codedName) || t('accession.public.p.sourceDescriptor.details.title') }/>
<ContentHeader title={ sourceDescriptor && (sourceDescriptor.title || sourceDescriptor.codedName) || t('accession.public.p.sourceDescriptor.details.title') }/>
<ContentHeader onRefresh={ this.refreshData } title={ sourceDescriptor && (sourceDescriptor.title || sourceDescriptor.codedName) || t('accession.public.p.sourceDescriptor.details.title') }/>
{ loading && <Loading /> }
{ sourceDescriptor && (
<>
......
......@@ -193,6 +193,10 @@ class SummaryPage extends React.Component<PropsFromRedux & WithTranslation & Wit
});
}
private refreshData = () => {
this.loadNumbers(this.state.group);
}
private selectGroup = (group: string, title: string) => (ev) => {
console.log(`Selected group ${group}`);
this.loadNumbers(group);
......@@ -208,7 +212,7 @@ class SummaryPage extends React.Component<PropsFromRedux & WithTranslation & Wit
return (
<>
<PageTitle title={ t('accession.public.p.summary.title') } />
<ContentHeader title={ t('accession.public.p.summary.title') }>
<ContentHeader onRefresh={ this.refreshData } title={ t('accession.public.p.summary.title') }>
<FiltersButton>
<Filters
onSubmit={ (filter) => this.setState({accessionFilter: filter}) }
......
......@@ -26,6 +26,7 @@ import CancelOutlinedIcon from '@material-ui/icons/CancelOutlined';
import EditIcon from '@material-ui/icons/Edit';
import FABMenu from '@gringlobal-ce/client/ui/common/button/FABMenu';
import withBrowsePageBase, { WithBrowsePage } from "ui/common/withBrowsePageBase";
import { Page } from "@gringlobal-ce/client/model/page";
export const AppSettingsTableConfig = new TableConfiguration({
defaultColumns: [
......@@ -110,6 +111,11 @@ class BrowsePage extends React.Component<PropsFromRedux & WithTranslation & With
this.setState({ appSettingDialogIsOpen: false, createNew: false });
};
private onRefresh = () => {
const { data, listAction } = this.props;
listAction({ ...Page.nextPage(data), page: 0 })
}
public render() {
const { t, data, loadMore } = this.props;
const { appSettingDialogIsOpen, error, selected, createNew } = this.state;
......@@ -131,7 +137,7 @@ class BrowsePage extends React.Component<PropsFromRedux & WithTranslation & With
return (
<>
<PageTitle title={ t('appsetting.admin.p.browse.title') }/>
<ContentHeader title={ t('appsetting.admin.p.browse.title') }/>
<ContentHeader onRefresh={ this.onRefresh } title={ t('appsetting.admin.p.browse.title') }/>
<Table
tableKey="app-setting-list"
type="AppSetting"
......
......@@ -13,6 +13,7 @@ import withBrowsePageBase, { WithBrowsePage } from 'ui/common/withBrowsePageBase
import PageTitle from '@gringlobal-ce/client/ui/common/PageTitle';
import Filters from 'auditlog/ui/admin/c/Filters';
import FiltersButton from 'accession/ui/c/FiltersButton';
import { Page } from "@gringlobal-ce/client/model/page";
export const AuditLogTableDefaultConfig = {
defaultColumns: [
......@@ -48,6 +49,11 @@ class BrowsePage extends React.Component<PropsFromRedux & WithTranslation & With
super(props);
}
private onRefresh = () => {
const { data, listAction } = this.props;
listAction(data.filter, { ...Page.nextPage(data), page: 0 })
}
public render() {
const { data, t, onSortChange, applyFilter, loadMore } = this.props;
const columns = AuditLogTableConfig.getColumns(data && data.content ? data.content[0] : null);
......@@ -55,7 +61,7 @@ class BrowsePage extends React.Component<PropsFromRedux & WithTranslation & With
return (
<>
<PageTitle title={ t('auditlog.admin.p.browse.title') }/>
<ContentHeader title={ t('auditlog.admin.p.browse.title') }>
<ContentHeader onRefresh={ this.onRefresh } title={ t('auditlog.admin.p.browse.title') }>
<FiltersButton>
<Filters
onSubmit={ applyFilter }
......
......@@ -129,7 +129,7 @@ class BrowsePage extends React.Component<PropsFromRedux & WithTranslation, IBrow
}
public render() {
const { codeValues, groupName } = this.props;
const { codeValues, refreshCodeValues, groupName } = this.props;
const { dialogIsOpen, statsDialogIsOpen, selected } = this.state;
const data = codeValues && codeValues.data ? getCodeValuesList(codeValues.data, groupName) : [];
const groups = codeValues && codeValues.data ? this.getGroups(codeValues.data) : [];
......@@ -158,7 +158,7 @@ class BrowsePage extends React.Component<PropsFromRedux & WithTranslation, IBrow
return (
<>
<PageTitle title={ this.getTitle() }/>
<ContentHeader title={ this.getTitle() }>
<ContentHeader onRefresh={ refreshCodeValues } title={ this.getTitle() }>
{ /* this.state.selected.length > 0 &&
<Button onClick={ this.remove } variant="contained" disabled={ this.state.selected.length < 1 }>
{ t('common:action.remove') }
......
......@@ -90,6 +90,15 @@ class CodeValueDetailsPage extends React.Component<PropsFromRedux & WithTranslat
}
}
private refreshData = () => {
const { id, getCodeValueAction } = this.props;
getCodeValueAction(id);
this.loadLangs().then((languages) => {
this.setState({ languages })
}).catch((e) => console.log('Loading translations error: ', e));
}
public handleRemove = () => {
const { removeCodeValueAction, id, t, codeValueCall } = this.props;
......@@ -182,7 +191,7 @@ class CodeValueDetailsPage extends React.Component<PropsFromRedux & WithTranslat
return (
<>
<PageTitle title={ codeValue ? codeValue.title : t('codevalue.admin.p.details.title') }/>
<ContentHeader title={ codeValue ? codeValue.title : t('codevalue.admin.p.details.title') }/>
<ContentHeader onRefresh={ this.refreshData } title={ codeValue ? codeValue.title : t('codevalue.admin.p.details.title') }/>
{ loading && <Loading /> }
{ codeValue && (
<GridContainer spacing="1rem">
......
......@@ -26,6 +26,7 @@ import CooperatorForm from 'cooperator/ui/c/CooperatorForm';
import { showSnackbar } from '@gringlobal-ce/client/action/snackbar';
import SimilarCooperatorsDialog from 'cooperator/ui/c/SimilarCooperatorsDialog';
import { GeographyLink } from 'ui/common/Links';
import { Page } from "@gringlobal-ce/client/model/page";
export const CooperatorTableDefaultConfig = {
defaultColumns: [
......@@ -142,6 +143,11 @@ class CooperatorBrowsePage extends React.Component<PropsFromRedux & WithTranslat
this.setState({ similar: null, unsaved: null });
};
private onRefresh = () => {
const { data, listAction } = this.props;
listAction(data.filter, { ...Page.nextPage(data), page: 0 })
}
public render() {
const { data, t, onSortChange, applyFilter, loadMore } = this.props;
const { cooperatorDialogIsOpen, similar, unsaved, error } = this.state;
......@@ -150,7 +156,7 @@ class CooperatorBrowsePage extends React.Component<PropsFromRedux & WithTranslat
return (
<>
<PageTitle title={ data && data.totalElements ? t('cooperator.browse.title', { count: data.totalElements }) : t('cooperator.public.p.browse.title') }/>
<ContentHeader title={ data && data.totalElements ? t('cooperator.browse.title', { count: data.totalElements }) : t('cooperator.public.p.browse.title') }>
<ContentHeader onRefresh={ this.onRefresh } title={ data && data.totalElements ? t('cooperator.browse.title', { count: data.totalElements }) : t('cooperator.public.p.browse.title') }>
<FiltersButton>
<Filters
onSubmit={ applyFilter }
......
......@@ -54,18 +54,18 @@ class CooperatorDetailsPage extends React.Component<PropsFromRedux & WithTransla
private loadingSimilar = false;
public componentDidMount(): void {
const { id, cooperatorCall, getCooperatorAction } = this.props;
const { id, cooperatorCall } = this.props;
if (!cooperatorCall || !cooperatorCall.data || cooperatorCall.data.id !== +id) {
getCooperatorAction(id);
this.refreshData()
}
}
public componentDidUpdate(prevProps) {
const { cooperatorCall, id, getCooperatorAction, currentTab } = this.props;
const { cooperatorCall, id, currentTab } = this.props;
if (!cooperatorCall || !cooperatorCall.loading && (!this.saveAsNew && !cooperatorCall.error && id && +id !== cooperatorCall.data.