Skip to content

Commit

Permalink
feat(espisodes_list): 12432 future episodes on timeline should be dis…
Browse files Browse the repository at this point in the history
…played distinctly (#449)

* add forecasted flag and conditional styling

* feat: add forecasted styles

* fix conflicts

* chore: review fixes

* Update src/features/event_episodes/components/EpisodesTimeline/EpisodesTimeline.tsx

Co-authored-by: dqunbp <[email protected]>

---------

Co-authored-by: dqunbp <[email protected]>
  • Loading branch information
Akiyamka and dqunbp authored Feb 21, 2023
1 parent f38d321 commit dd2e330
Show file tree
Hide file tree
Showing 8 changed files with 1,254 additions and 543 deletions.
1,709 changes: 1,185 additions & 524 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
"@deck.gl/mesh-layers": "^8.8.24",
"@konturio/default-icons": "^2.2.2",
"@konturio/default-theme": "3.2.4",
"@konturio/ui-kit": "3.15.0",
"@konturio/ui-kit": "^3.15.0",
"@loaders.gl/core": "^3.2.13",
"@mdx-js/rollup": "^2.3.0",
"@nebula.gl/edit-modes": "1.0.4",
Expand Down
1 change: 1 addition & 0 deletions src/core/types/episode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ export interface Episode {
updatedAt: string;
geojson: GeoJSON.FeatureCollection;
location: string;
forecasted: boolean;
}
10 changes: 7 additions & 3 deletions src/features/event_episodes/atoms/episodesResource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,14 @@ export const episodesResource = createAsyncAtom(
);
if (!responseData) throw 'No data received';

// Episodes not have any ids
// Adapter:
// - add missing ids
// - set default value for forecasted flag;
return responseData.map((e) => {
if (!e.id) e.id = 'temp_' + nanoid(6);
return e;
const copy = { ...e };
if (!copy.hasOwnProperty('id')) copy.id = 'temp_' + nanoid(6);
if (!copy.hasOwnProperty('forecasted')) copy.forecasted = false;
return copy;
});
}
return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.forecasted {
position: relative;
width: 100%;
height: 100%;
border: 1px solid var(--faint-strong-down);
z-index: -1;
}

.forecasted:hover {
background-color: var(--faint-weak);
}

.forecasted:after {
position: absolute;
width: 100%;
height: 100%;
top: 0;
right: 0;
left: 0;
bottom: 0;
content: '';
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAJ0lEQVQIW2NkwA7+M2IR/w8UY0SXAAuCFCNLwAWRJVAEYRIYgiAJALsgBgYbCawOAAAAAElFTkSuQmCC)
repeat;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,18 @@ import { useAtom } from '@reatom/react';
import { useCallback, useMemo } from 'react';
import { eventEpisodesController } from '../../controller';
import { eventEpisodesModel } from '../../model';
import s from './EpisodesTimeline.module.css';
import type { TimelineProps } from '@konturio/ui-kit';
import type { Episode } from '~core/types';

interface DataEntry {
id: string | number;
start: Date;
end?: Date;
group?: string;
forecasted: boolean;
}

type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };

const timelineMargins = { axis: 2 };
Expand All @@ -20,7 +29,18 @@ export function EpisodesTimeline({ episodes }: { episodes: Episode[] }) {
[selectedEpisode],
);

const dataSet: TimelineProps['dataset'] = useMemo(() => {
const timelineEntryClassName = useCallback(
(entry: DataEntry, defaultClassName?: string) => {
if (entry.forecasted) {
return s.forecasted;
}

return defaultClassName;
},
[],
);

const dataSet = useMemo(() => {
if (episodes.length) {
return episodes.map((episode) =>
episode.startedAt !== episode.endedAt
Expand All @@ -29,12 +49,14 @@ export function EpisodesTimeline({ episodes }: { episodes: Episode[] }) {
id: episode.id,
start: new Date(episode.startedAt),
end: new Date(episode.endedAt),
forecasted: episode.forecasted,
content: '',
}
: // Point
{
id: episode.id,
start: new Date(episode.startedAt),
forecasted: episode.forecasted,
content: '',
},
);
Expand All @@ -43,19 +65,17 @@ export function EpisodesTimeline({ episodes }: { episodes: Episode[] }) {
}
}, [episodes]);

const onSelect = useCallback<WithRequired<TimelineProps, 'onSelect'>['onSelect']>(
(selection) => {
if (selection.length > 1) {
return; // its cluster
}
if (selection[0] !== undefined) {
eventEpisodesController.setCurrentEpisode(String(selection[0].id));
} else {
eventEpisodesController.resetCurrentEpisode();
}
},
[],
);
const onSelect = useCallback((selection) => {
if (selection.length > 1) {
return; // its cluster
}
const [item] = selection
if (item !== undefined) {
eventEpisodesController.setCurrentEpisode(String(item.id));
} else {
eventEpisodesController.resetCurrentEpisode();
}
}, []);

// Timeline library have imperative api that provided trough useImperativeHandle handle
// Here I pass this api to atom.
Expand All @@ -70,6 +90,7 @@ export function EpisodesTimeline({ episodes }: { episodes: Episode[] }) {
cluster={timelineState.settings.cluster}
onSelect={onSelect}
margin={timelineMargins}
getEntryClassName={timelineEntryClassName}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { panelClasses } from '~components/Panel';
import { eventEpisodesController } from '../../controller';
import { eventEpisodesModel } from '../../model';
import { EpisodesTimeline } from '../EpisodesTimeline/EpisodesTimeline';
import s from './Episodes.module.css';
import s from './EpisodesTimelinePanel.module.css';

export function EpisodesTimelinePanel() {
const [episodes] = useAtom(eventEpisodesModel.currentEventEpisodes);
Expand Down

0 comments on commit dd2e330

Please sign in to comment.