From eef3053871d68221e0123e4dd8a4bff41d0c865d Mon Sep 17 00:00:00 2001 From: schettn Date: Tue, 7 Jul 2020 10:10:13 +0200 Subject: [PATCH 01/14] Add Movable Boundary A boundary has been added which allows components to move within a specified axis. --- package.json | 1 + .../molecules/MovableBoundary/index.jsx | 159 ++++++++++++++++++ .../MovableBoundary/movableboundary.scss | 30 ++++ 3 files changed, 190 insertions(+) create mode 100644 src/components/molecules/MovableBoundary/index.jsx create mode 100644 src/components/molecules/MovableBoundary/movableboundary.scss diff --git a/package.json b/package.json index 1e4035f..bc01aa1 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "gh-pages": "^3.1.0", "js-sha256": "^0.9.0", "mdbreact": "mdbreact-4.26.1.tgz", + "mdb-react-sortable": "mdb-react-sortable-4.26.0.tgz", "node-sass": "^4.12.0", "obelisk.js": "^1.2.2", "react-avatar-editor": "^11.0.9", diff --git a/src/components/molecules/MovableBoundary/index.jsx b/src/components/molecules/MovableBoundary/index.jsx new file mode 100644 index 0000000..331dd67 --- /dev/null +++ b/src/components/molecules/MovableBoundary/index.jsx @@ -0,0 +1,159 @@ +//#region > Imports +//> React +// Contains all the functionality necessary to define React components +import React, { lazy, Suspense } from "react"; +// DOM bindings for React Router +import { Link, withRouter } from "react-router-dom"; +// React PropTypes +import PropTypes from "prop-types"; + +//> MDB Sortable +// MDB plugin for sortable item lists +import MDBSortable from "mdb-react-sortable"; + +//> SCSS +import "./movableboundary.scss"; +//#endregion + +//#region > Components +/** + * @class This enables implememntation of horizontally or vertically movable items into a page. + */ +class MovableBoundary extends React.Component { + state = { + items: this.props.items ? this.props.items : null, + indexArray: null, + }; + + componentWillReceiveProps = (nextProps) => { + this.setState({ + items: nextProps.items ? nextProps.items : null, + }); + + // If props.edit changes to false, save indexArray. + if (!nextProps.edit && this.props.edit) { + this.saveItemOrder(); + } + }; + + componentDidMount() { + // Load item order after mounting. + this.loadItemOrder(); + } + + // Load the indexArray from storage. + // If there's no indexArray, + // default indexArray [0, 1, 2, 3, ...] will be generated. + loadItemOrder() { + let indexArray = localStorage.getItem([this.props.uid]); + + if (!indexArray) { + let baseIndexArray = []; + + this.state.items.map((item, i) => { + baseIndexArray = [...baseIndexArray, i]; + }); + + indexArray = baseIndexArray; + } else { + indexArray = JSON.parse(indexArray); + } + + this.setState({ indexArray }); + } + + // Returns items ordered by indexArray. + reorderItems() { + let orderedItems = []; + + this.state.indexArray.map((index) => { + orderedItems = [...orderedItems, this.state.items[index]]; + }); + + return orderedItems; + } + + // Store indexArray. + saveItemOrder() { + localStorage.setItem( + [this.props.uid], + JSON.stringify(this.state.indexArray) + ); + } + + // Returns items to be rendered in the Sortable. + renderItems(edit) { + const items = this.reorderItems(); + + return items.map((item) => { + if (edit) { + return
{item}
; + } else { + return ( +
+ {item} +
+ ); + } + }); + } + + // Swaps indexArray position of element. + swap = (newIndex, oldIndex) => { + let indexArray = this.state.indexArray; + + if (newIndex >= indexArray.length) { + let k = newIndex - indexArray.length + 1; + + while (k--) { + indexArray.push(undefined); + } + } + + indexArray.splice(newIndex, 0, indexArray.splice(oldIndex, 1)[0]); + + this.setState({ indexArray }); + }; + + render() { + return ( +
+ {this.state.items && this.state.indexArray && ( + <> + { + // When item is let go of, change indexArray position of Item. + this.swap(obj.newIndex, obj.oldIndex); + }} + /> + + )} +
+ ); + } +} +//#endregion + +//#region > PropTypes +MovableBoundary.propTypes = { + movementAxis: PropTypes.string, + items: PropTypes.array.isRequired, + uid: PropTypes.string.isRequired, + edit: PropTypes.bool.isRequired, +}; +//#endregion + +//#region > Exports +export default MovableBoundary; +//#endregion + +/** + * SPDX-License-Identifier: (EUPL-1.2) + * Copyright © 2019-2020 Simon Prast + */ diff --git a/src/components/molecules/MovableBoundary/movableboundary.scss b/src/components/molecules/MovableBoundary/movableboundary.scss new file mode 100644 index 0000000..65d28c3 --- /dev/null +++ b/src/components/molecules/MovableBoundary/movableboundary.scss @@ -0,0 +1,30 @@ +.SortableItem { + list-style: none; + cursor: move; + outline: none; + user-select: text !important; + + // View when sorting is enabled + &:not(.unsortable) { + background: transparentize($color: white, $amount: 0.5) !important; + margin-bottom: 1rem; + border-radius: 0.3rem; + padding-top: 0.3rem; + user-select: none !important; + } +} + +.SortableList { + display: grid; + grid: initial; + padding: 0; +} + +.unsortable { + cursor: default; +} + +/** + * SPDX-License-Identifier: (EUPL-1.2) + * Copyright © 2019-2020 Simon Prast + */ From 060aa20ba60cd9c941ff3daa5fa7e3843ec0c269 Mon Sep 17 00:00:00 2001 From: schettn Date: Tue, 7 Jul 2020 10:12:14 +0200 Subject: [PATCH 02/14] Add Origin Check A check which determines if the fetched and logged user matches. --- src/components/organisms/SoftwareTabs/index.jsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/components/organisms/SoftwareTabs/index.jsx b/src/components/organisms/SoftwareTabs/index.jsx index f91b66a..b616a9d 100644 --- a/src/components/organisms/SoftwareTabs/index.jsx +++ b/src/components/organisms/SoftwareTabs/index.jsx @@ -26,6 +26,12 @@ class SoftwareTabs extends React.Component { }); }; + isSameOrigin = () => { + const { fetchedUser, loggedUser } = this.props; + + return fetchedUser.username === loggedUser.username; + }; + render() { const { fetchedUser } = this.props; const { activeTab } = this.state; @@ -94,6 +100,7 @@ class SoftwareTabs extends React.Component { {activeTab === 0 && ( )} {activeTab === 1 && ( @@ -118,6 +125,7 @@ class SoftwareTabs extends React.Component { //#region > Redux Mapping const mapStateToProps = (state) => ({ + loggedUser: state.auth.loggedUser, fetchedUser: state.user.fetchedUser, }); From b916bcd56c4fe909561989ef1bf48afb61dff298 Mon Sep 17 00:00:00 2001 From: schettn Date: Tue, 7 Jul 2020 10:23:42 +0200 Subject: [PATCH 03/14] Integrate Movable in Overview Tab A editor mode has been added which allows movement for all relevant components. --- .../organisms/tabs/OverviewTab/index.jsx | 269 +++++++++++------- 1 file changed, 159 insertions(+), 110 deletions(-) diff --git a/src/components/organisms/tabs/OverviewTab/index.jsx b/src/components/organisms/tabs/OverviewTab/index.jsx index a5f0f5d..230e43c 100644 --- a/src/components/organisms/tabs/OverviewTab/index.jsx +++ b/src/components/organisms/tabs/OverviewTab/index.jsx @@ -19,6 +19,8 @@ import { LatestActivity, ErrorBoundary, } from "../../../atoms"; +import { MovableBoundary } from "../../../molecules"; + //#endregion //#region > Constant Variables @@ -67,126 +69,173 @@ class OverviewTab extends React.Component { }; render() { - const { platformData } = this.props; + const { platformData, sameOrigin } = this.props; return ( <> {/*