diff --git a/components/header.js b/components/header.js index 16e0add..b860e3c 100644 --- a/components/header.js +++ b/components/header.js @@ -19,10 +19,6 @@ export class Header extends HTMLElement { } textEn = { - download: 'Download', - rename: 'Move/Rename', - duplicate: 'Duplicate', - delete: 'Delete', confirmDelete: f => ( `Are you sure you want to delete ${f}?` ), @@ -35,10 +31,6 @@ export class Header extends HTMLElement { } textEs = { - download: 'Descargar', - rename: 'Mover/Renombrar', - duplicate: 'Duplicar', - delete: 'Borrar', confirmDelete: f => ( `¿Desea borrar ${f}?` ), @@ -80,10 +72,7 @@ export class Header extends HTMLElement { } ) this.pageButton.classList.add('right-end') - this.addPageMenu() this.addMenu() - this.dialogWrap = document.createElement('div') - this.shadowRoot.appendChild(this.dialogWrap) } connectedCallback() { @@ -150,11 +139,9 @@ export class Header extends HTMLElement { width: 20px; height: 20px; } - m-dialog::part(footer) { - padding-top: 15px; - } ` this.shadowRoot.append(style) + this.addPageMenu() } encodePath(path) { @@ -199,126 +186,10 @@ export class Header extends HTMLElement { this.pageMenu = document.createElement( 'm-menu-dropdown' ) - this.pageMenu.add(this.text.download, () => { - const text = localStorage.getItem(this.path) - const sp = this.path.split('/') - const filename = sp[sp.length - 1] - const el = document.createElement('a') - el.setAttribute( - 'href', - 'data:text/plain;charset=utf-8,' + - encodeURIComponent(text) - ) - el.setAttribute('download', filename) - el.style.display = 'none' - this.shadowRoot.appendChild(el) - el.click() - this.shadowRoot.removeChild(el) - }) - this.pageMenu.add(this.text.rename, () => { - const dialog = document.createElement( - 'm-dialog' - ) - this.dialogWrap.replaceChildren(dialog) - const input = document.createElement('input') - input.value = this.path - input.style.minWidth = '300px' - dialog.bodyEl.appendChild(input) - let errorEl - const bGroup = document.createElement( - 'm-forms-button-group' - ) - bGroup.addPrimary(this.text.rename, () => { - const newPath = input.value - const v = localStorage.getItem(newPath) - if (v !== null || newPath === this.path) { - if (!errorEl) { - errorEl = document.createElement('p') - errorEl.style.color = 'red' - const errText = this.text.alreadyExists - errorEl.innerText = errText - dialog.bodyEl.appendChild(errorEl) - } - return - } - localStorage.setItem( - newPath, - localStorage.getItem(this.path) - ) - localStorage.removeItem(this.path) - dialog.close() - location.hash = newPath - }) - bGroup.addCancel(this.text.cancel, () => { - dialog.close() - }) - dialog.footerEl.appendChild(bGroup) - dialog.open() - }) - this.pageMenu.add(this.text.duplicate, () => { - const dialog = document.createElement( - 'm-dialog' - ) - this.dialogWrap.replaceChildren(dialog) - const input = document.createElement('input') - input.value = this.path - input.style.minWidth = '300px' - dialog.bodyEl.appendChild(input) - let errorEl - const bGroup = document.createElement( - 'm-forms-button-group' - ) - bGroup.addPrimary(this.text.duplicate, () => { - const newPath = input.value - const v = localStorage.getItem(newPath) - if (v !== null || newPath === this.path) { - if (!errorEl) { - errorEl = document.createElement('p') - errorEl.style.color = 'red' - const errText = this.text.alreadyExists - errorEl.innerText = errText - dialog.bodyEl.appendChild(errorEl) - } - return - } - localStorage.setItem( - newPath, - localStorage.getItem(this.path) - ) - dialog.close() - location.hash = newPath - }) - bGroup.addCancel(this.text.cancel, () => { - dialog.close() - }) - dialog.footerEl.appendChild(bGroup) - dialog.open() - }) - this.pageMenu.add(this.text.delete, () => { - const dialog = document.createElement( - 'm-dialog' - ) - this.dialogWrap.replaceChildren(dialog) - const p = document.createElement('p') - p.innerText = this.text.confirmDelete( - JSON.stringify(this.path) - ) - dialog.bodyEl.appendChild(p) - - const bGroup = document.createElement( - 'm-forms-button-group' - ) - bGroup.addPrimary(this.text.delete, () => { - localStorage.removeItem(this.path) - location.hash = '/' - dialog.close() - }) - bGroup.addCancel(this.text.cancel, () => { - dialog.close() - }) - dialog.footerEl.appendChild(bGroup) - dialog.open() - }) + const actions = this.pageActions.menuActions + for (const {text, click} of actions) { + this.pageMenu.add(text, click) + } this.shadowRoot.appendChild(this.pageMenu) } diff --git a/components/layout.js b/components/layout.js index 4468f06..fd755e7 100644 --- a/components/layout.js +++ b/components/layout.js @@ -24,8 +24,12 @@ export class Layout extends HTMLElement { m-page, m-file-group-page { flex-grow: 1; } + m-dialog::part(footer) { + padding-top: 15px; + } ` this.shadowRoot.appendChild(style) + this.header.pageActions = this.pageActions this.header.editing = this.editing this.header.addEventListener('click-edit', () => { this.editing = !this.editing @@ -34,6 +38,10 @@ export class Layout extends HTMLElement { this.editing = true }) this.shadowRoot.appendChild(this.header) + this.dialogWrap = document.createElement('div') + this.header.dialogWrap = this.dialogWrap + this.pageActions.dialogWrap = this.dialogWrap + this.shadowRoot.appendChild(this.dialogWrap) this.load() addEventListener('hashchange', () => { this.load() @@ -73,6 +81,7 @@ export class Layout extends HTMLElement { } this.shadowRoot.appendChild(this.page) this.header.path = path + this.pageActions.path = path } get path() { diff --git a/components/page-actions.js b/components/page-actions.js new file mode 100644 index 0000000..8041836 --- /dev/null +++ b/components/page-actions.js @@ -0,0 +1,185 @@ +export class PageActions { + textEn = { + download: 'Download', + rename: 'Move/Rename', + duplicate: 'Duplicate', + delete_: 'Delete', + confirmDelete: f => ( + `Are you sure you want to delete ${f}?` + ), + cancel: 'Cancel', + alreadyExists: 'There is already a page with that name.', + } + + textEs = { + download: 'Descargar', + rename: 'Mover/Renombrar', + duplicate: 'Duplicar', + delete_: 'Borrar', + confirmDelete: f => ( + `¿Desea borrar ${f}?` + ), + cancel: 'Cancelar', + alreadyExists: 'Ya existe una página con ese nombre.', + } + + constructor() { + this.language = navigator.language + this.menuActions = [ + { + text: this.text.download, + click: this.download.bind(this), + }, + { + text: this.text.rename, + click: this.rename.bind(this), + }, + { + text: this.text.duplicate, + click: this.duplicate.bind(this), + }, + { + text: this.text.delete_, + click: this.delete_.bind(this), + }, + ] + } + + download() { + const text = localStorage.getItem(this.path) + const sp = this.path.split('/') + const filename = sp[sp.length - 1] + const el = document.createElement('a') + el.setAttribute( + 'href', + 'data:text/plain;charset=utf-8,' + + encodeURIComponent(text) + ) + el.setAttribute('download', filename) + el.style.display = 'none' + this.shadowRoot.appendChild(el) + el.click() + this.shadowRoot.removeChild(el) + } + + rename() { + const dialog = document.createElement( + 'm-dialog' + ) + this.dialogWrap.replaceChildren(dialog) + const input = document.createElement('input') + input.value = this.path + input.style.minWidth = '300px' + dialog.bodyEl.appendChild(input) + let errorEl + const bGroup = document.createElement( + 'm-forms-button-group' + ) + bGroup.addPrimary(this.text.rename, () => { + const newPath = input.value + const v = localStorage.getItem(newPath) + if (v !== null || newPath === this.path) { + if (!errorEl) { + errorEl = document.createElement('p') + errorEl.style.color = 'red' + const errText = this.text.alreadyExists + errorEl.innerText = errText + dialog.bodyEl.appendChild(errorEl) + } + return + } + localStorage.setItem( + newPath, + localStorage.getItem(this.path) + ) + localStorage.removeItem(this.path) + dialog.close() + location.hash = newPath + }) + bGroup.addCancel(this.text.cancel, () => { + dialog.close() + }) + dialog.footerEl.appendChild(bGroup) + dialog.open() + } + + duplicate() { + const dialog = document.createElement( + 'm-dialog' + ) + this.dialogWrap.replaceChildren(dialog) + const input = document.createElement('input') + input.value = this.path + input.style.minWidth = '300px' + dialog.bodyEl.appendChild(input) + let errorEl + const bGroup = document.createElement( + 'm-forms-button-group' + ) + const btnText = this.text.duplicate + bGroup.addPrimary(btnText, () => { + const newPath = input.value + const v = localStorage.getItem(newPath) + if (v !== null || newPath === this.path) { + if (!errorEl) { + errorEl = document.createElement('p') + errorEl.style.color = 'red' + const errText = this.text.alreadyExists + errorEl.innerText = errText + dialog.bodyEl.appendChild(errorEl) + } + return + } + localStorage.setItem( + newPath, + localStorage.getItem(this.path) + ) + dialog.close() + location.hash = newPath + }) + bGroup.addCancel(this.text.cancel, () => { + dialog.close() + }) + dialog.footerEl.appendChild(bGroup) + dialog.open() + } + + delete_() { + const dialog = document.createElement( + 'm-dialog' + ) + this.dialogWrap.replaceChildren(dialog) + const p = document.createElement('p') + p.innerText = this.text.confirmDelete( + JSON.stringify(this.path) + ) + dialog.bodyEl.appendChild(p) + + const bGroup = document.createElement( + 'm-forms-button-group' + ) + bGroup.addPrimary(this.text.delete_, () => { + localStorage.removeItem(this.path) + location.hash = '/' + dialog.close() + }) + bGroup.addCancel(this.text.cancel, () => { + dialog.close() + }) + dialog.footerEl.appendChild(bGroup) + dialog.open() + } + + get language() { + return this._language + } + + set language(language) { + this._language = language + this.text = this.langEs ? this.textEs : this.textEn + } + + get langEs() { + return /^es\b/.test(this.language) + } +} \ No newline at end of file diff --git a/sw.js b/sw.js index b781880..0202dce 100644 --- a/sw.js +++ b/sw.js @@ -7,6 +7,7 @@ async function initCache() { '/components/layout.js', '/components/nav-menu.js', '/components/page.js', + '/components/page-actions.js', '/dialog/dialog.js', '/editor/app.js', '/editor/file-group.js', @@ -17,7 +18,7 @@ async function initCache() { '/loader/builder.js', '/loader/editor-build.js', '/menu/dropdown.js', - ]) //6 + ]) } self.addEventListener("install", event => {