parent
78856f354f
commit
fc9780a41d
After Width: | Height: | Size: 513 B |
@ -0,0 +1,105 @@ |
||||
<?php |
||||
/** |
||||
* @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com> |
||||
* @copyright Copyright (c) 2016, ownCloud, Inc. |
||||
* |
||||
* @author Christoph Wurst <christoph@winzerhof-wurst.at> |
||||
* @author Daniel Kesselberg <mail@danielkesselberg.de> |
||||
* @author Joas Schilling <coding@schilljs.com> |
||||
* @author Lukas Reschke <lukas@statuscode.ch> |
||||
* @author Morris Jobke <hey@morrisjobke.de> |
||||
* @author Roeland Jago Douma <roeland@famdouma.nl> |
||||
* |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
namespace OCA\Settings\Controller; |
||||
|
||||
use OCP\AppFramework\Controller; |
||||
use OCP\AppFramework\Http; |
||||
use OCP\AppFramework\Http\DataResponse; |
||||
use OCP\IConfig; |
||||
use OCP\IL10N; |
||||
use OCP\IRequest; |
||||
use OCP\IURLGenerator; |
||||
use OCP\IUserSession; |
||||
use OCP\Mail\IMailer; |
||||
|
||||
class AISettingsController extends Controller { |
||||
|
||||
/** @var IL10N */ |
||||
private $l10n; |
||||
/** @var IConfig */ |
||||
private $config; |
||||
/** @var IUserSession */ |
||||
private $userSession; |
||||
/** @var IMailer */ |
||||
private $mailer; |
||||
/** @var IURLGenerator */ |
||||
private $urlGenerator; |
||||
|
||||
/** |
||||
* @param string $appName |
||||
* @param IRequest $request |
||||
* @param IL10N $l10n |
||||
* @param IConfig $config |
||||
* @param IUserSession $userSession |
||||
* @param IURLGenerator $urlGenerator, |
||||
* @param IMailer $mailer |
||||
*/ |
||||
public function __construct($appName, |
||||
IRequest $request, |
||||
IL10N $l10n, |
||||
IConfig $config, |
||||
IUserSession $userSession, |
||||
IURLGenerator $urlGenerator, |
||||
IMailer $mailer) { |
||||
parent::__construct($appName, $request); |
||||
$this->l10n = $l10n; |
||||
$this->config = $config; |
||||
$this->userSession = $userSession; |
||||
$this->urlGenerator = $urlGenerator; |
||||
$this->mailer = $mailer; |
||||
} |
||||
|
||||
/** |
||||
* Sets the email settings |
||||
* |
||||
* @PasswordConfirmationRequired |
||||
* @AuthorizedAdminSetting(settings=OCA\Settings\Settings\Admin\ArtificialIntelligence) |
||||
* |
||||
* @param array $settings |
||||
* @return DataResponse |
||||
*/ |
||||
public function setAISettings($settings) { |
||||
$params = get_defined_vars(); |
||||
$configs = []; |
||||
foreach ($params as $key => $value) { |
||||
$configs[$key] = empty($value) ? null : $value; |
||||
} |
||||
|
||||
// Delete passwords from config in case no auth is specified |
||||
if ($params['mail_smtpauth'] !== 1) { |
||||
$configs['mail_smtpname'] = null; |
||||
$configs['mail_smtppassword'] = null; |
||||
} |
||||
|
||||
$this->config->setSystemValues($configs); |
||||
|
||||
$this->config->setAppValue('core', 'emailTestSuccessful', '0'); |
||||
|
||||
return new DataResponse(); |
||||
} |
||||
} |
@ -0,0 +1,58 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/** |
||||
* @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
namespace OCA\Settings\Sections\Admin; |
||||
|
||||
use OCP\IL10N; |
||||
use OCP\IURLGenerator; |
||||
use OCP\Settings\IIconSection; |
||||
|
||||
class ArtificialIntelligence implements IIconSection { |
||||
|
||||
/** @var IL10N */ |
||||
private $l; |
||||
|
||||
/** @var IURLGenerator */ |
||||
private $urlGenerator; |
||||
|
||||
public function __construct(IL10N $l, IURLGenerator $urlGenerator) { |
||||
$this->l = $l; |
||||
$this->urlGenerator = $urlGenerator; |
||||
} |
||||
|
||||
public function getIcon(): string { |
||||
return $this->urlGenerator->imagePath('settings', 'ai.svg'); |
||||
} |
||||
|
||||
public function getID(): string { |
||||
return 'ai'; |
||||
} |
||||
|
||||
public function getName(): string { |
||||
return $this->l->t('Artificial Intelligence'); |
||||
} |
||||
|
||||
public function getPriority(): int { |
||||
return 40; |
||||
} |
||||
} |
@ -0,0 +1,163 @@ |
||||
<?php |
||||
/** |
||||
* @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net> |
||||
* |
||||
* @author Marcel Klehr <mklehr@gmx.net> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
namespace OCA\Settings\Settings\Admin; |
||||
|
||||
use OCP\AppFramework\Http\TemplateResponse; |
||||
use OCP\AppFramework\Services\IInitialState; |
||||
use OCP\IConfig; |
||||
use OCP\IL10N; |
||||
use OCP\IServerContainer; |
||||
use OCP\Settings\IDelegatedSettings; |
||||
use OCP\SpeechToText\ISpeechToTextManager; |
||||
use OCP\TextProcessing\IManager; |
||||
use OCP\TextProcessing\IProvider; |
||||
use OCP\TextProcessing\ITaskType; |
||||
use OCP\Translation\ITranslationManager; |
||||
use Psr\Container\ContainerExceptionInterface; |
||||
use Psr\Container\NotFoundExceptionInterface; |
||||
|
||||
class ArtificialIntelligence implements IDelegatedSettings { |
||||
public function __construct( |
||||
private IConfig $config, |
||||
private IL10N $l, |
||||
private IInitialState $initialState, |
||||
private ITranslationManager $translationManager, |
||||
private ISpeechToTextManager $sttManager, |
||||
private IManager $textProcessingManager, |
||||
private IServerContainer $container, |
||||
) { |
||||
} |
||||
|
||||
/** |
||||
* @return TemplateResponse |
||||
*/ |
||||
public function getForm() { |
||||
$translationProviders = []; |
||||
$translationPreferences = []; |
||||
foreach ($this->translationManager->getProviders() as $provider) { |
||||
$translationProviders[] = [ |
||||
'class' => $provider::class, |
||||
'name' => $provider->getName(), |
||||
]; |
||||
$translationPreferences[] = $provider::class; |
||||
} |
||||
|
||||
$sttProviders = []; |
||||
foreach ($this->sttManager->getProviders() as $provider) { |
||||
$sttProviders[] = [ |
||||
'class' => $provider::class, |
||||
'name' => $provider->getName(), |
||||
]; |
||||
} |
||||
|
||||
$textProcessingProviders = []; |
||||
/** @var array<class-string<ITaskType>, class-string<IProvider>> $textProcessingSettings */ |
||||
$textProcessingSettings = []; |
||||
foreach ($this->textProcessingManager->getProviders() as $provider) { |
||||
$textProcessingProviders[] = [ |
||||
'class' => $provider::class, |
||||
'name' => $provider->getName(), |
||||
'taskType' => $provider->getTaskType(), |
||||
]; |
||||
$textProcessingSettings[$provider->getTaskType()] = $provider::class; |
||||
} |
||||
$textProcessingTaskTypes = []; |
||||
foreach ($textProcessingSettings as $taskTypeClass => $providerClass) { |
||||
/** @var ITaskType $taskType */ |
||||
try { |
||||
$taskType = $this->container->get($taskTypeClass); |
||||
} catch (NotFoundExceptionInterface $e) { |
||||
continue; |
||||
} catch (ContainerExceptionInterface $e) { |
||||
continue; |
||||
} |
||||
$textProcessingTaskTypes[] = [ |
||||
'class' => $taskTypeClass, |
||||
'name' => $taskType->getName(), |
||||
'description' => $taskType->getDescription(), |
||||
]; |
||||
} |
||||
|
||||
$this->initialState->provideInitialState('ai-stt-providers', $sttProviders); |
||||
$this->initialState->provideInitialState('ai-translation-providers', $translationProviders); |
||||
$this->initialState->provideInitialState('ai-text-processing-providers', $textProcessingProviders); |
||||
$this->initialState->provideInitialState('ai-text-processing-task-types', $textProcessingTaskTypes); |
||||
|
||||
$settings = [ |
||||
'ai.stt_provider' => count($sttProviders) > 0 ? $sttProviders[0]['class'] : null, |
||||
'ai.textprocessing_provider_preferences' => $textProcessingSettings, |
||||
'ai.translation_provider_preferences' => $translationPreferences, |
||||
]; |
||||
foreach ($settings as $key => $defaultValue) { |
||||
$value = $defaultValue; |
||||
$json = $this->config->getAppValue('core', $key, ''); |
||||
if ($json !== '') { |
||||
$value = json_decode($json, JSON_OBJECT_AS_ARRAY); |
||||
switch($key) { |
||||
case 'ai.textprocessing_provider_preferences': |
||||
// fill $value with $defaultValue values |
||||
$value = array_merge($defaultValue, $value); |
||||
break; |
||||
case 'ai.translation_provider_preferences': |
||||
$value += array_diff($defaultValue, $value); // Add entries from $defaultValue that are not in $value to the end of $value |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
$settings[$key] = $value; |
||||
} |
||||
|
||||
$this->initialState->provideInitialState('ai-settings', $settings); |
||||
|
||||
return new TemplateResponse('settings', 'settings/admin/ai'); |
||||
} |
||||
|
||||
/** |
||||
* @return string the section ID, e.g. 'sharing' |
||||
*/ |
||||
public function getSection() { |
||||
return 'ai'; |
||||
} |
||||
|
||||
/** |
||||
* @return int whether the form should be rather on the top or bottom of |
||||
* the admin section. The forms are arranged in ascending order of the |
||||
* priority values. It is required to return a value between 0 and 100. |
||||
* |
||||
* E.g.: 70 |
||||
*/ |
||||
public function getPriority() { |
||||
return 10; |
||||
} |
||||
|
||||
public function getName(): ?string { |
||||
return $this->l->t('Artificial Intelligence'); |
||||
} |
||||
|
||||
public function getAuthorizedAppConfig(): array { |
||||
return [ |
||||
'core' => ['/ai_.*/'], |
||||
]; |
||||
} |
||||
} |
@ -0,0 +1,83 @@ |
||||
<template> |
||||
<NcSettingsSection :title="t('settings', 'Artificial Intelligence')" |
||||
:description="t('settings', 'Artificial Intelligence features can be implemented by different apps. Here you can set which app should be used for which features.')"> |
||||
<h3>{{ t('settings', 'Translations') }}</h3> |
||||
<h3>{{ t('settings', 'Speech-To-Text') }}</h3> |
||||
<template v-for="provider in sttProviders"> |
||||
<NcCheckboxRadioSwitch :key="provider.class" |
||||
:checked.sync="settings['ai.stt_provider']" |
||||
:value="provider.class" |
||||
name="stt_provider" |
||||
type="radio">{{ provider.name }}</NcCheckboxRadioSwitch> |
||||
</template> |
||||
<template v-if="sttProviders.length === 0"> |
||||
<NcCheckboxRadioSwitch disabled type="radio">{{ t('settings', 'No apps are currently installed that provide Speech-To-Text functionality') }}</NcCheckboxRadioSwitch> |
||||
</template> |
||||
<h3>{{ t('settings', 'Text processing') }}</h3> |
||||
<template v-for="(type, provider) in settings['ai.textprocessing_provider_preferences']"> |
||||
<h4>{{ type }}</h4> |
||||
<!--<p>{{ getTaskType(type).description }}</p> |
||||
<NcSelect v-model="settings['ai.textprocessing_provider_preferences'][type]" :options="textProcessingProviders.filter(provider => provider.taskType === type)" />--> |
||||
</template> |
||||
<template v-if="Object.keys(settings['ai.textprocessing_provider_preferences']).length === 0 || !Array.isArray(this.textProcessingTaskTypes)"> |
||||
<p>{{ t('settings', 'No apps are currently installed that provide Text processing functionality') }}</p> |
||||
</template> |
||||
</NcSettingsSection> |
||||
</template> |
||||
|
||||
<script> |
||||
import axios from '@nextcloud/axios' |
||||
import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js' |
||||
import NcSettingsSection from '@nextcloud/vue/dist/Components/NcSettingsSection.js' |
||||
import { loadState } from '@nextcloud/initial-state' |
||||
|
||||
import { generateUrl } from '@nextcloud/router' |
||||
|
||||
export default { |
||||
name: 'AdminAI', |
||||
components: { |
||||
NcCheckboxRadioSwitch, |
||||
NcSettingsSection, |
||||
}, |
||||
data() { |
||||
return { |
||||
loading: false, |
||||
dirty: false, |
||||
groups: [], |
||||
loadingGroups: false, |
||||
sttProviders: loadState('settings', 'ai-stt-providers'), |
||||
translationProviders: loadState('settings', 'ai-translation-providers'), |
||||
textProcessingProviders: loadState('settings', 'ai-text-processing-providers'), |
||||
textProcessingTaskTypes: loadState('settings', 'ai-text-processing-task-types'), |
||||
settings: loadState('settings', 'ai-settings'), |
||||
} |
||||
}, |
||||
methods: { |
||||
saveChanges() { |
||||
this.loading = true |
||||
|
||||
const data = { |
||||
enforced: this.enforced, |
||||
enforcedGroups: this.enforcedGroups, |
||||
excludedGroups: this.excludedGroups, |
||||
} |
||||
axios.put(generateUrl('/settings/api/admin/twofactorauth'), data) |
||||
.then(resp => resp.data) |
||||
.then(state => { |
||||
this.state = state |
||||
this.dirty = false |
||||
}) |
||||
.catch(err => { |
||||
console.error('could not save changes', err) |
||||
}) |
||||
.then(() => { this.loading = false }) |
||||
}, |
||||
getTaskType(type) { |
||||
if (!Array.isArray(this.textProcessingTaskTypes)) { |
||||
return null |
||||
} |
||||
return this.textProcessingTaskTypes.find(taskType => taskType === type) |
||||
} |
||||
}, |
||||
} |
||||
</script> |
@ -0,0 +1,28 @@ |
||||
<?php |
||||
/** |
||||
* @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
script('settings', [ |
||||
'vue-settings-admin-ai', |
||||
]); |
||||
?> |
||||
|
||||
<div id="ai-settings"> |
||||
</div> |
Loading…
Reference in new issue