feat: Add "Export" and "Duplicate" buttons in notes options menu. (#688)

Co-authored-by: Mough <mo@standardnotes.org>
This commit is contained in:
Aman Harwara 2021-10-19 21:13:20 +05:30 committed by GitHub
parent f9b15262c7
commit 3a4e2509af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 72 additions and 50 deletions

View file

@ -1,3 +1,3 @@
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.66724 3.66626C1.66724 2.56169 2.56267 1.66626 3.66724 1.66626H11.3339C12.4385 1.66626 13.3339 2.56169 13.3339 3.66626V13.3329H3.66724C2.56267 13.3329 1.66724 12.4375 1.66724 11.3329V3.66626ZM16.3339 6.66626C17.4385 6.66626 18.3339 7.56169 18.3339 8.66626V16.3329C18.3339 17.4375 17.4385 18.3329 16.3339 18.3329H8.66724C7.56267 18.3329 6.66724 17.4375 6.66724 16.3329V14.9996H15.0006V6.66626H16.3339ZM3.3339 3.33293V11.6663H11.6672V3.33293H3.3339Z" fill="#72767E"/>
<path d="M1.66724 3.66626C1.66724 2.56169 2.56267 1.66626 3.66724 1.66626H11.3339C12.4385 1.66626 13.3339 2.56169 13.3339 3.66626V13.3329H3.66724C2.56267 13.3329 1.66724 12.4375 1.66724 11.3329V3.66626ZM16.3339 6.66626C17.4385 6.66626 18.3339 7.56169 18.3339 8.66626V16.3329C18.3339 17.4375 17.4385 18.3329 16.3339 18.3329H8.66724C7.56267 18.3329 6.66724 17.4375 6.66724 16.3329V14.9996H15.0006V6.66626H16.3339ZM3.3339 3.33293V11.6663H11.6672V3.33293H3.3339Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 557 B

After

Width:  |  Height:  |  Size: 542 B

View file

@ -1,3 +1,3 @@
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11 3.5V9.5H12.17L10 11.67L7.83 9.5H9V3.5H11ZM13 1.5H7V7.5H3L10 14.5L17 7.5H13V1.5ZM17 16.5H3V18.5H17V16.5Z" fill="#72767E"/>
<path d="M11 3.5V9.5H12.17L10 11.67L7.83 9.5H9V3.5H11ZM13 1.5H7V7.5H3L10 14.5L17 7.5H13V1.5ZM17 16.5H3V18.5H17V16.5Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 215 B

After

Width:  |  Height:  |  Size: 200 B

View file

@ -205,6 +205,26 @@ export const NotesOptions = observer(
setTagsMenuOpen(!tagsMenuOpen);
};
const downloadSelectedItems = () => {
notes.forEach((note) => {
const editor = application.componentManager.editorForNote(note);
const format = editor?.package_info?.file_type || 'txt';
const downloadAnchor = document.createElement('a');
downloadAnchor.setAttribute(
'href',
'data:text/plain;charset=utf-8,' + encodeURIComponent(note.text)
);
downloadAnchor.setAttribute('download', `${note.title}.${format}`);
downloadAnchor.click();
});
};
const duplicateSelectedItems = () => {
notes.forEach((note) => {
application.duplicateItem(note);
});
};
return (
<>
<Switch
@ -329,6 +349,22 @@ export const NotesOptions = observer(
Unpin
</button>
)}
<button
onBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={downloadSelectedItems}
>
<Icon type="download" className={iconClass} />
Export
</button>
<button
onBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={duplicateSelectedItems}
>
<Icon type="copy" className={iconClass} />
Duplicate
</button>
{unarchived && (
<button
onBlur={closeOnBlur}

View file

@ -20,5 +20,5 @@ export enum HtmlInputTypes {
Text = 'text',
Time = 'time',
Url = 'url',
Week = 'week'
Week = 'week',
}

View file

@ -94,7 +94,6 @@ export const Extensions: FunctionComponent<{
<PreferencesGroup>
{
extensions
.filter(extension => extension.package_info.identifier !== 'org.standardnotes.extensions-manager')
.sort((e1, e2) => e1.name.toLowerCase().localeCompare(e2.name.toLowerCase()))
.map((extension, i) => (
<ExtensionItem

View file

@ -1,5 +1,6 @@
import { Dropdown, DropdownItem } from '@/components/Dropdown';
import { IconType } from '@/components/Icon';
import { FeatureIdentifier } from '@standardnotes/snjs';
import {
PreferencesGroup,
PreferencesSegment,
@ -20,37 +21,29 @@ type Props = {
application: WebApplication;
};
enum EditorIdentifier {
PlainEditor = 'plain-editor',
BoldEditor = 'org.standardnotes.bold-editor',
CodeEditor = 'org.standardnotes.code-editor',
MarkdownBasic = 'org.standardnotes.simple-markdown-editor',
MarkdownMath = 'org.standardnotes.fancy-markdown-editor',
MarkdownMinimist = 'org.standardnotes.minimal-markdown-editor',
MarkdownPro = 'org.standardnotes.advanced-markdown-editor',
PlusEditor = 'org.standardnotes.plus-editor',
SecureSpreadsheets = 'org.standardnotes.standard-sheets',
TaskEditor = 'org.standardnotes.simple-task-editor',
TokenVault = 'org.standardnotes.token-vault',
}
type EditorOption = {
icon?: IconType;
label: string;
value: FeatureIdentifier | 'plain-editor';
};
const getEditorIconType = (identifier: string): IconType | null => {
switch (identifier) {
case EditorIdentifier.BoldEditor:
case EditorIdentifier.PlusEditor:
case FeatureIdentifier.BoldEditor:
case FeatureIdentifier.PlusEditor:
return 'rich-text';
case EditorIdentifier.MarkdownBasic:
case EditorIdentifier.MarkdownMath:
case EditorIdentifier.MarkdownMinimist:
case EditorIdentifier.MarkdownPro:
case FeatureIdentifier.MarkdownBasicEditor:
case FeatureIdentifier.MarkdownMathEditor:
case FeatureIdentifier.MarkdownMinimistEditor:
case FeatureIdentifier.MarkdownProEditor:
return 'markdown';
case EditorIdentifier.TokenVault:
case FeatureIdentifier.TokenVaultEditor:
return 'authenticator';
case EditorIdentifier.SecureSpreadsheets:
case FeatureIdentifier.SheetsEditor:
return 'spreadsheets';
case EditorIdentifier.TaskEditor:
case FeatureIdentifier.TaskEditor:
return 'tasks';
case EditorIdentifier.CodeEditor:
case FeatureIdentifier.CodeEditor:
return 'code';
}
return null;
@ -90,14 +83,13 @@ export const Defaults: FunctionComponent<Props> = ({ application }) => {
const [editorItems, setEditorItems] = useState<DropdownItem[]>([]);
const [defaultEditorValue] = useState(
() =>
getDefaultEditor(application)?.package_info?.identifier ||
EditorIdentifier.PlainEditor
getDefaultEditor(application)?.package_info?.identifier || 'plain-editor'
);
useEffect(() => {
const editors = application.componentManager
.componentsForArea(ComponentArea.Editor)
.map((editor) => {
.map((editor): EditorOption => {
const identifier = editor.package_info.identifier;
const iconType = getEditorIconType(identifier);
@ -111,7 +103,7 @@ export const Defaults: FunctionComponent<Props> = ({ application }) => {
{
icon: 'plain-text',
label: 'Plain Editor',
value: EditorIdentifier.PlainEditor,
value: 'plain-editor',
},
])
.sort((a, b) => {
@ -127,7 +119,7 @@ export const Defaults: FunctionComponent<Props> = ({ application }) => {
);
const currentDefault = getDefaultEditor(application);
if (value !== EditorIdentifier.PlainEditor) {
if (value !== 'plain-editor') {
const editorComponent = editors.filter(
(e) => e.package_info.identifier === value
)[0];

View file

@ -49,6 +49,8 @@ type NotesCtrlState = {
[PrefKey.EditorMonospaceEnabled]?: boolean
[PrefKey.EditorSpellcheck]?: boolean
[PrefKey.EditorResizersEnabled]?: boolean
[PrefKey.NotesShowTrashed]?: boolean
[PrefKey.NotesHideProtected]?: boolean
}
type NoteFlag = {

View file

@ -71,9 +71,9 @@
"@reach/checkbox": "^0.13.2",
"@reach/dialog": "^0.13.0",
"@reach/listbox": "^0.16.1",
"@standardnotes/features": "1.6.1",
"@standardnotes/features": "1.7.2",
"@standardnotes/sncrypto-web": "1.5.2",
"@standardnotes/snjs": "2.14.14",
"@standardnotes/snjs": "2.15.2",
"mobx": "^6.3.2",
"mobx-react-lite": "^3.2.0",
"preact": "^10.5.12",

View file

@ -2117,17 +2117,10 @@
dependencies:
"@standardnotes/auth" "^3.7.0"
"@standardnotes/features@1.6.1":
version "1.6.1"
resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.6.1.tgz#bfa227bd231dc1b54449936663731f5132b08e23"
integrity sha512-IC6fEotUqs23JdZx96JnEgARxwYzjmPz3UwU/uVn8hHjxPev/W0nyZFRiSlj4v+dod0jSa6FTR8iLLsOQ6M4Ug==
dependencies:
"@standardnotes/common" "^1.1.0"
"@standardnotes/features@1.6.2":
version "1.6.2"
resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.6.2.tgz#98c5998426d9f93e06c2846c5bc7b6aef8d31063"
integrity sha512-s/rqRyG7mrrgxJOzckPSYlB68wsRpM9jlFwDE+7zQO5/xKh+37ueWfy3RoqOgkKLey6lMpnTurofIJCvqLM3dQ==
"@standardnotes/features@1.7.2":
version "1.7.2"
resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.7.2.tgz#7a45a947f56c55d191614f7293af553c5209705a"
integrity sha512-zFTHzYAC+08Lbeni5x3RalR5FT8qVORgv3T/z6/Ye4mGvDyXSAddgDPn+o/NmzirwBTpaF6ogSzwZocsElm8zg==
dependencies:
"@standardnotes/common" "^1.1.0"
@ -2149,15 +2142,15 @@
"@standardnotes/sncrypto-common" "^1.5.2"
libsodium-wrappers "^0.7.8"
"@standardnotes/snjs@2.14.14":
version "2.14.14"
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.14.14.tgz#02886f431570a19a7dc5de0411fb19bb864281f2"
integrity sha512-IQVsRLFhbmRtF2kB9mXnccjY2lBCb+k1biLmM6lF5ZpanxPPeW/Z5H398QWgCFzfKu70nocSXO+SqmLswKxnLQ==
"@standardnotes/snjs@2.15.2":
version "2.15.2"
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.15.2.tgz#4502a02333529434d2c8c00830652cce31c57d25"
integrity sha512-n0R6wSJfwYoBVtChPbBssvvPQEyYufP7AD+IEibjjbmZImFQky/7x45hsoEsFti0EL5FheAHHKFCC//4jD4fiA==
dependencies:
"@standardnotes/auth" "3.7.2"
"@standardnotes/common" "1.2.0"
"@standardnotes/domain-events" "2.1.0"
"@standardnotes/features" "1.6.2"
"@standardnotes/features" "1.7.2"
"@standardnotes/settings" "1.2.0"
"@standardnotes/sncrypto-common" "1.5.2"