Skip to content

Commit

Permalink
Merge pull request alephdata#1741 from alephdata/kirk/timelines
Browse files Browse the repository at this point in the history
Timelines
  • Loading branch information
pudo authored May 3, 2021
2 parents bd2eed8 + 4f6a220 commit e275e67
Show file tree
Hide file tree
Showing 49 changed files with 1,989 additions and 298 deletions.
2 changes: 1 addition & 1 deletion ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"dependencies": {
"@alephdata/followthemoney": "2.5.1",
"@alephdata/react-ftm": "2.3.10",
"@alephdata/react-ftm": "2.3.15",
"@blueprintjs/core": "3.43.0",
"@blueprintjs/datetime": "3.22.1",
"@blueprintjs/icons": "3.26.0",
Expand Down
3 changes: 3 additions & 0 deletions ui/src/app/Router.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import EntitySetIndexScreen from 'screens/EntitySetIndexScreen/EntitySetIndexScr
import DiagramScreen from 'screens/DiagramScreen/DiagramScreen';
import ProfileScreen from 'screens/ProfileScreen/ProfileScreen';
import ListScreen from 'screens/ListScreen/ListScreen';
import TimelineScreen from 'screens/TimelineScreen/TimelineScreen';
import EntityScreen from 'screens/EntityScreen/EntityScreen';
import ExportsScreen from 'src/screens/ExportsScreen/ExportsScreen';

Expand Down Expand Up @@ -90,6 +91,8 @@ class Router extends Component {
<Route path="/diagrams" exact component={EntitySetIndexScreen} />
<Route path="/lists/:entitySetId" exact component={ListScreen} />
<Route path="/lists" exact component={EntitySetIndexScreen} />
<Route path="/timelines/:entitySetId" exact component={TimelineScreen} />
<Route path="/timelines" exact component={EntitySetIndexScreen} />
<Route path="/search" exact component={SearchScreen} />
<Route path="/notifications" exact component={NotificationsScreen} />
<Route path="/alerts" exact component={AlertsScreen} />
Expand Down
17 changes: 15 additions & 2 deletions ui/src/components/AuthButtons/AuthButtons.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from '@blueprintjs/core';

import { fetchRole } from 'actions';
import { selectCurrentRole, selectCurrentRoleId, selectMetadata } from 'selectors';
import { selectCurrentRole, selectCurrentRoleId, selectMetadata, selectTester } from 'selectors';
import AuthenticationDialog from 'dialogs/AuthenticationDialog/AuthenticationDialog';
import { DialogToggleButton } from 'components/Toolbar'
import { Skeleton } from 'components/common'
Expand All @@ -24,6 +24,10 @@ const messages = defineMessages({
id: 'nav.diagrams',
defaultMessage: 'Network diagrams',
},
timelines: {
id: 'nav.timelines',
defaultMessage: 'Timelines',
},
lists: {
id: 'nav.lists',
defaultMessage: 'Lists',
Expand Down Expand Up @@ -81,7 +85,7 @@ export class AuthButtons extends Component {
}

render() {
const { role, metadata, intl } = this.props;
const { role, metadata, intl, isTester } = this.props;

if (!role.id && role.isPending) {
return this.renderSkeleton();
Expand Down Expand Up @@ -126,6 +130,14 @@ export class AuthButtons extends Component {
{intl.formatMessage(messages.diagrams)}
</div>
</Link>
{isTester && (
<Link to="/timelines" className="bp3-menu-item">
<Icon icon="gantt-chart" />
<div className="bp3-text-overflow-ellipsis bp3-fill">
{intl.formatMessage(messages.timelines)}
</div>
</Link>
)}
<Link to="/lists" className="bp3-menu-item">
<Icon icon="list" />
<div className="bp3-text-overflow-ellipsis bp3-fill">
Expand Down Expand Up @@ -180,6 +192,7 @@ export class AuthButtons extends Component {
}

const mapStateToProps = (state) => ({
isTester: selectTester(state),
role: selectCurrentRole(state),
roleId: selectCurrentRoleId(state),
metadata: selectMetadata(state),
Expand Down
12 changes: 12 additions & 0 deletions ui/src/components/Collection/CollectionView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ const messages = defineMessages({
id: 'collection.info.lists_description',
defaultMessage: 'Lists let you organize and group related entities of interest.',
},
timelines: {
id: 'collection.info.timelines',
defaultMessage: 'Timelines',
},
timelines_description: {
id: 'collection.info.timelines_description',
defaultMessage: 'Timelines are a way to view and organize events chronologically.',
},
xref: {
id: 'collection.info.xref',
defaultMessage: 'Cross-reference',
Expand Down Expand Up @@ -79,6 +87,7 @@ const icons = {
mappings: 'new-object',
search: 'search',
lists: 'list',
timelines: 'gantt-chart',
mentions: 'tag',
};

Expand Down Expand Up @@ -143,6 +152,9 @@ const CollectionViewCount = ({ id, collection, model, xrefResult }) => {
case 'lists':
count = collection?.counts?.entitysets?.list;
break;
case 'timelines':
count = collection?.counts?.entitysets?.timeline;
break;
default:
return null;
}
Expand Down
23 changes: 11 additions & 12 deletions ui/src/components/Collection/CollectionXrefMode.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
import { defineMessages, injectIntl } from 'react-intl';
import { compose } from 'redux';
import { connect } from 'react-redux';
import { withRouter } from 'react-router';
Expand All @@ -11,12 +11,12 @@ import SearchFacets from 'components/Facet/SearchFacets';
import { QueryInfiniteLoad } from 'components/common';
import CollectionXrefManageMenu from 'components/Collection/CollectionXrefManageMenu';
import XrefTable from 'components/XrefTable/XrefTable';
import SortingBar from 'components/SortingBar/SortingBar';
import { collectionXrefFacetsQuery } from 'queries';
import { selectCollection, selectCollectionXrefResult, selectTester } from 'selectors';
import { queryCollectionXref, queryRoles } from 'actions';

import './CollectionXrefMode.scss';
import 'src/components/common/SortingBar.scss';

const messages = defineMessages({
sort_random: {
Expand All @@ -26,6 +26,10 @@ const messages = defineMessages({
sort_default: {
id: 'xref.sort.default',
defaultMessage: 'Default',
},
sort_label: {
id: "xref.sort.label",
defaultMessage: "Sort by:"
}
});

Expand Down Expand Up @@ -79,22 +83,17 @@ export class CollectionXrefMode extends React.Component {
/>
<SearchActionBar result={result}>
{isTester && (
<div className="SortingBar">
<span className="SortingBar__label">
<FormattedMessage
id="xref.sort.label"
defaultMessage="Sort by:"
/>
</span>
<div className="SortingBar__control">
<SortingBar
filterButtonLabel={intl.formatMessage(messages.sort_label)}
filterButton={
<Button
text={intl.formatMessage(messages[isRandomSort ? 'sort_random' : 'sort_default'])}
onClick={this.toggleSort}
minimal
intent={Intent.PRIMARY}
/>
</div>
</div>
}
/>
)}
</SearchActionBar>
</div>
Expand Down
1 change: 1 addition & 0 deletions ui/src/components/Collection/collectionViewIds.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const viewIds = {
MENTIONS: 'mentions',
SEARCH: 'search',
LISTS: 'lists',
TIMELINES: 'timelines',
};

export default viewIds;
41 changes: 37 additions & 4 deletions ui/src/components/CollectionIndex/CollectionIndex.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,38 @@ import React, { Component } from 'react';
import { compose } from 'redux';
import { connect } from 'react-redux';
import { withRouter } from 'react-router';
import { defineMessages, injectIntl } from 'react-intl';
import { Button, Intent } from '@blueprintjs/core';

import { queryCollections } from 'actions';
import { selectCollectionsResult } from 'selectors';
import { ErrorSection, SearchBox, SortingBar, QueryInfiniteLoad } from 'components/common';
import { selectCollectionsResult, selectCurrentRole } from 'selectors';
import { ErrorSection, SearchBox, QueryInfiniteLoad } from 'components/common';
import QueryTags from 'components/QueryTags/QueryTags';
import SearchActionBar from 'components/common/SearchActionBar';
import CollectionIndexItem from './CollectionIndexItem';
import SortingBar from 'components/SortingBar/SortingBar';


import './CollectionIndex.scss';

const messages = defineMessages({
show_mine: {
id: 'collection.index.filter.mine',
defaultMessage: 'Created by me',
},
show_all: {
id: 'collection.index.filter.all',
defaultMessage: 'All',
},
});

export class CollectionIndex extends Component {
constructor(props) {
super(props);

this.onSearch = this.onSearch.bind(this);
this.updateQuery = this.updateQuery.bind(this);
this.toggleCreatedBy = this.toggleCreatedBy.bind(this);
}

onSearch(queryText) {
Expand All @@ -36,6 +51,12 @@ export class CollectionIndex extends Component {
});
}

toggleCreatedBy() {
const { createdByFilterVal, query, role } = this.props;
const newQuery = createdByFilterVal.length ? query.clearFilter('creator_id') : query.setFilter('creator_id', role.id);
this.updateQuery(newQuery);
}

renderErrors() {
const { emptyText, icon, noResultsText, query, result } = this.props;
const hasQuery = query.hasQuery() || query.hasFilter('creator_id');
Expand Down Expand Up @@ -69,7 +90,7 @@ export class CollectionIndex extends Component {
}

render() {
const { placeholder, query, result, showQueryTags } = this.props;
const { createdByFilterVal, intl, placeholder, query, result, showQueryTags } = this.props;

return (
<div className="CollectionIndex">
Expand All @@ -87,7 +108,15 @@ export class CollectionIndex extends Component {
<SortingBar
query={query}
updateQuery={this.updateQuery}
showCreatedByFilter
sortingFields={['created_at', 'count', 'label', 'updated_at']}
filterButton={
<Button
text={intl.formatMessage(createdByFilterVal.length ? messages.show_mine : messages.show_all)}
onClick={this.toggleCreatedBy}
minimal
intent={Intent.PRIMARY}
/>
}
/>
</SearchActionBar>
</div>
Expand All @@ -104,13 +133,17 @@ export class CollectionIndex extends Component {
}
const mapStateToProps = (state, ownProps) => {
const { query } = ownProps;
const createdByFilterVal = query.getFilter('creator_id');

return {
result: selectCollectionsResult(state, query),
role: selectCurrentRole(state),
createdByFilterVal
};
};

export default compose(
withRouter,
connect(mapStateToProps, { queryCollections }),
injectIntl
)(CollectionIndex);
18 changes: 16 additions & 2 deletions ui/src/components/Dashboard/Dashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import c from 'classnames';

import { queryRoles } from 'actions';
import { groupsQuery } from 'queries';
import { selectRolesResult, selectCurrentRole } from 'selectors';
import { selectRolesResult, selectCurrentRole, selectTester } from 'selectors';

import './Dashboard.scss';

Expand Down Expand Up @@ -37,6 +37,10 @@ const messages = defineMessages({
id: 'dashboard.lists',
defaultMessage: 'Lists',
},
timelines: {
id: 'dashboard.timelines',
defaultMessage: 'Timelines',
},
settings: {
id: 'dashboard.settings',
defaultMessage: 'Settings',
Expand Down Expand Up @@ -74,7 +78,7 @@ class Dashboard extends React.Component {
}

render() {
const { role, intl, location, groupsResult } = this.props;
const { role, intl, isTester, location, groupsResult } = this.props;
const current = location.pathname;

return (
Expand Down Expand Up @@ -127,6 +131,15 @@ class Dashboard extends React.Component {
onClick={() => this.navigate('/diagrams')}
active={current === '/diagrams'}
/>
{isTester && (
<MenuItem
icon="gantt-chart"
text={intl.formatMessage(messages.timelines)}
label={<Count count={role?.counts?.entitysets?.timeline} />}
onClick={() => this.navigate('/timelines')}
active={current === '/timelines'}
/>
)}
<MenuItem
icon="list"
text={intl.formatMessage(messages.lists)}
Expand Down Expand Up @@ -187,6 +200,7 @@ const mapStateToProps = (state, ownProps) => {
const query = groupsQuery(location);
return {
role: selectCurrentRole(state),
isTester: selectTester(state),
groupsQuery: query,
groupsResult: selectRolesResult(state, query),
};
Expand Down
11 changes: 7 additions & 4 deletions ui/src/components/Entity/entityEditorWrapper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
createEntity,
deleteEntity,
entitySetAddEntity,
updateEntitySetItemMutate,
updateEntitySetItemNoMutate,
queryEntities,
queryEntityExpand,
Expand Down Expand Up @@ -74,11 +75,11 @@ const entityEditorWrapper = (EditorComponent) => {
});
}

async createEntity(entity) {
async createEntity(entity, local = true) {
const { collection, entitySetId, onStatusChange } = this.props;
onStatusChange && onStatusChange(UpdateStatus.IN_PROGRESS);
try {
if (entitySetId) {
if (entitySetId && local) {
await this.props.entitySetAddEntity({ entity, entitySetId, sync: true });
} else {
await this.props.createEntity({ entity, collection_id: collection.id });
Expand Down Expand Up @@ -112,13 +113,14 @@ const entityEditorWrapper = (EditorComponent) => {
}

async deleteEntity(entityId) {
const { entitySetId, onStatusChange } = this.props;
const { entitySetId, mutateOnUpdate, onStatusChange } = this.props;

onStatusChange && onStatusChange(UpdateStatus.IN_PROGRESS);

try {
if (entitySetId) {
await this.props.updateEntitySetItemNoMutate({
const updateAction = mutateOnUpdate ? this.props.updateEntitySetItemMutate : this.props.updateEntitySetItemNoMutate;
await updateAction({
entityId,
entitySetId,
judgement: 'no_judgement'
Expand Down Expand Up @@ -180,6 +182,7 @@ const mapDispatchToProps = {
createEntity,
deleteEntity,
entitySetAddEntity,
updateEntitySetItemMutate,
updateEntitySetItemNoMutate,
queryEntities,
queryEntityExpand,
Expand Down
Loading

0 comments on commit e275e67

Please sign in to comment.