refactor: create workspace in one click

This commit is contained in:
Lin Onetwo 2020-06-26 23:56:11 +08:00
parent 5aa8ca95a0
commit 04f4991948
5 changed files with 149 additions and 127 deletions

5
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,5 @@
{
"cSpell.words": [
"subwiki"
]
}

View file

@ -16,10 +16,9 @@ async function createWiki(newFolderPath, folderName) {
} }
// Start copying wiki template to destination // Start copying wiki template to destination
await fs.copy(TIDDLYWIKI_FOLDER_PATH, newWikiPath); await fs.copy(TIDDLYWIKI_FOLDER_PATH, newWikiPath);
return newWikiPath;
} }
async function createSubWiki(newFolderPath, folderName) { async function createSubWiki(newFolderPath, folderName, mainWikiToLink) {
const newWikiPath = path.join(newFolderPath, folderName); const newWikiPath = path.join(newFolderPath, folderName);
if (!(await fs.pathExists(newFolderPath))) { if (!(await fs.pathExists(newFolderPath))) {
throw new Error(`该目录不存在 "${newFolderPath}"`); throw new Error(`该目录不存在 "${newFolderPath}"`);
@ -28,7 +27,6 @@ async function createSubWiki(newFolderPath, folderName) {
throw new Error(`Wiki已经存在于该位置 "${newWikiPath}"`); throw new Error(`Wiki已经存在于该位置 "${newWikiPath}"`);
} }
await fs.mkdirs(path.join(newFolderPath, folderName)); await fs.mkdirs(path.join(newFolderPath, folderName));
return newWikiPath;
} }
module.exports = { createWiki, createSubWiki }; module.exports = { createWiki, createSubWiki };

View file

@ -10,6 +10,7 @@ const { getPreference, getPreferences, resetPreferences, setPreference } = requi
const { getSystemPreference, getSystemPreferences, setSystemPreference } = require('../libs/system-preferences'); const { getSystemPreference, getSystemPreferences, setSystemPreference } = require('../libs/system-preferences');
const { const {
countWorkspaces,
getActiveWorkspace, getActiveWorkspace,
getWorkspace, getWorkspace,
getWorkspaces, getWorkspaces,
@ -55,21 +56,21 @@ const proxyWindow = require('../windows/proxy');
const spellcheckLanguagesWindow = require('../windows/spellcheck-languages'); const spellcheckLanguagesWindow = require('../windows/spellcheck-languages');
const loadListeners = () => { const loadListeners = () => {
ipcMain.on('copy-wiki-template', async (event, newFolderPath, folderName) => { ipcMain.handle('copy-wiki-template', async (event, newFolderPath, folderName) => {
try { try {
const createdWikiPath = await createWiki(newFolderPath, folderName); await createWiki(newFolderPath, folderName);
// eslint-disable-next-line sonarjs/no-duplicate-string // eslint-disable-next-line sonarjs/no-duplicate-string
event.reply('create-wiki-result', `Wiki 已成功创建到 ${createdWikiPath}`); return true;
} catch (error) { } catch (error) {
event.reply('create-wiki-result', String(error)); return String(error);
} }
}); });
ipcMain.on('create-sub-wiki', async (event, newFolderPath, folderName) => { ipcMain.handle('create-sub-wiki', async (event, newFolderPath, folderName, mainWikiToLink) => {
try { try {
const createdWikiPath = await createSubWiki(newFolderPath, folderName); await createSubWiki(newFolderPath, folderName, mainWikiToLink);
event.reply('create-wiki-result', `Wiki 已成功创建到 ${createdWikiPath}`); return true;
} catch (error) { } catch (error) {
event.reply('create-wiki-result', String(error)); return String(error);
} }
}); });
ipcMain.on('request-start-tiddlywiki', (wikiPath) => { ipcMain.on('request-start-tiddlywiki', (wikiPath) => {
@ -239,6 +240,10 @@ const loadListeners = () => {
}); });
// Workspaces // Workspaces
ipcMain.on('count-workspace', (e) => {
e.returnValue = countWorkspaces();
});
ipcMain.on('get-workspace', (e, id) => { ipcMain.on('get-workspace', (e, id) => {
const val = getWorkspace(id); const val = getWorkspace(id);
e.returnValue = val; e.returnValue = val;

View file

@ -2,7 +2,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import styled from 'styled-components'; import styled from 'styled-components';
import is from 'styled-is';
import Paper from '@material-ui/core/Paper'; import Paper from '@material-ui/core/Paper';
import FormControlLabel from '@material-ui/core/FormControlLabel'; import FormControlLabel from '@material-ui/core/FormControlLabel';
@ -18,9 +17,15 @@ import FolderIcon from '@material-ui/icons/Folder';
import GithubIcon from '@material-ui/icons/GitHub'; import GithubIcon from '@material-ui/icons/GitHub';
import connectComponent from '../../helpers/connect-component'; import connectComponent from '../../helpers/connect-component';
import { updateForm, save } from '../../state/dialog-add-workspace/actions'; import { updateForm, save, wikiCreationResult } from '../../state/dialog-add-workspace/actions';
import { requestCopyWikiTemplate, requestCreateSubWiki, getIconPath, getWorkspaces } from '../../senders'; import {
requestCopyWikiTemplate,
requestCreateSubWiki,
getIconPath,
getWorkspaces,
countWorkspace,
} from '../../senders';
const Container = styled.main` const Container = styled.main`
height: 100vh; height: 100vh;
@ -39,14 +44,6 @@ const LocationPickerButton = styled(Button)`
white-space: nowrap; white-space: nowrap;
width: 100%; width: 100%;
`; `;
const CreatorButton = styled(Button)`
white-space: nowrap;
width: 100%;
${is('disabled')`
display: none;
`}
border-radius: 0;
`;
const SyncToGithubButton = styled(Button)` const SyncToGithubButton = styled(Button)`
white-space: nowrap; white-space: nowrap;
width: 100%; width: 100%;
@ -60,17 +57,15 @@ const CloseButton = styled(Button)`
position: absolute; position: absolute;
bottom: 0; bottom: 0;
`; `;
const SoftLinkContainer = styled(Paper)`
margin-top: 5px;
padding-top: 5px;
`;
const SoftLinkToMainWikiSelect = styled(Select)` const SoftLinkToMainWikiSelect = styled(Select)`
width: 100%; width: 100%;
`; `;
const AddSoftLinkButton = styled(CloseButton)``; const SoftLinkToMainWikiSelectInputLabel = styled(InputLabel)`
margin-top: 5px;
`;
function AddWorkspace({ wikiCreationMessage, onUpdateForm, onSave }) { function AddWorkspace({ wikiCreationMessage, onUpdateForm, onSave, onWikiCreationResult }) {
const [isCreateMainWorkspace, isCreateMainWorkspaceSetter] = useState(true); const [isCreateMainWorkspace, isCreateMainWorkspaceSetter] = useState(countWorkspace() === 0);
const [parentFolderLocation, parentFolderLocationSetter] = useState(''); const [parentFolderLocation, parentFolderLocationSetter] = useState('');
const [wikiFolderLocation, wikiFolderLocationSetter] = useState(''); const [wikiFolderLocation, wikiFolderLocationSetter] = useState('');
@ -84,9 +79,6 @@ function AddWorkspace({ wikiCreationMessage, onUpdateForm, onSave }) {
useEffect(() => { useEffect(() => {
wikiFolderLocationSetter(`${parentFolderLocation}/${wikiFolderName}`); wikiFolderLocationSetter(`${parentFolderLocation}/${wikiFolderName}`);
}, [parentFolderLocation, wikiFolderName]); }, [parentFolderLocation, wikiFolderName]);
const messageHasError = wikiCreationMessage.startsWith('Error: ');
const message = wikiCreationMessage.replace('Error: ', '');
const creationSucceed = !messageHasError && wikiCreationMessage.length > 0;
const workspaceFormData = { const workspaceFormData = {
name: wikiFolderLocation, name: wikiFolderLocation,
isSubWiki: !isCreateMainWorkspace, isSubWiki: !isCreateMainWorkspace,
@ -139,112 +131,56 @@ function AddWorkspace({ wikiCreationMessage, onUpdateForm, onSave }) {
</Typography> </Typography>
</LocationPickerButton> </LocationPickerButton>
<LocationPickerInput <LocationPickerInput
error={messageHasError} error={wikiCreationMessage}
helperText={message} helperText={wikiCreationMessage}
fullWidth fullWidth
onChange={event => parentFolderLocationSetter(event.target.value)} onChange={event => parentFolderLocationSetter(event.target.value)}
label="知识库的父文件夹" label="知识库的父文件夹"
value={parentFolderLocation} value={parentFolderLocation}
disabled={creationSucceed}
/> />
<LocationPickerInput <LocationPickerInput
fullWidth fullWidth
onChange={event => wikiFolderNameSetter(event.target.value)} onChange={event => wikiFolderNameSetter(event.target.value)}
label="知识库文件夹名" label="知识库文件夹名"
value={wikiFolderName} value={wikiFolderName}
disabled={creationSucceed}
/> />
<CreatorButton {!isCreateMainWorkspace && (
variant="contained" <>
color="primary" <SoftLinkToMainWikiSelectInputLabel id="main-wiki-select-label">
disabled={parentFolderLocation.length === 0 || creationSucceed} 主知识库位置
onClick={() => { </SoftLinkToMainWikiSelectInputLabel>
if (isCreateMainWorkspace) { <SoftLinkToMainWikiSelect
requestCopyWikiTemplate(parentFolderLocation, wikiFolderName); labelId="main-wiki-select-label"
} else { id="main-wiki-select"
requestCreateSubWiki(parentFolderLocation, wikiFolderName); value={mainWikiToLink}
} onChange={event => mainWikiToLinkSetter(event.target.value)}
onUpdateForm(workspaceFormData); >
}} {Object.keys(workspaces).map(workspaceID => (
> <MenuItem key={workspaceID} value={workspaces[workspaceID].name}>
<Typography variant="body1" display="inline"> {workspaces[workspaceID].name}
</MenuItem>
</Typography> ))}
<Typography </SoftLinkToMainWikiSelect>
variant="body2" {mainWikiToLink && (
noWrap <FormHelperText>
display="inline-block" <Typography variant="body1" display="inline">
align="center" 子知识库将链接到
style={{ direction: 'rtl', textTransform: 'none' }} </Typography>
> <Typography
{wikiFolderLocation} variant="body2"
</Typography> noWrap
<Typography variant="body1" display="inline"> display="inline"
创建WIKI align="center"
</Typography> style={{ direction: 'rtl', textTransform: 'none' }}
</CreatorButton> >
{mainWikiToLink}/tiddlers/{wikiFolderName}
</Typography>
</FormHelperText>
)}
</>
)}
</CreateContainer> </CreateContainer>
{!isCreateMainWorkspace && (
<SoftLinkContainer elevation={2} square>
<InputLabel id="main-wiki-select-label">主知识库位置</InputLabel>
<SoftLinkToMainWikiSelect
labelId="main-wiki-select-label"
id="main-wiki-select"
value={mainWikiToLink}
onChange={event => mainWikiToLinkSetter(event.target.value)}
>
{Object.keys(workspaces).map(workspaceID => (
<MenuItem key={workspaceID} value={workspaces[workspaceID].name}>
{workspaces[workspaceID].name}
</MenuItem>
))}
</SoftLinkToMainWikiSelect>
{mainWikiToLink && (
<FormHelperText>
<Typography variant="body1" display="inline">
子知识库将链接到
</Typography>
<Typography
variant="body2"
noWrap
display="inline"
align="center"
style={{ direction: 'rtl', textTransform: 'none' }}
>
{mainWikiToLink}/tiddlers/{wikiFolderName}
</Typography>
</FormHelperText>
)}
</SoftLinkContainer>
)}
{isCreateMainWorkspace ? (
<CloseButton
variant="contained"
color="secondary"
disabled={!creationSucceed}
onClick={() => {
onUpdateForm(workspaceFormData);
onSave();
}}
>
启动WIKI
</CloseButton>
) : (
<AddSoftLinkButton
variant="contained"
color="secondary"
disabled={!creationSucceed || !mainWikiToLink}
onClick={() => {
onUpdateForm(workspaceFormData);
onSave();
}}
>
链接到主知识库
</AddSoftLinkButton>
)}
<SyncContainer elevation={2} square> <SyncContainer elevation={2} square>
<Typography variant="subtitle1" align="center"> <Typography variant="subtitle1" align="center">
同步到云端 同步到云端
@ -253,6 +189,81 @@ function AddWorkspace({ wikiCreationMessage, onUpdateForm, onSave }) {
登录Github账号 登录Github账号
</SyncToGithubButton> </SyncToGithubButton>
</SyncContainer> </SyncContainer>
{isCreateMainWorkspace ? (
<CloseButton
variant="contained"
color="secondary"
disabled={!parentFolderLocation}
onClick={async () => {
onUpdateForm(workspaceFormData);
const creationResult = await requestCopyWikiTemplate(parentFolderLocation, wikiFolderName);
if (creationResult) {
onSave();
} else {
onWikiCreationResult(creationResult);
}
}}
>
{parentFolderLocation && (
<>
<Typography variant="body1" display="inline">
</Typography>
<Typography
variant="body2"
noWrap
display="inline-block"
align="center"
style={{ direction: 'rtl', textTransform: 'none' }}
>
{wikiFolderLocation}
</Typography>
</>
)}
<Typography variant="body1" display="inline">
创建WIKI
</Typography>
</CloseButton>
) : (
<CloseButton
variant="contained"
color="secondary"
disabled={!parentFolderLocation || !mainWikiToLink}
onClick={async () => {
onUpdateForm(workspaceFormData);
const creationResult = await requestCreateSubWiki(parentFolderLocation, wikiFolderName, mainWikiToLink);
if (creationResult) {
onSave();
} else {
onWikiCreationResult(creationResult);
}
}}
>
{parentFolderLocation && (
<>
<Typography variant="body1" display="inline">
</Typography>
<Typography
variant="body2"
noWrap
display="inline-block"
align="center"
style={{ direction: 'rtl', textTransform: 'none' }}
>
{wikiFolderLocation}
</Typography>
</>
)}
<Typography variant="body1" display="inline">
创建WIKI
</Typography>
<Typography variant="body1" display="inline">
并链接到主知识库
</Typography>
</CloseButton>
)}
</Container> </Container>
); );
} }
@ -265,6 +276,7 @@ AddWorkspace.propTypes = {
wikiCreationMessage: PropTypes.string, wikiCreationMessage: PropTypes.string,
onUpdateForm: PropTypes.func.isRequired, onUpdateForm: PropTypes.func.isRequired,
onSave: PropTypes.func.isRequired, onSave: PropTypes.func.isRequired,
onWikiCreationResult: PropTypes.func.isRequired,
}; };
const mapStateToProps = state => ({ const mapStateToProps = state => ({
@ -274,6 +286,7 @@ const mapStateToProps = state => ({
const actionCreators = { const actionCreators = {
updateForm, updateForm,
save, save,
wikiCreationResult,
}; };
export default connectComponent(AddWorkspace, mapStateToProps, actionCreators); export default connectComponent(AddWorkspace, mapStateToProps, actionCreators);

View file

@ -1,7 +1,7 @@
const { ipcRenderer } = window.require('electron'); const { ipcRenderer } = window.require('electron');
export const requestCopyWikiTemplate = (newFolderPath, folderName) => ipcRenderer.send('copy-wiki-template', newFolderPath, folderName); export const requestCopyWikiTemplate = (newFolderPath, folderName) => ipcRenderer.invoke('copy-wiki-template', newFolderPath, folderName);
export const requestCreateSubWiki = (newFolderPath, folderName) => ipcRenderer.send('create-sub-wiki', newFolderPath, folderName); export const requestCreateSubWiki = (newFolderPath, folderName, mainWikiToLink) => ipcRenderer.invoke('create-sub-wiki', newFolderPath, folderName, mainWikiToLink);
export const requestStartTiddlyWiki = (wikiPath) => ipcRenderer.send('request-start-tiddlywiki', wikiPath); export const requestStartTiddlyWiki = (wikiPath) => ipcRenderer.send('request-start-tiddlywiki', wikiPath);
export const requestOpenInBrowser = (url) => ipcRenderer.send('request-open-in-browser', url); export const requestOpenInBrowser = (url) => ipcRenderer.send('request-open-in-browser', url);
export const requestShowMessageBox = (message, type) => ipcRenderer.send('request-show-message-box', message, type); export const requestShowMessageBox = (message, type) => ipcRenderer.send('request-show-message-box', message, type);
@ -45,6 +45,7 @@ export const requestSetSystemPreference = (name, value) =>
ipcRenderer.send('request-set-system-preference', name, value); ipcRenderer.send('request-set-system-preference', name, value);
// Workspace // Workspace
export const countWorkspace = () => ipcRenderer.sendSync('count-workspace');
export const getWorkspace = (id) => ipcRenderer.sendSync('get-workspace', id); export const getWorkspace = (id) => ipcRenderer.sendSync('get-workspace', id);
export const getWorkspaces = () => ipcRenderer.sendSync('get-workspaces'); export const getWorkspaces = () => ipcRenderer.sendSync('get-workspaces');
export const requestClearBrowsingData = () => ipcRenderer.send('request-clear-browsing-data'); export const requestClearBrowsingData = () => ipcRenderer.send('request-clear-browsing-data');