mirror of https://github.com/laurent22/joplin.git
Desktop: Resolves #5934: Use same notebook dialog when creating a new notebook too
parent
b5b02d8d7b
commit
e813d15ef2
|
@ -8,25 +8,31 @@ import StyledInput from '../style/StyledInput';
|
||||||
import { IconSelector, ChangeEvent } from './IconSelector';
|
import { IconSelector, ChangeEvent } from './IconSelector';
|
||||||
import useAsyncEffect, { AsyncEffectEvent } from '@joplin/lib/hooks/useAsyncEffect';
|
import useAsyncEffect, { AsyncEffectEvent } from '@joplin/lib/hooks/useAsyncEffect';
|
||||||
import Folder from '@joplin/lib/models/Folder';
|
import Folder from '@joplin/lib/models/Folder';
|
||||||
import { FolderIcon } from '@joplin/lib/services/database/types';
|
import { FolderEntity, FolderIcon } from '@joplin/lib/services/database/types';
|
||||||
import Button from '../Button/Button';
|
import Button from '../Button/Button';
|
||||||
|
import bridge from '../../services/bridge';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
themeId: number;
|
themeId: number;
|
||||||
dispatch: Function;
|
dispatch: Function;
|
||||||
folderId: string;
|
folderId: string;
|
||||||
|
parentId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function(props: Props) {
|
export default function(props: Props) {
|
||||||
const [folderTitle, setFolderTitle] = useState('');
|
const [folderTitle, setFolderTitle] = useState('');
|
||||||
const [folderIcon, setFolderIcon] = useState<FolderIcon>();
|
const [folderIcon, setFolderIcon] = useState<FolderIcon>();
|
||||||
|
|
||||||
|
const isNew = !props.folderId;
|
||||||
|
|
||||||
useAsyncEffect(async (event: AsyncEffectEvent) => {
|
useAsyncEffect(async (event: AsyncEffectEvent) => {
|
||||||
|
if (isNew) return;
|
||||||
|
|
||||||
const folder = await Folder.load(props.folderId);
|
const folder = await Folder.load(props.folderId);
|
||||||
if (event.cancelled) return;
|
if (event.cancelled) return;
|
||||||
setFolderTitle(folder.title);
|
setFolderTitle(folder.title);
|
||||||
setFolderIcon(Folder.unserializeIcon(folder.icon));
|
setFolderIcon(Folder.unserializeIcon(folder.icon));
|
||||||
}, [props.folderId]);
|
}, [props.folderId, isNew]);
|
||||||
|
|
||||||
const onClose = useCallback(() => {
|
const onClose = useCallback(() => {
|
||||||
props.dispatch({
|
props.dispatch({
|
||||||
|
@ -42,15 +48,29 @@ export default function(props: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.buttonName === 'ok') {
|
if (event.buttonName === 'ok') {
|
||||||
await Folder.save({
|
const folder: FolderEntity = {
|
||||||
id: props.folderId,
|
|
||||||
title: folderTitle,
|
title: folderTitle,
|
||||||
icon: Folder.serializeIcon(folderIcon),
|
icon: Folder.serializeIcon(folderIcon),
|
||||||
});
|
};
|
||||||
onClose();
|
|
||||||
|
if (!isNew) folder.id = props.folderId;
|
||||||
|
if (props.parentId) folder.parent_id = props.parentId;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const savedFolder = await Folder.save(folder, { userSideValidation: true });
|
||||||
|
onClose();
|
||||||
|
|
||||||
|
props.dispatch({
|
||||||
|
type: 'FOLDER_SELECT',
|
||||||
|
id: savedFolder.id,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
bridge().showErrorMessageBox(error.message);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}, [onClose, folderTitle, folderIcon, props.folderId]);
|
}, [onClose, folderTitle, folderIcon, props.folderId, props.parentId]);
|
||||||
|
|
||||||
const onFolderTitleChange = useCallback((event: any) => {
|
const onFolderTitleChange = useCallback((event: any) => {
|
||||||
setFolderTitle(event.target.value);
|
setFolderTitle(event.target.value);
|
||||||
|
@ -96,10 +116,12 @@ export default function(props: Props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const dialogTitle = isNew ? _('Create notebook') : _('Edit notebook');
|
||||||
|
|
||||||
function renderDialogWrapper() {
|
function renderDialogWrapper() {
|
||||||
return (
|
return (
|
||||||
<div className="dialog-root">
|
<div className="dialog-root">
|
||||||
<DialogTitle title={_('Edit notebook')}/>
|
<DialogTitle title={dialogTitle}/>
|
||||||
{renderContent()}
|
{renderContent()}
|
||||||
<DialogButtonRow
|
<DialogButtonRow
|
||||||
themeId={props.themeId}
|
themeId={props.themeId}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { CommandContext, CommandDeclaration, CommandRuntime } from '@joplin/lib/services/CommandService';
|
import CommandService, { CommandContext, CommandDeclaration, CommandRuntime } from '@joplin/lib/services/CommandService';
|
||||||
import { _ } from '@joplin/lib/locale';
|
import { _ } from '@joplin/lib/locale';
|
||||||
import Folder from '@joplin/lib/models/Folder';
|
import { Options } from './openFolderDialog';
|
||||||
const bridge = require('@electron/remote').require('./bridge').default;
|
|
||||||
|
|
||||||
export const declaration: CommandDeclaration = {
|
export const declaration: CommandDeclaration = {
|
||||||
name: 'newFolder',
|
name: 'newFolder',
|
||||||
|
@ -9,35 +8,15 @@ export const declaration: CommandDeclaration = {
|
||||||
iconName: 'fa-book',
|
iconName: 'fa-book',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const runtime = (comp: any): CommandRuntime => {
|
export const runtime = (): CommandRuntime => {
|
||||||
return {
|
return {
|
||||||
execute: async (_context: CommandContext, parentId: string = null) => {
|
execute: async (_context: CommandContext, parentId: string = null) => {
|
||||||
comp.setState({
|
const options: Options = {
|
||||||
promptOptions: {
|
isNew: true,
|
||||||
label: _('Notebook title:'),
|
parentId: parentId,
|
||||||
onClose: async (answer: string) => {
|
};
|
||||||
if (answer) {
|
|
||||||
let folder = null;
|
|
||||||
try {
|
|
||||||
const toSave: any = { title: answer };
|
|
||||||
if (parentId) toSave.parent_id = parentId;
|
|
||||||
folder = await Folder.save(toSave, { userSideValidation: true });
|
|
||||||
} catch (error) {
|
|
||||||
bridge().showErrorMessageBox(error.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (folder) {
|
void CommandService.instance().execute('openFolderDialog', options);
|
||||||
comp.props.dispatch({
|
|
||||||
type: 'FOLDER_SELECT',
|
|
||||||
id: folder.id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
comp.setState({ promptOptions: null });
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
||||||
import { _ } from '@joplin/lib/locale';
|
import { _ } from '@joplin/lib/locale';
|
||||||
|
|
||||||
|
export interface Options {
|
||||||
|
isNew?: boolean;
|
||||||
|
folderId?: string;
|
||||||
|
parentId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export const declaration: CommandDeclaration = {
|
export const declaration: CommandDeclaration = {
|
||||||
name: 'openFolderDialog',
|
name: 'openFolderDialog',
|
||||||
label: () => _('Edit'),
|
label: () => _('Edit'),
|
||||||
|
@ -8,13 +14,22 @@ export const declaration: CommandDeclaration = {
|
||||||
|
|
||||||
export const runtime = (): CommandRuntime => {
|
export const runtime = (): CommandRuntime => {
|
||||||
return {
|
return {
|
||||||
execute: async (context: CommandContext, folderId: string) => {
|
execute: async (context: CommandContext, options: Options = null) => {
|
||||||
|
options = {
|
||||||
|
isNew: false,
|
||||||
|
...options,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (options.isNew && !('parentId' in options)) throw new Error('parentId mst be specified when creating a new folder');
|
||||||
|
if (!options.isNew && !('folderId' in options)) throw new Error('folderId property is required');
|
||||||
|
|
||||||
context.dispatch({
|
context.dispatch({
|
||||||
type: 'DIALOG_OPEN',
|
type: 'DIALOG_OPEN',
|
||||||
name: 'editFolder',
|
name: 'editFolder',
|
||||||
isOpen: true,
|
isOpen: true,
|
||||||
props: {
|
props: {
|
||||||
folderId,
|
folderId: options.folderId,
|
||||||
|
parentId: options.parentId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -294,7 +294,7 @@ class SidebarComponent extends React.Component<Props, State> {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (itemType === BaseModel.TYPE_FOLDER && !item.encryption_applied) {
|
if (itemType === BaseModel.TYPE_FOLDER && !item.encryption_applied) {
|
||||||
menu.append(new MenuItem(menuUtils.commandToStatefulMenuItem('openFolderDialog', itemId)));
|
menu.append(new MenuItem(menuUtils.commandToStatefulMenuItem('openFolderDialog', { folderId: itemId })));
|
||||||
|
|
||||||
menu.append(new MenuItem({ type: 'separator' }));
|
menu.append(new MenuItem({ type: 'separator' }));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue