Skip to content

Commit

Permalink
feat: improved status messages
Browse files Browse the repository at this point in the history
  • Loading branch information
amanharwara committed Dec 11, 2023
1 parent 98854b1 commit f1fd256
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 56 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { NativeFeatureIdentifier, NoteType } from '@standardnotes/features'
import { ConversionResult, Converter } from '../Converter'
import { Converter } from '../Converter'
import { ConversionResult } from '../ConversionResult'

type AegisData = {
db: {
Expand Down
9 changes: 9 additions & 0 deletions packages/ui-services/src/Import/ConversionResult.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { DecryptedItemInterface } from '@standardnotes/models'

export type ConversionResult = {
successful: DecryptedItemInterface[]
errored: {
name: string
error: Error
}[]
}
9 changes: 1 addition & 8 deletions packages/ui-services/src/Import/Converter.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
import { NoteType } from '@standardnotes/features'
import { DecryptedItemInterface, FileItem, ItemContent, NoteContent, SNNote, SNTag } from '@standardnotes/models'

export type ConversionResult = {
successful: DecryptedItemInterface[]
errored: {
name: string
error: Error
}[]
}
import { ConversionResult } from './ConversionResult'

export interface Converter {
getImportType(): string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import utc from 'dayjs/plugin/utc'
import { GenerateUuid } from '@standardnotes/services'
import MD5 from 'crypto-js/md5'
import Base64 from 'crypto-js/enc-base64'
import { ConversionResult, Converter, UploadFileFn } from '../Converter'
import { Converter, UploadFileFn } from '../Converter'
import { ConversionResult } from '../ConversionResult'
dayjs.extend(customParseFormat)
dayjs.extend(utc)

Expand Down
16 changes: 6 additions & 10 deletions packages/ui-services/src/Import/Importer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,8 @@ import {
} from '@standardnotes/models'
import { HTMLConverter } from './HTMLConverter/HTMLConverter'
import { SuperConverter } from './SuperConverter/SuperConverter'
import {
CleanupItemsFn,
ConversionResult,
Converter,
InsertNoteFn,
InsertTagFn,
LinkItemsFn,
UploadFileFn,
} from './Converter'
import { CleanupItemsFn, Converter, InsertNoteFn, InsertTagFn, LinkItemsFn, UploadFileFn } from './Converter'
import { ConversionResult } from './ConversionResult'
import { FilesClientInterface, SuperConverterServiceInterface } from '@standardnotes/files'
import { ContentType } from '@standardnotes/domain-core'

Expand Down Expand Up @@ -255,7 +248,7 @@ export class Importer {
throw new Error('Content is not valid')
}

await converter.convert(file, {
const result = await converter.convert(file, {
insertNote: this.insertNote,
insertTag: this.insertTag,
canUploadFiles: this.canUploadFiles(),
Expand All @@ -268,6 +261,9 @@ export class Importer {
cleanupItems: this.cleanupItems,
})

successful.push(...result.successful)
errored.push(...result.errored)

break
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { SuperConverterServiceInterface } from '@standardnotes/files'
import { parseFileName } from '@standardnotes/filepicker'
import { ConversionResult, Converter } from '../Converter'
import { Converter } from '../Converter'
import { ConversionResult } from '../ConversionResult'

export class SuperConverter implements Converter {
constructor(private converterService: SuperConverterServiceInterface) {}
Expand Down
2 changes: 1 addition & 1 deletion packages/ui-services/src/Import/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ export * from './EvernoteConverter/EvernoteConverter'
export * from './PlaintextConverter/PlaintextConverter'
export * from './Utils'
export * from './Importer'
export { ConversionResult } from './Converter'
export * from './ConversionResult'
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ const ImportModal = ({ importModalController }: { importModalController: ImportM
close,
} = importModalController

const isReadyToImport = files.length > 0 && files.every((file) => file.status === 'ready')
const isReadyToImport = files.length > 0 && files.every((file) => file.status === 'pending' && file.service)
const importSuccessOrError =
files.length > 0 && files.every((file) => file.status === 'success' || file.status === 'error')
files.length > 0 && files.every((file) => file.status === 'finished' || file.status === 'error')

const modalActions: ModalAction[] = useMemo(
() => [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export class ImportModalController extends AbstractViewController {
id: UuidGenerator.GenerateUuid(),
file,
service,
status: service ? 'ready' : 'pending',
status: 'pending',
} as ImportModalFile
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ImportModalController, ImportModalFile } from '@/Components/ImportModal/ImportModalController'
import { classNames, ContentType, pluralize } from '@standardnotes/snjs'
import { Importer } from '@standardnotes/ui-services'
import { ConversionResult, Importer } from '@standardnotes/ui-services'
import { observer } from 'mobx-react-lite'
import { useCallback, useEffect, useState } from 'react'
import Icon from '../Icon/Icon'
Expand All @@ -25,6 +25,53 @@ const NoteImportTypeIcons: Record<string, string> = {
super: 'file-doc',
}

const countSuccessfulItemsByGroup = (successful: ConversionResult['successful']) => {
let notes = 0
let tags = 0
let files = 0

for (const item of successful) {
if (item.content_type === ContentType.TYPES.Note) {
notes++
} else if (item.content_type === ContentType.TYPES.Tag) {
tags++
} else if (item.content_type === ContentType.TYPES.File) {
files++
}
}

return {
notes,
tags,
files,
}
}

const ImportFinishedStatus = ({ file }: { file: ImportModalFile }) => {
if (file.status !== 'finished') {
return null
}

const { notes, tags, files } = countSuccessfulItemsByGroup(file.successful)

const notesStatus = notes > 0 ? `${notes} ${pluralize(notes, 'note', 'notes')}` : ''
const tagsStatus = tags > 0 ? `${tags} ${pluralize(tags, 'tag', 'tags')}` : ''
const filesStatus = files > 0 ? `${files} ${pluralize(files, 'file', 'files')}` : ''
const status = [notesStatus, tagsStatus, filesStatus].filter(Boolean).join(', ')

return (
<>
{file.successful.length > 0 && (
<div className="flex items-center gap-1">
<Icon type="check-circle-filled" className="flex-shrink-0 text-success" size="small" />
<span>{status} imported</span>
</div>
)}
{file.errored.length > 0 && <></>}
</>
)
}

const ImportModalFileItem = ({
file,
updateFile,
Expand All @@ -36,6 +83,7 @@ const ImportModalFileItem = ({
removeFile: ImportModalController['removeFile']
importer: Importer
}) => {
const [isDetectingService, setIsDetectingService] = useState(false)
const [changingService, setChangingService] = useState(false)

const setFileService = useCallback(
Expand All @@ -46,36 +94,24 @@ const ImportModalFileItem = ({
updateFile({
...file,
service,
status: service ? 'ready' : 'pending',
status: 'pending',
})
},
[file, updateFile],
)

useEffect(() => {
const detect = async () => {
setIsDetectingService(true)
const detectedService = await importer.detectService(file.file)
void setFileService(detectedService)
setIsDetectingService(false)
}
if (file.service === undefined) {
void detect()
}
}, [file, importer, setFileService])

const notePayloads =
file.status === 'ready' && file.payloads
? file.payloads.filter((payload) => payload.content_type === ContentType.TYPES.Note)
: []
const tagPayloads =
file.status === 'ready' && file.payloads
? file.payloads.filter((payload) => payload.content_type === ContentType.TYPES.Tag)
: []

const payloadsImportMessage =
`Ready to import ${notePayloads.length} ` +
pluralize(notePayloads.length, 'note', 'notes') +
(tagPayloads.length > 0 ? ` and ${tagPayloads.length} ${pluralize(tagPayloads.length, 'tag', 'tags')}` : '')

return (
<div
className={classNames(
Expand All @@ -91,22 +127,22 @@ const ImportModalFileItem = ({
)}
<div className="flex flex-col">
<div>{file.file.name}</div>
<div className="line-clamp-3 text-xs opacity-75">
{file.status === 'ready'
? notePayloads.length > 1 || tagPayloads.length
? payloadsImportMessage
: 'Ready to import'
: null}
{file.status === 'pending' && !file.service && 'Could not auto-detect service. Please select manually.'}
{file.status === 'parsing' && 'Parsing...'}
{file.status === 'importing' && 'Importing...'}
{file.status === 'uploading-files' && 'Uploading and embedding files...'}
{file.status === 'error' && file.error.message}
{file.status === 'success' && file.successMessage}
</div>
{isDetectingService ? (
<div className="text-xs opacity-75">Detecting service...</div>
) : (
<div className="line-clamp-3 text-xs opacity-75">
{file.status === 'pending' && file.service && 'Ready to import'}
{file.status === 'pending' && !file.service && 'Could not auto-detect service. Please select manually.'}
{file.status === 'parsing' && 'Parsing...'}
{file.status === 'importing' && 'Importing...'}
{file.status === 'uploading-files' && 'Uploading and embedding files...'}
{file.status === 'error' && file.error.message}
<ImportFinishedStatus file={file} />
</div>
)}
</div>
</div>
{(file.status === 'ready' || file.status === 'pending') && (
{file.status === 'pending' && (
<div className="flex items-center">
{changingService ? (
<>
Expand Down Expand Up @@ -172,7 +208,9 @@ const ImportModalFileItem = ({
</button>
</div>
)}
{file.status === 'success' && <Icon type="check-circle-filled" className="flex-shrink-0 text-success" />}
{file.status === 'finished' && file.successful.length > 0 && file.errored.length === 0 && (
<Icon type="check-circle-filled" className="flex-shrink-0 text-success" />
)}
{file.status === 'error' && <Icon type="warning" className="flex-shrink-0 text-danger" />}
</div>
)
Expand Down

0 comments on commit f1fd256

Please sign in to comment.