feat: Add "Export" and "Duplicate" buttons in notes options menu. (#688)
Co-authored-by: Mough <mo@standardnotes.org>
This commit is contained in:
@@ -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 |
@@ -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 |
@@ -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}
|
||||
|
||||
@@ -20,5 +20,5 @@ export enum HtmlInputTypes {
|
||||
Text = 'text',
|
||||
Time = 'time',
|
||||
Url = 'url',
|
||||
Week = 'week'
|
||||
Week = 'week',
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -49,6 +49,8 @@ type NotesCtrlState = {
|
||||
[PrefKey.EditorMonospaceEnabled]?: boolean
|
||||
[PrefKey.EditorSpellcheck]?: boolean
|
||||
[PrefKey.EditorResizersEnabled]?: boolean
|
||||
[PrefKey.NotesShowTrashed]?: boolean
|
||||
[PrefKey.NotesHideProtected]?: boolean
|
||||
}
|
||||
|
||||
type NoteFlag = {
|
||||
|
||||
@@ -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",
|
||||
|
||||
25
yarn.lock
25
yarn.lock
@@ -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"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user