diff --git a/package.json b/package.json index af0b201f..1cf9f363 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "dependencies": { "@quasar/extras": "=1.16.11", "axios": "=1.7.2", + "nunjucks": "=3.2.4", "pinia": "=2.1.7", "quasar": "=2.16.4", "v-viewer": "=3.0.13", @@ -47,7 +48,6 @@ "eslint-plugin-vue": "=9.26.0", "gherkin-lint": "=4.2.4", "jsdoc": "=4.0.3", - "nunjucks": "=3.2.4", "vitest": "=1.6.0" }, "engines": { diff --git a/src/components/card/CustomAIConfigurationCard.vue b/src/components/card/CustomAIConfigurationCard.vue new file mode 100644 index 00000000..5d567341 --- /dev/null +++ b/src/components/card/CustomAIConfigurationCard.vue @@ -0,0 +1,261 @@ + + + + + diff --git a/src/components/card/DefaultAIConfigurationCard.vue b/src/components/card/DefaultAIConfigurationCard.vue new file mode 100644 index 00000000..83b9080e --- /dev/null +++ b/src/components/card/DefaultAIConfigurationCard.vue @@ -0,0 +1,233 @@ + + + + + diff --git a/src/components/tab-panel/ConfigurationsTabPanel.vue b/src/components/tab-panel/ConfigurationsTabPanel.vue index e50aaff7..3fa9501e 100644 --- a/src/components/tab-panel/ConfigurationsTabPanel.vue +++ b/src/components/tab-panel/ConfigurationsTabPanel.vue @@ -3,11 +3,118 @@ name="configurations" data-cy="configurations_tab_panel" > + +
{{ $t('ConfigurationsTabPanel.text.title') }}
+
+ +
+
+ +
+ + diff --git a/src/composables/events/ReloadConfigurationsEvent.js b/src/composables/events/ReloadConfigurationsEvent.js new file mode 100644 index 00000000..238703d2 --- /dev/null +++ b/src/composables/events/ReloadConfigurationsEvent.js @@ -0,0 +1,10 @@ +import { Subject } from 'rxjs'; + +/** + * Represent a rxjs Event object to emit and to receive events to force reloading + * the configurations. + * @typedef {Subject} ReloadConfigurationsEvent + */ +const ReloadConfigurationsEvent = new Subject(); + +export default ReloadConfigurationsEvent; diff --git a/src/i18n/en-US/index.js b/src/i18n/en-US/index.js index b4aca51e..26c03cd6 100644 --- a/src/i18n/en-US/index.js +++ b/src/i18n/en-US/index.js @@ -643,6 +643,37 @@ export default { warning: 'fa-solid fa-triangle-exclamation', }, }, + DefaultAIConfigurationCard: { + text: { + title: 'Global configuration', + addPlugin: 'Add AI model for a new plugin', + editPlugin: 'Update AI model for existing plugin', + newPluginNameLabel: 'Plugin name', + newPluginNameHint: '"default" for all unlisted plugin', + newPluginHandler: 'Select AI model for plugin', + save: 'Save', + update: 'Update', + notEmpty: 'Field is required.', + notifyDeleteSuccess: 'Configuration is deleted.', + notifySaveSuccess: 'Configuration is added.', + notifyUpdateSuccess: 'Configuration(s) is updated.', + }, + icon: { + delete: 'fa-solid fa-trash', + }, + }, + CustomAIConfigurationCard: { + text: { + title: 'AI configuration: {handler}', + pluginTitle: 'Plugin configuration: { plugin }', + save: 'Save', + notEmpty: 'Field is required.', + notifySaveSuccess: 'Configuration is saved.', + }, + icon: { + delete: 'fa-solid fa-trash', + }, + }, TablePaginationCard: { text: { content: '{current}/{max} of {total}', diff --git a/src/services/ConfigurationService.js b/src/services/ConfigurationService.js new file mode 100644 index 00000000..f96cfe1f --- /dev/null +++ b/src/services/ConfigurationService.js @@ -0,0 +1,92 @@ +import { + prepareQueryParameters, + prepareRequest, + makeFilterRequest, +} from 'boot/axios'; + +/** + * Get all configurations paginated. + * @param {object} filters - API filters. + * @returns {Promise} Promise with an array of configurations on success + * otherwise an error. + */ +export async function find(filters) { + const api = await prepareRequest(); + const queryParameters = prepareQueryParameters(filters); + + return makeFilterRequest(api, `/ai/configurations${queryParameters}`) + .then(({ data }) => data); +} + +/** + * Get all configurations without pagination. + * Recursive function to get all configurations from `find`. + * @param {object} filters - API filters. + * @param {Array} configurations - Pagination result to set. + * @returns {Promise} Promise with an array of configurations on success + * otherwise an error. + */ +export async function findAll(filters = {}, configurations = []) { + return find(filters) + .then((data) => { + const nextPage = data.pageable.pageNumber + 1; + data.content.forEach((item) => configurations.push(item)); + + if (data.totalPages <= nextPage) { + return Promise.resolve(configurations); + } + + return findAll({ + ...filters, + page: `${nextPage}`, + }, configurations); + }); +} + +/** + * Get all configuration field descriptions. + * @returns {Promise} Promise with an array of configuration field descriptions on success + * otherwise an error. + */ +export async function findDescriptionFields() { + const api = await prepareRequest(); + + return api.get('/ai/proxy/descriptions') + .then(({ data }) => data); +} + +/** + * Create a new configuration. + * @param {object} configuration - Configuration to create. + * @returns {Promise} Promise with new created configuration on success otherwise an error. + */ +export async function add(configuration) { + const api = await prepareRequest(); + + return api.post('/ai/configurations', configuration) + .then(({ data }) => data); +} + +/** + * Delete configuration by id. + * @param {string} id - Id of configuration. + * @returns {Promise} Promise with nothing on success. + */ +export async function deleteById(id) { + const api = await prepareRequest(); + + return api.delete(`/ai/configurations/${id}`) + .then(({ data }) => data); +} + +/** + * Update multiple configurations. + * @param {Array} configurations - Configurations to update. + * @returns {Promise<*>} Promise with updated configurations on success otherwise an error. + */ +export async function updateAll(configurations) { + const api = await prepareRequest(); + + return api.put('/ai/configurations', configurations) + .then(({ data }) => data); +}