Ubuntu

­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ import { reactive, computed, readonly, DeepReadonly, } from 'vue'; import { AjaxHelper } from 'CoreHome'; import { Variable, VariableCategory } from '../types'; interface VariablesStoreState { variables: Variable[]; isLoadingVars: boolean; isLoadingSingle: boolean; isUpdating: boolean; } type AvailableVariablePromises = Record>>; class VariablesStore { private privateState = reactive({ variables: [], isLoadingVars: false, isLoadingSingle: false, isUpdating: false, }); private state = computed(() => readonly(this.privateState)); readonly isLoading = computed(() => { const state = this.state.value; return state.isLoadingVars || state.isLoadingSingle; }); readonly isUpdating = computed(() => this.state.value.isUpdating); readonly variables = computed(() => this.state.value.variables); private fetchPromise: Promise|null = null; private availableVariablesPromises: AvailableVariablePromises = {}; fetchVariablesIfNotLoaded(idContainer: string|number, idContainerVersion: string|number) { if (!this.fetchPromise) { // needed for suggestNameForType() to make sure it is aware of all names this.fetchVariables(idContainer, idContainerVersion); } } findVariable( idContainer: string, idContainerVersion: number, idVariable: number, ignoreCache: boolean, ): Promise> { // before going through an API request we first try to find it in loaded variables const found = this.variables.value.find((v) => v.idvariable === idVariable); if (found && !ignoreCache) { return Promise.resolve(found); } // otherwise we fetch it via API this.privateState.isLoadingSingle = true; return AjaxHelper.fetch({ idVariable, idContainer, idContainerVersion, method: 'TagManager.getContainerVariable', filter_limit: '-1', }).then((record) => { this.privateState.variables = [...this.privateState.variables, record]; return readonly(record); }).finally(() => { this.privateState.isLoadingSingle = false; }); } fetchVariables( idContainer: string|number, idContainerVersion: string|number, ): Promise { this.privateState.isLoadingVars = true; this.privateState.variables = []; if (!this.fetchPromise) { this.fetchPromise = AjaxHelper.fetch({ method: 'TagManager.getContainerVariables', idContainer, idContainerVersion, filter_limit: '-1', }); } return Promise.resolve(this.fetchPromise).then((variables) => { this.privateState.variables = variables; this.privateState.isLoadingVars = false; return this.variables.value; }).finally(() => { this.privateState.isLoadingVars = false; }); } fetchAvailableVariables(idContext: string): VariablesStore['availableVariablesPromises'][''] { if (!this.availableVariablesPromises[idContext]) { this.availableVariablesPromises[idContext] = AjaxHelper.fetch({ method: 'TagManager.getAvailableVariableTypesInContext', idContext, filter_limit: '-1', }).then((variables) => readonly(variables)); } return Promise.resolve(this.availableVariablesPromises[idContext]); } suggestNameForType(templateId: string): string|undefined { for (let counter = 0; counter < 100; counter += 1) { let name = templateId; if (counter) { name = `${name} (${counter})`; } const isFree = !this.variables.value.some((v) => v.name === name); if (isFree) { return name; } } return undefined; } createOrUpdateVariable( variable: DeepReadonly|Variable, method: string, idContainer: string, idContainerVersion: number, parameterValues: Record, ): Promise<{ value: number }> { this.privateState.isUpdating = true; const mappedEntries = Object.entries(parameterValues).map(([key, value]) => { let newValue = value; if (typeof value === 'boolean') { newValue = (+value).toString(); } return [key, newValue]; }); const parameters = Object.fromEntries(mappedEntries); const lookupTable = variable.lookup_table.filter((l) => l && l.out_value && l.comparison); return AjaxHelper.post<{ value: number }>( { idVariable: variable.idvariable, method, idContainer, idContainerVersion, type: variable.type, name: variable.name, description: variable.description, defaultValue: variable.default_value, }, { parameters, lookupTable, }, { withTokenInUrl: true }, ).finally(() => { // TODO: test finally() use here in old browser (works in node) this.privateState.isUpdating = false; }); } reload( idContainer: string, idContainerVersion: number, ): ReturnType { this.privateState.variables = []; this.fetchPromise = null; this.availableVariablesPromises = {}; return this.fetchVariables(idContainer, idContainerVersion); } deleteVariable( idContainer: string, idContainerVersion: number, idVariable: number, ): Promise { this.privateState.isUpdating = true; this.privateState.variables = []; return AjaxHelper.fetch( { idVariable, idContainerVersion, idContainer, method: 'TagManager.deleteContainerVariable', }, { withTokenInUrl: true }, ).finally(() => { this.privateState.isUpdating = false; }); } } export default new VariablesStore();