mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 17:56:25 +00:00
When storage or folder is removed, Detail components should render without error (#3168)
* optimize: when storage or folder is removed, Detail components should render without error, fix #2876 * optimize: Handle some scenarios where storage is not found, should not break the renderer * optimize: NoteList should work without error when storage is not found
This commit is contained in:
@@ -156,7 +156,12 @@ class MarkdownSplitEditor extends React.Component {
|
|||||||
linesHighlighted,
|
linesHighlighted,
|
||||||
RTL
|
RTL
|
||||||
} = this.props
|
} = this.props
|
||||||
const storage = findStorage(storageKey)
|
let storage
|
||||||
|
try {
|
||||||
|
storage = findStorage(storageKey)
|
||||||
|
} catch (e) {
|
||||||
|
return <div />
|
||||||
|
}
|
||||||
let editorFontSize = parseInt(config.editor.fontSize, 10)
|
let editorFontSize = parseInt(config.editor.fontSize, 10)
|
||||||
if (!(editorFontSize > 0 && editorFontSize < 101)) editorFontSize = 14
|
if (!(editorFontSize > 0 && editorFontSize < 101)) editorFontSize = 14
|
||||||
let editorIndentSize = parseInt(config.editor.indentSize, 10)
|
let editorIndentSize = parseInt(config.editor.indentSize, 10)
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ class FolderSelect extends React.Component {
|
|||||||
{optionList}
|
{optionList}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : currentOption ? (
|
||||||
<div styleName='idle' style={{ color: currentOption.folder.color }}>
|
<div styleName='idle' style={{ color: currentOption.folder.color }}>
|
||||||
<div styleName='idle-label'>
|
<div styleName='idle-label'>
|
||||||
<i className='fa fa-folder' />
|
<i className='fa fa-folder' />
|
||||||
@@ -303,7 +303,7 @@ class FolderSelect extends React.Component {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -479,10 +479,16 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
const currentOption = options.filter(
|
|
||||||
|
const currentOption = _.find(
|
||||||
|
options,
|
||||||
option =>
|
option =>
|
||||||
option.storage.key === storageKey && option.folder.key === folderKey
|
option.storage.key === storageKey && option.folder.key === folderKey
|
||||||
)[0]
|
)
|
||||||
|
|
||||||
|
// currentOption may be undefined
|
||||||
|
const storageName = _.get(currentOption, 'storage.name') || ''
|
||||||
|
const folderName = _.get(currentOption, 'folder.name') || ''
|
||||||
|
|
||||||
const trashTopBar = (
|
const trashTopBar = (
|
||||||
<div styleName='info'>
|
<div styleName='info'>
|
||||||
@@ -495,8 +501,8 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
/>
|
/>
|
||||||
<InfoButton onClick={e => this.handleInfoButtonClick(e)} />
|
<InfoButton onClick={e => this.handleInfoButtonClick(e)} />
|
||||||
<InfoPanelTrashed
|
<InfoPanelTrashed
|
||||||
storageName={currentOption.storage.name}
|
storageName={storageName}
|
||||||
folderName={currentOption.folder.name}
|
folderName={folderName}
|
||||||
updatedAt={formatDate(note.updatedAt)}
|
updatedAt={formatDate(note.updatedAt)}
|
||||||
createdAt={formatDate(note.createdAt)}
|
createdAt={formatDate(note.createdAt)}
|
||||||
exportAsHtml={this.exportAsHtml}
|
exportAsHtml={this.exportAsHtml}
|
||||||
@@ -579,8 +585,8 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
<InfoButton onClick={e => this.handleInfoButtonClick(e)} />
|
<InfoButton onClick={e => this.handleInfoButtonClick(e)} />
|
||||||
|
|
||||||
<InfoPanel
|
<InfoPanel
|
||||||
storageName={currentOption.storage.name}
|
storageName={storageName}
|
||||||
folderName={currentOption.folder.name}
|
folderName={folderName}
|
||||||
noteLink={`[${note.title}](:note:${
|
noteLink={`[${note.title}](:note:${
|
||||||
queryString.parse(location.search).key
|
queryString.parse(location.search).key
|
||||||
})`}
|
})`}
|
||||||
|
|||||||
@@ -885,10 +885,16 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
const currentOption = options.filter(
|
|
||||||
|
const currentOption = _.find(
|
||||||
|
options,
|
||||||
option =>
|
option =>
|
||||||
option.storage.key === storageKey && option.folder.key === folderKey
|
option.storage.key === storageKey && option.folder.key === folderKey
|
||||||
)[0]
|
)
|
||||||
|
|
||||||
|
// currentOption may be undefined
|
||||||
|
const storageName = _.get(currentOption, 'storage.name') || ''
|
||||||
|
const folderName = _.get(currentOption, 'folder.name') || ''
|
||||||
|
|
||||||
const trashTopBar = (
|
const trashTopBar = (
|
||||||
<div styleName='info'>
|
<div styleName='info'>
|
||||||
@@ -901,8 +907,8 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
/>
|
/>
|
||||||
<InfoButton onClick={e => this.handleInfoButtonClick(e)} />
|
<InfoButton onClick={e => this.handleInfoButtonClick(e)} />
|
||||||
<InfoPanelTrashed
|
<InfoPanelTrashed
|
||||||
storageName={currentOption.storage.name}
|
storageName={storageName}
|
||||||
folderName={currentOption.folder.name}
|
folderName={folderName}
|
||||||
updatedAt={formatDate(note.updatedAt)}
|
updatedAt={formatDate(note.updatedAt)}
|
||||||
createdAt={formatDate(note.createdAt)}
|
createdAt={formatDate(note.createdAt)}
|
||||||
exportAsMd={this.showWarning}
|
exportAsMd={this.showWarning}
|
||||||
@@ -951,8 +957,8 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
<InfoButton onClick={e => this.handleInfoButtonClick(e)} />
|
<InfoButton onClick={e => this.handleInfoButtonClick(e)} />
|
||||||
|
|
||||||
<InfoPanel
|
<InfoPanel
|
||||||
storageName={currentOption.storage.name}
|
storageName={storageName}
|
||||||
folderName={currentOption.folder.name}
|
folderName={folderName}
|
||||||
noteLink={`[${note.title}](:note:${
|
noteLink={`[${note.title}](:note:${
|
||||||
queryString.parse(location.search).key
|
queryString.parse(location.search).key
|
||||||
})`}
|
})`}
|
||||||
|
|||||||
@@ -1107,10 +1107,10 @@ class NoteList extends React.Component {
|
|||||||
|
|
||||||
getNoteFolder(note) {
|
getNoteFolder(note) {
|
||||||
// note.folder = folder key
|
// note.folder = folder key
|
||||||
return _.find(
|
const storage = this.getNoteStorage(note)
|
||||||
this.getNoteStorage(note).folders,
|
return storage
|
||||||
({ key }) => key === note.folder
|
? _.find(storage.folders, ({ key }) => key === note.folder)
|
||||||
)
|
: []
|
||||||
}
|
}
|
||||||
|
|
||||||
getViewType() {
|
getViewType() {
|
||||||
@@ -1145,9 +1145,14 @@ class NoteList extends React.Component {
|
|||||||
? this.getNotes().sort(sortFunc)
|
? this.getNotes().sort(sortFunc)
|
||||||
: this.sortByPin(this.getNotes().sort(sortFunc))
|
: this.sortByPin(this.getNotes().sort(sortFunc))
|
||||||
this.notes = notes = sortedNotes.filter(note => {
|
this.notes = notes = sortedNotes.filter(note => {
|
||||||
// this is for the trash box
|
if (
|
||||||
if (note.isTrashed !== true || location.pathname === '/trashed')
|
// has matching storage
|
||||||
|
!!this.getNoteStorage(note) &&
|
||||||
|
// this is for the trash box
|
||||||
|
(note.isTrashed !== true || location.pathname === '/trashed')
|
||||||
|
) {
|
||||||
return true
|
return true
|
||||||
|
}
|
||||||
})
|
})
|
||||||
if (sortDir === 'DESCENDING') this.notes.reverse()
|
if (sortDir === 'DESCENDING') this.notes.reverse()
|
||||||
|
|
||||||
@@ -1193,6 +1198,8 @@ class NoteList extends React.Component {
|
|||||||
sortBy === 'CREATED_AT' ? note.createdAt : note.updatedAt
|
sortBy === 'CREATED_AT' ? note.createdAt : note.updatedAt
|
||||||
).fromNow('D')
|
).fromNow('D')
|
||||||
|
|
||||||
|
const storage = this.getNoteStorage(note)
|
||||||
|
|
||||||
if (isDefault) {
|
if (isDefault) {
|
||||||
return (
|
return (
|
||||||
<NoteItem
|
<NoteItem
|
||||||
@@ -1205,7 +1212,7 @@ class NoteList extends React.Component {
|
|||||||
handleDragStart={this.handleDragStart.bind(this)}
|
handleDragStart={this.handleDragStart.bind(this)}
|
||||||
pathname={location.pathname}
|
pathname={location.pathname}
|
||||||
folderName={this.getNoteFolder(note).name}
|
folderName={this.getNoteFolder(note).name}
|
||||||
storageName={this.getNoteStorage(note).name}
|
storageName={storage.name}
|
||||||
viewType={viewType}
|
viewType={viewType}
|
||||||
showTagsAlphabetically={config.ui.showTagsAlphabetically}
|
showTagsAlphabetically={config.ui.showTagsAlphabetically}
|
||||||
coloredTags={config.coloredTags}
|
coloredTags={config.coloredTags}
|
||||||
@@ -1223,7 +1230,7 @@ class NoteList extends React.Component {
|
|||||||
handleDragStart={this.handleDragStart.bind(this)}
|
handleDragStart={this.handleDragStart.bind(this)}
|
||||||
pathname={location.pathname}
|
pathname={location.pathname}
|
||||||
folderName={this.getNoteFolder(note).name}
|
folderName={this.getNoteFolder(note).name}
|
||||||
storageName={this.getNoteStorage(note).name}
|
storageName={storage.name}
|
||||||
viewType={viewType}
|
viewType={viewType}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -835,7 +835,15 @@ function getAttachmentsPathAndStatus(markdownContent, storageKey, noteKey) {
|
|||||||
if (storageKey == null || noteKey == null || markdownContent == null) {
|
if (storageKey == null || noteKey == null || markdownContent == null) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const targetStorage = findStorage.findStorage(storageKey)
|
let targetStorage = null
|
||||||
|
try {
|
||||||
|
targetStorage = findStorage.findStorage(storageKey)
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(`No stroage found for: ${storageKey}`)
|
||||||
|
}
|
||||||
|
if (!targetStorage) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
const attachmentFolder = path.join(
|
const attachmentFolder = path.join(
|
||||||
targetStorage.path,
|
targetStorage.path,
|
||||||
DESTINATION_FOLDER,
|
DESTINATION_FOLDER,
|
||||||
|
|||||||
@@ -912,6 +912,19 @@ it('should test that getAttachmentsPathAndStatus return null if noteKey, storage
|
|||||||
expect(result).toBeNull()
|
expect(result).toBeNull()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should test that getAttachmentsPathAndStatus return null if no storage found', function() {
|
||||||
|
const noteKey = 'test'
|
||||||
|
const storageKey = 'not_exist'
|
||||||
|
const markdownContent = ''
|
||||||
|
|
||||||
|
const result = systemUnderTest.getAttachmentsPathAndStatus(
|
||||||
|
markdownContent,
|
||||||
|
storageKey,
|
||||||
|
noteKey
|
||||||
|
)
|
||||||
|
expect(result).toBeNull()
|
||||||
|
})
|
||||||
|
|
||||||
it('should test that getAttachmentsPathAndStatus return the correct path and status for attachments', async function() {
|
it('should test that getAttachmentsPathAndStatus return the correct path and status for attachments', async function() {
|
||||||
const dummyStorage = { path: 'dummyStoragePath' }
|
const dummyStorage = { path: 'dummyStoragePath' }
|
||||||
const noteKey = 'noteKey'
|
const noteKey = 'noteKey'
|
||||||
|
|||||||
Reference in New Issue
Block a user