diff --git a/public/locales/ar.json b/public/locales/ar.json index 8ba4b9d56..13a259c5d 100644 --- a/public/locales/ar.json +++ b/public/locales/ar.json @@ -124,10 +124,10 @@ "image": "صورة", "uploadImage": "تحميل صورة" }, - "menu": { + "documentBar": { "menu": "القائمة", "new": "جديد", - "publish": "انشر", + "shareLink": "", "extra": "إضافي", "revision": "مراجعة", "slideMode": "نمط الشرائح التقديمية", diff --git a/public/locales/ca.json b/public/locales/ca.json index 26a1f7c26..7490230fd 100644 --- a/public/locales/ca.json +++ b/public/locales/ca.json @@ -124,10 +124,10 @@ "image": "Imatge", "uploadImage": "Pujar imatge" }, - "menu": { + "documentBar": { "menu": "Menú", "new": "Nou", - "publish": "Publicar", + "shareLink": "", "extra": "Extra", "revision": "Revisió", "slideMode": "Mode presentació", diff --git a/public/locales/cs.json b/public/locales/cs.json index 1ade5352c..13100d485 100644 --- a/public/locales/cs.json +++ b/public/locales/cs.json @@ -124,10 +124,10 @@ "image": "Obrázek", "uploadImage": "Nahrát obrázek" }, - "menu": { + "documentBar": { "menu": "Menu", "new": "Nová", - "publish": "Publikovat", + "shareLink": "", "extra": "Extra", "revision": "Revize", "slideMode": "Režim prezentace", diff --git a/public/locales/da.json b/public/locales/da.json index 57171c06f..79a5a1210 100644 --- a/public/locales/da.json +++ b/public/locales/da.json @@ -108,10 +108,10 @@ "image": "Billede", "uploadImage": "Upload billede" }, - "menu": { + "documentBar": { "menu": "Menu", "new": "Ny", - "publish": "Publicér", + "shareLink": "", "extra": "Ekstra", "revision": "Revision", "slideMode": "Præsentationstilstand", @@ -166,4 +166,4 @@ "error": {} } } -} \ No newline at end of file +} diff --git a/public/locales/de.json b/public/locales/de.json index 24f4ab941..bd4406acd 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -124,10 +124,10 @@ "image": "Foto", "uploadImage": "Foto hochladen" }, - "menu": { + "documentBar": { "menu": "Menü", "new": "Neu", - "publish": "Veröffentlichen", + "shareLink": "Link teilen", "extra": "Extra", "revision": "Version", "slideMode": "Präsentationsmodus", diff --git a/public/locales/el.json b/public/locales/el.json index b0878534f..4ec885ae9 100644 --- a/public/locales/el.json +++ b/public/locales/el.json @@ -108,10 +108,10 @@ "image": "Εικόνα", "uploadImage": "Ανέβασμα φωτογραφίας" }, - "menu": { + "documentBar": { "menu": "Μενού", "new": "Νέο", - "publish": "Δημοσίευση", + "shareLink": "", "extra": "Επιπλέον", "revision": "Αναθεώρηση", "slideMode": "Λειτουργία με σύρσιμο", @@ -166,4 +166,4 @@ "error": {} } } -} \ No newline at end of file +} diff --git a/public/locales/en.json b/public/locales/en.json index cf02d65f7..ec26fec1b 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -16,32 +16,32 @@ "history": { "error": { "getHistory": { - "title": "Load History Error", - "text": "While trying to load the history form the server an error occurred" + "title": "Load History Error", + "text": "While trying to load the history form the server an error occurred" }, "deleteHistory": { - "title": "Delete History Error", - "text": "While trying to delete the history on the server an error occurred" + "title": "Delete History Error", + "text": "While trying to delete the history on the server an error occurred" }, "setHistory": { - "title": "Upload History Error", - "text": "While trying to upload the history to the server an error occurred" + "title": "Upload History Error", + "text": "While trying to upload the history to the server an error occurred" }, "deleteNote": { - "title": "Delete Note Error", - "text": "While trying to delete a note on the server an error occurred" + "title": "Delete Note Error", + "text": "While trying to delete a note on the server an error occurred" }, "updateEntry": { - "title": "Update History Entry Error", - "text": "While trying to update a history entry on the server an error occurred" + "title": "Update History Entry Error", + "text": "While trying to update a history entry on the server an error occurred" }, "deleteEntry": { - "title": "Delete History Entry Error", - "text": "While trying to delete a history entry on the server an error occurred" + "title": "Delete History Entry Error", + "text": "While trying to delete a history entry on the server an error occurred" }, "notFoundEntry": { - "title": "History Entry not found", - "text": "We can't find the history entry you requested." + "title": "History Entry not found", + "text": "We can't find the history entry you requested." } }, "noHistory": "No history", @@ -72,10 +72,10 @@ "tooNewVersion": "The file '{{fileName}}' comes from a newer client and can't be imported." }, "removeNote": { - "title": "Remove note from history", - "question": "Do you really want to remove this note from your history?", - "warning": "This just removes the history entry and won't delete the note itself.", - "button": "Remove note from history" + "title": "Remove note from history", + "question": "Do you really want to remove this note from your history?", + "warning": "This just removes the history entry and won't delete the note itself.", + "button": "Remove note from history" } }, "tableHeader": { @@ -85,11 +85,11 @@ "lastVisit": "Last Visit" }, "menu": { - "recentNotes": "Recent notes", - "entryLocal": "Saved in your browser history", - "entryRemote": "Saved in your user history", - "removeEntry": "Remove from history", - "deleteNote": "Delete note" + "recentNotes": "Recent notes", + "entryLocal": "Saved in your browser history", + "entryRemote": "Saved in your user history", + "removeEntry": "Remove from history", + "deleteNote": "Delete note" } }, "navigation": { @@ -219,21 +219,41 @@ "uploadImage": "Upload Image", "table": "Table", "line": "Horizontal line", - "comment": "Comment" + "comment": "Comment", + "preferences": "Editor settings", + "emoji": "Open emoji picker" }, - "menu": { + "documentBar": { "menu": "Menu", + "import": "Import", + "export": "Export", "new": "New", - "publish": "Publish", + "shareLink": "Share link", "extra": "Extra", "revision": "Revision", "slideMode": "Slide Mode", "download": "Download", "help": "Help", - "deleteNote": "Delete note" + "deleteNote": "Delete note", + "permissions": "Permissions", + "documentInfo": "Document info", + "pinNoteToHistory": "Pin note to history", + "pinnedToHistory": "Pinned to history" + }, + "statusBar": { + "cursor": "Line {{line}}, Columns {{columns}}", + "selection": { + "column": "Selected {{count}} columns", + "line": "Selected {{count}} lines" + }, + "lines": "{{lines}} Lines", + "length": "Length {{length}}", + "lengthTooltip": "You can write up to 100000 characters in this document." }, "export": { - "rawHtml": "Raw HTML" + "rawHtml": "Raw HTML", + "pdf": "PDF export is unavailable.", + "why": "Why?" }, "import": { "clipboard": "Clipboard" @@ -244,6 +264,13 @@ "selectProject": "Select From Available Projects", "selectSnippet": "Select From Available Snippets" }, + "documentInfo": { + "title": "Document info", + "created": "<0> created this note <1> ago", + "edited": "<0> was the last editor <1> ago", + "usersContributed": "<0> users contributed to this document", + "revisions": "<0> revisions are saved" + }, "gistImport": { "title": "Import from Gist", "insertGistUrl": "Paste your gist url here…" @@ -265,10 +292,25 @@ "question": "Do you really want to delete this note?", "warning": "All users will lose their connection. This process is irreversible.", "button": "Delete note" + }, + "permissions": { + "title": "Permissions" + }, + "shareLink": { + "title": "Share link", + "viewOnlyDescription": "This link points to a read-only version of this note. You can use this e.g. for feedback from friends and colleagues." + }, + "preferences": { + "title": "Preferences", + "theme": "Editor theme", + "keyMap": "Keymap", + "indentWithTabs": "Tab character", + "indentUnit": "Tab size (when using spaces)", + "spellChecker": "Spell checking" } }, "embeddings": { - "clickToLoad": "Click to load" + "clickToLoad": "Click to load" } }, "common": { @@ -280,7 +322,8 @@ "close": "Close", "save": "Save", "or": "or", - "and": "and" + "and": "and", + "avatarOf": "avatar of '{{name}}'" }, "login": { "chooseMethod": "Choose method", @@ -297,15 +340,15 @@ } }, "register": { - "title": "Register", - "passwordAgain": "Password (again)", - "usernameInfo": "The username is your unique identifier for login.", - "passwordInfo": "Choose a unique and secure password. It must contain at least 8 characters.", - "infoTermsPrivacy": "With the registration of my user account I agree to the following terms:", - "error": { - "usernameExisting": "There is already an account with this username.", - "other": "There was an error while registering your account. Just try it again." - } + "title": "Register", + "passwordAgain": "Password (again)", + "usernameInfo": "The username is your unique identifier for login.", + "passwordInfo": "Choose a unique and secure password. It must contain at least 8 characters.", + "infoTermsPrivacy": "With the registration of my user account I agree to the following terms:", + "error": { + "usernameExisting": "There is already an account with this username.", + "other": "There was an error while registering your account. Just try it again." + } } } } diff --git a/public/locales/eo.json b/public/locales/eo.json index 4bc8ff474..5165bff93 100644 --- a/public/locales/eo.json +++ b/public/locales/eo.json @@ -108,10 +108,10 @@ "image": "Bildo", "uploadImage": "Alŝutu bildon" }, - "menu": { + "documentBar": { "menu": "Menuo", "new": "Nova", - "publish": "Dissendu", + "shareLink": "", "extra": "Plia", "revision": "Versio", "slideMode": "Bildvica modo", @@ -166,4 +166,4 @@ "error": {} } } -} \ No newline at end of file +} diff --git a/public/locales/es.json b/public/locales/es.json index f8471d994..c783df447 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -124,10 +124,10 @@ "image": "Imagen", "uploadImage": "Subir imagen" }, - "menu": { + "documentBar": { "menu": "Menú", "new": "Nuevo", - "publish": "Publicar", + "shareLink": "", "extra": "Extra", "revision": "Revision", "slideMode": "Modo presentación", diff --git a/public/locales/fr.json b/public/locales/fr.json index 65e9946b5..191917fd6 100644 --- a/public/locales/fr.json +++ b/public/locales/fr.json @@ -124,10 +124,10 @@ "image": "Image", "uploadImage": "Téléverser une image" }, - "menu": { + "documentBar": { "menu": "Menu", "new": "Nouvelle", - "publish": "Publier", + "shareLink": "", "extra": "Extra", "revision": "Historique", "slideMode": "Mode présentation", diff --git a/public/locales/hi.json b/public/locales/hi.json index caa745f6e..f547a17f1 100644 --- a/public/locales/hi.json +++ b/public/locales/hi.json @@ -108,10 +108,10 @@ "image": "तस्वीर", "uploadImage": "तस्वीर डालिये" }, - "menu": { + "documentBar": { "menu": "मेन्यू", "new": "नया", - "publish": "प्रकाशित करें", + "shareLink": "", "extra": "अतिरिक्त", "revision": "संशोधन", "slideMode": "स्लाइड मोड", @@ -166,4 +166,4 @@ "error": {} } } -} \ No newline at end of file +} diff --git a/public/locales/hr.json b/public/locales/hr.json index e0484de36..2e2e599b1 100644 --- a/public/locales/hr.json +++ b/public/locales/hr.json @@ -108,10 +108,10 @@ "image": "Slika", "uploadImage": "Prenesi sliku" }, - "menu": { + "documentBar": { "menu": "Meni", "new": "Novo", - "publish": "Objavi", + "shareLink": "", "extra": "Dodatno", "revision": "Revizija", "slideMode": "Način slajda", @@ -166,4 +166,4 @@ "error": {} } } -} \ No newline at end of file +} diff --git a/public/locales/id.json b/public/locales/id.json index 2b7216e8f..deb0d98af 100644 --- a/public/locales/id.json +++ b/public/locales/id.json @@ -124,10 +124,10 @@ "image": "Gambar", "uploadImage": "Unggah Gambar" }, - "menu": { + "documentBar": { "menu": "Menu", "new": "Baru", - "publish": "Terbitkan", + "shareLink": "", "extra": "Tambahan", "revision": "Revisi", "slideMode": "Mode Slide", diff --git a/public/locales/it.json b/public/locales/it.json index d100e2260..1bb8dfd62 100644 --- a/public/locales/it.json +++ b/public/locales/it.json @@ -124,10 +124,10 @@ "image": "Immagine", "uploadImage": "Carica Immagine" }, - "menu": { + "documentBar": { "menu": "Menu", "new": "Nuovo", - "publish": "Pubblica", + "shareLink": "", "extra": "Extra", "revision": "Revisione", "slideMode": "Modalità slide", diff --git a/public/locales/ja.json b/public/locales/ja.json index 17c366e19..944ae94b3 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -124,10 +124,10 @@ "image": "画像", "uploadImage": "画像をアップロード" }, - "menu": { + "documentBar": { "menu": "メニュー", "new": "新規作成", - "publish": "公開する", + "shareLink": "", "extra": "その他", "revision": "編集履歴", "slideMode": "スライドモード", diff --git a/public/locales/ko.json b/public/locales/ko.json index 1593a61fd..50e771145 100644 --- a/public/locales/ko.json +++ b/public/locales/ko.json @@ -120,10 +120,10 @@ "image": "이미지", "uploadImage": "이미지 업로드" }, - "menu": { + "documentBar": { "menu": "메뉴", "new": "새", - "publish": "공개하기", + "shareLink": "", "extra": "추가", "revision": "기록", "slideMode": "슬라이드 모드", diff --git a/public/locales/nl.json b/public/locales/nl.json index 9bb75da98..396fe73ed 100644 --- a/public/locales/nl.json +++ b/public/locales/nl.json @@ -124,10 +124,10 @@ "image": "Afbeelding", "uploadImage": "Afbeelding uploaden" }, - "menu": { + "documentBar": { "menu": "Menu", "new": "Nieuw", - "publish": "Publiceren", + "shareLink": "", "extra": "Extra", "revision": "Versie", "slideMode": "Presentatiemodus", diff --git a/public/locales/pl.json b/public/locales/pl.json index c4457b991..c1e8e6548 100644 --- a/public/locales/pl.json +++ b/public/locales/pl.json @@ -124,10 +124,10 @@ "image": "Zdjęcie", "uploadImage": "Prześlij zdjęcie" }, - "menu": { + "documentBar": { "menu": "Menu", "new": "Nowy", - "publish": "Publikuj", + "shareLink": "", "extra": "Ekstra", "revision": "Korekta", "slideMode": "Tryb slajdów", diff --git a/public/locales/pt.json b/public/locales/pt.json index f6592fa73..e8aca5d0b 100644 --- a/public/locales/pt.json +++ b/public/locales/pt.json @@ -124,10 +124,10 @@ "image": "Imagem", "uploadImage": "Carregar Imagem" }, - "menu": { + "documentBar": { "menu": "Menu", "new": "Novo", - "publish": "Publicar", + "shareLink": "", "extra": "Extra", "revision": "Revisão", "slideMode": "Modo Apresentação", diff --git a/public/locales/ru.json b/public/locales/ru.json index 4e6bd86ed..926206b0f 100644 --- a/public/locales/ru.json +++ b/public/locales/ru.json @@ -124,10 +124,10 @@ "image": "Изображение", "uploadImage": "Загрузить изображение" }, - "menu": { + "documentBar": { "menu": "Меню", "new": "Новая", - "publish": "Опубликовать", + "shareLink": "", "extra": "Дополнительно", "revision": "Изменения", "slideMode": "Режим слайдера", diff --git a/public/locales/sk.json b/public/locales/sk.json index 12b7a43a1..9ce2d2e10 100644 --- a/public/locales/sk.json +++ b/public/locales/sk.json @@ -124,10 +124,10 @@ "image": "Obrázok", "uploadImage": "Nahrať obrázok" }, - "menu": { + "documentBar": { "menu": "Menu", "new": "Nová", - "publish": "Publikovať", + "shareLink": "", "extra": "Extra", "revision": "Revízia", "slideMode": "Prezentačný režim", diff --git a/public/locales/sr.json b/public/locales/sr.json index 814b8e98c..6f1ef4a71 100644 --- a/public/locales/sr.json +++ b/public/locales/sr.json @@ -123,10 +123,10 @@ "image": "Слика", "uploadImage": "Пошаљи слику" }, - "menu": { + "documentBar": { "menu": "Мени", "new": "Ново", - "publish": "Објави", + "shareLink": "", "extra": "Додатно", "revision": "Ревизија", "slideMode": "Презентациони мод", diff --git a/public/locales/sv.json b/public/locales/sv.json index 64e4db2f8..edac49c13 100644 --- a/public/locales/sv.json +++ b/public/locales/sv.json @@ -124,10 +124,10 @@ "image": "Bild", "uploadImage": "Ladda upp bilder" }, - "menu": { + "documentBar": { "menu": "Meny", "new": "Ny", - "publish": "Publicera", + "shareLink": "", "extra": "Extra", "revision": "Revision", "slideMode": "Slide Mode", diff --git a/public/locales/tr.json b/public/locales/tr.json index 53c48e486..7ec7593fb 100644 --- a/public/locales/tr.json +++ b/public/locales/tr.json @@ -108,10 +108,10 @@ "image": "Resim", "uploadImage": "Resim Yükle" }, - "menu": { + "documentBar": { "menu": "Menü", "new": "Yeni", - "publish": "Yayınla", + "shareLink": "", "extra": "Ekstra", "revision": "Sürüm", "slideMode": "Slayt Modu", @@ -166,4 +166,4 @@ "error": {} } } -} \ No newline at end of file +} diff --git a/public/locales/uk.json b/public/locales/uk.json index 0617364ff..0f21fda4e 100644 --- a/public/locales/uk.json +++ b/public/locales/uk.json @@ -108,10 +108,10 @@ "image": "Зображення", "uploadImage": "Завантажити зображення" }, - "menu": { + "documentBar": { "menu": "Меню", "new": "Нова", - "publish": "Опублікувати", + "shareLink": "", "extra": "Дотатково", "revision": "Ревізія", "slideMode": "Режим слайдера", @@ -166,4 +166,4 @@ "error": {} } } -} \ No newline at end of file +} diff --git a/public/locales/vi.json b/public/locales/vi.json index 91dba4ea0..f89a34e48 100644 --- a/public/locales/vi.json +++ b/public/locales/vi.json @@ -123,10 +123,10 @@ "image": "Ảnh", "uploadImage": "Tải ảnh lên" }, - "menu": { + "documentBar": { "menu": "Menu", "new": "Mới", - "publish": "Xuất bản", + "shareLink": "", "extra": "Extra", "revision": "Sửa đổi", "slideMode": "Chế độ slide", diff --git a/public/locales/zh-CN.json b/public/locales/zh-CN.json index 142f24b25..f8bcdf077 100644 --- a/public/locales/zh-CN.json +++ b/public/locales/zh-CN.json @@ -124,10 +124,10 @@ "image": "图片", "uploadImage": "上传图片" }, - "menu": { + "documentBar": { "menu": "菜单", "new": "新建", - "publish": "发表", + "shareLink": "", "extra": "附加功能", "revision": "修订版本", "slideMode": "幻灯模式", diff --git a/public/locales/zh-TW.json b/public/locales/zh-TW.json index f28dbc33f..f0b83886c 100644 --- a/public/locales/zh-TW.json +++ b/public/locales/zh-TW.json @@ -124,10 +124,10 @@ "image": "圖片", "uploadImage": "上傳圖片" }, - "menu": { + "documentBar": { "menu": "選單", "new": "新增", - "publish": "發表", + "shareLink": "", "extra": "增益", "revision": "修訂版本", "slideMode": "簡報模式", diff --git a/src/components/landing/layout/version-info/version-input-field.tsx b/src/components/common/copyable-field/copyable-field.tsx similarity index 57% rename from src/components/landing/layout/version-info/version-input-field.tsx rename to src/components/common/copyable-field/copyable-field.tsx index c3b4c8264..8a3bffd40 100644 --- a/src/components/landing/layout/version-info/version-input-field.tsx +++ b/src/components/common/copyable-field/copyable-field.tsx @@ -1,40 +1,48 @@ -import React, { Fragment, useRef, useState } from 'react' +import React, { Fragment, useCallback, useRef, useState } from 'react' import { Button, FormControl, InputGroup, Overlay, Tooltip } from 'react-bootstrap' import { Trans, useTranslation } from 'react-i18next' -import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon' +import { ForkAwesomeIcon } from '../fork-awesome/fork-awesome-icon' -export interface VersionInputFieldProps { - version: string +export interface CopyableFieldProps { + content: string } -export const VersionInputField: React.FC = ({ version }) => { +export const CopyableField: React.FC = ({ content }) => { useTranslation() const inputField = useRef(null) const [showCopiedTooltip, setShowCopiedTooltip] = useState(false) - const copyToClipboard = (content: string) => { + const copyToClipboard = useCallback((content: string) => { navigator.clipboard.writeText(content).then(() => { setShowCopiedTooltip(true) setTimeout(() => { setShowCopiedTooltip(false) }, 2000) }).catch(() => { console.error("couldn't copy") }) - } + }, []) + + const selectContent = useCallback(() => { + if (!inputField.current) { + return + } + inputField.current.focus() + inputField.current.setSelectionRange(0, inputField.current.value.length) + }, [inputField]) return ( {(props) => ( - + )} - - + + - diff --git a/src/components/editor/task-bar/active-indicator.scss b/src/components/editor/document-bar/connection-indicator/active-indicator.scss similarity index 100% rename from src/components/editor/task-bar/active-indicator.scss rename to src/components/editor/document-bar/connection-indicator/active-indicator.scss diff --git a/src/components/editor/task-bar/active-indicator.tsx b/src/components/editor/document-bar/connection-indicator/active-indicator.tsx similarity index 87% rename from src/components/editor/task-bar/active-indicator.tsx rename to src/components/editor/document-bar/connection-indicator/active-indicator.tsx index 9ac33ec0b..e2a88bfd2 100644 --- a/src/components/editor/task-bar/active-indicator.tsx +++ b/src/components/editor/document-bar/connection-indicator/active-indicator.tsx @@ -2,8 +2,8 @@ import React from 'react' import './active-indicator.scss' export enum ActiveIndicatorStatus { - ACTIVE ='active', - INACTIVE ='inactive' + ACTIVE = 'active', + INACTIVE = 'inactive' } export interface ActiveIndicatorProps { diff --git a/src/components/editor/task-bar/connection-indicator.scss b/src/components/editor/document-bar/connection-indicator/connection-indicator.scss similarity index 100% rename from src/components/editor/task-bar/connection-indicator.scss rename to src/components/editor/document-bar/connection-indicator/connection-indicator.scss diff --git a/src/components/editor/task-bar/connection-indicator.tsx b/src/components/editor/document-bar/connection-indicator/connection-indicator.tsx similarity index 83% rename from src/components/editor/task-bar/connection-indicator.tsx rename to src/components/editor/document-bar/connection-indicator/connection-indicator.tsx index 3c5723954..99734d6a1 100644 --- a/src/components/editor/task-bar/connection-indicator.tsx +++ b/src/components/editor/document-bar/connection-indicator/connection-indicator.tsx @@ -1,6 +1,6 @@ import React from 'react' import { Dropdown } from 'react-bootstrap' -import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon' +import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon' import { ActiveIndicatorStatus } from './active-indicator' import './connection-indicator.scss' import { UserLine } from './user-line' @@ -8,9 +8,9 @@ import { UserLine } from './user-line' const ConnectionIndicator: React.FC = () => { const userOnline = 2 return ( - + - {userOnline} Online + {userOnline} Online diff --git a/src/components/editor/task-bar/user-line.scss b/src/components/editor/document-bar/connection-indicator/user-line.scss similarity index 100% rename from src/components/editor/task-bar/user-line.scss rename to src/components/editor/document-bar/connection-indicator/user-line.scss diff --git a/src/components/editor/task-bar/user-line.tsx b/src/components/editor/document-bar/connection-indicator/user-line.tsx similarity index 89% rename from src/components/editor/task-bar/user-line.tsx rename to src/components/editor/document-bar/connection-indicator/user-line.tsx index d47d9c91c..42d9c9050 100644 --- a/src/components/editor/task-bar/user-line.tsx +++ b/src/components/editor/document-bar/connection-indicator/user-line.tsx @@ -1,5 +1,5 @@ import React, { Fragment } from 'react' -import { UserAvatar } from '../../landing/layout/user-avatar/user-avatar' +import { UserAvatar } from '../../../landing/layout/user-avatar/user-avatar' import { ActiveIndicator, ActiveIndicatorStatus } from './active-indicator' import './user-line.scss' diff --git a/src/components/editor/document-bar/document-bar.tsx b/src/components/editor/document-bar/document-bar.tsx new file mode 100644 index 000000000..d6f3b988f --- /dev/null +++ b/src/components/editor/document-bar/document-bar.tsx @@ -0,0 +1,37 @@ +import React from 'react' +import { useTranslation } from 'react-i18next' +import { ConnectionIndicator } from './connection-indicator/connection-indicator' +import { DocumentInfoButton } from './document-info-button' +import { EditorMenu } from './editor-menu' +import { ExportMenu } from './export-menu' +import { ImportMenu } from './import-menu' +import { PermissionButton } from './permission-button' +import { PinToHistoryButton } from './pin-to-history-button' +import { ShareLinkButton } from './share-link-button' +import { RevisionButton } from './revision-button' + +export interface DocumentBarProps { + title: string +} + +export const DocumentBar: React.FC = ({ title }) => { + useTranslation() + + return ( +
+
+ + + + + +
+
+ + + + +
+
+ ) +} diff --git a/src/components/editor/document-bar/document-info-button.tsx b/src/components/editor/document-bar/document-info-button.tsx new file mode 100644 index 000000000..0952f4459 --- /dev/null +++ b/src/components/editor/document-bar/document-info-button.tsx @@ -0,0 +1,61 @@ +import moment from 'moment' +import React, { Fragment, useState } from 'react' +import { Button, ListGroup, Modal } from 'react-bootstrap' +import { Trans, useTranslation } from 'react-i18next' +import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon' +import { CommonModal } from '../../common/modals/common-modal' +import { DocumentInfoLine } from './document-info-line' +import { DocumentInfoLineWithTimeMode, DocumentInfoTimeLine } from './document-info-time-line' +import { UnitalicBoldText } from './document-info-time-line-helper/unitalic-bold-text' + +export const DocumentInfoButton: React.FC = () => { + const [showModal, setShowModal] = useState(false) + useTranslation() + + return ( + + + setShowModal(false)} + closeButton={true} + titleI18nKey={'editor.modal.documentInfo.title'}> + + + + + + + + + + + + + + + + + + + + + + + + + + + ) +} diff --git a/src/components/editor/document-bar/document-info-line.tsx b/src/components/editor/document-bar/document-info-line.tsx new file mode 100644 index 000000000..9a4b9e539 --- /dev/null +++ b/src/components/editor/document-bar/document-info-line.tsx @@ -0,0 +1,17 @@ +import React from 'react' +import { ForkAwesomeIcon, IconName } from '../../common/fork-awesome/fork-awesome-icon' + +export interface DocumentInfoLineProps { + icon: IconName +} + +export const DocumentInfoLine: React.FC = ({ icon, children }) => { + return ( + + + + {children} + + + ) +} diff --git a/src/components/editor/document-bar/document-info-time-line-helper/time-from-now.tsx b/src/components/editor/document-bar/document-info-time-line-helper/time-from-now.tsx new file mode 100644 index 000000000..d2814c6e0 --- /dev/null +++ b/src/components/editor/document-bar/document-info-time-line-helper/time-from-now.tsx @@ -0,0 +1,12 @@ +import { Moment } from 'moment' +import React from 'react' + +export interface ItalicTime { + time: Moment +} + +export const TimeFromNow: React.FC = ({ time }) => { + return ( + + ) +} diff --git a/src/components/editor/document-bar/document-info-time-line-helper/unitalic-bold-text.scss b/src/components/editor/document-bar/document-info-time-line-helper/unitalic-bold-text.scss new file mode 100644 index 000000000..e4b91dcfe --- /dev/null +++ b/src/components/editor/document-bar/document-info-time-line-helper/unitalic-bold-text.scss @@ -0,0 +1,3 @@ +.font-style-normal { + font-style: normal; +} diff --git a/src/components/editor/document-bar/document-info-time-line-helper/unitalic-bold-text.tsx b/src/components/editor/document-bar/document-info-time-line-helper/unitalic-bold-text.tsx new file mode 100644 index 000000000..ec37be6ea --- /dev/null +++ b/src/components/editor/document-bar/document-info-time-line-helper/unitalic-bold-text.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import './unitalic-bold-text.scss' + +export interface BoldTextProps { + text: string ; +} + +export const UnitalicBoldText: React.FC = ({ text }) => { + return {text} +} diff --git a/src/components/editor/document-bar/document-info-time-line.scss b/src/components/editor/document-bar/document-info-time-line.scss new file mode 100644 index 000000000..62b0930f0 --- /dev/null +++ b/src/components/editor/document-bar/document-info-time-line.scss @@ -0,0 +1,4 @@ +.document-info-avatar img { + height: 30px; + width: 30px; +} diff --git a/src/components/editor/document-bar/document-info-time-line.tsx b/src/components/editor/document-bar/document-info-time-line.tsx new file mode 100644 index 000000000..119549e9e --- /dev/null +++ b/src/components/editor/document-bar/document-info-time-line.tsx @@ -0,0 +1,36 @@ +import { Moment } from 'moment' +import React from 'react' +import { Trans, useTranslation } from 'react-i18next' +import { IconName } from '../../common/fork-awesome/fork-awesome-icon' +import { DocumentInfoLine } from './document-info-line' +import './document-info-time-line.scss' +import { TimeFromNow } from './document-info-time-line-helper/time-from-now' +import { UserAvatar } from '../../landing/layout/user-avatar/user-avatar' + +export interface DocumentInfoLineWithTimeProps { + time: Moment, + mode: DocumentInfoLineWithTimeMode + userName: string + profileImageSrc: string +} + +export enum DocumentInfoLineWithTimeMode { + CREATED, + EDITED +} + +export const DocumentInfoTimeLine: React.FC = ({ time, mode, userName, profileImageSrc }) => { + useTranslation() + + const i18nKey = mode === DocumentInfoLineWithTimeMode.CREATED ? 'editor.modal.documentInfo.created' : 'editor.modal.documentInfo.edited' + const icon: IconName = mode === DocumentInfoLineWithTimeMode.CREATED ? 'plus' : 'pencil' + + return ( + + + + + + + ) +} diff --git a/src/components/editor/document-bar/editor-menu.tsx b/src/components/editor/document-bar/editor-menu.tsx new file mode 100644 index 000000000..132671798 --- /dev/null +++ b/src/components/editor/document-bar/editor-menu.tsx @@ -0,0 +1,34 @@ +import React from 'react' +import { Dropdown } from 'react-bootstrap' +import { Trans, useTranslation } from 'react-i18next' +import { DropdownItemWithDeletionModal } from '../../landing/pages/history/common/entry-menu/dropdown-item-with-deletion-modal' + +export interface EditorMenuProps { + noteTitle: string +} + +export const EditorMenu: React.FC = ({ noteTitle }) => { + useTranslation() + + return ( + + + + + + + console.log('deleted')}/> + + + + ) +} diff --git a/src/components/editor/document-bar/export-menu.tsx b/src/components/editor/document-bar/export-menu.tsx new file mode 100644 index 000000000..a80715c82 --- /dev/null +++ b/src/components/editor/document-bar/export-menu.tsx @@ -0,0 +1,59 @@ +import React from 'react' +import { Dropdown } from 'react-bootstrap' +import { Trans, useTranslation } from 'react-i18next' +import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon' +import { TranslatedExternalLink } from '../../common/links/translated-external-link' + +const ExportMenu: React.FC = () => { + useTranslation() + return ( + + + + + + + + + + + + Dropbox + + + + Gist + + + + + + + + + + Markdown + + + + HTML + + + + + + + + + + + +   + + + + + ) +} + +export { ExportMenu } diff --git a/src/components/editor/document-bar/import-menu.tsx b/src/components/editor/document-bar/import-menu.tsx new file mode 100644 index 000000000..bb5534d82 --- /dev/null +++ b/src/components/editor/document-bar/import-menu.tsx @@ -0,0 +1,29 @@ +import React from 'react' +import { Dropdown } from 'react-bootstrap' +import { Trans } from 'react-i18next' +import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon' + +export const ImportMenu: React.FC = () => { + return ( + + + + + + + + + Dropbox + + + + Gist + + + + + + + + ) +} diff --git a/src/components/editor/document-bar/permission-button.tsx b/src/components/editor/document-bar/permission-button.tsx new file mode 100644 index 000000000..355cad538 --- /dev/null +++ b/src/components/editor/document-bar/permission-button.tsx @@ -0,0 +1,27 @@ +import React, { Fragment, useState } from 'react' +import { Trans } from 'react-i18next' +import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon' +import { Button, Modal } from 'react-bootstrap' +import { CommonModal } from '../../common/modals/common-modal' + +export const PermissionButton: React.FC = () => { + const [showReadOnly, setShowReadOnly] = useState(false) + + return ( + + + setShowReadOnly(false)} + closeButton={true} + titleI18nKey={'editor.modal.permissions.title'}> + + {'Placeholder'}/ + + + + ) +} diff --git a/src/components/editor/document-bar/pin-to-history-button.tsx b/src/components/editor/document-bar/pin-to-history-button.tsx new file mode 100644 index 000000000..36d4ca403 --- /dev/null +++ b/src/components/editor/document-bar/pin-to-history-button.tsx @@ -0,0 +1,18 @@ +import React from 'react' +import { Button } from 'react-bootstrap' +import { Trans, useTranslation } from 'react-i18next' +import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon' + +export const PinToHistoryButton: React.FC = () => { + useTranslation() + + const isPinned = true + const i18nKey = isPinned ? 'editor.documentBar.pinNoteToHistory' : 'editor.documentBar.pinnedToHistory' + + return ( + + ) +} diff --git a/src/components/editor/document-bar/revision-button.tsx b/src/components/editor/document-bar/revision-button.tsx new file mode 100644 index 000000000..6899c6a4f --- /dev/null +++ b/src/components/editor/document-bar/revision-button.tsx @@ -0,0 +1,13 @@ +import React from 'react' +import { Button } from 'react-bootstrap' +import { Trans } from 'react-i18next' +import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon' + +export const RevisionButton: React.FC = () => { + return ( + + ) +} diff --git a/src/components/editor/document-bar/share-link-button.tsx b/src/components/editor/document-bar/share-link-button.tsx new file mode 100644 index 000000000..7c0ba3f41 --- /dev/null +++ b/src/components/editor/document-bar/share-link-button.tsx @@ -0,0 +1,29 @@ +import React, { Fragment, useState } from 'react' +import { Button, Modal } from 'react-bootstrap' +import { Trans } from 'react-i18next' +import { CopyableField } from '../../common/copyable-field/copyable-field' +import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon' +import { CommonModal } from '../../common/modals/common-modal' + +export const ShareLinkButton: React.FC = () => { + const [showReadOnly, setShowReadOnly] = useState(false) + + return ( + + + setShowReadOnly(false)} + closeButton={true} + titleI18nKey={'editor.modal.shareLink.title'}> + + + + + + + ) +} diff --git a/src/components/editor/editor-window/editor-window.scss b/src/components/editor/editor-window/editor-window.scss index 9a80ff180..43d0583e3 100644 --- a/src/components/editor/editor-window/editor-window.scss +++ b/src/components/editor/editor-window/editor-window.scss @@ -1,5 +1,7 @@ @import '../../../../node_modules/codemirror/lib/codemirror.css'; @import '../../../../node_modules/codemirror/addon/display/fullscreen.css'; +@import '../../../../node_modules/codemirror/addon/dialog/dialog.css'; +@import '../../../../node_modules/codemirror/theme/neat.css'; @import './one-dark.css'; @import 'hints'; diff --git a/src/components/editor/editor-window/editor-window.tsx b/src/components/editor/editor-window/editor-window.tsx index 4abb874b2..133956b5d 100644 --- a/src/components/editor/editor-window/editor-window.tsx +++ b/src/components/editor/editor-window/editor-window.tsx @@ -1,5 +1,6 @@ -import { Editor, EditorChange } from 'codemirror' +import { Editor, EditorChange, EditorConfiguration } from 'codemirror' import 'codemirror/addon/comment/comment' +import 'codemirror/addon/dialog/dialog' import 'codemirror/addon/display/autorefresh' import 'codemirror/addon/display/fullscreen' import 'codemirror/addon/display/placeholder' @@ -11,16 +12,21 @@ import 'codemirror/addon/edit/matchtags' import 'codemirror/addon/fold/foldcode' import 'codemirror/addon/fold/foldgutter' import 'codemirror/addon/hint/show-hint' +import 'codemirror/addon/search/search' +import 'codemirror/addon/search/jump-to-line' import 'codemirror/addon/search/match-highlighter' import 'codemirror/addon/selection/active-line' -import 'codemirror/keymap/sublime.js' -import 'codemirror/mode/gfm/gfm.js' -import React, { useCallback, useState } from 'react' +import 'codemirror/keymap/sublime' +import 'codemirror/keymap/emacs' +import 'codemirror/keymap/vim' +import 'codemirror/mode/gfm/gfm' +import React, { useCallback, useMemo, useState } from 'react' import { Controlled as ControlledCodeMirror } from 'react-codemirror2' import { useTranslation } from 'react-i18next' import './editor-window.scss' import { emojiHints, emojiWordRegex, findWordAtCursor } from './hints/emoji' import { defaultKeyMap } from './key-map' +import { createStatusInfo, defaultState, StatusBar, StatusBarInfo } from './status-bar/status-bar' import { ToolBar } from './tool-bar/tool-bar' export interface EditorWindowProps { @@ -45,55 +51,71 @@ const onChange = (editor: Editor) => { export const EditorWindow: React.FC = ({ onContentChange, content }) => { const { t } = useTranslation() const [editor, setEditor] = useState() + const [statusBarInfo, setStatusBarInfo] = useState(defaultState) + const [editorPreferences, setEditorPreferences] = useState({ + theme: 'one-dark', + keyMap: 'sublime', + indentUnit: 4, + indentWithTabs: false + }) const onBeforeChange = useCallback((editor: Editor, data: EditorChange, value: string) => { onContentChange(value) }, [onContentChange]) + const onEditorDidMount = useCallback(mountedEditor => { + setStatusBarInfo(createStatusInfo(mountedEditor)) + setEditor(mountedEditor) + }, []) + const onCursorActivity = useCallback((editorWithActivity) => { + setStatusBarInfo(createStatusInfo(editorWithActivity)) + }, []) + const codeMirrorOptions: EditorConfiguration = useMemo(() => ({ + ...editorPreferences, + mode: 'gfm', + viewportMargin: 20, + styleActiveLine: true, + lineNumbers: true, + lineWrapping: true, + showCursorWhenSelecting: true, + highlightSelectionMatches: true, + inputStyle: 'textarea', + matchBrackets: true, + autoCloseBrackets: true, + matchTags: { + bothTags: true + }, + autoCloseTags: true, + foldGutter: true, + gutters: [ + 'CodeMirror-linenumbers', + 'authorship-gutters', + 'CodeMirror-foldgutter' + ], + extraKeys: defaultKeyMap, + flattenSpans: true, + addModeClass: true, + autoRefresh: true, + // otherCursors: true, + placeholder: t('editor.placeholder') + }), [t, editorPreferences]) return (
setEditorPreferences(config)} + editorPreferences={editorPreferences} /> setEditor(mountedEditor)} - onBeforeChange={onBeforeChange} + options={codeMirrorOptions} onChange={onChange} - />
+ onCursorActivity={onCursorActivity} + editorDidMount={onEditorDidMount} + onBeforeChange={onBeforeChange} + /> + + ) } diff --git a/src/components/editor/editor-window/status-bar/status-bar.scss b/src/components/editor/editor-window/status-bar/status-bar.scss new file mode 100644 index 000000000..ef9f4c385 --- /dev/null +++ b/src/components/editor/editor-window/status-bar/status-bar.scss @@ -0,0 +1,11 @@ +.status-bar { + background: #1c1c1e; + border-top: 1px solid #343434; + color: #ccc; + position: relative; + display: block; + box-sizing: border-box; + font-size: 13px; + line-height: 25px; + height: 26px; +} diff --git a/src/components/editor/editor-window/status-bar/status-bar.tsx b/src/components/editor/editor-window/status-bar/status-bar.tsx new file mode 100644 index 000000000..a116cd93b --- /dev/null +++ b/src/components/editor/editor-window/status-bar/status-bar.tsx @@ -0,0 +1,53 @@ +import { Editor, Position } from 'codemirror' +import React from 'react' +import { useTranslation } from 'react-i18next' +import { ShowIf } from '../../../common/show-if/show-if' +import './status-bar.scss' + +export interface StatusBarInfo { + position: Position + selectedColumns: number + selectedLines: number + linesInDocument: number + charactersInDocument: number +} + +export const defaultState: StatusBarInfo = { + position: { line: 0, ch: 0 }, + selectedColumns: 0, + selectedLines: 0, + linesInDocument: 0, + charactersInDocument: 0 +} + +export const createStatusInfo = (editor: Editor): StatusBarInfo => ({ + position: editor.getCursor(), + charactersInDocument: editor.getValue().length, + linesInDocument: editor.lineCount(), + selectedColumns: editor.getSelection().length, + selectedLines: editor.getSelection().split('\n').length +}) + +export const StatusBar: React.FC = ({ position, selectedColumns, selectedLines, charactersInDocument, linesInDocument }) => { + const { t } = useTranslation() + + return ( +
+
+ {t('editor.statusBar.cursor', { line: position.line + 1, columns: position.ch + 1 })} + + +  – {t('editor.statusBar.selection.column', { count: selectedColumns })} + + 1}> +  – {t('editor.statusBar.selection.line', { count: selectedLines })} + + +
+
+ {t('editor.statusBar.lines', { lines: linesInDocument })} +  – {t('editor.statusBar.length', { length: charactersInDocument })} +
+
+ ) +} diff --git a/src/components/editor/editor-window/tool-bar/editor-preferences/editor-preference-select.tsx b/src/components/editor/editor-window/tool-bar/editor-preferences/editor-preference-select.tsx new file mode 100644 index 000000000..9803bd0d1 --- /dev/null +++ b/src/components/editor/editor-window/tool-bar/editor-preferences/editor-preference-select.tsx @@ -0,0 +1,53 @@ +import { EditorConfiguration } from 'codemirror' +import React, { ChangeEvent, useCallback, useState } from 'react' +import { Form } from 'react-bootstrap' +import { Trans, useTranslation } from 'react-i18next' + +export enum EditorPreferenceProperty { + KEYMAP = 'keyMap', + THEME = 'theme', + INDENT_WITH_TABS = 'indentWithTabs', + INDENT_UNIT = 'indentUnit' +} + +export interface EditorPreferenceSelectProps { + onChange: (config: EditorConfiguration) => void + preferences: EditorConfiguration + property: EditorPreferenceProperty +} + +export const EditorPreferenceSelect: React.FC = ({ property, onChange, preferences, children }) => { + useTranslation() + const [selected, setSelected] = useState(preferences[property]) + + const selectItem = useCallback((event: ChangeEvent) => { + let selectedItem: string | boolean | number = event.target.value + if (property === EditorPreferenceProperty.INDENT_UNIT) { + selectedItem = parseInt(selectedItem) + } + setSelected(selectedItem) + if (property === EditorPreferenceProperty.INDENT_WITH_TABS) { + selectedItem = selectedItem === 'true' + } + onChange({ + ...preferences, + [property]: selectedItem + }) + }, [preferences, property, setSelected, onChange]) + + return ( + + + + + + { children } + + + ) +} diff --git a/src/components/editor/editor-window/tool-bar/editor-preferences/editor-preferences.tsx b/src/components/editor/editor-window/tool-bar/editor-preferences/editor-preferences.tsx new file mode 100644 index 000000000..6bb7365d1 --- /dev/null +++ b/src/components/editor/editor-window/tool-bar/editor-preferences/editor-preferences.tsx @@ -0,0 +1,73 @@ +import { EditorConfiguration } from 'codemirror' +import React, { Fragment, useCallback, useState } from 'react' +import { Button, Form, ListGroup } from 'react-bootstrap' +import { Trans, useTranslation } from 'react-i18next' +import { ForkAwesomeIcon } from '../../../../common/fork-awesome/fork-awesome-icon' +import { CommonModal } from '../../../../common/modals/common-modal' +import { EditorPreferenceProperty, EditorPreferenceSelect } from './editor-preference-select' + +export interface EditorSettingsButtonProps { + preferences: EditorConfiguration + onPreferencesChange: (config: EditorConfiguration) => void +} + +export const EditorPreferences: React.FC = ({ onPreferencesChange, preferences }) => { + const { t } = useTranslation() + const [showModal, setShowModal] = useState(false) + + const sendPreferences = useCallback((newPreferences: EditorConfiguration) => { + onPreferencesChange(newPreferences) + }, [onPreferencesChange]) + + return ( + + + setShowModal(false)} + titleI18nKey={'editor.modal.preferences.title'} + closeButton={true} + icon={'wrench'}> +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + alert('This feature is not yet implemented.')}> + + + + + + +
+
+
+ ) +} diff --git a/src/components/editor/editor-window/tool-bar/emoji-picker-button.tsx b/src/components/editor/editor-window/tool-bar/emoji-picker-button.tsx new file mode 100644 index 000000000..7ac317b17 --- /dev/null +++ b/src/components/editor/editor-window/tool-bar/emoji-picker-button.tsx @@ -0,0 +1,28 @@ +import CodeMirror from 'codemirror' +import React, { Fragment, useState } from 'react' +import { Button } from 'react-bootstrap' +import { useTranslation } from 'react-i18next' +import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon' +import { EmojiPicker } from './emoji-picker/emoji-picker' +import { addEmoji } from './utils' + +export interface EmojiPickerButtonProps { + editor: CodeMirror.Editor +} + +export const EmojiPickerButton: React.FC = ({ editor }) => { + const { t } = useTranslation() + const [showEmojiPicker, setShowEmojiPicker] = useState(false) + + return ( + + { + setShowEmojiPicker(false) + addEmoji(emoji, editor) + }} onDismiss={() => setShowEmojiPicker(false)}/> + + + ) +} diff --git a/src/components/editor/editor-window/tool-bar/tool-bar.scss b/src/components/editor/editor-window/tool-bar/tool-bar.scss index 954de9777..6cd7dfaf2 100644 --- a/src/components/editor/editor-window/tool-bar/tool-bar.scss +++ b/src/components/editor/editor-window/tool-bar/tool-bar.scss @@ -1,3 +1,9 @@ .btn-toolbar { border: 1px solid #ededed; } + +.divider { + background-color: #e2e6ea; + width: 2px; + padding: 0.25rem 0; +} diff --git a/src/components/editor/editor-window/tool-bar/tool-bar.tsx b/src/components/editor/editor-window/tool-bar/tool-bar.tsx index dd59613d4..33fbfb73e 100644 --- a/src/components/editor/editor-window/tool-bar/tool-bar.tsx +++ b/src/components/editor/editor-window/tool-bar/tool-bar.tsx @@ -1,14 +1,14 @@ -import { Editor } from 'codemirror' -import React, { Fragment, useState } from 'react' -import { Button, ButtonToolbar } from 'react-bootstrap' +import { Editor, EditorConfiguration } from 'codemirror' +import React, { Fragment } from 'react' +import { Button, ButtonGroup, ButtonToolbar } from 'react-bootstrap' import { useTranslation } from 'react-i18next' import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon' -import { EmojiPicker } from './emoji-picker/emoji-picker' +import { EditorPreferences } from './editor-preferences/editor-preferences' +import { EmojiPickerButton } from './emoji-picker-button' import './tool-bar.scss' import { addCodeFences, addComment, - addEmoji, addHeaderLevel, addImage, addLine, @@ -28,11 +28,12 @@ import { export interface ToolBarProps { editor: Editor | undefined + onPreferencesChange: (config: EditorConfiguration) => void + editorPreferences: EditorConfiguration } -export const ToolBar: React.FC = ({ editor }) => { +export const ToolBar: React.FC = ({ editor, onPreferencesChange, editorPreferences }) => { const { t } = useTranslation() - const [showEmojiPicker, setShowEmojiPicker] = useState(false) const notImplemented = () => { alert('This feature is not yet implemented') @@ -44,68 +45,77 @@ export const ToolBar: React.FC = ({ editor }) => { return ( - - - - - - - - - - - - - - - - - - - - { - setShowEmojiPicker(false) - addEmoji(emoji, editor) - }} onDismiss={() => setShowEmojiPicker(false)}/> - + + + + + + + + + +   + + + + + + + + +   + + + + + +   + + + + + + +   + + + ) diff --git a/src/components/editor/editor.tsx b/src/components/editor/editor.tsx index 7c7082087..7eb32cc3f 100644 --- a/src/components/editor/editor.tsx +++ b/src/components/editor/editor.tsx @@ -7,6 +7,7 @@ import { setEditorModeConfig } from '../../redux/editor/methods' import { DocumentTitle } from '../common/document-title/document-title' import { Splitter } from '../common/splitter/splitter' import { InfoBanner } from '../landing/layout/info-banner' +import { DocumentBar } from './document-bar/document-bar' import { EditorWindow } from './editor-window/editor-window' import { editorTestContent } from './editorTestContent' import { MarkdownRenderWindow } from './renderer-window/markdown-render-window' @@ -14,6 +15,10 @@ import { EditorMode } from './task-bar/editor-view-mode' import { TaskBar } from './task-bar/task-bar' import { YAMLMetaData } from './yaml-metadata/yaml-metadata' +export interface EditorPathParams { + id: string +} + export const Editor: React.FC = () => { const { t } = useTranslation() const untitledNote = t('editor.untitledNote') @@ -61,11 +66,22 @@ export const Editor: React.FC = () => {
+ setMarkdownContent(content)} content={markdownContent}/>} + left={ + setMarkdownContent(content)} + content={markdownContent}/> + } showRight={editorMode === EditorMode.PREVIEW || (editorMode === EditorMode.BOTH)} - right={} + right={ + + } containerClassName={'overflow-hidden'}/>
diff --git a/src/components/editor/markdown-renderer/markdown-renderer.scss b/src/components/editor/markdown-renderer/markdown-renderer.scss index 19f96eb9b..cbc7ebc2f 100644 --- a/src/components/editor/markdown-renderer/markdown-renderer.scss +++ b/src/components/editor/markdown-renderer/markdown-renderer.scss @@ -50,4 +50,8 @@ } } + pre { + overflow: visible; + } + } diff --git a/src/components/editor/markdown-toc/markdown-toc.scss b/src/components/editor/markdown-toc/markdown-toc.scss index ddd4b95ed..561789529 100644 --- a/src/components/editor/markdown-toc/markdown-toc.scss +++ b/src/components/editor/markdown-toc/markdown-toc.scss @@ -52,11 +52,11 @@ .markdown-toc-sidebar-button { position: fixed; right: 40px; - bottom: 20px; + bottom: 30px; &>.dropup { position: sticky; bottom: 20px; - right: 0px; + right: 0; } } diff --git a/src/components/editor/task-bar/editor-menu.tsx b/src/components/editor/task-bar/editor-menu.tsx deleted file mode 100644 index f342ca27b..000000000 --- a/src/components/editor/task-bar/editor-menu.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import React from 'react' -import { Dropdown } from 'react-bootstrap' -import { Trans, useTranslation } from 'react-i18next' -import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon' - -const EditorMenu: React.FC = () => { - useTranslation() - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - Dropbox - - - Gist - - - - - - - - - Dropbox - - - Gist - - - - - - - - - - - - Markdown - - - HTML - - - - - - - - ) -} - -export { EditorMenu } diff --git a/src/components/editor/task-bar/help-button.tsx b/src/components/editor/task-bar/help-button.tsx index 8342a6631..70046038c 100644 --- a/src/components/editor/task-bar/help-button.tsx +++ b/src/components/editor/task-bar/help-button.tsx @@ -12,14 +12,14 @@ export const HelpButton: React.FC = () => { const handleClose = () => setShow(false) return ( - - + @@ -67,6 +67,7 @@ export const HelpButton: React.FC = () => { +
diff --git a/src/components/editor/task-bar/task-bar.tsx b/src/components/editor/task-bar/task-bar.tsx index 5a57c0444..d229fb575 100644 --- a/src/components/editor/task-bar/task-bar.tsx +++ b/src/components/editor/task-bar/task-bar.tsx @@ -1,17 +1,25 @@ import React from 'react' import { Button, Nav, Navbar } from 'react-bootstrap' import { Trans, useTranslation } from 'react-i18next' +import { useSelector } from 'react-redux' +import { useParams } from 'react-router' import { Link } from 'react-router-dom' +import { ApplicationState } from '../../../redux' import { Branding } from '../../common/branding/branding' import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon' -import { ConnectionIndicator } from './connection-indicator' +import { ShowIf } from '../../common/show-if/show-if' +import { SignInButton } from '../../landing/layout/navigation/sign-in-button' +import { UserDropdown } from '../../landing/layout/navigation/user-dropdown/user-dropdown' +import { EditorPathParams } from '../editor' import { DarkModeButton } from './dark-mode-button' -import { EditorMenu } from './editor-menu' import { EditorViewMode } from './editor-view-mode' import { HelpButton } from './help-button' -const TaskBar: React.FC = () => { - useTranslation() +export const TaskBar: React.FC = () => { + const { t } = useTranslation() + const { id } = useParams() + const user = useSelector((state: ApplicationState) => state.user) + return ( ) } - -export { TaskBar } diff --git a/src/components/landing/layout/user-avatar/user-avatar.tsx b/src/components/landing/layout/user-avatar/user-avatar.tsx index aae0b3a4d..1543906ed 100644 --- a/src/components/landing/layout/user-avatar/user-avatar.tsx +++ b/src/components/landing/layout/user-avatar/user-avatar.tsx @@ -1,22 +1,28 @@ import React from 'react' +import { useTranslation } from 'react-i18next' +import { ShowIf } from '../../../common/show-if/show-if' import './user-avatar.scss' export interface UserAvatarProps { name: string; photo: string; additionalClasses?: string; + showName?: boolean } -const UserAvatar: React.FC = ({ name, photo, additionalClasses = '' }) => { - // ToDo: add Translation Key for Avatar of ${name} +const UserAvatar: React.FC = ({ name, photo, additionalClasses = '', showName = true }) => { + const { t } = useTranslation() + return ( {`Avatar - {name} + + {name} + ) } diff --git a/src/components/landing/layout/version-info/version-info.tsx b/src/components/landing/layout/version-info/version-info.tsx index 990b5939b..2e665e4b0 100644 --- a/src/components/landing/layout/version-info/version-info.tsx +++ b/src/components/landing/layout/version-info/version-info.tsx @@ -7,7 +7,7 @@ import { ApplicationState } from '../../../../redux' import frontendVersion from '../../../../version.json' import { TranslatedExternalLink } from '../../../common/links/translated-external-link' import { ShowIf } from '../../../common/show-if/show-if' -import { VersionInputField } from './version-input-field' +import { CopyableField } from '../../../common/copyable-field/copyable-field' export const VersionInfo: React.FC = () => { const [show, setShow] = useState(false) @@ -22,7 +22,7 @@ export const VersionInfo: React.FC = () => { const column = (title: string, version: string, sourceCodeLink: string, issueTrackerLink: string) => (
{title}
- + diff --git a/src/components/landing/pages/history/common/entry-menu/dropdown-item-with-deletion-modal.tsx b/src/components/landing/pages/history/common/entry-menu/dropdown-item-with-deletion-modal.tsx index 8514fe87e..783d697e4 100644 --- a/src/components/landing/pages/history/common/entry-menu/dropdown-item-with-deletion-modal.tsx +++ b/src/components/landing/pages/history/common/entry-menu/dropdown-item-with-deletion-modal.tsx @@ -13,19 +13,20 @@ export interface DropdownItemWithDeletionModalProps { modalQuestionI18nKey: string modalWarningI18nKey: string noteTitle: string + className?: string } export const DropdownItemWithDeletionModal: React.FC = ({ onConfirm, noteTitle, modalTitleI18nKey, modalButtonI18nKey, itemI18nKey, modalIcon, - modalQuestionI18nKey, modalWarningI18nKey + modalQuestionI18nKey, modalWarningI18nKey, className }) => { useTranslation() const [showDialog, setShowDialog] = useState(false) return ( - setShowDialog(true)}> + setShowDialog(true)} className={className}> diff --git a/yarn.lock b/yarn.lock index 6b3cfeee3..8fc4846ac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4186,7 +4186,7 @@ cyclist@^1.0.1: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= -cypress@*, cypress@4.12.1: +cypress@4.12.1: version "4.12.1" resolved "https://registry.yarnpkg.com/cypress/-/cypress-4.12.1.tgz#0ead1b9f4c0917d69d8b57f996b6e01fe693b6ec" integrity sha512-9SGIPEmqU8vuRA6xst2CMTYd9sCFCxKSzrHt0wr+w2iAQMCIIsXsQ5Gplns1sT6LDbZcmLv6uehabAOl3fhc9Q==