diff options
Diffstat (limited to 'apps/settings/src/components/AdminAI.vue')
-rw-r--r-- | apps/settings/src/components/AdminAI.vue | 137 |
1 files changed, 98 insertions, 39 deletions
diff --git a/apps/settings/src/components/AdminAI.vue b/apps/settings/src/components/AdminAI.vue index 6a3f30451e9..0d3e9154bb9 100644 --- a/apps/settings/src/components/AdminAI.vue +++ b/apps/settings/src/components/AdminAI.vue @@ -1,5 +1,47 @@ +<!-- + - SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors + - SPDX-License-Identifier: AGPL-3.0-or-later +--> <template> - <div> + <div class="ai-settings"> + <NcSettingsSection :name="t('settings', 'Unified task processing')" + :description="t('settings', 'AI tasks can be implemented by different apps. Here you can set which app should be used for which task.')"> + <NcCheckboxRadioSwitch v-model="settings['ai.taskprocessing_guests']" + type="switch" + @update:modelValue="saveChanges"> + {{ t('settings', 'Allow AI usage for guest users') }} + </NcCheckboxRadioSwitch> + <h3>{{ t('settings', 'Provider for Task types') }}</h3> + <template v-for="type in taskProcessingTaskTypes"> + <div :key="type" class="tasktype-item"> + <p class="tasktype-name"> + {{ type.name }} + </p> + <NcCheckboxRadioSwitch v-model="settings['ai.taskprocessing_type_preferences'][type.id]" + type="switch" + @update:modelValue="saveChanges"> + {{ t('settings', 'Enable') }} + </NcCheckboxRadioSwitch><NcSelect v-model="settings['ai.taskprocessing_provider_preferences'][type.id]" + class="provider-select" + :clearable="false" + :disabled="!settings['ai.taskprocessing_type_preferences'][type.id]" + :options="taskProcessingProviders.filter(p => p.taskType === type.id).map(p => p.id)" + @input="saveChanges"> + <template #option="{label}"> + {{ taskProcessingProviders.find(p => p.id === label)?.name }} + </template> + <template #selected-option="{label}"> + {{ taskProcessingProviders.find(p => p.id === label)?.name }} + </template> + </NcSelect> + </div> + </template> + <template v-if="!hasTaskProcessing"> + <NcNoteCard type="info"> + {{ t('settings', 'None of your currently installed apps provide Task processing functionality') }} + </NcNoteCard> + </template> + </NcSettingsSection> <NcSettingsSection :name="t('settings', 'Machine translation')" :description="t('settings', 'Machine translation can be implemented by different apps. Here you can define the precedence of the machine translation apps you have installed at the moment.')"> <draggable v-model="settings['ai.translation_provider_preferences']" @change="saveChanges"> @@ -18,24 +60,6 @@ </div> </draggable> </NcSettingsSection> - <NcSettingsSection :name="t('settings', 'Speech-To-Text')" - :description="t('settings', 'Speech-To-Text can be implemented by different apps. Here you can set which app should be used.')"> - <template v-for="provider in sttProviders"> - <NcCheckboxRadioSwitch :key="provider.class" - :checked.sync="settings['ai.stt_provider']" - :value="provider.class" - name="stt_provider" - type="radio" - @update:checked="saveChanges"> - {{ provider.name }} - </NcCheckboxRadioSwitch> - </template> - <template v-if="!hasStt"> - <NcCheckboxRadioSwitch disabled type="radio"> - {{ t('settings', 'None of your currently installed apps provide Speech-To-Text functionality') }} - </NcCheckboxRadioSwitch> - </template> - </NcSettingsSection> <NcSettingsSection :name="t('settings', 'Image generation')" :description="t('settings', 'Image generation can be implemented by different apps. Here you can set which app should be used.')"> <template v-for="provider in text2imageProviders"> @@ -49,19 +73,20 @@ </NcCheckboxRadioSwitch> </template> <template v-if="!hasText2ImageProviders"> - <NcCheckboxRadioSwitch disabled type="radio"> + <NcNoteCard type="info"> {{ t('settings', 'None of your currently installed apps provide image generation functionality') }} - </NcCheckboxRadioSwitch> + </NcNoteCard> </template> </NcSettingsSection> <NcSettingsSection :name="t('settings', 'Text processing')" :description="t('settings', 'Text processing tasks can be implemented by different apps. Here you can set which app should be used for which task.')"> <template v-for="type in tpTaskTypes"> <div :key="type"> - <h3>{{ t('settings', 'Task:') }} {{ getTaskType(type).name }}</h3> - <p>{{ getTaskType(type).description }}</p> + <h3>{{ t('settings', 'Task:') }} {{ getTextProcessingTaskType(type).name }}</h3> + <p>{{ getTextProcessingTaskType(type).description }}</p> <p> </p> <NcSelect v-model="settings['ai.textprocessing_provider_preferences'][type]" + class="provider-select" :clearable="false" :options="textProcessingProviders.filter(p => p.taskType === type).map(p => p.class)" @input="saveChanges"> @@ -75,8 +100,11 @@ <p> </p> </div> </template> - <template v-if="!hasTextProcessing"> - <p>{{ t('settings', 'None of your currently installed apps provide Text processing functionality') }}</p> + <template v-if="tpTaskTypes.length === 0"> + <NcNoteCard type="info"> + <!-- TRANSLATORS Text processing is the name of a Nextcloud-internal API --> + {{ t('settings', 'None of your currently installed apps provide text processing functionality using the Text Processing API.') }} + </NcNoteCard> </template> </NcSettingsSection> </div> @@ -84,16 +112,17 @@ <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 NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js' -import NcButton from '@nextcloud/vue/dist/Components/NcButton.js' +import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch' +import NcSettingsSection from '@nextcloud/vue/components/NcSettingsSection' +import NcSelect from '@nextcloud/vue/components/NcSelect' +import NcButton from '@nextcloud/vue/components/NcButton' +import NcNoteCard from '@nextcloud/vue/components/NcNoteCard' import draggable from 'vuedraggable' import DragVerticalIcon from 'vue-material-design-icons/DragVertical.vue' import ArrowDownIcon from 'vue-material-design-icons/ArrowDown.vue' import ArrowUpIcon from 'vue-material-design-icons/ArrowUp.vue' import { loadState } from '@nextcloud/initial-state' - +import { nextTick } from 'vue' import { generateUrl } from '@nextcloud/router' export default { @@ -107,6 +136,7 @@ export default { ArrowDownIcon, ArrowUpIcon, NcButton, + NcNoteCard, }, data() { return { @@ -119,22 +149,32 @@ export default { textProcessingProviders: loadState('settings', 'ai-text-processing-providers'), textProcessingTaskTypes: loadState('settings', 'ai-text-processing-task-types'), text2imageProviders: loadState('settings', 'ai-text2image-providers'), + taskProcessingProviders: loadState('settings', 'ai-task-processing-providers'), + taskProcessingTaskTypes: loadState('settings', 'ai-task-processing-task-types'), settings: loadState('settings', 'ai-settings'), } }, computed: { - hasStt() { - return this.sttProviders.length > 0 - }, hasTextProcessing() { return Object.keys(this.settings['ai.textprocessing_provider_preferences']).length > 0 && Array.isArray(this.textProcessingTaskTypes) }, tpTaskTypes() { - return Object.keys(this.settings['ai.textprocessing_provider_preferences']).filter(type => !!this.getTaskType(type)) + const builtinTextProcessingTypes = [ + 'OCP\\TextProcessing\\FreePromptTaskType', + 'OCP\\TextProcessing\\HeadlineTaskType', + 'OCP\\TextProcessing\\SummaryTaskType', + 'OCP\\TextProcessing\\TopicsTaskType', + ] + return Object.keys(this.settings['ai.textprocessing_provider_preferences']) + .filter(type => !!this.getTextProcessingTaskType(type)) + .filter(type => !builtinTextProcessingTypes.includes(type)) }, hasText2ImageProviders() { return this.text2imageProviders.length > 0 }, + hasTaskProcessing() { + return Object.keys(this.settings['ai.taskprocessing_provider_preferences']).length > 0 && Array.isArray(this.taskProcessingTaskTypes) + }, }, methods: { moveUp(i) { @@ -155,6 +195,7 @@ export default { }, async saveChanges() { this.loading = true + await nextTick() const data = { settings: this.settings } try { await axios.put(generateUrl('/settings/api/admin/ai'), data) @@ -163,7 +204,7 @@ export default { } this.loading = false }, - getTaskType(type) { + getTextProcessingTaskType(type) { if (!Array.isArray(this.textProcessingTaskTypes)) { return null } @@ -186,13 +227,31 @@ export default { .draggable__number { border-radius: 20px; - border: 2px solid var(--color-primary-default); - color: var(--color-primary-default); - padding: 0px 7px; - margin-right: 3px; + border: 2px solid var(--color-primary-element); + color: var(--color-primary-element); + padding: 0px 7px; + margin-inline-end: 3px; } .drag-vertical-icon { float: left; } + +.ai-settings h3 { + font-size: 16px; /* to offset against the 20px section heading */ +} + +.provider-select { + min-width: 350px !important; +} + +.tasktype-item { + display: flex; + align-items: center; + gap: 8px; + .tasktype-name { + flex: 1; + margin: 0; + } +} </style> |