From be3b9f8a7f99d55c627c1e1e61631f50dc10b566 Mon Sep 17 00:00:00 2001 From: Pinterid Date: Sat, 27 Jun 2020 22:00:12 +0200 Subject: [PATCH 01/86] Update globalState The active object was added to globalState. --- src/App.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/App.js b/src/App.js index 9137495..5ed51bc 100644 --- a/src/App.js +++ b/src/App.js @@ -53,6 +53,10 @@ class App extends React.Component { fetchedUser: undefined, loading: true, caching: false, + active: { + softwareTab: 0, + actionCard: 0, + }, }; globalFunctions = { From 0bc78b81124d7d117e0d5730ab679c0e7c40e7a4 Mon Sep 17 00:00:00 2001 From: Pinterid Date: Sat, 27 Jun 2020 22:01:20 +0200 Subject: [PATCH 02/86] Implement active tab The active software tab is now stored in the new globalState. --- src/components/organisms/SoftwareTabs/index.jsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/components/organisms/SoftwareTabs/index.jsx b/src/components/organisms/SoftwareTabs/index.jsx index 8492a94..7610c79 100644 --- a/src/components/organisms/SoftwareTabs/index.jsx +++ b/src/components/organisms/SoftwareTabs/index.jsx @@ -14,7 +14,7 @@ import { ProjectTab, OverviewTab, TalksTab } from "../tabs"; /** @class A component which contains all tabs for software engineer profile */ class SoftwareTabs extends React.Component { state = { - activeTab: 0, + activeTab: this.props.globalState?.active?.softwareTab, tabItems: [ { title: "Overview", @@ -61,6 +61,14 @@ class SoftwareTabs extends React.Component { ], }; + setActiveTab = (activeTab) => { + this.props.globalState.active.softwareTab = activeTab; + + this.setState({ + activeTab, + }); + }; + render() { const { globalState } = this.props; const { activeTab } = this.state; @@ -73,7 +81,7 @@ class SoftwareTabs extends React.Component {
  • this.setState({ activeTab: i })} + onClick={() => this.setActiveTab(i)} > {item.title} {item.pill} From c696cd82fa10c9c0c213aedc14cae8588572fd63 Mon Sep 17 00:00:00 2001 From: Pinterid Date: Sat, 27 Jun 2020 22:02:23 +0200 Subject: [PATCH 03/86] Implement active action card The active actionCard is now stored in the new globalState. --- .../molecules/UserActionCard/index.jsx | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/components/molecules/UserActionCard/index.jsx b/src/components/molecules/UserActionCard/index.jsx index ba23daf..3997c7c 100644 --- a/src/components/molecules/UserActionCard/index.jsx +++ b/src/components/molecules/UserActionCard/index.jsx @@ -24,15 +24,24 @@ import "./useractioncard.scss"; */ class UserActionCard extends React.Component { state = { - activeItem: 0, + activeItem: this.props.globalState?.active?.actionCard, }; goTo = (item) => { + console.log(item); this.setState({ activeItem: item, }); }; + setActiveItem = (activeItem) => { + this.setState({ + activeItem, + }); + + this.props.globalState.active.actionCard = activeItem; + }; + render() { const { globalState, globalFunctions } = this.props; const { activeItem } = this.state; @@ -41,10 +50,7 @@ class UserActionCard extends React.Component {
    {activeItem === 0 && ( <> - this.setState({ activeItem: 1 })} - > + this.setActiveItem(1)}> Login to SNEK
    @@ -60,7 +66,7 @@ class UserActionCard extends React.Component {
    this.setState({ activeItem: 2 })} + onClick={() => this.setActiveItem(2)} >

    Software Engineer

    @@ -69,7 +75,7 @@ class UserActionCard extends React.Component {
    this.setState({ activeItem: 3 })} + onClick={() => this.setActiveItem(3)} >

    Media Engineer

    From 421da9520a46ce97af886a7f8e2d69bbe778e30d Mon Sep 17 00:00:00 2001 From: Pinterid Date: Sat, 27 Jun 2020 22:03:09 +0200 Subject: [PATCH 04/86] Update navbar login The navbar login button now sets the active actionCard. --- src/App.js | 7 +++++++ src/components/molecules/Navbar/index.jsx | 9 ++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/App.js b/src/App.js index 5ed51bc..d1c7ea0 100644 --- a/src/App.js +++ b/src/App.js @@ -89,6 +89,13 @@ class App extends React.Component { componentDidMount = () => { // Start a session as anonymous user this.handleLoginSession(); + if (localStorage.getItem("actionCard")) { + this.state.active.actionCard = parseInt( + localStorage.getItem("actionCard") + ); + + localStorage.removeItem("actionCard"); + } }; /** diff --git a/src/components/molecules/Navbar/index.jsx b/src/components/molecules/Navbar/index.jsx index 02713c8..22562ec 100644 --- a/src/components/molecules/Navbar/index.jsx +++ b/src/components/molecules/Navbar/index.jsx @@ -153,7 +153,14 @@ class Navbar extends React.Component { ) : ( <> {location.pathname !== "/" && ( - + { + localStorage.setItem("actionCard", 1); + }} + > Sign In )} From 67f7befdc9b13c127d56829cd9ff934e91cedb44 Mon Sep 17 00:00:00 2001 From: schettn Date: Tue, 30 Jun 2020 22:10:30 +0200 Subject: [PATCH 05/86] Refine signin button redirect and remove software tab workaround With the introduced implementation it is possible to use the "Sign In" button to redirect to the correct login action card. The workaround which allows reloading the last tab before caching remounts every component is removed now. The functionality which is missing now will be added soon. --- src/App.js | 11 ---------- src/components/molecules/Navbar/index.jsx | 20 ++++++++++--------- .../molecules/UserActionCard/index.jsx | 6 ++---- .../organisms/SoftwareTabs/index.jsx | 4 ++-- src/components/pages/HomePage/index.jsx | 2 ++ 5 files changed, 17 insertions(+), 26 deletions(-) diff --git a/src/App.js b/src/App.js index d1c7ea0..9137495 100644 --- a/src/App.js +++ b/src/App.js @@ -53,10 +53,6 @@ class App extends React.Component { fetchedUser: undefined, loading: true, caching: false, - active: { - softwareTab: 0, - actionCard: 0, - }, }; globalFunctions = { @@ -89,13 +85,6 @@ class App extends React.Component { componentDidMount = () => { // Start a session as anonymous user this.handleLoginSession(); - if (localStorage.getItem("actionCard")) { - this.state.active.actionCard = parseInt( - localStorage.getItem("actionCard") - ); - - localStorage.removeItem("actionCard"); - } }; /** diff --git a/src/components/molecules/Navbar/index.jsx b/src/components/molecules/Navbar/index.jsx index 22562ec..25c0dd5 100644 --- a/src/components/molecules/Navbar/index.jsx +++ b/src/components/molecules/Navbar/index.jsx @@ -3,7 +3,7 @@ // 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"; +import { Link, withRouter, NavLink } from "react-router-dom"; // React PropTypes import PropTypes from "prop-types"; //> MDB @@ -153,16 +153,18 @@ class Navbar extends React.Component { ) : ( <> {location.pathname !== "/" && ( - { - localStorage.setItem("actionCard", 1); + - Sign In - + + Sign In + + )} )} diff --git a/src/components/molecules/UserActionCard/index.jsx b/src/components/molecules/UserActionCard/index.jsx index 3997c7c..71b9174 100644 --- a/src/components/molecules/UserActionCard/index.jsx +++ b/src/components/molecules/UserActionCard/index.jsx @@ -24,7 +24,7 @@ import "./useractioncard.scss"; */ class UserActionCard extends React.Component { state = { - activeItem: this.props.globalState?.active?.actionCard, + activeItem: this.props.activeIndex, }; goTo = (item) => { @@ -38,12 +38,10 @@ class UserActionCard extends React.Component { this.setState({ activeItem, }); - - this.props.globalState.active.actionCard = activeItem; }; render() { - const { globalState, globalFunctions } = this.props; + const { globalFunctions } = this.props; const { activeItem } = this.state; return ( diff --git a/src/components/organisms/SoftwareTabs/index.jsx b/src/components/organisms/SoftwareTabs/index.jsx index 7610c79..6fac998 100644 --- a/src/components/organisms/SoftwareTabs/index.jsx +++ b/src/components/organisms/SoftwareTabs/index.jsx @@ -14,7 +14,7 @@ import { ProjectTab, OverviewTab, TalksTab } from "../tabs"; /** @class A component which contains all tabs for software engineer profile */ class SoftwareTabs extends React.Component { state = { - activeTab: this.props.globalState?.active?.softwareTab, + activeTab: 0, tabItems: [ { title: "Overview", @@ -62,7 +62,7 @@ class SoftwareTabs extends React.Component { }; setActiveTab = (activeTab) => { - this.props.globalState.active.softwareTab = activeTab; + // this.props.globalState.active.softwareTab = activeTab; this.setState({ activeTab, diff --git a/src/components/pages/HomePage/index.jsx b/src/components/pages/HomePage/index.jsx index f8fe11b..739efb1 100644 --- a/src/components/pages/HomePage/index.jsx +++ b/src/components/pages/HomePage/index.jsx @@ -95,6 +95,7 @@ class HomePage extends React.Component { render() { const { globalState, globalFunctions } = this.props; + const activeActionCard = this.props.location?.state?.actionCard; if (!globalState.loading && globalState.loggedUser) { return ; @@ -154,6 +155,7 @@ class HomePage extends React.Component { From 27705e42fc15f6a48cfb51c5acd7bdd0c81397fa Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 2 Jul 2020 04:11:57 +0200 Subject: [PATCH 06/86] Upgrade to redux New redux structure was roughly implemented. Refinements take place in the following commits. But .. redux is fun :) --- package.json | 4 + src/App.js | 535 +++++++++-------- src/Routes.js | 40 +- src/components/atoms/SearchBar/index.jsx | 40 +- src/components/molecules/Navbar/index.jsx | 48 +- .../molecules/UserActionCard/index.jsx | 16 +- .../molecules/forms/LoginForm/index.jsx | 20 +- .../molecules/forms/RegisterForm/index.jsx | 2 - .../molecules/modals/SettingsModal/index.jsx | 27 +- .../molecules/modals/UploadModal/index.jsx | 21 +- .../organisms/ProfileInfo/index.jsx | 138 ++--- .../organisms/SoftwareTabs/index.jsx | 33 +- .../profiles/SoftwareEngineer/index.jsx | 12 +- .../organisms/tabs/TalksTab/index.jsx | 45 +- src/components/pages/CompanyPage/index.jsx | 2 - src/components/pages/HomePage/index.jsx | 21 +- src/components/pages/ProfilePage/index.jsx | 86 ++- src/components/pages/TalkPage/index.jsx | 83 ++- src/index.js | 41 +- src/store/actions/authActions.js | 96 +++ src/store/actions/generalActions.js | 162 +++++ src/store/actions/userActions.js | 563 ++++++++++++++++++ src/store/reducers/authReducers.js | 50 ++ src/store/reducers/generalReducers.js | 73 +++ src/store/reducers/index.js | 23 + src/store/reducers/userReducers.js | 130 ++++ 26 files changed, 1787 insertions(+), 524 deletions(-) create mode 100644 src/store/actions/authActions.js create mode 100644 src/store/actions/generalActions.js create mode 100644 src/store/actions/userActions.js create mode 100644 src/store/reducers/authReducers.js create mode 100644 src/store/reducers/generalReducers.js create mode 100644 src/store/reducers/index.js create mode 100644 src/store/reducers/userReducers.js diff --git a/package.json b/package.json index 20af087..c5c8645 100644 --- a/package.json +++ b/package.json @@ -13,10 +13,14 @@ "obelisk.js": "^1.2.2", "react-chartjs-2": "^2.9.0", "react-dropzone": "^11.0.1", + "react-redux": "^7.2.0", "react-router-dom": "^5.0.1", "react-text-loop": "^2.3.0", "react-typed": "^1.2.0", "reactjs-oauth": "file:reactjs-oauth-0.1.0.tgz", + "redux": "^4.0.5", + "redux-thunk": "^2.3.0", + "serialize-error": "^7.0.1", "snek-intel": "^0.1.1", "tippy.js": "^6.2.3" }, diff --git a/src/App.js b/src/App.js index 9137495..590b488 100644 --- a/src/App.js +++ b/src/App.js @@ -1,7 +1,7 @@ //#region > Imports //> React // Contains all the functionality necessary to define React components -import React from "react"; +import React, { useEffect } from "react"; // DOM bindings for React Router import { withRouter } from "react-router-dom"; //> Additional @@ -24,6 +24,13 @@ import Routes from "./Routes"; //> Core import { ferryIntel } from "./actions"; //> Actions +import { loginAction } from "./store/actions/authActions"; +import { + getAllPageUrlsAction, + fetchGitLabServersAction, +} from "./store/actions/generalActions"; +import { readCacheAction } from "./store/actions/userActions"; + import { login, logout, @@ -41,265 +48,319 @@ import { uploadTalk, deleteTalk, } from "./actions/intel"; +import { useSelector, useDispatch } from "react-redux"; +import { Intel } from "snek-intel"; //#endregion //#region > Components /** * @class Root component which loads all other components */ -class App extends React.Component { - state = { - loggedUser: undefined, - fetchedUser: undefined, - loading: true, - caching: false, - }; +// class App extends React.Component { +// state = { +// loggedUser: undefined, +// fetchedUser: undefined, +// loading: true, +// caching: false, +// }; - globalFunctions = { - //> Authentication - login: async (username, password) => - this.handleLoginSession({ username, password: sha256(password) }), - logout: async () => this.handleLogout(), - //> General - fetchGitLabServers: async () => ferryIntel(fetchGitLabServers()), - appendSourceObjects: async (sourceList) => - ferryIntel(appendSourceObjects(sourceList)), - users: async () => ferryIntel(getAllPageUrls()), - saveSettings: async (nextSettings) => this.handleSaveSettings(nextSettings), - //> User - updateCache: async (fetchedUser) => this.handleCacheRenewal(fetchedUser), - writeCache: async (platformData) => ferryIntel(writeCache(platformData)), - registerUser: async (registrationData) => - this.handleRegistration(registrationData), - fetchCacheData: async (username) => this.handleProfileFetching(username), - //> Talk - deleteTalk: async (talk) => this.handleTalkDeletion(talk), - uploadTalk: async (file, talkInfo) => this.handleTalkUpload(file, talkInfo), - getTalk: (uid, username) => ferryIntel(getTalk(uid, username)), - //> State checking - refetchRequired: (username) => this.refetchRequired(username), - usernameMatchesFetchedUsername: (username) => - this.usernameMatchesFetchedUsername(username), - }; +// globalFunctions = { +// //> Authentication +// login: async (username, password) => +// this.handleLoginSession({ username, password: sha256(password) }), +// logout: async () => this.handleLogout(), +// //> General +// fetchGitLabServers: async () => ferryIntel(fetchGitLabServers()), +// appendSourceObjects: async (sourceList) => +// ferryIntel(appendSourceObjects(sourceList)), +// users: async () => ferryIntel(getAllPageUrls()), +// saveSettings: async (nextSettings) => this.handleSaveSettings(nextSettings), +// //> User +// updateCache: async (fetchedUser) => this.handleCacheRenewal(fetchedUser), +// writeCache: async (platformData) => ferryIntel(writeCache(platformData)), +// registerUser: async (registrationData) => +// this.handleRegistration(registrationData), +// fetchCacheData: async (username) => this.handleProfileFetching(username), +// //> Talk +// deleteTalk: async (talk) => this.handleTalkDeletion(talk), +// uploadTalk: async (file, talkInfo) => this.handleTalkUpload(file, talkInfo), +// getTalk: (uid, username) => ferryIntel(getTalk(uid, username)), +// //> State checking +// refetchRequired: (username) => this.refetchRequired(username), +// usernameMatchesFetchedUsername: (username) => +// this.usernameMatchesFetchedUsername(username), +// }; - componentDidMount = () => { - // Start a session as anonymous user - this.handleLoginSession(); - }; +// componentDidMount = () => { +// // Start a session as anonymous user +// this.handleLoginSession(); +// }; - /** - * Handle login session. - * - * @param user A user to login with - * @description Handles states for login - */ - handleLoginSession = async (user) => { - return ferryIntel(login(user)).then((loggedUser) => { - if (loggedUser) { - this.setState({ - loggedUser, - loading: false, - }); - } else { - if (this.state.loggedUser !== null) { - this.setState({ - loggedUser: null, - loading: false, - }); - } - } - }); - }; +// /** +// * Handle login session. +// * +// * @param user A user to login with +// * @description Handles states for login +// */ +// handleLoginSession = async (user) => { +// return ferryIntel(login(user)).then((loggedUser) => { +// if (loggedUser) { +// this.setState({ +// loggedUser, +// loading: false, +// }); +// } else { +// if (this.state.loggedUser !== null) { +// this.setState({ +// loggedUser: null, +// loading: false, +// }); +// } +// } +// }); +// }; - /** - * Handle logout. - * - * @description Handles states for logout - */ - handleLogout = () => { - this.setState( - { - loggedUser: undefined, - fetchedUser: undefined, - loading: false, - caching: false, - }, - () => ferryIntel(logout()).then(() => this.handleLoginSession()) - ); - }; +// /** +// * Handle logout. +// * +// * @description Handles states for logout +// */ +// handleLogout = () => { +// this.setState( +// { +// loggedUser: undefined, +// fetchedUser: undefined, +// loading: false, +// caching: false, +// }, +// () => ferryIntel(logout()).then(() => this.handleLoginSession()) +// ); +// }; - /** - * Handle registration - * - * @param registrationData Data to register a user - * @description Handles states for registration - */ - handleRegistration = (registrationData) => { - ferryIntel(register(registrationData)).then((res) => { - this.globalFunctions.login(res.username, res.password).then(() => { - this.globalFunctions.writeCache(registrationData.platform_data); - this.setState({ caching: true, loading: false }); - }); - }); - }; +// /** +// * Handle registration +// * +// * @param registrationData Data to register a user +// * @description Handles states for registration +// */ +// handleRegistration = (registrationData) => { +// ferryIntel(register(registrationData)).then((res) => { +// this.globalFunctions.login(res.username, res.password).then(() => { +// this.globalFunctions.writeCache(registrationData.platform_data); +// this.setState({ caching: true, loading: false }); +// }); +// }); +// }; - /** - * Handle cache renewal. - * - * @param fetchedUser A fetched user object - * @description Handles states for cache renewal - */ - handleCacheRenewal = async (fetchedUser) => { - if ( - !this.state.caching && - this.state.loggedUser?.username === fetchedUser?.username - ) { - // Renew cache - const fetchedUser = await ferryIntel(updateCache(fetchedUser)); +// /** +// * Handle cache renewal. +// * +// * @param fetchedUser A fetched user object +// * @description Handles states for cache renewal +// */ +// handleCacheRenewal = async (fetchedUser) => { +// if ( +// !this.state.caching && +// this.state.loggedUser?.username === fetchedUser?.username +// ) { +// // Renew cache +// const fetchedUser = await ferryIntel(updateCache(fetchedUser)); - this.setState({ - fetchedUser, - caching: true, - }); - } - }; +// this.setState({ +// fetchedUser, +// caching: true, +// }); +// } +// }; - /** - * Handle profile fetching. - * - * @param username A username to read the cache from - * @description Handles states for profile fetching - */ - handleProfileFetching = async (username) => { - const fetchedUser = await ferryIntel(readCache(username)); - // Update visible data - this.setState({ - fetchedUser: fetchedUser ? fetchedUser : false, - loading: false, - }); - }; +// /** +// * Handle profile fetching. +// * +// * @param username A username to read the cache from +// * @description Handles states for profile fetching +// */ +// handleProfileFetching = async (username) => { +// const fetchedUser = await ferryIntel(readCache(username)); +// // Update visible data +// this.setState({ +// fetchedUser: fetchedUser ? fetchedUser : false, +// loading: false, +// }); +// }; - /** - * Handle talk upload. - * - * @param file A file to be uploaded - * @param talkInfo Additional information to add to the talk - * @description Handles states for talk uploading - */ - handleTalkUpload = async (file, talkInfo) => { - ferryIntel(uploadTalk(file, talkInfo), { - currentCache: this.state.fetchedUser.platformData, - }).then((platformData) => { - this.setState({ - fetchedUser: { - ...this.state.fetchedUser, - platformData, - }, - }); - }); - }; +// /** +// * Handle talk upload. +// * +// * @param file A file to be uploaded +// * @param talkInfo Additional information to add to the talk +// * @description Handles states for talk uploading +// */ +// handleTalkUpload = async (file, talkInfo) => { +// ferryIntel(uploadTalk(file, talkInfo), { +// currentCache: this.state.fetchedUser.platformData, +// }).then((platformData) => { +// this.setState({ +// fetchedUser: { +// ...this.state.fetchedUser, +// platformData, +// }, +// }); +// }); +// }; - /** - * Handle talk deletion. - * - * @param talk A talk that should be deleted - * @description Handles states for talk deleting - */ - handleTalkDeletion = async (talk) => { - ferryIntel(deleteTalk(talk), { - currentCache: this.state.fetchedUser.platformData, - }).then((platformData) => { - this.setState({ - fetchedUser: { - ...this.state.fetchedUser, - platformData, - }, - }); - }); - }; +// /** +// * Handle talk deletion. +// * +// * @param talk A talk that should be deleted +// * @description Handles states for talk deleting +// */ +// handleTalkDeletion = async (talk) => { +// ferryIntel(deleteTalk(talk), { +// currentCache: this.state.fetchedUser.platformData, +// }).then((platformData) => { +// this.setState({ +// fetchedUser: { +// ...this.state.fetchedUser, +// platformData, +// }, +// }); +// }); +// }; - /** - * Handle save settings. - * - * @param nextSettings A settings object that should be applied - * @description Handles states for saving settings - */ - handleSaveSettings = async (nextSettings) => { - ferryIntel(saveSettings(nextSettings), { - currentCache: this.state.fetchedUser.platformData, - }).then((platformData) => { - this.setState({ - fetchedUser: { - ...this.state.fetchedUser, - platformData, - }, - }); - }); - }; +// /** +// * Handle save settings. +// * +// * @param nextSettings A settings object that should be applied +// * @description Handles states for saving settings +// */ +// handleSaveSettings = async (nextSettings) => { +// ferryIntel(saveSettings(nextSettings), { +// currentCache: this.state.fetchedUser.platformData, +// }).then((platformData) => { +// this.setState({ +// fetchedUser: { +// ...this.state.fetchedUser, +// platformData, +// }, +// }); +// }); +// }; - //#region > Refetch Checking - /** - * Check for refetch for a specific username. - * - * @param {string} username The username associated with a profile page - * @returns {boolean} True if a refetch is required otherwise False - */ - refetchRequired = (username) => { - const loading = this.state.loading; - const fetchedUser = this.state.fetchedUser; +// //#region > Refetch Checking +// /** +// * Check for refetch for a specific username. +// * +// * @param {string} username The username associated with a profile page +// * @returns {boolean} True if a refetch is required otherwise False +// */ +// refetchRequired = (username) => { +// const loading = this.state.loading; +// const fetchedUser = this.state.fetchedUser; - if (!loading) { - if (!fetchedUser && fetchedUser !== false) { - return true; - } else if ( - fetchedUser && - !this.usernameMatchesFetchedUsername(username) - ) { - return true; - } - return false; - } - }; +// if (!loading) { +// if (!fetchedUser && fetchedUser !== false) { +// return true; +// } else if ( +// fetchedUser && +// !this.usernameMatchesFetchedUsername(username) +// ) { +// return true; +// } +// return false; +// } +// }; - /** - * Check if the provided username matches with the current fetched user. - * - * @param {string} username The username associated with a profile page - * @returns {boolean} True if the usernames matches otherwise False - */ - usernameMatchesFetchedUsername = (username) => { - return username === this.state.fetchedUser?.username; - }; - //#endregion +// /** +// * Check if the provided username matches with the current fetched user. +// * +// * @param {string} username The username associated with a profile page +// * @returns {boolean} True if the usernames matches otherwise False +// */ +// usernameMatchesFetchedUsername = (username) => { +// return username === this.state.fetchedUser?.username; +// }; +// //#endregion - render() { - return ( - -
    - {!this.state.caching && - this.state.fetchedUser && - this.state.loggedUser?.username === - this.state.fetchedUser.username && ( - - )} - -
    - -
    -
    -
    -
    - ); - } -} +// render() { +// return ( +// +//
    +// {!this.state.caching && +// this.state.fetchedUser && +// this.state.loggedUser?.username === +// this.state.fetchedUser.username && ( +// +// )} +// +//
    +// +//
    +//
    +//
    +//
    +// ); +// } +// } //#endregion +// function App(params) { +// const loggedUser = useSelector((state) => state.auth.loggedUser); +// const fetchedUser = useSelector((state) => state.user.fetchedUser); + +// const dispatch = useDispatch(); + +// return ( +//
    +// {loggedUser?.username} +// {fetchedUser?.username} +// +// +// +// +//
    +// ); +// } + +function App() { + const dispatch = useDispatch(); + + useEffect(() => { + dispatch(loginAction()); + }, []); + + return ( + +
    + +
    + +
    +
    +
    +
    + ); +} + //#region > Exports //> Default Class export default withRouter(App); diff --git a/src/Routes.js b/src/Routes.js index 2d3c66d..95783f9 100644 --- a/src/Routes.js +++ b/src/Routes.js @@ -18,51 +18,19 @@ import { /** @class Route component which includes all routes to specified components */ class Routes extends React.Component { render() { - const { globalState, globalFunctions } = this.props; - return ( - ( - - )} - /> + } /> ( - - )} - /> - ( - - )} + component={(props) => } /> + } /> ( - - )} + component={(props) => } /> CSS import "./search.scss"; +import { connect } from "react-redux"; +import { getAllPageUrlsAction } from "../../../store/actions/generalActions"; //#endregion //#region > Components @@ -28,14 +30,14 @@ import "./search.scss"; class SearchBar extends React.Component { state = { filter: "", - usernames: [], + usernames: this.props.allRegisteredUsernames, }; - componentWillReceiveProps = (nextProps) => { - if (!nextProps.globalState.loading) { - this.getUsernameList(); - } - }; + componentDidMount() { + this.props.allUsernames().then(() => { + this.setState({ usernames: this.props.allRegisteredUsernames }); + }); + } handleSelection = (event, value) => { if (event === "user") { @@ -60,19 +62,7 @@ class SearchBar extends React.Component { } }; - getUsernameList = () => { - const { globalFunctions } = this.props; - - globalFunctions.users().then((usernames) => { - this.setState({ - usernames, - }); - }); - }; - render() { - const { globalState } = this.props; - //Select component does not support onChange event. Instead, you can use getValue or getTextContent methods. return ( ({ + allRegisteredUsernames: state.general.allRegisteredUsernames, +}); + +const mapDispatchToProps = (dispatch) => { + return { + allUsernames: () => dispatch(getAllPageUrlsAction()), + }; +}; + //#region > Exports //> Default Class -export default withRouter(SearchBar); +export default withRouter( + connect(mapStateToProps, mapDispatchToProps)(SearchBar) +); //#endregion /** diff --git a/src/components/molecules/Navbar/index.jsx b/src/components/molecules/Navbar/index.jsx index 25c0dd5..46c732c 100644 --- a/src/components/molecules/Navbar/index.jsx +++ b/src/components/molecules/Navbar/index.jsx @@ -30,6 +30,8 @@ import { SearchBar } from "../../atoms"; import SNEKLogo from "../../../assets/navigation/logo.png"; //> CSS import "./navbar.scss"; +import { connect } from "react-redux"; +import { logoutAction } from "../../../store/actions/authActions"; //> Components const Settings = lazy(() => import("../modals/SettingsModal")); //#endregion @@ -59,8 +61,8 @@ class Navbar extends React.Component { }; render() { - const { globalState, globalFunctions, location } = this.props; - + const { location, loggedUser } = this.props; + console.log(this.props); return ( <> @@ -78,8 +80,8 @@ class Navbar extends React.Component { ) : ( <> - {!globalState.loading && globalState.loggedUser ? ( - + {loggedUser ? ( + - + - {!globalState.loading && globalState.loggedUser ? ( + {!loggedUser.anonymous ? ( <>
    {globalState.loggedUser.username} - + My profile Sign Out @@ -174,11 +171,7 @@ class Navbar extends React.Component { {this.state.showSettings && ( Loading...
    }> - + )} @@ -188,16 +181,25 @@ class Navbar extends React.Component { //#endregion //#region > PropTypes +// is it required to write down all stuff in map...toProps?? Navbar.propTypes = { - globalState: PropTypes.object, - globalFunctions: PropTypes.object, location: PropTypes.object, }; //#endregion +const mapStateToProps = (state) => ({ + loggedUser: state.auth.loggedUser, +}); + +const mapDispatchToProps = (dispatch) => { + return { + logout: () => dispatch(logoutAction()), + }; +}; + //#region > Exports //> Default Class -export default withRouter(Navbar); +export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Navbar)); //#endregion /** diff --git a/src/components/molecules/UserActionCard/index.jsx b/src/components/molecules/UserActionCard/index.jsx index 71b9174..3c35cf9 100644 --- a/src/components/molecules/UserActionCard/index.jsx +++ b/src/components/molecules/UserActionCard/index.jsx @@ -41,7 +41,6 @@ class UserActionCard extends React.Component { }; render() { - const { globalFunctions } = this.props; const { activeItem } = this.state; return ( @@ -82,12 +81,8 @@ class UserActionCard extends React.Component { )} - {activeItem === 1 && ( - - )} - {activeItem === 2 && ( - - )} + {activeItem === 1 && } + {activeItem === 2 && } {activeItem === 3 && ( <>
    @@ -116,13 +111,6 @@ class UserActionCard extends React.Component { } //#endregion -//#region > PropTypes -UserActionCard.propTypes = { - globalState: PropTypes.object, - globalFunctions: PropTypes.object, -}; -//#endregion - //#region > Exports //> Default Class export default UserActionCard; diff --git a/src/components/molecules/forms/LoginForm/index.jsx b/src/components/molecules/forms/LoginForm/index.jsx index 244d144..2d2b69f 100644 --- a/src/components/molecules/forms/LoginForm/index.jsx +++ b/src/components/molecules/forms/LoginForm/index.jsx @@ -10,6 +10,9 @@ import TextLoop from "react-text-loop"; //> MDB // "Material Design for Bootstrap" is a great UI design framework import { MDBAlert, MDBBtn, MDBIcon } from "mdbreact"; +import { loginAction } from "../../../../store/actions/authActions"; +import { sha256 } from "js-sha256"; +import { connect } from "react-redux"; //#endregion //#region > Components @@ -119,10 +122,10 @@ class LoginForm extends React.Component { }); } else { // Proceed to login - const result = await this.props.globalFunctions.login( - this.state.login_username, - this.state.login_password - ); + const result = await this.props.login({ + username: this.state.login_username, + password: sha256(this.state.login_password), // Hash password + }); //#TSID6 //console.log("LOGIN FORM PROCEED TO LOGIN", result); @@ -194,14 +197,19 @@ class LoginForm extends React.Component { //#region > PropTypes LoginForm.propTypes = { - globalFunctions: PropTypes.object, goTo: PropTypes.func, }; //#endregion +const mapStateToProps = (state) => ({}); + +const mapDispatchToProps = (dispatch) => { + return { login: (user) => dispatch(loginAction(user)) }; +}; + //#region > Exports //> Default Class -export default LoginForm; +export default connect(mapStateToProps, mapDispatchToProps)(LoginForm); //#endregion /** diff --git a/src/components/molecules/forms/RegisterForm/index.jsx b/src/components/molecules/forms/RegisterForm/index.jsx index 4078d05..1fb342b 100644 --- a/src/components/molecules/forms/RegisterForm/index.jsx +++ b/src/components/molecules/forms/RegisterForm/index.jsx @@ -825,8 +825,6 @@ class RegisterForm extends React.Component { //#region > PropTypes RegisterForm.propTypes = { - globalState: PropTypes.object, - globalFunctions: PropTypes.object, goto: PropTypes.func, }; //#endregion diff --git a/src/components/molecules/modals/SettingsModal/index.jsx b/src/components/molecules/modals/SettingsModal/index.jsx index 5c5a316..8345c55 100644 --- a/src/components/molecules/modals/SettingsModal/index.jsx +++ b/src/components/molecules/modals/SettingsModal/index.jsx @@ -28,6 +28,11 @@ import { //> CSS import "./settings.scss"; +import { connect } from "react-redux"; +import { + saveSettingsActions, + readCacheAction, +} from "../../../../store/actions/userActions"; //#endregion //#region > Constant Variables @@ -52,8 +57,9 @@ class SettingsModal extends React.Component { }; componentDidMount = () => { + const { fetchedUser } = this.props; // Check for the current values - const platformData = this.props.globalState?.fetchedUser?.platformData; + const platformData = fetchedUser?.platformData; if (platformData?.profile && platformData?.user) { const profile = platformData.profile; @@ -192,7 +198,7 @@ class SettingsModal extends React.Component { save = () => { this.props.saveSettings(this.state); - this.props.closeModal(); + this.props.this.props.closeModal(); }; render() { @@ -423,9 +429,8 @@ class SettingsModal extends React.Component { /> Default - {this.props.globalState.fetchedUser.accessories - .themes && - this.props.globalState.fetchedUser.accessories.themes.tids.map( + {this.props.fetchedUser.accessories.themes && + this.props.fetchedUser.accessories.themes.tids.map( (tid, i) => { let name = "Unnamed"; switch (tid) { @@ -472,9 +477,19 @@ class SettingsModal extends React.Component { } //#endregion +const mapStateToProps = (state) => ({ + fetchedUser: state.user.fetchedUser, +}); + +const mapDispatchToProps = (dispatch) => { + return { + saveSettings: (nextSettings) => dispatch(saveSettingsActions(nextSettings)), + }; +}; + //#region > Exports //> Default Class -export default SettingsModal; +export default connect(mapStateToProps, mapDispatchToProps)(SettingsModal); //#endregion /** diff --git a/src/components/molecules/modals/UploadModal/index.jsx b/src/components/molecules/modals/UploadModal/index.jsx index 37cf98e..ff8e5fa 100644 --- a/src/components/molecules/modals/UploadModal/index.jsx +++ b/src/components/molecules/modals/UploadModal/index.jsx @@ -13,6 +13,8 @@ import { MDBModalBody, MDBProgress, } from "mdbreact"; +import { connect } from "react-redux"; +import { uploadTalkAction } from "../../../../store/actions/userActions"; //#endregion //#region > Components @@ -24,7 +26,7 @@ class UploadModal extends React.Component { }; onDrop = async (files) => { - const { globalState, globalFunctions } = this.props; + const { loggedUser, fetchedUser } = this.props; if (files.length > 0) { this.setState({ @@ -32,11 +34,11 @@ class UploadModal extends React.Component { loading: true, }); - globalFunctions + this.props .uploadTalk(files[0], { - avatarUrl: globalState.fetchedUser.platformData.profile.avatarUrl, + avatarUrl: fetchedUser.platformData.profile.avatarUrl, owner: { - username: globalState.loggedUser.username, + username: loggedUser.username, }, }) .then(() => { @@ -145,9 +147,18 @@ class UploadModal extends React.Component { } //#endregion +const mapStateToProps = (state) => ({ + loggedUser: state.user.fetchedUser, + fetchedUser: state.user.fetchedUser, +}); + +const mapDispatchToProps = (dispatch) => { + return { uploadTalk: (file) => dispatch(uploadTalkAction(file)) }; +}; + //#region > Exports //> Default Class -export default UploadModal; +export default connect(mapStateToProps, mapDispatchToProps)(UploadModal); //#endregion /** diff --git a/src/components/organisms/ProfileInfo/index.jsx b/src/components/organisms/ProfileInfo/index.jsx index d64a8eb..c291ec2 100644 --- a/src/components/organisms/ProfileInfo/index.jsx +++ b/src/components/organisms/ProfileInfo/index.jsx @@ -15,6 +15,7 @@ import { MDBIcon, MDBTooltip, } from "mdbreact"; +import { connect } from "react-redux"; //#endregion //#region > Components @@ -23,10 +24,11 @@ class ProfileInfo extends React.Component { state = {}; componentDidMount = () => { - const { globalState } = this.props; - - if (this.props.globalState.fetchedUser && !this.state.sources) { - this.displaySources(globalState.fetchedUser.platformData.profile.sources); + const { fetchedUser } = this.props; + console.log(this.props); + console.log("PROFILE INFO", fetchedUser); + if (fetchedUser && !this.state.sources) { + this.displaySources(fetchedUser.platformData.profile.sources); } }; @@ -50,90 +52,77 @@ class ProfileInfo extends React.Component { }; render() { - const { globalState } = this.props; + const { fetchedUser } = this.props; return (

    - {globalState.fetchedUser && - globalState.fetchedUser.platformData.user.firstName && - globalState.fetchedUser.platformData.user.lastName && ( + {fetchedUser && + fetchedUser.platformData.user.firstName && + fetchedUser.platformData.user.lastName && ( <> - {globalState.fetchedUser.platformData.user.firstName + " "} - {globalState.fetchedUser.platformData.user.lastName} + {fetchedUser.platformData.user.firstName + " "} + {fetchedUser.platformData.user.lastName} )}

    - {globalState.fetchedUser && - globalState.fetchedUser.platformData.user.settings && - globalState.fetchedUser.platformData.user.settings - .showLocalRanking && ( + {fetchedUser && + fetchedUser.platformData.user.settings && + fetchedUser.platformData.user.settings.showLocalRanking && (

    #3 in your region

    )} - {globalState.fetchedUser && - globalState.fetchedUser.platformData.profile.company && ( + {fetchedUser && fetchedUser.platformData.profile.company && ( + <> + {fetchedUser && + fetchedUser.platformData.user.settings.showCompanyPublic && ( + + {fetchedUser.platformData.profile.company} + + )} + + )} +
    + {fetchedUser && fetchedUser.accessories.badges && ( <> - {globalState.fetchedUser && - globalState.fetchedUser.platformData.user.settings - .showCompanyPublic && ( - - {globalState.fetchedUser.platformData.profile.company} - - )} + {fetchedUser.accessories.badges.bids.map((bid, i) => { + switch (bid) { + case "6403bf4d17b8472735a93b71a37e0bd0": + return ( + + Alpha + + ); + } + })} )} -
    - {globalState.fetchedUser && - globalState.fetchedUser.accessories.badges && ( - <> - {globalState.fetchedUser.accessories.badges.bids.map( - (bid, i) => { - switch (bid) { - case "6403bf4d17b8472735a93b71a37e0bd0": - return ( - - Alpha - - ); - } - } - )} - - )}
    - {globalState.fetchedUser && - globalState.fetchedUser.platformData.profile.statusMessage && ( -
    - {globalState.fetchedUser.platformData.profile - .statusEmojiHTML && ( -
    - )} - - {globalState.fetchedUser.platformData.profile.statusMessage} - -
    - )} + {fetchedUser && fetchedUser.platformData.profile.statusMessage && ( +
    + {fetchedUser.platformData.profile.statusEmojiHTML && ( +
    + )} + + {fetchedUser.platformData.profile.statusMessage} + +
    + )}
    @@ -181,19 +170,17 @@ class ProfileInfo extends React.Component {

    Organisations

    - {globalState.fetchedUser && ( + {fetchedUser && (
    = 5 + fetchedUser.platformData.profile.organizations.length >= 5 ? "orgs text-center" : "orgs" } > - {globalState.fetchedUser.platformData.profile.organizations - .length > 0 ? ( + {fetchedUser.platformData.profile.organizations.length > 0 ? ( <> - {globalState.fetchedUser.platformData.profile.organizations.map( + {fetchedUser.platformData.profile.organizations.map( (org, i) => { return ( @@ -297,8 +284,7 @@ class ProfileInfo extends React.Component { ) : ( - {globalState.fetchedUser.username} hasn't joined an - organisation yet. + {fetchedUser.username} hasn't joined an organisation yet. )}
    @@ -315,9 +301,17 @@ class ProfileInfo extends React.Component { } //#endregion +const mapStateToProps = (state) => ({ + fetchedUser: state.user.fetchedUser, +}); + +const mapDispatchToProps = (dispatch) => { + return {}; +}; + //#region > Exports //> Default Class -export default ProfileInfo; +export default connect(mapStateToProps, mapDispatchToProps)(ProfileInfo); //#endregion /** diff --git a/src/components/organisms/SoftwareTabs/index.jsx b/src/components/organisms/SoftwareTabs/index.jsx index 6fac998..7e0725b 100644 --- a/src/components/organisms/SoftwareTabs/index.jsx +++ b/src/components/organisms/SoftwareTabs/index.jsx @@ -8,6 +8,7 @@ import { MDBBadge } from "mdbreact"; //> Components import { ProjectTab, OverviewTab, TalksTab } from "../tabs"; +import { connect } from "react-redux"; //#endregion //#region > Components @@ -25,10 +26,8 @@ class SoftwareTabs extends React.Component { { title: "Projects", visible: true, - pill: this.props.globalState?.fetchedUser?.platformData?.profile - ?.repositories - ? this.props.globalState?.fetchedUser?.platformData?.profile - ?.repositories?.length + pill: this.props.fetchedUser?.platformData?.profile?.repositories + ? this.props.fetchedUser?.platformData?.profile?.repositories?.length : "0", notification: false, }, @@ -53,8 +52,8 @@ class SoftwareTabs extends React.Component { title: "Talks", visible: true, notification: false, - pill: this.props.globalState.fetchedUser.platformData.talks - ? this.props.globalState.fetchedUser.platformData.talks.length + pill: this.props.fetchedUser?.platformData.talks + ? this.props.fetchedUser?.platformData.talks.length : "0", notification: false, }, @@ -62,16 +61,15 @@ class SoftwareTabs extends React.Component { }; setActiveTab = (activeTab) => { - // this.props.globalState.active.softwareTab = activeTab; - this.setState({ activeTab, }); }; render() { - const { globalState } = this.props; + const { fetchedUser } = this.props; const { activeTab } = this.state; + console.log("SOFTWARE", this.props); return (
    @@ -93,16 +91,13 @@ class SoftwareTabs extends React.Component {
    {activeTab === 0 && ( )} {activeTab === 1 && ( )} @@ -119,9 +114,17 @@ class SoftwareTabs extends React.Component { } //#endregion +const mapStateToProps = (state) => ({ + fetchedUser: state.user.fetchedUser, +}); + +const mapDispatchToProps = (dispatch) => { + return {}; +}; + //#region > Exports //> Default Class -export default SoftwareTabs; +export default connect(mapStateToProps, mapDispatchToProps)(SoftwareTabs); //#endregion /** diff --git a/src/components/organisms/profiles/SoftwareEngineer/index.jsx b/src/components/organisms/profiles/SoftwareEngineer/index.jsx index 3c3c391..3774062 100644 --- a/src/components/organisms/profiles/SoftwareEngineer/index.jsx +++ b/src/components/organisms/profiles/SoftwareEngineer/index.jsx @@ -16,22 +16,14 @@ class SoftwareEngineer extends React.Component { state = {}; render() { - const { globalState, globalFunctions } = this.props; - return ( - + - + diff --git a/src/components/organisms/tabs/TalksTab/index.jsx b/src/components/organisms/tabs/TalksTab/index.jsx index a0b9aa3..0c84688 100644 --- a/src/components/organisms/tabs/TalksTab/index.jsx +++ b/src/components/organisms/tabs/TalksTab/index.jsx @@ -3,7 +3,7 @@ // Contains all the functionality necessary to define React components import React from "react"; //> React Router bindings to DOM -import { withRouter } from "react-router-dom"; +import { withRouter, Link } from "react-router-dom"; //> MDB // "Material Design for Bootstrap" is a great UI design framework import { @@ -21,6 +21,9 @@ import { import "./talkstab.scss"; //> Modules import { UploadModal } from "../../../molecules/modals"; +import { connect } from "react-redux"; +import { TalksTab } from ".."; +import { deleteTalkAction } from "../../../../store/actions/userActions"; //#endregion //#region > Components @@ -51,9 +54,8 @@ class Talks extends React.Component { }; render() { - const { globalState, globalFunctions } = this.props; - const talkList = globalState?.fetchedUser?.platformData?.talks; - const { deleteTalk } = globalFunctions; + const { loggedUser, fetchedUser } = this.props; + const talkList = fetchedUser?.platformData?.talks; if (talkList) { talkList.map((talk) => { @@ -81,7 +83,7 @@ class Talks extends React.Component {

    Talks

    - {globalState.loggedUser && ( + {loggedUser && ( - {globalState.loggedUser && ( - deleteTalk(talk)}> + {loggedUser && ( + this.props.deleteTalk(talk)}> - @@ -143,7 +146,7 @@ class Talks extends React.Component {
    - +
    {talk.social && ( @@ -174,17 +177,17 @@ class Talks extends React.Component { )}
    {talk.repository.name} - Owned by {talk.repository.owner.username} + Owned by {talk.repository?.owner.username}
    @@ -203,10 +206,18 @@ class Talks extends React.Component { } //#endregion +const mapStateToProps = (state) => ({ + loggedUser: state.auth.loggedUser, + fetchedUser: state.user.fetchedUser, +}); + +const mapDispatchToProps = (dispatch) => { + return { deleteTalk: (talk) => dispatch(deleteTalkAction(talk)) }; +}; + //#region > Exports //> Default Class -export default withRouter(Talks); -//#endregion +export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Talks)); /** * SPDX-License-Identifier: (EUPL-1.2) diff --git a/src/components/pages/CompanyPage/index.jsx b/src/components/pages/CompanyPage/index.jsx index 463066e..47cebd4 100644 --- a/src/components/pages/CompanyPage/index.jsx +++ b/src/components/pages/CompanyPage/index.jsx @@ -160,8 +160,6 @@ class CompanyPage extends React.Component { }; render() { - const { globalState } = this.props; - return (
    diff --git a/src/components/pages/HomePage/index.jsx b/src/components/pages/HomePage/index.jsx index 739efb1..6fd904e 100644 --- a/src/components/pages/HomePage/index.jsx +++ b/src/components/pages/HomePage/index.jsx @@ -27,6 +27,7 @@ import "./homepage.scss"; import imageRanking from "../../../assets/body/ranking.png"; import imageProfiles from "../../../assets/body/profiles.png"; import imageTrophy from "../../../assets/body/trophy.png"; +import { connect } from "react-redux"; //#endregion //#region > Components @@ -94,13 +95,11 @@ class HomePage extends React.Component { }; render() { - const { globalState, globalFunctions } = this.props; + const { loggedUser } = this.props; const activeActionCard = this.props.location?.state?.actionCard; - if (!globalState.loading && globalState.loggedUser) { - return ; - } else if (globalState.loading) { - return

    Loading

    ; + if (!loggedUser.anonymous) { + return ; } else { return (
    @@ -153,8 +152,6 @@ class HomePage extends React.Component { @@ -228,9 +225,17 @@ class HomePage extends React.Component { } //#endregion +const mapStateToProps = (state) => ({ + loggedUser: state.auth.loggedUser, +}); + +const mapDispatchToProps = (dispatch) => { + return {}; +}; + //#region > Exports //> Default Class -export default HomePage; +export default connect(mapStateToProps, mapDispatchToProps)(HomePage); //#endregion /** diff --git a/src/components/pages/ProfilePage/index.jsx b/src/components/pages/ProfilePage/index.jsx index 20edf71..5117e07 100644 --- a/src/components/pages/ProfilePage/index.jsx +++ b/src/components/pages/ProfilePage/index.jsx @@ -9,6 +9,12 @@ import { withRouter } from "react-router-dom"; import { SoftwareEngineer } from "../../organisms/profiles"; //> CSS import "./profile.scss"; +import { + readCacheAction, + updateCacheAction, + saveSettingsActions, +} from "../../../store/actions/userActions"; +import { connect } from "react-redux"; //#endregion //#region > Components @@ -24,38 +30,58 @@ class ProfilePage extends React.Component { this.props.saveSettings(state); }; + /** + * Check for refetch for a specific username. + * + * @param {string} username The username associated with a profile page + * @returns {boolean} True if a refetch is required otherwise False + */ + refetchRequired = (username) => { + const fetchedUser = this.state.fetchedUser; + + if (!fetchedUser) { + return true; + } else if (fetchedUser && !this.usernameMatchesFetchedUsername(username)) { + return true; + } + return false; + }; + + /** + * Check if the provided username matches with the current fetched user. + * + * @param {string} username The username associated with a profile page + * @returns {boolean} True if the usernames matches otherwise False + */ + usernameMatchesFetchedUsername = (username) => { + return username === this.state.fetchedUser?.username; + }; + componentDidMount = () => { - const { match, globalState, globalFunctions } = this.props; + console.log("MIUNT"); + const { match, loggedUser, fetchedUser } = this.props; const username = match?.params?.username; if (username) { - if (globalFunctions.refetchRequired(username)) { - globalFunctions.fetchCacheData(username); + if (this.refetchRequired(username)) { + this.props.readCache(username); } - if ( - globalState.loggedUser && - globalFunctions.usernameMatchesFetchedUsername(username) - ) { - globalFunctions.updateCache(globalState?.fetchedUser); + if (loggedUser && this.usernameMatchesFetchedUsername(username)) { + this.props.updateCache(fetchedUser); } } }; componentWillReceiveProps = (nextProps) => { - const { globalState, globalFunctions } = this.props; - //#TSID10 //console.log("PROFILE PAGE NEXT PROPS", nextProps); }; render() { - const { globalState, globalFunctions } = this.props; - - if ( - globalState.loading || - (!globalState.loading && !globalState.fetchedUser) - ) { + const { fetchedUser } = this.props; + console.log(fetchedUser); + if (!fetchedUser) { return (
    @@ -63,18 +89,13 @@ class ProfilePage extends React.Component {
    ); - } else if (!globalState.loading && globalState.fetchedUser === false) { - return

    Error. User can not be fetched.

    ; - } else if (!globalState.loading && globalState.fetchedUser) { + } else if (fetchedUser) { //#TSID11 - //console.dir("PROFILE PAGE RENDER SUCCESS", globalState.fetchedUser); + //console.dir("PROFILE PAGE RENDER SUCCESS", this.props.fetchedUser); return (
    - +
    ); } else { @@ -84,9 +105,24 @@ class ProfilePage extends React.Component { } //#endregion +const mapStateToProps = (state) => ({ + loggedUser: state.auth.loggedUser, + fetchedUser: state.user.fetchedUser, +}); + +const mapDispatchToProps = (dispatch) => { + return { + saveSettings: (nextSettings) => dispatch(saveSettingsActions(nextSettings)), + readCache: (username) => dispatch(readCacheAction(username)), + updateCache: (fetchedUser) => dispatch(updateCacheAction(fetchedUser)), + }; +}; + //#region > Exports //> Default Class -export default withRouter(ProfilePage); +export default withRouter( + connect(mapStateToProps, mapDispatchToProps)(ProfilePage) +); //#endregion /** diff --git a/src/components/pages/TalkPage/index.jsx b/src/components/pages/TalkPage/index.jsx index 20d886b..fa35def 100644 --- a/src/components/pages/TalkPage/index.jsx +++ b/src/components/pages/TalkPage/index.jsx @@ -23,29 +23,28 @@ import { //> CSS import "./talk.scss"; +import { getTalkAction } from "../../../store/actions/userActions"; +import { connect } from "react-redux"; //#endregion //#region > Components /** @class This component adds the Talk Page which displays a certain talk */ class TalkPage extends React.Component { state = { - talk: undefined, + loading: true, + talk: this.props.selectedTalk, }; componentDidMount = () => { - const { globalState, globalFunctions } = this.props; + const { fetchedUser, selectedTalk } = this.props; const { uid, username } = this.props.match?.params; - if ( - uid && - username && - !globalState.loading && - !globalState.fetchedUser && - globalState.fetchedUser !== false - ) { - if (this.state.talk === undefined) { - globalFunctions.getTalk(uid, username).then((talk) => { - talk.social = { + console.log("TALKS,", fetchedUser, selectedTalk); + console.log(this.state); + if (!this.state.loading) { + if (uid && username && fetchedUser) { + if (!this.state.talk) { + selectedTalk.social = { likes: 17, date: new Date().toLocaleDateString("en-US", { year: "numeric", @@ -54,14 +53,41 @@ class TalkPage extends React.Component { }), }; - talk.interval = { - timeoutID: setInterval(() => this.updateIframe(talk), 4000), + selectedTalk.interval = { + timeoutID: setInterval(() => this.updateIframe(selectedTalk), 4000), loaded: false, }; - - this.setState({ talk }); - }); + this.setState({ talk: selectedTalk }); + } } + } else { + console.log("TrY to get talks"); + this.props.getTalk(uid, username).then(() => { + console.log("INFO", uid, username, fetchedUser); + if (uid && username && fetchedUser) { + console.log(this.state.talk, "TALLK"); + if (!this.state.talk) { + selectedTalk.social = { + likes: 17, + date: new Date().toLocaleDateString("en-US", { + year: "numeric", + month: "numeric", + day: "numeric", + }), + }; + + selectedTalk.interval = { + timeoutID: setInterval( + () => this.updateIframe(selectedTalk), + 4000 + ), + loaded: false, + }; + console.log(selectedTalk, "SEL TALK"); + this.setState({ talk: selectedTalk, loading: false }); + } + } + }); } }; @@ -78,7 +104,7 @@ class TalkPage extends React.Component { render() { const talk = this.state.talk; - + console.log(talk); return (
    {talk && ( @@ -123,7 +149,7 @@ class TalkPage extends React.Component { logo @@ -132,9 +158,9 @@ class TalkPage extends React.Component {

    - Owned by {talk.repository.owner.username} + Owned by {talk.repository?.owner.username}

    - {talk.repository.owner && ( + {talk.repository?.owner && (
    @@ -143,7 +169,7 @@ class TalkPage extends React.Component {
    )}

    - {talk.repository.description} + {talk.repository?.description}

    @@ -226,7 +252,7 @@ class TalkPage extends React.Component { {/* - {talk1.repository.readme} + {talk1.repository?.readme} */} @@ -377,9 +403,18 @@ class TalkPage extends React.Component { } //#endregion +const mapStateToProps = (state) => ({ + fetchedUser: state.user.fetchedUser, + selectedTalk: state.user.selectedTalk, +}); + +const mapDispatchToProps = (dispatch) => { + return { getTalk: (uid, username) => dispatch(getTalkAction(uid, username)) }; +}; + //#region > Exports //> Default Class -export default TalkPage; +export default connect(mapStateToProps, mapDispatchToProps)(TalkPage); //#endregion /** diff --git a/src/index.js b/src/index.js index 3f8cc71..1dc9830 100644 --- a/src/index.js +++ b/src/index.js @@ -6,6 +6,14 @@ import React from "react"; import { BrowserRouter as Router } from "react-router-dom"; // This serves as an entry point to the DOM and server renderers for React import ReactDOM from "react-dom"; +//> Redux +import { createStore, applyMiddleware, compose } from "redux"; +import { Provider } from "react-redux"; +// Thunk +import thunk from "redux-thunk"; +//> Intel +import { Intel } from "snek-intel"; + //> Font Awesome // Font Awesome is an awesome icon library import "@fortawesome/fontawesome-free/css/all.min.css"; @@ -21,15 +29,42 @@ import "./index.scss"; //> Components // Root component import App from "./App"; +//> Root Reducer +import rootReducer from "./store/reducers"; //> Service Worker import registerServiceWorker from "./registerServiceWorker"; //#endregion +const INTEL = new Intel(); + +//#TODO +// Must be moved to INTEL in future? +const getIntel = () => { + return INTEL; +}; + +const STORE = createStore( + rootReducer /* preloadedState, */, + compose( + applyMiddleware( + thunk.withExtraArgument({ + getIntel, // Intel + }) + ), + process.env.NODE_ENV !== "production" && + typeof window === "object" && + window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ && + window.__REDUX_DEVTOOLS_EXTENSION__() + ) +); + // Render the root component to
    ReactDOM.render( - - - , + + + + + , document.getElementById("root") ); diff --git a/src/store/actions/authActions.js b/src/store/actions/authActions.js new file mode 100644 index 0000000..fc6f094 --- /dev/null +++ b/src/store/actions/authActions.js @@ -0,0 +1,96 @@ +//#region > Authentication +/** + * Handle login + * + * @param user A user to login with + * @description Handles states for login + */ +const loginAction = (user) => { + console.log("USER", user); + console.log("run action"); + return (dispatch, getState, { getIntel }) => { + try { + const intel = getIntel(); + console.log(intel); + + const session = intel.snekclient.session; + + console.log(session); + + session + .begin(user) + .then((whoami) => { + console.log("WHOAMI", whoami); + if (whoami?.username !== process.env.REACT_APP_ANONYMOUS_USER) { + dispatch({ + type: "LOGIN_SUCCESS", + payload: { + username: whoami.username, + avatarUrl: + "https://www.clipartmax.com/png/full/166-1669056_the-20-cooler-octocat-github-octocat.png", + }, + }); + } else { + console.log(whoami.username, process.env.REACT_APP_ANONYMOUS_USER); + dispatch({ + type: "LOGIN_ANON_SUCCESS", + payload: {}, + }); + } + }) + .catch((ex) => + dispatch({ type: "LOGIN_ERROR", payload: { error: ex } }) + ); + } catch (ex) { + console.log("ERRORRR"); + dispatch({ + type: "LOGIN_ERROR", + payload: { errorCode: 600, message: "Login failed", error: ex }, + }); + } + }; +}; + +/** + * Logout user. + * + * @description Handles the logging out of active users + */ +const logoutAction = () => { + return async (dispatch, getState, { getIntel }) => { + try { + const intel = getIntel(); + const session = intel.snekclient.session; + await session + .end() + .then(() => + dispatch({ + type: "LOGOUT_SUCCESS", + payload: {}, + }) + ) + .catch((ex) => + dispatch({ type: "LOGOUT_ERROR", payload: { error: ex } }) + ); + } catch (ex) { + dispatch({ + type: "LOGOUT_FAILED", + payload: { + errorCode: 601, + message: "Logout failed", + error: ex, + }, + }); + } + }; +}; +//#endregion + +//#region > Exports +export { loginAction, logoutAction }; +//#endregion + +/** + * SPDX-License-Identifier: (EUPL-1.2) + * Copyright © 2019-2020 Simon Prast + */ diff --git a/src/store/actions/generalActions.js b/src/store/actions/generalActions.js new file mode 100644 index 0000000..dde9c5d --- /dev/null +++ b/src/store/actions/generalActions.js @@ -0,0 +1,162 @@ +//#region > Registration +/** + * Append Source Objects + * + * @param sourceList A source object + * @description Hands source list over to intel + */ +const appendSourceObjectsAction = (sourceList) => { + return async (dispatch, getState, { getIntel }) => { + try { + const intel = getIntel(); + + intel.appendList(sourceList); + dispatch({ + type: "APPEND_SOURCE_OBJECTS_SUCCESS", + payload: {}, + }); + } catch (ex) { + dispatch({ + type: "APPEND_SOURCE_OBJECTS_ERROR", + payload: { + errorCode: 602, + message: "Appending source objects failed", + error: ex, + }, + }); + } + }; +}; + +/** + * Fetch GitLab Servers + * + * @description Retrieves a list of available GitLab servers + */ +const fetchGitLabServersAction = () => { + return async (dispatch, getState, { getIntel }) => { + try { + const intel = getIntel(); + const session = intel.snekclient.session; + + return session.tasks.general + .gitlabServer() + .then(({ data }) => { + const gitLabServers = data?.page?.supportedGitlabs; + + dispatch({ + type: "FETCH_GITLAB_SERVER_SUCCESS", + payload: { gitLabServers }, + }); + }) + .catch((ex) => + dispatch({ + type: "FETCH_GITLAB_SERVER_ERROR", + payload: { error: ex }, + }) + ); + } catch (ex) { + dispatch({ + type: "FETCH_GITLAB_SERVER_ERROR", + payload: { + errorCode: 605, + message: "Fetching GitLab server failed", + error: ex, + }, + }); + } + }; +}; +//#endregion + +//#region > Data Handling +/** + * Get intel data + * + * @description Retrieves data from current applied source list + */ +const getDataAction = () => { + return async (dispatch, getState, { getIntel }) => { + try { + const intel = getIntel(); + + intel + .get() + .then((res) => dispatch({ type: "GET_DATA_SUCCESS", payload: res })) + .catch((ex) => + dispatch({ type: "GET_DATA_ERROR", payload: { error: ex } }) + ); + } catch (ex) { + dispatch({ + type: "GET_DATA_ERROR", + payload: { + errorCode: 603, + message: "Getting intel data failed", + error: ex, + }, + }); + } + }; +}; + +/** + * Get all users + * + * @description Retrieves a list of all users + */ +const getAllPageUrlsAction = () => { + return async (dispatch, getState, { getIntel }) => { + try { + console.log("getAllPageUrlsAction"); + const intel = getIntel(); + const session = intel.snekclient.session; + + return await session.tasks.general + .allPageUrls() + .then((res) => { + let urls = []; + + res.data.pages && + res.data.pages.forEach((page) => { + if (page.urlPath.includes("registration/")) { + let url = page.urlPath.split("/")[2]; + + urls.push(url); + } + }); + + dispatch({ + type: "GET_APP_PAGE_URLS_SUCCESS", + payload: { urls }, + }); + }) + .catch((ex) => + dispatch({ type: "GET_APP_PAGE_URLS_ERROR", payload: { error: ex } }) + ); + } catch (ex) { + dispatch({ + type: "GET_APP_PAGE_URLS_ERROR", + payload: { + errorCode: 616, + message: "Getting all page urls failed", + error: ex, + }, + }); + } + }; +}; +//#endregion + +//#region > Exports +export { + appendSourceObjectsAction, + getDataAction, + getAllPageUrlsAction, + fetchGitLabServersAction, +}; +//#endregion + +/** + * SPDX-License-Identifier: (EUPL-1.2) + * Copyright © 2019-2020 Simon Prast + */ diff --git a/src/store/actions/userActions.js b/src/store/actions/userActions.js new file mode 100644 index 0000000..ab36ab8 --- /dev/null +++ b/src/store/actions/userActions.js @@ -0,0 +1,563 @@ +//#region > Imports +//> Additional +// SHA Hashing algorithm +import sha256 from "js-sha256"; +//#endregion + +//#region > Register +/** + * Register user. + * + * @param registrationData Data to register a user + * @description Handles the registration of users + */ +const registerAction = (registrationData) => { + return async (dispatch, getState, { getIntel }) => { + try { + const intel = getIntel(); + const session = intel.snekclient.session; + const clearPassword = registrationData.password; + + // Hash password + registrationData.password = sha256(registrationData.password); + + // Append Source objects + await intel.appendList(registrationData.sources); + // Generate talks based on the previous appended list + await intel.generateTalks(registrationData.sources); + + // Get fresh platform data + const intelData = { + ...(await intel.get()), + talks: await intel.getTalks(), + }; + + // Save Object to platformData as JSON + registrationData.platform_data = JSON.stringify(intelData); + // Create JSON string out of sources for backend use + registrationData.sources = JSON.stringify(registrationData.sources); + + session.tasks.user + .registration(registrationData) + .then((res) => { + if (res.result === "FAIL") { + dispatch({ + type: "SIGNUP_FAILED", + payload: { + errorCode: 606, + message: "Registration failed due to false registration result", + error: undefined, + }, + }); + } else { + dispatch({ + type: "SIGNUP_SUCCESS", + payload: { + registrationData, + username: registrationData.username, + password: clearPassword, + }, + }); + } + }) + .catch((ex) => + dispatch({ type: "SIGNUP_ERROR", payload: { error: ex } }) + ); + } catch (ex) { + dispatch({ + type: "SIGNUP_ERROR", + payload: { + errorCode: 617, + message: "Registration failed", + error: ex, + }, + }); + } + }; +}; +//#endregion + +//#region > Caching +/** + * Write cache. + * + * @param platformData A data object to store in cache + * @description Handles the calls for writing to cache + */ +const writeCacheAction = (platformData) => { + return async (dispatch, getState, { getIntel }) => { + try { + const intel = getIntel(); + const session = intel.snekclient.session; + + return session.tasks.user + .cache(platformData) + .then(() => + dispatch({ + type: "WRITE_CACHE_SUCCESS", + payload: {}, + }) + ) + .catch((ex) => + dispatch({ type: "WRITE_CACHE_ERROR", payload: { error: ex } }) + ); + } catch (ex) { + dispatch({ + type: "WRITE_CACHE_ERROR", + payload: { + errorCode: 607, + message: "Writing to cache failed", + error: ex, + }, + }); + } + }; +}; + +/** + * Read cache. + * + * @param username A username to read the cache from + * @description Handles the calls for reading the cache + */ +const readCacheAction = (username) => { + return async (dispatch, getState, { getIntel }) => { + try { + const intel = getIntel(); + const session = intel.snekclient.session; + + return session.tasks.user + .profile("/registration/" + username) + .then(async ({ data }) => { + if (!data.profile) { + dispatch({ + type: "READ_CACHE_FAILED", + payload: { + errorCode: 608, + message: "Cache not loaded", + error: undefined, + }, + }); + } else { + // Split profile to chunks + const profile = data.profile; + const sources = profile.sources + ? JSON.parse(profile.sources) + : null; + + let platformData = profile.platformData + ? JSON.parse(profile.platformData) + : {}; + + let user = platformData.user ? platformData.user : {}; + + // Check if data is valid + if (!sources) { + dispatch({ + type: "READ_CACHE_FAILED", + payload: { + errorCode: 609, + message: "Sources are empty", + error: undefined, + }, + }); + } else { + // Set settings for first time fetching + if (Object.keys(user).length === 0) { + user.firstName = profile.firstName; + user.lastName = profile.lastName; + user.email = profile.email; + } + + if (!user.settings) { + user.settings = { + show3DDiagram: true, + show2DDiagram: true, + showCompanyPublic: true, + showEmailPublic: true, + showLocalRanking: true, + activeTheme: null, + }; + } + + // Build fetchedUser object + let fetchedUser = { + username: profile.username, + platformData: { + ...platformData, + user, + }, + sources, + verified: data.profile.verified, + accessories: { + badges: data.profile.bids + ? JSON.parse(data.profile.bids) + : null, + themes: data.profile.tids + ? JSON.parse(data.profile.tids) + : null, + }, + }; + + dispatch({ + type: "READ_CACHE_SUCCESS", + payload: { fetchedUser }, + }); + } + } + }) + .catch((ex) => + dispatch({ type: "READ_CACHE_ERROR", payload: { error: ex } }) + ); + } catch (ex) { + dispatch({ + type: "READ_CACHE_ERROR", + payload: { + errorCode: 610, + message: "Reading from cache failed", + error: ex, + }, + }); + } + }; +}; + +/** + * Update cache. + * + * @param fetchedUser A fetched user object + * @description Handles the calls for updating the cache + */ +const updateCacheAction = (fetchedUser) => { + return async (dispatch, getState, { getIntel }) => { + try { + const intel = getIntel(); + const session = intel.snekclient.session; + + // Appned Source objects + await intel.appendList(fetchedUser.sources); + // Generate talks based on the previous appended list + await intel.generateTalks(fetchedUser.sources); + + // Get fresh platform data + const intelData = { + ...(await intel.get()), + talks: await intel.getTalks(), + }; + + // Fix duplicates + for (const i in intelData.talks) { + let state = true; + + for (const i2 in fetchedUser.platformData.talks) { + if ( + intelData.talks[i].url === fetchedUser.platformData.talks[i2].url + ) { + state = false; + } + } + + if (state) { + fetchedUser.platformData.talks.push(intelData.talks[i]); + } + } + + fetchedUser.platformData = { + ...intelData, + user: fetchedUser.platformData.user, + talks: fetchedUser.platformData.talks, + }; + + intel.resetReducer(); + + session.tasks.user + .cache(JSON.stringify(fetchedUser.platformData)) + .catch((ex) => + dispatch({ type: "UPDATE_CACHE_ERROR", payload: { error: ex } }) + ); + + dispatch({ + type: "UPDATE_CACHE_SUCCESS", + payload: { fetchedUser }, + }); + } catch (ex) { + dispatch({ + type: "UPDATE_CACHE_ERROR", + payload: { + errorCode: 618, + message: "Updating cache failed", + error: ex, + }, + }); + } + }; +}; +/** + * Save settings + * + * @param nextSettings The settings that should be applied + * @description Saves the user settings + */ +const saveSettingsActions = (nextSettings) => { + return async (dispatch, getState, { getIntel }) => { + try { + console.log("save settings"); + const intel = getIntel(); + const state = getState(); + + const fetchedUser = state.user.fetchedUser; + const session = intel.snekclient.session; + + console.log("save settings", fetchedUser, nextSettings); + + if (fetchedUser.platformData) { + // Check for mandatory fields + if (nextSettings.email) { + fetchedUser.platformData.user.firstName = nextSettings.first_name + ? nextSettings.first_name + : ""; + fetchedUser.platformData.user.lastName = nextSettings.last_name + ? nextSettings.last_name + : ""; + fetchedUser.platformData.user.email = nextSettings.email + ? nextSettings.email + : fetchedUser.platformData.user.email; + fetchedUser.platformData.profile.websiteUrl = nextSettings.website + ? nextSettings.website + : ""; + fetchedUser.platformData.profile.location = nextSettings.location + ? nextSettings.location + : ""; + fetchedUser.platformData.profile.company = nextSettings.company + ? nextSettings.company + : ""; + fetchedUser.platformData.user.settings = { + showTopLanguages: nextSettings.showTopLanguages, + showLocalRanking: nextSettings.showLocalRanking, + show3DDiagram: nextSettings.show3DDiagram, + show2DDiagram: nextSettings.show2DDiagram, + showEmailPublic: nextSettings.showEmailPublic, + showCompanyPublic: nextSettings.showCompanyPublic, + activeTheme: nextSettings.activeTheme, + }; + } + + session.tasks.user.cache(JSON.stringify(fetchedUser.platformData)); + + dispatch({ + type: "SAVE_SETTING_SUCCESS", + payload: { + fetchedUser, + }, + }); + } + } catch (ex) { + dispatch({ + type: "SAVE_SETTING_ERROR", + payload: { + errorCode: 604, + message: "Saving settings failed", + error: ex, + }, + }); + } + }; +}; + +//#endregion + +//#region > Talks +// /** +// * Get all talks. +// * +// * @description Handles the call for getting all talks. +// */ +// const getAllTalksAction = () => { +// return async (dispatch, getState, { getIntel }) => { +// try { +// const intel = getIntel(); + +// return intel +// .getTalks() +// .then((talks) => +// dispatch({ type: "GET_TALKS_SUCCESS", payload: { talks } }) +// ) +// .catch((ex) => +// dispatch({ type: "GET_TALKS_ERROR", payload: { error: ex } }) +// ); +// } catch (ex) { +// dispatch({ +// type: "GET_TALKS_ERROR", +// payload: { +// errorCode: 611, +// message: "Getting intel talks failed", +// error: ex, +// }, +// }); +// } +// }; +// }; + +/** + * Get a talk. + * + * @param uid A unique id to find a talk + * @param username A username associated with the talk + * @description Handles the call for getting one specific talk + */ +const getTalkAction = (uid, username) => { + return async (dispatch, getState, { getIntel }) => { + try { + const intel = getIntel(); + const session = intel.snekclient.session; + + return session.tasks.user + .profile("/registration/" + username) + .then(async ({ data }) => { + if (data.profile) { + let talks = JSON.parse(data.profile.platformData).talks; + + talks = talks.filter((talk) => { + return talk.uid === uid; + }); + + dispatch({ + type: "GET_TALK_SUCCESS", + payload: { talk: talks[0] }, + }); + } else { + dispatch({ + type: "GET_TALK_FAILED", + payload: { + errorCode: 613, + message: "Cannot get specific talk " + uid, + error: undefined, + }, + }); + } + }) + .catch((ex) => + dispatch({ type: "GET_TALK_ERROR", payload: { error: ex } }) + ); + } catch (ex) { + dispatch({ + type: "GET_TALK_ERROR", + payload: { + errorCode: 614, + message: "Getting talks failed", + error: ex, + }, + }); + } + }; +}; + +/** + * Upload talk. + * + * @param file A file to be uploaded + * @param talkInfo Additional information to add to the talk + * @description Handles the call for uploading a talk + */ +const uploadTalkAction = (file, talkInfo) => { + return async (dispatch, getState, { getIntel }) => { + try { + const intel = getIntel(); + const state = getState(); + + const fetchedUser = state.user.fetchedUser; + const session = intel.snekclient.session; + + return intel.appendTalk(file).then(() => { + return intel.getTalks().then((talks) => { + talks[talks.length - 1].repository = talkInfo; + + fetchedUser.platformData.talks.push(talks[talks.length - 1]); + console.log("BEFORE CACHING"); + session.tasks.user + .cache(JSON.stringify(fetchedUser.platformData)) + .then(() => + dispatch({ + type: "UPLOAD_TALK_SUCCESS", + payload: { + fetchedUser, + }, + }) + ); + }); + }); + } catch (ex) { + dispatch({ + type: "UPLOAD_TALK_ERROR", + payload: { + errorCode: 612, + message: "Uploading talk failed", + error: ex, + }, + }); + } + }; +}; + +/** + * @todo currentCache over getState + * Delete talk. + * + * @param talk A talk that should be deleted + * @description Handles the call for deleting a talk. + */ +const deleteTalkAction = (talk) => { + return async (dispatch, getState, { getIntel }) => { + try { + const intel = getIntel(); + const state = getState(); + + const fetchedUser = state.user.fetchedUser.platformData; + const session = intel.snekclient.session; + + for (const index in fetchedUser.platformData.talks) { + if (talk.uid === fetchedUser.platformData.talks[index].uid) { + fetchedUser.platformData.talks.splice(index, 1); + } + } + + session.tasks.user.cache(JSON.stringify(fetchedUser.platformData)); + + dispatch({ + type: "DELETING_TALK_SUCCESS", + payload: { + fetchedUser, + }, + }); + } catch (ex) { + dispatch({ + type: "DELETING_TALK_ERROR", + payload: { + errorCode: 615, + message: "Deleting talk failed", + raw: ex, + }, + }); + } + }; +}; +//#endregion + +//#region > Exports +export { + registerAction, + writeCacheAction, + readCacheAction, + updateCacheAction, + saveSettingsActions, + // getAllTalksAction, + getTalkAction, + uploadTalkAction, + deleteTalkAction, +}; +//#endregion + +/** + * SPDX-License-Identifier: (EUPL-1.2) + * Copyright © 2019-2020 Simon Prast + */ diff --git a/src/store/reducers/authReducers.js b/src/store/reducers/authReducers.js new file mode 100644 index 0000000..cf6632b --- /dev/null +++ b/src/store/reducers/authReducers.js @@ -0,0 +1,50 @@ +import { serializeError } from "serialize-error"; + +const INIT_STATE = { + loggedUser: { anonymous: true }, + authError: null, + authErrorDetails: null, +}; + +const authReducer = (state = INIT_STATE, action) => { + switch (action.type) { + //> LOGIN + case "LOGIN_SUCCESS": + return { + ...state, + loggedUser: { ...action.payload, anonymous: false }, + authErrorDetails: null, + }; + + case "LOGIN_ANON_SUCCESS": + return { + ...state, + loggedUser: undefined, + loggedUser: { anonymous: true }, + authErrorDetails: null, + }; + + case "LOGIN_FAILED" || "LOGIN_ERROR": + return { + ...state, + authError: action.payload, + authErrorDetails: serializeError(action.payload.error), + }; + + //> LOGOUT + case "LOGOUT_SUCCESS": + return INIT_STATE; + + case "LOGOUT_FAILED" || "LOGIN_ERROR": + return { + ...state, + authError: action.payload, + authErrorDetails: serializeError(action.payload.error), + }; + + default: + return state; + } +}; + +export default authReducer; diff --git a/src/store/reducers/generalReducers.js b/src/store/reducers/generalReducers.js new file mode 100644 index 0000000..746f64d --- /dev/null +++ b/src/store/reducers/generalReducers.js @@ -0,0 +1,73 @@ +import { serializeError } from "serialize-error"; + +const INIT_STATE = { + allRegisteredUsernames: null, + allGitlabServers: [], + generatedIntelData: null, + generalError: null, + generalErrorDetails: null, +}; + +const generalReducer = (state = INIT_STATE, action) => { + switch (action.type) { + //> appendSourceObjectsAction + case "APPEND_SOURCE_OBJECTS_SUCCESS": + return { + ...state, + }; + + case "APPEND_SOURCE_OBJECTS_ERROR": + return { + ...state, + authError: action.payload, + authErrorDetails: serializeError(action.payload.error), + }; + + //> fetchGitLabServersAction + case "FETCH_GITLAB_SERVER_SUCCESS": + return { + ...state, + allGitlabServers: action.payload.gitLabServers, + }; + + case "FETCH_GITLAB_SERVER_ERROR": + return { + ...state, + authError: action.payload, + authErrorDetails: serializeError(action.payload.error), + }; + + //> getDataAction + case "GET_DATA_SUCCESS": + return { + ...state, + generatedIntelData: action.payload, + }; + + case "GET_DATA_ERROR": + return { + ...state, + authError: action.payload, + authErrorDetails: serializeError(action.payload.error), + }; + + //> getAllPageUrlsAction + case "GET_APP_PAGE_URLS_SUCCESS": + return { + ...state, + allRegisteredUsernames: action.payload.urls, + }; + + case "GET_APP_PAGE_URLS_ERROR": + return { + ...state, + authError: action.payload, + authErrorDetails: serializeError(action.payload.error), + }; + + default: + return state; + } +}; + +export default generalReducer; diff --git a/src/store/reducers/index.js b/src/store/reducers/index.js new file mode 100644 index 0000000..c7535ea --- /dev/null +++ b/src/store/reducers/index.js @@ -0,0 +1,23 @@ +//#region > Imports +//> Redux +import { combineReducers } from "redux"; + +//> Reducers +// Authentication +import authReducer from "./authReducers"; +import generalReducer from "./generalReducers"; +import userReducer from "./userReducers"; + +//#endregion + +//#region > Config +const rootReducer = combineReducers({ + auth: authReducer, // User authentication + general: generalReducer, // General data + user: userReducer, // User data +}); +//#endregion + +//#region > Exports +export default rootReducer; +//#endregion diff --git a/src/store/reducers/userReducers.js b/src/store/reducers/userReducers.js new file mode 100644 index 0000000..a829613 --- /dev/null +++ b/src/store/reducers/userReducers.js @@ -0,0 +1,130 @@ +import { serializeError } from "serialize-error"; + +const INIT_STATE = { + fetchedUser: null, + registrationHistory: null, + selectedTalk: null, + userError: null, + userErrorDetails: null, +}; + +const userReducer = (state = INIT_STATE, action) => { + switch (action.type) { + //> registerAction + case "SIGNUP_SUCCESS": + return { + ...state, + registrationHistory: action.payload, + }; + + case "SIGNUP_FAILED" || "SIGNUP_ERROR": + return { + ...state, + authError: action.payload, + authErrorDetails: serializeError(action.payload.error), + }; + + //> writeCacheAction + case "WRITE_CACHE_SUCCESS": + return { + ...state, + }; + + case "WRITE_CACHE_ERROR": + return { + ...state, + authError: action.payload, + authErrorDetails: serializeError(action.payload.error), + }; + + //> readCacheAction + case "READ_CACHE_SUCCESS": + return { + ...state, + fetchedUser: action.payload.fetchedUser, + }; + + case "READ_CACHE_FAILED" || "READ_CACHE_ERROR": + return { + ...state, + authError: action.payload, + authErrorDetails: serializeError(action.payload.error), + }; + + //> updateCacheAction + case "UPDATE_CACHE_SUCCESS": + return { + ...state, + fetchedUser: action.payload.fetchedUser, + }; + + case "UPDATE_CACHE_ERROR": + return { + ...state, + authError: action.payload, + authErrorDetails: serializeError(action.payload.error), + }; + + //> saveSettingsActions + case "SAVE_SETTING_SUCCESS": + return { + ...state, + fetchedUser: action.payload.fetchedUser, + }; + + case "SAVE_SETTING_ERROR": + return { + ...state, + authError: action.payload, + authErrorDetails: serializeError(action.payload.error), + }; + + //> getTalkAction + case "GET_TALK_SUCCESS": + return { + ...state, + selectedTalk: action.payload.talk, + }; + + case "GET_TALK_FAILED" || "GET_TALK_ERROR": + return { + ...state, + authError: action.payload, + authErrorDetails: serializeError(action.payload.error), + }; + + //> uploadTalkAction + case "UPLOAD_TALK_SUCCESS": + return { + ...state, + fetchedUser: action.payload.fetchedUser, + }; + + case "UPLOAD_TALK_ERROR": + return { + ...state, + authError: action.payload, + authErrorDetails: serializeError(action.payload.error), + }; + + //> deleteTalkAction + case "DELETING_TALK_SUCCESS": + return { + ...state, + fetchedUser: action.payload.fetchedUser, + }; + + case "DELETING_TALK_ERROR": + return { + ...state, + authError: action.payload, + authErrorDetails: serializeError(action.payload.error), + }; + + //> Default + default: + return state; + } +}; + +export default userReducer; From bd269f81b94bbdd9818081e203adbc60bcd85064 Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 2 Jul 2020 14:37:51 +0200 Subject: [PATCH 07/86] Enhance Redux Some bugs are fixed and the actions were adjusted. --- package.json | 1 + src/App.js | 21 ++--- src/components/atoms/SearchBar/index.jsx | 49 +++++++----- src/components/molecules/Navbar/index.jsx | 2 +- .../molecules/modals/SettingsModal/index.jsx | 2 +- .../organisms/SoftwareTabs/index.jsx | 36 +++++---- .../profiles/SoftwareEngineer/index.jsx | 4 + .../organisms/tabs/TalksTab/index.jsx | 6 +- src/components/pages/ProfilePage/index.jsx | 53 +++++++++++-- src/components/pages/TalkPage/index.jsx | 76 ++++++------------- src/index.js | 2 + src/store/actions/userActions.js | 2 +- src/store/reducers/index.js | 3 + src/store/reducers/userReducers.js | 14 ++-- 14 files changed, 159 insertions(+), 112 deletions(-) diff --git a/package.json b/package.json index c5c8645..68a6775 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "react-chartjs-2": "^2.9.0", "react-dropzone": "^11.0.1", "react-redux": "^7.2.0", + "react-redux-loading-bar": "^4.6.0", "react-router-dom": "^5.0.1", "react-text-loop": "^2.3.0", "react-typed": "^1.2.0", diff --git a/src/App.js b/src/App.js index 590b488..4fbe8cf 100644 --- a/src/App.js +++ b/src/App.js @@ -4,6 +4,7 @@ import React, { useEffect } from "react"; // DOM bindings for React Router import { withRouter } from "react-router-dom"; +import LoadingBar, { showLoading, resetLoading } from "react-redux-loading-bar"; //> Additional // SHA Hashing algorithm import sha256 from "js-sha256"; @@ -349,15 +350,17 @@ function App() { }, []); return ( - -
    - -
    - -
    -
    -
    -
    + <> + +
    + +
    + +
    +
    +
    +
    + ); } diff --git a/src/components/atoms/SearchBar/index.jsx b/src/components/atoms/SearchBar/index.jsx index b4f1537..bd46641 100644 --- a/src/components/atoms/SearchBar/index.jsx +++ b/src/components/atoms/SearchBar/index.jsx @@ -29,14 +29,21 @@ import { getAllPageUrlsAction } from "../../../store/actions/generalActions"; */ class SearchBar extends React.Component { state = { + loading: true, filter: "", usernames: this.props.allRegisteredUsernames, }; componentDidMount() { - this.props.allUsernames().then(() => { - this.setState({ usernames: this.props.allRegisteredUsernames }); - }); + if (this.state.loading) { + this.props.allUsernames().then(() => { + console.log("ALL USERNAMES", this.props.allRegisteredUsernames); + this.setState({ + loading: false, + usernames: this.props.allRegisteredUsernames, + }); + }); + } } handleSelection = (event, value) => { @@ -48,6 +55,7 @@ class SearchBar extends React.Component { }; search = (event) => { + console.log(event); const value = event.target.value; // 'keypress' event misbehaves on mobile so we track 'Enter' key via 'keydown' event @@ -63,6 +71,8 @@ class SearchBar extends React.Component { }; render() { + console.log("RENDER NAV"); + console.log(fuzzysort); //Select component does not support onChange event. Instead, you can use getValue or getTextContent methods. return ( - {this.state.usernames ? ( - this.state.usernames.length > 0 && this.state.filter.length > 0 ? ( - fuzzysort - .go(this.state.filter, this.state.usernames) - .map((element, i) => { - return ( - - {element.target} - - ); - }) - ) : null + {!this.state.loading && this.state.usernames ? ( + (console.log(this.state.usernames), + this.state.usernames.length > 0 && this.state.filter.length > 0 + ? (console.log("FUZZY"), + fuzzysort + .go(this.state.filter, this.state.usernames) + .map((element, i) => { + console.log("FUZZY ELEMNET", element); + return ( + + {element.target} + + ); + })) + : null) ) : ( Loading )} diff --git a/src/components/molecules/Navbar/index.jsx b/src/components/molecules/Navbar/index.jsx index 46c732c..c8371f5 100644 --- a/src/components/molecules/Navbar/index.jsx +++ b/src/components/molecules/Navbar/index.jsx @@ -80,7 +80,7 @@ class Navbar extends React.Component { ) : ( <> - {loggedUser ? ( + {!loggedUser.anonymous ? ( { this.props.saveSettings(this.state); - this.props.this.props.closeModal(); + this.props.closeModal(); }; render() { diff --git a/src/components/organisms/SoftwareTabs/index.jsx b/src/components/organisms/SoftwareTabs/index.jsx index 7e0725b..097264b 100644 --- a/src/components/organisms/SoftwareTabs/index.jsx +++ b/src/components/organisms/SoftwareTabs/index.jsx @@ -16,7 +16,25 @@ import { connect } from "react-redux"; class SoftwareTabs extends React.Component { state = { activeTab: 0, - tabItems: [ + }; + + setActiveTab = (activeTab) => { + this.setState({ + activeTab, + }); + }; + + componentDidUpdate() { + console.log("UPDATE SOFTWARE TABS", this.state.activeTab); + } + + render() { + const { fetchedUser } = this.props; + const { activeTab } = this.state; + + console.log(fetchedUser); + + const tabItems = [ { title: "Overview", visible: true, @@ -57,24 +75,12 @@ class SoftwareTabs extends React.Component { : "0", notification: false, }, - ], - }; - - setActiveTab = (activeTab) => { - this.setState({ - activeTab, - }); - }; - - render() { - const { fetchedUser } = this.props; - const { activeTab } = this.state; - console.log("SOFTWARE", this.props); + ]; return (
      - {this.state.tabItems.map((item, i) => { + {tabItems.map((item, i) => { return (
    • diff --git a/src/components/organisms/tabs/TalksTab/index.jsx b/src/components/organisms/tabs/TalksTab/index.jsx index 0c84688..ff99ec6 100644 --- a/src/components/organisms/tabs/TalksTab/index.jsx +++ b/src/components/organisms/tabs/TalksTab/index.jsx @@ -34,6 +34,10 @@ class Talks extends React.Component { loading: true, }; + componentDidUpdate() { + console.log("UPDATE TALKS TAB"); + } + handleUploadClose = () => { if (this.state.showUpload) { this.setState({ @@ -56,6 +60,7 @@ class Talks extends React.Component { render() { const { loggedUser, fetchedUser } = this.props; const talkList = fetchedUser?.platformData?.talks; + console.log("rerender"); if (talkList) { talkList.map((talk) => { @@ -76,7 +81,6 @@ class Talks extends React.Component { return talk; }); } - return ( <> diff --git a/src/components/pages/ProfilePage/index.jsx b/src/components/pages/ProfilePage/index.jsx index 5117e07..06fb09d 100644 --- a/src/components/pages/ProfilePage/index.jsx +++ b/src/components/pages/ProfilePage/index.jsx @@ -24,7 +24,9 @@ import { connect } from "react-redux"; * loads the components accordingly. */ class ProfilePage extends React.Component { - state = {}; + state = { + cachingDone: false, + }; saveSettings = (state) => { this.props.saveSettings(state); @@ -37,7 +39,7 @@ class ProfilePage extends React.Component { * @returns {boolean} True if a refetch is required otherwise False */ refetchRequired = (username) => { - const fetchedUser = this.state.fetchedUser; + const fetchedUser = this.props.fetchedUser; if (!fetchedUser) { return true; @@ -54,24 +56,61 @@ class ProfilePage extends React.Component { * @returns {boolean} True if the usernames matches otherwise False */ usernameMatchesFetchedUsername = (username) => { - return username === this.state.fetchedUser?.username; + return username === this.props.fetchedUser?.username; }; componentDidMount = () => { - console.log("MIUNT"); + this._isMounted = true; + const { match, loggedUser, fetchedUser } = this.props; const username = match?.params?.username; + console.log("BAR USERNAME", username); + console.log("REFETCH REQUIRED", this.refetchRequired(username)); + console.log("LOGGED", loggedUser); + console.log("FETCHED", fetchedUser); + console.log( + "USERNAME MATCHES FETCHED USERNAME", + this.usernameMatchesFetchedUsername(username) + ); if (username) { if (this.refetchRequired(username)) { this.props.readCache(username); } + console.log( + !loggedUser.anonymous && loggedUser.username === fetchedUser?.username + ); + } + }; - if (loggedUser && this.usernameMatchesFetchedUsername(username)) { - this.props.updateCache(fetchedUser); + componentDidUpdate() { + const { loggedUser, fetchedUser } = this.props; + + if (!this.state.cachingDone) { + if ( + !loggedUser.anonymous && + loggedUser.username === fetchedUser?.username + ) { + console.log("UPDATE CACHE"); + this.props.updateCache(fetchedUser).then(() => { + console.log("UPDATEd"); + if (this._isMounted) { + this.props.readCache(loggedUser.username); + this.setState( + { cachingDone: true }, + console.log("CACHING DONE", this.props.fetchedUser) + ); + } else { + console.log("CACHING DONE BUT NOT MOUNTED"); + } + }); } } - }; + } + + componentWillUnmount() { + this._isMounted = false; + } componentWillReceiveProps = (nextProps) => { //#TSID10 diff --git a/src/components/pages/TalkPage/index.jsx b/src/components/pages/TalkPage/index.jsx index fa35def..57642e9 100644 --- a/src/components/pages/TalkPage/index.jsx +++ b/src/components/pages/TalkPage/index.jsx @@ -32,63 +32,36 @@ import { connect } from "react-redux"; class TalkPage extends React.Component { state = { loading: true, - talk: this.props.selectedTalk, + talk: undefined, + }; + + componentDidUpdate = () => { + console.log("UPDATE"); }; componentDidMount = () => { - const { fetchedUser, selectedTalk } = this.props; const { uid, username } = this.props.match?.params; - console.log("TALKS,", fetchedUser, selectedTalk); - console.log(this.state); - if (!this.state.loading) { - if (uid && username && fetchedUser) { - if (!this.state.talk) { - selectedTalk.social = { - likes: 17, - date: new Date().toLocaleDateString("en-US", { - year: "numeric", - month: "numeric", - day: "numeric", - }), - }; + this.props.getTalk(uid, username).then(() => { + const { selectedTalk } = this.props; - selectedTalk.interval = { - timeoutID: setInterval(() => this.updateIframe(selectedTalk), 4000), - loaded: false, - }; - this.setState({ talk: selectedTalk }); - } - } - } else { - console.log("TrY to get talks"); - this.props.getTalk(uid, username).then(() => { - console.log("INFO", uid, username, fetchedUser); - if (uid && username && fetchedUser) { - console.log(this.state.talk, "TALLK"); - if (!this.state.talk) { - selectedTalk.social = { - likes: 17, - date: new Date().toLocaleDateString("en-US", { - year: "numeric", - month: "numeric", - day: "numeric", - }), - }; + if (uid && username) { + selectedTalk.social = { + likes: 17, + date: new Date().toLocaleDateString("en-US", { + year: "numeric", + month: "numeric", + day: "numeric", + }), + }; - selectedTalk.interval = { - timeoutID: setInterval( - () => this.updateIframe(selectedTalk), - 4000 - ), - loaded: false, - }; - console.log(selectedTalk, "SEL TALK"); - this.setState({ talk: selectedTalk, loading: false }); - } - } - }); - } + selectedTalk.interval = { + timeoutID: setInterval(() => this.updateIframe(selectedTalk), 4000), + loaded: false, + }; + } + this.setState({ talk: selectedTalk, loading: false }); + }); }; updateIframe = (talk) => { @@ -104,7 +77,7 @@ class TalkPage extends React.Component { render() { const talk = this.state.talk; - console.log(talk); + console.log(this.state); return (
      {talk && ( @@ -404,7 +377,6 @@ class TalkPage extends React.Component { //#endregion const mapStateToProps = (state) => ({ - fetchedUser: state.user.fetchedUser, selectedTalk: state.user.selectedTalk, }); diff --git a/src/index.js b/src/index.js index 1dc9830..47098b0 100644 --- a/src/index.js +++ b/src/index.js @@ -33,6 +33,7 @@ import App from "./App"; import rootReducer from "./store/reducers"; //> Service Worker import registerServiceWorker from "./registerServiceWorker"; +import { loadingBarMiddleware } from "react-redux-loading-bar"; //#endregion const INTEL = new Intel(); @@ -47,6 +48,7 @@ const STORE = createStore( rootReducer /* preloadedState, */, compose( applyMiddleware( + loadingBarMiddleware(), thunk.withExtraArgument({ getIntel, // Intel }) diff --git a/src/store/actions/userActions.js b/src/store/actions/userActions.js index ab36ab8..edacc7f 100644 --- a/src/store/actions/userActions.js +++ b/src/store/actions/userActions.js @@ -512,7 +512,7 @@ const deleteTalkAction = (talk) => { const intel = getIntel(); const state = getState(); - const fetchedUser = state.user.fetchedUser.platformData; + const fetchedUser = state.user.fetchedUser; const session = intel.snekclient.session; for (const index in fetchedUser.platformData.talks) { diff --git a/src/store/reducers/index.js b/src/store/reducers/index.js index c7535ea..3621a7b 100644 --- a/src/store/reducers/index.js +++ b/src/store/reducers/index.js @@ -1,6 +1,8 @@ //#region > Imports //> Redux import { combineReducers } from "redux"; +//> Reducers +import { loadingBarReducer } from "react-redux-loading-bar"; //> Reducers // Authentication @@ -12,6 +14,7 @@ import userReducer from "./userReducers"; //#region > Config const rootReducer = combineReducers({ + loadingBar: loadingBarReducer, // Loading bar auth: authReducer, // User authentication general: generalReducer, // General data user: userReducer, // User data diff --git a/src/store/reducers/userReducers.js b/src/store/reducers/userReducers.js index a829613..74bc867 100644 --- a/src/store/reducers/userReducers.js +++ b/src/store/reducers/userReducers.js @@ -14,7 +14,7 @@ const userReducer = (state = INIT_STATE, action) => { case "SIGNUP_SUCCESS": return { ...state, - registrationHistory: action.payload, + registrationHistory: { ...action.payload }, }; case "SIGNUP_FAILED" || "SIGNUP_ERROR": @@ -41,7 +41,7 @@ const userReducer = (state = INIT_STATE, action) => { case "READ_CACHE_SUCCESS": return { ...state, - fetchedUser: action.payload.fetchedUser, + fetchedUser: { ...action.payload.fetchedUser }, }; case "READ_CACHE_FAILED" || "READ_CACHE_ERROR": @@ -55,7 +55,7 @@ const userReducer = (state = INIT_STATE, action) => { case "UPDATE_CACHE_SUCCESS": return { ...state, - fetchedUser: action.payload.fetchedUser, + // fetchedUser: { ...action.payload.fetchedUser }, }; case "UPDATE_CACHE_ERROR": @@ -69,7 +69,7 @@ const userReducer = (state = INIT_STATE, action) => { case "SAVE_SETTING_SUCCESS": return { ...state, - fetchedUser: action.payload.fetchedUser, + fetchedUser: { ...action.payload.fetchedUser }, }; case "SAVE_SETTING_ERROR": @@ -83,7 +83,7 @@ const userReducer = (state = INIT_STATE, action) => { case "GET_TALK_SUCCESS": return { ...state, - selectedTalk: action.payload.talk, + selectedTalk: { ...action.payload.talk }, }; case "GET_TALK_FAILED" || "GET_TALK_ERROR": @@ -97,7 +97,7 @@ const userReducer = (state = INIT_STATE, action) => { case "UPLOAD_TALK_SUCCESS": return { ...state, - fetchedUser: action.payload.fetchedUser, + fetchedUser: { ...action.payload.fetchedUser }, }; case "UPLOAD_TALK_ERROR": @@ -111,7 +111,7 @@ const userReducer = (state = INIT_STATE, action) => { case "DELETING_TALK_SUCCESS": return { ...state, - fetchedUser: action.payload.fetchedUser, + fetchedUser: { ...action.payload.fetchedUser }, }; case "DELETING_TALK_ERROR": From 1c6a968394e23de33effa9804fda42eb2472eaac Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 2 Jul 2020 15:26:04 +0200 Subject: [PATCH 08/86] Improve user fetching Incorrect user fetching has been fixed. --- src/components/pages/ProfilePage/index.jsx | 13 +++++-------- src/store/actions/userActions.js | 13 +++++++------ src/store/reducers/userReducers.js | 5 ++++- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/components/pages/ProfilePage/index.jsx b/src/components/pages/ProfilePage/index.jsx index 06fb09d..76caf66 100644 --- a/src/components/pages/ProfilePage/index.jsx +++ b/src/components/pages/ProfilePage/index.jsx @@ -24,9 +24,7 @@ import { connect } from "react-redux"; * loads the components accordingly. */ class ProfilePage extends React.Component { - state = { - cachingDone: false, - }; + state = {}; saveSettings = (state) => { this.props.saveSettings(state); @@ -86,7 +84,7 @@ class ProfilePage extends React.Component { componentDidUpdate() { const { loggedUser, fetchedUser } = this.props; - if (!this.state.cachingDone) { + if (!this.props.cachingDone) { if ( !loggedUser.anonymous && loggedUser.username === fetchedUser?.username @@ -96,10 +94,8 @@ class ProfilePage extends React.Component { console.log("UPDATEd"); if (this._isMounted) { this.props.readCache(loggedUser.username); - this.setState( - { cachingDone: true }, - console.log("CACHING DONE", this.props.fetchedUser) - ); + + console.log("CACHING DONE", this.props.fetchedUser); } else { console.log("CACHING DONE BUT NOT MOUNTED"); } @@ -147,6 +143,7 @@ class ProfilePage extends React.Component { const mapStateToProps = (state) => ({ loggedUser: state.auth.loggedUser, fetchedUser: state.user.fetchedUser, + cachingDone: state.user.cachingDone, }); const mapDispatchToProps = (dispatch) => { diff --git a/src/store/actions/userActions.js b/src/store/actions/userActions.js index edacc7f..bb02bf5 100644 --- a/src/store/actions/userActions.js +++ b/src/store/actions/userActions.js @@ -270,16 +270,17 @@ const updateCacheAction = (fetchedUser) => { intel.resetReducer(); - session.tasks.user + return session.tasks.user .cache(JSON.stringify(fetchedUser.platformData)) + .then( + dispatch({ + type: "UPDATE_CACHE_SUCCESS", + payload: { fetchedUser }, + }) + ) .catch((ex) => dispatch({ type: "UPDATE_CACHE_ERROR", payload: { error: ex } }) ); - - dispatch({ - type: "UPDATE_CACHE_SUCCESS", - payload: { fetchedUser }, - }); } catch (ex) { dispatch({ type: "UPDATE_CACHE_ERROR", diff --git a/src/store/reducers/userReducers.js b/src/store/reducers/userReducers.js index 74bc867..a727c87 100644 --- a/src/store/reducers/userReducers.js +++ b/src/store/reducers/userReducers.js @@ -4,6 +4,8 @@ const INIT_STATE = { fetchedUser: null, registrationHistory: null, selectedTalk: null, + newCachedUser: null, + cachingDone: false, userError: null, userErrorDetails: null, }; @@ -55,7 +57,8 @@ const userReducer = (state = INIT_STATE, action) => { case "UPDATE_CACHE_SUCCESS": return { ...state, - // fetchedUser: { ...action.payload.fetchedUser }, + newCachedUser: { ...action.payload.fetchedUser }, + cachingDone: true, }; case "UPDATE_CACHE_ERROR": From 6b0ca3f421602af364c446d13432c07184e72d22 Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 2 Jul 2020 16:13:31 +0200 Subject: [PATCH 09/86] Upgrade registration component with redux The registration works now with the new structure. --- .../molecules/forms/RegisterForm/index.jsx | 37 ++++++++++++++++--- src/store/actions/userActions.js | 2 +- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/components/molecules/forms/RegisterForm/index.jsx b/src/components/molecules/forms/RegisterForm/index.jsx index 1fb342b..18f520e 100644 --- a/src/components/molecules/forms/RegisterForm/index.jsx +++ b/src/components/molecules/forms/RegisterForm/index.jsx @@ -32,6 +32,10 @@ import { //> OAuth import GitHubOAuth from "reactjs-oauth"; +import { registerAction } from "../../../../store/actions/userActions"; +import { fetchGitLabServersAction } from "../../../../store/actions/generalActions"; +import { loginAction } from "../../../../store/actions/authActions"; +import { connect } from "react-redux"; //#endregion //#region > Components @@ -77,10 +81,10 @@ class RegisterForm extends React.Component { // Check if GitLab Servers have already been set if (this.state.gitlab_servers === undefined) { // Retrieve GitLab servers - const gitlab_servers = await this.props.globalFunctions.fetchGitLabServers(); - - this.setState({ - gitlab_servers, + this.props.fetchGitLabServers().then(() => { + this.setState({ + gitlab_servers: this.props.gitlabServers, + }); }); } }; @@ -404,8 +408,17 @@ class RegisterForm extends React.Component { gift_code: promoCode && code !== "" ? code : null, password: password1, }; + console.log(this.props); + this.props.register(registrationData).then(() => { + const { username, password } = registrationData; + + console.log({ username, password }); - this.props.globalFunctions.registerUser(registrationData); + this.props.login({ + username, + password, + }); + }); } ); } else { @@ -828,10 +841,22 @@ RegisterForm.propTypes = { goto: PropTypes.func, }; //#endregion +const mapStateToProps = (state) => ({ + registrationHistory: state.user.registrationHistory, + gitlabServers: state.general.allGitlabServers, +}); + +const mapDispatchToProps = (dispatch) => { + return { + register: (registrationData) => dispatch(registerAction(registrationData)), + login: (user) => dispatch(loginAction(user)), + fetchGitLabServers: () => dispatch(fetchGitLabServersAction()), + }; +}; //#region > Exports //> Default Class -export default RegisterForm; +export default connect(mapStateToProps, mapDispatchToProps)(RegisterForm); //#endregion /** diff --git a/src/store/actions/userActions.js b/src/store/actions/userActions.js index bb02bf5..c34f40e 100644 --- a/src/store/actions/userActions.js +++ b/src/store/actions/userActions.js @@ -37,7 +37,7 @@ const registerAction = (registrationData) => { // Create JSON string out of sources for backend use registrationData.sources = JSON.stringify(registrationData.sources); - session.tasks.user + return session.tasks.user .registration(registrationData) .then((res) => { if (res.result === "FAIL") { From 6455e6cc3bb26cee3339362821cc0a0a5d480d9a Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 2 Jul 2020 16:14:42 +0200 Subject: [PATCH 10/86] Login after regisration A context error where the login function was not defined due to asynchronously is fixed now. After registering a user will be logged in. --- src/store/actions/authActions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/store/actions/authActions.js b/src/store/actions/authActions.js index fc6f094..ebe912b 100644 --- a/src/store/actions/authActions.js +++ b/src/store/actions/authActions.js @@ -17,7 +17,7 @@ const loginAction = (user) => { console.log(session); - session + return session .begin(user) .then((whoami) => { console.log("WHOAMI", whoami); From 4548fd052e5831cd305c35f7f533b2562141c245 Mon Sep 17 00:00:00 2001 From: Pinterid Date: Thu, 2 Jul 2020 16:06:22 +0200 Subject: [PATCH 11/86] Update package.json React-Avatar-Editor was added for editing images on the site. --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 68a6775..1e4035f 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "mdbreact": "mdbreact-4.26.1.tgz", "node-sass": "^4.12.0", "obelisk.js": "^1.2.2", + "react-avatar-editor": "^11.0.9", "react-chartjs-2": "^2.9.0", "react-dropzone": "^11.0.1", "react-redux": "^7.2.0", From cf9f25d2299581b714d549d3c488b03dc9836764 Mon Sep 17 00:00:00 2001 From: Pinterid Date: Thu, 2 Jul 2020 16:09:56 +0200 Subject: [PATCH 12/86] Add profile picture modal The modal for editing images was added. --- .../modals/ProfilePictureModal/index.jsx | 148 ++++++++++++++++++ .../modals/ProfilePictureModal/profile.scss | 115 ++++++++++++++ 2 files changed, 263 insertions(+) create mode 100644 src/components/molecules/modals/ProfilePictureModal/index.jsx create mode 100644 src/components/molecules/modals/ProfilePictureModal/profile.scss diff --git a/src/components/molecules/modals/ProfilePictureModal/index.jsx b/src/components/molecules/modals/ProfilePictureModal/index.jsx new file mode 100644 index 0000000..6192b6b --- /dev/null +++ b/src/components/molecules/modals/ProfilePictureModal/index.jsx @@ -0,0 +1,148 @@ +//#region > Imports +//> React +// Contains all the functionality necessary to define React components +import React from "react"; +// Contains the functionality for editing a file +import AvatarEditor from "react-avatar-editor"; +//> MDB +// "Material Design for Bootstrap" is a great UI design framework +import { + MDBModal, + MDBModalHeader, + MDBIcon, + MDBModalBody, + MDBBtn, + MDBCol, + MDBRow, +} from "mdbreact"; + +//> CSS +import "./profile.scss"; +//#endregion + +//#region > Components +class ProfilePictureModal extends React.Component { + constructor(props) { + super(props); + + this.state = { + scale: 1, + }; + this.handleWheel = this.handleWheel.bind(this); + } + + onClickSave = () => { + if (this.editor) { + const file = this.editor.getImageScaledToCanvas().toDataURL(); + + this.props.setAvatarUrl(file); + this.props.handleProfilePictureModal(); + } + }; + + componentDidMount() { + window.addEventListener("wheel", this.handleWheel, { passive: true }); + } + + componentWillUnmount() { + window.removeEventListener("wheel", this.handleWheel); + } + + handleWheel(event) { + let scale = this.state.scale; + + if (event.deltaY < 0) { + if (scale < 2) { + scale += 0.01; + } + } else { + if (scale > 1) { + scale -= 0.01; + } + } + + this.setState({ scale }); + } + + handleScale = (e) => { + const scale = parseFloat(e.target.value); + + this.setState({ scale }); + }; + + setEditorRef = (editor) => (this.editor = editor); + + render() { + return ( + + + + + + + + Image Editor + + + + Save + + + + + + + + + + ); + } +} +//#endregion + +//#region > Exports +export default ProfilePictureModal; +//#endregion + +/** + * SPDX-License-Identifier: (EUPL-1.2) + * Copyright © Simon Prast + */ diff --git a/src/components/molecules/modals/ProfilePictureModal/profile.scss b/src/components/molecules/modals/ProfilePictureModal/profile.scss new file mode 100644 index 0000000..0041e7b --- /dev/null +++ b/src/components/molecules/modals/ProfilePictureModal/profile.scss @@ -0,0 +1,115 @@ +#profile { + #header { + margin-bottom: -0.5em; + } + + #btn-save { + margin-top: -0.5em; + } + + input[type=range] { + -webkit-appearance: none; + margin: 18px 0; + width: 80%; + } + + input[type=range]:focus { + outline: none; + } + + input[type=range]::-webkit-slider-runnable-track { + width: 100%; + height: 8.4px; + cursor: pointer; + animate: 0.2s; + box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; + background: #77bd43; + border-radius: 1.3px; + border: 0.2px solid #010101; + } + + input[type=range]::-webkit-slider-thumb { + box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; + border: 1px solid #000000; + height: 20px; + width: 16px; + border-radius: 3px; + background: #ffffff; + cursor: pointer; + -webkit-appearance: none; + margin-top: -7px; + } + + input[type=range]:focus::-webkit-slider-runnable-track { + background: #77bd43; + } + + input[type=range]::-moz-range-track { + width: 100%; + height: 8.4px; + cursor: pointer; + animate: 0.2s; + box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; + background: #77bd43; + border-radius: 1.3px; + border: 0.2px solid #010101; + } + + input[type=range]::-moz-range-thumb { + box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; + border: 1px solid #000000; + height: 36px; + width: 16px; + border-radius: 3px; + background: #ffffff; + cursor: pointer; + } + + input[type=range]::-ms-track { + width: 100%; + height: 8.4px; + cursor: pointer; + animate: 0.2s; + background: transparent; + border-color: transparent; + border-width: 16px 0; + color: transparent; + } + + input[type=range]::-ms-fill-lower { + background: #77bd43; + border: 0.2px solid #010101; + border-radius: 2.6px; + box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; + } + + input[type=range]::-ms-fill-upper { + background: #77bd43; + border: 0.2px solid #010101; + border-radius: 2.6px; + box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; + } + + input[type=range]::-ms-thumb { + box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; + border: 1px solid #000000; + height: 36px; + width: 16px; + border-radius: 3px; + background: #ffffff; + cursor: pointer; + } + + input[type=range]:focus::-ms-fill-lower { + background: #77bd43; + } + + input[type=range]:focus::-ms-fill-upper { + background: #77bd43; + } +} + +/** + * SPDX-License-Identifier: (EUPL-1.2) + * Copyright © 2019-2020 Simon Prast + */ From 63d488cf946b577bf2c05fe6fc2a41df0faa979a Mon Sep 17 00:00:00 2001 From: Pinterid Date: Thu, 2 Jul 2020 16:11:45 +0200 Subject: [PATCH 13/86] Update modal export/imports The modal imports and exports were updated. --- src/components/molecules/index.js | 11 +++++++-- .../index.jsx | 23 +++++-------------- src/components/molecules/modals/index.js | 6 ++--- .../organisms/tabs/TalksTab/index.jsx | 7 ++++-- 4 files changed, 23 insertions(+), 24 deletions(-) rename src/components/molecules/modals/{UploadModal => TalkUploadModal}/index.jsx (87%) diff --git a/src/components/molecules/index.js b/src/components/molecules/index.js index 6ef41db..3cbfd12 100644 --- a/src/components/molecules/index.js +++ b/src/components/molecules/index.js @@ -5,13 +5,20 @@ import Footer from "./Footer"; import Navbar from "./Navbar"; import LoginForm from "./forms/LoginForm"; import RegisterForm from "./forms/RegisterForm"; -import UploadModal from "./modals/UploadModal"; +import TalkUploadModal from "./modals/TalkUploadModal"; import UserActionCard from "./UserActionCard"; //#endregion //#region > Exports //> Molecules -export { Footer, Navbar, LoginForm, RegisterForm, UploadModal, UserActionCard }; +export { + Footer, + Navbar, + LoginForm, + RegisterForm, + TalkUploadModal, + UserActionCard, +}; //#endregion /** diff --git a/src/components/molecules/modals/UploadModal/index.jsx b/src/components/molecules/modals/TalkUploadModal/index.jsx similarity index 87% rename from src/components/molecules/modals/UploadModal/index.jsx rename to src/components/molecules/modals/TalkUploadModal/index.jsx index ff8e5fa..b434b09 100644 --- a/src/components/molecules/modals/UploadModal/index.jsx +++ b/src/components/molecules/modals/TalkUploadModal/index.jsx @@ -13,20 +13,18 @@ import { MDBModalBody, MDBProgress, } from "mdbreact"; -import { connect } from "react-redux"; -import { uploadTalkAction } from "../../../../store/actions/userActions"; //#endregion //#region > Components /** @class A upload modal component for uploading files including a drop-zone */ -class UploadModal extends React.Component { +class TalkUploadModal extends React.Component { state = { loading: false, error: [], }; onDrop = async (files) => { - const { loggedUser, fetchedUser } = this.props; + const { globalState, globalFunctions } = this.props; if (files.length > 0) { this.setState({ @@ -34,11 +32,11 @@ class UploadModal extends React.Component { loading: true, }); - this.props + globalFunctions .uploadTalk(files[0], { - avatarUrl: fetchedUser.platformData.profile.avatarUrl, + avatarUrl: globalState.fetchedUser.platformData.profile.avatarUrl, owner: { - username: loggedUser.username, + username: globalState.loggedUser.username, }, }) .then(() => { @@ -147,18 +145,9 @@ class UploadModal extends React.Component { } //#endregion -const mapStateToProps = (state) => ({ - loggedUser: state.user.fetchedUser, - fetchedUser: state.user.fetchedUser, -}); - -const mapDispatchToProps = (dispatch) => { - return { uploadTalk: (file) => dispatch(uploadTalkAction(file)) }; -}; - //#region > Exports //> Default Class -export default connect(mapStateToProps, mapDispatchToProps)(UploadModal); +export default TalkUploadModal; //#endregion /** diff --git a/src/components/molecules/modals/index.js b/src/components/molecules/modals/index.js index 008ffd4..f95b0ad 100644 --- a/src/components/molecules/modals/index.js +++ b/src/components/molecules/modals/index.js @@ -1,14 +1,14 @@ //#region > Imports //> Components // Import all components to export them for easy access from parent components -import UploadModal from "./UploadModal"; -import SettingModal from "./SettingsModal"; +import TalkUploadModal from "./TalkUploadModal"; +import ProfilePictureModal from "./ProfilePictureModal"; //#endregion //#region > Exports //> Components // Export the components for easy access from parent components -export { UploadModal, SettingModal }; +export { TalkUploadModal, ProfilePictureModal }; //#endregion /** diff --git a/src/components/organisms/tabs/TalksTab/index.jsx b/src/components/organisms/tabs/TalksTab/index.jsx index ff99ec6..b4634e9 100644 --- a/src/components/organisms/tabs/TalksTab/index.jsx +++ b/src/components/organisms/tabs/TalksTab/index.jsx @@ -20,7 +20,7 @@ import { //> CSS import "./talkstab.scss"; //> Modules -import { UploadModal } from "../../../molecules/modals"; +import { TalkUploadModal } from "../../../molecules/modals"; import { connect } from "react-redux"; import { TalksTab } from ".."; import { deleteTalkAction } from "../../../../store/actions/userActions"; @@ -202,7 +202,10 @@ class Talks extends React.Component { })} {this.state.showUpload && ( - + )} ); From 3fdfaebf68a5ec04b2342ae6d3063365d8edbc62 Mon Sep 17 00:00:00 2001 From: Pinterid Date: Thu, 2 Jul 2020 16:12:29 +0200 Subject: [PATCH 14/86] Add settings page A page for editing user settings was added. --- .../molecules/modals/SettingsModal/index.jsx | 498 --------------- .../modals/SettingsModal/settings.scss | 59 -- src/components/pages/SettingsPage/index.jsx | 586 ++++++++++++++++++ .../pages/SettingsPage/settings.scss | 93 +++ 4 files changed, 679 insertions(+), 557 deletions(-) delete mode 100644 src/components/molecules/modals/SettingsModal/index.jsx delete mode 100644 src/components/molecules/modals/SettingsModal/settings.scss create mode 100644 src/components/pages/SettingsPage/index.jsx create mode 100644 src/components/pages/SettingsPage/settings.scss diff --git a/src/components/molecules/modals/SettingsModal/index.jsx b/src/components/molecules/modals/SettingsModal/index.jsx deleted file mode 100644 index 7467518..0000000 --- a/src/components/molecules/modals/SettingsModal/index.jsx +++ /dev/null @@ -1,498 +0,0 @@ -//#region > Imports -//> React -// Contains all the functionality necessary to define React components -import React from "react"; -//> MDB -// "Material Design for Bootstrap" is a great UI design framework -import { - MDBBtn, - MDBIcon, - MDBModal, - MDBModalBody, - MDBModalHeader, - MDBModalFooter, - MDBTabPane, - MDBTabContent, - MDBRow, - MDBCol, - MDBNav, - MDBNavLink, - MDBNavItem, - MDBInput, - MDBAnimation, - MDBSelect, - MDBSelectInput, - MDBSelectOption, - MDBSelectOptions, -} from "mdbreact"; - -//> CSS -import "./settings.scss"; -import { connect } from "react-redux"; -import { - saveSettingsActions, - readCacheAction, -} from "../../../../store/actions/userActions"; -//#endregion - -//#region > Constant Variables -//> Settings data -const SETTINGS_TAB = [ - { name: "Profile", icon: "" }, - { name: "Customization", icon: "" }, - { name: "Account", icon: "" }, - { name: "Connections", icon: "" }, - { name: "Blocked users", icon: "" }, - { name: "Billing", icon: "" }, - { name: "Security", icon: "" }, -]; -//#endregion - -//#region > Components -/** @class A settings modal component for displaying and editing user settings */ -class SettingsModal extends React.Component { - state = { - changeDetected: false, - activeItemInnerPills: 0, - }; - - componentDidMount = () => { - const { fetchedUser } = this.props; - // Check for the current values - const platformData = fetchedUser?.platformData; - - if (platformData?.profile && platformData?.user) { - const profile = platformData.profile; - const data = platformData.user; - const enterData = { - first_name: data.firstName ? data.firstName : "", - last_name: data.lastName ? data.lastName : "", - email: data.email ? data.email : "", - showEmailPublic: data.settings.showEmailPublic, - company: profile.company ? profile.company : "", - showCompanyPublic: data.settings.showCompanyPublic, - website: profile.websiteUrl ? profile.websiteUrl : "", - location: profile.location ? profile.location : "", - showLocalRanking: data.settings.showLocalRanking, - showTopLanguages: data.settings.showTopLanguages, - show3DDiagram: data.settings.show3DDiagram, - show2DDiagram: data.settings.show2DDiagram, - activeTheme: data.settings.activeTheme - ? data.settings.activeTheme - : null, - }; - - const dataString = this.stringToHash(JSON.stringify(enterData)); - - this.setState({ - ...enterData, - checksum: dataString, - }); - } else { - this.initBlank(); - } - }; - - initBlank = () => { - this.setState({ - first_name: "", - last_name: "", - email: "", - showEmailPublic: true, - company: "", - showCompanyPublic: true, - website: "", - location: "", - showLocalRanking: true, - showTopLanguages: true, - show3DDiagram: true, - show2DDiagram: true, - activeTheme: null, - }); - }; - - stringToHash = (string) => { - let hash = 0; - - if (string.length == 0) return hash; - - for (let i = 0; i < string.length; i++) { - let char = string.charCodeAt(i); - - hash = (hash << 5) - hash + char; - hash = hash & hash; - } - - return hash; - }; - - handleSelectChange = (val) => { - this.setState( - { - activeTheme: val[0], - }, - () => this.getChange() - ); - }; - - handleCheckChange = (e) => { - this.setState( - { - [e.target.name]: e.target.checked, - }, - () => this.getChange() - ); - }; - - handleTextChange = (e) => { - this.setState( - { - [e.target.name]: e.target.value, - }, - () => this.getChange() - ); - }; - - getChange = () => { - let currentData = { - first_name: this.state.first_name, - last_name: this.state.last_name, - email: this.state.email, - showEmailPublic: this.state.showEmailPublic, - company: this.state.company, - showCompanyPublic: this.state.showCompanyPublic, - website: this.state.website, - location: this.state.location, - showLocalRanking: this.state.showLocalRanking, - showTopLanguages: this.state.showTopLanguages, - show3DDiagram: this.state.show3DDiagram, - show2DDiagram: this.state.show2DDiagram, - activeTheme: this.state.activeTheme ? this.state.activeTheme : null, - }; - - // Get hash of current data - let currentHash = this.stringToHash(JSON.stringify(currentData)); - - if (this.state.changeDetected) { - if (this.state.checksum === currentHash) { - this.setState({ - changeDetected: false, - }); - } - } else { - if (this.state.checksum !== currentHash) { - this.setState({ - changeDetected: true, - }); - } - } - }; - - toggleInnerPills = (tab) => (e) => { - if (this.state.activeItemInnerPills !== tab) { - this.setState({ - activeItemInnerPills: tab, - }); - } - }; - - save = () => { - this.props.saveSettings(this.state); - this.props.closeModal(); - }; - - render() { - return ( - - - - Settings - - - - - - {SETTINGS_TAB.map((tab, i) => { - return ( - - - {tab.name} - {this.state.activeItemInnerPills === i && - tab.icon !== "" && ( - - - - )} - - - ); - })} - - - - - -
      Profile
      -
      -

      Your full name

      - - - - - - - - -

      Public email

      - - - - - - Display email on profile

      } - filled - type="checkbox" - id="checkbox0" - name="showEmailPublic" - onChange={this.handleCheckChange} - checked={this.state.showEmailPublic} - containerClass="mr-5" - /> -

      Your workplace

      - - - - - - - You can @mention your company anywhere on SNEK - - Display company on profile

      } - filled - type="checkbox" - id="checkbox1" - name="showCompanyPublic" - onChange={this.handleCheckChange} - checked={this.state.showCompanyPublic} - containerClass="mr-5" - /> -

      Website

      - - - - - -

      Location

      - - - - - - - This can also assist us in finding you the best local - matches - -
      -
      - - - Show local ranking

      } - filled - type="checkbox" - id="checkbox3" - name="showLocalRanking" - onChange={this.handleCheckChange} - checked={this.state.showLocalRanking} - containerClass="mr-5" - /> -
      - - Show top programming languages

      } - filled - type="checkbox" - id="checkbox4" - name="showTopLanguages" - onChange={this.handleCheckChange} - checked={this.state.showTopLanguages} - containerClass="mr-5" - /> -
      - -
      -
      - - Show 3D work activity diagram

      } - filled - type="checkbox" - id="checkbox5" - name="show3DDiagram" - onChange={this.handleCheckChange} - checked={this.state.show3DDiagram} - containerClass="mr-5" - /> -
      - - Show 2D work activity diagram

      } - filled - type="checkbox" - id="checkbox6" - name="show2DDiagram" - onChange={this.handleCheckChange} - checked={this.state.show2DDiagram} - containerClass="mr-5" - /> -
      -
      -
      - -
      Customization
      -
      -

      Choose your theme

      - - - - - - Default - {this.props.fetchedUser.accessories.themes && - this.props.fetchedUser.accessories.themes.tids.map( - (tid, i) => { - let name = "Unnamed"; - switch (tid) { - case "9d88bda4657dcf17581ee91dfe6ab2a3": - name = "Alpha"; - break; - default: - name = "Unnamed"; - } - name += " Theme"; - return ( - - {tid} - - ); - } - )} - - - - -
      -
      - -
      Panel 3
      -
      -
      -
      -
      -
      - - {this.state.changeDetected && ( - - Save - - )} - - Close - - -
      - ); - } -} -//#endregion - -const mapStateToProps = (state) => ({ - fetchedUser: state.user.fetchedUser, -}); - -const mapDispatchToProps = (dispatch) => { - return { - saveSettings: (nextSettings) => dispatch(saveSettingsActions(nextSettings)), - }; -}; - -//#region > Exports -//> Default Class -export default connect(mapStateToProps, mapDispatchToProps)(SettingsModal); -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © 2019-2020 Simon Prast - */ diff --git a/src/components/molecules/modals/SettingsModal/settings.scss b/src/components/molecules/modals/SettingsModal/settings.scss deleted file mode 100644 index add85fc..0000000 --- a/src/components/molecules/modals/SettingsModal/settings.scss +++ /dev/null @@ -1,59 +0,0 @@ -#settings { - .nav-item { - padding: 0; - } - - .pills-primary .nav-link { - background-color: darken(#fff, 2%) !important; - border-color: #77bd43; - padding-top: 1rem; - padding-bottom: 1rem; - color: #212529; - text-align: left; - box-shadow: none; - - i { - padding-left: 0.5rem; - } - - &:hover { - background-color: darken(#fff, 5%) !important; - } - - &.active { - background-color: darken(#fff, 10%) !important; - border-left: 5px #77bd43 solid; - } - } - - .tab-content { - padding: 0; - text-align: left; - - .font-weight-bold { - margin-bottom: 0.4rem; - padding-bottom: 0; - border-bottom: 3px #77bd43 solid; - display: inline-block; - margin-top: 1rem; - } - } - - .form-check-input[type="checkbox"].filled-in:checked + label::after, - label.btn input[type="checkbox"].filled-in:checked + label::after { - background-color: #77bd43; - border: 2px solid #77bd43; - } - - .personal-data { - .form-check { - padding-left: 0 !important; - margin-top: 0.4rem; - } - } -} - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © 2019-2020 Simon Prast - */ diff --git a/src/components/pages/SettingsPage/index.jsx b/src/components/pages/SettingsPage/index.jsx new file mode 100644 index 0000000..74e27d7 --- /dev/null +++ b/src/components/pages/SettingsPage/index.jsx @@ -0,0 +1,586 @@ +//#region > Imports +//> React +// Contains all the functionality necessary to define React components +import React from "react"; +// DOM bindings for React Router +import { Link } from "react-router-dom"; +// Contains the functionality for uploading a file +import Dropzone from "react-dropzone"; +//> MDB +// "Material Design for Bootstrap" is a great UI design framework +import { + MDBContainer, + MDBCol, + MDBInput, + MDBTabPane, + MDBRow, + MDBSelect, + MDBSelectOption, + MDBSelectOptions, + MDBNav, + MDBNavItem, + MDBNavLink, + MDBAnimation, + MDBIcon, + MDBTabContent, + MDBView, + MDBMask, + MDBSelectInput, + MDBBtn, +} from "mdbreact"; +import { connect } from "react-redux"; + +// Profile Picture Editor +import { ProfilePictureModal } from "../../../components/molecules/modals"; +import { + readCacheAction, + saveSettingsActions, +} from "../../../store/actions/userActions"; +//> CSS +import "./settings.scss"; +//#endregion + +//#region > Components +/** + * @class This component adds the Settings page, + * used to change user information like. + */ +class SettingsPage extends React.Component { + state = { + changeDetected: false, + showProfilePicture: false, + showNotification: false, + file: undefined, + activeItem: 0, + tabItems: [ + { name: "Profile", icon: "" }, + { name: "Customization", icon: "" }, + { name: "Account", icon: "" }, + { name: "Connections", icon: "" }, + { name: "Blocked users", icon: "" }, + { name: "Billing", icon: "" }, + { name: "Security", icon: "" }, + ], + }; + + componentDidMount = () => { + console.log("XYX"); + // Check for the current values + const { loggedUser, fetchedUser } = this.props; + const username = loggedUser?.username; + + if (username) { + this.props.readCache(username); + } + + const platformData = this.props.fetchedUser?.platformData; + + if (platformData?.profile && platformData?.user) { + const profile = platformData.profile; + const data = platformData.user; + const enterData = { + avatar_url: profile.avatarUrl ? profile.avatarUrl : "", + first_name: data.firstName ? data.firstName : "", + last_name: data.lastName ? data.lastName : "", + email: data.email ? data.email : "", + showEmailPublic: data.settings.showEmailPublic, + company: profile.company ? profile.company : "", + showCompanyPublic: data.settings.showCompanyPublic, + website: profile.websiteUrl ? profile.websiteUrl : "", + location: profile.location ? profile.location : "", + showLocalRanking: data.settings.showLocalRanking, + showTopLanguages: data.settings.showTopLanguages, + show3DDiagram: data.settings.show3DDiagram, + show2DDiagram: data.settings.show2DDiagram, + activeTheme: data.settings.activeTheme + ? data.settings.activeTheme + : null, + }; + + const dataString = this.stringToHash(JSON.stringify(enterData)); + + this.setState({ + ...enterData, + checksum: dataString, + }); + } else { + this.initBlank(); + } + }; + + initBlank = () => { + this.setState({ + avatar_url: "", + first_name: "", + last_name: "", + email: "", + showEmailPublic: true, + company: "", + showCompanyPublic: true, + website: "", + location: "", + showLocalRanking: true, + showTopLanguages: true, + show3DDiagram: true, + show2DDiagram: true, + activeTheme: null, + }); + }; + + stringToHash = (string) => { + let hash = 0; + + if (string.length == 0) return hash; + + for (let i = 0; i < string.length; i++) { + let char = string.charCodeAt(i); + + hash = (hash << 5) - hash + char; + hash = hash & hash; + } + + return hash; + }; + + handleSelectChange = (val) => { + this.setState( + { + activeTheme: val[0], + }, + () => this.getChange() + ); + }; + + handleCheckChange = (e) => { + this.setState( + { + [e.target.name]: e.target.checked, + }, + () => this.getChange() + ); + }; + + handleTextChange = (e) => { + this.setState( + { + [e.target.name]: e.target.value, + }, + () => this.getChange() + ); + }; + + getChange = () => { + let currentData = { + avatar_url: this.state.avatar_url, + first_name: this.state.first_name, + last_name: this.state.last_name, + email: this.state.email, + showEmailPublic: this.state.showEmailPublic, + company: this.state.company, + showCompanyPublic: this.state.showCompanyPublic, + website: this.state.website, + location: this.state.location, + showLocalRanking: this.state.showLocalRanking, + showTopLanguages: this.state.showTopLanguages, + show3DDiagram: this.state.show3DDiagram, + show2DDiagram: this.state.show2DDiagram, + activeTheme: this.state.activeTheme ? this.state.activeTheme : null, + }; + + // Get hash of current data + let currentHash = this.stringToHash(JSON.stringify(currentData)); + + if (this.state.changeDetected) { + if (this.state.checksum === currentHash) { + this.setState({ + changeDetected: false, + }); + } + } else { + if (this.state.checksum !== currentHash) { + this.setState({ + changeDetected: true, + }); + } + } + }; + + save = () => { + this.props.saveSettings(this.state); + this.setState({ showNotification: true }); + }; + + handleProfilePictureModal = () => { + if (this.state.showProfilePicture) { + this.setState({ + showProfilePicture: !this.state.showProfilePicture, + }); + } + }; + + onDrop = async (files) => { + if (files.length > 0) { + this.setState({ + file: files[0], + showProfilePicture: true, + }); + } + }; + + setAvatarUrl = (avatar_url) => { + this.setState({ avatar_url }, () => this.getChange()); + }; + + render() { + const { fetchedUser, loggedUser } = this.props; + const { activeItem } = this.state; + + if (fetchedUser) { + return ( + <> + {this.state.showNotification && ( +
      + + + Changes were saved successfully —{" "} + + View your profile + + + +
      + )} + + + + + + + + + + +

      + {loggedUser.username} +

      + Profile Settings +
      +
      +
      + {this.state.tabItems.map((tab, i) => { + return ( + + this.setState({ activeItem: i })} + > + {tab.name} + {activeItem === i && tab.icon !== "" && ( + + + + )} + + + ); + })} +
      +
      + + + +

      Profile

      + + {({ getRootProps, getInputProps }) => ( +
      + + + + + + + +
      + )} +
      +
      +

      Your full name

      + + + + + + + + +

      Public email

      + + + + + + Display email on profile

      } + filled + type="checkbox" + id="checkbox0" + name="showEmailPublic" + onChange={this.handleCheckChange} + checked={this.state.showEmailPublic} + containerClass="mr-5" + /> +

      Your workplace

      + + + + + + + You can @mention your company anywhere on SNEK + + Display company on profile

      } + filled + type="checkbox" + id="checkbox1" + name="showCompanyPublic" + onChange={this.handleCheckChange} + checked={this.state.showCompanyPublic} + containerClass="mr-5" + /> +

      Website

      + + + + + +

      Location

      + + + + + + + This can also assist us in finding you the best local + matches + +
      +
      + + + Show local ranking

      } + filled + type="checkbox" + id="checkbox3" + name="showLocalRanking" + onChange={this.handleCheckChange} + checked={this.state.showLocalRanking} + containerClass="mr-5" + /> +
      + + Show top programming languages

      } + filled + type="checkbox" + id="checkbox4" + name="showTopLanguages" + onChange={this.handleCheckChange} + checked={this.state.showTopLanguages} + containerClass="mr-5" + /> +
      + +
      +
      + + Show 3D work activity diagram

      } + filled + type="checkbox" + id="checkbox5" + name="show3DDiagram" + onChange={this.handleCheckChange} + checked={this.state.show3DDiagram} + containerClass="mr-5" + /> +
      + + Show 2D work activity diagram

      } + filled + type="checkbox" + id="checkbox6" + name="show2DDiagram" + onChange={this.handleCheckChange} + checked={this.state.show2DDiagram} + containerClass="mr-5" + /> +
      +
      +
      + +
      Customization
      +
      +

      Choose your theme

      + + + + + + + Default + + {fetchedUser?.accessories?.themes && + fetchedUser.accessories.themes.tids.map( + (tid, i) => { + let name = "Unnamed"; + switch (tid) { + case "9d88bda4657dcf17581ee91dfe6ab2a3": + name = "Alpha"; + break; + default: + name = "Unnamed"; + } + name += " Theme"; + return ( + + {tid} + + ); + } + )} + + + + +
      +
      + +
      Panel 3
      +
      +
      +
      +
      + {this.state.changeDetected && ( + + + Save Changes + + + )} +
      + {this.state.showProfilePicture && ( + + )} + + ); + } else { + if (!loggedUser) { + //>TODO The active component has to be set to the login component + window.open("/", "_self"); + } else { + return ( +
      +
      + Loading... +
      +
      + ); + } + } + } +} +//#endregion + +const mapStateToProps = (state) => ({ + loggedUser: state.auth.loggedUser, + fetchedUser: state.user.fetchedUser, +}); + +const mapDispatchToProps = (dispatch) => { + return { + saveSettings: (nextSettings) => dispatch(saveSettingsActions(nextSettings)), + readCache: (username) => dispatch(readCacheAction(username)), + }; +}; + +//#region > Exports +//> Default Class +export default connect(mapStateToProps, mapDispatchToProps)(SettingsPage); +//#endregion + +/** + * SPDX-License-Identifier: (EUPL-1.2) + * Copyright © 2019-2020 Simon Prast + */ diff --git a/src/components/pages/SettingsPage/settings.scss b/src/components/pages/SettingsPage/settings.scss new file mode 100644 index 0000000..e94dd8c --- /dev/null +++ b/src/components/pages/SettingsPage/settings.scss @@ -0,0 +1,93 @@ +#settings { + padding: 2%; + + .nav-item { + padding: 0; + + img { + width: 50px; + height: 50px; + border-radius: 50%; + } + + .profile { + padding-left: 2%; + padding-bottom: 5%; + + .font-weight-bold { + margin-bottom: -3%; + } + } + } + + .pills-primary .nav-link { + background-color: darken(#fff, 2%) !important; + border-color: #77bd43; + padding-top: 1rem; + padding-bottom: 1rem; + color: #212529; + text-align: left; + box-shadow: none; + + i { + padding-left: 0.5rem; + } + + &:hover { + background-color: darken(#fff, 5%) !important; + } + + &.active { + background-color: darken(#fff, 10%) !important; + border-left: 5px #77bd43 solid; + } + } + + .tab-content { + padding: 0; + text-align: left; + + .font-weight-bold { + margin-bottom: 0.4rem; + padding-bottom: 0; + border-bottom: 3px #77bd43 solid; + display: inline-block; + margin-top: 1rem; + } + } + + .form-check-input[type="checkbox"].filled-in:checked + label::after, + label.btn input[type="checkbox"].filled-in:checked + label::after { + background-color: #77bd43; + border: 2px solid #77bd43; + } + + .personal-data { + .form-check { + padding-left: 0 !important; + margin-top: 0.4rem; + } + } + + .avatar{ + height: 150px; + width: 150px; + background: white; + } + } + + #notification { + background-color: rgba($color: #77bd43, $alpha: 0.5); + color: black; + + .message { + padding-top: 1.5%; + padding-bottom: 1.5%; + } + } + + /** + * SPDX-License-Identifier: (EUPL-1.2) + * Copyright © 2019-2020 Simon Prast + */ + \ No newline at end of file From 1c7d15b8dbaa10452e453c316685438179fb4ed3 Mon Sep 17 00:00:00 2001 From: Pinterid Date: Thu, 2 Jul 2020 16:13:05 +0200 Subject: [PATCH 15/86] Implement settings page The path for the settings page was set. --- src/Routes.js | 6 ++++++ src/components/pages/index.js | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Routes.js b/src/Routes.js index 95783f9..6863858 100644 --- a/src/Routes.js +++ b/src/Routes.js @@ -11,6 +11,7 @@ import { ProfilePage, CompanyPage, TalkPage, + SettingsPage, } from "./components/pages"; //#endregion @@ -42,6 +43,11 @@ class Routes extends React.Component { }; }} /> + } + /> {/* Some debugging routes */} Exports //> Pages -export { CompanyPage, HomePage, ProfilePage, TalkPage }; +export { CompanyPage, HomePage, ProfilePage, TalkPage, SettingsPage }; //#endregion /** From 11ce7b893c8162f51b1f1ad7dd089a8aa8af2a6f Mon Sep 17 00:00:00 2001 From: Pinterid Date: Thu, 2 Jul 2020 16:13:48 +0200 Subject: [PATCH 16/86] Update navbar settings The navbar settings now work with the settings page. --- src/components/molecules/Navbar/index.jsx | 213 ++++++++++------------ 1 file changed, 100 insertions(+), 113 deletions(-) diff --git a/src/components/molecules/Navbar/index.jsx b/src/components/molecules/Navbar/index.jsx index c8371f5..149db0d 100644 --- a/src/components/molecules/Navbar/index.jsx +++ b/src/components/molecules/Navbar/index.jsx @@ -32,8 +32,6 @@ import SNEKLogo from "../../../assets/navigation/logo.png"; import "./navbar.scss"; import { connect } from "react-redux"; import { logoutAction } from "../../../store/actions/authActions"; -//> Components -const Settings = lazy(() => import("../modals/SettingsModal")); //#endregion //#region > Components @@ -64,117 +62,106 @@ class Navbar extends React.Component { const { location, loggedUser } = this.props; console.log(this.props); return ( - <> - - - {location.pathname === "/" ? ( - - - SNEK Logo - SNEK - - - ) : ( - <> - {!loggedUser.anonymous ? ( - - - SNEK Logo - SNEK - - - ) : ( - - - SNEK Logo - SNEK - - - )} - - )} - - - - - - - - - {!loggedUser.anonymous ? ( - <> -
      - - - - {loggedUser.username} - - - - My profile - - - this.setState({ showSettings: true }) - } - > - Settings - - - Sign Out - - - - - - ) : ( - <> - {location.pathname !== "/" && ( - - - Sign In - - - )} - - )} - - - - - {this.state.showSettings && ( - Loading...
      }> - - - )} - + + + {location.pathname === "/" ? ( + + + SNEK Logo + SNEK + + + ) : ( + <> + {!loggedUser.anonymous ? ( + + + SNEK Logo + SNEK + + + ) : ( + + + SNEK Logo + SNEK + + + )} + + )} + + + + + + + + + {!loggedUser.anonymous ? ( + <> +
      + + + + {loggedUser.username} + + + + My profile + + + Settings + + + Sign Out + + + + + + ) : ( + <> + {location.pathname !== "/" && ( + + + Sign In + + + )} + + )} + + + + ); } } From 8b65ce7b9ab5f8156f0e4dc823ac60153b381f72 Mon Sep 17 00:00:00 2001 From: Pinterid Date: Thu, 2 Jul 2020 16:14:36 +0200 Subject: [PATCH 17/86] Update settings action The settings action is now capable of updating profile pictures. --- src/actions/intel/generalActions.js | 5 ++++- src/store/actions/userActions.js | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/actions/intel/generalActions.js b/src/actions/intel/generalActions.js index 07b0aed..2272be8 100644 --- a/src/actions/intel/generalActions.js +++ b/src/actions/intel/generalActions.js @@ -82,6 +82,9 @@ const saveSettings = (nextSettings) => { // Check for mandatory fields if (nextSettings.email) { + currentCache.profile.avatarUrl = nextSettings.avatar_url + ? nextSettings.avatar_url + : ""; currentCache.user.firstName = nextSettings.first_name ? nextSettings.first_name : ""; @@ -112,7 +115,7 @@ const saveSettings = (nextSettings) => { } session.tasks.user.cache(JSON.stringify(currentCache)); - + console.log(currentCache, "Current Cache"); return currentCache; } catch (ex) { return { diff --git a/src/store/actions/userActions.js b/src/store/actions/userActions.js index c34f40e..3df3670 100644 --- a/src/store/actions/userActions.js +++ b/src/store/actions/userActions.js @@ -314,6 +314,9 @@ const saveSettingsActions = (nextSettings) => { if (fetchedUser.platformData) { // Check for mandatory fields if (nextSettings.email) { + fetchedUser.platformData.profile.avatarUrl = nextSettings.avatar_url + ? nextSettings.avatar_url + : ""; fetchedUser.platformData.user.firstName = nextSettings.first_name ? nextSettings.first_name : ""; From 42f672894370082f2edcbb0b0b8cebbeae2c523c Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 2 Jul 2020 17:49:23 +0200 Subject: [PATCH 18/86] Improve settings page accesability Now it is possible to access the settings page directly by entering the url. Access is only granted to the own settings page. --- src/components/pages/SettingsPage/index.jsx | 79 ++++++++++++--------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/src/components/pages/SettingsPage/index.jsx b/src/components/pages/SettingsPage/index.jsx index 74e27d7..3313200 100644 --- a/src/components/pages/SettingsPage/index.jsx +++ b/src/components/pages/SettingsPage/index.jsx @@ -47,6 +47,7 @@ import "./settings.scss"; */ class SettingsPage extends React.Component { state = { + loading: true, changeDetected: false, showProfilePicture: false, showNotification: false, @@ -63,53 +64,63 @@ class SettingsPage extends React.Component { ], }; + // triggers every time the settings menu tab is pressed componentDidMount = () => { - console.log("XYX"); - // Check for the current values + const { loggedUser } = this.props; + if (!loggedUser.anonymous) { + this.props.readCache(loggedUser.username); + } + }; + + // important for direct url access + componentDidUpdate = () => { const { loggedUser, fetchedUser } = this.props; - const username = loggedUser?.username; - if (username) { - this.props.readCache(username); + if (!fetchedUser && !loggedUser.anonymous) { + this.props.readCache(loggedUser.username); } - const platformData = this.props.fetchedUser?.platformData; + if (fetchedUser && this.state.loading) { + const platformData = this.props.fetchedUser?.platformData; - if (platformData?.profile && platformData?.user) { - const profile = platformData.profile; - const data = platformData.user; - const enterData = { - avatar_url: profile.avatarUrl ? profile.avatarUrl : "", - first_name: data.firstName ? data.firstName : "", - last_name: data.lastName ? data.lastName : "", - email: data.email ? data.email : "", - showEmailPublic: data.settings.showEmailPublic, - company: profile.company ? profile.company : "", - showCompanyPublic: data.settings.showCompanyPublic, - website: profile.websiteUrl ? profile.websiteUrl : "", - location: profile.location ? profile.location : "", - showLocalRanking: data.settings.showLocalRanking, - showTopLanguages: data.settings.showTopLanguages, - show3DDiagram: data.settings.show3DDiagram, - show2DDiagram: data.settings.show2DDiagram, - activeTheme: data.settings.activeTheme - ? data.settings.activeTheme - : null, - }; + if (platformData?.profile && platformData?.user) { + const profile = platformData.profile; + const data = platformData.user; + const enterData = { + avatar_url: profile.avatarUrl ? profile.avatarUrl : "", + first_name: data.firstName ? data.firstName : "", + last_name: data.lastName ? data.lastName : "", + email: data.email ? data.email : "", + showEmailPublic: data.settings.showEmailPublic, + company: profile.company ? profile.company : "", + showCompanyPublic: data.settings.showCompanyPublic, + website: profile.websiteUrl ? profile.websiteUrl : "", + location: profile.location ? profile.location : "", + showLocalRanking: data.settings.showLocalRanking, + showTopLanguages: data.settings.showTopLanguages, + show3DDiagram: data.settings.show3DDiagram, + show2DDiagram: data.settings.show2DDiagram, + activeTheme: data.settings.activeTheme + ? data.settings.activeTheme + : null, + }; - const dataString = this.stringToHash(JSON.stringify(enterData)); + const dataString = this.stringToHash(JSON.stringify(enterData)); - this.setState({ - ...enterData, - checksum: dataString, - }); - } else { - this.initBlank(); + this.setState({ + ...enterData, + checksum: dataString, + loading: false, + }); + } else { + this.initBlank(); + } } }; initBlank = () => { this.setState({ + loading: false, avatar_url: "", first_name: "", last_name: "", From 4d9268d9738c23cd63227c4ec5c93049adf1a9f4 Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 2 Jul 2020 19:22:23 +0200 Subject: [PATCH 19/86] Improve user menu Now when clicking on `My Profile` only the corresponding components are rendered and not longer everyone like before. --- src/components/molecules/Navbar/index.jsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/molecules/Navbar/index.jsx b/src/components/molecules/Navbar/index.jsx index c8371f5..5a99246 100644 --- a/src/components/molecules/Navbar/index.jsx +++ b/src/components/molecules/Navbar/index.jsx @@ -126,9 +126,12 @@ class Navbar extends React.Component { /> - + My profile - + this.setState({ showSettings: true }) From 0332ee55712903436225225045e31b86beefd771 Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 2 Jul 2020 19:27:35 +0200 Subject: [PATCH 20/86] Remove legacy code Due to the switch to Redux, a lot of code is obsolete and is now being removed. --- src/App.js | 323 +--------------------------- src/actions/core.js | 39 ---- src/actions/index.js | 14 -- src/actions/intel/authActions.js | 65 ------ src/actions/intel/generalActions.js | 175 --------------- src/actions/intel/index.js | 40 ---- src/actions/intel/talksActions.js | 133 ------------ src/actions/intel/userActions.js | 250 --------------------- 8 files changed, 3 insertions(+), 1036 deletions(-) delete mode 100644 src/actions/core.js delete mode 100644 src/actions/index.js delete mode 100644 src/actions/intel/authActions.js delete mode 100644 src/actions/intel/generalActions.js delete mode 100644 src/actions/intel/index.js delete mode 100644 src/actions/intel/talksActions.js delete mode 100644 src/actions/intel/userActions.js diff --git a/src/App.js b/src/App.js index 4fbe8cf..cbbcaea 100644 --- a/src/App.js +++ b/src/App.js @@ -4,13 +4,8 @@ import React, { useEffect } from "react"; // DOM bindings for React Router import { withRouter } from "react-router-dom"; -import LoadingBar, { showLoading, resetLoading } from "react-redux-loading-bar"; -//> Additional -// SHA Hashing algorithm -import sha256 from "js-sha256"; -//> MDB -// "Material Design for Bootstrap" is a great UI design framework -import { MDBProgress } from "mdbreact"; +//> Redux +import { useDispatch } from "react-redux"; //> Components /** @@ -22,326 +17,14 @@ import { Footer, Navbar } from "./components/molecules"; import { ScrollToTop } from "./components/atoms"; //> Routes import Routes from "./Routes"; -//> Core -import { ferryIntel } from "./actions"; //> Actions import { loginAction } from "./store/actions/authActions"; -import { - getAllPageUrlsAction, - fetchGitLabServersAction, -} from "./store/actions/generalActions"; -import { readCacheAction } from "./store/actions/userActions"; - -import { - login, - logout, - fetchGitLabServers, - appendSourceObjects, - getAllPageUrls, - getData, - saveSettings, - register, - readCache, - updateCache, - writeCache, - getAllTalks, - getTalk, - uploadTalk, - deleteTalk, -} from "./actions/intel"; -import { useSelector, useDispatch } from "react-redux"; -import { Intel } from "snek-intel"; //#endregion //#region > Components /** * @class Root component which loads all other components */ -// class App extends React.Component { -// state = { -// loggedUser: undefined, -// fetchedUser: undefined, -// loading: true, -// caching: false, -// }; - -// globalFunctions = { -// //> Authentication -// login: async (username, password) => -// this.handleLoginSession({ username, password: sha256(password) }), -// logout: async () => this.handleLogout(), -// //> General -// fetchGitLabServers: async () => ferryIntel(fetchGitLabServers()), -// appendSourceObjects: async (sourceList) => -// ferryIntel(appendSourceObjects(sourceList)), -// users: async () => ferryIntel(getAllPageUrls()), -// saveSettings: async (nextSettings) => this.handleSaveSettings(nextSettings), -// //> User -// updateCache: async (fetchedUser) => this.handleCacheRenewal(fetchedUser), -// writeCache: async (platformData) => ferryIntel(writeCache(platformData)), -// registerUser: async (registrationData) => -// this.handleRegistration(registrationData), -// fetchCacheData: async (username) => this.handleProfileFetching(username), -// //> Talk -// deleteTalk: async (talk) => this.handleTalkDeletion(talk), -// uploadTalk: async (file, talkInfo) => this.handleTalkUpload(file, talkInfo), -// getTalk: (uid, username) => ferryIntel(getTalk(uid, username)), -// //> State checking -// refetchRequired: (username) => this.refetchRequired(username), -// usernameMatchesFetchedUsername: (username) => -// this.usernameMatchesFetchedUsername(username), -// }; - -// componentDidMount = () => { -// // Start a session as anonymous user -// this.handleLoginSession(); -// }; - -// /** -// * Handle login session. -// * -// * @param user A user to login with -// * @description Handles states for login -// */ -// handleLoginSession = async (user) => { -// return ferryIntel(login(user)).then((loggedUser) => { -// if (loggedUser) { -// this.setState({ -// loggedUser, -// loading: false, -// }); -// } else { -// if (this.state.loggedUser !== null) { -// this.setState({ -// loggedUser: null, -// loading: false, -// }); -// } -// } -// }); -// }; - -// /** -// * Handle logout. -// * -// * @description Handles states for logout -// */ -// handleLogout = () => { -// this.setState( -// { -// loggedUser: undefined, -// fetchedUser: undefined, -// loading: false, -// caching: false, -// }, -// () => ferryIntel(logout()).then(() => this.handleLoginSession()) -// ); -// }; - -// /** -// * Handle registration -// * -// * @param registrationData Data to register a user -// * @description Handles states for registration -// */ -// handleRegistration = (registrationData) => { -// ferryIntel(register(registrationData)).then((res) => { -// this.globalFunctions.login(res.username, res.password).then(() => { -// this.globalFunctions.writeCache(registrationData.platform_data); -// this.setState({ caching: true, loading: false }); -// }); -// }); -// }; - -// /** -// * Handle cache renewal. -// * -// * @param fetchedUser A fetched user object -// * @description Handles states for cache renewal -// */ -// handleCacheRenewal = async (fetchedUser) => { -// if ( -// !this.state.caching && -// this.state.loggedUser?.username === fetchedUser?.username -// ) { -// // Renew cache -// const fetchedUser = await ferryIntel(updateCache(fetchedUser)); - -// this.setState({ -// fetchedUser, -// caching: true, -// }); -// } -// }; - -// /** -// * Handle profile fetching. -// * -// * @param username A username to read the cache from -// * @description Handles states for profile fetching -// */ -// handleProfileFetching = async (username) => { -// const fetchedUser = await ferryIntel(readCache(username)); -// // Update visible data -// this.setState({ -// fetchedUser: fetchedUser ? fetchedUser : false, -// loading: false, -// }); -// }; - -// /** -// * Handle talk upload. -// * -// * @param file A file to be uploaded -// * @param talkInfo Additional information to add to the talk -// * @description Handles states for talk uploading -// */ -// handleTalkUpload = async (file, talkInfo) => { -// ferryIntel(uploadTalk(file, talkInfo), { -// currentCache: this.state.fetchedUser.platformData, -// }).then((platformData) => { -// this.setState({ -// fetchedUser: { -// ...this.state.fetchedUser, -// platformData, -// }, -// }); -// }); -// }; - -// /** -// * Handle talk deletion. -// * -// * @param talk A talk that should be deleted -// * @description Handles states for talk deleting -// */ -// handleTalkDeletion = async (talk) => { -// ferryIntel(deleteTalk(talk), { -// currentCache: this.state.fetchedUser.platformData, -// }).then((platformData) => { -// this.setState({ -// fetchedUser: { -// ...this.state.fetchedUser, -// platformData, -// }, -// }); -// }); -// }; - -// /** -// * Handle save settings. -// * -// * @param nextSettings A settings object that should be applied -// * @description Handles states for saving settings -// */ -// handleSaveSettings = async (nextSettings) => { -// ferryIntel(saveSettings(nextSettings), { -// currentCache: this.state.fetchedUser.platformData, -// }).then((platformData) => { -// this.setState({ -// fetchedUser: { -// ...this.state.fetchedUser, -// platformData, -// }, -// }); -// }); -// }; - -// //#region > Refetch Checking -// /** -// * Check for refetch for a specific username. -// * -// * @param {string} username The username associated with a profile page -// * @returns {boolean} True if a refetch is required otherwise False -// */ -// refetchRequired = (username) => { -// const loading = this.state.loading; -// const fetchedUser = this.state.fetchedUser; - -// if (!loading) { -// if (!fetchedUser && fetchedUser !== false) { -// return true; -// } else if ( -// fetchedUser && -// !this.usernameMatchesFetchedUsername(username) -// ) { -// return true; -// } -// return false; -// } -// }; - -// /** -// * Check if the provided username matches with the current fetched user. -// * -// * @param {string} username The username associated with a profile page -// * @returns {boolean} True if the usernames matches otherwise False -// */ -// usernameMatchesFetchedUsername = (username) => { -// return username === this.state.fetchedUser?.username; -// }; -// //#endregion - -// render() { -// return ( -// -//
      -// {!this.state.caching && -// this.state.fetchedUser && -// this.state.loggedUser?.username === -// this.state.fetchedUser.username && ( -// -// )} -// -//
      -// -//
      -//
      -//
      -//
      -// ); -// } -// } -//#endregion - -// function App(params) { -// const loggedUser = useSelector((state) => state.auth.loggedUser); -// const fetchedUser = useSelector((state) => state.user.fetchedUser); - -// const dispatch = useDispatch(); - -// return ( -//
      -// {loggedUser?.username} -// {fetchedUser?.username} -// -// -// -// -//
      -// ); -// } - function App() { const dispatch = useDispatch(); @@ -363,9 +46,9 @@ function App() { ); } +//#endregion //#region > Exports -//> Default Class export default withRouter(App); //#endregion diff --git a/src/actions/core.js b/src/actions/core.js deleted file mode 100644 index ea96736..0000000 --- a/src/actions/core.js +++ /dev/null @@ -1,39 +0,0 @@ -//#region > Imports -//> Intel -import { Intel } from "snek-intel"; -//#endregion - -//#region > Constant Variables -const INTEL = new Intel(); -//#endregion - -//#region > Core -/** - * The intel ferry. - * - * @param actionFn The action to use - * @param args Arguments to use for the action - * @description The intel ferry is used to deliver calls to the SNEK-Intel - */ -const ferryIntel = async (actionFn, args) => { - return actionFn(INTEL, args).then((res) => { - switch (res.errorCode) { - case undefined: - return res; - default: - //#ERROR - console.error(res.message); - return null; - } - }); -}; -//#endregion - -//#region > Exports -export { ferryIntel }; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © 2019-2020 Simon Prast - */ diff --git a/src/actions/index.js b/src/actions/index.js deleted file mode 100644 index a0031ec..0000000 --- a/src/actions/index.js +++ /dev/null @@ -1,14 +0,0 @@ -//#region > Imports -//> Core -import { ferryIntel } from "./core"; -//#endregion - -//#region > Export -//> Core -export { ferryIntel }; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © 2019-2020 Simon Prast - */ diff --git a/src/actions/intel/authActions.js b/src/actions/intel/authActions.js deleted file mode 100644 index 458a84d..0000000 --- a/src/actions/intel/authActions.js +++ /dev/null @@ -1,65 +0,0 @@ -//#region > Authentication -/** - * Handle login - * - * @param user A user to login with - * @description Handles states for login - */ -const login = (user) => { - return async (intel) => { - try { - const session = intel.snekclient.session; - - return await session.begin(user).then((whoami) => { - if (whoami?.username !== process.env.REACT_APP_ANONYMOUS_USER) { - return { - username: whoami.username, - avatarUrl: - "https://www.clipartmax.com/png/full/166-1669056_the-20-cooler-octocat-github-octocat.png", - }; - } else { - return false; - } - }); - } catch (ex) { - return { - errorCode: 600, - message: "Login failed", - raw: ex, - }; - } - }; -}; - -/** - * Logout user. - * - * @description Handles the logging out of active users - */ -const logout = () => { - return async (intel) => { - try { - const session = intel.snekclient.session; - - await session.end(); - - return true; - } catch (ex) { - return { - errorCode: 601, - message: "Logout failed", - raw: ex, - }; - } - }; -}; -//#endregion - -//#region > Exports -export { login, logout }; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © 2019-2020 Simon Prast - */ diff --git a/src/actions/intel/generalActions.js b/src/actions/intel/generalActions.js deleted file mode 100644 index 07b0aed..0000000 --- a/src/actions/intel/generalActions.js +++ /dev/null @@ -1,175 +0,0 @@ -//#region > Registration -/** - * Append Source Objects - * - * @param sourceList A source object - * @description Hands source list over to intel - */ -const appendSourceObjects = (sourceList) => { - return async (intel) => { - try { - return intel.appendList(sourceList); - } catch (ex) { - return { - errorCode: 602, - message: "Appending source objects failed", - raw: ex, - }; - } - }; -}; - -/** - * Fetch GitLab Servers - * - * @description Retrieves a list of available GitLab servers - */ -const fetchGitLabServers = () => { - return async (intel) => { - try { - const session = intel.snekclient.session; - - return session.tasks.general.gitlabServer().then(({ data }) => { - const gitLabServers = data?.page?.supportedGitlabs; - - if (gitLabServers) { - return gitLabServers; - } else { - return false; - } - }); - } catch (ex) { - return { - errorCode: 605, - message: "Fetching GitLab server failed", - raw: ex, - }; - } - }; -}; -//#endregion - -//#region > Data Handling -/** - * Get intel data - * - * @description Retrieves data from current applied source list - */ -const getData = () => { - return async (intel) => { - try { - return intel.get(); - } catch (ex) { - return { - errorCode: 603, - message: "Getting intel data failed", - raw: ex, - }; - } - }; -}; - -/** - * Save settings - * - * @param nextSettings The settings that should be applied - * @description Saves the user settings - */ -const saveSettings = (nextSettings) => { - return async (intel, { currentCache }) => { - try { - const session = intel.snekclient.session; - - // Check for mandatory fields - if (nextSettings.email) { - currentCache.user.firstName = nextSettings.first_name - ? nextSettings.first_name - : ""; - currentCache.user.lastName = nextSettings.last_name - ? nextSettings.last_name - : ""; - currentCache.user.email = nextSettings.email - ? nextSettings.email - : currentCache.user.email; - currentCache.profile.websiteUrl = nextSettings.website - ? nextSettings.website - : ""; - currentCache.profile.location = nextSettings.location - ? nextSettings.location - : ""; - currentCache.profile.company = nextSettings.company - ? nextSettings.company - : ""; - currentCache.user.settings = { - showTopLanguages: nextSettings.showTopLanguages, - showLocalRanking: nextSettings.showLocalRanking, - show3DDiagram: nextSettings.show3DDiagram, - show2DDiagram: nextSettings.show2DDiagram, - showEmailPublic: nextSettings.showEmailPublic, - showCompanyPublic: nextSettings.showCompanyPublic, - activeTheme: nextSettings.activeTheme, - }; - } - - session.tasks.user.cache(JSON.stringify(currentCache)); - - return currentCache; - } catch (ex) { - return { - errorCode: 604, - message: "Saving settings failed", - raw: ex, - }; - } - }; -}; - -/** - * Get all users - * - * @description Retrieves a list of all users - */ -const getAllPageUrls = () => { - return async (intel) => { - try { - const session = intel.snekclient.session; - - return await session.tasks.general.allPageUrls().then((res) => { - let urls = []; - - res.data.pages && - res.data.pages.forEach((page) => { - if (page.urlPath.includes("registration/")) { - let url = page.urlPath.split("/")[2]; - - urls.push(url); - } - }); - - return urls; - }); - } catch (ex) { - return { - errorCode: 616, - message: "Getting all page urls failed", - raw: ex, - }; - } - }; -}; -//#endregion - -//#region > Exports -export { - appendSourceObjects, - getData, - saveSettings, - getAllPageUrls, - fetchGitLabServers, -}; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © 2019-2020 Simon Prast - */ diff --git a/src/actions/intel/index.js b/src/actions/intel/index.js deleted file mode 100644 index 0eadb9e..0000000 --- a/src/actions/intel/index.js +++ /dev/null @@ -1,40 +0,0 @@ -//#region > Imports -//> Intel -// Import all components to export them for easy access from parent components -import { login, logout } from "./authActions"; -import { - fetchGitLabServers, - appendSourceObjects, - getAllPageUrls, - getData, - saveSettings, -} from "./generalActions"; -import { register, readCache, updateCache, writeCache } from "./userActions"; -import { getAllTalks, getTalk, uploadTalk, deleteTalk } from "./talksActions"; -//#endregion - -//#region > Exports -//> Actions -export { - login, - logout, - appendSourceObjects, - getData, - saveSettings, - getAllPageUrls, - fetchGitLabServers, - register, - readCache, - updateCache, - writeCache, - getAllTalks, - getTalk, - uploadTalk, - deleteTalk, -}; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © 2019-2020 Simon Prast - */ diff --git a/src/actions/intel/talksActions.js b/src/actions/intel/talksActions.js deleted file mode 100644 index d6032bb..0000000 --- a/src/actions/intel/talksActions.js +++ /dev/null @@ -1,133 +0,0 @@ -//#region > Talks -/** - * Get all talks. - * - * @description Handles the call for getting all talks. - */ -const getAllTalks = () => { - return async (intel) => { - try { - return intel.getTalks(); - } catch (ex) { - return { - errorCode: 611, - message: "Getting intel talks failed", - raw: ex, - }; - } - }; -}; - -/** - * Get a talk. - * - * @param uid A unique id to find a talk - * @param username A username associated with the talk - * @description Handles the call for getting one specific talk - */ -const getTalk = (uid, username) => { - return async (intel) => { - try { - const session = intel.snekclient.session; - - return session.tasks.user - .profile("/registration/" + username) - .then(async ({ data }) => { - if (data.profile) { - let talks = JSON.parse(data.profile.platformData).talks; - - talks = talks.filter((talk) => { - return talk.uid === uid; - }); - - return talks[0]; - } else { - return { - errorCode: 613, - message: "Cannot get specific talk " + uid, - raw: undefined, - }; - } - }); - } catch (ex) { - return { - errorCode: 614, - message: "Getting talks failed", - raw: ex, - }; - } - }; -}; - -/** - * Upload talk. - * - * @param file A file to be uploaded - * @param talkInfo Additional information to add to the talk - * @description Handles the call for uploading a talk - */ -const uploadTalk = (file, talkInfo) => { - return async (intel, { currentCache }) => { - try { - const session = intel.snekclient.session; - - return intel.appendTalk(file).then(() => { - return intel.getTalks().then((talks) => { - talks[talks.length - 1].repository = talkInfo; - - currentCache.talks.push(talks[talks.length - 1]); - - session.tasks.user.cache(JSON.stringify(currentCache)); - - return currentCache; - }); - }); - } catch (ex) { - return { - errorCode: 612, - message: "Uploading talk failed", - raw: ex, - }; - } - }; -}; - -/** - * Delete talk. - * - * @param talk A talk that should be deleted - * @description Handles the call for deleting a talk. - */ -const deleteTalk = (talk) => { - return async (intel, { currentCache }) => { - try { - const session = intel.snekclient.session; - for (const index in currentCache.talks) { - if (talk.uid === currentCache.talks[index].uid) { - currentCache.talks.splice(index, 1); - } - } - - session.tasks.user.cache(JSON.stringify(currentCache)); - - return currentCache; - } catch (ex) { - return { - errorCode: 615, - message: "Uploading talk failed", - raw: ex, - }; - } - }; -}; -//#endregion - -//#region > Exports -//> Export > Constant Variables -export { getAllTalks, getTalk, uploadTalk, deleteTalk }; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © 2019-2020 Simon Prast - */ diff --git a/src/actions/intel/userActions.js b/src/actions/intel/userActions.js deleted file mode 100644 index 3546321..0000000 --- a/src/actions/intel/userActions.js +++ /dev/null @@ -1,250 +0,0 @@ -//#region > Imports -//> Additional -// SHA Hashing algorithm -import sha256 from "js-sha256"; -//#endregion - -//#region > Register -/** - * Register user. - * - * @param registrationData Data to register a user - * @description Handles the registration of users - */ -const register = (registrationData) => { - return async (intel) => { - try { - const session = intel.snekclient.session; - const clearPassword = registrationData.password; - - // Hash password - registrationData.password = sha256(registrationData.password); - - // Append Source objects - await intel.appendList(registrationData.sources); - // Generate talks based on the previous appended list - await intel.generateTalks(registrationData.sources); - - // Get fresh platform data - const intelData = { - ...(await intel.get()), - talks: await intel.getTalks(), - }; - - // Save Object to platformData as JSON - registrationData.platform_data = JSON.stringify(intelData); - // Create JSON string out of sources for backend use - registrationData.sources = JSON.stringify(registrationData.sources); - - return await session.tasks.user - .registration(registrationData) - .then((res) => { - if (res.result === "FAIL") { - return { - errorCode: 606, - message: "Registration failed due to false registration result", - raw: undefined, - }; - } else { - return { - registrationData, - username: registrationData.username, - password: clearPassword, - }; - } - }); - } catch (ex) { - return { - errorCode: 617, - message: "Registration failed", - raw: ex, - }; - } - }; -}; -//#endregion - -//#region > Caching -/** - * Write cache. - * - * @param platformData A data object to store in cache - * @description Handles the calls for writing to cache - */ -const writeCache = (platformData) => { - return async (intel) => { - try { - const session = intel.snekclient.session; - - return session.tasks.user.cache(platformData); - } catch (ex) { - return { - errorCode: 607, - message: "Writing to cache failed", - raw: ex, - }; - } - }; -}; - -/** - * Read cache. - * - * @param username A username to read the cache from - * @description Handles the calls for reading the cache - */ -const readCache = (username) => { - return async (intel) => { - try { - const session = intel.snekclient.session; - - return session.tasks.user - .profile("/registration/" + username) - .then(async ({ data }) => { - if (!data.profile) { - return { - errorCode: 608, - message: "Cache not loaded", - raw: undefined, - }; - } else { - // Split profile to chunks - const profile = data.profile; - const sources = profile.sources - ? JSON.parse(profile.sources) - : null; - - let platformData = profile.platformData - ? JSON.parse(profile.platformData) - : {}; - - let user = platformData.user ? platformData.user : {}; - - // Check if data is valid - if (!sources) { - return { - errorCode: 609, - message: "Sources are empty", - raw: undefined, - }; - } else { - // Set settings for first time fetching - if (Object.keys(user).length === 0) { - user.firstName = profile.firstName; - user.lastName = profile.lastName; - user.email = profile.email; - } - - if (!user.settings) { - user.settings = { - show3DDiagram: true, - show2DDiagram: true, - showCompanyPublic: true, - showEmailPublic: true, - showLocalRanking: true, - activeTheme: null, - }; - } - - // Build fetchedUser object - let fetchedUser = { - username: profile.username, - platformData: { - ...platformData, - user, - }, - sources, - verified: data.profile.verified, - accessories: { - badges: data.profile.bids - ? JSON.parse(data.profile.bids) - : null, - themes: data.profile.tids - ? JSON.parse(data.profile.tids) - : null, - }, - }; - - return fetchedUser; - } - } - }); - } catch (ex) { - return { - errorCode: 610, - message: "Reading from cache failed", - raw: ex, - }; - } - }; -}; - -/** - * Update cache. - * - * @param fetchedUser A fetched user object - * @description Handles the calls for updating the cache - */ -const updateCache = (fetchedUser) => { - return async (intel) => { - try { - const session = intel.snekclient.session; - - // Appned Source objects - await intel.appendList(fetchedUser.sources); - // Generate talks based on the previous appended list - await intel.generateTalks(fetchedUser.sources); - - // Get fresh platform data - const intelData = { - ...(await intel.get()), - talks: await intel.getTalks(), - }; - - // Fix duplicates - for (const i in intelData.talks) { - let state = true; - - for (const i2 in fetchedUser.platformData.talks) { - if ( - intelData.talks[i].url === fetchedUser.platformData.talks[i2].url - ) { - state = false; - } - } - - if (state) { - fetchedUser.platformData.talks.push(intelData.talks[i]); - } - } - - fetchedUser.platformData = { - ...intelData, - user: fetchedUser.platformData.user, - talks: fetchedUser.platformData.talks, - }; - intel.resetReducer(); - - session.tasks.user.cache(JSON.stringify(fetchedUser.platformData)); - - return fetchedUser; - } catch (ex) { - return { - errorCode: 618, - message: "Updating cache failed", - raw: ex, - }; - } - }; -}; -//#endregion - -//#region > Exports -//> Default Constant Variable -export { register, writeCache, readCache, updateCache }; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © 2019-2020 Simon Prast - */ From 3765de6ae3ff588378cfa17b5cf15e100d609fd6 Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 2 Jul 2020 20:18:20 +0200 Subject: [PATCH 21/86] Improve Redux DevTools integration Now Redux DevTools only applies in development mode. --- src/index.js | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/index.js b/src/index.js index 47098b0..19a143e 100644 --- a/src/index.js +++ b/src/index.js @@ -44,22 +44,27 @@ const getIntel = () => { return INTEL; }; -const STORE = createStore( - rootReducer /* preloadedState, */, - compose( - applyMiddleware( - loadingBarMiddleware(), - thunk.withExtraArgument({ - getIntel, // Intel +const composeEnhancers = + typeof window === "object" && + process.env.NODE_ENV !== "production" && + window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ + ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({ + // Specify extension’s options like name, actionsBlacklist, actionsCreators, serialize... }) - ), - process.env.NODE_ENV !== "production" && - typeof window === "object" && - window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ && - window.__REDUX_DEVTOOLS_EXTENSION__() + : compose; + +const enhancer = composeEnhancers( + applyMiddleware( + loadingBarMiddleware(), + thunk.withExtraArgument({ + getIntel, // Intel + }) ) + // other store enhancers if any ); +const STORE = createStore(rootReducer /* preloadedState, */, enhancer); + // Render the root component to
      ReactDOM.render( From b3165692d0503d315a161ab162f5163ffe899eae Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 2 Jul 2020 20:19:32 +0200 Subject: [PATCH 22/86] Fix syntax error of previous merge The resolving of the merge conflicts went wrong and produced a syntax error which is fixed now. --- src/components/molecules/Navbar/index.jsx | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/components/molecules/Navbar/index.jsx b/src/components/molecules/Navbar/index.jsx index 6387e7d..772e86f 100644 --- a/src/components/molecules/Navbar/index.jsx +++ b/src/components/molecules/Navbar/index.jsx @@ -123,6 +123,12 @@ class Navbar extends React.Component { /> + + My profile + Settings @@ -159,13 +165,6 @@ class Navbar extends React.Component { - - My profile - - Date: Thu, 2 Jul 2020 20:20:27 +0200 Subject: [PATCH 23/86] Conditional Rendering of Talk Interaction Buttons Uploading and deleting of talks is now only possible if a user is signed in and on his profile. --- src/components/organisms/tabs/TalksTab/index.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/organisms/tabs/TalksTab/index.jsx b/src/components/organisms/tabs/TalksTab/index.jsx index b4634e9..6c86591 100644 --- a/src/components/organisms/tabs/TalksTab/index.jsx +++ b/src/components/organisms/tabs/TalksTab/index.jsx @@ -87,7 +87,7 @@ class Talks extends React.Component {

      Talks

      - {loggedUser && ( + {loggedUser.username === fetchedUser.username && ( - {loggedUser && ( + {loggedUser.username === fetchedUser.username && ( this.props.deleteTalk(talk)}> Date: Thu, 2 Jul 2020 21:22:51 +0200 Subject: [PATCH 24/86] Remove init blank Blank initialization was removed because it is no longer needed. --- src/components/pages/SettingsPage/index.jsx | 77 +++++++-------------- 1 file changed, 26 insertions(+), 51 deletions(-) diff --git a/src/components/pages/SettingsPage/index.jsx b/src/components/pages/SettingsPage/index.jsx index 3313200..8cdc437 100644 --- a/src/components/pages/SettingsPage/index.jsx +++ b/src/components/pages/SettingsPage/index.jsx @@ -82,62 +82,37 @@ class SettingsPage extends React.Component { if (fetchedUser && this.state.loading) { const platformData = this.props.fetchedUser?.platformData; + const profile = platformData.profile; + const data = platformData.user; + const enterData = { + avatar_url: profile.avatarUrl ? profile.avatarUrl : "", + first_name: data.firstName ? data.firstName : "", + last_name: data.lastName ? data.lastName : "", + email: data.email ? data.email : "", + showEmailPublic: data.settings.showEmailPublic, + company: profile.company ? profile.company : "", + showCompanyPublic: data.settings.showCompanyPublic, + website: profile.websiteUrl ? profile.websiteUrl : "", + location: profile.location ? profile.location : "", + showLocalRanking: data.settings.showLocalRanking, + showTopLanguages: data.settings.showTopLanguages, + show3DDiagram: data.settings.show3DDiagram, + show2DDiagram: data.settings.show2DDiagram, + activeTheme: data.settings.activeTheme + ? data.settings.activeTheme + : null, + }; - if (platformData?.profile && platformData?.user) { - const profile = platformData.profile; - const data = platformData.user; - const enterData = { - avatar_url: profile.avatarUrl ? profile.avatarUrl : "", - first_name: data.firstName ? data.firstName : "", - last_name: data.lastName ? data.lastName : "", - email: data.email ? data.email : "", - showEmailPublic: data.settings.showEmailPublic, - company: profile.company ? profile.company : "", - showCompanyPublic: data.settings.showCompanyPublic, - website: profile.websiteUrl ? profile.websiteUrl : "", - location: profile.location ? profile.location : "", - showLocalRanking: data.settings.showLocalRanking, - showTopLanguages: data.settings.showTopLanguages, - show3DDiagram: data.settings.show3DDiagram, - show2DDiagram: data.settings.show2DDiagram, - activeTheme: data.settings.activeTheme - ? data.settings.activeTheme - : null, - }; + const dataString = this.stringToHash(JSON.stringify(enterData)); - const dataString = this.stringToHash(JSON.stringify(enterData)); - - this.setState({ - ...enterData, - checksum: dataString, - loading: false, - }); - } else { - this.initBlank(); - } + this.setState({ + ...enterData, + checksum: dataString, + loading: false, + }); } }; - initBlank = () => { - this.setState({ - loading: false, - avatar_url: "", - first_name: "", - last_name: "", - email: "", - showEmailPublic: true, - company: "", - showCompanyPublic: true, - website: "", - location: "", - showLocalRanking: true, - showTopLanguages: true, - show3DDiagram: true, - show2DDiagram: true, - activeTheme: null, - }); - }; - stringToHash = (string) => { let hash = 0; From 46cfbd83a4743c2d0a4489279ec5ad0f40746ac5 Mon Sep 17 00:00:00 2001 From: Pinterid Date: Thu, 2 Jul 2020 21:24:17 +0200 Subject: [PATCH 25/86] Add input value check The check was added to prevent the uncontrolled component warning. --- src/components/pages/SettingsPage/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/pages/SettingsPage/index.jsx b/src/components/pages/SettingsPage/index.jsx index 8cdc437..9840680 100644 --- a/src/components/pages/SettingsPage/index.jsx +++ b/src/components/pages/SettingsPage/index.jsx @@ -221,7 +221,7 @@ class SettingsPage extends React.Component { const { fetchedUser, loggedUser } = this.props; const { activeItem } = this.state; - if (fetchedUser) { + if (fetchedUser && this.state.avatar_url) { return ( <> {this.state.showNotification && ( From 7b1c67a81e634e74437c5270bbb94abd78cd0d91 Mon Sep 17 00:00:00 2001 From: Christian Aichner Date: Thu, 2 Jul 2020 21:40:23 +0200 Subject: [PATCH 26/86] Add Language chart The chart for displaying languages has been added. --- .../atoms/charts/LanguageChart/index.jsx | 68 +++++++++++++++++++ .../atoms/charts/LanguageChart/languages.scss | 27 ++++++++ src/components/atoms/index.js | 2 + 3 files changed, 97 insertions(+) create mode 100644 src/components/atoms/charts/LanguageChart/index.jsx create mode 100644 src/components/atoms/charts/LanguageChart/languages.scss diff --git a/src/components/atoms/charts/LanguageChart/index.jsx b/src/components/atoms/charts/LanguageChart/index.jsx new file mode 100644 index 0000000..8f2009b --- /dev/null +++ b/src/components/atoms/charts/LanguageChart/index.jsx @@ -0,0 +1,68 @@ +//#region > Imports +//> React +// Contains all the functionality necessary to define React components +import React from "react"; + +//> CSS +import "./languages.scss"; +//#endregion + +//#region > Components +/** + * @class A week calendar which compares the contributions of a selectable week + * with the current week. + */ +class LatestActivity extends React.Component { + state = {}; + + renderBars = (languages) => { + let latest = 0; + + return languages.map((language, i) => { + const { color, share } = language; + const value = latest + share; + + latest += share; + + return ( +
      + ); + }); + }; + + render() { + const { languages, height } = this.props; + + if (languages) { + return ( +
      + {this.renderBars(languages)} +
      + ); + } else { + return null; + } + } +} +//#endregion + +//#region > Exports +//> Default Class +export default LatestActivity; +//#endregion + +/** + * SPDX-License-Identifier: (EUPL-1.2) + * Copyright © 2019-2020 Simon Prast + */ diff --git a/src/components/atoms/charts/LanguageChart/languages.scss b/src/components/atoms/charts/LanguageChart/languages.scss new file mode 100644 index 0000000..41611c7 --- /dev/null +++ b/src/components/atoms/charts/LanguageChart/languages.scss @@ -0,0 +1,27 @@ +.languages { + width: "100%"; + background-color: "#e0e0de"; + margin: 0.3rem 0; + position: relative; + transition: height 0.2s ease; + .filler { + height: 100%; + border-radius: inherit; + text-align: right; + position: absolute; + &:last-child { + border-top-right-radius: 0.3rem; + border-bottom-right-radius: 0.3rem; + } + border-top-left-radius: 0.3rem; + border-bottom-left-radius: 0.3rem; + } + /*&:hover { + height: 30px; + }*/ +} + +/** + * SPDX-License-Identifier: (EUPL-1.2) + * Copyright © 2019-2020 Simon Prast + */ diff --git a/src/components/atoms/index.js b/src/components/atoms/index.js index b9e0f83..1267356 100644 --- a/src/components/atoms/index.js +++ b/src/components/atoms/index.js @@ -10,6 +10,7 @@ import Calendar2D from "./charts/Calendar2D"; import Calendar3D from "./charts/Calendar3D"; import ContribRadar from "./charts/ContribRadar"; import LatestActivity from "./charts/LatestActivity"; +import LanguageChart from "./charts/LanguageChart"; //> General import SearchBar from "./SearchBar"; import ErrorBoundary from "./ErrorBoundary"; @@ -25,6 +26,7 @@ export { Calendar3D, ContribRadar, LatestActivity, + LanguageChart, SearchBar, ErrorBoundary, }; From 94424101298e09da5e3aa775741d6c6ae70354af Mon Sep 17 00:00:00 2001 From: Christian Aichner Date: Thu, 2 Jul 2020 21:40:46 +0200 Subject: [PATCH 27/86] Improve projects The project component has been improved and now actually looks nice. --- src/components/atoms/Project/index.jsx | 33 +++++++++++++------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/components/atoms/Project/index.jsx b/src/components/atoms/Project/index.jsx index 59a6fb9..332f620 100644 --- a/src/components/atoms/Project/index.jsx +++ b/src/components/atoms/Project/index.jsx @@ -6,7 +6,9 @@ import React from "react"; import PropTypes from "prop-types"; //> MDB // "Material Design for Bootstrap" is a great UI design framework -import { MDBCol, MDBIcon } from "mdbreact"; +import { MDBCol, MDBIcon, MDBProgress } from "mdbreact"; +//> Components +import { LanguageChart } from "../../atoms"; //#endregion //#region > Components @@ -20,30 +22,29 @@ class Project extends React.Component {
    • -

      - {repo.name.length > 25 - ? repo.name.substring(0, 25) + "..." - : repo.name} -

      +

      {repo.name.split("/")[1]}

      +
      +
      + {repo.name} + /{repo.owner.username} +
      +
      + {repo.languages.length > 0 && ( + + )} {repo.languages.length > 0 && ( - + - {repo.languages[0].name} + {repo.languages[0].name + ? repo.languages[0].name + : "NO LANAGUESES AVAILIAVBLE"} )}
      -
      -
      - {repo.name} - Owned by {repo.owner.username} -
      -
      - -
    • From 475eea33852caa4986bd1cb185d38dc054bf2174 Mon Sep 17 00:00:00 2001 From: Christian Aichner Date: Thu, 2 Jul 2020 21:41:05 +0200 Subject: [PATCH 28/86] Improve profile info The language chart and top languages have been implemented. --- .../organisms/ProfileInfo/index.jsx | 57 +++++++++++++++++-- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/src/components/organisms/ProfileInfo/index.jsx b/src/components/organisms/ProfileInfo/index.jsx index c291ec2..f6dc821 100644 --- a/src/components/organisms/ProfileInfo/index.jsx +++ b/src/components/organisms/ProfileInfo/index.jsx @@ -15,13 +15,16 @@ import { MDBIcon, MDBTooltip, } from "mdbreact"; +//> Redux import { connect } from "react-redux"; +//> Components +import { LanguageChart } from "../../atoms"; //#endregion //#region > Components /** @class This component displays personal information and status of a user */ class ProfileInfo extends React.Component { - state = {}; + state = { limitLanguages: true }; componentDidMount = () => { const { fetchedUser } = this.props; @@ -289,11 +292,53 @@ class ProfileInfo extends React.Component { )}
    )} -
    -

    Top languages

    -
    -

    Language Chart

    -
    + {fetchedUser.platformData?.statistic?.languages?.length > 0 && ( +
    +
    +

    Top languages

    + + {fetchedUser.platformData.statistic.languages + .slice( + 0, + this.state.limitLanguages + ? 3 + : fetchedUser.platformData.statistic.languages.length - 1 + ) + .map((language, i) => { + return ( + +
    +
    + + {language.name} +
    + + {language.share}% + +
    +
    + ); + })} + {this.state.limitLanguages && + fetchedUser.platformData.statistic.languages.length > 3 && ( +

    this.setState({ limitLanguages: false })} + > + Show more +

    + )} +
    + )}
    ); From 3fb02d6c7b724a0b9d1456f1de9f9d78830b6e63 Mon Sep 17 00:00:00 2001 From: Christian Aichner Date: Thu, 2 Jul 2020 21:41:18 +0200 Subject: [PATCH 29/86] Disable pinned The pinned posts have been temporarily disabled. --- src/components/organisms/tabs/OverviewTab/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/organisms/tabs/OverviewTab/index.jsx b/src/components/organisms/tabs/OverviewTab/index.jsx index ba8d8fb..940d88c 100644 --- a/src/components/organisms/tabs/OverviewTab/index.jsx +++ b/src/components/organisms/tabs/OverviewTab/index.jsx @@ -93,7 +93,7 @@ class OverviewTab extends React.Component { })}
    )} - {true && ( + {false && ( <> From 808753eb8abb293ebfe8e643a55a961d91c22b02 Mon Sep 17 00:00:00 2001 From: Pinterid Date: Thu, 2 Jul 2020 22:37:12 +0200 Subject: [PATCH 30/86] Update autch actions The auth actions errors were updated. --- src/store/actions/authActions.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/store/actions/authActions.js b/src/store/actions/authActions.js index ebe912b..83834dd 100644 --- a/src/store/actions/authActions.js +++ b/src/store/actions/authActions.js @@ -39,10 +39,16 @@ const loginAction = (user) => { } }) .catch((ex) => - dispatch({ type: "LOGIN_ERROR", payload: { error: ex } }) + dispatch({ + type: "LOGIN_FAILED", + payload: { + errorCode: 619, + message: "Login failed invalid credentials", + error: ex, + }, + }) ); } catch (ex) { - console.log("ERRORRR"); dispatch({ type: "LOGIN_ERROR", payload: { errorCode: 600, message: "Login failed", error: ex }, From 245eecfc065d838188cb111e8641ad72c7ddb3a3 Mon Sep 17 00:00:00 2001 From: Pinterid Date: Thu, 2 Jul 2020 22:37:56 +0200 Subject: [PATCH 31/86] Update login form errors The login form errors were updated. --- src/components/molecules/forms/LoginForm/index.jsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/molecules/forms/LoginForm/index.jsx b/src/components/molecules/forms/LoginForm/index.jsx index 2d2b69f..a64a660 100644 --- a/src/components/molecules/forms/LoginForm/index.jsx +++ b/src/components/molecules/forms/LoginForm/index.jsx @@ -21,6 +21,7 @@ class LoginForm extends React.Component { state = { login_username: "", login_password: "", + loginFail: false, }; testForError = (id) => { @@ -129,10 +130,10 @@ class LoginForm extends React.Component { //#TSID6 //console.log("LOGIN FORM PROCEED TO LOGIN", result); - - if (result) { + if (result.payload.error) { this.setState({ - loginFail: false, + loginFail: true, + errorMsg: result.payload.message, }); } } @@ -152,7 +153,7 @@ class LoginForm extends React.Component {

    Login to SNEK

    {this.state.loginFail && ( - Can not perform login. Please check your username and password. + {this.state.errorMsg} )}
    From 971d3ae05f12e3e4ed65ae852cd650c40a2ceb79 Mon Sep 17 00:00:00 2001 From: schettn Date: Sun, 5 Jul 2020 00:04:48 +0200 Subject: [PATCH 32/86] Add Default Project Avatar When there is no image available for a project, a default image is set. --- src/components/atoms/Project/index.jsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/atoms/Project/index.jsx b/src/components/atoms/Project/index.jsx index 332f620..70a33f3 100644 --- a/src/components/atoms/Project/index.jsx +++ b/src/components/atoms/Project/index.jsx @@ -25,7 +25,13 @@ class Project extends React.Component {

    {repo.name.split("/")[1]}

    - {repo.name} + /{repo.owner.username}
    From 31ac93461b2b8a03ac3f08593ee0052a4335cd44 Mon Sep 17 00:00:00 2001 From: schettn Date: Sun, 5 Jul 2020 00:06:34 +0200 Subject: [PATCH 33/86] Improve Default Major Language Name The default text has been adjusted cause of the suck-level of the previous one. --- src/components/atoms/Project/index.jsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/atoms/Project/index.jsx b/src/components/atoms/Project/index.jsx index 70a33f3..66cd600 100644 --- a/src/components/atoms/Project/index.jsx +++ b/src/components/atoms/Project/index.jsx @@ -45,9 +45,7 @@ class Project extends React.Component { className="pr-1" style={{ color: repo.languages[0].color }} /> - {repo.languages[0].name - ? repo.languages[0].name - : "NO LANAGUESES AVAILIAVBLE"} + {repo.languages[0].name ? repo.languages[0].name : "none"} )}
    From cc4b97b13c0c028609c1995ce93b9064201da316 Mon Sep 17 00:00:00 2001 From: schettn Date: Sun, 5 Jul 2020 00:08:46 +0200 Subject: [PATCH 34/86] Add Todo To LanguageChart Component A todo has been added. It includes renaming of component and descriptions due to a copy paste issue... --- src/components/atoms/charts/LanguageChart/index.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/atoms/charts/LanguageChart/index.jsx b/src/components/atoms/charts/LanguageChart/index.jsx index 8f2009b..e07649a 100644 --- a/src/components/atoms/charts/LanguageChart/index.jsx +++ b/src/components/atoms/charts/LanguageChart/index.jsx @@ -9,6 +9,8 @@ import "./languages.scss"; //#region > Components /** + * @todo The namings of the component and the description does not fit the + * actual usecase. * @class A week calendar which compares the contributions of a selectable week * with the current week. */ From bc8c9f8a858bac29ba1941bed45a54a2f022ae86 Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 6 Jul 2020 11:37:26 +0200 Subject: [PATCH 35/86] Update SignIn Error Message The message have been refined cause the old one was a bit shitty. --- src/store/actions/authActions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/store/actions/authActions.js b/src/store/actions/authActions.js index 83834dd..1952aae 100644 --- a/src/store/actions/authActions.js +++ b/src/store/actions/authActions.js @@ -43,7 +43,7 @@ const loginAction = (user) => { type: "LOGIN_FAILED", payload: { errorCode: 619, - message: "Login failed invalid credentials", + message: "Incorrect username or password", error: ex, }, }) From b8a022c978b2541f0822a185b6e3ba18ec10e527 Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 6 Jul 2020 11:38:46 +0200 Subject: [PATCH 36/86] Add Redirect to Homepage in Settings page for unlogged users Now when a anonymous user visits the settings page he is redirected to the homepage with active login form. --- src/components/pages/SettingsPage/index.jsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/pages/SettingsPage/index.jsx b/src/components/pages/SettingsPage/index.jsx index 9840680..d9c1076 100644 --- a/src/components/pages/SettingsPage/index.jsx +++ b/src/components/pages/SettingsPage/index.jsx @@ -69,6 +69,13 @@ class SettingsPage extends React.Component { const { loggedUser } = this.props; if (!loggedUser.anonymous) { this.props.readCache(loggedUser.username); + } else { + this.props.history.push({ + pathname: "/", + state: { + actionCard: 1, + }, + }); } }; From ac82913df9297be8943563083a87a45c26eccb0a Mon Sep 17 00:00:00 2001 From: Pinterid Date: Mon, 6 Jul 2020 12:57:54 +0200 Subject: [PATCH 37/86] Fix Codacy Issues marked by Codacy were resolved. --- .../atoms/charts/LanguageChart/languages.scss | 5 +- .../modals/ProfilePictureModal/profile.scss | 29 ++-- .../pages/SettingsPage/settings.scss | 144 +++++++++--------- 3 files changed, 87 insertions(+), 91 deletions(-) diff --git a/src/components/atoms/charts/LanguageChart/languages.scss b/src/components/atoms/charts/LanguageChart/languages.scss index 41611c7..521cc7a 100644 --- a/src/components/atoms/charts/LanguageChart/languages.scss +++ b/src/components/atoms/charts/LanguageChart/languages.scss @@ -4,11 +4,13 @@ margin: 0.3rem 0; position: relative; transition: height 0.2s ease; + .filler { height: 100%; border-radius: inherit; text-align: right; position: absolute; + &:last-child { border-top-right-radius: 0.3rem; border-bottom-right-radius: 0.3rem; @@ -16,9 +18,6 @@ border-top-left-radius: 0.3rem; border-bottom-left-radius: 0.3rem; } - /*&:hover { - height: 30px; - }*/ } /** diff --git a/src/components/molecules/modals/ProfilePictureModal/profile.scss b/src/components/molecules/modals/ProfilePictureModal/profile.scss index 0041e7b..b176c61 100644 --- a/src/components/molecules/modals/ProfilePictureModal/profile.scss +++ b/src/components/molecules/modals/ProfilePictureModal/profile.scss @@ -21,20 +21,19 @@ width: 100%; height: 8.4px; cursor: pointer; - animate: 0.2s; - box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; + box-shadow: 1 1 1 #000, 0 0 1 #0d0d0d; background: #77bd43; border-radius: 1.3px; border: 0.2px solid #010101; } input[type=range]::-webkit-slider-thumb { - box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; - border: 1px solid #000000; + box-shadow: 1 1 1 #000, 0 0 1 #0d0d0d; + border: 1px solid #000; height: 20px; width: 16px; border-radius: 3px; - background: #ffffff; + background: #fff; cursor: pointer; -webkit-appearance: none; margin-top: -7px; @@ -48,20 +47,19 @@ width: 100%; height: 8.4px; cursor: pointer; - animate: 0.2s; - box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; + box-shadow: 1 1 1 #000, 0 0 1 #0d0d0d; background: #77bd43; border-radius: 1.3px; border: 0.2px solid #010101; } input[type=range]::-moz-range-thumb { - box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; - border: 1px solid #000000; + box-shadow: 1 1 1 #000, 0 0 1 #0d0d0d; + border: 1px solid #000; height: 36px; width: 16px; border-radius: 3px; - background: #ffffff; + background: #fff; cursor: pointer; } @@ -69,7 +67,6 @@ width: 100%; height: 8.4px; cursor: pointer; - animate: 0.2s; background: transparent; border-color: transparent; border-width: 16px 0; @@ -80,23 +77,23 @@ background: #77bd43; border: 0.2px solid #010101; border-radius: 2.6px; - box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; + box-shadow: 1 1 1 #000, 0 0 1 #0d0d0d; } input[type=range]::-ms-fill-upper { background: #77bd43; border: 0.2px solid #010101; border-radius: 2.6px; - box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; + box-shadow: 1 1 1 #000, 0 0 1 #0d0d0d; } input[type=range]::-ms-thumb { - box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; - border: 1px solid #000000; + box-shadow: 1 1 1 #000, 0 0 1 #0d0d0d; + border: 1px solid #000; height: 36px; width: 16px; border-radius: 3px; - background: #ffffff; + background: #fff; cursor: pointer; } diff --git a/src/components/pages/SettingsPage/settings.scss b/src/components/pages/SettingsPage/settings.scss index e94dd8c..7a4b244 100644 --- a/src/components/pages/SettingsPage/settings.scss +++ b/src/components/pages/SettingsPage/settings.scss @@ -1,90 +1,90 @@ #settings { - padding: 2%; + padding: 2%; - .nav-item { - padding: 0; + .tab-content { + padding: 0; + text-align: left; - img { - width: 50px; - height: 50px; - border-radius: 50%; - } + .font-weight-bold { + margin-bottom: 0.4rem; + padding-bottom: 0; + border-bottom: 3px #77bd43 solid; + display: inline-block; + margin-top: 1rem; + } + } - .profile { - padding-left: 2%; - padding-bottom: 5%; + .nav-item { + padding: 0; - .font-weight-bold { - margin-bottom: -3%; - } - } - } - - .pills-primary .nav-link { - background-color: darken(#fff, 2%) !important; - border-color: #77bd43; - padding-top: 1rem; - padding-bottom: 1rem; - color: #212529; - text-align: left; - box-shadow: none; - - i { - padding-left: 0.5rem; - } - - &:hover { - background-color: darken(#fff, 5%) !important; - } - - &.active { - background-color: darken(#fff, 10%) !important; - border-left: 5px #77bd43 solid; - } + img { + width: 50px; + height: 50px; + border-radius: 50%; } - - .tab-content { - padding: 0; - text-align: left; - - .font-weight-bold { - margin-bottom: 0.4rem; - padding-bottom: 0; - border-bottom: 3px #77bd43 solid; - display: inline-block; - margin-top: 1rem; - } + + .profile { + padding-left: 2%; + padding-bottom: 5%; + + .font-weight-bold { + margin-bottom: -3%; + } } - - .form-check-input[type="checkbox"].filled-in:checked + label::after, - label.btn input[type="checkbox"].filled-in:checked + label::after { - background-color: #77bd43; - border: 2px solid #77bd43; + } + + .pills-primary .nav-link { + background-color: darken(#fff, 2%) !important; + border-color: #77bd43; + padding-top: 1rem; + padding-bottom: 1rem; + color: #212529; + text-align: left; + box-shadow: none; + + i { + padding-left: 0.5rem; } - - .personal-data { - .form-check { - padding-left: 0 !important; - margin-top: 0.4rem; - } + + &:hover { + background-color: darken(#fff, 5%) !important; } - - .avatar{ - height: 150px; - width: 150px; - background: white; + + &.active { + background-color: darken(#fff, 10%) !important; + border-left: 5px #77bd43 solid; } } - #notification { - background-color: rgba($color: #77bd43, $alpha: 0.5); - color: black; + .form-check-input[type="checkbox"].filled-in:checked + label::after, + label.btn input[type="checkbox"].filled-in:checked + label::after { + background-color: #77bd43; + border: 2px solid #77bd43; + } - .message { - padding-top: 1.5%; - padding-bottom: 1.5%; + .personal-data { + .form-check { + padding-left: 0 !important; + margin-top: 0.4rem; } } + + .avatar { + height: 150px; + width: 150px; + background: white; + } +} + +#notification { + background-color: rgba($color: #77bd43, $alpha: 0.5); + color: black; + + .message { + padding-top: 1.5%; + padding-bottom: 1.5%; + } +} /** * SPDX-License-Identifier: (EUPL-1.2) From 1707c85535824ed95b20cc327bf878532e9a1e45 Mon Sep 17 00:00:00 2001 From: Pinterid Date: Mon, 6 Jul 2020 13:02:56 +0200 Subject: [PATCH 38/86] Fix Codacy Issues marked by Codacy were resolved. --- .../pages/SettingsPage/settings.scss | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/components/pages/SettingsPage/settings.scss b/src/components/pages/SettingsPage/settings.scss index 7a4b244..ea1257b 100644 --- a/src/components/pages/SettingsPage/settings.scss +++ b/src/components/pages/SettingsPage/settings.scss @@ -18,18 +18,18 @@ padding: 0; img { - width: 50px; - height: 50px; - border-radius: 50%; + width: 50px; + height: 50px; + border-radius: 50%; } .profile { - padding-left: 2%; - padding-bottom: 5%; + padding-left: 2%; + padding-bottom: 5%; - .font-weight-bold { - margin-bottom: -3%; - } + .font-weight-bold { + margin-bottom: -3%; + } } } @@ -85,9 +85,8 @@ padding-bottom: 1.5%; } } - - /** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © 2019-2020 Simon Prast - */ - \ No newline at end of file + +/** + * SPDX-License-Identifier: (EUPL-1.2) + * Copyright © 2019-2020 Simon Prast + */ From 05062587cc794e38f4b8d5de28a7e1de6119b7eb Mon Sep 17 00:00:00 2001 From: Pinterid Date: Mon, 6 Jul 2020 14:13:57 +0200 Subject: [PATCH 39/86] Fix Codacy Codacy errors were fixed. --- src/components/atoms/charts/LanguageChart/languages.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/atoms/charts/LanguageChart/languages.scss b/src/components/atoms/charts/LanguageChart/languages.scss index 521cc7a..dd3fc01 100644 --- a/src/components/atoms/charts/LanguageChart/languages.scss +++ b/src/components/atoms/charts/LanguageChart/languages.scss @@ -15,6 +15,7 @@ border-top-right-radius: 0.3rem; border-bottom-right-radius: 0.3rem; } + border-top-left-radius: 0.3rem; border-bottom-left-radius: 0.3rem; } From 17db5626ff31bdad9beb183f4e491a269084a042 Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 6 Jul 2020 14:44:40 +0200 Subject: [PATCH 40/86] Move Changeable Content to User Section Previously some data was stored in the profile section. Therefore when adjusting data in settings it got overwritten during a refetch. By moving this data to user section it does not get overwritten anymore. --- .../modals/TalkUploadModal/index.jsx | 2 +- .../organisms/ProfileInfo/index.jsx | 6 +++--- src/components/pages/SettingsPage/index.jsx | 9 ++++----- src/store/actions/userActions.js | 20 +++++++++++-------- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/components/molecules/modals/TalkUploadModal/index.jsx b/src/components/molecules/modals/TalkUploadModal/index.jsx index b434b09..2177f38 100644 --- a/src/components/molecules/modals/TalkUploadModal/index.jsx +++ b/src/components/molecules/modals/TalkUploadModal/index.jsx @@ -34,7 +34,7 @@ class TalkUploadModal extends React.Component { globalFunctions .uploadTalk(files[0], { - avatarUrl: globalState.fetchedUser.platformData.profile.avatarUrl, + avatarUrl: globalState.fetchedUser.platformData.user.avatarUrl, owner: { username: globalState.loggedUser.username, }, diff --git a/src/components/organisms/ProfileInfo/index.jsx b/src/components/organisms/ProfileInfo/index.jsx index f6dc821..ba3b3dc 100644 --- a/src/components/organisms/ProfileInfo/index.jsx +++ b/src/components/organisms/ProfileInfo/index.jsx @@ -62,7 +62,7 @@ class ProfileInfo extends React.Component { @@ -86,12 +86,12 @@ class ProfileInfo extends React.Component {

    )} - {fetchedUser && fetchedUser.platformData.profile.company && ( + {fetchedUser && fetchedUser.platformData.user.company && ( <> {fetchedUser && fetchedUser.platformData.user.settings.showCompanyPublic && ( - {fetchedUser.platformData.profile.company} + {fetchedUser.platformData.user.company} )} diff --git a/src/components/pages/SettingsPage/index.jsx b/src/components/pages/SettingsPage/index.jsx index d9c1076..96abd08 100644 --- a/src/components/pages/SettingsPage/index.jsx +++ b/src/components/pages/SettingsPage/index.jsx @@ -89,18 +89,17 @@ class SettingsPage extends React.Component { if (fetchedUser && this.state.loading) { const platformData = this.props.fetchedUser?.platformData; - const profile = platformData.profile; const data = platformData.user; const enterData = { - avatar_url: profile.avatarUrl ? profile.avatarUrl : "", + avatar_url: data.avatarUrl ? data.avatarUrl : "", first_name: data.firstName ? data.firstName : "", last_name: data.lastName ? data.lastName : "", email: data.email ? data.email : "", showEmailPublic: data.settings.showEmailPublic, - company: profile.company ? profile.company : "", + company: data.company ? data.company : "", showCompanyPublic: data.settings.showCompanyPublic, - website: profile.websiteUrl ? profile.websiteUrl : "", - location: profile.location ? profile.location : "", + website: data.websiteUrl ? data.websiteUrl : "", + location: data.location ? data.location : "", showLocalRanking: data.settings.showLocalRanking, showTopLanguages: data.settings.showTopLanguages, show3DDiagram: data.settings.show3DDiagram, diff --git a/src/store/actions/userActions.js b/src/store/actions/userActions.js index 3df3670..d71c058 100644 --- a/src/store/actions/userActions.js +++ b/src/store/actions/userActions.js @@ -163,10 +163,14 @@ const readCacheAction = (username) => { }); } else { // Set settings for first time fetching - if (Object.keys(user).length === 0) { - user.firstName = profile.firstName; - user.lastName = profile.lastName; - user.email = profile.email; + if (Object.keys(user).length === 0 || true) { + user.firstName = platformData.profile.firstName; + user.lastName = platformData.profile.lastName; + user.email = platformData.profile.email; + user.avatarUrl = platformData.profile.avatarUrl; + user.websiteUrl = platformData.profile.websiteUrl; + user.location = platformData.profile.location; + user.company = platformData.profile.company; } if (!user.settings) { @@ -314,7 +318,7 @@ const saveSettingsActions = (nextSettings) => { if (fetchedUser.platformData) { // Check for mandatory fields if (nextSettings.email) { - fetchedUser.platformData.profile.avatarUrl = nextSettings.avatar_url + fetchedUser.platformData.user.avatarUrl = nextSettings.avatar_url ? nextSettings.avatar_url : ""; fetchedUser.platformData.user.firstName = nextSettings.first_name @@ -326,13 +330,13 @@ const saveSettingsActions = (nextSettings) => { fetchedUser.platformData.user.email = nextSettings.email ? nextSettings.email : fetchedUser.platformData.user.email; - fetchedUser.platformData.profile.websiteUrl = nextSettings.website + fetchedUser.platformData.user.websiteUrl = nextSettings.website ? nextSettings.website : ""; - fetchedUser.platformData.profile.location = nextSettings.location + fetchedUser.platformData.user.location = nextSettings.location ? nextSettings.location : ""; - fetchedUser.platformData.profile.company = nextSettings.company + fetchedUser.platformData.user.company = nextSettings.company ? nextSettings.company : ""; fetchedUser.platformData.user.settings = { From 52b81f9ae6eb6466f616236e77b0172e8f2faec1 Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 6 Jul 2020 14:45:43 +0200 Subject: [PATCH 41/86] Add Optional Chaining to Login Result Now when the result is undefined nothing happens cause there is no error. --- src/components/molecules/forms/LoginForm/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/molecules/forms/LoginForm/index.jsx b/src/components/molecules/forms/LoginForm/index.jsx index a64a660..769e3c2 100644 --- a/src/components/molecules/forms/LoginForm/index.jsx +++ b/src/components/molecules/forms/LoginForm/index.jsx @@ -130,7 +130,7 @@ class LoginForm extends React.Component { //#TSID6 //console.log("LOGIN FORM PROCEED TO LOGIN", result); - if (result.payload.error) { + if (result?.payload.error) { this.setState({ loginFail: true, errorMsg: result.payload.message, From d80c7155ae8685617c0eebbaa809bfb58344961b Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 6 Jul 2020 15:03:10 +0200 Subject: [PATCH 42/86] Fix Redirect to Homepage in Settings Page There was an error where it always redirected if the settings url was entered directly. This issue is fixed now, --- src/components/pages/SettingsPage/index.jsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/components/pages/SettingsPage/index.jsx b/src/components/pages/SettingsPage/index.jsx index 96abd08..4ffdf0a 100644 --- a/src/components/pages/SettingsPage/index.jsx +++ b/src/components/pages/SettingsPage/index.jsx @@ -67,9 +67,18 @@ class SettingsPage extends React.Component { // triggers every time the settings menu tab is pressed componentDidMount = () => { const { loggedUser } = this.props; + if (!loggedUser.anonymous) { this.props.readCache(loggedUser.username); - } else { + } + }; + + // important for direct url access + componentDidUpdate = () => { + const { loggedUser, fetchedUser } = this.props; + + // redirect to root if the loggedUser is anonymous + if (loggedUser.anonymous) { this.props.history.push({ pathname: "/", state: { @@ -77,11 +86,6 @@ class SettingsPage extends React.Component { }, }); } - }; - - // important for direct url access - componentDidUpdate = () => { - const { loggedUser, fetchedUser } = this.props; if (!fetchedUser && !loggedUser.anonymous) { this.props.readCache(loggedUser.username); From 72aeebe135ec8e1dd48a0cb955ffa96651c8393d Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 6 Jul 2020 15:03:55 +0200 Subject: [PATCH 43/86] Remove Workaround There was a workaround to update user settings. This is removed now because it resets the user data every read cache iteration. --- src/store/actions/userActions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/store/actions/userActions.js b/src/store/actions/userActions.js index d71c058..208651f 100644 --- a/src/store/actions/userActions.js +++ b/src/store/actions/userActions.js @@ -163,7 +163,7 @@ const readCacheAction = (username) => { }); } else { // Set settings for first time fetching - if (Object.keys(user).length === 0 || true) { + if (Object.keys(user).length === 0) { user.firstName = platformData.profile.firstName; user.lastName = platformData.profile.lastName; user.email = platformData.profile.email; From 0f41ce0c25ff6b39d6917e54eccad623b09df814 Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 6 Jul 2020 15:58:29 +0200 Subject: [PATCH 44/86] Update LanguageChart Namings Issues which occurred due to copy past errors are fixed now. This includes new naming and descriptions. --- .../charts/{LanguageChart => LanguageBar}/index.jsx | 10 +++------- .../{LanguageChart => LanguageBar}/languages.scss | 0 src/components/atoms/index.js | 2 +- 3 files changed, 4 insertions(+), 8 deletions(-) rename src/components/atoms/charts/{LanguageChart => LanguageBar}/index.jsx (78%) rename src/components/atoms/charts/{LanguageChart => LanguageBar}/languages.scss (100%) diff --git a/src/components/atoms/charts/LanguageChart/index.jsx b/src/components/atoms/charts/LanguageBar/index.jsx similarity index 78% rename from src/components/atoms/charts/LanguageChart/index.jsx rename to src/components/atoms/charts/LanguageBar/index.jsx index e07649a..f3c2261 100644 --- a/src/components/atoms/charts/LanguageChart/index.jsx +++ b/src/components/atoms/charts/LanguageBar/index.jsx @@ -9,12 +9,9 @@ import "./languages.scss"; //#region > Components /** - * @todo The namings of the component and the description does not fit the - * actual usecase. - * @class A week calendar which compares the contributions of a selectable week - * with the current week. + * @class A language chart which contains several items with their shares. */ -class LatestActivity extends React.Component { +class LanguageBar extends React.Component { state = {}; renderBars = (languages) => { @@ -60,8 +57,7 @@ class LatestActivity extends React.Component { //#endregion //#region > Exports -//> Default Class -export default LatestActivity; +export default LanguageBar; //#endregion /** diff --git a/src/components/atoms/charts/LanguageChart/languages.scss b/src/components/atoms/charts/LanguageBar/languages.scss similarity index 100% rename from src/components/atoms/charts/LanguageChart/languages.scss rename to src/components/atoms/charts/LanguageBar/languages.scss diff --git a/src/components/atoms/index.js b/src/components/atoms/index.js index 1267356..0b72d1f 100644 --- a/src/components/atoms/index.js +++ b/src/components/atoms/index.js @@ -10,7 +10,7 @@ import Calendar2D from "./charts/Calendar2D"; import Calendar3D from "./charts/Calendar3D"; import ContribRadar from "./charts/ContribRadar"; import LatestActivity from "./charts/LatestActivity"; -import LanguageChart from "./charts/LanguageChart"; +import LanguageChart from "./charts/LanguageBar"; //> General import SearchBar from "./SearchBar"; import ErrorBoundary from "./ErrorBoundary"; From daeb624b7f645b7d72acbe3bc2725cd94346c36c Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 6 Jul 2020 16:32:29 +0200 Subject: [PATCH 45/86] Improve Import and Export Regions The cleanliness of import and export region was not sufficient and was therefore improved. --- src/App.js | 4 ++-- src/components/atoms/Project/index.jsx | 3 ++- src/components/atoms/SearchBar/index.jsx | 15 +++++++-------- src/components/atoms/charts/LanguageBar/index.jsx | 1 + src/components/molecules/Navbar/index.jsx | 13 ++++++++----- src/components/molecules/UserActionCard/index.jsx | 2 -- .../molecules/forms/LoginForm/index.jsx | 13 +++++++++---- .../molecules/forms/RegisterForm/index.jsx | 9 +++++++-- src/components/organisms/ProfileInfo/index.jsx | 3 +++ src/components/organisms/SoftwareTabs/index.jsx | 6 +++++- src/components/organisms/tabs/TalksTab/index.jsx | 10 +++++++--- src/components/pages/HomePage/index.jsx | 6 ++++-- src/components/pages/ProfilePage/index.jsx | 15 ++++++++++----- src/components/pages/SettingsPage/index.jsx | 9 +++++++-- src/components/pages/TalkPage/index.jsx | 6 ++++-- src/index.js | 4 +++- src/store/actions/authActions.js | 2 +- src/store/actions/generalActions.js | 4 ++-- src/store/actions/userActions.js | 9 +++++---- src/store/reducers/authReducers.js | 10 ++++++++++ src/store/reducers/generalReducers.js | 10 ++++++++++ src/store/reducers/userReducers.js | 10 ++++++++++ 22 files changed, 117 insertions(+), 47 deletions(-) diff --git a/src/App.js b/src/App.js index cbbcaea..4329904 100644 --- a/src/App.js +++ b/src/App.js @@ -7,6 +7,8 @@ import { withRouter } from "react-router-dom"; //> Redux import { useDispatch } from "react-redux"; +//> Actions +import { loginAction } from "./store/actions/authActions"; //> Components /** * Footer: Global Footer @@ -17,8 +19,6 @@ import { Footer, Navbar } from "./components/molecules"; import { ScrollToTop } from "./components/atoms"; //> Routes import Routes from "./Routes"; -//> Actions -import { loginAction } from "./store/actions/authActions"; //#endregion //#region > Components diff --git a/src/components/atoms/Project/index.jsx b/src/components/atoms/Project/index.jsx index 66cd600..d8282d6 100644 --- a/src/components/atoms/Project/index.jsx +++ b/src/components/atoms/Project/index.jsx @@ -6,7 +6,8 @@ import React from "react"; import PropTypes from "prop-types"; //> MDB // "Material Design for Bootstrap" is a great UI design framework -import { MDBCol, MDBIcon, MDBProgress } from "mdbreact"; +import { MDBCol, MDBIcon } from "mdbreact"; + //> Components import { LanguageChart } from "../../atoms"; //#endregion diff --git a/src/components/atoms/SearchBar/index.jsx b/src/components/atoms/SearchBar/index.jsx index bd46641..5288419 100644 --- a/src/components/atoms/SearchBar/index.jsx +++ b/src/components/atoms/SearchBar/index.jsx @@ -4,8 +4,6 @@ import React from "react"; // DOM bindings for React Router import { withRouter } from "react-router-dom"; -// React PropTypes -import PropTypes from "prop-types"; //> MDB // "Material Design for Bootstrap" is a great UI design framework import { @@ -17,10 +15,13 @@ import { //> Fuzzysort // Fast SublimeText-like fuzzy search for JavaScript import * as fuzzysort from "fuzzysort"; -//> CSS -import "./search.scss"; +//> Redux import { connect } from "react-redux"; + +//> Actions import { getAllPageUrlsAction } from "../../../store/actions/generalActions"; +//> CSS +import "./search.scss"; //#endregion //#region > Components @@ -111,10 +112,7 @@ class SearchBar extends React.Component { } //#endregion -//#region > PropTypes -SearchBar.propTypes = {}; -//#endregion - +//#region > Redux Mapping const mapStateToProps = (state) => ({ allRegisteredUsernames: state.general.allRegisteredUsernames, }); @@ -124,6 +122,7 @@ const mapDispatchToProps = (dispatch) => { allUsernames: () => dispatch(getAllPageUrlsAction()), }; }; +//#endregion //#region > Exports //> Default Class diff --git a/src/components/atoms/charts/LanguageBar/index.jsx b/src/components/atoms/charts/LanguageBar/index.jsx index f3c2261..10e92e1 100644 --- a/src/components/atoms/charts/LanguageBar/index.jsx +++ b/src/components/atoms/charts/LanguageBar/index.jsx @@ -57,6 +57,7 @@ class LanguageBar extends React.Component { //#endregion //#region > Exports +//> Default Class export default LanguageBar; //#endregion diff --git a/src/components/molecules/Navbar/index.jsx b/src/components/molecules/Navbar/index.jsx index 772e86f..7c7d7b5 100644 --- a/src/components/molecules/Navbar/index.jsx +++ b/src/components/molecules/Navbar/index.jsx @@ -1,7 +1,7 @@ //#region > Imports //> React // Contains all the functionality necessary to define React components -import React, { lazy, Suspense } from "react"; +import React from "react"; // DOM bindings for React Router import { Link, withRouter, NavLink } from "react-router-dom"; // React PropTypes @@ -17,21 +17,22 @@ import { MDBCollapse, MDBContainer, MDBDropdown, - MDBDropdownItem, MDBDropdownToggle, MDBDropdownMenu, MDBSmoothScroll, MDBBtn, } from "mdbreact"; +//> Redux +import { connect } from "react-redux"; -//> Searchbar +//> Actions +import { logoutAction } from "../../../store/actions/authActions"; +//> SearchBar import { SearchBar } from "../../atoms"; //> Images import SNEKLogo from "../../../assets/navigation/logo.png"; //> CSS import "./navbar.scss"; -import { connect } from "react-redux"; -import { logoutAction } from "../../../store/actions/authActions"; //#endregion //#region > Components @@ -177,6 +178,7 @@ Navbar.propTypes = { }; //#endregion +//#region > Redux Mapping const mapStateToProps = (state) => ({ loggedUser: state.auth.loggedUser, }); @@ -186,6 +188,7 @@ const mapDispatchToProps = (dispatch) => { logout: () => dispatch(logoutAction()), }; }; +//#endregion //#region > Exports //> Default Class diff --git a/src/components/molecules/UserActionCard/index.jsx b/src/components/molecules/UserActionCard/index.jsx index 3c35cf9..d6c1ddf 100644 --- a/src/components/molecules/UserActionCard/index.jsx +++ b/src/components/molecules/UserActionCard/index.jsx @@ -2,8 +2,6 @@ //> React // Contains all the functionality necessary to define React components import React from "react"; -// React PropTypes -import PropTypes from "prop-types"; //> MDB // "Material Design for Bootstrap" is a great UI design framework import { MDBRow, MDBCol, MDBAlert, MDBBtn, MDBIcon } from "mdbreact"; diff --git a/src/components/molecules/forms/LoginForm/index.jsx b/src/components/molecules/forms/LoginForm/index.jsx index 769e3c2..107fd79 100644 --- a/src/components/molecules/forms/LoginForm/index.jsx +++ b/src/components/molecules/forms/LoginForm/index.jsx @@ -4,15 +4,18 @@ import React from "react"; // React PropTypes import PropTypes from "prop-types"; -//> Additional -// Text animations -import TextLoop from "react-text-loop"; //> MDB // "Material Design for Bootstrap" is a great UI design framework import { MDBAlert, MDBBtn, MDBIcon } from "mdbreact"; -import { loginAction } from "../../../../store/actions/authActions"; +//> Additional +// SHA hashing algorithm import { sha256 } from "js-sha256"; +//> Redux import { connect } from "react-redux"; + +//> Actions +import { loginAction } from "../../../../store/actions/authActions"; + //#endregion //#region > Components @@ -202,11 +205,13 @@ LoginForm.propTypes = { }; //#endregion +//#region > Redux Mapping const mapStateToProps = (state) => ({}); const mapDispatchToProps = (dispatch) => { return { login: (user) => dispatch(loginAction(user)) }; }; +//#endregion //#region > Exports //> Default Class diff --git a/src/components/molecules/forms/RegisterForm/index.jsx b/src/components/molecules/forms/RegisterForm/index.jsx index 18f520e..aea7999 100644 --- a/src/components/molecules/forms/RegisterForm/index.jsx +++ b/src/components/molecules/forms/RegisterForm/index.jsx @@ -29,13 +29,15 @@ import { MDBListGroup, MDBListGroupItem, } from "mdbreact"; - //> OAuth import GitHubOAuth from "reactjs-oauth"; +//> Redux +import { connect } from "react-redux"; + +//> Actions import { registerAction } from "../../../../store/actions/userActions"; import { fetchGitLabServersAction } from "../../../../store/actions/generalActions"; import { loginAction } from "../../../../store/actions/authActions"; -import { connect } from "react-redux"; //#endregion //#region > Components @@ -841,6 +843,8 @@ RegisterForm.propTypes = { goto: PropTypes.func, }; //#endregion + +//#region > Redux Mapping const mapStateToProps = (state) => ({ registrationHistory: state.user.registrationHistory, gitlabServers: state.general.allGitlabServers, @@ -853,6 +857,7 @@ const mapDispatchToProps = (dispatch) => { fetchGitLabServers: () => dispatch(fetchGitLabServersAction()), }; }; +//#endregion //#region > Exports //> Default Class diff --git a/src/components/organisms/ProfileInfo/index.jsx b/src/components/organisms/ProfileInfo/index.jsx index ba3b3dc..779ebdf 100644 --- a/src/components/organisms/ProfileInfo/index.jsx +++ b/src/components/organisms/ProfileInfo/index.jsx @@ -17,6 +17,7 @@ import { } from "mdbreact"; //> Redux import { connect } from "react-redux"; + //> Components import { LanguageChart } from "../../atoms"; //#endregion @@ -346,6 +347,7 @@ class ProfileInfo extends React.Component { } //#endregion +//#region > Redux Mapping const mapStateToProps = (state) => ({ fetchedUser: state.user.fetchedUser, }); @@ -353,6 +355,7 @@ const mapStateToProps = (state) => ({ const mapDispatchToProps = (dispatch) => { return {}; }; +//#endregion //#region > Exports //> Default Class diff --git a/src/components/organisms/SoftwareTabs/index.jsx b/src/components/organisms/SoftwareTabs/index.jsx index 097264b..a7bfa01 100644 --- a/src/components/organisms/SoftwareTabs/index.jsx +++ b/src/components/organisms/SoftwareTabs/index.jsx @@ -5,10 +5,12 @@ import React from "react"; //> MDB // "Material Design for Bootstrap" is a great UI design framework import { MDBBadge } from "mdbreact"; +//> Redux +import { connect } from "react-redux"; //> Components import { ProjectTab, OverviewTab, TalksTab } from "../tabs"; -import { connect } from "react-redux"; + //#endregion //#region > Components @@ -120,6 +122,7 @@ class SoftwareTabs extends React.Component { } //#endregion +//#region > Redux Mapping const mapStateToProps = (state) => ({ fetchedUser: state.user.fetchedUser, }); @@ -127,6 +130,7 @@ const mapStateToProps = (state) => ({ const mapDispatchToProps = (dispatch) => { return {}; }; +//#endregion //#region > Exports //> Default Class diff --git a/src/components/organisms/tabs/TalksTab/index.jsx b/src/components/organisms/tabs/TalksTab/index.jsx index 6c86591..3a9ccc0 100644 --- a/src/components/organisms/tabs/TalksTab/index.jsx +++ b/src/components/organisms/tabs/TalksTab/index.jsx @@ -16,14 +16,15 @@ import { MDBCardBody, MDBCardFooter, } from "mdbreact"; +//> Redux +import { connect } from "react-redux"; +//> Actions +import { deleteTalkAction } from "../../../../store/actions/userActions"; //> CSS import "./talkstab.scss"; //> Modules import { TalkUploadModal } from "../../../molecules/modals"; -import { connect } from "react-redux"; -import { TalksTab } from ".."; -import { deleteTalkAction } from "../../../../store/actions/userActions"; //#endregion //#region > Components @@ -213,6 +214,7 @@ class Talks extends React.Component { } //#endregion +//#region > Redux Mapping const mapStateToProps = (state) => ({ loggedUser: state.auth.loggedUser, fetchedUser: state.user.fetchedUser, @@ -221,10 +223,12 @@ const mapStateToProps = (state) => ({ const mapDispatchToProps = (dispatch) => { return { deleteTalk: (talk) => dispatch(deleteTalkAction(talk)) }; }; +//#endregion //#region > Exports //> Default Class export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Talks)); +//#endregion /** * SPDX-License-Identifier: (EUPL-1.2) diff --git a/src/components/pages/HomePage/index.jsx b/src/components/pages/HomePage/index.jsx index 8daebdd..a503ab9 100644 --- a/src/components/pages/HomePage/index.jsx +++ b/src/components/pages/HomePage/index.jsx @@ -18,6 +18,8 @@ import { MDBBtn, MDBIcon, } from "mdbreact"; +//> Redux +import { connect } from "react-redux"; //> Components import LatestActivity from "../../atoms/charts/LatestActivity"; @@ -30,8 +32,6 @@ import imageProfiles from "../../../assets/body/profiles.png"; import imageTrophy from "../../../assets/body/trophy.png"; import gitHubLab from "../../../assets/body/githublab.png"; import shareImage from "../../../assets/body/share.png"; - -import { connect } from "react-redux"; //#endregion //#region > Components @@ -301,6 +301,7 @@ class HomePage extends React.Component { } //#endregion +//#region > Redux Mapping const mapStateToProps = (state) => ({ loggedUser: state.auth.loggedUser, }); @@ -308,6 +309,7 @@ const mapStateToProps = (state) => ({ const mapDispatchToProps = (dispatch) => { return {}; }; +//#endregion //#region > Exports //> Default Class diff --git a/src/components/pages/ProfilePage/index.jsx b/src/components/pages/ProfilePage/index.jsx index 76caf66..c4bab96 100644 --- a/src/components/pages/ProfilePage/index.jsx +++ b/src/components/pages/ProfilePage/index.jsx @@ -4,17 +4,20 @@ import React from "react"; // DOM bindings for React Router import { withRouter } from "react-router-dom"; +//> Redux +import { connect } from "react-redux"; -//> Components -import { SoftwareEngineer } from "../../organisms/profiles"; -//> CSS -import "./profile.scss"; +//> Actions import { readCacheAction, updateCacheAction, saveSettingsActions, } from "../../../store/actions/userActions"; -import { connect } from "react-redux"; +//> Components +import { SoftwareEngineer } from "../../organisms/profiles"; +//> CSS +import "./profile.scss"; + //#endregion //#region > Components @@ -140,6 +143,7 @@ class ProfilePage extends React.Component { } //#endregion +//#region > Redux Mapping const mapStateToProps = (state) => ({ loggedUser: state.auth.loggedUser, fetchedUser: state.user.fetchedUser, @@ -153,6 +157,7 @@ const mapDispatchToProps = (dispatch) => { updateCache: (fetchedUser) => dispatch(updateCacheAction(fetchedUser)), }; }; +//#endregion //#region > Exports //> Default Class diff --git a/src/components/pages/SettingsPage/index.jsx b/src/components/pages/SettingsPage/index.jsx index 4ffdf0a..a408596 100644 --- a/src/components/pages/SettingsPage/index.jsx +++ b/src/components/pages/SettingsPage/index.jsx @@ -28,14 +28,17 @@ import { MDBSelectInput, MDBBtn, } from "mdbreact"; +//> Redux import { connect } from "react-redux"; -// Profile Picture Editor -import { ProfilePictureModal } from "../../../components/molecules/modals"; +//> Actions import { readCacheAction, saveSettingsActions, } from "../../../store/actions/userActions"; +//> Components +// Profile Picture Editor +import { ProfilePictureModal } from "../../../components/molecules/modals"; //> CSS import "./settings.scss"; //#endregion @@ -559,6 +562,7 @@ class SettingsPage extends React.Component { } //#endregion +//#region > Redux Mapping const mapStateToProps = (state) => ({ loggedUser: state.auth.loggedUser, fetchedUser: state.user.fetchedUser, @@ -570,6 +574,7 @@ const mapDispatchToProps = (dispatch) => { readCache: (username) => dispatch(readCacheAction(username)), }; }; +//#endregion //#region > Exports //> Default Class diff --git a/src/components/pages/TalkPage/index.jsx b/src/components/pages/TalkPage/index.jsx index 57642e9..f51bd7f 100644 --- a/src/components/pages/TalkPage/index.jsx +++ b/src/components/pages/TalkPage/index.jsx @@ -20,11 +20,13 @@ import { MDBPageNav, MDBPagination, } from "mdbreact"; +//> Redux +import { connect } from "react-redux"; +//> Actions +import { getTalkAction } from "../../../store/actions/userActions"; //> CSS import "./talk.scss"; -import { getTalkAction } from "../../../store/actions/userActions"; -import { connect } from "react-redux"; //#endregion //#region > Components diff --git a/src/index.js b/src/index.js index 19a143e..00c5c63 100644 --- a/src/index.js +++ b/src/index.js @@ -8,6 +8,7 @@ import { BrowserRouter as Router } from "react-router-dom"; import ReactDOM from "react-dom"; //> Redux import { createStore, applyMiddleware, compose } from "redux"; +import { loadingBarMiddleware } from "react-redux-loading-bar"; import { Provider } from "react-redux"; // Thunk import thunk from "redux-thunk"; @@ -33,9 +34,9 @@ import App from "./App"; import rootReducer from "./store/reducers"; //> Service Worker import registerServiceWorker from "./registerServiceWorker"; -import { loadingBarMiddleware } from "react-redux-loading-bar"; //#endregion +//#region > Redux Store Initialization const INTEL = new Intel(); //#TODO @@ -64,6 +65,7 @@ const enhancer = composeEnhancers( ); const STORE = createStore(rootReducer /* preloadedState, */, enhancer); +//#endregion // Render the root component to
    ReactDOM.render( diff --git a/src/store/actions/authActions.js b/src/store/actions/authActions.js index 1952aae..961b440 100644 --- a/src/store/actions/authActions.js +++ b/src/store/actions/authActions.js @@ -1,4 +1,4 @@ -//#region > Authentication +//#region > Authentication Actions /** * Handle login * diff --git a/src/store/actions/generalActions.js b/src/store/actions/generalActions.js index dde9c5d..13ab304 100644 --- a/src/store/actions/generalActions.js +++ b/src/store/actions/generalActions.js @@ -1,4 +1,4 @@ -//#region > Registration +//#region > Registration Actions /** * Append Source Objects * @@ -69,7 +69,7 @@ const fetchGitLabServersAction = () => { }; //#endregion -//#region > Data Handling +//#region > Data Handling Actions /** * Get intel data * diff --git a/src/store/actions/userActions.js b/src/store/actions/userActions.js index 208651f..1610c26 100644 --- a/src/store/actions/userActions.js +++ b/src/store/actions/userActions.js @@ -4,7 +4,7 @@ import sha256 from "js-sha256"; //#endregion -//#region > Register +//#region > Register Actions /** * Register user. * @@ -77,7 +77,7 @@ const registerAction = (registrationData) => { }; //#endregion -//#region > Caching +//#region > Caching Actions /** * Write cache. * @@ -374,7 +374,8 @@ const saveSettingsActions = (nextSettings) => { //#endregion -//#region > Talks +//#region > Talks Actions +//> Is currently not needed but has been left for later implementations! // /** // * Get all talks. // * @@ -558,7 +559,7 @@ export { readCacheAction, updateCacheAction, saveSettingsActions, - // getAllTalksAction, + //getAllTalksAction, getTalkAction, uploadTalkAction, deleteTalkAction, diff --git a/src/store/reducers/authReducers.js b/src/store/reducers/authReducers.js index cf6632b..a6bbec9 100644 --- a/src/store/reducers/authReducers.js +++ b/src/store/reducers/authReducers.js @@ -1,11 +1,18 @@ +//#region > Imports +//> Error Serialization +// Serialize/deserialize an error into a plain object import { serializeError } from "serialize-error"; +//#endregion +//#region > Constant Variables const INIT_STATE = { loggedUser: { anonymous: true }, authError: null, authErrorDetails: null, }; +//#endregion +//#region > Reducers const authReducer = (state = INIT_STATE, action) => { switch (action.type) { //> LOGIN @@ -46,5 +53,8 @@ const authReducer = (state = INIT_STATE, action) => { return state; } }; +//#endregion +//#region > Exports export default authReducer; +//#endregion diff --git a/src/store/reducers/generalReducers.js b/src/store/reducers/generalReducers.js index 746f64d..c5e06b2 100644 --- a/src/store/reducers/generalReducers.js +++ b/src/store/reducers/generalReducers.js @@ -1,5 +1,10 @@ +//#region > Imports +//> Error Serialization +// Serialize/deserialize an error into a plain object import { serializeError } from "serialize-error"; +//#endregion +//#region > Constant Variables const INIT_STATE = { allRegisteredUsernames: null, allGitlabServers: [], @@ -7,7 +12,9 @@ const INIT_STATE = { generalError: null, generalErrorDetails: null, }; +//#endregion +//#region > Reducers const generalReducer = (state = INIT_STATE, action) => { switch (action.type) { //> appendSourceObjectsAction @@ -69,5 +76,8 @@ const generalReducer = (state = INIT_STATE, action) => { return state; } }; +//#endregion +//#region > Exports export default generalReducer; +//#endregion diff --git a/src/store/reducers/userReducers.js b/src/store/reducers/userReducers.js index a727c87..ba83680 100644 --- a/src/store/reducers/userReducers.js +++ b/src/store/reducers/userReducers.js @@ -1,5 +1,10 @@ +//#region > Imports +//> Error Serialization +// Serialize/deserialize an error into a plain object import { serializeError } from "serialize-error"; +//#endregion +//#region > Constant Variables const INIT_STATE = { fetchedUser: null, registrationHistory: null, @@ -9,7 +14,9 @@ const INIT_STATE = { userError: null, userErrorDetails: null, }; +//#endregion +//#region > User Reducers const userReducer = (state = INIT_STATE, action) => { switch (action.type) { //> registerAction @@ -129,5 +136,8 @@ const userReducer = (state = INIT_STATE, action) => { return state; } }; +//#endregion +//#region > Exports export default userReducer; +//#endregion From 60c53eb5abc924bec664c0dc8e42d469faf13a65 Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 6 Jul 2020 16:34:52 +0200 Subject: [PATCH 46/86] Remove Default Class Comment from Export Regions The comment `Default Class` is completely useless and therefore removed. --- src/components/atoms/Pinned/index.jsx | 1 - src/components/atoms/Project/index.jsx | 1 - src/components/atoms/ScrollToTop/index.jsx | 1 - src/components/atoms/SearchBar/index.jsx | 1 - src/components/atoms/charts/Calendar2D/index.jsx | 1 - src/components/atoms/charts/Calendar3D/index.jsx | 1 - src/components/atoms/charts/ContribRadar/index.jsx | 1 - src/components/atoms/charts/LanguageBar/index.jsx | 1 - src/components/atoms/charts/LatestActivity/index.jsx | 1 - src/components/molecules/Footer/index.jsx | 1 - src/components/molecules/Navbar/index.jsx | 1 - src/components/molecules/UserActionCard/index.jsx | 1 - src/components/molecules/forms/LoginForm/index.jsx | 1 - src/components/molecules/forms/RegisterForm/index.jsx | 1 - src/components/molecules/modals/TalkUploadModal/index.jsx | 1 - src/components/organisms/ProfileInfo/index.jsx | 1 - src/components/organisms/SoftwareTabs/index.jsx | 1 - src/components/organisms/profiles/SoftwareEngineer/index.jsx | 1 - src/components/organisms/tabs/OverviewTab/index.jsx | 1 - src/components/organisms/tabs/ProjectTab/index.jsx | 1 - src/components/organisms/tabs/TalksTab/index.jsx | 1 - src/components/pages/CompanyPage/index.jsx | 1 - src/components/pages/HomePage/index.jsx | 1 - src/components/pages/ProfilePage/index.jsx | 1 - src/components/pages/SettingsPage/index.jsx | 1 - src/components/pages/TalkPage/index.jsx | 1 - 26 files changed, 26 deletions(-) diff --git a/src/components/atoms/Pinned/index.jsx b/src/components/atoms/Pinned/index.jsx index cd32f6a..e73a48e 100644 --- a/src/components/atoms/Pinned/index.jsx +++ b/src/components/atoms/Pinned/index.jsx @@ -63,7 +63,6 @@ Pinned.propTypes = { //#endregion //#region > Exports -//> Default Class export default Pinned; //#endregion diff --git a/src/components/atoms/Project/index.jsx b/src/components/atoms/Project/index.jsx index d8282d6..bfe243c 100644 --- a/src/components/atoms/Project/index.jsx +++ b/src/components/atoms/Project/index.jsx @@ -65,7 +65,6 @@ Project.propTypes = { //#endregion //#region > Exports -//> Default Class export default Project; //#endregion diff --git a/src/components/atoms/ScrollToTop/index.jsx b/src/components/atoms/ScrollToTop/index.jsx index 275ef97..f9c5722 100644 --- a/src/components/atoms/ScrollToTop/index.jsx +++ b/src/components/atoms/ScrollToTop/index.jsx @@ -29,7 +29,6 @@ class ScrollToTop extends React.Component { //#endregion //#region > Exports -//> Default Class export default withRouter(ScrollToTop); //#endregion diff --git a/src/components/atoms/SearchBar/index.jsx b/src/components/atoms/SearchBar/index.jsx index 5288419..15fd9d7 100644 --- a/src/components/atoms/SearchBar/index.jsx +++ b/src/components/atoms/SearchBar/index.jsx @@ -125,7 +125,6 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -//> Default Class export default withRouter( connect(mapStateToProps, mapDispatchToProps)(SearchBar) ); diff --git a/src/components/atoms/charts/Calendar2D/index.jsx b/src/components/atoms/charts/Calendar2D/index.jsx index 27ba11a..bf8cc29 100644 --- a/src/components/atoms/charts/Calendar2D/index.jsx +++ b/src/components/atoms/charts/Calendar2D/index.jsx @@ -234,7 +234,6 @@ class Calender2D extends React.Component { //#endregion //#region > Exports -//> Default Class export default Calender2D; //#endregion diff --git a/src/components/atoms/charts/Calendar3D/index.jsx b/src/components/atoms/charts/Calendar3D/index.jsx index 5892b18..272a662 100644 --- a/src/components/atoms/charts/Calendar3D/index.jsx +++ b/src/components/atoms/charts/Calendar3D/index.jsx @@ -364,7 +364,6 @@ class Calendar3D extends React.Component { //#endregion //#region > Exports -//> Default Class export default Calendar3D; //#endregion diff --git a/src/components/atoms/charts/ContribRadar/index.jsx b/src/components/atoms/charts/ContribRadar/index.jsx index 1acd626..f57bdc7 100644 --- a/src/components/atoms/charts/ContribRadar/index.jsx +++ b/src/components/atoms/charts/ContribRadar/index.jsx @@ -180,7 +180,6 @@ class ContribRadar extends React.Component { //#endregion //#region > Exports -//> Default Class export default ContribRadar; //#endregion diff --git a/src/components/atoms/charts/LanguageBar/index.jsx b/src/components/atoms/charts/LanguageBar/index.jsx index 10e92e1..f3c2261 100644 --- a/src/components/atoms/charts/LanguageBar/index.jsx +++ b/src/components/atoms/charts/LanguageBar/index.jsx @@ -57,7 +57,6 @@ class LanguageBar extends React.Component { //#endregion //#region > Exports -//> Default Class export default LanguageBar; //#endregion diff --git a/src/components/atoms/charts/LatestActivity/index.jsx b/src/components/atoms/charts/LatestActivity/index.jsx index 2842de1..fdc8cc6 100644 --- a/src/components/atoms/charts/LatestActivity/index.jsx +++ b/src/components/atoms/charts/LatestActivity/index.jsx @@ -175,7 +175,6 @@ class LatestActivity extends React.Component { //#endregion //#region > Exports -//> Default Class export default LatestActivity; //#endregion diff --git a/src/components/molecules/Footer/index.jsx b/src/components/molecules/Footer/index.jsx index ccaa3b8..2b6d9d4 100644 --- a/src/components/molecules/Footer/index.jsx +++ b/src/components/molecules/Footer/index.jsx @@ -254,7 +254,6 @@ class Footer extends React.PureComponent { //#endregion //#region > Exports -//> Default Class export default withRouter(Footer); //#endregion diff --git a/src/components/molecules/Navbar/index.jsx b/src/components/molecules/Navbar/index.jsx index 7c7d7b5..869d07e 100644 --- a/src/components/molecules/Navbar/index.jsx +++ b/src/components/molecules/Navbar/index.jsx @@ -191,7 +191,6 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -//> Default Class export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Navbar)); //#endregion diff --git a/src/components/molecules/UserActionCard/index.jsx b/src/components/molecules/UserActionCard/index.jsx index d6c1ddf..4a5f7a8 100644 --- a/src/components/molecules/UserActionCard/index.jsx +++ b/src/components/molecules/UserActionCard/index.jsx @@ -110,7 +110,6 @@ class UserActionCard extends React.Component { //#endregion //#region > Exports -//> Default Class export default UserActionCard; //#endregion diff --git a/src/components/molecules/forms/LoginForm/index.jsx b/src/components/molecules/forms/LoginForm/index.jsx index 107fd79..bf0f8ee 100644 --- a/src/components/molecules/forms/LoginForm/index.jsx +++ b/src/components/molecules/forms/LoginForm/index.jsx @@ -214,7 +214,6 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -//> Default Class export default connect(mapStateToProps, mapDispatchToProps)(LoginForm); //#endregion diff --git a/src/components/molecules/forms/RegisterForm/index.jsx b/src/components/molecules/forms/RegisterForm/index.jsx index aea7999..98b07fd 100644 --- a/src/components/molecules/forms/RegisterForm/index.jsx +++ b/src/components/molecules/forms/RegisterForm/index.jsx @@ -860,7 +860,6 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -//> Default Class export default connect(mapStateToProps, mapDispatchToProps)(RegisterForm); //#endregion diff --git a/src/components/molecules/modals/TalkUploadModal/index.jsx b/src/components/molecules/modals/TalkUploadModal/index.jsx index 2177f38..7754b5b 100644 --- a/src/components/molecules/modals/TalkUploadModal/index.jsx +++ b/src/components/molecules/modals/TalkUploadModal/index.jsx @@ -146,7 +146,6 @@ class TalkUploadModal extends React.Component { //#endregion //#region > Exports -//> Default Class export default TalkUploadModal; //#endregion diff --git a/src/components/organisms/ProfileInfo/index.jsx b/src/components/organisms/ProfileInfo/index.jsx index 779ebdf..3b74dc5 100644 --- a/src/components/organisms/ProfileInfo/index.jsx +++ b/src/components/organisms/ProfileInfo/index.jsx @@ -358,7 +358,6 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -//> Default Class export default connect(mapStateToProps, mapDispatchToProps)(ProfileInfo); //#endregion diff --git a/src/components/organisms/SoftwareTabs/index.jsx b/src/components/organisms/SoftwareTabs/index.jsx index a7bfa01..ebb96f9 100644 --- a/src/components/organisms/SoftwareTabs/index.jsx +++ b/src/components/organisms/SoftwareTabs/index.jsx @@ -133,7 +133,6 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -//> Default Class export default connect(mapStateToProps, mapDispatchToProps)(SoftwareTabs); //#endregion diff --git a/src/components/organisms/profiles/SoftwareEngineer/index.jsx b/src/components/organisms/profiles/SoftwareEngineer/index.jsx index 834150c..47ccf17 100644 --- a/src/components/organisms/profiles/SoftwareEngineer/index.jsx +++ b/src/components/organisms/profiles/SoftwareEngineer/index.jsx @@ -37,7 +37,6 @@ class SoftwareEngineer extends React.Component { //#endregion //#region > Exports -//> Default Class export default SoftwareEngineer; //#endregion diff --git a/src/components/organisms/tabs/OverviewTab/index.jsx b/src/components/organisms/tabs/OverviewTab/index.jsx index 1872a9f..a5f0f5d 100644 --- a/src/components/organisms/tabs/OverviewTab/index.jsx +++ b/src/components/organisms/tabs/OverviewTab/index.jsx @@ -201,7 +201,6 @@ OverviewTab.propTypes = { //#endregion //#region > Exports -//> Default Class export default OverviewTab; //#endregion diff --git a/src/components/organisms/tabs/ProjectTab/index.jsx b/src/components/organisms/tabs/ProjectTab/index.jsx index b4cf31a..621310f 100644 --- a/src/components/organisms/tabs/ProjectTab/index.jsx +++ b/src/components/organisms/tabs/ProjectTab/index.jsx @@ -42,7 +42,6 @@ ProjectTab.propTypes = { //#endregion //#region > Exports -//> Default Class export default ProjectTab; //#endregion diff --git a/src/components/organisms/tabs/TalksTab/index.jsx b/src/components/organisms/tabs/TalksTab/index.jsx index 3a9ccc0..88e0ae5 100644 --- a/src/components/organisms/tabs/TalksTab/index.jsx +++ b/src/components/organisms/tabs/TalksTab/index.jsx @@ -226,7 +226,6 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -//> Default Class export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Talks)); //#endregion diff --git a/src/components/pages/CompanyPage/index.jsx b/src/components/pages/CompanyPage/index.jsx index 47cebd4..df12945 100644 --- a/src/components/pages/CompanyPage/index.jsx +++ b/src/components/pages/CompanyPage/index.jsx @@ -666,7 +666,6 @@ class CompanyPage extends React.Component { //#endregion //#region > Exports -//> Default Class export default CompanyPage; //#endregion diff --git a/src/components/pages/HomePage/index.jsx b/src/components/pages/HomePage/index.jsx index a503ab9..fdd29df 100644 --- a/src/components/pages/HomePage/index.jsx +++ b/src/components/pages/HomePage/index.jsx @@ -312,7 +312,6 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -//> Default Class export default connect(mapStateToProps, mapDispatchToProps)(HomePage); //#endregion diff --git a/src/components/pages/ProfilePage/index.jsx b/src/components/pages/ProfilePage/index.jsx index c4bab96..83ae72e 100644 --- a/src/components/pages/ProfilePage/index.jsx +++ b/src/components/pages/ProfilePage/index.jsx @@ -160,7 +160,6 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -//> Default Class export default withRouter( connect(mapStateToProps, mapDispatchToProps)(ProfilePage) ); diff --git a/src/components/pages/SettingsPage/index.jsx b/src/components/pages/SettingsPage/index.jsx index a408596..998ee0e 100644 --- a/src/components/pages/SettingsPage/index.jsx +++ b/src/components/pages/SettingsPage/index.jsx @@ -577,7 +577,6 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -//> Default Class export default connect(mapStateToProps, mapDispatchToProps)(SettingsPage); //#endregion diff --git a/src/components/pages/TalkPage/index.jsx b/src/components/pages/TalkPage/index.jsx index f51bd7f..ede680d 100644 --- a/src/components/pages/TalkPage/index.jsx +++ b/src/components/pages/TalkPage/index.jsx @@ -387,7 +387,6 @@ const mapDispatchToProps = (dispatch) => { }; //#region > Exports -//> Default Class export default connect(mapStateToProps, mapDispatchToProps)(TalkPage); //#endregion From 9f5b9b77548ce33452ba037f5fde5ede51f4cc8f Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 6 Jul 2020 16:41:26 +0200 Subject: [PATCH 47/86] Add Comments to Export Regions All components that needed proper export documentation have been updated. Contains a description of withRouter and connect behaviour --- src/App.js | 2 ++ src/components/atoms/ScrollToTop/index.jsx | 2 ++ src/components/atoms/SearchBar/index.jsx | 4 ++++ src/components/molecules/Footer/index.jsx | 2 ++ src/components/molecules/Navbar/index.jsx | 4 ++++ src/components/molecules/forms/LoginForm/index.jsx | 4 ++++ src/components/molecules/forms/RegisterForm/index.jsx | 2 ++ src/components/organisms/ProfileInfo/index.jsx | 2 ++ src/components/organisms/SoftwareTabs/index.jsx | 2 ++ src/components/organisms/tabs/TalksTab/index.jsx | 4 ++++ src/components/pages/HomePage/index.jsx | 2 ++ src/components/pages/ProfilePage/index.jsx | 4 ++++ src/components/pages/SettingsPage/index.jsx | 4 ++++ src/components/pages/TalkPage/index.jsx | 4 ++++ 14 files changed, 42 insertions(+) diff --git a/src/App.js b/src/App.js index 4329904..887dd19 100644 --- a/src/App.js +++ b/src/App.js @@ -49,6 +49,8 @@ function App() { //#endregion //#region > Exports +// Got access to the history object’s properties and the closest +// 's match. export default withRouter(App); //#endregion diff --git a/src/components/atoms/ScrollToTop/index.jsx b/src/components/atoms/ScrollToTop/index.jsx index f9c5722..3d3710f 100644 --- a/src/components/atoms/ScrollToTop/index.jsx +++ b/src/components/atoms/ScrollToTop/index.jsx @@ -29,6 +29,8 @@ class ScrollToTop extends React.Component { //#endregion //#region > Exports +// Got access to the history object’s properties and the closest +// 's match. export default withRouter(ScrollToTop); //#endregion diff --git a/src/components/atoms/SearchBar/index.jsx b/src/components/atoms/SearchBar/index.jsx index 15fd9d7..5a34bcc 100644 --- a/src/components/atoms/SearchBar/index.jsx +++ b/src/components/atoms/SearchBar/index.jsx @@ -125,6 +125,10 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports +// Provides its connected component with the pieces of the data it needs from +// the store, and the functions it can use to dispatch actions to the store. +// Got access to the history object’s properties and the closest +// 's match. export default withRouter( connect(mapStateToProps, mapDispatchToProps)(SearchBar) ); diff --git a/src/components/molecules/Footer/index.jsx b/src/components/molecules/Footer/index.jsx index 2b6d9d4..7fdbe0a 100644 --- a/src/components/molecules/Footer/index.jsx +++ b/src/components/molecules/Footer/index.jsx @@ -254,6 +254,8 @@ class Footer extends React.PureComponent { //#endregion //#region > Exports +// Got access to the history object’s properties and the closest +// 's match. export default withRouter(Footer); //#endregion diff --git a/src/components/molecules/Navbar/index.jsx b/src/components/molecules/Navbar/index.jsx index 869d07e..e3b134b 100644 --- a/src/components/molecules/Navbar/index.jsx +++ b/src/components/molecules/Navbar/index.jsx @@ -191,6 +191,10 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports +// Provides its connected component with the pieces of the data it needs from +// the store, and the functions it can use to dispatch actions to the store. +// Got access to the history object’s properties and the closest +// 's match. export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Navbar)); //#endregion diff --git a/src/components/molecules/forms/LoginForm/index.jsx b/src/components/molecules/forms/LoginForm/index.jsx index bf0f8ee..9e782d2 100644 --- a/src/components/molecules/forms/LoginForm/index.jsx +++ b/src/components/molecules/forms/LoginForm/index.jsx @@ -214,6 +214,10 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports +// Provides its connected component with the pieces of the data it needs from +// the store, and the functions it can use to dispatch actions to the store. +// Got access to the history object’s properties and the closest +// 's match. export default connect(mapStateToProps, mapDispatchToProps)(LoginForm); //#endregion diff --git a/src/components/molecules/forms/RegisterForm/index.jsx b/src/components/molecules/forms/RegisterForm/index.jsx index 98b07fd..ddaaa92 100644 --- a/src/components/molecules/forms/RegisterForm/index.jsx +++ b/src/components/molecules/forms/RegisterForm/index.jsx @@ -860,6 +860,8 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports +// Provides its connected component with the pieces of the data it needs from +// the store, and the functions it can use to dispatch actions to the store. export default connect(mapStateToProps, mapDispatchToProps)(RegisterForm); //#endregion diff --git a/src/components/organisms/ProfileInfo/index.jsx b/src/components/organisms/ProfileInfo/index.jsx index 3b74dc5..68c7798 100644 --- a/src/components/organisms/ProfileInfo/index.jsx +++ b/src/components/organisms/ProfileInfo/index.jsx @@ -358,6 +358,8 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports +// Provides its connected component with the pieces of the data it needs from +// the store, and the functions it can use to dispatch actions to the store. export default connect(mapStateToProps, mapDispatchToProps)(ProfileInfo); //#endregion diff --git a/src/components/organisms/SoftwareTabs/index.jsx b/src/components/organisms/SoftwareTabs/index.jsx index ebb96f9..d346135 100644 --- a/src/components/organisms/SoftwareTabs/index.jsx +++ b/src/components/organisms/SoftwareTabs/index.jsx @@ -133,6 +133,8 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports +// Provides its connected component with the pieces of the data it needs from +// the store, and the functions it can use to dispatch actions to the store. export default connect(mapStateToProps, mapDispatchToProps)(SoftwareTabs); //#endregion diff --git a/src/components/organisms/tabs/TalksTab/index.jsx b/src/components/organisms/tabs/TalksTab/index.jsx index 88e0ae5..5b3630c 100644 --- a/src/components/organisms/tabs/TalksTab/index.jsx +++ b/src/components/organisms/tabs/TalksTab/index.jsx @@ -226,6 +226,10 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports +// Provides its connected component with the pieces of the data it needs from +// the store, and the functions it can use to dispatch actions to the store. +// Got access to the history object’s properties and the closest +// 's match. export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Talks)); //#endregion diff --git a/src/components/pages/HomePage/index.jsx b/src/components/pages/HomePage/index.jsx index fdd29df..081cff6 100644 --- a/src/components/pages/HomePage/index.jsx +++ b/src/components/pages/HomePage/index.jsx @@ -312,6 +312,8 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports +// Provides its connected component with the pieces of the data it needs from +// the store, and the functions it can use to dispatch actions to the store. export default connect(mapStateToProps, mapDispatchToProps)(HomePage); //#endregion diff --git a/src/components/pages/ProfilePage/index.jsx b/src/components/pages/ProfilePage/index.jsx index 83ae72e..5ffa2c9 100644 --- a/src/components/pages/ProfilePage/index.jsx +++ b/src/components/pages/ProfilePage/index.jsx @@ -160,6 +160,10 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports +// Provides its connected component with the pieces of the data it needs from +// the store, and the functions it can use to dispatch actions to the store. +// Got access to the history object’s properties and the closest +// 's match. export default withRouter( connect(mapStateToProps, mapDispatchToProps)(ProfilePage) ); diff --git a/src/components/pages/SettingsPage/index.jsx b/src/components/pages/SettingsPage/index.jsx index 998ee0e..18fb3ae 100644 --- a/src/components/pages/SettingsPage/index.jsx +++ b/src/components/pages/SettingsPage/index.jsx @@ -577,6 +577,10 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports +// Provides its connected component with the pieces of the data it needs from +// the store, and the functions it can use to dispatch actions to the store. +// Got access to the history object’s properties and the closest +// 's match. export default connect(mapStateToProps, mapDispatchToProps)(SettingsPage); //#endregion diff --git a/src/components/pages/TalkPage/index.jsx b/src/components/pages/TalkPage/index.jsx index ede680d..ce08702 100644 --- a/src/components/pages/TalkPage/index.jsx +++ b/src/components/pages/TalkPage/index.jsx @@ -387,6 +387,10 @@ const mapDispatchToProps = (dispatch) => { }; //#region > Exports +// Provides its connected component with the pieces of the data it needs from +// the store, and the functions it can use to dispatch actions to the store. +// Got access to the history object’s properties and the closest +// 's match. export default connect(mapStateToProps, mapDispatchToProps)(TalkPage); //#endregion From 8ccf8cc6a192fc4ef3e727e636d2b13fa9778f72 Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 6 Jul 2020 16:46:12 +0200 Subject: [PATCH 48/86] Logs Cleanup All unnecessary console logs are removed now. --- src/components/atoms/SearchBar/index.jsx | 36 ++++++++----------- src/components/molecules/Navbar/index.jsx | 2 +- .../molecules/UserActionCard/index.jsx | 1 - .../molecules/forms/RegisterForm/index.jsx | 4 +-- .../organisms/ProfileInfo/index.jsx | 3 +- .../organisms/SoftwareTabs/index.jsx | 6 ---- .../profiles/SoftwareEngineer/index.jsx | 4 --- .../organisms/tabs/TalksTab/index.jsx | 5 --- src/components/pages/ProfilePage/index.jsx | 19 +--------- src/components/pages/TalkPage/index.jsx | 6 +--- src/store/actions/authActions.js | 8 ----- src/store/actions/generalActions.js | 1 - src/store/actions/userActions.js | 5 +-- 13 files changed, 21 insertions(+), 79 deletions(-) diff --git a/src/components/atoms/SearchBar/index.jsx b/src/components/atoms/SearchBar/index.jsx index 5a34bcc..7b0bbc7 100644 --- a/src/components/atoms/SearchBar/index.jsx +++ b/src/components/atoms/SearchBar/index.jsx @@ -38,7 +38,6 @@ class SearchBar extends React.Component { componentDidMount() { if (this.state.loading) { this.props.allUsernames().then(() => { - console.log("ALL USERNAMES", this.props.allRegisteredUsernames); this.setState({ loading: false, usernames: this.props.allRegisteredUsernames, @@ -56,7 +55,6 @@ class SearchBar extends React.Component { }; search = (event) => { - console.log(event); const value = event.target.value; // 'keypress' event misbehaves on mobile so we track 'Enter' key via 'keydown' event @@ -72,8 +70,6 @@ class SearchBar extends React.Component { }; render() { - console.log("RENDER NAV"); - console.log(fuzzysort); //Select component does not support onChange event. Instead, you can use getValue or getTextContent methods. return ( {!this.state.loading && this.state.usernames ? ( - (console.log(this.state.usernames), - this.state.usernames.length > 0 && this.state.filter.length > 0 - ? (console.log("FUZZY"), - fuzzysort - .go(this.state.filter, this.state.usernames) - .map((element, i) => { - console.log("FUZZY ELEMNET", element); - return ( - - {element.target} - - ); - })) - : null) + this.state.usernames.length > 0 && this.state.filter.length > 0 ? ( + fuzzysort + .go(this.state.filter, this.state.usernames) + .map((element, i) => { + console.log("FUZZY ELEMNET", element); + return ( + + {element.target} + + ); + }) + ) : null ) : ( Loading )} diff --git a/src/components/molecules/Navbar/index.jsx b/src/components/molecules/Navbar/index.jsx index e3b134b..4381599 100644 --- a/src/components/molecules/Navbar/index.jsx +++ b/src/components/molecules/Navbar/index.jsx @@ -61,7 +61,7 @@ class Navbar extends React.Component { render() { const { location, loggedUser } = this.props; - console.log(this.props); + return ( diff --git a/src/components/molecules/UserActionCard/index.jsx b/src/components/molecules/UserActionCard/index.jsx index 4a5f7a8..dd48322 100644 --- a/src/components/molecules/UserActionCard/index.jsx +++ b/src/components/molecules/UserActionCard/index.jsx @@ -26,7 +26,6 @@ class UserActionCard extends React.Component { }; goTo = (item) => { - console.log(item); this.setState({ activeItem: item, }); diff --git a/src/components/molecules/forms/RegisterForm/index.jsx b/src/components/molecules/forms/RegisterForm/index.jsx index ddaaa92..7f438c4 100644 --- a/src/components/molecules/forms/RegisterForm/index.jsx +++ b/src/components/molecules/forms/RegisterForm/index.jsx @@ -410,12 +410,10 @@ class RegisterForm extends React.Component { gift_code: promoCode && code !== "" ? code : null, password: password1, }; - console.log(this.props); + this.props.register(registrationData).then(() => { const { username, password } = registrationData; - console.log({ username, password }); - this.props.login({ username, password, diff --git a/src/components/organisms/ProfileInfo/index.jsx b/src/components/organisms/ProfileInfo/index.jsx index 68c7798..da37323 100644 --- a/src/components/organisms/ProfileInfo/index.jsx +++ b/src/components/organisms/ProfileInfo/index.jsx @@ -29,8 +29,7 @@ class ProfileInfo extends React.Component { componentDidMount = () => { const { fetchedUser } = this.props; - console.log(this.props); - console.log("PROFILE INFO", fetchedUser); + if (fetchedUser && !this.state.sources) { this.displaySources(fetchedUser.platformData.profile.sources); } diff --git a/src/components/organisms/SoftwareTabs/index.jsx b/src/components/organisms/SoftwareTabs/index.jsx index d346135..f91b66a 100644 --- a/src/components/organisms/SoftwareTabs/index.jsx +++ b/src/components/organisms/SoftwareTabs/index.jsx @@ -26,16 +26,10 @@ class SoftwareTabs extends React.Component { }); }; - componentDidUpdate() { - console.log("UPDATE SOFTWARE TABS", this.state.activeTab); - } - render() { const { fetchedUser } = this.props; const { activeTab } = this.state; - console.log(fetchedUser); - const tabItems = [ { title: "Overview", diff --git a/src/components/organisms/profiles/SoftwareEngineer/index.jsx b/src/components/organisms/profiles/SoftwareEngineer/index.jsx index 47ccf17..bb556cd 100644 --- a/src/components/organisms/profiles/SoftwareEngineer/index.jsx +++ b/src/components/organisms/profiles/SoftwareEngineer/index.jsx @@ -15,10 +15,6 @@ import { SoftwareTabs, ProfileInfo } from "../../index"; class SoftwareEngineer extends React.Component { state = {}; - componentDidUpdate() { - console.log("UPDATE SOFTWARE ENGINEER"); - } - render() { return ( diff --git a/src/components/organisms/tabs/TalksTab/index.jsx b/src/components/organisms/tabs/TalksTab/index.jsx index 5b3630c..b53c15d 100644 --- a/src/components/organisms/tabs/TalksTab/index.jsx +++ b/src/components/organisms/tabs/TalksTab/index.jsx @@ -35,10 +35,6 @@ class Talks extends React.Component { loading: true, }; - componentDidUpdate() { - console.log("UPDATE TALKS TAB"); - } - handleUploadClose = () => { if (this.state.showUpload) { this.setState({ @@ -61,7 +57,6 @@ class Talks extends React.Component { render() { const { loggedUser, fetchedUser } = this.props; const talkList = fetchedUser?.platformData?.talks; - console.log("rerender"); if (talkList) { talkList.map((talk) => { diff --git a/src/components/pages/ProfilePage/index.jsx b/src/components/pages/ProfilePage/index.jsx index 5ffa2c9..506cf90 100644 --- a/src/components/pages/ProfilePage/index.jsx +++ b/src/components/pages/ProfilePage/index.jsx @@ -66,21 +66,10 @@ class ProfilePage extends React.Component { const { match, loggedUser, fetchedUser } = this.props; const username = match?.params?.username; - console.log("BAR USERNAME", username); - console.log("REFETCH REQUIRED", this.refetchRequired(username)); - console.log("LOGGED", loggedUser); - console.log("FETCHED", fetchedUser); - console.log( - "USERNAME MATCHES FETCHED USERNAME", - this.usernameMatchesFetchedUsername(username) - ); if (username) { if (this.refetchRequired(username)) { this.props.readCache(username); } - console.log( - !loggedUser.anonymous && loggedUser.username === fetchedUser?.username - ); } }; @@ -92,15 +81,9 @@ class ProfilePage extends React.Component { !loggedUser.anonymous && loggedUser.username === fetchedUser?.username ) { - console.log("UPDATE CACHE"); this.props.updateCache(fetchedUser).then(() => { - console.log("UPDATEd"); if (this._isMounted) { this.props.readCache(loggedUser.username); - - console.log("CACHING DONE", this.props.fetchedUser); - } else { - console.log("CACHING DONE BUT NOT MOUNTED"); } }); } @@ -118,7 +101,7 @@ class ProfilePage extends React.Component { render() { const { fetchedUser } = this.props; - console.log(fetchedUser); + if (!fetchedUser) { return (
    diff --git a/src/components/pages/TalkPage/index.jsx b/src/components/pages/TalkPage/index.jsx index ce08702..8ef09ea 100644 --- a/src/components/pages/TalkPage/index.jsx +++ b/src/components/pages/TalkPage/index.jsx @@ -37,10 +37,6 @@ class TalkPage extends React.Component { talk: undefined, }; - componentDidUpdate = () => { - console.log("UPDATE"); - }; - componentDidMount = () => { const { uid, username } = this.props.match?.params; @@ -79,7 +75,7 @@ class TalkPage extends React.Component { render() { const talk = this.state.talk; - console.log(this.state); + return (
    {talk && ( diff --git a/src/store/actions/authActions.js b/src/store/actions/authActions.js index 961b440..555269b 100644 --- a/src/store/actions/authActions.js +++ b/src/store/actions/authActions.js @@ -6,21 +6,14 @@ * @description Handles states for login */ const loginAction = (user) => { - console.log("USER", user); - console.log("run action"); return (dispatch, getState, { getIntel }) => { try { const intel = getIntel(); - console.log(intel); - const session = intel.snekclient.session; - console.log(session); - return session .begin(user) .then((whoami) => { - console.log("WHOAMI", whoami); if (whoami?.username !== process.env.REACT_APP_ANONYMOUS_USER) { dispatch({ type: "LOGIN_SUCCESS", @@ -31,7 +24,6 @@ const loginAction = (user) => { }, }); } else { - console.log(whoami.username, process.env.REACT_APP_ANONYMOUS_USER); dispatch({ type: "LOGIN_ANON_SUCCESS", payload: {}, diff --git a/src/store/actions/generalActions.js b/src/store/actions/generalActions.js index 13ab304..37c2d64 100644 --- a/src/store/actions/generalActions.js +++ b/src/store/actions/generalActions.js @@ -107,7 +107,6 @@ const getDataAction = () => { const getAllPageUrlsAction = () => { return async (dispatch, getState, { getIntel }) => { try { - console.log("getAllPageUrlsAction"); const intel = getIntel(); const session = intel.snekclient.session; diff --git a/src/store/actions/userActions.js b/src/store/actions/userActions.js index 1610c26..9e886ae 100644 --- a/src/store/actions/userActions.js +++ b/src/store/actions/userActions.js @@ -306,15 +306,12 @@ const updateCacheAction = (fetchedUser) => { const saveSettingsActions = (nextSettings) => { return async (dispatch, getState, { getIntel }) => { try { - console.log("save settings"); const intel = getIntel(); const state = getState(); const fetchedUser = state.user.fetchedUser; const session = intel.snekclient.session; - console.log("save settings", fetchedUser, nextSettings); - if (fetchedUser.platformData) { // Check for mandatory fields if (nextSettings.email) { @@ -482,7 +479,7 @@ const uploadTalkAction = (file, talkInfo) => { talks[talks.length - 1].repository = talkInfo; fetchedUser.platformData.talks.push(talks[talks.length - 1]); - console.log("BEFORE CACHING"); + session.tasks.user .cache(JSON.stringify(fetchedUser.platformData)) .then(() => From d5793ac04e1ec3cd65374457562d0c74de827667 Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 6 Jul 2020 19:20:53 +0200 Subject: [PATCH 49/86] Implement Loading Bar on Cache Update Now there is a loading bar which gets displayed when updatingCache action is running. In future, there will be a separate loading bar for this purpose. --- src/App.js | 4 ++++ src/store/actions/userActions.js | 5 +++++ src/utilities/_base.scss | 9 +++++++++ 3 files changed, 18 insertions(+) diff --git a/src/App.js b/src/App.js index 887dd19..80c79bc 100644 --- a/src/App.js +++ b/src/App.js @@ -19,6 +19,7 @@ import { Footer, Navbar } from "./components/molecules"; import { ScrollToTop } from "./components/atoms"; //> Routes import Routes from "./Routes"; +import LoadingBarContainer from "react-redux-loading-bar"; //#endregion //#region > Components @@ -34,6 +35,9 @@ function App() { return ( <> +
    + +
    diff --git a/src/store/actions/userActions.js b/src/store/actions/userActions.js index 9e886ae..69369d6 100644 --- a/src/store/actions/userActions.js +++ b/src/store/actions/userActions.js @@ -3,6 +3,7 @@ // SHA Hashing algorithm import sha256 from "js-sha256"; //#endregion +import { showLoading, hideLoading } from "react-redux-loading-bar"; //#region > Register Actions /** @@ -235,6 +236,8 @@ const readCacheAction = (username) => { const updateCacheAction = (fetchedUser) => { return async (dispatch, getState, { getIntel }) => { try { + dispatch(showLoading()); + const intel = getIntel(); const session = intel.snekclient.session; @@ -274,6 +277,8 @@ const updateCacheAction = (fetchedUser) => { intel.resetReducer(); + dispatch(hideLoading()); + return session.tasks.user .cache(JSON.stringify(fetchedUser.platformData)) .then( diff --git a/src/utilities/_base.scss b/src/utilities/_base.scss index e27c219..3315ad1 100644 --- a/src/utilities/_base.scss +++ b/src/utilities/_base.scss @@ -172,6 +172,15 @@ } } +// Loading bar +.loading { + z-index: 99999; + height: 3px; + width: auto; + position: fixed; + background-color: #4285f4; +} + /** * SPDX-License-Identifier: (EUPL-1.2) * Copyright © 2019-2020 Simon Prast From 1c776ab9d39b63d37473b528f1cea3c3a092fafb Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 6 Jul 2020 19:32:02 +0200 Subject: [PATCH 50/86] Improve Code Quality Suggestions of @pinterid have been applied. --- src/Routes.js | 11 ++++++++--- src/store/actions/authActions.js | 3 ++- src/store/actions/userActions.js | 3 +++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/Routes.js b/src/Routes.js index 6863858..f4fa545 100644 --- a/src/Routes.js +++ b/src/Routes.js @@ -25,9 +25,13 @@ class Routes extends React.Component { } + component={(props) => } + /> + } /> - } /> } /> - {/* Some debugging routes */} + {/* Some debugging routes start*/} Not Found; @@ -74,6 +78,7 @@ class Routes extends React.Component { return

    Third Layer

    ; }} /> + {/* Some debugging routes end*/} ); } diff --git a/src/store/actions/authActions.js b/src/store/actions/authActions.js index 555269b..507cdc9 100644 --- a/src/store/actions/authActions.js +++ b/src/store/actions/authActions.js @@ -1,6 +1,6 @@ //#region > Authentication Actions /** - * Handle login + * Handle login. * * @param user A user to login with * @description Handles states for login @@ -59,6 +59,7 @@ const logoutAction = () => { try { const intel = getIntel(); const session = intel.snekclient.session; + await session .end() .then(() => diff --git a/src/store/actions/userActions.js b/src/store/actions/userActions.js index 69369d6..62d8c53 100644 --- a/src/store/actions/userActions.js +++ b/src/store/actions/userActions.js @@ -124,6 +124,8 @@ const writeCacheAction = (platformData) => { const readCacheAction = (username) => { return async (dispatch, getState, { getIntel }) => { try { + dispatch(showLoading()); + const intel = getIntel(); const session = intel.snekclient.session; @@ -203,6 +205,7 @@ const readCacheAction = (username) => { : null, }, }; + dispatch(hideLoading()); dispatch({ type: "READ_CACHE_SUCCESS", From eef3053871d68221e0123e4dd8a4bff41d0c865d Mon Sep 17 00:00:00 2001 From: schettn Date: Tue, 7 Jul 2020 10:10:13 +0200 Subject: [PATCH 51/86] 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 52/86] 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 53/86] 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 ( <> {/*
    - {this.props.platformData && this.state.width > 500 && ( + {this.state.width > 500 && ( <> -
    -
    +
    +

    Contributions

    +
    +
    +

    + {this.state.contrib.countTotal} +

    +

    Total

    +

    + {this.state.contrib.datesTotal} +

    +
    +
    +

    + {this.state.contrib.maxCount} +

    +

    Best day

    +

    + {this.state.contrib.dateBest} +

    +
    +
    +

    + Average:{" "} + + {this.state.contrib.averageCount} + {" "} + / day +

    +
    +
    +

    Streaks

    +
    +
    +

    + {this.state.streak.streakLongest}{" "} + days +

    +

    Longest

    +

    + {this.state.streak.datesLongest} +

    +
    +
    +

    + {this.state.streak.streakCurrent}{" "} + days +

    +

    Current

    +

    + {this.state.streak.datesCurrent} +

    +
    +
    +
    )}
    (this.context = c)} width={this.state.width} - height="350" + height="400" >
    {this.state.cache && } From 532224dd89eb77508273e82e9b329bed897714d3 Mon Sep 17 00:00:00 2001 From: Christian Aichner Date: Tue, 7 Jul 2020 20:37:53 +0200 Subject: [PATCH 61/86] Improve Language chart There is now a grey chart if there is no language found. --- .../atoms/charts/LanguageBar/index.jsx | 54 +++++++++++-------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/src/components/atoms/charts/LanguageBar/index.jsx b/src/components/atoms/charts/LanguageBar/index.jsx index f3c2261..f79c301 100644 --- a/src/components/atoms/charts/LanguageBar/index.jsx +++ b/src/components/atoms/charts/LanguageBar/index.jsx @@ -17,41 +17,53 @@ class LanguageBar extends React.Component { renderBars = (languages) => { let latest = 0; - return languages.map((language, i) => { - const { color, share } = language; - const value = latest + share; + console.log("LANG", languages); - latest += share; + if (languages[0].size !== 0) { + return languages.map((language, i) => { + const { color, share } = language; + const value = latest + share; + latest += share; + + return ( +
    + ); + }); + } else { return (
    ); - }); + } }; render() { const { languages, height } = this.props; - if (languages) { - return ( -
    - {this.renderBars(languages)} -
    - ); - } else { - return null; - } + return ( +
    + {this.renderBars(languages)} +
    + ); } } //#endregion From 1308d04c56115615bdf2097383a969da2b571dd4 Mon Sep 17 00:00:00 2001 From: Christian Aichner Date: Tue, 7 Jul 2020 20:38:16 +0200 Subject: [PATCH 62/86] Improve design The design of buttons and pinned items has been improved. --- src/components/molecules/Footer/index.jsx | 4 ++-- src/components/molecules/Navbar/index.jsx | 2 +- src/components/molecules/UserActionCard/index.jsx | 2 +- src/components/molecules/forms/LoginForm/index.jsx | 2 +- src/components/molecules/forms/RegisterForm/index.jsx | 1 + src/components/molecules/modals/ProfilePictureModal/index.jsx | 1 + src/components/organisms/ProfileInfo/index.jsx | 2 +- src/components/organisms/SoftwareTabs/index.jsx | 2 +- src/components/organisms/tabs/OverviewTab/index.jsx | 2 +- src/components/organisms/tabs/TalksTab/index.jsx | 1 + src/components/pages/TalkPage/index.jsx | 2 +- 11 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/components/molecules/Footer/index.jsx b/src/components/molecules/Footer/index.jsx index 7fdbe0a..f0a6510 100644 --- a/src/components/molecules/Footer/index.jsx +++ b/src/components/molecules/Footer/index.jsx @@ -207,13 +207,13 @@ class Footer extends React.PureComponent {

    {this.state.slogan}

    {this.props.location.pathname === "/" ? ( - + Join now ) : ( - + Join now diff --git a/src/components/molecules/Navbar/index.jsx b/src/components/molecules/Navbar/index.jsx index 4381599..5f3e1b3 100644 --- a/src/components/molecules/Navbar/index.jsx +++ b/src/components/molecules/Navbar/index.jsx @@ -155,7 +155,7 @@ class Navbar extends React.Component { }, }} > - + Sign In diff --git a/src/components/molecules/UserActionCard/index.jsx b/src/components/molecules/UserActionCard/index.jsx index dd48322..705cfad 100644 --- a/src/components/molecules/UserActionCard/index.jsx +++ b/src/components/molecules/UserActionCard/index.jsx @@ -44,7 +44,7 @@ class UserActionCard extends React.Component {
    {activeItem === 0 && ( <> - this.setActiveItem(1)}> + this.setActiveItem(1)}> Login to SNEK
    diff --git a/src/components/molecules/forms/LoginForm/index.jsx b/src/components/molecules/forms/LoginForm/index.jsx index 9e782d2..098b938 100644 --- a/src/components/molecules/forms/LoginForm/index.jsx +++ b/src/components/molecules/forms/LoginForm/index.jsx @@ -188,7 +188,7 @@ class LoginForm extends React.Component { } value={this.state.login_password} /> - + Login diff --git a/src/components/molecules/forms/RegisterForm/index.jsx b/src/components/molecules/forms/RegisterForm/index.jsx index 7f438c4..a084cff 100644 --- a/src/components/molecules/forms/RegisterForm/index.jsx +++ b/src/components/molecules/forms/RegisterForm/index.jsx @@ -736,6 +736,7 @@ class RegisterForm extends React.Component {
    - + Follow diff --git a/src/components/organisms/SoftwareTabs/index.jsx b/src/components/organisms/SoftwareTabs/index.jsx index f91b66a..f9da088 100644 --- a/src/components/organisms/SoftwareTabs/index.jsx +++ b/src/components/organisms/SoftwareTabs/index.jsx @@ -90,7 +90,7 @@ class SoftwareTabs extends React.Component { ); })} -
    +
    {activeTab === 0 && ( diff --git a/src/components/organisms/tabs/TalksTab/index.jsx b/src/components/organisms/tabs/TalksTab/index.jsx index b53c15d..3d186c5 100644 --- a/src/components/organisms/tabs/TalksTab/index.jsx +++ b/src/components/organisms/tabs/TalksTab/index.jsx @@ -87,6 +87,7 @@ class Talks extends React.Component { this.setState({ showUpload: true })} > diff --git a/src/components/pages/TalkPage/index.jsx b/src/components/pages/TalkPage/index.jsx index 8ef09ea..cdb23e0 100644 --- a/src/components/pages/TalkPage/index.jsx +++ b/src/components/pages/TalkPage/index.jsx @@ -151,7 +151,7 @@ class TalkPage extends React.Component { - + Follow From 261c35031a5755ae725ee98ffc4842d931ca15e0 Mon Sep 17 00:00:00 2001 From: Christian Aichner Date: Tue, 7 Jul 2020 20:47:06 +0200 Subject: [PATCH 63/86] Add profile button to main navbar The profile button has been moved. --- src/components/molecules/Navbar/index.jsx | 13 +++++++------ src/components/molecules/Navbar/navbar.scss | 10 ++++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/components/molecules/Navbar/index.jsx b/src/components/molecules/Navbar/index.jsx index 5f3e1b3..a0ec1ae 100644 --- a/src/components/molecules/Navbar/index.jsx +++ b/src/components/molecules/Navbar/index.jsx @@ -21,6 +21,7 @@ import { MDBDropdownMenu, MDBSmoothScroll, MDBBtn, + MDBIcon, } from "mdbreact"; //> Redux import { connect } from "react-redux"; @@ -113,6 +114,12 @@ class Navbar extends React.Component { {!loggedUser.anonymous ? ( <> + + + + Profile + +
    @@ -124,12 +131,6 @@ class Navbar extends React.Component { /> - - My profile - Settings diff --git a/src/components/molecules/Navbar/navbar.scss b/src/components/molecules/Navbar/navbar.scss index b9ed1c3..155ffd5 100644 --- a/src/components/molecules/Navbar/navbar.scss +++ b/src/components/molecules/Navbar/navbar.scss @@ -5,6 +5,16 @@ box-shadow: none; background: #f0f0f0; + .btn-white { + background: transparentize($color: white, $amount: 0.3) !important; + border: 2px white solid; + padding: 0.5rem 0.8rem; + &:hover { + background: white !important; + border: 2px $snekGreen solid; + } + } + li { align-self: center; From afa82374638fc7e53cfdebe64312d0b32c18142d Mon Sep 17 00:00:00 2001 From: Christian Aichner Date: Tue, 7 Jul 2020 20:48:31 +0200 Subject: [PATCH 64/86] Improve profile button on navbar The padding has been adjusted. --- src/components/molecules/Navbar/navbar.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/molecules/Navbar/navbar.scss b/src/components/molecules/Navbar/navbar.scss index 155ffd5..00860fa 100644 --- a/src/components/molecules/Navbar/navbar.scss +++ b/src/components/molecules/Navbar/navbar.scss @@ -8,7 +8,7 @@ .btn-white { background: transparentize($color: white, $amount: 0.3) !important; border: 2px white solid; - padding: 0.5rem 0.8rem; + padding: 0.5rem 1rem; &:hover { background: white !important; border: 2px $snekGreen solid; From f4f71fe3f15b503fae3b8953526b7dda11a8f657 Mon Sep 17 00:00:00 2001 From: Christian Aichner Date: Tue, 7 Jul 2020 21:19:19 +0200 Subject: [PATCH 65/86] Fix day and days seperation The streaks are now marked as days or day. --- src/components/atoms/charts/Calendar3D/index.jsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/atoms/charts/Calendar3D/index.jsx b/src/components/atoms/charts/Calendar3D/index.jsx index e591bbb..25fe331 100644 --- a/src/components/atoms/charts/Calendar3D/index.jsx +++ b/src/components/atoms/charts/Calendar3D/index.jsx @@ -346,7 +346,9 @@ class Calendar3D extends React.Component {

    {this.state.streak.streakLongest}{" "} - days + + {this.state.streak.streakLongest === 1 ? "day" : "days"} +

    Longest

    @@ -356,7 +358,9 @@ class Calendar3D extends React.Component {

    {this.state.streak.streakCurrent}{" "} - days + + {this.state.streak.streakCurrent === 1 ? "day" : "days"} +

    Current

    From cabe83bfd8812a9f19f23325f867d86ba09c5540 Mon Sep 17 00:00:00 2001 From: Christian Aichner Date: Wed, 8 Jul 2020 10:20:42 +0200 Subject: [PATCH 66/86] Improve project cards The slash for owners has been replaced with an @. --- src/components/atoms/Project/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/atoms/Project/index.jsx b/src/components/atoms/Project/index.jsx index bfe243c..271e67e 100644 --- a/src/components/atoms/Project/index.jsx +++ b/src/components/atoms/Project/index.jsx @@ -33,7 +33,7 @@ class Project extends React.Component { : "https://img.favpng.com/4/1/20/computer-icons-gregorio-lvarez-museum-png-favpng-xPCKYGtUJihZeAkdqind0HH2N.jpg" } /> - /{repo.owner.username} + @{repo.owner.username}

    {repo.languages.length > 0 && ( From 0973e70d20bbd4cdead5401e32da086fde90d198 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 8 Jul 2020 10:38:31 +0200 Subject: [PATCH 67/86] Improve Read Cache Action The loading bar is disabled now because it interferes with the caching loading bar. Now the user object is set every time a key is missing. --- src/store/actions/userActions.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/store/actions/userActions.js b/src/store/actions/userActions.js index 62d8c53..e2be49f 100644 --- a/src/store/actions/userActions.js +++ b/src/store/actions/userActions.js @@ -124,8 +124,6 @@ const writeCacheAction = (platformData) => { const readCacheAction = (username) => { return async (dispatch, getState, { getIntel }) => { try { - dispatch(showLoading()); - const intel = getIntel(); const session = intel.snekclient.session; @@ -166,7 +164,18 @@ const readCacheAction = (username) => { }); } else { // Set settings for first time fetching - if (Object.keys(user).length === 0) { + if ( + ![ + "firstName", + "lastName", + "email", + "avatarUrl", + "websiteUrl", + "websiteUrl", + "location", + "company", + ].every((item) => user.hasOwnProperty(item)) + ) { user.firstName = platformData.profile.firstName; user.lastName = platformData.profile.lastName; user.email = platformData.profile.email; @@ -205,7 +214,6 @@ const readCacheAction = (username) => { : null, }, }; - dispatch(hideLoading()); dispatch({ type: "READ_CACHE_SUCCESS", From 3ba02c2ad65d58ec25dab93b74abb1e421ec76d2 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 8 Jul 2020 10:39:34 +0200 Subject: [PATCH 68/86] Improve Write Cache Action Now the platform data is stringified before cached. --- src/store/actions/userActions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/store/actions/userActions.js b/src/store/actions/userActions.js index e2be49f..11f5a7f 100644 --- a/src/store/actions/userActions.js +++ b/src/store/actions/userActions.js @@ -92,7 +92,7 @@ const writeCacheAction = (platformData) => { const session = intel.snekclient.session; return session.tasks.user - .cache(platformData) + .cache(JSON.stringify(platformData)) .then(() => dispatch({ type: "WRITE_CACHE_SUCCESS", From 789a6df62afdc3fe3f267dbbbf15a36534fb394a Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 8 Jul 2020 10:34:22 +0200 Subject: [PATCH 69/86] Implement Movable Pool Save Functionallity Now when pressing the save button the pool gets stored in the platformData. --- .../organisms/tabs/OverviewTab/index.jsx | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/src/components/organisms/tabs/OverviewTab/index.jsx b/src/components/organisms/tabs/OverviewTab/index.jsx index 230e43c..12b394f 100644 --- a/src/components/organisms/tabs/OverviewTab/index.jsx +++ b/src/components/organisms/tabs/OverviewTab/index.jsx @@ -7,7 +7,11 @@ import PropTypes from "prop-types"; //> MDB // "Material Design for Bootstrap" is a great UI design framework import { MDBRow, MDBCol, MDBBtn, MDBIcon } from "mdbreact"; +//> Redux +import { connect } from "react-redux"; +//> Actions +import { writeCacheAction } from "../../../../store/actions/userActions"; //> CSS import "./overviewtab.scss"; //> Components @@ -56,6 +60,7 @@ const pinned = [ class OverviewTab extends React.Component { state = { selectedYear: undefined, + edit: false, }; selectDay = (day, wkey, dkey) => { @@ -68,8 +73,25 @@ class OverviewTab extends React.Component { }); }; + componentDidMount = () => {}; + + handleEditClick = (platformData) => { + if (this.state.edit) { + this.props.writeCache(platformData); + } + this.setState({ edit: !this.state.edit }); + }; + render() { - const { platformData, sameOrigin } = this.props; + const { fetchedUser, sameOrigin } = this.props; + const platformData = fetchedUser.platformData; + + // Create empty pool if there isn't already one + if (!fetchedUser.platformData.user.movablePool) { + fetchedUser.platformData.user.movablePool = {}; + } + + const movablePool = fetchedUser.platformData.user.movablePool; return ( <> @@ -80,7 +102,7 @@ class OverviewTab extends React.Component { this.setState({ edit: !this.state.edit })} + onClick={() => this.handleEditClick(platformData)} > {this.state.edit ? ( @@ -94,6 +116,7 @@ class OverviewTab extends React.Component {
    )} ,
    Redux Mapping +const mapStateToProps = (state) => ({ + fetchedUser: state.user.fetchedUser, +}); + +const mapDispatchToProps = (dispatch) => { + return { + writeCache: (platformData) => dispatch(writeCacheAction(platformData)), + }; +}; +//#endregion + //#region > Exports -export default OverviewTab; +// Provides its connected component with the pieces of the data it needs from +// the store, and the functions it can use to dispatch actions to the store. +export default connect(mapStateToProps, mapDispatchToProps)(OverviewTab); //#endregion /** From 82116487cbfc1e8676ee07fde881fe2425f9335f Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 8 Jul 2020 10:36:05 +0200 Subject: [PATCH 70/86] Replace Local Storage Save with Pool Instead of local storage the indexArray is stored in a passed in object. --- .../molecules/MovableBoundary/index.jsx | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/components/molecules/MovableBoundary/index.jsx b/src/components/molecules/MovableBoundary/index.jsx index 331dd67..701de2b 100644 --- a/src/components/molecules/MovableBoundary/index.jsx +++ b/src/components/molecules/MovableBoundary/index.jsx @@ -41,11 +41,18 @@ class MovableBoundary extends React.Component { this.loadItemOrder(); } + componentDidUpdate(prevProps, prevState) { + // Load items when pool changes + if (prevProps.pool !== this.props.pool) { + 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]); + let indexArray = this.props.pool[this.props.uid]; if (!indexArray) { let baseIndexArray = []; @@ -75,10 +82,7 @@ class MovableBoundary extends React.Component { // Store indexArray. saveItemOrder() { - localStorage.setItem( - [this.props.uid], - JSON.stringify(this.state.indexArray) - ); + this.props.pool[this.props.uid] = JSON.stringify(this.state.indexArray); } // Returns items to be rendered in the Sortable. @@ -142,6 +146,7 @@ class MovableBoundary extends React.Component { //#region > PropTypes MovableBoundary.propTypes = { + pool: PropTypes.object, movementAxis: PropTypes.string, items: PropTypes.array.isRequired, uid: PropTypes.string.isRequired, From dcfeca9378c2ac7a9dd467b6e32891070209b435 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 8 Jul 2020 12:25:19 +0200 Subject: [PATCH 71/86] Improve Movable Boundary Now the item order is saved on swapping --- src/components/molecules/MovableBoundary/index.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/molecules/MovableBoundary/index.jsx b/src/components/molecules/MovableBoundary/index.jsx index 701de2b..facfeaf 100644 --- a/src/components/molecules/MovableBoundary/index.jsx +++ b/src/components/molecules/MovableBoundary/index.jsx @@ -116,6 +116,8 @@ class MovableBoundary extends React.Component { indexArray.splice(newIndex, 0, indexArray.splice(oldIndex, 1)[0]); + // Save item order when items swap + this.saveItemOrder(); this.setState({ indexArray }); }; From 9b895a3e9faad8342ae9421060e83743a68b7d40 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 8 Jul 2020 12:43:05 +0200 Subject: [PATCH 72/86] Improve Code Quality The code quality has been improved due to codacy check. --- src/components/molecules/MovableBoundary/movableboundary.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/molecules/MovableBoundary/movableboundary.scss b/src/components/molecules/MovableBoundary/movableboundary.scss index 65d28c3..d8b447e 100644 --- a/src/components/molecules/MovableBoundary/movableboundary.scss +++ b/src/components/molecules/MovableBoundary/movableboundary.scss @@ -1,3 +1,4 @@ + .SortableItem { list-style: none; cursor: move; From 6357341381d892c39dde4d5c0950eaafdf7fe7ec Mon Sep 17 00:00:00 2001 From: Pinterid Date: Wed, 8 Jul 2020 12:54:24 +0200 Subject: [PATCH 73/86] Fix Codacy The issues marked by Codacy were resolved. --- src/components/organisms/tabs/OverviewTab/overviewtab.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/organisms/tabs/OverviewTab/overviewtab.scss b/src/components/organisms/tabs/OverviewTab/overviewtab.scss index bff3d07..5d9ec32 100644 --- a/src/components/organisms/tabs/OverviewTab/overviewtab.scss +++ b/src/components/organisms/tabs/OverviewTab/overviewtab.scss @@ -16,6 +16,7 @@ .SortableList { display: flex; + .SortableItem { margin: 0.2rem; } From f70bdbd3f94d39e4b66a94976003b56ff5c21c18 Mon Sep 17 00:00:00 2001 From: Pinterid Date: Wed, 8 Jul 2020 13:06:07 +0200 Subject: [PATCH 74/86] Fix Codacy Issues marked by Codacy were resolved. --- src/components/organisms/tabs/OverviewTab/overviewtab.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/organisms/tabs/OverviewTab/overviewtab.scss b/src/components/organisms/tabs/OverviewTab/overviewtab.scss index 5d9ec32..a6627c9 100644 --- a/src/components/organisms/tabs/OverviewTab/overviewtab.scss +++ b/src/components/organisms/tabs/OverviewTab/overviewtab.scss @@ -26,6 +26,7 @@ .interchange-charts { .SortableList { display: flex; + .SortableItem { margin: 0.2rem; } From abcae218e0d5ba8940ba22a88848fc6017fb7e22 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 8 Jul 2020 13:36:15 +0200 Subject: [PATCH 75/86] Improve code quality The code quality has been improved due to a request of @pinterid. --- .../molecules/MovableBoundary/index.jsx | 32 +++++++++---------- .../MovableBoundary/movableboundary.scss | 1 - .../organisms/tabs/OverviewTab/index.jsx | 4 +-- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/components/molecules/MovableBoundary/index.jsx b/src/components/molecules/MovableBoundary/index.jsx index facfeaf..4429767 100644 --- a/src/components/molecules/MovableBoundary/index.jsx +++ b/src/components/molecules/MovableBoundary/index.jsx @@ -1,23 +1,21 @@ //#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"; +import React from "react"; // React PropTypes import PropTypes from "prop-types"; - //> MDB Sortable // MDB plugin for sortable item lists import MDBSortable from "mdb-react-sortable"; -//> SCSS +//> CSS import "./movableboundary.scss"; //#endregion //#region > Components /** - * @class This enables implememntation of horizontally or vertically movable items into a page. + * @class This enables implementation of horizontally or vertically movable + * items into a page. */ class MovableBoundary extends React.Component { state = { @@ -30,14 +28,14 @@ class MovableBoundary extends React.Component { items: nextProps.items ? nextProps.items : null, }); - // If props.edit changes to false, save indexArray. + // If props.edit changes to false, save indexArray if (!nextProps.edit && this.props.edit) { this.saveItemOrder(); } }; componentDidMount() { - // Load item order after mounting. + // Load item order after mounting this.loadItemOrder(); } @@ -48,9 +46,11 @@ class MovableBoundary extends React.Component { } } - // Load the indexArray from storage. - // If there's no indexArray, - // default indexArray [0, 1, 2, 3, ...] will be generated. + /** + * Load the indexArray from storage. + * If there's no indexArray, + * default indexArray [0, 1, 2, 3, ...] will be generated. + */ loadItemOrder() { let indexArray = this.props.pool[this.props.uid]; @@ -69,7 +69,7 @@ class MovableBoundary extends React.Component { this.setState({ indexArray }); } - // Returns items ordered by indexArray. + // Returns items ordered by indexArray reorderItems() { let orderedItems = []; @@ -80,12 +80,12 @@ class MovableBoundary extends React.Component { return orderedItems; } - // Store indexArray. + // Store indexArray saveItemOrder() { this.props.pool[this.props.uid] = JSON.stringify(this.state.indexArray); } - // Returns items to be rendered in the Sortable. + // Returns items to be rendered in the Sortable renderItems(edit) { const items = this.reorderItems(); @@ -102,7 +102,7 @@ class MovableBoundary extends React.Component { }); } - // Swaps indexArray position of element. + // Swaps indexArray position of element swap = (newIndex, oldIndex) => { let indexArray = this.state.indexArray; @@ -134,7 +134,7 @@ class MovableBoundary extends React.Component { } listClassName="SortableList" onSortEnd={(obj, e) => { - // When item is let go of, change indexArray position of Item. + // When item is let go of, change indexArray position of item this.swap(obj.newIndex, obj.oldIndex); }} /> diff --git a/src/components/molecules/MovableBoundary/movableboundary.scss b/src/components/molecules/MovableBoundary/movableboundary.scss index d8b447e..65d28c3 100644 --- a/src/components/molecules/MovableBoundary/movableboundary.scss +++ b/src/components/molecules/MovableBoundary/movableboundary.scss @@ -1,4 +1,3 @@ - .SortableItem { list-style: none; cursor: move; diff --git a/src/components/organisms/tabs/OverviewTab/index.jsx b/src/components/organisms/tabs/OverviewTab/index.jsx index 12b394f..81ebfc4 100644 --- a/src/components/organisms/tabs/OverviewTab/index.jsx +++ b/src/components/organisms/tabs/OverviewTab/index.jsx @@ -24,7 +24,6 @@ import { ErrorBoundary, } from "../../../atoms"; import { MovableBoundary } from "../../../molecules"; - //#endregion //#region > Constant Variables @@ -73,12 +72,11 @@ class OverviewTab extends React.Component { }); }; - componentDidMount = () => {}; - handleEditClick = (platformData) => { if (this.state.edit) { this.props.writeCache(platformData); } + this.setState({ edit: !this.state.edit }); }; From 8469dc000481489b2b83246b0506845bfce72898 Mon Sep 17 00:00:00 2001 From: Christian Aichner Date: Wed, 8 Jul 2020 18:48:47 +0200 Subject: [PATCH 76/86] Improve wording None has been replaced with Unknown in the project item. --- src/components/atoms/Project/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/atoms/Project/index.jsx b/src/components/atoms/Project/index.jsx index 271e67e..ec368dc 100644 --- a/src/components/atoms/Project/index.jsx +++ b/src/components/atoms/Project/index.jsx @@ -46,7 +46,7 @@ class Project extends React.Component { className="pr-1" style={{ color: repo.languages[0].color }} /> - {repo.languages[0].name ? repo.languages[0].name : "none"} + {repo.languages[0].name ? repo.languages[0].name : "Unknown"} )}
    From 0034279a417744ebe87f321ad19697516e19c6ee Mon Sep 17 00:00:00 2001 From: Christian Aichner Date: Wed, 8 Jul 2020 18:53:20 +0200 Subject: [PATCH 77/86] Improve stability If there is no owner for a project, the new owner is unknown. --- src/components/atoms/Project/index.jsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/atoms/Project/index.jsx b/src/components/atoms/Project/index.jsx index ec368dc..4fbe2a4 100644 --- a/src/components/atoms/Project/index.jsx +++ b/src/components/atoms/Project/index.jsx @@ -33,7 +33,14 @@ class Project extends React.Component { : "https://img.favpng.com/4/1/20/computer-icons-gregorio-lvarez-museum-png-favpng-xPCKYGtUJihZeAkdqind0HH2N.jpg" } /> - @{repo.owner.username} + + @ + {repo.owner.username ? ( + repo.owner.username + ) : ( + unknown + )} +
    {repo.languages.length > 0 && ( From f20e71c8b1602d437f3c00c74416de51256e6f13 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 8 Jul 2020 19:00:42 +0200 Subject: [PATCH 78/86] Re-add loading bar styling The loading bar styling, which was previously accidentally removed, is now available again. This will show the loading bar again. --- src/utilities/_base.scss | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/utilities/_base.scss b/src/utilities/_base.scss index df97f34..805ede0 100644 --- a/src/utilities/_base.scss +++ b/src/utilities/_base.scss @@ -198,6 +198,15 @@ } } +// Loading bar +.loading { + z-index: 99999; + height: 3px; + width: auto; + position: fixed; + background-color: #4285f4; +} + /** * SPDX-License-Identifier: (EUPL-1.2) * Copyright © 2019-2020 Simon Prast From d2d0e089e2cf119c36e1a48a78b09e4406ecb2ba Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 8 Jul 2020 20:42:01 +0200 Subject: [PATCH 79/86] Improve code quality Some scss stuff has been fixed due to a codacy request. --- src/components/atoms/Pinned/pinned.scss | 2 ++ src/components/molecules/Navbar/navbar.scss | 1 + src/components/pages/ProfilePage/profile.scss | 2 ++ src/components/pages/TalkPage/talk.scss | 1 - src/utilities/_base.scss | 12 ++++++++++++ 5 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/components/atoms/Pinned/pinned.scss b/src/components/atoms/Pinned/pinned.scss index 7416e9a..b819fa5 100644 --- a/src/components/atoms/Pinned/pinned.scss +++ b/src/components/atoms/Pinned/pinned.scss @@ -2,12 +2,14 @@ .pinned-header { width: 100%; padding: 0.1rem; + .card { border: 1px #e1e4e8 solid; margin-bottom: 2rem; overflow: hidden; border-radius: 0.3rem; } + .card-body { border: none !important; padding: 0.3rem; diff --git a/src/components/molecules/Navbar/navbar.scss b/src/components/molecules/Navbar/navbar.scss index 00860fa..ff57e63 100644 --- a/src/components/molecules/Navbar/navbar.scss +++ b/src/components/molecules/Navbar/navbar.scss @@ -9,6 +9,7 @@ background: transparentize($color: white, $amount: 0.3) !important; border: 2px white solid; padding: 0.5rem 1rem; + &:hover { background: white !important; border: 2px $snekGreen solid; diff --git a/src/components/pages/ProfilePage/profile.scss b/src/components/pages/ProfilePage/profile.scss index 91373de..ac933b9 100644 --- a/src/components/pages/ProfilePage/profile.scss +++ b/src/components/pages/ProfilePage/profile.scss @@ -25,6 +25,7 @@ margin-right: 0.4rem; padding: 0.4rem; border-radius: 0.4rem; + &.badge-secondary-color { background: transparentize( $color: $secondary, @@ -161,6 +162,7 @@ } } } + // General things } diff --git a/src/components/pages/TalkPage/talk.scss b/src/components/pages/TalkPage/talk.scss index 4c1ff16..4c00758 100644 --- a/src/components/pages/TalkPage/talk.scss +++ b/src/components/pages/TalkPage/talk.scss @@ -16,7 +16,6 @@ } .verified-badge { - .badge { background: rgba(0, 200, 81, 0.1) !important; border: 1px #00c851 solid; diff --git a/src/utilities/_base.scss b/src/utilities/_base.scss index 805ede0..37b3c5c 100644 --- a/src/utilities/_base.scss +++ b/src/utilities/_base.scss @@ -44,6 +44,7 @@ ) !important; border: 2px $snekGreen solid; color: darken($snekGreen, 10%); + &:hover { background-color: transparentize( $color: $snekGreen, @@ -51,12 +52,14 @@ ) !important; } } + &.btn-green { background-color: transparentize( $color: $snekGreen, $amount: 0.4 ) !important; border: 2px $snekGreen solid; + &:hover { background-color: transparentize( $color: $snekGreen, @@ -64,14 +67,17 @@ ) !important; } } + &.btn-outline-primary { background-color: transparentize($color: $blue, $amount: 0.9) !important; border: 2px $blue solid; color: darken($blue, 10%); + &:hover { background-color: transparentize($color: $blue, $amount: 0.8) !important; } } + // Button WhatsApp &.btn-wa { background-color: #25d366 !important; @@ -88,21 +94,27 @@ // Custom colors .snek-dark { background-color: $snekDark !important; + &.darken-1 { background-color: darken($snekDark, 5%) !important; } + &.darken-2 { background-color: darken($snekDark, 10%) !important; } + &.darken-3 { background-color: darken($snekDark, 15%) !important; } + &.lighten-1 { background-color: lighten($snekDark, 10%) !important; } + &.lighten-2 { background-color: lighten($snekDark, 20%) !important; } + &.lighten-3 { background-color: lighten($snekDark, 30%) !important; } From c01d1d6b3b18aeeb1c2c6c1d592fdf50f3d759a4 Mon Sep 17 00:00:00 2001 From: Schett Nico <52858351+schettn@users.noreply.github.com> Date: Wed, 8 Jul 2020 20:48:53 +0200 Subject: [PATCH 80/86] Apply suggestions from code review Co-authored-by: Aichner Christian --- src/components/atoms/charts/LanguageBar/index.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/atoms/charts/LanguageBar/index.jsx b/src/components/atoms/charts/LanguageBar/index.jsx index f79c301..1ec20ff 100644 --- a/src/components/atoms/charts/LanguageBar/index.jsx +++ b/src/components/atoms/charts/LanguageBar/index.jsx @@ -17,7 +17,6 @@ class LanguageBar extends React.Component { renderBars = (languages) => { let latest = 0; - console.log("LANG", languages); if (languages[0].size !== 0) { return languages.map((language, i) => { From 2e6d448c358bf228792cd62440ec8af2cbccffcc Mon Sep 17 00:00:00 2001 From: Schett Nico <52858351+schettn@users.noreply.github.com> Date: Wed, 8 Jul 2020 20:50:09 +0200 Subject: [PATCH 81/86] Apply suggestions from code review --- src/components/atoms/charts/LanguageBar/index.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/atoms/charts/LanguageBar/index.jsx b/src/components/atoms/charts/LanguageBar/index.jsx index 1ec20ff..4e00db3 100644 --- a/src/components/atoms/charts/LanguageBar/index.jsx +++ b/src/components/atoms/charts/LanguageBar/index.jsx @@ -17,7 +17,6 @@ class LanguageBar extends React.Component { renderBars = (languages) => { let latest = 0; - if (languages[0].size !== 0) { return languages.map((language, i) => { const { color, share } = language; From bc0eb01ee97606888554577c492dee4626ab8b59 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 8 Jul 2020 21:17:14 +0200 Subject: [PATCH 82/86] Improve code quality The code quality has been improved due to request of @aichnerc @pinterid @kleberbaum. --- src/App.js | 3 +++ src/components/atoms/SearchBar/index.jsx | 14 +++++++++----- src/components/molecules/Navbar/index.jsx | 13 +++++++++---- .../molecules/forms/LoginForm/index.jsx | 11 +++++++---- .../molecules/forms/RegisterForm/index.jsx | 9 +++++++-- src/components/organisms/ProfileInfo/index.jsx | 8 ++++++-- src/components/organisms/SoftwareTabs/index.jsx | 10 ++++++---- .../organisms/tabs/OverviewTab/index.jsx | 9 +++++++-- src/components/organisms/tabs/TalksTab/index.jsx | 15 ++++++++++----- src/components/pages/HomePage/index.jsx | 8 ++++++-- src/components/pages/ProfilePage/index.jsx | 13 +++++++++---- src/components/pages/SettingsPage/index.jsx | 11 +++++++---- src/components/pages/TalkPage/index.jsx | 11 +++++++---- src/index.js | 2 ++ src/store/reducers/index.js | 2 ++ 15 files changed, 97 insertions(+), 42 deletions(-) diff --git a/src/App.js b/src/App.js index 80c79bc..4d3e306 100644 --- a/src/App.js +++ b/src/App.js @@ -5,9 +5,12 @@ import React, { useEffect } from "react"; // DOM bindings for React Router import { withRouter } from "react-router-dom"; //> Redux +// Allows to React components read data from a Redux store, and dispatch actions +// to the store to update data. import { useDispatch } from "react-redux"; //> Actions +// Functions to send data from the application to the store import { loginAction } from "./store/actions/authActions"; //> Components /** diff --git a/src/components/atoms/SearchBar/index.jsx b/src/components/atoms/SearchBar/index.jsx index 7b0bbc7..b73881a 100644 --- a/src/components/atoms/SearchBar/index.jsx +++ b/src/components/atoms/SearchBar/index.jsx @@ -16,9 +16,12 @@ import { // Fast SublimeText-like fuzzy search for JavaScript import * as fuzzysort from "fuzzysort"; //> Redux +// Allows to React components read data from a Redux store, and dispatch actions +// to the store to update data. import { connect } from "react-redux"; //> Actions +// Functions to send data from the application to the store import { getAllPageUrlsAction } from "../../../store/actions/generalActions"; //> CSS import "./search.scss"; @@ -85,7 +88,6 @@ class SearchBar extends React.Component { fuzzysort .go(this.state.filter, this.state.usernames) .map((element, i) => { - console.log("FUZZY ELEMNET", element); return ( { //#endregion //#region > Exports -// Provides its connected component with the pieces of the data it needs from -// the store, and the functions it can use to dispatch actions to the store. -// Got access to the history object’s properties and the closest -// 's match. +/** + * Provides its connected component with the pieces of the data it needs from + * the store, and the functions it can use to dispatch actions to the store. + * Got access to the history object’s properties and the closest + * 's match. + */ export default withRouter( connect(mapStateToProps, mapDispatchToProps)(SearchBar) ); diff --git a/src/components/molecules/Navbar/index.jsx b/src/components/molecules/Navbar/index.jsx index a0ec1ae..58b664c 100644 --- a/src/components/molecules/Navbar/index.jsx +++ b/src/components/molecules/Navbar/index.jsx @@ -24,9 +24,12 @@ import { MDBIcon, } from "mdbreact"; //> Redux +// Allows to React components read data from a Redux store, and dispatch actions +// to the store to update data. import { connect } from "react-redux"; //> Actions +// Functions to send data from the application to the store import { logoutAction } from "../../../store/actions/authActions"; //> SearchBar import { SearchBar } from "../../atoms"; @@ -192,10 +195,12 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -// Provides its connected component with the pieces of the data it needs from -// the store, and the functions it can use to dispatch actions to the store. -// Got access to the history object’s properties and the closest -// 's match. +/** + * Provides its connected component with the pieces of the data it needs from + * the store, and the functions it can use to dispatch actions to the store. + * Got access to the history object’s properties and the closest + * 's match. + */ export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Navbar)); //#endregion diff --git a/src/components/molecules/forms/LoginForm/index.jsx b/src/components/molecules/forms/LoginForm/index.jsx index 098b938..5d48a78 100644 --- a/src/components/molecules/forms/LoginForm/index.jsx +++ b/src/components/molecules/forms/LoginForm/index.jsx @@ -11,9 +11,12 @@ import { MDBAlert, MDBBtn, MDBIcon } from "mdbreact"; // SHA hashing algorithm import { sha256 } from "js-sha256"; //> Redux +// Allows to React components read data from a Redux store, and dispatch actions +// to the store to update data. import { connect } from "react-redux"; //> Actions +// Functions to send data from the application to the store import { loginAction } from "../../../../store/actions/authActions"; //#endregion @@ -214,10 +217,10 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -// Provides its connected component with the pieces of the data it needs from -// the store, and the functions it can use to dispatch actions to the store. -// Got access to the history object’s properties and the closest -// 's match. +/** + * Provides its connected component with the pieces of the data it needs from + * the store, and the functions it can use to dispatch actions to the store. + */ export default connect(mapStateToProps, mapDispatchToProps)(LoginForm); //#endregion diff --git a/src/components/molecules/forms/RegisterForm/index.jsx b/src/components/molecules/forms/RegisterForm/index.jsx index a084cff..08b4e85 100644 --- a/src/components/molecules/forms/RegisterForm/index.jsx +++ b/src/components/molecules/forms/RegisterForm/index.jsx @@ -32,9 +32,12 @@ import { //> OAuth import GitHubOAuth from "reactjs-oauth"; //> Redux +// Allows to React components read data from a Redux store, and dispatch actions +// to the store to update data. import { connect } from "react-redux"; //> Actions +// Functions to send data from the application to the store import { registerAction } from "../../../../store/actions/userActions"; import { fetchGitLabServersAction } from "../../../../store/actions/generalActions"; import { loginAction } from "../../../../store/actions/authActions"; @@ -859,8 +862,10 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -// Provides its connected component with the pieces of the data it needs from -// the store, and the functions it can use to dispatch actions to the store. +/** + * Provides its connected component with the pieces of the data it needs from + * the store, and the functions it can use to dispatch actions to the store. + */ export default connect(mapStateToProps, mapDispatchToProps)(RegisterForm); //#endregion diff --git a/src/components/organisms/ProfileInfo/index.jsx b/src/components/organisms/ProfileInfo/index.jsx index a39a2d6..21dceb6 100644 --- a/src/components/organisms/ProfileInfo/index.jsx +++ b/src/components/organisms/ProfileInfo/index.jsx @@ -16,6 +16,8 @@ import { MDBTooltip, } from "mdbreact"; //> Redux +// Allows to React components read data from a Redux store, and dispatch actions +// to the store to update data. import { connect } from "react-redux"; //> Components @@ -357,8 +359,10 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -// Provides its connected component with the pieces of the data it needs from -// the store, and the functions it can use to dispatch actions to the store. +/** + * Provides its connected component with the pieces of the data it needs from + * the store, and the functions it can use to dispatch actions to the store. + */ export default connect(mapStateToProps, mapDispatchToProps)(ProfileInfo); //#endregion diff --git a/src/components/organisms/SoftwareTabs/index.jsx b/src/components/organisms/SoftwareTabs/index.jsx index 05220ac..f5ea35a 100644 --- a/src/components/organisms/SoftwareTabs/index.jsx +++ b/src/components/organisms/SoftwareTabs/index.jsx @@ -6,11 +6,12 @@ import React from "react"; // "Material Design for Bootstrap" is a great UI design framework import { MDBBadge } from "mdbreact"; //> Redux +// Allows to React components read data from a Redux store, and dispatch actions +// to the store to update data. import { connect } from "react-redux"; //> Components import { ProjectTab, OverviewTab, TalksTab } from "../tabs"; - //#endregion //#region > Components @@ -35,7 +36,6 @@ class SoftwareTabs extends React.Component { render() { const { fetchedUser } = this.props; const { activeTab } = this.state; - const tabItems = [ { title: "Overview", @@ -135,8 +135,10 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -// Provides its connected component with the pieces of the data it needs from -// the store, and the functions it can use to dispatch actions to the store. +/** + * Provides its connected component with the pieces of the data it needs from + * the store, and the functions it can use to dispatch actions to the store. + */ export default connect(mapStateToProps, mapDispatchToProps)(SoftwareTabs); //#endregion diff --git a/src/components/organisms/tabs/OverviewTab/index.jsx b/src/components/organisms/tabs/OverviewTab/index.jsx index 2f9e74e..68fb873 100644 --- a/src/components/organisms/tabs/OverviewTab/index.jsx +++ b/src/components/organisms/tabs/OverviewTab/index.jsx @@ -8,9 +8,12 @@ import PropTypes from "prop-types"; // "Material Design for Bootstrap" is a great UI design framework import { MDBRow, MDBCol, MDBBtn, MDBIcon } from "mdbreact"; //> Redux +// Allows to React components read data from a Redux store, and dispatch actions +// to the store to update data. import { connect } from "react-redux"; //> Actions +// Functions to send data from the application to the store import { writeCacheAction } from "../../../../store/actions/userActions"; //> CSS import "./overviewtab.scss"; @@ -284,8 +287,10 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -// Provides its connected component with the pieces of the data it needs from -// the store, and the functions it can use to dispatch actions to the store. +/** + * Provides its connected component with the pieces of the data it needs from + * the store, and the functions it can use to dispatch actions to the store. + */ export default connect(mapStateToProps, mapDispatchToProps)(OverviewTab); //#endregion diff --git a/src/components/organisms/tabs/TalksTab/index.jsx b/src/components/organisms/tabs/TalksTab/index.jsx index 3d186c5..bd39ffe 100644 --- a/src/components/organisms/tabs/TalksTab/index.jsx +++ b/src/components/organisms/tabs/TalksTab/index.jsx @@ -17,9 +17,12 @@ import { MDBCardFooter, } from "mdbreact"; //> Redux +// Allows to React components read data from a Redux store, and dispatch actions +// to the store to update data. import { connect } from "react-redux"; //> Actions +// Functions to send data from the application to the store import { deleteTalkAction } from "../../../../store/actions/userActions"; //> CSS import "./talkstab.scss"; @@ -77,6 +80,7 @@ class Talks extends React.Component { return talk; }); } + return ( <> @@ -121,7 +125,6 @@ class Talks extends React.Component { - { //#endregion //#region > Exports -// Provides its connected component with the pieces of the data it needs from -// the store, and the functions it can use to dispatch actions to the store. -// Got access to the history object’s properties and the closest -// 's match. +/** + * Provides its connected component with the pieces of the data it needs from + * the store, and the functions it can use to dispatch actions to the store. + * Got access to the history object’s properties and the closest + * 's match. + */ export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Talks)); //#endregion diff --git a/src/components/pages/HomePage/index.jsx b/src/components/pages/HomePage/index.jsx index 081cff6..18be0cd 100644 --- a/src/components/pages/HomePage/index.jsx +++ b/src/components/pages/HomePage/index.jsx @@ -19,6 +19,8 @@ import { MDBIcon, } from "mdbreact"; //> Redux +// Allows to React components read data from a Redux store, and dispatch actions +// to the store to update data. import { connect } from "react-redux"; //> Components @@ -312,8 +314,10 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -// Provides its connected component with the pieces of the data it needs from -// the store, and the functions it can use to dispatch actions to the store. +/** + * Provides its connected component with the pieces of the data it needs from + * the store, and the functions it can use to dispatch actions to the store. + */ export default connect(mapStateToProps, mapDispatchToProps)(HomePage); //#endregion diff --git a/src/components/pages/ProfilePage/index.jsx b/src/components/pages/ProfilePage/index.jsx index 506cf90..dc0dc8a 100644 --- a/src/components/pages/ProfilePage/index.jsx +++ b/src/components/pages/ProfilePage/index.jsx @@ -5,9 +5,12 @@ import React from "react"; // DOM bindings for React Router import { withRouter } from "react-router-dom"; //> Redux +// Allows to React components read data from a Redux store, and dispatch actions +// to the store to update data. import { connect } from "react-redux"; //> Actions +// Functions to send data from the application to the store import { readCacheAction, updateCacheAction, @@ -143,10 +146,12 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -// Provides its connected component with the pieces of the data it needs from -// the store, and the functions it can use to dispatch actions to the store. -// Got access to the history object’s properties and the closest -// 's match. +/** + * Provides its connected component with the pieces of the data it needs from + * the store, and the functions it can use to dispatch actions to the store. + * Got access to the history object’s properties and the closest + * 's match. + */ export default withRouter( connect(mapStateToProps, mapDispatchToProps)(ProfilePage) ); diff --git a/src/components/pages/SettingsPage/index.jsx b/src/components/pages/SettingsPage/index.jsx index 18fb3ae..a82b1a8 100644 --- a/src/components/pages/SettingsPage/index.jsx +++ b/src/components/pages/SettingsPage/index.jsx @@ -29,9 +29,12 @@ import { MDBBtn, } from "mdbreact"; //> Redux +// Allows to React components read data from a Redux store, and dispatch actions +// to the store to update data. import { connect } from "react-redux"; //> Actions +// Functions to send data from the application to the store import { readCacheAction, saveSettingsActions, @@ -577,10 +580,10 @@ const mapDispatchToProps = (dispatch) => { //#endregion //#region > Exports -// Provides its connected component with the pieces of the data it needs from -// the store, and the functions it can use to dispatch actions to the store. -// Got access to the history object’s properties and the closest -// 's match. +/** + * Provides its connected component with the pieces of the data it needs from + * the store, and the functions it can use to dispatch actions to the store. + */ export default connect(mapStateToProps, mapDispatchToProps)(SettingsPage); //#endregion diff --git a/src/components/pages/TalkPage/index.jsx b/src/components/pages/TalkPage/index.jsx index cdb23e0..26a1175 100644 --- a/src/components/pages/TalkPage/index.jsx +++ b/src/components/pages/TalkPage/index.jsx @@ -21,9 +21,12 @@ import { MDBPagination, } from "mdbreact"; //> Redux +// Allows to React components read data from a Redux store, and dispatch actions +// to the store to update data. import { connect } from "react-redux"; //> Actions +// Functions to send data from the application to the store import { getTalkAction } from "../../../store/actions/userActions"; //> CSS import "./talk.scss"; @@ -383,10 +386,10 @@ const mapDispatchToProps = (dispatch) => { }; //#region > Exports -// Provides its connected component with the pieces of the data it needs from -// the store, and the functions it can use to dispatch actions to the store. -// Got access to the history object’s properties and the closest -// 's match. +/** + * Provides its connected component with the pieces of the data it needs from + * the store, and the functions it can use to dispatch actions to the store. + */ export default connect(mapStateToProps, mapDispatchToProps)(TalkPage); //#endregion diff --git a/src/index.js b/src/index.js index 00c5c63..e41db7f 100644 --- a/src/index.js +++ b/src/index.js @@ -7,6 +7,8 @@ import { BrowserRouter as Router } from "react-router-dom"; // This serves as an entry point to the DOM and server renderers for React import ReactDOM from "react-dom"; //> Redux +// Allows to React components read data from a Redux store, and dispatch actions +// to the store to update data. import { createStore, applyMiddleware, compose } from "redux"; import { loadingBarMiddleware } from "react-redux-loading-bar"; import { Provider } from "react-redux"; diff --git a/src/store/reducers/index.js b/src/store/reducers/index.js index 3621a7b..f79d8de 100644 --- a/src/store/reducers/index.js +++ b/src/store/reducers/index.js @@ -1,5 +1,7 @@ //#region > Imports //> Redux +// Allows to React components read data from a Redux store, and dispatch actions +// to the store to update data. import { combineReducers } from "redux"; //> Reducers import { loadingBarReducer } from "react-redux-loading-bar"; From 427b3d2cdee5d3136904f6ebd9633c9043d38aaa Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 8 Jul 2020 21:49:43 +0200 Subject: [PATCH 83/86] Upgrade TalkUploadModal with Redux Due to a merging problem the talk upload modal did not use redux and therefore did not work anymore. Redux was added in order to get it back working. --- .../modals/TalkUploadModal/index.jsx | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/src/components/molecules/modals/TalkUploadModal/index.jsx b/src/components/molecules/modals/TalkUploadModal/index.jsx index 7754b5b..58fca7b 100644 --- a/src/components/molecules/modals/TalkUploadModal/index.jsx +++ b/src/components/molecules/modals/TalkUploadModal/index.jsx @@ -13,6 +13,14 @@ import { MDBModalBody, MDBProgress, } from "mdbreact"; +//> Redux +// Allows to React components read data from a Redux store, and dispatch actions +// to the store to update data. +import { connect } from "react-redux"; + +//> Actions +// Functions to send data from the application to the store +import { uploadTalkAction } from "../../../../store/actions/userActions"; //#endregion //#region > Components @@ -24,7 +32,7 @@ class TalkUploadModal extends React.Component { }; onDrop = async (files) => { - const { globalState, globalFunctions } = this.props; + const { loggedUser, fetchedUser } = this.props; if (files.length > 0) { this.setState({ @@ -32,11 +40,11 @@ class TalkUploadModal extends React.Component { loading: true, }); - globalFunctions + this.props .uploadTalk(files[0], { - avatarUrl: globalState.fetchedUser.platformData.user.avatarUrl, + avatarUrl: fetchedUser.platformData.user.avatarUrl, owner: { - username: globalState.loggedUser.username, + username: loggedUser.username, }, }) .then(() => { @@ -145,8 +153,23 @@ class TalkUploadModal extends React.Component { } //#endregion +//#region > Redux Mapping +const mapStateToProps = (state) => ({ + loggedUser: state.user.fetchedUser, + fetchedUser: state.user.fetchedUser, +}); + +const mapDispatchToProps = (dispatch) => { + return { uploadTalk: (file) => dispatch(uploadTalkAction(file)) }; +}; +//#endregion + //#region > Exports -export default TalkUploadModal; +/** + * Provides its connected component with the pieces of the data it needs from + * the store, and the functions it can use to dispatch actions to the store. + */ +export default connect(mapStateToProps, mapDispatchToProps)(TalkUploadModal); //#endregion /** From 068d3d4176d7aa2623459d7710b9ad3636e480a1 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 8 Jul 2020 21:58:18 +0200 Subject: [PATCH 84/86] Improve code quality The code quality has been improved due to a reuqest of @aichnerc. --- src/App.js | 6 ++++-- src/components/molecules/Footer/index.jsx | 6 ++++-- src/components/molecules/Navbar/index.jsx | 1 - src/store/actions/generalActions.js | 1 + 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/App.js b/src/App.js index 4d3e306..d0bb353 100644 --- a/src/App.js +++ b/src/App.js @@ -56,8 +56,10 @@ function App() { //#endregion //#region > Exports -// Got access to the history object’s properties and the closest -// 's match. +/** + * Got access to the history object’s properties and the closest + * 's match. + */ export default withRouter(App); //#endregion diff --git a/src/components/molecules/Footer/index.jsx b/src/components/molecules/Footer/index.jsx index f0a6510..7074437 100644 --- a/src/components/molecules/Footer/index.jsx +++ b/src/components/molecules/Footer/index.jsx @@ -254,8 +254,10 @@ class Footer extends React.PureComponent { //#endregion //#region > Exports -// Got access to the history object’s properties and the closest -// 's match. +/** + * Got access to the history object’s properties and the closest + * 's match. + */ export default withRouter(Footer); //#endregion diff --git a/src/components/molecules/Navbar/index.jsx b/src/components/molecules/Navbar/index.jsx index 58b664c..d054a89 100644 --- a/src/components/molecules/Navbar/index.jsx +++ b/src/components/molecules/Navbar/index.jsx @@ -176,7 +176,6 @@ class Navbar extends React.Component { //#endregion //#region > PropTypes -// is it required to write down all stuff in map...toProps?? Navbar.propTypes = { location: PropTypes.object, }; diff --git a/src/store/actions/generalActions.js b/src/store/actions/generalActions.js index 37c2d64..761fe1a 100644 --- a/src/store/actions/generalActions.js +++ b/src/store/actions/generalActions.js @@ -11,6 +11,7 @@ const appendSourceObjectsAction = (sourceList) => { const intel = getIntel(); intel.appendList(sourceList); + dispatch({ type: "APPEND_SOURCE_OBJECTS_SUCCESS", payload: {}, From d52b5d2f81bbdf73cabdb2025e43a1df915cdc99 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 8 Jul 2020 23:22:54 +0200 Subject: [PATCH 85/86] Add loggedUser Object on Read Cache Now when reading the cache the loggedUser is set with fetchUser data if the read user is the same as the loggedUser. --- src/components/molecules/Navbar/index.jsx | 7 +++++-- src/store/actions/authActions.js | 10 +++++++--- src/store/actions/userActions.js | 9 +++++++++ src/store/reducers/userReducers.js | 15 +++++++++++++++ 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/components/molecules/Navbar/index.jsx b/src/components/molecules/Navbar/index.jsx index d054a89..744daac 100644 --- a/src/components/molecules/Navbar/index.jsx +++ b/src/components/molecules/Navbar/index.jsx @@ -65,6 +65,9 @@ class Navbar extends React.Component { render() { const { location, loggedUser } = this.props; + const avatarUrl = loggedUser.platformData?.user?.avatarUrl + ? loggedUser.platformData.user.avatarUrl + : loggedUser.avatarUrl; return ( @@ -128,7 +131,7 @@ class Navbar extends React.Component { {loggedUser.username} @@ -183,7 +186,7 @@ Navbar.propTypes = { //#region > Redux Mapping const mapStateToProps = (state) => ({ - loggedUser: state.auth.loggedUser, + loggedUser: { ...state.auth.loggedUser, ...state.user.loggedUser }, }); const mapDispatchToProps = (dispatch) => { diff --git a/src/store/actions/authActions.js b/src/store/actions/authActions.js index 507cdc9..06f5d95 100644 --- a/src/store/actions/authActions.js +++ b/src/store/actions/authActions.js @@ -62,12 +62,16 @@ const logoutAction = () => { await session .end() - .then(() => + .then(() => { dispatch({ type: "LOGOUT_SUCCESS", payload: {}, - }) - ) + }); + + dispatch({ + type: "REMOVE_LOGGED_USER", + }); + }) .catch((ex) => dispatch({ type: "LOGOUT_ERROR", payload: { error: ex } }) ); diff --git a/src/store/actions/userActions.js b/src/store/actions/userActions.js index 11f5a7f..3b1af48 100644 --- a/src/store/actions/userActions.js +++ b/src/store/actions/userActions.js @@ -219,6 +219,15 @@ const readCacheAction = (username) => { type: "READ_CACHE_SUCCESS", payload: { fetchedUser }, }); + + const state = getState(); + + if (fetchedUser.username === state.auth.loggedUser?.username) { + dispatch({ + type: "SET_LOGGED_USER", + payload: { fetchedUser }, + }); + } } } }) diff --git a/src/store/reducers/userReducers.js b/src/store/reducers/userReducers.js index ba83680..f5caabc 100644 --- a/src/store/reducers/userReducers.js +++ b/src/store/reducers/userReducers.js @@ -7,6 +7,7 @@ import { serializeError } from "serialize-error"; //#region > Constant Variables const INIT_STATE = { fetchedUser: null, + loggedUser: null, registrationHistory: null, selectedTalk: null, newCachedUser: null, @@ -131,6 +132,20 @@ const userReducer = (state = INIT_STATE, action) => { authErrorDetails: serializeError(action.payload.error), }; + /** Temporary implementation */ + //> loggedUser + case "SET_LOGGED_USER": + return { + ...state, + loggedUser: action.payload.fetchedUser, + }; + + case "REMOVE_LOGGED_USER": + return { + ...state, + loggedUser: null, + }; + //> Default default: return state; From 0a0104f7a7321c4a37e6ad37ba108440d407cbe3 Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 9 Jul 2020 10:39:49 +0200 Subject: [PATCH 86/86] Improve code quality The code quality has been improved due to a request of @kleberbaum. --- src/components/atoms/SearchBar/index.jsx | 1 + src/components/molecules/Navbar/index.jsx | 1 + .../organisms/tabs/TalksTab/index.jsx | 1 + src/components/pages/ProfilePage/index.jsx | 1 + src/components/pages/ProfilePage/profile.scss | 2 -- src/index.js | 3 ++- src/store/reducers/index.js | 17 +++++++++++------ 7 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/components/atoms/SearchBar/index.jsx b/src/components/atoms/SearchBar/index.jsx index b73881a..531de91 100644 --- a/src/components/atoms/SearchBar/index.jsx +++ b/src/components/atoms/SearchBar/index.jsx @@ -124,6 +124,7 @@ const mapDispatchToProps = (dispatch) => { /** * Provides its connected component with the pieces of the data it needs from * the store, and the functions it can use to dispatch actions to the store. + * * Got access to the history object’s properties and the closest * 's match. */ diff --git a/src/components/molecules/Navbar/index.jsx b/src/components/molecules/Navbar/index.jsx index 744daac..701825e 100644 --- a/src/components/molecules/Navbar/index.jsx +++ b/src/components/molecules/Navbar/index.jsx @@ -200,6 +200,7 @@ const mapDispatchToProps = (dispatch) => { /** * Provides its connected component with the pieces of the data it needs from * the store, and the functions it can use to dispatch actions to the store. + * * Got access to the history object’s properties and the closest * 's match. */ diff --git a/src/components/organisms/tabs/TalksTab/index.jsx b/src/components/organisms/tabs/TalksTab/index.jsx index bd39ffe..03eed9b 100644 --- a/src/components/organisms/tabs/TalksTab/index.jsx +++ b/src/components/organisms/tabs/TalksTab/index.jsx @@ -228,6 +228,7 @@ const mapDispatchToProps = (dispatch) => { /** * Provides its connected component with the pieces of the data it needs from * the store, and the functions it can use to dispatch actions to the store. + * * Got access to the history object’s properties and the closest * 's match. */ diff --git a/src/components/pages/ProfilePage/index.jsx b/src/components/pages/ProfilePage/index.jsx index dc0dc8a..e5c2594 100644 --- a/src/components/pages/ProfilePage/index.jsx +++ b/src/components/pages/ProfilePage/index.jsx @@ -149,6 +149,7 @@ const mapDispatchToProps = (dispatch) => { /** * Provides its connected component with the pieces of the data it needs from * the store, and the functions it can use to dispatch actions to the store. + * * Got access to the history object’s properties and the closest * 's match. */ diff --git a/src/components/pages/ProfilePage/profile.scss b/src/components/pages/ProfilePage/profile.scss index ac933b9..6161319 100644 --- a/src/components/pages/ProfilePage/profile.scss +++ b/src/components/pages/ProfilePage/profile.scss @@ -162,8 +162,6 @@ } } } - - // General things } /** diff --git a/src/index.js b/src/index.js index e41db7f..5d500cf 100644 --- a/src/index.js +++ b/src/index.js @@ -60,7 +60,8 @@ const enhancer = composeEnhancers( applyMiddleware( loadingBarMiddleware(), thunk.withExtraArgument({ - getIntel, // Intel + // Intel + getIntel, }) ) // other store enhancers if any diff --git a/src/store/reducers/index.js b/src/store/reducers/index.js index f79d8de..b34a270 100644 --- a/src/store/reducers/index.js +++ b/src/store/reducers/index.js @@ -3,23 +3,28 @@ // Allows to React components read data from a Redux store, and dispatch actions // to the store to update data. import { combineReducers } from "redux"; -//> Reducers +// LoadingBar import { loadingBarReducer } from "react-redux-loading-bar"; //> Reducers // Authentication import authReducer from "./authReducers"; +// General import generalReducer from "./generalReducers"; +// User import userReducer from "./userReducers"; - //#endregion //#region > Config const rootReducer = combineReducers({ - loadingBar: loadingBarReducer, // Loading bar - auth: authReducer, // User authentication - general: generalReducer, // General data - user: userReducer, // User data + // Loading bar + loadingBar: loadingBarReducer, + // User authentication + auth: authReducer, + // General data + general: generalReducer, + // User data + user: userReducer, }); //#endregion