mirror of
https://github.com/pawelmalak/flame.git
synced 2025-07-19 19:49:37 +02:00
Added App Edit Functionality
This commit is contained in:
parent
28683e7511
commit
8813bf6181
6 changed files with 98 additions and 12 deletions
|
@ -1,7 +1,7 @@
|
||||||
import { useState, ChangeEvent, SyntheticEvent } from 'react';
|
import { useState, useEffect, ChangeEvent, SyntheticEvent } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { addApp } from '../../../store/actions';
|
import { addApp, updateApp } from '../../../store/actions';
|
||||||
import { NewApp } from '../../../interfaces/App';
|
import { App, NewApp } from '../../../interfaces/App';
|
||||||
|
|
||||||
import classes from './AppForm.module.css';
|
import classes from './AppForm.module.css';
|
||||||
import Icon from '../../UI/Icons/Icon/Icon';
|
import Icon from '../../UI/Icons/Icon/Icon';
|
||||||
|
@ -9,6 +9,8 @@ import Icon from '../../UI/Icons/Icon/Icon';
|
||||||
interface ComponentProps {
|
interface ComponentProps {
|
||||||
modalHandler: Function;
|
modalHandler: Function;
|
||||||
addApp: (formData: NewApp) => any;
|
addApp: (formData: NewApp) => any;
|
||||||
|
updateApp: (id: number, formData: NewApp) => any;
|
||||||
|
app?: App;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AppForm = (props: ComponentProps): JSX.Element => {
|
const AppForm = (props: ComponentProps): JSX.Element => {
|
||||||
|
@ -18,6 +20,17 @@ const AppForm = (props: ComponentProps): JSX.Element => {
|
||||||
icon: ''
|
icon: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (props.app) {
|
||||||
|
console.log('app');
|
||||||
|
setFormData({
|
||||||
|
name: props.app.name,
|
||||||
|
url: props.app.url,
|
||||||
|
icon: props.app.icon
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [props.app])
|
||||||
|
|
||||||
const _modalHandler = () => {
|
const _modalHandler = () => {
|
||||||
props.modalHandler();
|
props.modalHandler();
|
||||||
}
|
}
|
||||||
|
@ -31,7 +44,14 @@ const AppForm = (props: ComponentProps): JSX.Element => {
|
||||||
|
|
||||||
const formSubmitHandler = (e: SyntheticEvent): void => {
|
const formSubmitHandler = (e: SyntheticEvent): void => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
props.addApp(formData);
|
|
||||||
|
if (!props.app) {
|
||||||
|
props.addApp(formData);
|
||||||
|
} else {
|
||||||
|
props.updateApp(props.app.id, formData);
|
||||||
|
props.modalHandler();
|
||||||
|
}
|
||||||
|
|
||||||
setFormData({
|
setFormData({
|
||||||
name: '',
|
name: '',
|
||||||
url: '',
|
url: '',
|
||||||
|
@ -90,10 +110,13 @@ const AppForm = (props: ComponentProps): JSX.Element => {
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit">add</button>
|
{!props.app
|
||||||
|
? <button type="submit">add</button>
|
||||||
|
: <button type="submit">update</button>
|
||||||
|
}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(null, { addApp })(AppForm);
|
export default connect(null, { addApp, updateApp })(AppForm);
|
|
@ -9,6 +9,7 @@ interface ComponentProps {
|
||||||
apps: App[];
|
apps: App[];
|
||||||
pinApp: (id: number, isPinned: boolean) => void;
|
pinApp: (id: number, isPinned: boolean) => void;
|
||||||
deleteApp: (id: number) => void;
|
deleteApp: (id: number) => void;
|
||||||
|
updateAppHandler: (app: App) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AppTable = (props: ComponentProps): JSX.Element => {
|
const AppTable = (props: ComponentProps): JSX.Element => {
|
||||||
|
@ -44,7 +45,11 @@ const AppTable = (props: ComponentProps): JSX.Element => {
|
||||||
onClick={() => deleteAppHandler(app)}>
|
onClick={() => deleteAppHandler(app)}>
|
||||||
<Icon icon='mdiDelete' />
|
<Icon icon='mdiDelete' />
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.TableAction}><Icon icon='mdiPencil' /></div>
|
<div
|
||||||
|
className={classes.TableAction}
|
||||||
|
onClick={() => props.updateAppHandler(app)}>
|
||||||
|
<Icon icon='mdiPencil' />
|
||||||
|
</div>
|
||||||
<div className={classes.TableAction} onClick={() => props.pinApp(app.id, app.isPinned)}>
|
<div className={classes.TableAction} onClick={() => props.pinApp(app.id, app.isPinned)}>
|
||||||
{app.isPinned? <Icon icon='mdiPinOff' color='var(--color-accent)' /> : <Icon icon='mdiPin' />}
|
{app.isPinned? <Icon icon='mdiPinOff' color='var(--color-accent)' /> : <Icon icon='mdiPin' />}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -34,6 +34,16 @@ interface ComponentProps {
|
||||||
const Apps = (props: ComponentProps): JSX.Element => {
|
const Apps = (props: ComponentProps): JSX.Element => {
|
||||||
const [modalIsOpen, setModalIsOpen] = useState(false);
|
const [modalIsOpen, setModalIsOpen] = useState(false);
|
||||||
const [isInEdit, setIsInEdit] = useState(false);
|
const [isInEdit, setIsInEdit] = useState(false);
|
||||||
|
const [isInUpdate, setIsInUpdate] = useState(false);
|
||||||
|
const [appInUpdate, setAppInUpdate] = useState<App>({
|
||||||
|
name: 'string',
|
||||||
|
url: 'string',
|
||||||
|
icon: 'string',
|
||||||
|
isPinned: false,
|
||||||
|
id: 0,
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedAt: new Date()
|
||||||
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (props.apps.length === 0) {
|
if (props.apps.length === 0) {
|
||||||
|
@ -43,16 +53,27 @@ const Apps = (props: ComponentProps): JSX.Element => {
|
||||||
|
|
||||||
const toggleModal = (): void => {
|
const toggleModal = (): void => {
|
||||||
setModalIsOpen(!modalIsOpen);
|
setModalIsOpen(!modalIsOpen);
|
||||||
|
setIsInUpdate(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const toggleEdit = (): void => {
|
const toggleEdit = (): void => {
|
||||||
setIsInEdit(!isInEdit);
|
setIsInEdit(!isInEdit);
|
||||||
|
setIsInUpdate(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleUpdate = (app: App): void => {
|
||||||
|
setAppInUpdate(app);
|
||||||
|
setIsInUpdate(true);
|
||||||
|
setModalIsOpen(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Modal isOpen={modalIsOpen} setIsOpen={setModalIsOpen}>
|
<Modal isOpen={modalIsOpen} setIsOpen={setModalIsOpen}>
|
||||||
<AppForm modalHandler={toggleModal} />
|
{!isInUpdate
|
||||||
|
? <AppForm modalHandler={toggleModal} />
|
||||||
|
: <AppForm modalHandler={toggleModal} app={appInUpdate} />
|
||||||
|
}
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<Headline
|
<Headline
|
||||||
|
@ -80,7 +101,7 @@ const Apps = (props: ComponentProps): JSX.Element => {
|
||||||
? props.apps.length > 0
|
? props.apps.length > 0
|
||||||
? <AppGrid apps={props.apps} />
|
? <AppGrid apps={props.apps} />
|
||||||
: <p className={classes.AppsMessage}>You don't have any applications. You can a new one from <Link to='/applications'>/application</Link> menu</p>
|
: <p className={classes.AppsMessage}>You don't have any applications. You can a new one from <Link to='/applications'>/application</Link> menu</p>
|
||||||
: <AppTable />)
|
: <AppTable updateAppHandler={toggleUpdate} />)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
|
@ -3,7 +3,8 @@ import {
|
||||||
SetThemeAction,
|
SetThemeAction,
|
||||||
PinAppAction,
|
PinAppAction,
|
||||||
AddAppAction,
|
AddAppAction,
|
||||||
DeleteAppAction
|
DeleteAppAction,
|
||||||
|
UpdateAppAction
|
||||||
} from './';
|
} from './';
|
||||||
|
|
||||||
export enum ActionTypes {
|
export enum ActionTypes {
|
||||||
|
@ -14,7 +15,8 @@ export enum ActionTypes {
|
||||||
pinApp = 'PIN_APP',
|
pinApp = 'PIN_APP',
|
||||||
addApp = 'ADD_APP',
|
addApp = 'ADD_APP',
|
||||||
addAppSuccess = 'ADD_APP_SUCCESS',
|
addAppSuccess = 'ADD_APP_SUCCESS',
|
||||||
deleteApp = 'DELETE_APP'
|
deleteApp = 'DELETE_APP',
|
||||||
|
updateApp = 'UPDATE_APP'
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Action = GetAppsAction<any> | SetThemeAction | PinAppAction | AddAppAction | DeleteAppAction;
|
export type Action = GetAppsAction<any> | SetThemeAction | PinAppAction | AddAppAction | DeleteAppAction | UpdateAppAction;
|
|
@ -82,3 +82,21 @@ export const deleteApp = (id: number) => async (dispatch: Dispatch) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UpdateAppAction {
|
||||||
|
type: ActionTypes.updateApp;
|
||||||
|
payload: App;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const updateApp = (id: number, formData: NewApp) => async (dispatch: Dispatch) => {
|
||||||
|
try {
|
||||||
|
const res = await axios.put<ApiResponse<App>>(`/api/apps/${id}`, formData);
|
||||||
|
|
||||||
|
dispatch<UpdateAppAction>({
|
||||||
|
type: ActionTypes.updateApp,
|
||||||
|
payload: res.data.data
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
}
|
|
@ -69,6 +69,22 @@ const deleteApp = (state: State, action: Action): State => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateApp = (state: State, action: Action): State => {
|
||||||
|
const tmpApps = [...state.apps];
|
||||||
|
const appInUpdate = tmpApps.find((app: App) => app.id === action.payload.id);
|
||||||
|
|
||||||
|
if (appInUpdate) {
|
||||||
|
appInUpdate.name = action.payload.name;
|
||||||
|
appInUpdate.url = action.payload.url;
|
||||||
|
appInUpdate.icon = action.payload.icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
apps: tmpApps
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const appReducer = (state = initialState, action: Action) => {
|
const appReducer = (state = initialState, action: Action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case ActionTypes.getApps: return getApps(state, action);
|
case ActionTypes.getApps: return getApps(state, action);
|
||||||
|
@ -77,6 +93,7 @@ const appReducer = (state = initialState, action: Action) => {
|
||||||
case ActionTypes.pinApp: return pinApp(state, action);
|
case ActionTypes.pinApp: return pinApp(state, action);
|
||||||
case ActionTypes.addAppSuccess: return addAppSuccess(state, action);
|
case ActionTypes.addAppSuccess: return addAppSuccess(state, action);
|
||||||
case ActionTypes.deleteApp: return deleteApp(state, action);
|
case ActionTypes.deleteApp: return deleteApp(state, action);
|
||||||
|
case ActionTypes.updateApp: return updateApp(state, action);
|
||||||
default: return state;
|
default: return state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue