import { DataTableFilters } from '../data-table-filters/data-table-filters-tree';
import { DataTableFiltersPopover } from '../data-table-filters/data-table-filters-popover';
import { countNodes } from 'models/tree';
+import { PendingIcon } from 'components/icon/icon';
import { SvgIconProps } from '@material-ui/core/SvgIcon';
import ArrowDownwardIcon from '@material-ui/icons/ArrowDownward';
currentRoute?: string;
}
-type CssRules = "tableBody" | "root" | "content" | "noItemsInfo" | 'tableCell' | 'arrow' | 'arrowButton' | 'tableCellWorkflows';
+type CssRules = "tableBody" | "root" | "content" | "noItemsInfo" | 'tableCell' | 'arrow' | 'arrowButton' | 'tableCellWorkflows' | 'loader';
const styles: StyleRulesCallback<CssRules> = (theme: Theme) => ({
root: {
tableBody: {
background: theme.palette.background.paper
},
+ loader: {
+ left: '50%',
+ marginLeft: '-84px',
+ position: 'absolute'
+ },
noItemsInfo: {
textAlign: "center",
padding: theme.spacing.unit
</TableRow>
</TableHead>
<TableBody className={classes.tableBody}>
- {items.map(this.renderBodyRow)}
+ {
+ this.props.working ?
+ <div className={classes.loader}>
+ <DataTableDefaultView
+ icon={PendingIcon}
+ messages={['Loading data, please wait.']} />
+ </div> : items.map(this.renderBodyRow)
+ }
</TableBody>
</Table>
{items.length === 0 && this.props.working !== undefined && !this.props.working && this.renderNoItemsPlaceholder()}
// Import FontAwesome icons
import { library } from '@fortawesome/fontawesome-svg-core';
-import { faPencilAlt, faSlash, faUsers } from '@fortawesome/free-solid-svg-icons';
+import { faPencilAlt, faSlash, faUsers, faEllipsisH } from '@fortawesome/free-solid-svg-icons';
import { CropFreeSharp } from '@material-ui/icons';
library.add(
faPencilAlt,
faSlash,
faUsers,
+ faEllipsisH,
);
+export const PendingIcon = (props: any) =>
+ <span {...props}>
+ <span className='fas fa-ellipsis-h' />
+ </span>
+
export const ReadOnlyIcon = (props: any) =>
<span {...props}>
<div className="fa-layers fa-1x fa-fw">
import { GroupResource, GroupClass } from 'models/group';
import { SortDirection } from 'components/data-table/data-column';
import { GroupsPanelColumnNames } from 'views/groups-panel/groups-panel';
+import { progressIndicatorActions } from "store/progress-indicator/progress-indicator-actions";
export class GroupsPanelMiddlewareService extends DataExplorerMiddlewareService {
constructor(private services: ServiceRepository, id: string) {
api.dispatch(groupsPanelDataExplorerIsNotSet());
} else {
try {
+ api.dispatch(progressIndicatorActions.START_WORKING(this.getId()));
const order = new OrderBuilder<GroupResource>();
const sortColumn = getSortColumn(dataExplorer);
if (sortColumn) {
api.dispatch(updateResources(permissions.items));
} catch (e) {
api.dispatch(couldNotFetchFavoritesContents());
+ } finally {
+ api.dispatch(progressIndicatorActions.STOP_WORKING(this.getId()));
}
}
}
await api.dispatch<any>(loadMissingProcessesInformation(response.items));
api.dispatch(setItems(response));
} catch (e) {
- api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId()));
api.dispatch(projectPanelActions.SET_ITEMS({
items: [],
itemsAvailable: 0,
rowsPerPage: dataExplorer.rowsPerPage
}));
api.dispatch(couldNotFetchProjectContents());
+ } finally {
+ api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId()));
}
}
}
import { getSortColumn } from "store/data-explorer/data-explorer-reducer";
import { updatePublicFavorites } from 'store/public-favorites/public-favorites-actions';
import { FilterBuilder } from 'services/api/filter-builder';
+import { progressIndicatorActions } from 'store/progress-indicator/progress-indicator-actions';
export class SharedWithMeMiddlewareService extends DataExplorerMiddlewareService {
constructor(private services: ServiceRepository, id: string) {
const state = api.getState();
const dataExplorer = getDataExplorer(state.dataExplorer, this.getId());
try {
+ api.dispatch(progressIndicatorActions.START_WORKING(this.getId()));
const response = await this.services.groupsService
.contents('', {
...getParams(dataExplorer),
api.dispatch(setItems(response));
} catch (e) {
api.dispatch(couldNotFetchSharedItems());
+ } finally {
+ api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId()));
}
}
}
// SPDX-License-Identifier: AGPL-3.0
import { bindDataExplorerActions } from "../data-explorer/data-explorer-action";
-import { Dispatch } from 'redux';
-import { ServiceRepository } from "services/services";
-import { RootState } from 'store/store';
export const SHARED_WITH_ME_PANEL_ID = "sharedWithMePanel";
export const sharedWithMePanelActions = bindDataExplorerActions(SHARED_WITH_ME_PANEL_ID);
-
-export const loadSharedWithMePanel = () =>
- (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
- dispatch(sharedWithMePanelActions.REQUEST_ITEMS());
- };
-
-
+export const loadSharedWithMePanel = () => sharedWithMePanelActions.REQUEST_ITEMS();
onContextMenu?: (event: React.MouseEvent<HTMLElement>, item: any, isAdmin?: boolean) => void;
onRowDoubleClick: (item: any) => void;
extractKey?: (item: any) => React.Key;
+ working?: boolean;
}
+let data: any[] = [];
+let href: string = '';
+
const mapStateToProps = (state: RootState, { id }: Props) => {
const progress = state.progressIndicator.find(p => p.id === id);
- const working = progress && progress.working;
+ const dataExplorerState = getDataExplorer(state.dataExplorer, id);
const currentRoute = state.router.location ? state.router.location.pathname : '';
const currentItemUuid = currentRoute === '/workflows' ? state.properties.workflowPanelDetailsUuid : state.detailsPanel.resourceUuid;
- return { ...getDataExplorer(state.dataExplorer, id), working, paperKey: currentRoute, currentItemUuid };
+
+ let loading = false;
+
+ if (dataExplorerState.items.length > 0 && data === dataExplorerState.items && href !== window.location.href) {
+ loading = true
+ } else {
+ href = window.location.href;
+ data = dataExplorerState.items;
+ }
+
+ const working = (progress && progress.working) || loading;
+
+ return { ...dataExplorerState, working, paperKey: currentRoute, currentItemUuid };
};
const mapDispatchToProps = () => {
resources: ResourcesState;
isAdmin: boolean;
userUuid: string;
+ dataExplorerItems: any;
}
type ProjectPanelProps = ProjectPanelDataProps & DispatchProp
& WithStyles<CssRules> & RouteComponentProps<{ id: string }>;
+
export const ProjectPanel = withStyles(styles)(
connect((state: RootState) => ({
currentItemId: getProperty(PROJECT_PANEL_CURRENT_UUID)(state.properties),
resources: state.resources,
- userUuid: state.auth.user!.uuid,
+ userUuid: state.auth.user!.uuid
}))(
class extends React.Component<ProjectPanelProps> {
render() {
const { classes } = this.props;
+
return <div data-cy='project-panel' className={classes.root}>
<DataExplorer
id={PROJECT_PANEL_ID}
onRowDoubleClick={this.handleRowDoubleClick}
onContextMenu={this.handleContextMenu}
contextMenuColumn={false}
- dataTableDefaultView={<DataTableDefaultView icon={ShareMeIcon} />} /></div>;
+ dataTableDefaultView={
+ <DataTableDefaultView
+ icon={ShareMeIcon}
+ messages={['No shared items']} />
+ } /></div>;
}
handleContextMenu = (event: React.MouseEvent<HTMLElement>, resourceUuid: string) => {