From 873ddacf5abafe43fbc2b6c1033e473c3366dc62 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Tue, 11 May 2021 15:40:11 +0200 Subject: ui: Move component styling into CSS modules This change updates the frontend codebase by moving the component styling into CSS module files as opposed to the global styles which we used before. In addition, I have changed the syntax to the newer SCSS syntax, which is more similar to CSS. These changes reduces the styling conflicts that can occur between components and allows us to migrate to systems that do not support importing global styles in components. Moreover, we can benefit from treeshaking using CSS modules. --- opendc-web/opendc-web-ui/src/components/projects/FilterPanel.js | 4 ++-- .../opendc-web-ui/src/components/projects/FilterPanel.module.scss | 7 +++++++ opendc-web/opendc-web-ui/src/components/projects/FilterPanel.sass | 5 ----- 3 files changed, 9 insertions(+), 7 deletions(-) create mode 100644 opendc-web/opendc-web-ui/src/components/projects/FilterPanel.module.scss delete mode 100644 opendc-web/opendc-web-ui/src/components/projects/FilterPanel.sass (limited to 'opendc-web/opendc-web-ui/src/components/projects') diff --git a/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.js b/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.js index 2b9795d0..89b483fb 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.js +++ b/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.js @@ -1,9 +1,9 @@ import React from 'react' import FilterLink from '../../containers/projects/FilterLink' -import './FilterPanel.sass' +import { filterPanel } from './FilterPanel.module.scss' const FilterPanel = () => ( -
+
All Projects My Projects Shared with me diff --git a/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.module.scss b/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.module.scss new file mode 100644 index 00000000..79cdf81a --- /dev/null +++ b/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.module.scss @@ -0,0 +1,7 @@ +.filterPanel { + display: flex; + + button { + flex: 1 !important; + } +} diff --git a/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.sass b/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.sass deleted file mode 100644 index f71cf6c8..00000000 --- a/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.sass +++ /dev/null @@ -1,5 +0,0 @@ -.filter-panel - display: flex - - button - flex: 1 !important -- cgit v1.2.3 From 4397a959e806bf476be4c81bc804616adf58b969 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Wed, 12 May 2021 22:42:12 +0200 Subject: ui: Migrate from CRA to Next.js This change updates the web frontend to use Next.js instead of Create React App (CRA). Next.js enables the possibility of rendering pages on the server side (which reduces the time to first frame) and overall provides a better development experience. Future commits will try to futher optimize the implementation for Next.js. --- .../opendc-web-ui/src/components/projects/ProjectActionButtons.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/components/projects') diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectActionButtons.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectActionButtons.js index 1c76cc7f..48cce019 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/ProjectActionButtons.js +++ b/opendc-web/opendc-web-ui/src/components/projects/ProjectActionButtons.js @@ -1,11 +1,13 @@ import PropTypes from 'prop-types' import React from 'react' -import { Link } from 'react-router-dom' +import Link from 'next/link' const ProjectActionButtons = ({ projectId, onViewUsers, onDelete }) => ( - - + + + +
Date: Thu, 13 May 2021 13:00:00 +0200 Subject: ui: Address technical dept in frontend --- opendc-web/opendc-web-ui/src/components/projects/ProjectAuthList.js | 4 ++-- opendc-web/opendc-web-ui/src/components/projects/ProjectAuthRow.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/components/projects') diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectAuthList.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectAuthList.js index 8eb4f93b..15147e08 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/ProjectAuthList.js +++ b/opendc-web/opendc-web-ui/src/components/projects/ProjectAuthList.js @@ -1,6 +1,6 @@ import PropTypes from 'prop-types' import React from 'react' -import Shapes from '../../shapes/index' +import { Authorization } from '../../shapes' import ProjectAuthRow from './ProjectAuthRow' const ProjectAuthList = ({ authorizations }) => { @@ -33,7 +33,7 @@ const ProjectAuthList = ({ authorizations }) => { } ProjectAuthList.propTypes = { - authorizations: PropTypes.arrayOf(Shapes.Authorization).isRequired, + authorizations: PropTypes.arrayOf(Authorization).isRequired, } export default ProjectAuthList diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectAuthRow.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectAuthRow.js index 3f904061..1c1d5cd8 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/ProjectAuthRow.js +++ b/opendc-web/opendc-web-ui/src/components/projects/ProjectAuthRow.js @@ -1,7 +1,7 @@ import classNames from 'classnames' import React from 'react' import ProjectActions from '../../containers/projects/ProjectActions' -import Shapes from '../../shapes/index' +import { Authorization } from '../../shapes/index' import { AUTH_DESCRIPTION_MAP, AUTH_ICON_MAP } from '../../util/authorizations' import { parseAndFormatDateTime } from '../../util/date-time' @@ -18,7 +18,7 @@ const ProjectAuthRow = ({ projectAuth }) => ( ) ProjectAuthRow.propTypes = { - projectAuth: Shapes.Authorization.isRequired, + projectAuth: Authorization.isRequired, } export default ProjectAuthRow -- cgit v1.2.3 From 1891a6f3963d3ddeae0ea093f9a7e3608a97b4d7 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Thu, 13 May 2021 16:35:01 +0200 Subject: ui: Simplify projects page This change simplifies the logic and components of the projects page and reduces its dependency on Redux for simple operations. --- .../src/components/projects/FilterButton.js | 24 ------------- .../src/components/projects/FilterPanel.js | 29 ++++++++++++---- .../projects/NewProjectButtonComponent.js | 17 ---------- .../components/projects/ProjectActionButtons.js | 19 +++++++---- .../src/components/projects/ProjectAuthList.js | 39 ---------------------- .../src/components/projects/ProjectAuthRow.js | 24 ------------- .../src/components/projects/ProjectList.js | 39 ++++++++++++++++++++++ .../src/components/projects/ProjectRow.js | 24 +++++++++++++ 8 files changed, 97 insertions(+), 118 deletions(-) delete mode 100644 opendc-web/opendc-web-ui/src/components/projects/FilterButton.js delete mode 100644 opendc-web/opendc-web-ui/src/components/projects/NewProjectButtonComponent.js delete mode 100644 opendc-web/opendc-web-ui/src/components/projects/ProjectAuthList.js delete mode 100644 opendc-web/opendc-web-ui/src/components/projects/ProjectAuthRow.js create mode 100644 opendc-web/opendc-web-ui/src/components/projects/ProjectList.js create mode 100644 opendc-web/opendc-web-ui/src/components/projects/ProjectRow.js (limited to 'opendc-web/opendc-web-ui/src/components/projects') diff --git a/opendc-web/opendc-web-ui/src/components/projects/FilterButton.js b/opendc-web/opendc-web-ui/src/components/projects/FilterButton.js deleted file mode 100644 index 664f9b46..00000000 --- a/opendc-web/opendc-web-ui/src/components/projects/FilterButton.js +++ /dev/null @@ -1,24 +0,0 @@ -import classNames from 'classnames' -import PropTypes from 'prop-types' -import React from 'react' - -const FilterButton = ({ active, children, onClick }) => ( - -) - -FilterButton.propTypes = { - active: PropTypes.bool.isRequired, - children: PropTypes.node.isRequired, - onClick: PropTypes.func.isRequired, -} - -export default FilterButton diff --git a/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.js b/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.js index 89b483fb..5129c013 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.js +++ b/opendc-web/opendc-web-ui/src/components/projects/FilterPanel.js @@ -1,13 +1,28 @@ import React from 'react' -import FilterLink from '../../containers/projects/FilterLink' +import PropTypes from 'prop-types' +import { Button, ButtonGroup } from 'reactstrap' import { filterPanel } from './FilterPanel.module.scss' -const FilterPanel = () => ( -
- All Projects - My Projects - Shared with me -
+export const FILTERS = { SHOW_ALL: 'All Projects', SHOW_OWN: 'My Projects', SHOW_SHARED: 'Shared with me' } + +const FilterPanel = ({ onSelect, activeFilter = 'SHOW_ALL' }) => ( + + {Object.keys(FILTERS).map((filter) => ( + + ))} + ) +FilterPanel.propTypes = { + onSelect: PropTypes.func.isRequired, + activeFilter: PropTypes.string, +} + export default FilterPanel diff --git a/opendc-web/opendc-web-ui/src/components/projects/NewProjectButtonComponent.js b/opendc-web/opendc-web-ui/src/components/projects/NewProjectButtonComponent.js deleted file mode 100644 index 312671c6..00000000 --- a/opendc-web/opendc-web-ui/src/components/projects/NewProjectButtonComponent.js +++ /dev/null @@ -1,17 +0,0 @@ -import PropTypes from 'prop-types' -import React from 'react' - -const NewProjectButtonComponent = ({ onClick }) => ( -
-
- - New Project -
-
-) - -NewProjectButtonComponent.propTypes = { - onClick: PropTypes.func.isRequired, -} - -export default NewProjectButtonComponent diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectActionButtons.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectActionButtons.js index 48cce019..96970fd9 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/ProjectActionButtons.js +++ b/opendc-web/opendc-web-ui/src/components/projects/ProjectActionButtons.js @@ -1,24 +1,29 @@ import PropTypes from 'prop-types' import React from 'react' import Link from 'next/link' +import { Button } from 'reactstrap' const ProjectActionButtons = ({ projectId, onViewUsers, onDelete }) => ( - + -
onViewUsers(projectId)} > -
-
onDelete(projectId)}> + +
+ ) diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectAuthList.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectAuthList.js deleted file mode 100644 index 15147e08..00000000 --- a/opendc-web/opendc-web-ui/src/components/projects/ProjectAuthList.js +++ /dev/null @@ -1,39 +0,0 @@ -import PropTypes from 'prop-types' -import React from 'react' -import { Authorization } from '../../shapes' -import ProjectAuthRow from './ProjectAuthRow' - -const ProjectAuthList = ({ authorizations }) => { - return ( -
- {authorizations.length === 0 ? ( -
- - No projects here yet... Add some with the 'New Project' button! -
- ) : ( - - - - - - - - - - {authorizations.map((authorization) => ( - - ))} - -
Project nameLast editedAccess rights -
- )} -
- ) -} - -ProjectAuthList.propTypes = { - authorizations: PropTypes.arrayOf(Authorization).isRequired, -} - -export default ProjectAuthList diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectAuthRow.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectAuthRow.js deleted file mode 100644 index 1c1d5cd8..00000000 --- a/opendc-web/opendc-web-ui/src/components/projects/ProjectAuthRow.js +++ /dev/null @@ -1,24 +0,0 @@ -import classNames from 'classnames' -import React from 'react' -import ProjectActions from '../../containers/projects/ProjectActions' -import { Authorization } from '../../shapes/index' -import { AUTH_DESCRIPTION_MAP, AUTH_ICON_MAP } from '../../util/authorizations' -import { parseAndFormatDateTime } from '../../util/date-time' - -const ProjectAuthRow = ({ projectAuth }) => ( - - {projectAuth.project.name} - {parseAndFormatDateTime(projectAuth.project.datetimeLastEdited)} - - - {AUTH_DESCRIPTION_MAP[projectAuth.authorizationLevel]} - - - -) - -ProjectAuthRow.propTypes = { - projectAuth: Authorization.isRequired, -} - -export default ProjectAuthRow diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectList.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectList.js new file mode 100644 index 00000000..90d42326 --- /dev/null +++ b/opendc-web/opendc-web-ui/src/components/projects/ProjectList.js @@ -0,0 +1,39 @@ +import PropTypes from 'prop-types' +import React from 'react' +import { Authorization } from '../../shapes' +import ProjectRow from './ProjectRow' + +const ProjectList = ({ authorizations }) => { + return ( +
+ {authorizations.length === 0 ? ( +
+ + No projects here yet... Add some with the 'New Project' button! +
+ ) : ( + + + + + + + + + + {authorizations.map((authorization) => ( + + ))} + +
Project nameLast editedAccess rights +
+ )} +
+ ) +} + +ProjectList.propTypes = { + authorizations: PropTypes.arrayOf(Authorization).isRequired, +} + +export default ProjectList diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectRow.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectRow.js new file mode 100644 index 00000000..bc63c805 --- /dev/null +++ b/opendc-web/opendc-web-ui/src/components/projects/ProjectRow.js @@ -0,0 +1,24 @@ +import classNames from 'classnames' +import React from 'react' +import ProjectActions from '../../containers/projects/ProjectActions' +import { Authorization } from '../../shapes/index' +import { AUTH_DESCRIPTION_MAP, AUTH_ICON_MAP } from '../../util/authorizations' +import { parseAndFormatDateTime } from '../../util/date-time' + +const ProjectRow = ({ projectAuth }) => ( + + {projectAuth.project.name} + {parseAndFormatDateTime(projectAuth.project.datetimeLastEdited)} + + + {AUTH_DESCRIPTION_MAP[projectAuth.authorizationLevel]} + + + +) + +ProjectRow.propTypes = { + projectAuth: Authorization.isRequired, +} + +export default ProjectRow -- cgit v1.2.3 From d9e65dceb38cdb8dc4e464d388755f9456620566 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Sun, 16 May 2021 17:07:58 +0200 Subject: ui: Restructure OpenDC frontend This change updates the structure of the OpenDC frontend in order to improve the maintainability of the frontend. --- opendc-web/opendc-web-ui/src/components/projects/ProjectRow.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'opendc-web/opendc-web-ui/src/components/projects') diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectRow.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectRow.js index bc63c805..a0aac098 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/ProjectRow.js +++ b/opendc-web/opendc-web-ui/src/components/projects/ProjectRow.js @@ -1,7 +1,7 @@ import classNames from 'classnames' import React from 'react' import ProjectActions from '../../containers/projects/ProjectActions' -import { Authorization } from '../../shapes/index' +import { Authorization } from '../../shapes' import { AUTH_DESCRIPTION_MAP, AUTH_ICON_MAP } from '../../util/authorizations' import { parseAndFormatDateTime } from '../../util/date-time' -- cgit v1.2.3 From a6865b86cc8d710374fc0b6cfcbd2b863f1942a9 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Sun, 16 May 2021 23:18:02 +0200 Subject: ui: Migrate to Auth0 as Identity Provider This change updates the frontend codebase to move away from the Google login and instead use Auth0 as generic Identity Provider. This allows users to login with other accounts as well. Since Auth0 has a free tier, users can experiment themselves with OpenDC locally without having to pay for the login functionality. The code has been written so that we should be able to migrate away from Auth0 once it is not a suitable Identity Provider for OpenDC anymore. --- .../src/components/projects/ProjectList.js | 12 ++++----- .../src/components/projects/ProjectRow.js | 31 +++++++++++++--------- 2 files changed, 24 insertions(+), 19 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/components/projects') diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectList.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectList.js index 90d42326..cb17b835 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/ProjectList.js +++ b/opendc-web/opendc-web-ui/src/components/projects/ProjectList.js @@ -1,12 +1,12 @@ import PropTypes from 'prop-types' import React from 'react' -import { Authorization } from '../../shapes' +import { Project } from '../../shapes' import ProjectRow from './ProjectRow' -const ProjectList = ({ authorizations }) => { +const ProjectList = ({ projects }) => { return (
- {authorizations.length === 0 ? ( + {projects.length === 0 ? (
No projects here yet... Add some with the 'New Project' button! @@ -22,8 +22,8 @@ const ProjectList = ({ authorizations }) => { - {authorizations.map((authorization) => ( - + {projects.map((project) => ( + ))} @@ -33,7 +33,7 @@ const ProjectList = ({ authorizations }) => { } ProjectList.propTypes = { - authorizations: PropTypes.arrayOf(Authorization).isRequired, + projects: PropTypes.arrayOf(Project).isRequired, } export default ProjectList diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectRow.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectRow.js index a0aac098..9a95b777 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/ProjectRow.js +++ b/opendc-web/opendc-web-ui/src/components/projects/ProjectRow.js @@ -1,24 +1,29 @@ import classNames from 'classnames' import React from 'react' import ProjectActions from '../../containers/projects/ProjectActions' -import { Authorization } from '../../shapes' +import { Project } from '../../shapes' import { AUTH_DESCRIPTION_MAP, AUTH_ICON_MAP } from '../../util/authorizations' import { parseAndFormatDateTime } from '../../util/date-time' +import { useAuth } from '../../auth' -const ProjectRow = ({ projectAuth }) => ( - - {projectAuth.project.name} - {parseAndFormatDateTime(projectAuth.project.datetimeLastEdited)} - - - {AUTH_DESCRIPTION_MAP[projectAuth.authorizationLevel]} - - - -) +const ProjectRow = ({ project }) => { + const { user } = useAuth() + const { level } = project.authorizations.find((auth) => auth.userId === user.sub) + return ( + + {project.name} + {parseAndFormatDateTime(project.datetimeLastEdited)} + + + {AUTH_DESCRIPTION_MAP[level]} + + + + ) +} ProjectRow.propTypes = { - projectAuth: Authorization.isRequired, + project: Project.isRequired, } export default ProjectRow -- cgit v1.2.3 From 53623fad76274e39206b8e073e371775ea96946b Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Mon, 17 May 2021 12:16:10 +0200 Subject: ui: Migrate to FontAwesome 5 React library This change updates the frontend to use the FontAwesome 5 React library that renders SVG icons as opposed to CSS icon fonts. This migration resolves a couple of issues we had with server-side rendering of the previous FontAwesome icons. --- .../opendc-web-ui/src/components/projects/ProjectActionButtons.js | 8 +++++--- opendc-web/opendc-web-ui/src/components/projects/ProjectList.js | 4 +++- opendc-web/opendc-web-ui/src/components/projects/ProjectRow.js | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/components/projects') diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectActionButtons.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectActionButtons.js index 96970fd9..0725e42b 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/ProjectActionButtons.js +++ b/opendc-web/opendc-web-ui/src/components/projects/ProjectActionButtons.js @@ -2,12 +2,14 @@ import PropTypes from 'prop-types' import React from 'react' import Link from 'next/link' import { Button } from 'reactstrap' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faPlay, faUsers, faTrash } from '@fortawesome/free-solid-svg-icons' const ProjectActionButtons = ({ projectId, onViewUsers, onDelete }) => ( ) diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectList.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectList.js index cb17b835..dc3f85ec 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/ProjectList.js +++ b/opendc-web/opendc-web-ui/src/components/projects/ProjectList.js @@ -2,13 +2,15 @@ import PropTypes from 'prop-types' import React from 'react' import { Project } from '../../shapes' import ProjectRow from './ProjectRow' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faQuestionCircle } from '@fortawesome/free-solid-svg-icons' const ProjectList = ({ projects }) => { return (
{projects.length === 0 ? (
- + No projects here yet... Add some with the 'New Project' button!
) : ( diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectRow.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectRow.js index 9a95b777..91368de8 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/ProjectRow.js +++ b/opendc-web/opendc-web-ui/src/components/projects/ProjectRow.js @@ -1,10 +1,10 @@ -import classNames from 'classnames' import React from 'react' import ProjectActions from '../../containers/projects/ProjectActions' import { Project } from '../../shapes' import { AUTH_DESCRIPTION_MAP, AUTH_ICON_MAP } from '../../util/authorizations' import { parseAndFormatDateTime } from '../../util/date-time' import { useAuth } from '../../auth' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' const ProjectRow = ({ project }) => { const { user } = useAuth() @@ -14,7 +14,7 @@ const ProjectRow = ({ project }) => { {project.name} {parseAndFormatDateTime(project.datetimeLastEdited)} - + {AUTH_DESCRIPTION_MAP[level]} -- cgit v1.2.3