diff --git a/assets/bootstrap.js b/assets/bootstrap.js new file mode 100644 index 000000000..c91af8043 --- /dev/null +++ b/assets/bootstrap.js @@ -0,0 +1,11 @@ +import { startStimulusApp } from '@symfony/stimulus-bridge'; + +// Registers Stimulus controllers from controllers.json and in the controllers/ directory +export default startStimulusApp(require.context( + '@symfony/stimulus-bridge/lazy-controller-loader!./controllers', + true, + /\.[jt]sx?$/, +)); + +// register any custom, 3rd party controllers here +// app.register('some_controller_name', SomeImportedController); diff --git a/assets/controllers.json b/assets/controllers.json new file mode 100644 index 000000000..a1c6e90cf --- /dev/null +++ b/assets/controllers.json @@ -0,0 +1,4 @@ +{ + "controllers": [], + "entrypoints": [] +} diff --git a/assets/controllers/add_tag_controller.js b/assets/controllers/add_tag_controller.js new file mode 100644 index 000000000..2afe9c2b6 --- /dev/null +++ b/assets/controllers/add_tag_controller.js @@ -0,0 +1,13 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + static targets = ['input']; + + toggle() { + this.element.classList.toggle('hidden'); + + if (!this.element.classList.contains('hidden')) { + this.inputTarget.focus(); + } + } +} diff --git a/assets/controllers/annotations_controller.js b/assets/controllers/annotations_controller.js new file mode 100644 index 000000000..1fd4308f6 --- /dev/null +++ b/assets/controllers/annotations_controller.js @@ -0,0 +1,57 @@ +import { Controller } from '@hotwired/stimulus'; +import annotator from 'annotator'; + +export default class extends Controller { + static values = { + entryId: Number, + createUrl: String, + updateUrl: String, + destroyUrl: String, + searchUrl: String, + }; + + connect() { + this.app = new annotator.App(); + + this.app.include(annotator.ui.main, { + element: this.element, + }); + + const authorization = { + permits() { return true; }, + }; + this.app.registry.registerUtility(authorization, 'authorizationPolicy'); + + this.app.include(annotator.storage.http, { + prefix: '', + urls: { + create: this.createUrlValue, + update: this.updateUrlValue, + destroy: this.destroyUrlValue, + search: this.searchUrlValue, + }, + entryId: this.entryIdValue, + onError(msg, xhr) { + if (!Object.prototype.hasOwnProperty.call(xhr, 'responseJSON')) { + annotator.notification.banner('An error occurred', 'error'); + return; + } + Object.values(xhr.responseJSON.children).forEach((v) => { + if (v.errors) { + Object.values(v.errors).forEach((errorText) => { + annotator.notification.banner(errorText, 'error'); + }); + } + }); + }, + }); + + this.app.start().then(() => { + this.app.annotations.load({ entry: this.entryIdValue }); + }); + } + + disconnect() { + this.app.destroy(); + } +} diff --git a/assets/controllers/batch_edit_controller.js b/assets/controllers/batch_edit_controller.js new file mode 100644 index 000000000..e15fc41c5 --- /dev/null +++ b/assets/controllers/batch_edit_controller.js @@ -0,0 +1,15 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + static targets = ['item', 'tagAction']; + + toggleSelection(e) { + this.itemTargets.forEach((item) => { + item.checked = e.currentTarget.checked; // eslint-disable-line no-param-reassign + }); + } + + tagSelection() { + this.element.requestSubmit(this.tagActionTarget); + } +} diff --git a/assets/controllers/clipboard_controller.js b/assets/controllers/clipboard_controller.js new file mode 100644 index 000000000..eba297138 --- /dev/null +++ b/assets/controllers/clipboard_controller.js @@ -0,0 +1,16 @@ +import { Controller } from '@hotwired/stimulus'; +import ClipboardJS from 'clipboard'; + +export default class extends Controller { + connect() { + this.clipboard = new ClipboardJS(this.element); + + this.clipboard.on('success', (e) => { + e.clearSelection(); + }); + } + + disconnect() { + this.clipboard.destroy(); + } +} diff --git a/assets/controllers/config_controller.js b/assets/controllers/config_controller.js new file mode 100644 index 000000000..804da826a --- /dev/null +++ b/assets/controllers/config_controller.js @@ -0,0 +1,16 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + static targets = ['previewArticle', 'previewContent', 'font', 'fontSize', 'lineHeight', 'maxWidth']; + + connect() { + this.updatePreview(); + } + + updatePreview() { + this.previewArticleTarget.style.maxWidth = `${this.maxWidthTarget.value}em`; + this.previewContentTarget.style.fontFamily = this.fontTarget.value; + this.previewContentTarget.style.fontSize = `${this.fontSizeTarget.value}em`; + this.previewContentTarget.style.lineHeight = `${this.lineHeightTarget.value}em`; + } +} diff --git a/assets/controllers/dark_theme_controller.js b/assets/controllers/dark_theme_controller.js new file mode 100644 index 000000000..e19b364ea --- /dev/null +++ b/assets/controllers/dark_theme_controller.js @@ -0,0 +1,39 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + connect() { + this.#choose(); + + this.mql = window.matchMedia('(prefers-color-scheme: dark)'); + this.mql.addEventListener('change', this.#choose.bind(this)); + } + + useLight() { + this.element.classList.remove('dark-theme'); + document.cookie = 'theme=light;samesite=Lax;path=/;max-age=31536000'; + } + + useDark() { + this.element.classList.add('dark-theme'); + document.cookie = 'theme=dark;samesite=Lax;path=/;max-age=31536000'; + } + + useAuto() { + document.cookie = 'theme=auto;samesite=Lax;path=/;max-age=0'; + this.#choose(); + } + + #choose() { + const themeCookieExists = document.cookie.split(';').some((cookie) => cookie.trim().startsWith('theme=')); + + if (themeCookieExists) { + return; + } + + if (this.mql.matches) { + this.element.classList.add('dark-theme'); + } else { + this.element.classList.remove('dark-theme'); + } + } +} diff --git a/assets/controllers/entries_navigation_controller.js b/assets/controllers/entries_navigation_controller.js new file mode 100644 index 000000000..52bbb1138 --- /dev/null +++ b/assets/controllers/entries_navigation_controller.js @@ -0,0 +1,58 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + static targets = ['card', 'paginationWrapper']; + + connect() { + this.pagination = this.paginationWrapperTarget.querySelector('.pagination'); + + this.cardIndex = 0; + this.lastCardIndex = this.cardTargets.length - 1; + + /* If we come from next page */ + if (window.location.hash === '#prev') { + this.cardIndex = this.lastCardIndex; + } + + this.currentCard = this.cardTargets[this.cardIndex]; + + this.currentCard.classList.add('z-depth-4'); + } + + selectRightCard() { + if (this.cardIndex >= 0 && this.cardIndex < this.lastCardIndex) { + this.currentCard.classList.remove('z-depth-4'); + this.cardIndex += 1; + this.currentCard = this.cardTargets[this.cardIndex]; + this.currentCard.classList.add('z-depth-4'); + + return; + } + + if (this.pagination && this.pagination.querySelector('a[rel="next"]')) { + window.location.href = this.pagination.querySelector('a[rel="next"]').href; + } + } + + selectLeftCard() { + if (this.cardIndex > 0 && this.cardIndex <= this.lastCardIndex) { + this.currentCard.classList.remove('z-depth-4'); + this.cardIndex -= 1; + this.currentCard = this.cardTargets[this.cardIndex]; + this.currentCard.classList.add('z-depth-4'); + + return; + } + + if (this.pagination && this.pagination.querySelector('a[rel="prev"]')) { + window.location.href = `${this.pagination.querySelector('a[rel="prev"]').href}#prev`; + } + } + + selectCurrentCard() { + const url = this.currentCard.querySelector('a.card-title').href; + if (url) { + window.location.href = url; + } + } +} diff --git a/assets/controllers/fake_radio_controller.js b/assets/controllers/fake_radio_controller.js new file mode 100644 index 000000000..a9426a189 --- /dev/null +++ b/assets/controllers/fake_radio_controller.js @@ -0,0 +1,13 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + static targets = ['emailTwoFactor', 'googleTwoFactor']; + + uncheckGoogle() { + this.googleTwoFactorTarget.checked = false; + } + + uncheckEmail() { + this.emailTwoFactorTarget.checked = false; + } +} diff --git a/assets/controllers/highlight_controller.js b/assets/controllers/highlight_controller.js new file mode 100644 index 000000000..8177b342e --- /dev/null +++ b/assets/controllers/highlight_controller.js @@ -0,0 +1,11 @@ +import { Controller } from '@hotwired/stimulus'; +import 'highlight.js/styles/atom-one-light.css'; +import hljs from 'highlight.js'; + +export default class extends Controller { + connect() { + this.element.querySelectorAll('pre code').forEach((element) => { + hljs.highlightElement(element); + }); + } +} diff --git a/assets/controllers/leftbar_controller.js b/assets/controllers/leftbar_controller.js new file mode 100644 index 000000000..45728a6f0 --- /dev/null +++ b/assets/controllers/leftbar_controller.js @@ -0,0 +1,7 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + toggleAddTagForm() { + this.dispatch('toggleAddTagForm'); + } +} diff --git a/assets/controllers/materialize/collapsible_controller.js b/assets/controllers/materialize/collapsible_controller.js new file mode 100644 index 000000000..b9e60f38c --- /dev/null +++ b/assets/controllers/materialize/collapsible_controller.js @@ -0,0 +1,16 @@ +import { Controller } from '@hotwired/stimulus'; +import M from '@materializecss/materialize'; + +export default class extends Controller { + static values = { + accordion: { type: Boolean, default: true }, + }; + + connect() { + this.instance = M.Collapsible.init(this.element, { accordion: this.accordionValue }); + } + + disconnect() { + this.instance.destroy(); + } +} diff --git a/assets/controllers/materialize/dropdown_controller.js b/assets/controllers/materialize/dropdown_controller.js new file mode 100644 index 000000000..12a209d16 --- /dev/null +++ b/assets/controllers/materialize/dropdown_controller.js @@ -0,0 +1,16 @@ +import { Controller } from '@hotwired/stimulus'; +import M from '@materializecss/materialize'; + +export default class extends Controller { + connect() { + this.instance = M.Dropdown.init(this.element, { + hover: false, + coverTrigger: false, + constrainWidth: false, + }); + } + + disconnect() { + this.instance.destroy(); + } +} diff --git a/assets/controllers/materialize/fab_controller.js b/assets/controllers/materialize/fab_controller.js new file mode 100644 index 000000000..1d11f38bd --- /dev/null +++ b/assets/controllers/materialize/fab_controller.js @@ -0,0 +1,32 @@ +import { Controller } from '@hotwired/stimulus'; +import M from '@materializecss/materialize'; + +export default class extends Controller { + static values = { + edge: { type: String, default: 'left' }, + }; + + connect() { + this.instance = M.FloatingActionButton.init(this.element); + } + + autoDisplay() { + const scrolled = (window.innerHeight + window.scrollY) >= document.body.offsetHeight; + + if (scrolled) { + this.toggleScroll = true; + this.instance.open(); + } else if (this.toggleScroll === true) { + this.toggleScroll = false; + this.instance.close(); + } + } + + click() { + this.dispatch('click'); + } + + disconnect() { + this.instance.destroy(); + } +} diff --git a/assets/controllers/materialize/form_select_controller.js b/assets/controllers/materialize/form_select_controller.js new file mode 100644 index 000000000..3a0fcf374 --- /dev/null +++ b/assets/controllers/materialize/form_select_controller.js @@ -0,0 +1,12 @@ +import { Controller } from '@hotwired/stimulus'; +import M from '@materializecss/materialize'; + +export default class extends Controller { + connect() { + this.instance = M.FormSelect.init(this.element.querySelector('select')); + } + + disconnect() { + this.instance.destroy(); + } +} diff --git a/assets/controllers/materialize/sidenav_controller.js b/assets/controllers/materialize/sidenav_controller.js new file mode 100644 index 000000000..c5c9fbd26 --- /dev/null +++ b/assets/controllers/materialize/sidenav_controller.js @@ -0,0 +1,24 @@ +import { Controller } from '@hotwired/stimulus'; +import M from '@materializecss/materialize'; + +const mobileMaxWidth = 993; + +export default class extends Controller { + static values = { + edge: { type: String, default: 'left' }, + }; + + connect() { + this.instance = M.Sidenav.init(this.element, { edge: this.edgeValue }); + } + + close() { + if (window.innerWidth < mobileMaxWidth) { + this.instance.close(); + } + } + + disconnect() { + this.instance.destroy(); + } +} diff --git a/assets/controllers/materialize/tabs_controller.js b/assets/controllers/materialize/tabs_controller.js new file mode 100644 index 000000000..312b486d4 --- /dev/null +++ b/assets/controllers/materialize/tabs_controller.js @@ -0,0 +1,12 @@ +import { Controller } from '@hotwired/stimulus'; +import M from '@materializecss/materialize'; + +export default class extends Controller { + connect() { + this.instance = M.Tabs.init(this.element); + } + + disconnect() { + this.instance.destroy(); + } +} diff --git a/assets/controllers/materialize/toast_controller.js b/assets/controllers/materialize/toast_controller.js new file mode 100644 index 000000000..ba9165473 --- /dev/null +++ b/assets/controllers/materialize/toast_controller.js @@ -0,0 +1,12 @@ +import { Controller } from '@hotwired/stimulus'; +import M from '@materializecss/materialize'; + +export default class extends Controller { + connect() { + this.instance = M.toast({ text: this.element.innerText }); + } + + disconnect() { + this.instance.dismissAll(); + } +} diff --git a/assets/controllers/materialize/tooltip_controller.js b/assets/controllers/materialize/tooltip_controller.js new file mode 100644 index 000000000..99f2acf3a --- /dev/null +++ b/assets/controllers/materialize/tooltip_controller.js @@ -0,0 +1,12 @@ +import { Controller } from '@hotwired/stimulus'; +import M from '@materializecss/materialize'; + +export default class extends Controller { + connect() { + this.instance = M.Tooltip.init(this.element); + } + + disconnect() { + this.instance.destroy(); + } +} diff --git a/assets/controllers/qrcode_controller.js b/assets/controllers/qrcode_controller.js new file mode 100644 index 000000000..c7818bca7 --- /dev/null +++ b/assets/controllers/qrcode_controller.js @@ -0,0 +1,10 @@ +import { Controller } from '@hotwired/stimulus'; +import jrQrcode from 'jr-qrcode'; + +export default class extends Controller { + static values = { url: String }; + + connect() { + this.element.setAttribute('src', jrQrcode.getQrBase64(this.urlValue)); + } +} diff --git a/assets/controllers/scroll_indicator_controller.js b/assets/controllers/scroll_indicator_controller.js new file mode 100644 index 000000000..1fab9b4ed --- /dev/null +++ b/assets/controllers/scroll_indicator_controller.js @@ -0,0 +1,10 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + updateWidth() { + const referenceHeight = document.body.offsetHeight - window.innerHeight; + const scrollPercent = (window.scrollY / referenceHeight) * 100; + + this.element.style.width = `${scrollPercent}%`; + } +} diff --git a/assets/controllers/scroll_storage_controller.js b/assets/controllers/scroll_storage_controller.js new file mode 100644 index 000000000..2bb6fc14b --- /dev/null +++ b/assets/controllers/scroll_storage_controller.js @@ -0,0 +1,19 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + static values = { entryId: Number }; + + connect() { + window.scrollTo({ + top: window.innerHeight * localStorage[`wallabag.article.${this.entryIdValue}.percent`], + behavior: 'smooth', + }); + } + + saveScroll() { + const scrollPercent = window.scrollY / window.innerHeight; + const scrollPercentRounded = Math.round(scrollPercent * 100) / 100; + + localStorage[`wallabag.article.${this.entryIdValue}.percent`] = scrollPercentRounded; + } +} diff --git a/assets/controllers/shortcuts_controller.js b/assets/controllers/shortcuts_controller.js new file mode 100644 index 000000000..921395fca --- /dev/null +++ b/assets/controllers/shortcuts_controller.js @@ -0,0 +1,141 @@ +import { Controller } from '@hotwired/stimulus'; +import Mousetrap from 'mousetrap'; + +export default class extends Controller { + static targets = ['openOriginal', 'markAsFavorite', 'markAsRead', 'deleteEntry', 'showAddUrl', 'showSearch', 'showActions']; + + static outlets = ['entries-navigation']; + + connect() { + /* Go to */ + Mousetrap.bind('g u', () => { + window.location.href = Routing.generate('homepage'); + }); + Mousetrap.bind('g s', () => { + window.location.href = Routing.generate('starred'); + }); + Mousetrap.bind('g r', () => { + window.location.href = Routing.generate('archive'); + }); + Mousetrap.bind('g a', () => { + window.location.href = Routing.generate('all'); + }); + Mousetrap.bind('g t', () => { + window.location.href = Routing.generate('tag'); + }); + Mousetrap.bind('g c', () => { + window.location.href = Routing.generate('config'); + }); + Mousetrap.bind('g i', () => { + window.location.href = Routing.generate('import'); + }); + Mousetrap.bind('g d', () => { + window.location.href = Routing.generate('developer'); + }); + Mousetrap.bind('?', () => { + window.location.href = Routing.generate('howto'); + }); + Mousetrap.bind('g l', () => { + window.location.href = Routing.generate('fos_user_security_logout'); + }); + + /* open original article */ + Mousetrap.bind('o', () => { + if (!this.hasOpenOriginalTarget) { + return; + } + + this.openOriginalTarget.click(); + }); + + /* mark as favorite */ + Mousetrap.bind('f', () => { + if (!this.hasMarkAsFavoriteTarget) { + return; + } + + this.markAsFavoriteTarget.click(); + }); + + /* mark as read */ + Mousetrap.bind('a', () => { + if (!this.hasMarkAsReadTarget) { + return; + } + + this.markAsReadTarget.click(); + }); + + /* delete */ + Mousetrap.bind('del', () => { + if (!this.hasDeleteEntryTarget) { + return; + } + + this.deleteEntryTarget.click(); + }); + + /* Actions */ + Mousetrap.bind('g n', (e) => { + if (!this.hasShowAddUrlTarget) { + return; + } + + e.preventDefault(); + this.showAddUrlTarget.click(); + }); + + Mousetrap.bind('s', (e) => { + if (!this.hasShowSearchTarget) { + return; + } + + e.preventDefault(); + this.showSearchTarget.click(); + }); + + Mousetrap.bind('esc', (e) => { + if (!this.hasShowActionsTarget) { + return; + } + + e.preventDefault(); + this.showActionsTarget.click(); + }); + + const originalStopCallback = Mousetrap.prototype.stopCallback; + + Mousetrap.prototype.stopCallback = (e, element, combo) => { + // allow esc key to be used in input fields of topbar + if (combo === 'esc' && element.dataset.topbarTarget !== undefined) { + return false; + } + + return originalStopCallback(e, element); + }; + + Mousetrap.bind('right', () => { + if (!this.hasEntriesNavigationOutlet) { + return; + } + + this.entriesNavigationOutlet.selectRightCard(); + }); + + Mousetrap.bind('left', () => { + if (!this.hasEntriesNavigationOutlet) { + return; + } + + this.entriesNavigationOutlet.selectLeftCard(); + }); + + Mousetrap.bind('enter', () => { + if (!this.hasEntriesNavigationOutlet) { + return; + } + + this.entriesNavigationOutlet.selectCurrentCard(); + }); + } +} diff --git a/assets/controllers/sticky_nav_controller.js b/assets/controllers/sticky_nav_controller.js new file mode 100644 index 000000000..12b405b0e --- /dev/null +++ b/assets/controllers/sticky_nav_controller.js @@ -0,0 +1,7 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + toggle() { + this.element.classList.toggle('entry-nav-top--sticky'); + } +} diff --git a/assets/controllers/tag_controller.js b/assets/controllers/tag_controller.js new file mode 100644 index 000000000..3f2b6c054 --- /dev/null +++ b/assets/controllers/tag_controller.js @@ -0,0 +1,12 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + static targets = ['link', 'edit', 'form', 'input']; + + showForm() { + this.formTarget.classList.remove('hidden'); + this.editTarget.classList.add('hidden'); + this.linkTarget.classList.add('hidden'); + this.inputTarget.focus(); + } +} diff --git a/assets/controllers/topbar_controller.js b/assets/controllers/topbar_controller.js new file mode 100644 index 000000000..e200893ad --- /dev/null +++ b/assets/controllers/topbar_controller.js @@ -0,0 +1,31 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + static targets = ['addUrl', 'addUrlInput', 'search', 'searchInput', 'actions']; + + showAddUrl() { + this.actionsTarget.style.display = 'none'; + this.addUrlTarget.style.display = 'flex'; + this.searchTarget.style.display = 'none'; + this.addUrlInputTarget.focus(); + } + + submittingUrl(e) { + e.currentTarget.disabled = true; + this.addUrlInputTarget.readOnly = true; + this.addUrlInputTarget.blur(); + } + + showSearch() { + this.actionsTarget.style.display = 'none'; + this.addUrlTarget.style.display = 'none'; + this.searchTarget.style.display = 'flex'; + this.searchInputTarget.focus(); + } + + showActions() { + this.actionsTarget.style.display = 'flex'; + this.addUrlTarget.style.display = 'none'; + this.searchTarget.style.display = 'none'; + } +} diff --git a/assets/index.js b/assets/index.js index a8cfc4877..dbbd06fdc 100755 --- a/assets/index.js +++ b/assets/index.js @@ -1,18 +1,11 @@ -import $ from 'jquery'; +import './bootstrap'; /* Materialize imports */ import '@materializecss/materialize/dist/css/materialize.css'; -import M from '@materializecss/materialize/dist/js/materialize'; +import '@materializecss/materialize/dist/js/materialize'; -/* Annotations */ -import annotator from 'annotator'; - -import ClipboardJS from 'clipboard'; import 'mathjax/es5/tex-svg'; -/* jrQrcode */ -import jrQrcode from 'jr-qrcode'; - /* Fonts */ import 'material-design-icons-iconfont/dist/material-design-icons.css'; import 'lato-font/css/lato-font.css'; @@ -22,371 +15,5 @@ import '@fontsource/eb-garamond'; import '@fontsource/montserrat'; import '@fontsource/oswald'; -/* Highlight */ -import './js/highlight'; - -/* Tools */ -import { - savePercent, retrievePercent, initPreviewText, -} from './js/tools'; - -/* Import shortcuts */ -import './js/shortcuts/main'; -import './js/shortcuts/entry'; - /* Theme style */ import './scss/index.scss'; - -const mobileMaxWidth = 993; - -/* ========================================================================== - Annotations & Remember position - ========================================================================== */ - -$(document).ready(() => { - if ($('#article').length) { - const app = new annotator.App(); - - app.include(annotator.ui.main, { - element: document.querySelector('article'), - }); - - const authorization = { - permits() { return true; }, - }; - app.registry.registerUtility(authorization, 'authorizationPolicy'); - - const x = JSON.parse($('#annotationroutes').html()); - app.include(annotator.storage.http, $.extend({}, x, { - onError(msg, xhr) { - if (!Object.prototype.hasOwnProperty.call(xhr, 'responseJSON')) { - annotator.notification.banner('An error occurred', 'error'); - return; - } - $.each(xhr.responseJSON.children, (k, v) => { - if (v.errors) { - $.each(v.errors, (n, errorText) => { - annotator.notification.banner(errorText, 'error'); - }); - } - }); - }, - })); - - app.start().then(() => { - app.annotations.load({ entry: x.entryId }); - }); - - $(window).scroll(() => { - const scrollTop = $(window).scrollTop(); - const docHeight = $(document).height(); - const scrollPercent = (scrollTop) / (docHeight); - const scrollPercentRounded = Math.round(scrollPercent * 100) / 100; - savePercent(x.entryId, scrollPercentRounded); - }); - - retrievePercent(x.entryId); - - $(window).resize(() => { - retrievePercent(x.entryId, true); - }); - } - - document.querySelectorAll('[data-handler=tag-rename]').forEach((item) => { - const current = item; - current.wallabag_edit_mode = false; - current.onclick = (event) => { - const target = event.currentTarget; - - if (target.wallabag_edit_mode === false) { - $(target.parentNode.querySelector('[data-handle=tag-link]')).addClass('hidden'); - $(target.parentNode.querySelector('[data-handle=tag-rename-form]')).removeClass('hidden'); - target.parentNode.querySelector('[data-handle=tag-rename-form] input').focus(); - target.querySelector('.material-icons').innerHTML = 'done'; - - target.wallabag_edit_mode = true; - } else { - target.parentNode.querySelector('[data-handle=tag-rename-form]').submit(); - } - }; - }); - - // mimic radio button because emailTwoFactor is a boolean - $('#update_user_googleTwoFactor').on('change', () => { - $('#update_user_emailTwoFactor').prop('checked', false); - }); - - $('#update_user_emailTwoFactor').on('change', () => { - $('#update_user_googleTwoFactor').prop('checked', false); - }); - - // same mimic for super admin - $('#user_googleTwoFactor').on('change', () => { - $('#user_emailTwoFactor').prop('checked', false); - }); - - $('#user_emailTwoFactor').on('change', () => { - $('#user_googleTwoFactor').prop('checked', false); - }); - - // handle copy to clipboard for developer stuff - const clipboard = new ClipboardJS('.btn'); - clipboard.on('success', (e) => { - e.clearSelection(); - }); -}); - -(function darkTheme() { - const rootEl = document.querySelector('html'); - const themeDom = { - darkClass: 'dark-theme', - - toggleClass(el) { - return el.classList.toggle(this.darkClass); - }, - - addClass(el) { - return el.classList.add(this.darkClass); - }, - - removeClass(el) { - return el.classList.remove(this.darkClass); - }, - }; - const themeCookie = { - values: { - light: 'light', - dark: 'dark', - }, - - name: 'theme', - - getValue(isDarkTheme) { - return isDarkTheme ? this.values.dark : this.values.light; - }, - - setCookie(isDarkTheme) { - const value = this.getValue(isDarkTheme); - document.cookie = `${this.name}=${value};samesite=Lax;path=/;max-age=31536000`; - }, - - removeCookie() { - document.cookie = `${this.name}=auto;samesite=Lax;path=/;max-age=0`; - }, - - exists() { - return document.cookie.split(';').some((cookie) => cookie.trim().startsWith(`${this.name}=`)); - }, - }; - const preferedColorScheme = { - choose() { - const themeCookieExists = themeCookie.exists(); - if (this.isAvailable() && !themeCookieExists) { - const isPreferedColorSchemeDark = window.matchMedia('(prefers-color-scheme: dark)').matches === true; - if (!themeCookieExists) { - themeDom[isPreferedColorSchemeDark ? 'addClass' : 'removeClass'](rootEl); - } - } - }, - - isAvailable() { - return typeof window.matchMedia === 'function'; - }, - - init() { - if (!this.isAvailable()) { - return false; - } - this.choose(); - window.matchMedia('(prefers-color-scheme: dark)').addListener(() => { - this.choose(); - }); - return true; - }, - }; - - const addDarkThemeListeners = () => { - $(document).ready(() => { - const lightThemeButtons = document.querySelectorAll('.js-theme-toggle[data-theme="light"]'); - [...lightThemeButtons].map((lightThemeButton) => { - lightThemeButton.addEventListener('click', (e) => { - e.preventDefault(); - themeDom.removeClass(rootEl); - themeCookie.setCookie(false); - }); - return true; - }); - const darkThemeButtons = document.querySelectorAll('.js-theme-toggle[data-theme="dark"]'); - [...darkThemeButtons].map((darkThemeButton) => { - darkThemeButton.addEventListener('click', (e) => { - e.preventDefault(); - themeDom.addClass(rootEl); - themeCookie.setCookie(true); - }); - return true; - }); - const autoThemeButtons = document.querySelectorAll('.js-theme-toggle[data-theme="auto"]'); - [...autoThemeButtons].map((autoThemeButton) => { - autoThemeButton.addEventListener('click', (e) => { - e.preventDefault(); - themeCookie.removeCookie(); - preferedColorScheme.choose(); - }); - return true; - }); - }); - }; - - preferedColorScheme.init(); - addDarkThemeListeners(); -}()); - -const stickyNav = () => { - const nav = $('.js-entry-nav-top'); - $('[data-toggle="actions"]').click(() => { - nav.toggleClass('entry-nav-top--sticky'); - }); -}; - -const articleScroll = () => { - const articleEl = $('#article'); - if (articleEl.length > 0) { - $(window).scroll(() => { - const s = $(window).scrollTop(); - const d = $(document).height(); - const c = $(window).height(); - const articleElBottom = articleEl.offset().top + articleEl.height(); - const scrollPercent = (s / (d - c)) * 100; - $('.progress .determinate').css('width', `${scrollPercent}%`); - const fixedActionBtn = $('.js-fixed-action-btn'); - const toggleScrollDataName = 'toggle-auto'; - if ((s + c) > articleElBottom) { - fixedActionBtn.data(toggleScrollDataName, true); - fixedActionBtn.floatingActionButton('open'); - } else if (fixedActionBtn.data(toggleScrollDataName) === true) { - fixedActionBtn.data(toggleScrollDataName, false); - fixedActionBtn.floatingActionButton('close'); - } - }); - } -}; - -$(document).ready(() => { - // sidenav - document.querySelectorAll('.sidenav').forEach((element) => { - $(element).sidenav({ edge: element.getAttribute('data-edge') ?? 'left' }); - }); - - $('select').formSelect(); - $('.collapsible[data-collapsible="accordion"]').collapsible(); - $('.collapsible[data-collapsible="expandable"]').collapsible({ - accordion: false, - }); - - $('.dropdown-trigger').dropdown({ hover: false }); - $('.dropdown-trigger[data-covertrigger="false"][data-constrainwidth="false"]').dropdown({ - hover: false, - coverTrigger: false, - constrainWidth: false, - }); - - $('.tabs').tabs(); - $('.tooltipped').tooltip(); - $('.fixed-action-btn').floatingActionButton(); - - stickyNav(); - articleScroll(); - initPreviewText(); - - const toggleNav = (toShow, toFocus) => { - $('.nav-panel-actions').hide(); - $(toShow).show(); - $(toFocus).focus(); - }; - - $('#nav-btn-add-tag').on('click', () => { - $('.nav-panel-add-tag').toggle(); - $('.nav-panel-menu').addClass('hidden'); - if (window.innerWidth < mobileMaxWidth) { - $('.sidenav').sidenav('close'); - } - $('#tag_label').focus(); - return false; - }); - - $('#nav-btn-add').on('click', () => { - toggleNav('.nav-panel-add', '#entry_url'); - return false; - }); - - $('#config_fontsize').on('input', () => { - const value = $('#config_fontsize').val(); - const css = `${value}em`; - $('#preview-content').css('font-size', css); - }); - - $('#config_font').on('change', () => { - const value = $('#config_font').val(); - $('#preview-content').css('font-family', value); - }); - - $('#config_lineHeight').on('input', () => { - const value = $('#config_lineHeight').val(); - const css = `${value}em`; - $('#preview-content').css('line-height', css); - }); - - $('#config_maxWidth').on('input', () => { - const value = $('#config_maxWidth').val(); - const css = `${value}em`; - $('#preview-article').css('max-width', css); - }); - - const materialAddForm = $('.nav-panel-add'); - materialAddForm.on('submit', () => { - materialAddForm.addClass('disabled'); - $('input#entry_url', materialAddForm).prop('readonly', true).trigger('blur'); - }); - - $('#nav-btn-search').on('click', () => { - toggleNav('.nav-panel-search', '#search_entry_term'); - return false; - }); - - $('.close').on('click', (e) => { - $(e.target).parent('.nav-panel-item').hide(); - $('.nav-panel-actions').show(); - return false; - }); - - const mainCheckboxes = document.querySelectorAll('[data-js="checkboxes-toggle"]'); - if (mainCheckboxes.length) { - [...mainCheckboxes].forEach((el) => { - el.addEventListener('click', () => { - const checkboxes = document.querySelectorAll(el.dataset.toggle); - [...checkboxes].forEach((checkbox) => { - const checkboxClone = checkbox; - checkboxClone.checked = el.checked; - }); - }); - }); - } - $('form[name="form_mass_action"] input[name="tags"]').on('keydown', (e) => { - if (e.key === 'Enter') { - e.preventDefault(); - $('form[name="form_mass_action"] button[name="tag"]').trigger('click'); - } - }); - - document.querySelectorAll('img.jr-qrcode').forEach((qrcode) => { - const src = jrQrcode.getQrBase64(qrcode.getAttribute('data-url')); - - qrcode.setAttribute('src', src); - }); - - document.querySelectorAll('.material-toast').forEach((toast) => { - M.toast({ - text: toast.innerText, - }); - }); -}); diff --git a/assets/js/highlight.js b/assets/js/highlight.js deleted file mode 100644 index f6f8349b4..000000000 --- a/assets/js/highlight.js +++ /dev/null @@ -1,8 +0,0 @@ -import 'highlight.js/styles/atom-one-light.css'; -import hljs from 'highlight.js'; - -window.addEventListener('load', () => { - document.querySelectorAll('pre').forEach((element) => { - hljs.highlightElement(element); - }); -}); diff --git a/assets/js/shortcuts/entry.js b/assets/js/shortcuts/entry.js deleted file mode 100644 index 3c15f3d29..000000000 --- a/assets/js/shortcuts/entry.js +++ /dev/null @@ -1,26 +0,0 @@ -import Mousetrap from 'mousetrap'; -import $ from 'jquery'; - -$(document).ready(() => { - if ($('#article').length > 0) { - /* open original article */ - Mousetrap.bind('o', () => { - $('ul.sidenav a.original i')[0].click(); - }); - - /* mark as favorite */ - Mousetrap.bind('f', () => { - $('ul.sidenav a.favorite i')[0].click(); - }); - - /* mark as read */ - Mousetrap.bind('a', () => { - $('ul.sidenav a.markasread i')[0].click(); - }); - - /* delete */ - Mousetrap.bind('del', () => { - $('ul.sidenav a.delete i')[0].click(); - }); - } -}); diff --git a/assets/js/shortcuts/main.js b/assets/js/shortcuts/main.js deleted file mode 100644 index 8033d9651..000000000 --- a/assets/js/shortcuts/main.js +++ /dev/null @@ -1,104 +0,0 @@ -import Mousetrap from 'mousetrap'; -import $ from 'jquery'; - -/* Go to */ -Mousetrap.bind('g u', () => { window.location.href = Routing.generate('homepage'); }); -Mousetrap.bind('g s', () => { window.location.href = Routing.generate('starred'); }); -Mousetrap.bind('g r', () => { window.location.href = Routing.generate('archive'); }); -Mousetrap.bind('g a', () => { window.location.href = Routing.generate('all'); }); -Mousetrap.bind('g t', () => { window.location.href = Routing.generate('tag'); }); -Mousetrap.bind('g c', () => { window.location.href = Routing.generate('config'); }); -Mousetrap.bind('g i', () => { window.location.href = Routing.generate('import'); }); -Mousetrap.bind('g d', () => { window.location.href = Routing.generate('developer'); }); -Mousetrap.bind('?', () => { window.location.href = Routing.generate('howto'); }); -Mousetrap.bind('g l', () => { window.location.href = Routing.generate('fos_user_security_logout'); }); - -function toggleFocus(cardToToogleFocus) { - if (cardToToogleFocus) { - $(cardToToogleFocus).toggleClass('z-depth-4'); - } -} - -$(document).ready(() => { - const cards = $('#content').find('.card'); - const cardNumber = cards.length; - let cardIndex = 0; - /* If we come from next page */ - if (window.location.hash === '#prev') { - cardIndex = cardNumber - 1; - } - let card = cards[cardIndex]; - const pagination = $('.pagination'); - - /* Show nothing on quickstart */ - if ($('#content > div.quickstart').length > 0) { - return; - } - - /* Show nothing on login/register page */ - if ($('#username').length > 0 || $('#fos_user_registration_form_username').length > 0) { - return; - } - - /* Show nothing on login/register page */ - if ($('#username').length > 0 || $('#fos_user_registration_form_username').length > 0) { - return; - } - - /* Focus current card */ - toggleFocus(card); - - /* Actions */ - Mousetrap.bind('g n', () => { - $('#nav-btn-add').trigger('click'); - return false; - }); - - Mousetrap.bind('s', () => { - $('#nav-btn-search').trigger('click'); - return false; - }); - - Mousetrap.bind('esc', () => { - $('.close').trigger('click'); - }); - - /* Select right card. If there's a next page, go to next page */ - Mousetrap.bind('right', () => { - if (cardIndex >= 0 && cardIndex < cardNumber - 1) { - toggleFocus(card); - cardIndex += 1; - card = cards[cardIndex]; - toggleFocus(card); - return; - } - if (pagination.length > 0 && pagination.find('li.next:not(.disabled)').length > 0 && cardIndex === cardNumber - 1) { - window.location.href = window.location.origin + $(pagination).find('li.next a').attr('href'); - } - }); - - /* Select previous card. If there's a previous page, go to next page */ - Mousetrap.bind('left', () => { - if (cardIndex > 0 && cardIndex < cardNumber) { - toggleFocus(card); - cardIndex -= 1; - card = cards[cardIndex]; - toggleFocus(card); - return; - } - if (pagination.length > 0 && $(pagination).find('li.prev:not(.disabled)').length > 0 && cardIndex === 0) { - window.location.href = `${window.location.origin + $(pagination).find('li.prev a').attr('href')}#prev`; - } - }); - - Mousetrap.bind('enter', () => { - if (typeof card !== 'object') { - return; - } - - const url = $(card).find('.card-title a').attr('href'); - if (typeof url === 'string' && url.length > 0) { - window.location.href = window.location.origin + url; - } - }); -}); diff --git a/assets/js/tools.js b/assets/js/tools.js deleted file mode 100644 index 18528548d..000000000 --- a/assets/js/tools.js +++ /dev/null @@ -1,54 +0,0 @@ -import $ from 'jquery'; - -function supportsLocalStorage() { - try { - return 'localStorage' in window && window.localStorage !== null; - } catch (e) { - return false; - } -} - -function savePercent(id, percent) { - if (!supportsLocalStorage()) { return false; } - localStorage[`wallabag.article.${id}.percent`] = percent; - return true; -} - -function retrievePercent(id, resized) { - if (!supportsLocalStorage()) { return false; } - - const bheight = $(document).height(); - const percent = localStorage[`wallabag.article.${id}.percent`]; - const scroll = bheight * percent; - - if (!resized) { - window.scrollTo({ - top: scroll, - behavior: 'smooth', - }); - } - - return true; -} - -function initPreviewText() { - // no display if preview_text not available - if ($('div').is('#preview-article')) { - const defaultFontFamily = $('#config_font').val(); - const defaultFontSize = $('#config_fontsize').val(); - const defaultLineHeight = $('#config_lineHeight').val(); - const defaultMaxWidth = $('#config_maxWidth').val(); - const previewContent = $('#preview-content'); - - previewContent.css('font-family', defaultFontFamily); - previewContent.css('font-size', `${defaultFontSize}em`); - previewContent.css('line-height', `${defaultLineHeight}em`); - $('#preview-article').css('max-width', `${defaultMaxWidth}em`); - } -} - -export { - savePercent, - retrievePercent, - initPreviewText, -}; diff --git a/assets/scss/_cards.scss b/assets/scss/_cards.scss index b63fad649..6ae2b8e9b 100644 --- a/assets/scss/_cards.scss +++ b/assets/scss/_cards.scss @@ -186,6 +186,14 @@ a.original:not(.waves-effect) { color: #fff; } +.card-tag-labels button { + background: transparent; + border: none; + font-weight: normal; + color: #fff; + cursor: pointer; +} + .card-tag-link { width: calc(100% - 24px); line-height: 1.3; @@ -196,6 +204,7 @@ a.original:not(.waves-effect) { .card-tag-form { display: flex; + align-items: center; min-width: 100px; flex-grow: 1; } diff --git a/package.json b/package.json index 5ecdbc7af..c2675b005 100644 --- a/package.json +++ b/package.json @@ -80,14 +80,14 @@ "@fontsource/eb-garamond": "^5.2.5", "@fontsource/montserrat": "^5.2.5", "@fontsource/oswald": "^5.2.5", + "@hotwired/stimulus": "^3.2.2", "@materializecss/materialize": "^1.2.2", + "@symfony/stimulus-bridge": "^4.0.0", "annotator": "wallabag/annotator#master", "clipboard": "^2.0.11", "hammerjs": "^2.0.8", "highlight.js": "^11.11.1", "icomoon-free-npm": "^0.0.0", - "jquery": "^3.7.1", - "jquery.cookie": "^1.4.1", "jr-qrcode": "^1.2.1", "material-design-icons-iconfont": "^6.7.0", "mathjax": "^3.2.2", @@ -100,7 +100,7 @@ "build:dev": "encore dev", "watch": "encore dev --watch", "build:prod": "encore production --progress", - "lint:js": "eslint assets/*.js assets/js/*.js assets/js/**/*.js", + "lint:js": "eslint assets/*.js assets/controllers/*.js", "lint:scss": "stylelint assets/scss/*.scss assets/scss/**/*.scss" } } diff --git a/templates/Config/index.html.twig b/templates/Config/index.html.twig index add3d3577..51ec63776 100644 --- a/templates/Config/index.html.twig +++ b/templates/Config/index.html.twig @@ -10,7 +10,7 @@
-
-
+
{{ form_start(form.config) }} {{ form_errors(form.config) }} @@ -32,7 +32,7 @@ {{ form_label(form.config.items_per_page) }}
@@ -47,7 +47,7 @@
- + live_help
@@ -64,14 +64,14 @@

- + live_help
-
+
{{ form_errors(form.config.action_mark_as_read) }} {{ form_widget(form.config.action_mark_as_read) }} {{ form_label(form.config.action_mark_as_read) }} @@ -79,13 +79,13 @@
-
+
{{ form_errors(form.config.language) }} {{ form_widget(form.config.language) }} {{ form_label(form.config.language) }}
@@ -102,7 +102,7 @@

@@ -112,31 +112,31 @@
{{ 'config.form_settings.android_configuration'|trans }}
{{ 'config.form_settings.android_instruction'|trans }} - {{ 'config.otp.app.qrcode_label'|trans }} + {{ 'config.otp.app.qrcode_label'|trans }}
{{ 'config.tab_menu.article_display'|trans }}
-
+
{{ form_errors(form.config.font) }} - {{ form_widget(form.config.font) }} + {{ form_widget(form.config.font, {attr: {'data-config-target': 'font', 'data-action': 'config#updatePreview'}}) }} {{ form_label(form.config.font) }}
{{ form_errors(form.config.lineHeight) }} - {{ form_widget(form.config.lineHeight) }} + {{ form_widget(form.config.lineHeight, {attr: {'data-config-target': 'lineHeight', 'data-action': 'config#updatePreview'}}) }} {{ form_label(form.config.lineHeight, null, {'label_attr': {'class': 'settings-range-label'}}) }}
@@ -145,22 +145,22 @@
{{ form_errors(form.config.fontsize) }} - {{ form_widget(form.config.fontsize) }} + {{ form_widget(form.config.fontsize, {attr: {'data-config-target': 'fontSize', 'data-action': 'config#updatePreview'}}) }} {{ form_label(form.config.fontsize, null, {'label_attr': {'class': 'settings-range-label'}}) }}
{{ form_errors(form.config.maxWidth) }} - {{ form_widget(form.config.maxWidth) }} + {{ form_widget(form.config.maxWidth, {attr: {'data-config-target': 'maxWidth', 'data-action': 'config#updatePreview'}}) }} {{ form_label(form.config.maxWidth, null, {'label_attr': {'class': 'settings-range-label'}}) }}
@@ -168,8 +168,8 @@
-
-
+
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
diff --git a/templates/Config/otp_app.html.twig b/templates/Config/otp_app.html.twig index e409043af..792455d3f 100644 --- a/templates/Config/otp_app.html.twig +++ b/templates/Config/otp_app.html.twig @@ -15,17 +15,17 @@

{{ 'config.otp.app.two_factor_code_description_2'|trans }}

- +

-

- {{ 'config.otp.app.two_factor_code_description_5'|trans }}

{{ secret }}
-

+
+ {{ 'config.otp.app.two_factor_code_description_5'|trans }}
{{ secret }}
+
  • {{ 'config.otp.app.two_factor_code_description_3'|trans }}

    -

    {{ backupCodes|join("\n") }}

    +
    {{ backupCodes|join("\n") }}
  • {{ 'config.otp.app.two_factor_code_description_4'|trans }}

    diff --git a/templates/Developer/client_parameters.html.twig b/templates/Developer/client_parameters.html.twig index b17d3ea34..70fe3943d 100644 --- a/templates/Developer/client_parameters.html.twig +++ b/templates/Developer/client_parameters.html.twig @@ -18,14 +18,14 @@ {{ 'developer.client_parameter.field_id'|trans }} {{ client_id }} - + {{ 'developer.client_parameter.field_secret'|trans }} {{ client_secret }} - + diff --git a/templates/Developer/howto_app.html.twig b/templates/Developer/howto_app.html.twig index d4795d5c4..f2d9a6ac2 100644 --- a/templates/Developer/howto_app.html.twig +++ b/templates/Developer/howto_app.html.twig @@ -12,16 +12,16 @@

    {{ 'developer.howto.description.paragraph_2'|trans }}

    {{ 'developer.howto.description.paragraph_3'|trans({'%link%': path('developer_create_client')})|raw }}

    {{ 'developer.howto.description.paragraph_4'|trans }}

    -

    +

    http POST {{ wallabag_url }}/oauth/v2/token \
         grant_type=password \
         client_id=12_5um6nz50ceg4088c0840wwc0kgg44g00kk84og044ggkscso0k \
         client_secret=3qd12zpeaxes8cwg8c0404g888co4wo8kc4gcw0occww8cgw4k \
         username=yourUsername \
         password=yourPassw0rd
    -

    +

    {{ 'developer.howto.description.paragraph_5'|trans }}

    -

    +

    HTTP/1.1 200 OK
     Cache-Control: no-store, private
     Connection: close
    @@ -39,12 +39,12 @@ X-Powered-By: PHP/5.5.9-1ubuntu4.13
         "scope": null,
         "token_type": "bearer"
     }
    -

    +

    {{ 'developer.howto.description.paragraph_6'|trans }}

    -

    +

    http GET {{ wallabag_url }}/api/entries.json \
         "Authorization:Bearer ZWFjNjA3ZWMwYWVmYzRkYTBlMmQ3NTllYmVhOGJiZDE0ZTg1NjE4MjczOTVlNzM0ZTRlMWQ0MmRlMmYwNTk5Mw"
    -

    +

    {{ 'developer.howto.description.paragraph_7'|trans }}

    {{ 'developer.howto.description.paragraph_8'|trans({'%link%': path('nelmio_api_doc.swagger_ui')})|raw }}

    {{ 'developer.howto.back'|trans }}

    diff --git a/templates/Developer/index.html.twig b/templates/Developer/index.html.twig index fa437d0ae..8ca4767fb 100644 --- a/templates/Developer/index.html.twig +++ b/templates/Developer/index.html.twig @@ -25,7 +25,7 @@

    {{ 'developer.existing_clients.title'|trans }}

    {% if clients %} -
      +
        {% for client in clients %}
      • {{ client.name }} - #{{ client.id }}
        @@ -35,14 +35,14 @@ {{ 'developer.existing_clients.field_id'|trans }} {{ client.clientId }} - + {{ 'developer.existing_clients.field_secret'|trans }} {{ client.secret }} - + diff --git a/templates/Entry/Card/_mass_checkbox.html.twig b/templates/Entry/Card/_mass_checkbox.html.twig index 5e4fe8f6d..e972f5695 100644 --- a/templates/Entry/Card/_mass_checkbox.html.twig +++ b/templates/Entry/Card/_mass_checkbox.html.twig @@ -1,3 +1,3 @@ diff --git a/templates/Entry/entries.html.twig b/templates/Entry/entries.html.twig index a3dc3fe8a..ac3c580a7 100644 --- a/templates/Entry/entries.html.twig +++ b/templates/Entry/entries.html.twig @@ -24,21 +24,21 @@ {% block nav_panel_extra_actions %} {% if active_route %}
      • - + casino
      • {% endif %} {% if has_filters %}
      • - + filter_list
      • {% endif %} {% if has_exports %}
      • - + file_download
      • @@ -53,15 +53,15 @@ {% if current_route == 'homepage' %} {% set current_route = 'unread' %} {% endif %} -
        -
        + +
        {{ 'entry.list.number_on_the_page'|trans({'%count%': entries.count}) }} {% if entries.count > 0 %} {% if list_mode == 0 %}view_list{% else %}view_module{% endif %} {% endif %} {% if entries.count > 0 and is_granted('EDIT_ENTRIES') %} - + {% endif %} {% if app.user.config.feedToken %} {% include "Entry/_feed_link.html.twig" %} @@ -77,22 +77,22 @@
        - +
        - - + +
          {% for entry in entries %} -
        1. +
        2. {% if list_mode == 1 %} {% include "Entry/_card_list.html.twig" with {'entry': entry, 'currentRoute': current_route, 'routes': entries_with_archived_class_routes} only %} {% elseif not entry.previewPicture is null and entry.mimetype starts with 'image/' %} @@ -114,7 +114,7 @@ {% if has_exports and is_granted('EXPORT_ENTRIES') %} -
          +
          {% set current_tag = null %} {% if tag is defined %} {% set current_tag = tag.slug %} @@ -140,7 +140,7 @@ {% if has_filters %} -
          +

          {{ 'entry.filters.title'|trans }}

          diff --git a/templates/Entry/entry.html.twig b/templates/Entry/entry.html.twig index 101e9aabc..c702c2351 100644 --- a/templates/Entry/entry.html.twig +++ b/templates/Entry/entry.html.twig @@ -8,9 +8,9 @@ {% block menu %}
          -
          +
          -
          - - - {% endblock %} {% block footer %} diff --git a/templates/Entry/new_form.html.twig b/templates/Entry/new_form.html.twig index e572d9f50..f1a9cf45e 100644 --- a/templates/Entry/new_form.html.twig +++ b/templates/Entry/new_form.html.twig @@ -1,4 +1,4 @@ - + {% if form_errors(form) %} {{ form_errors(form) }} {% endif %} @@ -8,8 +8,8 @@ {{ form_errors(form.url) }} {% endif %} - {{ form_widget(form.url, {'attr': {'autocomplete': 'off', 'placeholder': 'entry.new.placeholder'}}) }} - + {{ form_widget(form.url, {'attr': {'autocomplete': 'off', 'placeholder': 'entry.new.placeholder', 'data-topbar-target': 'addUrlInput'}}) }} + {{ form_rest(form) }} diff --git a/templates/Entry/search_form.html.twig b/templates/Entry/search_form.html.twig index 451a1f8ba..ebd10e70a 100644 --- a/templates/Entry/search_form.html.twig +++ b/templates/Entry/search_form.html.twig @@ -1,4 +1,4 @@ - diff --git a/templates/Import/check_queue.html.twig b/templates/Import/check_queue.html.twig index 34ab57a16..4d8e924ad 100644 --- a/templates/Import/check_queue.html.twig +++ b/templates/Import/check_queue.html.twig @@ -1,9 +1,9 @@ {% if nbRedisMessages is defined and nbRedisMessages > 0 %} - + {% endif %} {% if nbRabbitMessages is defined and nbRabbitMessages > 0 %} - + {% endif %} {% if redisNotInstalled is defined and redisNotInstalled %} diff --git a/templates/Static/about.html.twig b/templates/Static/about.html.twig index 02805405b..c01b2edbe 100644 --- a/templates/Static/about.html.twig +++ b/templates/Static/about.html.twig @@ -10,7 +10,7 @@
          -
            +
            • {{ 'about.top_menu.who_behind_wallabag'|trans }}
            • {{ 'about.top_menu.getting_help'|trans }}
            • {{ 'about.top_menu.helping'|trans }}
            • diff --git a/templates/Static/howto.html.twig b/templates/Static/howto.html.twig index 493961294..6b9412595 100644 --- a/templates/Static/howto.html.twig +++ b/templates/Static/howto.html.twig @@ -10,7 +10,7 @@
              -
              -
              +
              diff --git a/templates/base.html.twig b/templates/base.html.twig index 00e66482f..43d75fc9f 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -4,7 +4,7 @@ - + {% block head %} diff --git a/templates/bundles/CraueConfigBundle/Settings/modify.html.twig b/templates/bundles/CraueConfigBundle/Settings/modify.html.twig index 438b36e03..83d9a6fa6 100644 --- a/templates/bundles/CraueConfigBundle/Settings/modify.html.twig +++ b/templates/bundles/CraueConfigBundle/Settings/modify.html.twig @@ -11,7 +11,7 @@
              -
                +
                  {% for section in sections|craue_sortSections %}
                • {{ section|trans({}, 'CraueConfigBundle') }}
                • {% endfor %} diff --git a/templates/bundles/FOSUserBundle/Security/login.html.twig b/templates/bundles/FOSUserBundle/Security/login.html.twig index 2466a0752..c25b106ff 100644 --- a/templates/bundles/FOSUserBundle/Security/login.html.twig +++ b/templates/bundles/FOSUserBundle/Security/login.html.twig @@ -5,11 +5,11 @@
                  {% if error %} - + {% endif %} {% for flash_message in app.session.flashbag.get('notice') %} - + {% endfor %}
                  diff --git a/templates/layout.html.twig b/templates/layout.html.twig index 9ceb4a32e..b0c2de45c 100644 --- a/templates/layout.html.twig +++ b/templates/layout.html.twig @@ -35,7 +35,7 @@ {% block messages %} {% for flash_message in app.session.flashbag.get('notice') %} - + {% endfor %} {% endblock %} @@ -43,7 +43,7 @@ {% block menu %}