From 904c3c409678a7ed4c2ab522f35197aca3065cf7 Mon Sep 17 00:00:00 2001
From: Elizabeth Danzberger
Date: Wed, 9 Oct 2024 17:31:05 -0400
Subject: [PATCH] refactor: move template settings to vue component
Signed-off-by: Elizabeth Danzberger
---
css/admin.scss | 84 +------
lib/Service/InitialStateService.php | 9 +
lib/Settings/Admin.php | 8 +-
src/admin.js | 118 ----------
src/components/AdminSettings.vue | 15 +-
.../AdminSettings/GlobalTemplates.vue | 212 ++++++++++++++++++
templates/admin.php | 47 +---
7 files changed, 234 insertions(+), 259 deletions(-)
create mode 100644 src/components/AdminSettings/GlobalTemplates.vue
diff --git a/css/admin.scss b/css/admin.scss
index 0d2a579709..3222da918e 100644
--- a/css/admin.scss
+++ b/css/admin.scss
@@ -21,14 +21,7 @@
margin-top: -4px;
width: 300px !important;
}
-}
-
-input#zoteroAPIKeyField {
- width: 300px;
-}
-#richdocuments,
-#richdocuments-templates {
// inline buttons on section headers
> h2 {
display: inline-flex;
@@ -55,77 +48,6 @@ input#zoteroAPIKeyField {
}
}
-#richdocuments-templates {
- > input {
- // feedback for keyboard navigation
- &:hover,
- &:focus,
- &:active {
- + h2 .icon-add,
- + h2 .icon-loading-small {
- opacity: 0.7;
- }
- + #emptycontent label {
- color: var(--color-text-light);
- }
- }
- }
- ul:not(.hidden) {
- display: flex;
- flex-wrap: wrap;
- li {
- $size: 150px;
- $sizeY: math.div($size, 210) * 297;
- $space: 10px;
- border-radius: var(--border-radius);
- border: 1px solid var(--color-border);
- margin: $space;
- position: relative;
- figure {
- display: flex;
- flex-direction: column;
- width: $size;
- margin: $space;
- img, .templatePlaceholder {
- width: $size;
- height: $sizeY;
- background-color: var(--color-background-dark);
- }
- figcaption {
- margin-top: $space;
- }
- }
- .delete-cover,
- .delete-template {
- width: $size;
- height: $sizeY;
- top: 0;
- left: 0;
- position: absolute;
- margin: $space;
- opacity: 0;
- transition: opacity 250ms ease-in-out;
- z-index: 3;
- line-height: $sizeY;
- text-align: center;
- font-size: 20px;
- background-size: 24px;
- // text is set as bg
- color: var(--color-background-darker);
- }
- .delete-cover {
- // bg is set as color
- background-color: var(--color-text-lighter);
- z-index: 2;
- }
- &:hover .delete-template,
- .delete-template:focus,
- .delete-template.icon-loading {
- opacity: 1;
- + .delete-cover {
- opacity: 0.5;
- }
- }
- }
- }
-}
+input#zoteroAPIKeyField {
+ width: 300px;
+}
\ No newline at end of file
diff --git a/lib/Service/InitialStateService.php b/lib/Service/InitialStateService.php
index 8e2550204b..9a8be2f469 100644
--- a/lib/Service/InitialStateService.php
+++ b/lib/Service/InitialStateService.php
@@ -11,6 +11,7 @@
use OCA\Richdocuments\AppConfig;
use OCA\Richdocuments\AppInfo\Application;
use OCA\Richdocuments\Db\Wopi;
+use OCA\Richdocuments\TemplateManager;
use OCP\AppFramework\Services\IInitialState;
use OCP\Defaults;
use OCP\IConfig;
@@ -22,6 +23,7 @@ class InitialStateService {
public function __construct(
private IInitialState $initialState,
private AppConfig $appConfig,
+ private TemplateManager $templateManager,
private CapabilitiesService $capabilitiesService,
private IURLGenerator $urlGenerator,
private Defaults $themingDefaults,
@@ -56,6 +58,13 @@ public function provideDocument(Wopi $wopi, array $params): void {
$this->provideOptions();
}
+ public function provideAdminSettings(): void {
+ $this->initialState->provideInitialState('adminSettings', [
+ 'templatesAvailable' => $this->capabilitiesService->hasTemplateSource(),
+ 'templates' => $this->templateManager->getSystemFormatted(),
+ ]);
+ }
+
public function prepareParams(array $params): array {
$defaults = [
'instanceId' => $this->config->getSystemValue('instanceid'),
diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php
index 9c99946772..100ef6eddd 100644
--- a/lib/Settings/Admin.php
+++ b/lib/Settings/Admin.php
@@ -30,6 +30,8 @@ public function __construct(
public function getForm(): TemplateResponse {
$this->initialStateService->provideCapabilities();
+ $this->initialStateService->provideAdminSettings();
+
return new TemplateResponse(
'richdocuments',
'admin',
@@ -45,8 +47,6 @@ public function getForm(): TemplateResponse {
'external_apps' => $this->config->getAppValue('richdocuments', 'external_apps'),
'canonical_webroot' => $this->config->getAppValue('richdocuments', 'canonical_webroot'),
'disable_certificate_verification' => $this->config->getAppValue('richdocuments', 'disable_certificate_verification', '') === 'yes',
- 'templates' => $this->manager->getSystemFormatted(),
- 'templatesAvailable' => $this->capabilitiesService->hasTemplateSource(),
'settings' => $this->appConfig->getAppSettings(),
'demo_servers' => $this->demoService->fetchDemoServers(),
'web_server' => strtolower($_SERVER['SERVER_SOFTWARE']),
@@ -59,11 +59,11 @@ public function getForm(): TemplateResponse {
);
}
- public function getSection() {
+ public function getSection(): string {
return 'richdocuments';
}
- public function getPriority() {
+ public function getPriority(): int {
return 0;
}
}
diff --git a/src/admin.js b/src/admin.js
index 0b716f4333..1bea381dba 100644
--- a/src/admin.js
+++ b/src/admin.js
@@ -4,8 +4,6 @@
*/
import './init-shared.js'
import Vue from 'vue'
-import axios from '@nextcloud/axios'
-import { generateUrl } from '@nextcloud/router'
import AdminSettings from './components/AdminSettings.vue'
import '../css/admin.scss'
@@ -29,119 +27,3 @@ const element = document.getElementById('admin-vue')
new Vue({
render: h => h(AdminSettings, { props: { initial: JSON.parse(element.dataset.initial) } }),
}).$mount('#admin-vue')
-
-/**
- * Append a new template to the dom
- *
- * @param {object} data the template data from the template controller response
- */
-function appendTemplateFromData(data) {
- const template = document.querySelector('.template-model').cloneNode(true)
- template.className = ''
- template.dataset.filename = data.name
- template.querySelector('img').src = data.preview
- template.querySelector('figcaption').textContent = data.name
- template.querySelector('.delete-template').href = data.delete
-
- document.querySelector('#richdocuments-templates > ul').appendChild(template)
- template.querySelector('.delete-template').addEventListener('click', deleteTemplate)
-}
-
-/**
- * Delete template event handler
- *
- * @param {Event} event the button click event
- */
-function deleteTemplate(event) {
- event.preventDefault()
- const emptyElmt = document.querySelector('#richdocuments-templates #emptycontent')
- const tplListElmt = document.querySelector('#richdocuments-templates > ul')
- const elmt = event.target
-
- // ensure no request is in progress
- if (elmt.className.indexOf('loading') === -1 && elmt.textContent === '') {
- const remote = event.target.href
- elmt.classList.add('icon-loading')
- elmt.classList.remove('icon-delete')
-
- // send request
- axios.delete(remote)
- .then(function() {
- // remove template
- elmt.parentElement.remove()
- // is list empty? Only the default template is left
- if (tplListElmt.querySelectorAll('li').length === 1) {
- tplListElmt.classList.add('hidden')
- emptyElmt.classList.remove('hidden')
- }
- })
- .catch(function(e) {
- // failure, show warning
- elmt.textContent = t('richdocuments', 'Error')
- elmt.classList.remove('icon-loading')
- setTimeout(function() {
- elmt.classList.add('icon-delete')
- elmt.textContent = ''
- }, 2000)
- })
- }
-}
-
-/**
- * Init the upload manager and the delete template handler
- */
-function initTemplateManager() {
- const inputElmt = document.querySelector('#add-template')
- const buttonElmt = document.querySelector('.icon-add')
- const deleteElmts = document.querySelectorAll('.delete-template')
- const emptyElmt = document.querySelector('#richdocuments-templates #emptycontent')
- const tplListElmt = document.querySelector('#richdocuments-templates > ul')
-
- deleteElmts.forEach(function(elmt) {
- elmt.addEventListener('click', deleteTemplate)
- })
-
- // fileupload plugin
- $('#richdocuments-templates').fileupload({
- dataType: 'json',
- url: generateUrl('apps/richdocuments/template'),
- type: 'POST',
-
- add(e, data) {
- // submit on file selection
- data.submit()
- inputElmt.disabled = true
- buttonElmt.className = 'icon-loading-small'
- },
-
- submit(e, data) {
- data.formData = _.extend(data.formData || {}, {
- requesttoken: OC.requestToken,
- })
- },
-
- success(e) {
- document.querySelector(`[data-filename="${e.data.name}"]`)?.remove()
- inputElmt.disabled = false
- buttonElmt.className = 'icon-add'
- // add template to dom
- appendTemplateFromData(e.data)
- tplListElmt.classList.remove('hidden')
- emptyElmt.classList.add('hidden')
- },
-
- fail(e, data) {
- // failure, show warning
- buttonElmt.className = 'icon-add'
- buttonElmt.textContent = t('richdocuments', 'An error occurred') + ': ' + data.jqXHR.responseJSON.data.message
- setTimeout(function() {
- inputElmt.disabled = false
- buttonElmt.textContent = ''
- }, 2000)
- },
- })
-}
-
-document.addEventListener('DOMContentLoaded', () => {
- initTemplateManager()
-})
diff --git a/src/components/AdminSettings.vue b/src/components/AdminSettings.vue
index 4ca5e687e1..e2b30eccce 100644
--- a/src/components/AdminSettings.vue
+++ b/src/components/AdminSettings.vue
@@ -390,6 +390,8 @@
+
+
@@ -406,6 +408,7 @@ import SettingsSelectGroup from './SettingsSelectGroup.vue'
import SettingsExternalApps from './SettingsExternalApps.vue'
import SettingsInputFile from './SettingsInputFile.vue'
import SettingsFontList from './SettingsFontList.vue'
+import GlobalTemplates from './AdminSettings/GlobalTemplates.vue'
import '@nextcloud/dialogs/style.css'
import { getCallbackBaseUrl } from '../helpers/url.js'
@@ -435,6 +438,7 @@ export default {
SettingsExternalApps,
SettingsInputFile,
SettingsFontList,
+ GlobalTemplates,
NcModal,
NcNoteCard,
},
@@ -533,9 +537,6 @@ export default {
else this.serverError = Object.values(getCapabilities().collabora).length > 0 ? SERVER_STATE_OK : SERVER_STATE_CONNECTION_ERROR
}
},
- isSetup() {
- this.toggleTemplateSettings()
- },
},
beforeMount() {
for (const key in this.initial.settings) {
@@ -581,7 +582,6 @@ export default {
}
this.checkIfDemoServerIsActive()
this.checkSettings()
- this.toggleTemplateSettings()
},
methods: {
async checkSettings() {
@@ -815,13 +815,6 @@ export default {
this.settings.fonts.splice(index, 1)
}
},
- toggleTemplateSettings() {
- if (this.isSetup) {
- document.getElementById('richdocuments-templates').classList.remove('hidden')
- } else {
- document.getElementById('richdocuments-templates').classList.add('hidden')
- }
- },
},
}
diff --git a/src/components/AdminSettings/GlobalTemplates.vue b/src/components/AdminSettings/GlobalTemplates.vue
new file mode 100644
index 0000000000..2b4002497d
--- /dev/null
+++ b/src/components/AdminSettings/GlobalTemplates.vue
@@ -0,0 +1,212 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/templates/admin.php b/templates/admin.php
index a5dca9c522..4c27962b7a 100644
--- a/templates/admin.php
+++ b/templates/admin.php
@@ -4,51 +4,8 @@
* SPDX-FileCopyrightText: 2014-2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-script('richdocuments', 'richdocuments-admin');
-script('files', 'jquery.fileupload');
+\OCP\Util::addScript('richdocuments', 'richdocuments-admin');
/** @var array $_ */
?>
-
-
-
-
-
-
+
\ No newline at end of file