Skip to content

Commit

Permalink
Prettier formatting for menus and modal dialogs
Browse files Browse the repository at this point in the history
  • Loading branch information
nelsonni committed Apr 21, 2023
1 parent a247bbf commit 16e3369
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 53 deletions.
6 changes: 4 additions & 2 deletions src/components/NavItem/NavItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ export type NavItemProps = {

const NavItem = ({ label, click, disabled }: NavItemProps) => {
return (
<MenuItem onClick={click} {...removeNullableProperties({ disabled: disabled })}>{label}</MenuItem>
<MenuItem onClick={click} {...removeNullableProperties({ disabled: disabled })}>
{label}
</MenuItem>
);
};

export default NavItem;
export default NavItem;
53 changes: 38 additions & 15 deletions src/components/NavMenu/NavMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import NavItem, { NavItemProps } from '../NavItem/NavItem';
type NavMenuProps = {
label: string;
submenu: NavItemProps[];
}
};

const NavMenu = ({ label, submenu }: NavMenuProps) => {
const [open, setOpen] = React.useState(false);
const anchorRef = React.useRef<HTMLButtonElement>(null);

const handleToggle = () => setOpen((prevOpen) => !prevOpen);
const handleToggle = () => setOpen(prevOpen => !prevOpen);

const handleClose = (event: React.MouseEvent<EventTarget>) => {
if (anchorRef.current && anchorRef.current.contains(event.target as HTMLElement)) {
Expand All @@ -35,22 +35,45 @@ const NavMenu = ({ label, submenu }: NavMenuProps) => {

return (
<>
<Button ref={anchorRef} aria-controls={open ? `${label}-menu` : undefined} aria-haspopup='true' onClick={handleToggle}>
<Button
ref={anchorRef}
aria-controls={open ? `${label}-menu` : undefined}
aria-haspopup="true"
onClick={handleToggle}
>
{label}
</Button>
<Popper open={open} anchorEl={anchorRef.current} role={undefined} style={{ zIndex: 1000 }} transition disablePortal>
<Popper
open={open}
anchorEl={anchorRef.current}
role={undefined}
style={{ zIndex: 1000 }}
transition
disablePortal
>
{({ TransitionProps, placement }) => (
<Grow {...TransitionProps} style={{ transformOrigin: placement === 'bottom' ? 'center top' : 'center bottom' }}>
<Grow
{...TransitionProps}
style={{ transformOrigin: placement === 'bottom' ? 'center top' : 'center bottom' }}
>
<Paper>
<ClickAwayListener onClickAway={handleClose}>
<MenuList autoFocusItem={open} id={`${label}-menu-list`} onKeyDown={handleListKeyDown}>
{submenu.map(item => <NavItem key={item.label}
label={item.label}
{...removeNullableProperties({ disabled: item.disabled })}
click={(event: React.MouseEvent<HTMLLIElement, MouseEvent>) => {
item.click(event);
setOpen(false);
}} />)}
<MenuList
autoFocusItem={open}
id={`${label}-menu-list`}
onKeyDown={handleListKeyDown}
>
{submenu.map(item => (
<NavItem
key={item.label}
label={item.label}
{...removeNullableProperties({ disabled: item.disabled })}
click={(event: React.MouseEvent<HTMLLIElement, MouseEvent>) => {
item.click(event);
setOpen(false);
}}
/>
))}
</MenuList>
</ClickAwayListener>
</Paper>
Expand All @@ -59,6 +82,6 @@ const NavMenu = ({ label, submenu }: NavMenuProps) => {
</Popper>
</>
);
}
};

export default NavMenu;
export default NavMenu;
49 changes: 36 additions & 13 deletions src/containers/dialogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,21 @@ export const fileOpenDialog = createAppAsyncThunk<void, PickerType | void>(
'dialogs/fileOpenDialog',
async (pickerType, thunkAPI) => {
const isMac = process.platform === 'darwin';
const properties: ('openFile' | 'openDirectory')[] = pickerType ? [pickerType] : (isMac ? ['openFile', 'openDirectory'] : ['openFile']);
const paths: Electron.OpenDialogReturnValue = await ipcRenderer.invoke('fileOpenDialog', properties);
const properties: ('openFile' | 'openDirectory')[] = pickerType
? [pickerType]
: isMac
? ['openFile', 'openDirectory']
: ['openFile'];
const paths: Electron.OpenDialogReturnValue = await ipcRenderer.invoke(
'fileOpenDialog',
properties
);
if (!paths.canceled && paths.filePaths) {
await Promise.all(paths.filePaths.map(async filePath => await thunkAPI.dispatch(buildCard({ path: filePath }))));
await Promise.all(
paths.filePaths.map(
async filePath => await thunkAPI.dispatch(buildCard({ path: filePath }))
)
);
}
}
);
Expand All @@ -25,17 +36,24 @@ export const fileSaveDialog = createAppAsyncThunk<boolean, Metafile>(
'dialogs/fileSaveDialog',
async (metafile, thunkAPI) => {
const isMac = process.platform === 'darwin';
const properties: ('showHiddenFiles' | 'createDirectory')[] = isMac ? ['showHiddenFiles', 'createDirectory'] : ['showHiddenFiles'];
const response: Electron.SaveDialogReturnValue = await ipcRenderer.invoke('fileSaveDialog',
{ defaultPath: join(process.cwd(), metafile.name), properties: properties });
const properties: ('showHiddenFiles' | 'createDirectory')[] = isMac
? ['showHiddenFiles', 'createDirectory']
: ['showHiddenFiles'];
const response: Electron.SaveDialogReturnValue = await ipcRenderer.invoke('fileSaveDialog', {
defaultPath: join(process.cwd(), metafile.name),
properties: properties
});
if (!response.canceled && response.filePath && metafile.content) {
// update metafile
thunkAPI.dispatch(metafileUpdated({ ...metafile, path: response.filePath, state: 'unmodified' }));
thunkAPI.dispatch(
metafileUpdated({ ...metafile, path: response.filePath, state: 'unmodified' })
);
// write file
await writeFileAsync(response.filePath, metafile.content);
// update git info
await Promise.all(
metafileSelectors.selectByFilepath(thunkAPI.getState(), response.filePath)
metafileSelectors
.selectByFilepath(thunkAPI.getState(), response.filePath)
.filter(isFilebasedMetafile)
.map(async m => await thunkAPI.dispatch(updateVersionedMetafile(m)))
);
Expand All @@ -47,14 +65,19 @@ export const fileSaveDialog = createAppAsyncThunk<boolean, Metafile>(

export const cloneDirectoryDialog = createAppAsyncThunk<string | null, string>(
'dialogs/cloneDirectoryDialog',
async (repoName) => {
async repoName => {
const isMac = process.platform === 'darwin';
const properties: ('showHiddenFiles' | 'createDirectory')[] = isMac ? ['showHiddenFiles', 'createDirectory'] : ['showHiddenFiles'];
const response: Electron.SaveDialogReturnValue = await ipcRenderer.invoke('fileSaveDialog',
{ defaultPath: join(process.cwd(), repoName), properties: properties, buttonLabel: 'Select Repo Location' });
const properties: ('showHiddenFiles' | 'createDirectory')[] = isMac
? ['showHiddenFiles', 'createDirectory']
: ['showHiddenFiles'];
const response: Electron.SaveDialogReturnValue = await ipcRenderer.invoke('fileSaveDialog', {
defaultPath: join(process.cwd(), repoName),
properties: properties,
buttonLabel: 'Select Repo Location'
});
if (!response.canceled && response.filePath) {
return response.filePath;
}
return null;
}
);
);
45 changes: 22 additions & 23 deletions src/store/slices/modals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,32 @@ import { ModalType, UUID } from '../types';

/** A queued modal event (dialog or error) that requires a visible response from the system. */
export type Modal = {
/** The UUID for Modal object. */
readonly id: UUID;
/** The type of modal (e.g. `NewCardDialog` or `Error`). */
readonly type: ModalType;
/** The UUID for related object that triggered the modal event. */
readonly target?: UUID;
/** Options targeting specific types of modals. */
readonly options?: { [key: string]: string | number | boolean }
}
/** The UUID for Modal object. */
readonly id: UUID;
/** The type of modal (e.g. `NewCardDialog`, `Error`, etc). */
readonly type: ModalType;
/** The UUID for related object that triggered the modal event. */
readonly target?: UUID;
/** Options targeting specific types of modals. */
readonly options?: { [key: string]: string | number | boolean };
};

export const modalAdapter = createEntityAdapter<Modal>();

export const modalSlice = createSlice({
name: 'modals',
initialState: modalAdapter.getInitialState(),
reducers: {
modalAdded: modalAdapter.addOne,
modalRemoved: modalAdapter.removeOne
},
extraReducers: (builder) => {
builder
.addCase(PURGE, (state) => {
modalAdapter.removeAll(state);
})
}
})
name: 'modals',
initialState: modalAdapter.getInitialState(),
reducers: {
modalAdded: modalAdapter.addOne,
modalRemoved: modalAdapter.removeOne
},
extraReducers: builder => {
builder.addCase(PURGE, state => {
modalAdapter.removeAll(state);
});
}
});

export const { modalAdded, modalRemoved } = modalSlice.actions;

export default modalSlice.reducer;
export default modalSlice.reducer;

0 comments on commit 16e3369

Please sign in to comment.