mirror of
https://github.com/wallabag/wallabag.git
synced 2025-03-13 22:52:39 +00:00
Merge 6c1fc24ac1
into a4a6eb580b
This commit is contained in:
commit
464f1ccf04
58 changed files with 830 additions and 765 deletions
11
assets/bootstrap.js
vendored
Normal file
11
assets/bootstrap.js
vendored
Normal file
|
@ -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);
|
4
assets/controllers.json
Normal file
4
assets/controllers.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"controllers": [],
|
||||
"entrypoints": []
|
||||
}
|
13
assets/controllers/add_tag_controller.js
Normal file
13
assets/controllers/add_tag_controller.js
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
57
assets/controllers/annotations_controller.js
Normal file
57
assets/controllers/annotations_controller.js
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
15
assets/controllers/batch_edit_controller.js
Normal file
15
assets/controllers/batch_edit_controller.js
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
16
assets/controllers/clipboard_controller.js
Normal file
16
assets/controllers/clipboard_controller.js
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
16
assets/controllers/config_controller.js
Normal file
16
assets/controllers/config_controller.js
Normal file
|
@ -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`;
|
||||
}
|
||||
}
|
39
assets/controllers/dark_theme_controller.js
Normal file
39
assets/controllers/dark_theme_controller.js
Normal file
|
@ -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');
|
||||
}
|
||||
}
|
||||
}
|
58
assets/controllers/entries_navigation_controller.js
Normal file
58
assets/controllers/entries_navigation_controller.js
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
13
assets/controllers/fake_radio_controller.js
Normal file
13
assets/controllers/fake_radio_controller.js
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
11
assets/controllers/highlight_controller.js
Normal file
11
assets/controllers/highlight_controller.js
Normal file
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
7
assets/controllers/leftbar_controller.js
Normal file
7
assets/controllers/leftbar_controller.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { Controller } from '@hotwired/stimulus';
|
||||
|
||||
export default class extends Controller {
|
||||
toggleAddTagForm() {
|
||||
this.dispatch('toggleAddTagForm');
|
||||
}
|
||||
}
|
16
assets/controllers/materialize/collapsible_controller.js
Normal file
16
assets/controllers/materialize/collapsible_controller.js
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
16
assets/controllers/materialize/dropdown_controller.js
Normal file
16
assets/controllers/materialize/dropdown_controller.js
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
32
assets/controllers/materialize/fab_controller.js
Normal file
32
assets/controllers/materialize/fab_controller.js
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
12
assets/controllers/materialize/form_select_controller.js
Normal file
12
assets/controllers/materialize/form_select_controller.js
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
24
assets/controllers/materialize/sidenav_controller.js
Normal file
24
assets/controllers/materialize/sidenav_controller.js
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
12
assets/controllers/materialize/tabs_controller.js
Normal file
12
assets/controllers/materialize/tabs_controller.js
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
12
assets/controllers/materialize/toast_controller.js
Normal file
12
assets/controllers/materialize/toast_controller.js
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
12
assets/controllers/materialize/tooltip_controller.js
Normal file
12
assets/controllers/materialize/tooltip_controller.js
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
10
assets/controllers/qrcode_controller.js
Normal file
10
assets/controllers/qrcode_controller.js
Normal file
|
@ -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));
|
||||
}
|
||||
}
|
10
assets/controllers/scroll_indicator_controller.js
Normal file
10
assets/controllers/scroll_indicator_controller.js
Normal file
|
@ -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}%`;
|
||||
}
|
||||
}
|
19
assets/controllers/scroll_storage_controller.js
Normal file
19
assets/controllers/scroll_storage_controller.js
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
141
assets/controllers/shortcuts_controller.js
Normal file
141
assets/controllers/shortcuts_controller.js
Normal file
|
@ -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();
|
||||
});
|
||||
}
|
||||
}
|
7
assets/controllers/sticky_nav_controller.js
Normal file
7
assets/controllers/sticky_nav_controller.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { Controller } from '@hotwired/stimulus';
|
||||
|
||||
export default class extends Controller {
|
||||
toggle() {
|
||||
this.element.classList.toggle('entry-nav-top--sticky');
|
||||
}
|
||||
}
|
12
assets/controllers/tag_controller.js
Normal file
12
assets/controllers/tag_controller.js
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
31
assets/controllers/topbar_controller.js
Normal file
31
assets/controllers/topbar_controller.js
Normal file
|
@ -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';
|
||||
}
|
||||
}
|
377
assets/index.js
377
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, initExport, initFilters, initRandom, 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
|
||||
$('.sidenav').sidenav();
|
||||
$('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();
|
||||
|
||||
initFilters();
|
||||
initExport();
|
||||
initRandom();
|
||||
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,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
});
|
|
@ -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;
|
||||
}
|
||||
});
|
||||
});
|
|
@ -1,86 +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 initFilters() {
|
||||
// no display if filters not available
|
||||
if ($('div').is('#filters')) {
|
||||
$('#button_filters').show();
|
||||
$('#filters.sidenav').sidenav({ edge: 'right' });
|
||||
$('#clear_form_filters').on('click', () => {
|
||||
$('#filters input').val('');
|
||||
$('#filters :checked').removeAttr('checked');
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function initExport() {
|
||||
// no display if export not available
|
||||
if ($('div').is('#export')) {
|
||||
$('#button_export').show();
|
||||
$('#export.sidenav').sidenav({ edge: 'right' });
|
||||
}
|
||||
}
|
||||
|
||||
function initRandom() {
|
||||
// no display if export (ie: entries) not available
|
||||
if ($('div').is('#export')) {
|
||||
$('#button_random').show();
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
initExport,
|
||||
initFilters,
|
||||
initRandom,
|
||||
initPreviewText,
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -143,14 +143,6 @@ nav {
|
|||
margin: 0 1%;
|
||||
}
|
||||
|
||||
.button-filters {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.button-export {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.entry-nav-top--sticky {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use Doctrine\ORM\EntityManagerInterface;
|
|||
use Doctrine\ORM\QueryBuilder;
|
||||
use Pagerfanta\Adapter\ArrayAdapter;
|
||||
use Pagerfanta\Exception\OutOfRangeCurrentPageException;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
@ -136,6 +137,7 @@ class TagController extends AbstractController
|
|||
* @param int $page
|
||||
*
|
||||
* @Route("/tag/list/{slug}/{page}", name="tag_entries", methods={"GET"}, defaults={"page" = "1"})
|
||||
* @IsGranted("LIST_ENTRIES")
|
||||
* @ParamConverter("tag", options={"mapping": {"slug": "slug"}})
|
||||
*
|
||||
* @return Response
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="tabs-container col s12">
|
||||
<ul class="tabs">
|
||||
<ul class="tabs" data-controller="materialize--tabs">
|
||||
<li class="tab col s12 m6 l3"><a class="active" href="#set1">{{ 'config.tab_menu.settings'|trans }}</a></li>
|
||||
<li class="tab col s12 m6 l3"><a href="#set2">{{ 'config.tab_menu.feed'|trans }}</a></li>
|
||||
<li class="tab col s12 m6 l3"><a href="#set3">{{ 'config.tab_menu.user_info'|trans }}</a></li>
|
||||
|
@ -21,7 +21,7 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="set1" class="col s12">
|
||||
<div id="set1" class="col s12" data-controller="config">
|
||||
{{ form_start(form.config) }}
|
||||
{{ form_errors(form.config) }}
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
|||
{{ form_label(form.config.items_per_page) }}
|
||||
</div>
|
||||
<div class="input-field col s1">
|
||||
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_items_per_page'|trans }}">
|
||||
<a href="#" data-controller="materialize--tooltip" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_items_per_page'|trans }}">
|
||||
<i class="material-icons">live_help</i>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -45,7 +45,7 @@
|
|||
{{ form_label(form.config.display_thumbnails, null, {'label_attr': {'class': 'settings-checkbox-label'}}) }}
|
||||
</div>
|
||||
<div class="input-field col s1">
|
||||
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_display_thumbnails'|trans }}">
|
||||
<a href="#" data-controller="materialize--tooltip" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_display_thumbnails'|trans }}">
|
||||
<i class="material-icons">live_help</i>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -62,14 +62,14 @@
|
|||
</p>
|
||||
</div>
|
||||
<div class="input-field col s1">
|
||||
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_reading_speed'|trans }}">
|
||||
<a href="#" data-controller="materialize--tooltip" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_reading_speed'|trans }}">
|
||||
<i class="material-icons">live_help</i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="input-field col s11">
|
||||
<div class="input-field col s11" data-controller="materialize--form-select">
|
||||
{{ form_errors(form.config.action_mark_as_read) }}
|
||||
{{ form_widget(form.config.action_mark_as_read) }}
|
||||
{{ form_label(form.config.action_mark_as_read) }}
|
||||
|
@ -77,13 +77,13 @@
|
|||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="input-field col s11">
|
||||
<div class="input-field col s11" data-controller="materialize--form-select">
|
||||
{{ form_errors(form.config.language) }}
|
||||
{{ form_widget(form.config.language) }}
|
||||
{{ form_label(form.config.language) }}
|
||||
</div>
|
||||
<div class="input-field col s1">
|
||||
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_language'|trans }}">
|
||||
<a href="#" data-controller="materialize--tooltip" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_language'|trans }}">
|
||||
<i class="material-icons">live_help</i>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -100,7 +100,7 @@
|
|||
</p>
|
||||
</div>
|
||||
<div class="input-field col s1">
|
||||
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_pocket_consumer_key'|trans }}">
|
||||
<a href="#" data-controller="materialize--tooltip" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_pocket_consumer_key'|trans }}">
|
||||
<i class="material-icons">live_help</i>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -110,31 +110,31 @@
|
|||
<div class="input-field col s12">
|
||||
<h5>{{ 'config.form_settings.android_configuration'|trans }}</h5>
|
||||
<a href="wallabag://{{ app.user.username }}@{{ wallabag_url }}" class="waves-effect waves-light btn hide-on-large-only">{{ 'config.form_settings.android_instruction'|trans }}</a>
|
||||
<img class="hide-on-med-and-down jr-qrcode" alt="{{ 'config.otp.app.qrcode_label'|trans }}" data-url="wallabag://{{ app.user.username }}@{{ wallabag_url }}" />
|
||||
<img data-controller="qrcode" data-qrcode-url-value="wallabag://{{ app.user.username }}@{{ wallabag_url }}" class="hide-on-med-and-down" alt="{{ 'config.otp.app.qrcode_label'|trans }}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5>{{ 'config.tab_menu.article_display'|trans }}</h5>
|
||||
|
||||
<div class="row">
|
||||
<div class="input-field col s5">
|
||||
<div class="input-field col s5" data-controller="materialize--form-select">
|
||||
{{ 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) }}
|
||||
</div>
|
||||
<div class="input-field col s1">
|
||||
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_font'|trans }}">
|
||||
<a href="#" data-controller="materialize--tooltip" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_font'|trans }}">
|
||||
<i class="material-icons">live_help</i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="input-field col s5">
|
||||
{{ 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'}}) }}
|
||||
</div>
|
||||
<div class="input-field col s1">
|
||||
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_lineheight'|trans }}">
|
||||
<a href="#" data-controller="materialize--tooltip" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_lineheight'|trans }}">
|
||||
<i class="material-icons">live_help</i>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -143,22 +143,22 @@
|
|||
<div class="row">
|
||||
<div class="input-field col s5">
|
||||
{{ 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'}}) }}
|
||||
</div>
|
||||
<div class="input-field col s1">
|
||||
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_fontsize'|trans }}">
|
||||
<a href="#" data-controller="materialize--tooltip" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_fontsize'|trans }}">
|
||||
<i class="material-icons">live_help</i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="input-field col s5">
|
||||
{{ 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'}}) }}
|
||||
</div>
|
||||
<div class="input-field col s1">
|
||||
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_maxwidth'|trans }}">
|
||||
<a href="#" data-controller="materialize--tooltip" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_settings.help_maxwidth'|trans }}">
|
||||
<i class="material-icons">live_help</i>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -166,8 +166,8 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="input-field col s12">
|
||||
<div id="preview-article">
|
||||
<article id="preview-content">
|
||||
<div id="preview-article" data-config-target="previewArticle">
|
||||
<article id="preview-content" data-config-target="previewContent">
|
||||
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.
|
||||
</article>
|
||||
</div>
|
||||
|
|
|
@ -15,17 +15,17 @@
|
|||
<p>{{ 'config.otp.app.two_factor_code_description_2'|trans }}</p>
|
||||
|
||||
<p>
|
||||
<img class="hide-on-med-and-down jr-qrcode" data-url="{{ qr_code|raw }}" />
|
||||
<img data-controller="qrcode" data-qrcode-url-value="{{ qr_code|raw }}" class="hide-on-med-and-down" />
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{{ 'config.otp.app.two_factor_code_description_5'|trans }} <pre>{{ secret }}</pre>
|
||||
</p>
|
||||
<div data-controller="highlight">
|
||||
{{ 'config.otp.app.two_factor_code_description_5'|trans }} <pre><code>{{ secret }}</code></pre>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>{{ 'config.otp.app.two_factor_code_description_3'|trans }}</p>
|
||||
|
||||
<p><pre>{{ backupCodes|join("\n") }}</pre></p>
|
||||
<div data-controller="highlight"><pre><code>{{ backupCodes|join("\n") }}</code></pre></div>
|
||||
</li>
|
||||
<li>
|
||||
<p>{{ 'config.otp.app.two_factor_code_description_4'|trans }}</p>
|
||||
|
|
|
@ -18,14 +18,14 @@
|
|||
<td>{{ 'developer.client_parameter.field_id'|trans }}</td>
|
||||
<td>
|
||||
<strong><code>{{ client_id }}</code></strong>
|
||||
<button class="btn" data-clipboard-text="{{ client_id }}">{{ 'developer.client.copy_to_clipboard'|trans }}</button>
|
||||
<button class="btn" data-controller="clipboard" data-clipboard-text="{{ client_id }}">{{ 'developer.client.copy_to_clipboard'|trans }}</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ 'developer.client_parameter.field_secret'|trans }}</td>
|
||||
<td>
|
||||
<strong><code>{{ client_secret }}</code></strong>
|
||||
<button class="btn" data-clipboard-text="{{ client_secret }}">{{ 'developer.client.copy_to_clipboard'|trans }}</button>
|
||||
<button class="btn" data-controller="clipboard" data-clipboard-text="{{ client_secret }}">{{ 'developer.client.copy_to_clipboard'|trans }}</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -12,16 +12,16 @@
|
|||
<p>{{ 'developer.howto.description.paragraph_2'|trans }}</p>
|
||||
<p>{{ 'developer.howto.description.paragraph_3'|trans({'%link%': path('developer_create_client')})|raw }}</p>
|
||||
<p>{{ 'developer.howto.description.paragraph_4'|trans }}</p>
|
||||
<p>
|
||||
<div data-controller="highlight">
|
||||
<pre><code class="language-bash">http POST {{ wallabag_url }}/oauth/v2/token \
|
||||
grant_type=password \
|
||||
client_id=12_5um6nz50ceg4088c0840wwc0kgg44g00kk84og044ggkscso0k \
|
||||
client_secret=3qd12zpeaxes8cwg8c0404g888co4wo8kc4gcw0occww8cgw4k \
|
||||
username=yourUsername \
|
||||
password=yourPassw0rd</code></pre>
|
||||
</p>
|
||||
</div>
|
||||
<p>{{ 'developer.howto.description.paragraph_5'|trans }}</p>
|
||||
<p>
|
||||
<div data-controller="highlight">
|
||||
<pre><code class="language-bash">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"
|
||||
}</code></pre>
|
||||
</p>
|
||||
</div>
|
||||
<p>{{ 'developer.howto.description.paragraph_6'|trans }}</p>
|
||||
<p>
|
||||
<div data-controller="highlight">
|
||||
<pre><code class="language-bash">http GET {{ wallabag_url }}/api/entries.json \
|
||||
"Authorization:Bearer ZWFjNjA3ZWMwYWVmYzRkYTBlMmQ3NTllYmVhOGJiZDE0ZTg1NjE4MjczOTVlNzM0ZTRlMWQ0MmRlMmYwNTk5Mw"</code></pre>
|
||||
</p>
|
||||
</div>
|
||||
<p>{{ 'developer.howto.description.paragraph_7'|trans }}</p>
|
||||
<p>{{ 'developer.howto.description.paragraph_8'|trans({'%link%': path('nelmio_api_doc.swagger_ui')})|raw }}</p>
|
||||
<p><a href="{{ path('developer') }}" class="waves-effect waves-light grey btn">{{ 'developer.howto.back'|trans }}</a></p>
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
<h4>{{ 'developer.existing_clients.title'|trans }}</h4>
|
||||
{% if clients %}
|
||||
<ul class="collapsible" data-collapsible="expandable">
|
||||
<ul class="collapsible" data-controller="materialize--collapsible" data-materialize--collapsible-accordion-value="false">
|
||||
{% for client in clients %}
|
||||
<li>
|
||||
<div class="collapsible-header">{{ client.name }} - #{{ client.id }}</div>
|
||||
|
@ -35,14 +35,14 @@
|
|||
<td>{{ 'developer.existing_clients.field_id'|trans }}</td>
|
||||
<td>
|
||||
<strong><code>{{ client.clientId }}</code></strong>
|
||||
<button class="btn" data-clipboard-text="{{ client.clientId }}">{{ 'developer.client.copy_to_clipboard'|trans }}</button>
|
||||
<button class="btn" data-controller="clipboard" data-clipboard-text="{{ client.clientId }}">{{ 'developer.client.copy_to_clipboard'|trans }}</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ 'developer.existing_clients.field_secret'|trans }}</td>
|
||||
<td>
|
||||
<strong><code>{{ client.secret }}</code></strong>
|
||||
<button class="btn" data-clipboard-text="{{ client.secret }}">{{ 'developer.client.copy_to_clipboard'|trans }}</button>
|
||||
<button class="btn" data-controller="clipboard" data-clipboard-text="{{ client.secret }}">{{ 'developer.client.copy_to_clipboard'|trans }}</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
<label class="entry-checkbox">
|
||||
<input type="checkbox" class="entry-checkbox-input" data-js="entry-checkbox" name="entry-checkbox[]" value="{{ entry.id }}" />
|
||||
<input type="checkbox" class="entry-checkbox-input" name="entry-checkbox[]" value="{{ entry.id }}" data-batch-edit-target="item" />
|
||||
</label>
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
{% extends "layout.html.twig" %}
|
||||
|
||||
{% set has_filters = form is not null %}
|
||||
{% set has_exports = craue_setting('export_epub') or craue_setting('export_pdf') or craue_setting('export_json') or craue_setting('export_csv') or craue_setting('export_txt') or craue_setting('export_xml') or craue_setting('export_md') %}
|
||||
|
||||
{% block head %}
|
||||
{{ parent() }}
|
||||
{% if tag is defined and app.user.config.feedToken %}
|
||||
|
@ -18,6 +21,30 @@
|
|||
{% include "Entry/_title.html.twig" with {'filter': filter} %}
|
||||
{% endblock %}
|
||||
|
||||
{% block nav_panel_extra_actions %}
|
||||
{% if active_route %}
|
||||
<li>
|
||||
<a class="waves-effect js-random-action" data-controller="materialize--tooltip" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.random_entry'|trans }}" href="{{ path('random_entry', {'type': active_route}) }}">
|
||||
<i class="material-icons">casino</i>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if has_filters %}
|
||||
<li class="button-filters">
|
||||
<a class="nav-panel-menu sidenav-trigger js-filters-action" data-controller="materialize--tooltip" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.filter_entries'|trans }}" href="#" data-target="filters">
|
||||
<i class="material-icons">filter_list</i>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if has_exports %}
|
||||
<li class="button-export">
|
||||
<a class="nav-panel-menu sidenav-trigger js-export-action" data-controller="materialize--tooltip" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.export'|trans }}" href="#" data-target="export">
|
||||
<i class="material-icons">file_download</i>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% set current_path = path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')) %}
|
||||
{% set list_mode = app.user.config.listMode %}
|
||||
|
@ -26,15 +53,15 @@
|
|||
{% if current_route == 'homepage' %}
|
||||
{% set current_route = 'unread' %}
|
||||
{% endif %}
|
||||
<form name="form_mass_action" action="{{ path('mass_action', {redirect: current_path}) }}" method="post">
|
||||
<div class="results">
|
||||
<form name="form_mass_action" action="{{ path('mass_action', {redirect: current_path}) }}" method="post" data-controller="batch-edit entries-navigation">
|
||||
<div class="results" data-entries-navigation-target="paginationWrapper">
|
||||
<div class="nb-results">
|
||||
{{ 'entry.list.number_on_the_page'|trans({'%count%': entries.count}) }}
|
||||
{% if entries.count > 0 %}
|
||||
<a class="results-item" href="{{ path('switch_view_mode', {redirect: current_path}) }}"><i class="material-icons">{% if list_mode == 0 %}view_list{% else %}view_module{% endif %}</i></a>
|
||||
{% endif %}
|
||||
{% if entries.count > 0 and is_granted('EDIT_ENTRIES') %}
|
||||
<label for="mass-action-inputs-displayed" class="mass-action-toggle results-item tooltipped" data-position="right" data-delay="50" data-tooltip="{{ 'entry.list.toggle_mass_action'|trans }}"><i class="material-icons">library_add_check</i></label>
|
||||
<label for="mass-action-inputs-displayed" class="mass-action-toggle results-item" data-controller="materialize--tooltip" data-position="right" data-delay="50" data-tooltip="{{ 'entry.list.toggle_mass_action'|trans }}"><i class="material-icons">library_add_check</i></label>
|
||||
{% endif %}
|
||||
{% if app.user.config.feedToken %}
|
||||
{% include "Entry/_feed_link.html.twig" %}
|
||||
|
@ -50,22 +77,22 @@
|
|||
<input id="mass-action-inputs-displayed" class="toggle-checkbox" type="checkbox" />
|
||||
<div class="mass-action">
|
||||
<div class="mass-action-group">
|
||||
<input type="checkbox" class="entry-checkbox-input" data-toggle="[data-js='entry-checkbox']" data-js="checkboxes-toggle" />
|
||||
<input type="checkbox" class="entry-checkbox-input" data-action="batch-edit#toggleSelection" />
|
||||
<button class="mass-action-button btn cyan darken-1" type="submit" name="toggle-read" title="{{ 'entry.list.toogle_as_read'|trans }}"><i class="material-icons">done</i></button>
|
||||
<button class="mass-action-button btn cyan darken-1" type="submit" name="toggle-star" title="{{ 'entry.list.toogle_as_star'|trans }}" ><i class="material-icons">star</i></button>
|
||||
<button class="mass-action-button btn cyan darken-1" type="submit" name="delete" onclick="return confirm('{{ 'entry.confirm.delete_entries'|trans|escape('js') }}')" title="{{ 'entry.list.delete'|trans }}"><i class="material-icons">delete</i></button>
|
||||
</div>
|
||||
|
||||
<div class="mass-action-tags">
|
||||
<button class="btn cyan darken-1 mass-action-button mass-action-button--tags" type="submit" name="tag" title="{{ 'entry.list.add_tags'|trans }}"><i class="material-icons">label</i></button>
|
||||
<input type="text" class="mass-action-tags-input" name="tags" placeholder="{{ 'entry.list.mass_action_tags_input_placeholder'|trans }}" />
|
||||
<button class="btn cyan darken-1 mass-action-button mass-action-button--tags" type="submit" name="tag" title="{{ 'entry.list.add_tags'|trans }}" data-batch-edit-target="tagAction"><i class="material-icons">label</i></button>
|
||||
<input type="text" class="mass-action-tags-input" name="tags" placeholder="{{ 'entry.list.mass_action_tags_input_placeholder'|trans }}" data-action="keydown.enter->batch-edit#tagSelection:prevent:stop" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ol class="entries {% if list_mode == 1 %}collection{% else %}row entries-row data{% endif %}">
|
||||
|
||||
{% for entry in entries %}
|
||||
<li id="entry-{{ entry.id|e }}" class="{% if list_mode != 0 %}col collection-item{% endif %} s12" data-entry-id="{{ entry.id|e }}" data-test="entry">
|
||||
<li id="entry-{{ entry.id|e }}" class="{% if list_mode != 0 %}col collection-item{% endif %} s12" data-entry-id="{{ entry.id|e }}" data-test="entry" data-entries-navigation-target="card">
|
||||
{% 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/' %}
|
||||
|
@ -86,7 +113,8 @@
|
|||
{% endif %}
|
||||
|
||||
<!-- Export -->
|
||||
<div id="export" class="sidenav">
|
||||
{% if has_exports %}
|
||||
<div id="export" class="sidenav" data-controller="materialize--sidenav" data-materialize--sidenav-edge-value="right">
|
||||
{% set current_tag = null %}
|
||||
{% if tag is defined %}
|
||||
{% set current_tag = tag.slug %}
|
||||
|
@ -108,10 +136,11 @@
|
|||
{% if craue_setting('export_md') %}<li class="bold"><a class="waves-effect" href="{{ path('export_entries', {'category': current_route, 'format': 'md', 'tag': current_tag, 'search_entry[term]': export_search_term, 'currentRoute': previous_route, 'entry': entry}) }}">Markdown</a></li>{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Filters -->
|
||||
{% if form is not null and is_granted('LIST_ENTRIES') %}
|
||||
<div id="filters" class="sidenav">
|
||||
{% if has_filters %}
|
||||
<div id="filters" class="sidenav" data-controller="materialize--sidenav" data-materialize--sidenav-edge-value="right">
|
||||
<form action="{{ path('all') }}">
|
||||
|
||||
<h4 class="center">{{ 'entry.filters.title'|trans }}</h4>
|
||||
|
@ -233,7 +262,7 @@
|
|||
</div>
|
||||
|
||||
<div class="col s6">
|
||||
<a href="#!" class="center waves-effect waves-green btn-flat" id="clear_form_filters">{{ 'entry.filters.action.clear'|trans }}</a>
|
||||
<button type="reset" class="center waves-effect waves-green btn-flat">{{ 'entry.filters.action.clear'|trans }}</button>
|
||||
</div>
|
||||
|
||||
<div class="col s6">
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
|
||||
{% block menu %}
|
||||
<div class="progress">
|
||||
<div class="determinate"></div>
|
||||
<div class="determinate" data-controller="scroll-indicator" data-action="scroll@window->scroll-indicator#updateWidth"></div>
|
||||
</div>
|
||||
<nav class="hide-on-large-only js-entry-nav-top">
|
||||
<nav class="hide-on-large-only" data-controller="sticky-nav" data-action="materialize--fab:click@window->sticky-nav#toggle">
|
||||
<div class="nav-panel-item cyan darken-1">
|
||||
<ul>
|
||||
<li>
|
||||
|
@ -42,7 +42,7 @@
|
|||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<ul id="slide-out" class="left-bar collapsible sidenav sidenav-fixed reader-mode" data-collapsible="accordion">
|
||||
<ul id="slide-out" class="left-bar collapsible sidenav sidenav-fixed reader-mode" data-controller="materialize--sidenav materialize--collapsible leftbar">
|
||||
<li class="bold border-bottom hide-on-med-and-down">
|
||||
<a class="waves-effect collapsible-header" href="{{ path('homepage') }}">
|
||||
<i class="material-icons small">arrow_back</i>
|
||||
|
@ -52,7 +52,7 @@
|
|||
</li>
|
||||
|
||||
<li class="bold border-bottom hide-on-med-and-down">
|
||||
<a class="waves-effect collapsible-header original" href="{{ entry.url|e }}" target="_blank" rel="noopener">
|
||||
<a class="waves-effect collapsible-header original" href="{{ entry.url|e }}" target="_blank" rel="noopener" data-shortcuts-target="openOriginal">
|
||||
<i class="material-icons small">link</i>
|
||||
<span>{{ 'entry.view.left_menu.view_original_article'|trans }}</span>
|
||||
</a>
|
||||
|
@ -76,7 +76,7 @@
|
|||
|
||||
{% if is_granted('ARCHIVE', entry) %}
|
||||
<li class="bold hide-on-med-and-down">
|
||||
<a class="waves-effect collapsible-header markasread" title="{{ mark_as_read_label|trans }}" href="{{ path('archive_entry', {'id': entry.id, redirect: current_path}) }}" id="markAsRead">
|
||||
<a class="waves-effect collapsible-header markasread" title="{{ mark_as_read_label|trans }}" href="{{ path('archive_entry', {'id': entry.id, redirect: current_path}) }}" id="markAsRead" data-shortcuts-target="markAsRead">
|
||||
<i class="material-icons small">{% if entry.isArchived == 0 %}done{% else %}unarchive{% endif %}</i>
|
||||
<span>{{ mark_as_read_label|trans }}</span>
|
||||
</a>
|
||||
|
@ -86,7 +86,7 @@
|
|||
|
||||
{% if is_granted('STAR', entry) %}
|
||||
<li class="bold hide-on-med-and-down">
|
||||
<a class="waves-effect collapsible-header favorite" title="{{ 'entry.view.left_menu.set_as_starred'|trans }}" href="{{ path('star_entry', {'id': entry.id, redirect: current_path}) }}" id="setFav">
|
||||
<a class="waves-effect collapsible-header favorite" title="{{ 'entry.view.left_menu.set_as_starred'|trans }}" href="{{ path('star_entry', {'id': entry.id, redirect: current_path}) }}" id="setFav" data-shortcuts-target="markAsFavorite">
|
||||
<i class="material-icons small">{% if entry.isStarred == 0 %}star_outline{% else %}star{% endif %}</i>
|
||||
<span>{{ 'entry.view.left_menu.set_as_starred'|trans }}</span>
|
||||
</a>
|
||||
|
@ -96,7 +96,7 @@
|
|||
|
||||
{% if is_granted('DELETE', entry) %}
|
||||
<li class="bold border-bottom">
|
||||
<a class="waves-effect collapsible-header delete" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" title="{{ 'entry.view.left_menu.delete'|trans }}" href="{{ path('delete_entry', {'id': entry.id, redirect: current_path}) }}">
|
||||
<a class="waves-effect collapsible-header delete" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" title="{{ 'entry.view.left_menu.delete'|trans }}" href="{{ path('delete_entry', {'id': entry.id, redirect: current_path}) }}" data-shortcuts-target="deleteEntry">
|
||||
<i class="material-icons small">delete</i>
|
||||
<span>{{ 'entry.view.left_menu.delete'|trans }}</span>
|
||||
</a>
|
||||
|
@ -105,7 +105,7 @@
|
|||
{% endif %}
|
||||
|
||||
<li class="bold border-bottom">
|
||||
<a class="waves-effect collapsible-header" id="nav-btn-add-tag">
|
||||
<a class="waves-effect collapsible-header" id="nav-btn-add-tag" data-action="click->materialize--sidenav#close click->leftbar#toggleAddTagForm">
|
||||
<i class="material-icons small">label_outline</i>
|
||||
<span>{{ 'entry.view.left_menu.add_a_tag'|trans }}</span>
|
||||
</a>
|
||||
|
@ -119,19 +119,19 @@
|
|||
</a>
|
||||
<ul class="collapsible-body">
|
||||
<li>
|
||||
<a href="#" class="js-theme-toggle" data-theme="light">
|
||||
<a href="#" data-action="click->dark-theme#useLight:prevent">
|
||||
<i class="theme-toggle-icon material-icons tiny">brightness_high</i>
|
||||
<span>{{ 'entry.view.left_menu.theme_toggle_light'|trans }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="js-theme-toggle" data-theme="dark">
|
||||
<a href="#" data-action="click->dark-theme#useDark:prevent">
|
||||
<i class="theme-toggle-icon material-icons tiny">brightness_low</i>
|
||||
<span>{{ 'entry.view.left_menu.theme_toggle_dark'|trans }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="js-theme-toggle" data-theme="auto">
|
||||
<a href="#" data-action="click->dark-theme#useAuto:prevent">
|
||||
<i class="theme-toggle-icon material-icons tiny">brightness_auto</i>
|
||||
<span>{{ 'entry.view.left_menu.theme_toggle_auto'|trans }}</span>
|
||||
</a>
|
||||
|
@ -260,7 +260,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="article" class="article">
|
||||
<div id="article" class="article" data-controller="scroll-storage" data-scroll-storage-entry-id-value="{{ entry.id }}" data-action="scroll@window->scroll-storage#saveScroll">
|
||||
<header class="mbm">
|
||||
<h1>
|
||||
<span{% if entry.language is defined and entry.language is not null %} lang="{{ entry.getHTMLLanguage() }}"{% endif %}>{{ entry.title|striptags|default('entry.default_title'|trans)|raw }}</span>
|
||||
|
@ -317,16 +317,24 @@
|
|||
{% include "Entry/_tags.html.twig" with {'tags': entry.tags, 'entryId': entry.id, 'withRemove': true} only %}
|
||||
</div>
|
||||
|
||||
<div class="input-field nav-panel-add-tag" style="display: none">
|
||||
<div class="input-field nav-panel-add-tag hidden" data-controller="add-tag" data-action="leftbar:toggleAddTagForm@window->add-tag#toggle">
|
||||
{{ render(controller('Wallabag\\Controller\\TagController::addTagFormAction', {'id': entry.id})) }}
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
<article{% if entry.language is defined and entry.language is not null %} lang="{{ entry.getHTMLLanguage() }}"{% endif %}>
|
||||
<article
|
||||
{% if entry.language is defined and entry.language is not null %} lang="{{ entry.getHTMLLanguage() }}"{% endif %}
|
||||
data-controller="highlight annotations"
|
||||
data-annotations-entry-id-value="{{ entry.id }}"
|
||||
data-annotations-create-url-value="{{ path('annotations_post_annotation', {'entry': entry.id}) }}"
|
||||
data-annotations-update-url-value="{{ path('annotations_put_annotation', {'annotation': 'idAnnotation'}) }}"
|
||||
data-annotations-destroy-url-value="{{ path('annotations_delete_annotation', {'annotation': 'idAnnotation'}) }}"
|
||||
data-annotations-search-url-value="{{ path('annotations_get_annotations', {'entry': entry.id}) }}"
|
||||
>
|
||||
{{ entry.content|raw }}
|
||||
</article>
|
||||
|
||||
<div class="fixed-action-btn js-fixed-action-btn horizontal click-to-toggle hide-on-large-only">
|
||||
<div class="fixed-action-btn horizontal click-to-toggle hide-on-large-only" data-controller="materialize--fab" data-action="scroll@window->materialize--fab#autoDisplay click->materialize--fab#click">
|
||||
<a class="btn-floating btn-large" data-toggle="actions">
|
||||
<i class="material-icons">menu</i>
|
||||
</a>
|
||||
|
@ -343,19 +351,6 @@
|
|||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script id="annotationroutes" type="application/json">
|
||||
{
|
||||
"prefix": "",
|
||||
"urls": {
|
||||
"create": "{{ path('annotations_post_annotation', {'entry': entry.id}) }}",
|
||||
"update": "{{ path('annotations_put_annotation', {'annotation': 'idAnnotation'}) }}",
|
||||
"destroy": "{{ path('annotations_delete_annotation', {'annotation': 'idAnnotation'}) }}",
|
||||
"search": "{{ path('annotations_get_annotations', {'entry': entry.id}) }}"
|
||||
},
|
||||
"entryId": "{{ entry.id }}"
|
||||
}</script>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block footer %}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<form class="input-field nav-panel-item nav-panel-add" style="display: none" name="entry" method="post" action="{{ path('new_entry') }}">
|
||||
<form class="input-field nav-panel-item nav-panel-add" style="display: none" name="entry" method="post" action="{{ path('new_entry') }}" data-topbar-target="addUrl" data-action="topbar#submittingUrl">
|
||||
{% if form_errors(form) %}
|
||||
<span class="black-text">{{ form_errors(form) }}</span>
|
||||
{% endif %}
|
||||
|
@ -8,8 +8,8 @@
|
|||
<span class="black-text">{{ form_errors(form.url) }}</span>
|
||||
{% endif %}
|
||||
|
||||
{{ form_widget(form.url, {'attr': {'autocomplete': 'off', 'placeholder': 'entry.new.placeholder'}}) }}
|
||||
<i class="material-icons close" aria-label="clear" role="button"></i>
|
||||
{{ form_widget(form.url, {'attr': {'autocomplete': 'off', 'placeholder': 'entry.new.placeholder', 'data-topbar-target': 'addUrlInput'}}) }}
|
||||
<i class="material-icons close" aria-label="clear" role="button" data-action="click->topbar#showActions" data-shortcuts-target="showActions"></i>
|
||||
|
||||
{{ form_rest(form) }}
|
||||
</form>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<form class="input-field nav-panel-item nav-panel-search" style="display: none" name="search" method="GET" action="{{ path('search') }}">
|
||||
<form class="input-field nav-panel-item nav-panel-search" style="display: none" name="search" method="GET" action="{{ path('search') }}" data-topbar-target="search">
|
||||
{% if form_errors(form) %}
|
||||
<span class="black-text">{{ form_errors(form) }}</span>
|
||||
{% endif %}
|
||||
|
@ -10,8 +10,8 @@
|
|||
|
||||
<input type="hidden" name="currentRoute" value="{{ currentRoute }}" />
|
||||
|
||||
{{ form_widget(form.term, {'attr': {'autocomplete': 'off', 'placeholder': 'entry.search.placeholder'}}) }}
|
||||
<i class="material-icons close" aria-label="clear" role="button"></i>
|
||||
{{ form_widget(form.term, {'attr': {'autocomplete': 'off', 'placeholder': 'entry.search.placeholder', 'data-topbar-target': 'searchInput'}}) }}
|
||||
<i class="material-icons close" aria-label="clear" role="button" data-action="click->topbar#showActions" data-shortcuts-target="showActions"></i>
|
||||
|
||||
{{ form_rest(form) }}
|
||||
</form>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{% if nbRedisMessages is defined and nbRedisMessages > 0 %}
|
||||
<p class="material-toast hidden">Messages in queue: {{ nbRedisMessages }}</p>
|
||||
<p class="hidden" data-controller="materialize--toast">Messages in queue: {{ nbRedisMessages }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% if nbRabbitMessages is defined and nbRabbitMessages > 0 %}
|
||||
<p class="material-toast hidden">Messages in queue: {{ nbRabbitMessages }}</p>
|
||||
<p class="hidden" data-controller="materialize--toast">Messages in queue: {{ nbRabbitMessages }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% if redisNotInstalled is defined and redisNotInstalled %}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="tabs-container col s12">
|
||||
<ul class="tabs">
|
||||
<ul class="tabs" data-controller="materialize--tabs">
|
||||
<li class="tab col s12 m6 l3"><a class="active" href="#set1">{{ 'about.top_menu.who_behind_wallabag'|trans }}</a></li>
|
||||
<li class="tab col s12 m6 l3"><a href="#set2">{{ 'about.top_menu.getting_help'|trans }}</a></li>
|
||||
<li class="tab col s12 m6 l3"><a href="#set3">{{ 'about.top_menu.helping'|trans }}</a></li>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="tabs-container col s12">
|
||||
<ul class="tabs">
|
||||
<ul class="tabs" data-controller="materialize--tabs">
|
||||
<li class="tab col s12 m6 l3"><a class="active" href="#set1">{{ 'howto.tab_menu.add_link'|trans }}</a></li>
|
||||
<li class="tab col s12 m6 l3"><a href="#set2">{{ 'howto.tab_menu.shortcuts'|trans }}</a></li>
|
||||
</ul>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<span class="black-text">{{ form_errors(form.label) }}</span>
|
||||
{% endif %}
|
||||
|
||||
{{ form_widget(form.label, {'attr': {'autocomplete': 'off'}}) }}
|
||||
{{ form_widget(form.label, {'attr': {'autocomplete': 'off', 'data-add-tag-target': 'input'}}) }}
|
||||
|
||||
{{ form_widget(form.add, {'attr': {'class': 'btn waves-effect waves-light tags-add-form-submit'}}) }}
|
||||
{{ form_widget(form._token) }}
|
||||
|
|
|
@ -17,18 +17,19 @@
|
|||
</li>
|
||||
{% endif %}
|
||||
{% for tag in tags %}
|
||||
<li title="{{ tag.label }} ({{ tag.nbEntries }})" id="tag-{{ tag.id }}" class="chip">
|
||||
<a href="{{ path('tag_entries', {'slug': tag.slug}) }}" class="card-tag-link" data-handle="tag-link">
|
||||
<li title="{{ tag.label }} ({{ tag.nbEntries }})" id="tag-{{ tag.id }}" class="chip" data-controller="tag">
|
||||
<a href="{{ path('tag_entries', {'slug': tag.slug}) }}" class="card-tag-link" data-tag-target="link">
|
||||
{{ tag.label }} ({{ tag.nbEntries }})
|
||||
</a>
|
||||
{% if renameForms is defined and renameForms[tag.id] is defined %}
|
||||
<form class="card-tag-form hidden" data-handle="tag-rename-form" action="{{ path('tag_rename', {'slug': tag.slug, redirect: current_path}) }}" method="POST">
|
||||
{{ form_widget(renameForms[tag.id].label, {'attr': {'value': tag.label}}) }}
|
||||
<form class="card-tag-form hidden" data-tag-target="form" action="{{ path('tag_rename', {'slug': tag.slug, redirect: current_path}) }}" method="POST">
|
||||
{{ form_widget(renameForms[tag.id].label, {'attr': {'value': tag.label, 'data-tag-target': 'input'}}) }}
|
||||
{{ form_rest(renameForms[tag.id]) }}
|
||||
<button type="submit"><i class="material-icons">done</i></button>
|
||||
</form>
|
||||
<a class="card-tag-icon card-tag-rename" data-handler="tag-rename" href="javascript:void(0);">
|
||||
<button type="button" data-tag-target="edit" data-action="tag#showForm">
|
||||
<i class="material-icons">mode_edit</i>
|
||||
</a>
|
||||
</button>
|
||||
{% endif %}
|
||||
<a id="delete-{{ tag.slug }}" href="{{ path('tag_delete', {'slug': tag.slug, redirect: current_path}) }}" class="card-tag-icon card-tag-delete" onclick="return confirm('{{ 'tag.confirm.delete'|trans({'%name%': tag.label})|escape('js') }}')">
|
||||
<i class="material-icons">delete</i>
|
||||
|
|
|
@ -48,16 +48,16 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="row" data-controller="fake-radio">
|
||||
<div class="input-field col s12">
|
||||
<label for="{{ edit_form.emailTwoFactor.vars.id }}">
|
||||
{{ form_widget(edit_form.emailTwoFactor) }}
|
||||
{{ form_widget(edit_form.emailTwoFactor, {attr: {'data-fake-radio-target': 'emailTwoFactor', 'data-action': 'fake-radio#uncheckGoogle'}}) }}
|
||||
<span>{{ edit_form.emailTwoFactor.vars.label|trans }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="input-field col s12">
|
||||
<label for="{{ edit_form.googleTwoFactor.vars.id }}">
|
||||
{{ form_widget(edit_form.googleTwoFactor) }}
|
||||
{{ form_widget(edit_form.googleTwoFactor, {attr: {'data-fake-radio-target': 'googleTwoFactor', 'data-action': 'fake-radio#uncheckEmail'}}) }}
|
||||
<span>{{ edit_form.googleTwoFactor.vars.label|trans }}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<!--[if lte IE 7]><html class="no-js ie7 ie67 ie678"{% if lang is not empty %} lang="{{ lang }}"{% endif %}><![endif]-->
|
||||
<!--[if IE 8]><html class="no-js ie8 ie678"{% if lang is not empty %} lang="{{ lang }}"{% endif %}><![endif]-->
|
||||
<!--[if gt IE 8]><html class="no-js"{% if lang is not empty %} lang="{{ lang }}"{% endif %}><![endif]-->
|
||||
<html{% if lang is not empty %} class="{{ theme_class() }}" lang="{{ lang }}"{% endif %}>
|
||||
<html{% if lang is not empty %} lang="{{ lang }}"{% endif %} class="{{ theme_class() }}" data-controller="dark-theme shortcuts" data-shortcuts-entries-navigation-outlet="[data-controller~='entries-navigation']">
|
||||
<head>
|
||||
{% block head %}
|
||||
<meta name="viewport" content="initial-scale=1.0">
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="div_tabs col s12">
|
||||
<ul class="tabs">
|
||||
<ul class="tabs" data-controller="materialize--tabs">
|
||||
{% for section in sections|craue_sortSections %}
|
||||
<li class="tab col s12 m6 l3"><a href="#set-{{ section }}">{{ section|trans({}, 'CraueConfigBundle') }}</a></li>
|
||||
{% endfor %}
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
<div class="card-content">
|
||||
|
||||
{% if error %}
|
||||
<p class="material-toast hidden">{{ error.messageKey|trans(error.messageData, 'security') }}</p>
|
||||
<p class="hidden" data-controller="materialize--toast">{{ error.messageKey|trans(error.messageData, 'security') }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% for flash_message in app.session.flashbag.get('notice') %}
|
||||
<p class="material-toast hidden">{{ flash_message }}</p>
|
||||
<p class="hidden" data-controller="materialize--toast">{{ flash_message }}</p>
|
||||
{% endfor %}
|
||||
|
||||
<div class="row">
|
||||
|
|
|
@ -1,5 +1,23 @@
|
|||
{% extends "base.html.twig" %}
|
||||
|
||||
{% set current_route = app.request.attributes.get('_route') %}
|
||||
{% set current_route_from_query_params = app.request.query.get('currentRoute') %}
|
||||
|
||||
{% set active_route = null %}
|
||||
{% if current_route == 'all' or current_route_from_query_params == 'all' %}
|
||||
{% set active_route = 'all' %}
|
||||
{% elseif current_route == 'annotated' or current_route_from_query_params == 'annotated' %}
|
||||
{% set active_route = 'annotated' %}
|
||||
{% elseif current_route == 'archive' or current_route_from_query_params == 'archive' %}
|
||||
{% set active_route = 'archive' %}
|
||||
{% elseif current_route == 'starred' or current_route_from_query_params == 'starred' %}
|
||||
{% set active_route = 'starred' %}
|
||||
{% elseif current_route == 'unread' or current_route == 'homepage' or current_route_from_query_params == 'unread' %}
|
||||
{% set active_route = 'unread' %}
|
||||
{% elseif current_route == 'untagged' %}
|
||||
{% set active_route = 'untagged' %}
|
||||
{% endif %}
|
||||
|
||||
{% block css %}
|
||||
{{ parent() }}
|
||||
|
||||
|
@ -17,7 +35,7 @@
|
|||
|
||||
{% block messages %}
|
||||
{% for flash_message in app.session.flashbag.get('notice') %}
|
||||
<p class="material-toast hidden">{{ flash_message|trans }}</p>
|
||||
<p class="hidden" data-controller="materialize--toast">{{ flash_message|trans }}</p>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
|
@ -25,7 +43,7 @@
|
|||
|
||||
{% block menu %}
|
||||
<nav class="cyan darken-1">
|
||||
<ul id="slide-out" class="left-bar sidenav sidenav-fixed">
|
||||
<ul id="slide-out" class="left-bar sidenav sidenav-fixed" data-controller="materialize--sidenav">
|
||||
{% block logo %}
|
||||
<li class="logo border-bottom">
|
||||
{% if is_granted('LIST_ENTRIES') %}
|
||||
|
@ -38,24 +56,6 @@
|
|||
</li>
|
||||
{% endblock %}
|
||||
|
||||
{% set current_route = app.request.attributes.get('_route') %}
|
||||
{% set current_route_from_query_params = app.request.query.get('currentRoute') %}
|
||||
|
||||
{% set active_route = null %}
|
||||
{% if current_route == 'all' or current_route_from_query_params == 'all' %}
|
||||
{% set active_route = 'all' %}
|
||||
{% elseif current_route == 'annotated' or current_route_from_query_params == 'annotated' %}
|
||||
{% set active_route = 'annotated' %}
|
||||
{% elseif current_route == 'archive' or current_route_from_query_params == 'archive' %}
|
||||
{% set active_route = 'archive' %}
|
||||
{% elseif current_route == 'starred' or current_route_from_query_params == 'starred' %}
|
||||
{% set active_route = 'starred' %}
|
||||
{% elseif current_route == 'unread' or current_route == 'homepage' or current_route_from_query_params == 'unread' %}
|
||||
{% set active_route = 'unread' %}
|
||||
{% elseif current_route == 'untagged' %}
|
||||
{% set active_route = 'untagged' %}
|
||||
{% endif %}
|
||||
|
||||
{% if is_granted('LIST_ENTRIES') %}
|
||||
<li class="bold {% if active_route == 'unread' %}active{% endif %}">
|
||||
<a class="waves-effect" href="{{ path('unread') }}">{{ 'menu.left.unread'|trans }} <span class="items-number grey-text">{{ count_entries('unread') }}</span></a>
|
||||
|
@ -77,8 +77,8 @@
|
|||
<a class="waves-effect" href="{{ path('tag') }}">{{ 'menu.left.tags'|trans }} <span class="items-number grey-text">{{ count_tags() }}</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="nav-panels">
|
||||
<div class="nav-panel-actions nav-panel-item">
|
||||
<div class="nav-panels" data-controller="topbar">
|
||||
<div class="nav-panel-actions nav-panel-item" data-topbar-target="actions">
|
||||
<div class="nav-panel-top">
|
||||
<a href="#" data-target="slide-out" class="nav-panel-menu sidenav-trigger"><i class="material-icons">menu</i></a>
|
||||
<h1 class="left action">
|
||||
|
@ -88,34 +88,18 @@
|
|||
</div>
|
||||
<ul class="input-field nav-panel-buttom">
|
||||
<li class="bold toggle-add-url-container">
|
||||
<a class="waves-effect tooltipped toggle-add-url" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.add_new_entry'|trans }}" href="{{ path('new') }}" id="nav-btn-add">
|
||||
<a class="waves-effect toggle-add-url" data-controller="materialize--tooltip" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.add_new_entry'|trans }}" href="{{ path('new') }}" data-action="topbar#showAddUrl:prevent:stop" data-shortcuts-target="showAddUrl">
|
||||
<i class="material-icons">add</i>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="waves-effect tooltipped" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.search'|trans }}" href="javascript: void(null);" id="nav-btn-search">
|
||||
<a class="waves-effect" data-controller="materialize--tooltip" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.search'|trans }}" href="javascript: void(null);" data-action="topbar#showSearch:prevent:stop" data-shortcuts-target="showSearch">
|
||||
<i class="material-icons">search</i>
|
||||
</a>
|
||||
</li>
|
||||
{% if active_route and is_granted('LIST_ENTRIES') %}
|
||||
<li id="button_random">
|
||||
<a class="waves-effect tooltipped js-random-action" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.random_entry'|trans }}" href="{{ path('random_entry', {'type': active_route}) }}">
|
||||
<i class="material-icons">casino</i>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li id="button_filters" class="button-filters">
|
||||
<a class="nav-panel-menu sidenav-trigger tooltipped js-filters-action" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.filter_entries'|trans }}" href="#" data-target="filters">
|
||||
<i class="material-icons">filter_list</i>
|
||||
</a>
|
||||
</li>
|
||||
<li id="button_export" class="button-export">
|
||||
<a class="nav-panel-menu sidenav-trigger tooltipped js-export-action" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.export'|trans }}" href="#" data-target="export">
|
||||
<i class="material-icons">file_download</i>
|
||||
</a>
|
||||
</li>
|
||||
{% block nav_panel_extra_actions '' %}
|
||||
<li class="bold">
|
||||
<a class="wave-effect tooltipped dropdown-trigger" data-covertrigger="false" data-constrainwidth="false" data-target="dropdown-account" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.account'|trans }}" href="#" id="news_menu">
|
||||
<a class="wave-effect dropdown-trigger" data-controller="materialize--dropdown materialize--tooltip" data-target="dropdown-account" data-position="bottom" data-delay="50" data-tooltip="{{ 'menu.top.account'|trans }}" href="#" id="news_menu">
|
||||
<i class="material-icons" id="news_link">account_circle</i>
|
||||
</a>
|
||||
</li>
|
||||
|
@ -144,19 +128,19 @@
|
|||
<li class="divider"></li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a href="#" class="js-theme-toggle" data-theme="light">
|
||||
<a href="#" data-action="click->dark-theme#useLight:prevent">
|
||||
<i class="theme-toggle-icon material-icons tiny">brightness_high</i>
|
||||
<span>{{ 'menu.left.theme_toggle_light'|trans }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="js-theme-toggle" data-theme="dark">
|
||||
<a href="#" data-action="click->dark-theme#useDark:prevent">
|
||||
<i class="theme-toggle-icon material-icons tiny">brightness_low</i>
|
||||
<span>{{ 'menu.left.theme_toggle_dark'|trans }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="js-theme-toggle" data-theme="auto">
|
||||
<a href="#" data-action="click->dark-theme#useAuto:prevent">
|
||||
<i class="theme-toggle-icon material-icons tiny">brightness_auto</i>
|
||||
<span>{{ 'menu.left.theme_toggle_auto'|trans }}</span>
|
||||
</a>
|
||||
|
|
|
@ -10,6 +10,7 @@ Encore
|
|||
.addEntry('main', './assets/index.js')
|
||||
.addEntry('public', './assets/share.js')
|
||||
.splitEntryChunks()
|
||||
.enableStimulusBridge('./assets/controllers.json')
|
||||
.enableSingleRuntimeChunk()
|
||||
.cleanupOutputBeforeBuild()
|
||||
.enableBuildNotifications()
|
||||
|
@ -21,7 +22,6 @@ Encore
|
|||
config.corejs = '3.23';
|
||||
})
|
||||
.enableSassLoader()
|
||||
.enablePostCssLoader()
|
||||
.autoProvidejQuery();
|
||||
.enablePostCssLoader();
|
||||
|
||||
module.exports = Encore.getWebpackConfig();
|
||||
|
|
38
yarn.lock
38
yarn.lock
|
@ -911,6 +911,16 @@
|
|||
resolved "https://registry.yarnpkg.com/@fontsource/oswald/-/oswald-5.2.5.tgz#01ef5b61fae44542eb22330255d32b728ee45b0c"
|
||||
integrity sha512-Sw8ayEYCoOzG2ISw5HaX3d5ILt3OEG2VFX2nzHaGywYD9p0WvVfO4SBK5/y9JGuOty3jA6OhptxOYZgwjTTPLQ==
|
||||
|
||||
"@hotwired/stimulus-webpack-helpers@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@hotwired/stimulus-webpack-helpers/-/stimulus-webpack-helpers-1.0.1.tgz#4cd74487adeca576c9865ac2b9fe5cb20cef16dd"
|
||||
integrity sha512-wa/zupVG0eWxRYJjC1IiPBdt3Lruv0RqGN+/DTMmUWUyMAEB27KXmVY6a8YpUVTM7QwVuaLNGW4EqDgrS2upXQ==
|
||||
|
||||
"@hotwired/stimulus@^3.2.2":
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@hotwired/stimulus/-/stimulus-3.2.2.tgz#071aab59c600fed95b97939e605ff261a4251608"
|
||||
integrity sha512-eGeIqNOQpXoPAIP7tC1+1Yc1yl1xnwYqg+3mzqxyrbE5pg5YFBZcA6YoTiByJB6DKAEsiWtl6tjTJS4IYtbB7A==
|
||||
|
||||
"@humanwhocodes/config-array@^0.13.0":
|
||||
version "0.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748"
|
||||
|
@ -1056,6 +1066,16 @@
|
|||
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e"
|
||||
integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==
|
||||
|
||||
"@symfony/stimulus-bridge@^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@symfony/stimulus-bridge/-/stimulus-bridge-4.0.0.tgz#dbd352a373f8ff323f2895e0bb29f22b9abcc122"
|
||||
integrity sha512-BfeXHAyNtE2hFJtTKFS8vLW2ElqNyzUZJJ4TMeUhrjBjYVt4/myeQxpLidy995l+TEzryE7YrnShqLviBr3pAg==
|
||||
dependencies:
|
||||
"@hotwired/stimulus-webpack-helpers" "^1.0.1"
|
||||
"@types/webpack-env" "^1.16.4"
|
||||
loader-utils "^2.0.0 || ^3.0.0"
|
||||
schema-utils "^3.0.0 || ^4.0.0"
|
||||
|
||||
"@symfony/webpack-encore@^5.1.0":
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@symfony/webpack-encore/-/webpack-encore-5.1.0.tgz#d5664153136959e3baf3e248c9b55350c2c81a6d"
|
||||
|
@ -1157,6 +1177,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901"
|
||||
integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==
|
||||
|
||||
"@types/webpack-env@^1.16.4":
|
||||
version "1.18.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.18.8.tgz#71f083718c094204d7b64443701d32f1db3989e3"
|
||||
integrity sha512-G9eAoJRMLjcvN4I08wB5I7YofOb/kaJNd5uoCMX+LbKXTPCF+ZIHuqTnFaK9Jz1rgs035f9JUPUhNFtqgucy/A==
|
||||
|
||||
"@types/yargs-parser@*":
|
||||
version "21.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15"
|
||||
|
@ -1379,7 +1404,6 @@ ajv@^8.0.0, ajv@^8.0.1, ajv@^8.9.0:
|
|||
|
||||
annotator@wallabag/annotator#master:
|
||||
version "2.0.0-alpha.4"
|
||||
uid "082069d777ed0fe5080392e85675ef3a519c7886"
|
||||
resolved "https://codeload.github.com/wallabag/annotator/tar.gz/082069d777ed0fe5080392e85675ef3a519c7886"
|
||||
dependencies:
|
||||
backbone-extend-standalone "^0.1.2"
|
||||
|
@ -3361,11 +3385,6 @@ jiti@^1.20.0:
|
|||
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d"
|
||||
integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==
|
||||
|
||||
jquery.cookie@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/jquery.cookie/-/jquery.cookie-1.4.1.tgz#d63dce209eab691fe63316db08ca9e47e0f9385b"
|
||||
integrity sha512-c/hZOOL+8VSw/FkTVH637gS1/6YzMSCROpTZ2qBYwJ7s7sHajU7uBkSSiE5+GXWwrfCCyO+jsYjUQ7Hs2rIxAA==
|
||||
|
||||
jquery@^3.7.1:
|
||||
version "3.7.1"
|
||||
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de"
|
||||
|
@ -3489,6 +3508,11 @@ loader-utils@^2.0.0:
|
|||
emojis-list "^3.0.0"
|
||||
json5 "^2.1.2"
|
||||
|
||||
"loader-utils@^2.0.0 || ^3.0.0":
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.3.1.tgz#735b9a19fd63648ca7adbd31c2327dfe281304e5"
|
||||
integrity sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==
|
||||
|
||||
locate-path@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
|
||||
|
@ -4688,7 +4712,7 @@ schema-utils@^3.0.0:
|
|||
ajv "^6.12.5"
|
||||
ajv-keywords "^3.5.2"
|
||||
|
||||
schema-utils@^4.0.0, schema-utils@^4.2.0, schema-utils@^4.3.0:
|
||||
"schema-utils@^3.0.0 || ^4.0.0", schema-utils@^4.0.0, schema-utils@^4.2.0, schema-utils@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.3.0.tgz#3b669f04f71ff2dfb5aba7ce2d5a9d79b35622c0"
|
||||
integrity sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==
|
||||
|
|
Loading…
Reference in a new issue