Timeline component
parent
853cc9c9ad
commit
99b4929b2a
|
@ -64,7 +64,8 @@
|
||||||
"About": {
|
"About": {
|
||||||
"Navigation": {
|
"Navigation": {
|
||||||
"System": "System",
|
"System": "System",
|
||||||
"ReleaseNotes": "Release notes"
|
"ReleaseNotes": "Release notes",
|
||||||
|
"Timeline": "Timeline"
|
||||||
},
|
},
|
||||||
"ReleaseNotes": {
|
"ReleaseNotes": {
|
||||||
"Version": "Version",
|
"Version": "Version",
|
||||||
|
|
|
@ -55,7 +55,8 @@
|
||||||
"About": {
|
"About": {
|
||||||
"Navigation": {
|
"Navigation": {
|
||||||
"System": "Sistem",
|
"System": "Sistem",
|
||||||
"ReleaseNotes": "Note de lansare"
|
"ReleaseNotes": "Note de lansare",
|
||||||
|
"Timeline": "Cronologie"
|
||||||
},
|
},
|
||||||
"ReleaseNotes": {
|
"ReleaseNotes": {
|
||||||
"Version": "Versiune",
|
"Version": "Versiune",
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React, { useState, useMemo } from "react";
|
||||||
import PageTitle from "../../components/common/PageTitle";
|
import PageTitle from "../../components/common/PageTitle";
|
||||||
import BubbleChartIcon from "@material-ui/icons/BubbleChart";
|
import BubbleChartIcon from "@material-ui/icons/BubbleChart";
|
||||||
import NotesIcon from "@material-ui/icons/Notes";
|
import NotesIcon from "@material-ui/icons/Notes";
|
||||||
|
import TimelineIcon from "@material-ui/icons/Timeline";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import AboutSystemContainer from "./system/AboutSystemContainer";
|
import AboutSystemContainer from "./system/AboutSystemContainer";
|
||||||
import ReleaseNotesContainer from "./releaseNotes/ReleaseNotesContainer";
|
import ReleaseNotesContainer from "./releaseNotes/ReleaseNotesContainer";
|
||||||
|
@ -9,7 +10,8 @@ import NavigationButtons from "../../components/common/NavigationButtons";
|
||||||
|
|
||||||
const NavigationTabs = {
|
const NavigationTabs = {
|
||||||
SYSTEM: "About.Navigation.System",
|
SYSTEM: "About.Navigation.System",
|
||||||
RELEASE_NOTES: "About.Navigation.ReleaseNotes"
|
RELEASE_NOTES: "About.Navigation.ReleaseNotes",
|
||||||
|
TIMELINE: "About.Navigation.Timeline"
|
||||||
};
|
};
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
|
@ -20,6 +22,10 @@ const tabs = [
|
||||||
{
|
{
|
||||||
code: NavigationTabs.RELEASE_NOTES,
|
code: NavigationTabs.RELEASE_NOTES,
|
||||||
icon: NotesIcon
|
icon: NotesIcon
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: NavigationTabs.TIMELINE,
|
||||||
|
icon: TimelineIcon
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -42,6 +48,9 @@ const AboutContainer = () => {
|
||||||
/>
|
/>
|
||||||
{tab === NavigationTabs.SYSTEM && <AboutSystemContainer />}
|
{tab === NavigationTabs.SYSTEM && <AboutSystemContainer />}
|
||||||
{tab === NavigationTabs.RELEASE_NOTES && <ReleaseNotesContainer />}
|
{tab === NavigationTabs.RELEASE_NOTES && <ReleaseNotesContainer />}
|
||||||
|
{tab === NavigationTabs.TIMELINE && (
|
||||||
|
<ReleaseNotesContainer view="timeline" />
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
import useApi from "../../../api";
|
import useApi from "../../../api";
|
||||||
import ReleaseNotesList from "./ReleaseNotesList";
|
import ReleaseNotesList from "./ReleaseNotesList";
|
||||||
|
import TimelineComponent from "../timeline/TimelineComponent";
|
||||||
|
|
||||||
const ReleaseNotesContainer = () => {
|
const sort = releases =>
|
||||||
|
releases.sort((a, b) => new Date(b.date) - new Date(a.date));
|
||||||
|
|
||||||
|
const ReleaseNotesContainer = ({ view }) => {
|
||||||
const [state, setState] = useState({ data: [], loaded: false });
|
const [state, setState] = useState({ data: [], loaded: false });
|
||||||
|
|
||||||
const api = useApi();
|
const api = useApi();
|
||||||
|
@ -16,7 +21,20 @@ const ReleaseNotesContainer = () => {
|
||||||
});
|
});
|
||||||
}, [api, state.loaded]);
|
}, [api, state.loaded]);
|
||||||
|
|
||||||
return <>{state.loaded && <ReleaseNotesList releaseNotes={state.data} />}</>;
|
return (
|
||||||
|
<>
|
||||||
|
{state.loaded &&
|
||||||
|
(view === "timeline" ? (
|
||||||
|
<TimelineComponent releases={sort(state.data)} />
|
||||||
|
) : (
|
||||||
|
<ReleaseNotesList releases={sort(state.data)} />
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ReleaseNotesContainer.propTypes = {
|
||||||
|
view: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ReleaseNotesContainer;
|
export default ReleaseNotesContainer;
|
||||||
|
|
|
@ -9,7 +9,7 @@ import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
|
||||||
import ReleaseNoteSummary from "./ReleaseNoteSummary";
|
import ReleaseNoteSummary from "./ReleaseNoteSummary";
|
||||||
import ReleaseNote from "./ReleaseNote";
|
import ReleaseNote from "./ReleaseNote";
|
||||||
|
|
||||||
const ReleaseNotesList = ({ releaseNotes }) => {
|
const ReleaseNotesList = ({ releases }) => {
|
||||||
const [flags, setFlags] = useState({});
|
const [flags, setFlags] = useState({});
|
||||||
|
|
||||||
const handleToggle = key => (_, expanded) => {
|
const handleToggle = key => (_, expanded) => {
|
||||||
|
@ -25,22 +25,30 @@ const ReleaseNotesList = ({ releaseNotes }) => {
|
||||||
return collapsed;
|
return collapsed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"sortedReleases",
|
||||||
|
JSON.stringify(releases.map(z => ({ version: z.version, date: z.date })))
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{releaseNotes.map(note => {
|
{releases.map(release => {
|
||||||
return (
|
return (
|
||||||
<Accordion key={note.version} onChange={handleToggle(note.version)}>
|
<Accordion
|
||||||
|
key={release.version}
|
||||||
|
onChange={handleToggle(release.version)}
|
||||||
|
>
|
||||||
<AccordionSummary
|
<AccordionSummary
|
||||||
expandIcon={<ExpandMoreIcon />}
|
expandIcon={<ExpandMoreIcon />}
|
||||||
id={`panel-${note.version}-header`}
|
id={`panel-${release.version}-header`}
|
||||||
>
|
>
|
||||||
<ReleaseNoteSummary
|
<ReleaseNoteSummary
|
||||||
releaseNote={note}
|
releaseNote={release}
|
||||||
collapsed={isCollapsed(note.version)}
|
collapsed={isCollapsed(release.version)}
|
||||||
/>
|
/>
|
||||||
</AccordionSummary>
|
</AccordionSummary>
|
||||||
<AccordionDetails>
|
<AccordionDetails>
|
||||||
<ReleaseNote releaseNote={note} />
|
<ReleaseNote releaseNote={release} />
|
||||||
</AccordionDetails>
|
</AccordionDetails>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
);
|
);
|
||||||
|
@ -50,7 +58,7 @@ const ReleaseNotesList = ({ releaseNotes }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
ReleaseNotesList.propTypes = {
|
ReleaseNotesList.propTypes = {
|
||||||
releaseNotes: PropTypes.array.isRequired
|
releases: PropTypes.array.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ReleaseNotesList;
|
export default ReleaseNotesList;
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
import React from "react";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
import { makeStyles } from "@material-ui/core/styles";
|
||||||
|
import Timeline from "@material-ui/lab/Timeline";
|
||||||
|
import TimelineItem from "@material-ui/lab/TimelineItem";
|
||||||
|
import TimelineSeparator from "@material-ui/lab/TimelineSeparator";
|
||||||
|
import TimelineConnector from "@material-ui/lab/TimelineConnector";
|
||||||
|
import TimelineContent from "@material-ui/lab/TimelineContent";
|
||||||
|
import TimelineOppositeContent from "@material-ui/lab/TimelineOppositeContent";
|
||||||
|
import TimelineDot from "@material-ui/lab/TimelineDot";
|
||||||
|
import Paper from "@material-ui/core/Paper";
|
||||||
|
import Typography from "@material-ui/core/Typography";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { getRandomElement } from "../../../utils";
|
||||||
|
import {
|
||||||
|
Announcement,
|
||||||
|
AmpStories,
|
||||||
|
Apps,
|
||||||
|
BugReport,
|
||||||
|
DeviceHub,
|
||||||
|
Equalizer,
|
||||||
|
FilterTiltShift,
|
||||||
|
Grain,
|
||||||
|
Layers,
|
||||||
|
LocalOffer,
|
||||||
|
Memory,
|
||||||
|
NetworkCheck,
|
||||||
|
OfflineBolt,
|
||||||
|
Star,
|
||||||
|
Whatshot,
|
||||||
|
Widgets
|
||||||
|
} from "@material-ui/icons";
|
||||||
|
|
||||||
|
const timelineIcons = [
|
||||||
|
Announcement,
|
||||||
|
AmpStories,
|
||||||
|
Apps,
|
||||||
|
BugReport,
|
||||||
|
DeviceHub,
|
||||||
|
Equalizer,
|
||||||
|
FilterTiltShift,
|
||||||
|
Grain,
|
||||||
|
Layers,
|
||||||
|
LocalOffer,
|
||||||
|
Memory,
|
||||||
|
NetworkCheck,
|
||||||
|
OfflineBolt,
|
||||||
|
Star,
|
||||||
|
Whatshot,
|
||||||
|
Widgets
|
||||||
|
];
|
||||||
|
|
||||||
|
const timelineDotVariants = [
|
||||||
|
{ color: "primary", variant: "outlined" },
|
||||||
|
{ color: "secondary", variant: "outlined" }
|
||||||
|
];
|
||||||
|
|
||||||
|
const useStyles = makeStyles(() => ({
|
||||||
|
paper: {
|
||||||
|
padding: "6px 16px"
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
const TimelineComponent = ({ releases }) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const _releases = releases.map((release, index) => {
|
||||||
|
const isLast = index === releases.length - 1;
|
||||||
|
const icon = getRandomElement(timelineIcons);
|
||||||
|
const dot = getRandomElement(timelineDotVariants);
|
||||||
|
return { ...release, isLast, icon, dot };
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Timeline align="alternate">
|
||||||
|
{_releases.map(release => (
|
||||||
|
<TimelineItem key={release.version}>
|
||||||
|
<TimelineOppositeContent>
|
||||||
|
<Typography variant="body2" color="textSecondary">
|
||||||
|
{t("DATE_FORMAT", {
|
||||||
|
date: { value: release.date, format: "DD-MM-YYYY HH:mm" }
|
||||||
|
})}
|
||||||
|
</Typography>
|
||||||
|
</TimelineOppositeContent>
|
||||||
|
<TimelineSeparator>
|
||||||
|
<TimelineDot
|
||||||
|
color={release.dot.color}
|
||||||
|
variant={release.dot.variant}
|
||||||
|
>
|
||||||
|
<release.icon />
|
||||||
|
</TimelineDot>
|
||||||
|
{!release.isLast && <TimelineConnector />}
|
||||||
|
</TimelineSeparator>
|
||||||
|
<TimelineContent>
|
||||||
|
<Paper elevation={3} className={classes.paper}>
|
||||||
|
<Typography variant="h6" component="h1">
|
||||||
|
{release.notes[0]}
|
||||||
|
</Typography>
|
||||||
|
{release.notes.slice(1).map((note, index) => (
|
||||||
|
<Typography key={index} variant="body2">
|
||||||
|
{note}
|
||||||
|
</Typography>
|
||||||
|
))}
|
||||||
|
</Paper>
|
||||||
|
</TimelineContent>
|
||||||
|
</TimelineItem>
|
||||||
|
))}
|
||||||
|
</Timeline>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
TimelineComponent.propTypes = {
|
||||||
|
releases: PropTypes.array.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TimelineComponent;
|
|
@ -1,5 +1,5 @@
|
||||||
const primary = "#00695C";
|
const primary = "#00695C";
|
||||||
const secondary = "#FF5C93";
|
const secondary = "#F9A825";
|
||||||
const warning = "#ff9800";
|
const warning = "#ff9800";
|
||||||
const success = "#4caf50";
|
const success = "#4caf50";
|
||||||
const info = "#2196f3";
|
const info = "#2196f3";
|
||||||
|
@ -10,8 +10,8 @@ const defaultTheme = {
|
||||||
main: primary
|
main: primary
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
main: secondary,
|
main: secondary
|
||||||
contrastText: "#ffcc00"
|
// contrastText: "#ffcc00"
|
||||||
},
|
},
|
||||||
warning: {
|
warning: {
|
||||||
main: warning
|
main: warning
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
import { getRandomElement } from "./random";
|
||||||
|
|
||||||
|
export { getRandomElement };
|
|
@ -0,0 +1,7 @@
|
||||||
|
const getRandomElement = array => {
|
||||||
|
const randomIndex = Math.floor(Math.random() * array.length);
|
||||||
|
const element = array[randomIndex];
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { getRandomElement };
|
Loading…
Reference in New Issue