refs #17 add admin option to globally disable search

Signed-off-by: Julien Veyssier <eneiluj@posteo.net>
This commit is contained in:
Julien Veyssier 2021-01-27 12:08:12 +01:00
parent 4e4e753df1
commit 163893a679
No known key found for this signature in database
GPG key ID: 4141FEE162030638
12 changed files with 290 additions and 5 deletions

View file

@ -5,7 +5,7 @@
<summary>Integration of Moodle learning management system</summary>
<description><![CDATA[Moodle integration provides a dashboard widget displaying information about your recent courses and upcoming events.
It also allows you to search for content in Moodle.]]></description>
<version>0.0.6</version>
<version>0.0.7</version>
<licence>agpl</licence>
<author>Julien Veyssier</author>
<namespace>Moodle</namespace>
@ -24,6 +24,8 @@
<nextcloud min-version="20" max-version="21"/>
</dependencies>
<settings>
<admin>OCA\Moodle\Settings\Admin</admin>
<admin-section>OCA\Moodle\Settings\AdminSection</admin-section>
<personal>OCA\Moodle\Settings\Personal</personal>
<personal-section>OCA\Moodle\Settings\PersonalSection</personal-section>
</settings>

View file

@ -12,6 +12,7 @@
return [
'routes' => [
['name' => 'config#setConfig', 'url' => '/config', 'verb' => 'PUT'],
['name' => 'config#setAdminConfig', 'url' => '/admin-config', 'verb' => 'PUT'],
['name' => 'moodleAPI#getNotifications', 'url' => '/notifications', 'verb' => 'GET'],
['name' => 'moodleAPI#getMoodleUrl', 'url' => '/url', 'verb' => 'GET'],
['name' => 'moodleAPI#getMoodleAvatar', 'url' => '/avatar', 'verb' => 'GET'],

View file

@ -11,6 +11,7 @@ namespace OCA\Moodle\AppInfo;
use OCP\IContainer;
use OCP\IConfig;
use OCP\AppFramework\App;
use OCP\AppFramework\IAppContainer;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
@ -41,13 +42,17 @@ class Application extends App implements IBootstrap {
parent::__construct(self::APP_ID, $urlParams);
$container = $this->getContainer();
$this->config = $container->query(IConfig::class);
}
public function register(IRegistrationContext $context): void {
$context->registerDashboardWidget(MoodleWidget::class);
$context->registerSearchProvider(MoodleSearchCoursesProvider::class);
$context->registerSearchProvider(MoodleSearchModulesProvider::class);
$context->registerSearchProvider(MoodleSearchUpcomingProvider::class);
if ($this->config->getAppValue(self::APP_ID, 'search_disabled', '0') === '0') {
$context->registerSearchProvider(MoodleSearchCoursesProvider::class);
$context->registerSearchProvider(MoodleSearchModulesProvider::class);
$context->registerSearchProvider(MoodleSearchUpcomingProvider::class);
}
}
public function boot(IBootContext $context): void {

View file

@ -84,4 +84,18 @@ class ConfigController extends Controller {
$response = new DataResponse(1);
return $response;
}
/**
* set admin config values
*
* @param array $values
* @return DataResponse
*/
public function setAdminConfig(array $values): DataResponse {
foreach ($values as $key => $value) {
$this->config->setAppValue(Application::APP_ID, $key, $value);
}
$response = new DataResponse(1);
return $response;
}
}

59
lib/Settings/Admin.php Normal file
View file

@ -0,0 +1,59 @@
<?php
namespace OCA\Moodle\Settings;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IRequest;
use OCP\IL10N;
use OCP\IConfig;
use OCP\Settings\ISettings;
use OCP\Util;
use OCP\IURLGenerator;
use OCP\IInitialStateService;
use OCA\Moodle\AppInfo\Application;
class Admin implements ISettings {
private $request;
private $config;
private $dataDirPath;
private $urlGenerator;
private $l;
public function __construct(string $appName,
IL10N $l,
IRequest $request,
IConfig $config,
IURLGenerator $urlGenerator,
IInitialStateService $initialStateService,
$userId) {
$this->appName = $appName;
$this->urlGenerator = $urlGenerator;
$this->request = $request;
$this->l = $l;
$this->config = $config;
$this->initialStateService = $initialStateService;
$this->userId = $userId;
}
/**
* @return TemplateResponse
*/
public function getForm(): TemplateResponse {
$searchDisabled = $this->config->getAppValue(Application::APP_ID, 'search_disabled', '0') === '1';
$adminConfig = [
'search_disabled' => $searchDisabled,
];
$this->initialStateService->provideInitialState($this->appName, 'admin-config', $adminConfig);
return new TemplateResponse(Application::APP_ID, 'adminSettings');
}
public function getSection(): string {
return 'connected-accounts';
}
public function getPriority(): int {
return 10;
}
}

View file

@ -0,0 +1,60 @@
<?php
namespace OCA\Moodle\Settings;
use OCP\IURLGenerator;
use OCP\IL10N;
use OCP\Settings\IIconSection;
class AdminSection implements IIconSection {
/** @var IL10N */
private $l;
/** @var IURLGenerator */
private $urlGenerator;
public function __construct(string $appName,
IURLGenerator $urlGenerator,
IL10N $l
) {
$this->appName = $appName;
$this->l = $l;
$this->urlGenerator = $urlGenerator;
}
/**
* returns the ID of the section. It is supposed to be a lower case string
*
* @returns string
*/
public function getID(): string {
return 'connected-accounts'; //or a generic id if feasible
}
/**
* returns the translated name as it should be displayed, e.g. 'LDAP / AD
* integration'. Use the L10N service to translate it.
*
* @return string
*/
public function getName(): string {
return $this->l->t('Connected accounts');
}
/**
* @return int whether the form should be rather on the top or bottom of
* the settings navigation. The sections are arranged in ascending order of
* the priority values. It is required to return a value between 0 and 99.
*/
public function getPriority(): int {
return 80;
}
/**
* @return ?string The relative path to a an icon describing the section
*/
public function getIcon(): ?string {
return $this->urlGenerator->imagePath('core', 'categories/integration.svg');
}
}

View file

@ -49,6 +49,8 @@ class Personal implements ISettings {
$userName = $this->config->getUserValue($this->userId, Application::APP_ID, 'user_name', '');
$checkSsl = $this->config->getUserValue($this->userId, Application::APP_ID, 'check_ssl', '1') === '1';
$searchDisabled = $this->config->getAppValue(Application::APP_ID, 'search_disabled', '0') === '1';
$userConfig = [
'token' => $token,
'url' => $url,
@ -57,6 +59,7 @@ class Personal implements ISettings {
'search_upcoming_enabled' => ($searchUpcomingEnabled === '1'),
'user_name' => $userName,
'check_ssl' => $checkSsl,
'search_disabled' => $searchDisabled,
];
$this->initialStateService->provideInitialState($this->appName, 'user-config', $userConfig);
return new TemplateResponse(Application::APP_ID, 'personalSettings');

25
src/adminSettings.js Normal file
View file

@ -0,0 +1,25 @@
/* jshint esversion: 6 */
/**
* Nextcloud - moodle
*
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Julien Veyssier <eneiluj@posteo.net>
* @copyright Julien Veyssier 2021
*/
import Vue from 'vue'
import './bootstrap'
import AdminSettings from './components/AdminSettings'
// eslint-disable-next-line
'use strict'
// eslint-disable-next-line
new Vue({
el: '#moodle_prefs',
render: h => h(AdminSettings),
})

View file

@ -0,0 +1,109 @@
<template>
<div id="moodle_prefs" class="section">
<h2>
<a class="icon icon-moodle" />
{{ t('integration_moodle', 'Moodle integration') }}
</h2>
<div class="grid-form">
<input
id="disable-search"
type="checkbox"
class="checkbox"
:checked="state.search_disabled"
@input="onCheckSearchChange">
<label for="disable-search">{{ t('integration_moodle', 'Disable search for all users') }}</label>
</div>
</div>
</template>
<script>
import { loadState } from '@nextcloud/initial-state'
import { generateUrl } from '@nextcloud/router'
import axios from '@nextcloud/axios'
import { showSuccess, showError } from '@nextcloud/dialogs'
export default {
name: 'AdminSettings',
components: {
},
props: [],
data() {
return {
state: loadState('integration_moodle', 'admin-config'),
}
},
watch: {
},
mounted() {
},
methods: {
onCheckSearchChange(e) {
this.state.search_disabled = e.target.checked
this.saveOptions({ search_disabled: this.state.search_disabled ? '1' : '0' })
},
saveOptions(values) {
const req = {
values,
}
const url = generateUrl('/apps/integration_moodle/admin-config')
axios.put(url, req)
.then((response) => {
showSuccess(t('integration_moodle', 'Moodle admin options saved'))
})
.catch((error) => {
showError(
t('integration_moodle', 'Failed to save Moodle admin options')
+ ': ' + (error.response?.request?.responseText ?? '')
)
console.debug(error)
})
.then(() => {
})
},
},
}
</script>
<style scoped lang="scss">
.grid-form label {
line-height: 38px;
}
.grid-form input {
width: 100%;
}
.grid-form {
max-width: 500px;
display: grid;
grid-template: 1fr / 1fr 1fr;
margin-left: 30px;
}
#moodle_prefs .icon {
display: inline-block;
width: 32px;
}
#moodle_prefs .grid-form .icon {
margin-bottom: -3px;
}
.icon-moodle {
background-image: url(./../../img/app-dark.svg);
background-size: 23px 23px;
height: 23px;
margin-bottom: -4px;
}
body.theme--dark .icon-moodle {
background-image: url(./../../img/app.svg);
}
</style>

View file

@ -72,7 +72,7 @@
@input="onCheckSslChange">
<label for="check-ssl-moodle">{{ t('integration_moodle', 'Check SSL certificate') }}</label>
<br>
<div v-if="connected" id="moodle-search-block">
<div v-if="connected && !state.search_disabled" id="moodle-search-block">
<input
id="search-moodle-courses"
type="checkbox"

View file

@ -0,0 +1,6 @@
<?php
$appId = OCA\Moodle\AppInfo\Application::APP_ID;
script($appId, $appId . '-adminSettings');
?>
<div id="moodle_prefs"></div>

View file

@ -12,6 +12,7 @@ webpackConfig.stats = {
webpackConfig.entry = {
personalSettings: { import: path.join(__dirname, 'src', 'personalSettings.js'), filename: 'integration_moodle-personalSettings.js' },
adminSettings: { import: path.join(__dirname, 'src', 'adminSettings.js'), filename: 'integration_moodle-adminSettings.js' },
dashboard: { import: path.join(__dirname, 'src', 'dashboard.js'), filename: 'integration_moodle-dashboard.js' },
}