From fa5c35b61982c8736908c4e5fbb80044927a0e0a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 12 May 2021 17:31:25 +0200 Subject: [PATCH] Pinned Apps --- .../components/Settings/Settings.module.css | 1 + client/src/interfaces/App.ts | 11 ++++- client/src/store/actions/actionTypes.ts | 17 ++++--- client/src/store/actions/app.ts | 44 +++++++++++++++++-- client/src/store/reducers/app.ts | 25 +++++++++++ models/App.js | 4 ++ 6 files changed, 90 insertions(+), 12 deletions(-) diff --git a/client/src/components/Settings/Settings.module.css b/client/src/components/Settings/Settings.module.css index 1d360d7..6bbd7cc 100644 --- a/client/src/components/Settings/Settings.module.css +++ b/client/src/components/Settings/Settings.module.css @@ -16,6 +16,7 @@ display: flex; align-items: center; height: 40px; + transition: all 0.3s; } .SettingsNavLink:hover { diff --git a/client/src/interfaces/App.ts b/client/src/interfaces/App.ts index ddec96f..ffdbf82 100644 --- a/client/src/interfaces/App.ts +++ b/client/src/interfaces/App.ts @@ -3,11 +3,18 @@ export interface App { name: string; url: string; icon: string; + isPinned: boolean; createdAt: Date; updatedAt: Date; } -export interface AppResponse { +export interface AppResponse { success: boolean; - data: App[] + data: T; +} + +export interface NewApp { + name: string; + url: string; + icon: string; } \ No newline at end of file diff --git a/client/src/store/actions/actionTypes.ts b/client/src/store/actions/actionTypes.ts index 0821251..250201d 100644 --- a/client/src/store/actions/actionTypes.ts +++ b/client/src/store/actions/actionTypes.ts @@ -1,13 +1,18 @@ import { GetAppsAction, - SetTheme + SetTheme, + PinAppAction, + AddAppAction } from './'; export enum ActionTypes { - setTheme, - getApps, - getAppsSuccess, - getAppsError + setTheme = 'SET_THEME', + getApps = 'GET_APPS', + getAppsSuccess = 'GET_APPS_SUCCESS', + getAppsError = 'GET_APPS_ERROR', + pinApp = 'PIN_APP', + addApp = 'ADD_APP', + addAppSuccess = 'ADD_APP_SUCCESS' } -export type Action = GetAppsAction | SetTheme; \ No newline at end of file +export type Action = GetAppsAction | SetTheme | PinAppAction | AddAppAction; \ No newline at end of file diff --git a/client/src/store/actions/app.ts b/client/src/store/actions/app.ts index c713877..411f825 100644 --- a/client/src/store/actions/app.ts +++ b/client/src/store/actions/app.ts @@ -1,11 +1,11 @@ import axios from 'axios'; import { Dispatch } from 'redux'; import { ActionTypes } from './actionTypes'; -import { App, AppResponse } from '../../interfaces/App'; +import { App, AppResponse, NewApp } from '../../interfaces/App'; export interface GetAppsAction { - type: ActionTypes.getApps | ActionTypes.getAppsSuccess | ActionTypes.getAppsError, - payload: T + type: ActionTypes.getApps | ActionTypes.getAppsSuccess | ActionTypes.getAppsError; + payload: T; } export const getApps = () => async (dispatch: Dispatch) => { @@ -15,7 +15,7 @@ export const getApps = () => async (dispatch: Dispatch) => { }); try { - const res = await axios.get('/api/apps'); + const res = await axios.get>('/api/apps'); dispatch>({ type: ActionTypes.getAppsSuccess, @@ -27,4 +27,40 @@ export const getApps = () => async (dispatch: Dispatch) => { payload: err.data.data }) } +} + +export interface PinAppAction { + type: ActionTypes.pinApp; + payload: App; +} + +export const pinApp = (id: number, isPinned: boolean) => async (dispatch: Dispatch) => { + try { + const res = await axios.put>(`/api/apps/${id}`, { isPinned: !isPinned }); + + dispatch({ + type: ActionTypes.pinApp, + payload: res.data.data + }) + } catch (err) { + console.log(err); + } +} + +export interface AddAppAction { + type: ActionTypes.addAppSuccess; + payload: App; +} + +export const addApp = (formData: NewApp) => async (dispatch: Dispatch) => { + try { + const res = await axios.post>('/api/apps', formData); + + dispatch({ + type: ActionTypes.addAppSuccess, + payload: res.data.data + }) + } catch (err) { + console.log(err); + } } \ No newline at end of file diff --git a/client/src/store/reducers/app.ts b/client/src/store/reducers/app.ts index d4ee074..f8d9d7b 100644 --- a/client/src/store/reducers/app.ts +++ b/client/src/store/reducers/app.ts @@ -37,11 +37,36 @@ const getAppsError = (state: State, action: Action): State => { } } +const pinApp = (state: State, action: Action): State => { + const tmpApps = [...state.apps]; + const changedApp = tmpApps.find((app: App) => app.id === action.payload.id); + + if (changedApp) { + changedApp.isPinned = action.payload.isPinned; + } + + return { + ...state, + apps: tmpApps + } +} + +const addAppSuccess = (state: State, action: Action): State => { + const tmpApps = [...state.apps, ...action.payload]; + + return { + ...state, + apps: tmpApps + } +} + const appReducer = (state = initialState, action: Action) => { switch (action.type) { case ActionTypes.getApps: return getApps(state, action); case ActionTypes.getAppsSuccess: return getAppsSuccess(state, action); case ActionTypes.getAppsError: return getAppsError(state, action); + case ActionTypes.pinApp: return pinApp(state, action); + case ActionTypes.addAppSuccess: return addAppSuccess(state, action); default: return state; } } diff --git a/models/App.js b/models/App.js index a3d34d1..57e5801 100644 --- a/models/App.js +++ b/models/App.js @@ -14,6 +14,10 @@ const App = sequelize.define('App', { type: DataTypes.STRING, allowNull: false, defaultValue: 'cancel' + }, + isPinned: { + type: DataTypes.BOOLEAN, + defaultValue: false } });