Skip to content

LxReportPresets

Resumo

O LxReportPresets é um sidebar para gerenciar preferências salvas de painéis. Permite criar, editar, excluir, aplicar e desativar preferências com colunas e filtros.

O componente opera em dois modos distintos:

ModoQuando usar
EstáticoQuando o host já possui os dados localmente e quer controle total sobre persistência.
Via APIQuando o componente deve buscar e persistir as preferências diretamente via HTTP.
Clique para visualizar o código do exemplo
vue
<script setup>
import { ref, reactive, computed, provide, watch } from 'vue';
import LxReportPresetsTrigger from '@/components/LxReportPresets/LxReportPresetsTrigger/LxReportPresetsTrigger.vue';
import LxInputText from '@/components/LxInputText/LxInputText.vue';
import LxCheckbox from '@/components/LxCheckbox/LxCheckbox.vue';
import LxMultiSelect from '@/components/LxComboBox/LxMultiSelect.vue';
import LxToast from '@/components/LxToast/LxToast.vue';
import { PresetTypeEnum } from '@/components/LxReportPresets';
import { REPORT_PRESETS_HTTP_KEY } from '@/components/LxReportPresets/injectionKey';
import { useToast } from '@/components/LxToast/useToast.js';

const toast = useToast();

/* ── Modo de demo: estático (emits) ou real (backend) ── */
const demoMode = ref('static'); // 'static' | 'real'

/* ── Conexão com backend real ── */
const apiBaseUrl = ref('');
const apiJwt = ref('');
const apiConnected = ref(false);
const apiError = ref(null);

let _baseUrl = '';
let _jwt = '';

const canConnect = computed(() => apiJwt.value.trim().length > 0 && viewPageId.value > 0);

const connectApi = () => {
	apiError.value = null;
	_baseUrl = apiBaseUrl.value.trim().replace(/\/$/, '');
	_jwt = apiJwt.value.trim();
	apiConnected.value = true;
};

const disconnectApi = () => {
	apiConnected.value = false;
	apiError.value = null;
};

const FILTER_IDS = { PENDENTE: '1', BUSCA: '2', SITUACOES: '3' };

const situacaoOptions = [
	{ id: 'emitida', label: 'Emitida' },
	{ id: 'cancelada', label: 'Cancelada' },
	{ id: 'pendente', label: 'Pendente' },
	{ id: 'autorizada', label: 'Autorizada' }
];

const filtersState = ref({
	pendente: true,
	busca: 'NF-e',
	situacoes: []
});

const currentFilters = computed(() => {
	const result = [];
	if (filtersState.value.pendente) result.push({ FiltroId: Number(FILTER_IDS.PENDENTE), Valor: 'true' });
	if (filtersState.value.busca.trim()) result.push({ FiltroId: Number(FILTER_IDS.BUSCA), Valor: filtersState.value.busca.trim() });
	if (filtersState.value.situacoes.length) result.push({ FiltroId: Number(FILTER_IDS.SITUACOES), Valor: filtersState.value.situacoes.map((s) => s.id) });
	return result;
});

const currentColumns = computed(() => ['1', '2', '3']);

const applyFiltersFromView = (filtros) => {
	const getId = (f) => String(f.FiltroId ?? f.Id ?? '');
	const pendente = filtros.find((f) => getId(f) === FILTER_IDS.PENDENTE);
	const busca = filtros.find((f) => getId(f) === FILTER_IDS.BUSCA);
	const situacoes = filtros.find((f) => getId(f) === FILTER_IDS.SITUACOES);
	filtersState.value = {
		pendente: pendente?.Valor === 'true',
		busca: busca?.Valor ?? '',
		situacoes: situacoes ? situacaoOptions.filter((o) => situacoes.Valor.includes(o.id)) : []
	};
};

const appliedViewId = ref(1);
const appliedView = computed(() => [...mockViewLists.privadas, ...mockViewLists.publicas].find((v) => v.Id === appliedViewId.value) ?? null);
const appliedViewName = computed(() => appliedView.value?.Nome ?? null);

let lastAppliedFilters = JSON.stringify({
	pendente: filtersState.value.pendente,
	busca: filtersState.value.busca,
	situacoes: filtersState.value.situacoes.map((s) => s.id)
});

watch(
	filtersState,
	(val) => {
		const now = JSON.stringify({
			pendente: val.pendente,
			busca: val.busca,
			situacoes: val.situacoes.map((s) => s.id)
		});
		if (appliedViewId.value !== null && now !== lastAppliedFilters) {
			const deactivatedName = appliedView.value?.Nome ?? `id=${appliedViewId.value}`;
			syncAppliedView(null);
			appliedViewId.value = null;
			addLog(`filtros alterados → preferência "${deactivatedName}" desativada`);
			addLog(`↳ currentFilters agora: ${JSON.stringify(currentFilters.value)}`);
		}
	},
	{ deep: true }
);

const mockUsers = [
	{ Id: 1, Nome: 'Ana Souza' },
	{ Id: 2, Nome: 'Bruno Lima' },
	{ Id: 3, Nome: 'Carlos Pereira' },
	{ Id: 4, Nome: 'Daniela Rocha' },
	{ Id: 5, Nome: 'Eduardo Martins' }
];

const mockViewLists = reactive({
	privadas: [
		{
			Id: 1,
			Nome: 'Pendentes do mês',
			Tipo: PresetTypeEnum.PRIVATE,
			Padrao: true,
			Aplicada: true,
			UsuarioCriadorId: 10,
			PodeEditar: true,
			IgnorarDatas: true,
			IgnorarEmpresas: true,
			Colunas: [
				{ Id: '1', Visivel: true },
				{ Id: '2', Visivel: true },
				{ Id: '3', Visivel: true }
			],
			Filtros: [
				{ Id: FILTER_IDS.PENDENTE, Valor: 'true' },
				{ Id: FILTER_IDS.BUSCA, Valor: 'NF-e' }
			],
			Administradores: []
		},
		{
			Id: 2,
			Nome: 'Autorizadas e emitidas',
			Tipo: PresetTypeEnum.PRIVATE,
			Padrao: false,
			Aplicada: false,
			UsuarioCriadorId: 10,
			PodeEditar: true,
			IgnorarDatas: true,
			IgnorarEmpresas: false,
			Colunas: [
				{ Id: '1', Visivel: true },
				{ Id: '4', Visivel: true },
				{ Id: '5', Visivel: true }
			],
			Filtros: [{ Id: FILTER_IDS.SITUACOES, Valor: ['autorizada', 'emitida'] }],
			Administradores: []
		}
	],
	publicas: [
		{
			Id: 50,
			Nome: 'Padrão da equipe',
			Tipo: PresetTypeEnum.PUBLIC,
			Padrao: false,
			Aplicada: false,
			UsuarioCriadorId: 99,
			PodeEditar: true,
			IgnorarDatas: true,
			IgnorarEmpresas: true,
			Colunas: [
				{ Id: '1', Visivel: true },
				{ Id: '2', Visivel: true }
			],
			Filtros: [],
			Administradores: [1, 2]
		},
		{
			Id: 51,
			Nome: 'Canceladas do trimestre',
			Tipo: PresetTypeEnum.PUBLIC,
			Padrao: false,
			Aplicada: false,
			UsuarioCriadorId: 99,
			PodeEditar: false,
			IgnorarDatas: false,
			IgnorarEmpresas: true,
			Colunas: [{ Id: '1', Visivel: true }],
			Filtros: [{ Id: FILTER_IDS.SITUACOES, Valor: ['cancelada'] }],
			Administradores: []
		}
	]
});

const syncAppliedView = (id) => {
	[...mockViewLists.privadas, ...mockViewLists.publicas].forEach((v) => {
		v.Aplicada = v.Id === id;
	});
};

let _nextId = 100;

// ── Modo real: httpClient via fetch (usa _baseUrl e _jwt congelados) ──
const viewPageId = ref(42);

/* ── httpClient real via fetch (usa _baseUrl e _jwt congelados) ── */
const realHttpClient = {
	get: async (url, config) => {
		const params = config?.params ?? {};
		const qs = new URLSearchParams();
		Object.entries(params).forEach(([k, v]) => {
			if (v != null && v !== '') qs.append(k, String(v));
		});
		const fullUrl = `${_baseUrl}${url}${qs.toString() ? '?' + qs.toString() : ''}`;
		const res = await fetch(fullUrl, { headers: _jwt ? { Authorization: _jwt } : {} });
		if (!res.ok) {
			const msg = `HTTP ${res.status} — ${res.statusText} (${fullUrl})`;
			apiError.value = msg;
			throw new Error(msg);
		}
		apiError.value = null;
		return { data: await res.json() };
	},
	post: async (url, body) => {
		const fullUrl = `${_baseUrl}${url}`;
		const res = await fetch(fullUrl, {
			method: 'POST',
			headers: {
				'Content-Type': 'application/json',
				...(_jwt ? { Authorization: _jwt } : {})
			},
			body: JSON.stringify(body)
		});
		if (!res.ok) {
			const msg = `HTTP ${res.status} — ${res.statusText} (${fullUrl})`;
			apiError.value = msg;
			throw new Error(msg);
		}
		apiError.value = null;
		const text = await res.text();
		return { data: text ? JSON.parse(text) : null };
	},
	delete: async (url, config) => {
		const params = config?.params ?? {};
		const qs = new URLSearchParams();
		Object.entries(params).forEach(([k, v]) => {
			if (v != null && v !== '') qs.append(k, String(v));
		});
		const fullUrl = `${_baseUrl}${url}${qs.toString() ? '?' + qs.toString() : ''}`;
		const res = await fetch(fullUrl, {
			method: 'DELETE',
			headers: _jwt ? { Authorization: _jwt } : {}
		});
		if (!res.ok) {
			const msg = `HTTP ${res.status} — ${res.statusText} (${fullUrl})`;
			apiError.value = msg;
			throw new Error(msg);
		}
		apiError.value = null;
		const text = await res.text();
		return { data: text ? JSON.parse(text) : null };
	}
};

provide(REPORT_PRESETS_HTTP_KEY, realHttpClient);

const reportPresetsTrigger = ref(null);
const eventLog = ref([]);

const addLog = (msg) => {
	eventLog.value.unshift(`[${new Date().toLocaleTimeString()}] ${msg}`);
	if (eventLog.value.length > 10) eventLog.value.pop();
};

const onApply = (view) => {
	syncAppliedView(view.Id);
	appliedViewId.value = view.Id;
	applyFiltersFromView(view.Filtros ?? []);
	lastAppliedFilters = JSON.stringify({
		pendente: filtersState.value.pendente,
		busca: filtersState.value.busca,
		situacoes: filtersState.value.situacoes.map((s) => s.id)
	});
	toast?.add({
		status: 'success',
		title: `Visao aplicada: ${view.Nome}`,
		time: 3000
	});
	reportPresetsTrigger.value?.close();
	addLog(`apply:view → "${view.Nome}" (id=${view.Id})`);
	addLog(`↳ filtros aplicados ao painel: ${JSON.stringify(currentFilters.value)}`);
};

const onDeactivate = (view) => {
	syncAppliedView(null);
	appliedViewId.value = null;
	addLog(`deactivate:view → preferência "${view?.Nome ?? 'sem nome'}" desativada`);
};

const onNotify = ({ text }) => {
	toast?.add({
		status: text?.toLowerCase().startsWith('falha') ? 'error' : 'success',
		title: text,
		time: 3000
	});
	addLog(`notify:message → "${text}"`);
};

const onSavePreset = (payload) => {
	const created = {
		Id: ++_nextId,
		Nome: payload.Descricao,
		Tipo: payload.Tipo,
		Padrao: payload.Padrao,
		Aplicada: false,
		UsuarioCriadorId: 10,
		PodeEditar: true,
		Colunas: payload.ColunasConfiguracao ?? [],
		Filtros: payload.Filtros ?? [],
		Administradores: payload.IdsUsuarios ?? []
	};
	if (payload.Tipo === PresetTypeEnum.PUBLIC) {
		mockViewLists.publicas.push(created);
	} else {
		mockViewLists.privadas.push(created);
	}
	syncAppliedView(created.Id);
	appliedViewId.value = created.Id;
	lastAppliedFilters = JSON.stringify({
		pendente: filtersState.value.pendente,
		busca: filtersState.value.busca,
		situacoes: filtersState.value.situacoes.map((s) => s.id)
	});
	addLog(`insert:preset → "${created.Nome}" criada (id=${created.Id})`);
	reportPresetsTrigger.value?.close();
};

const onUpdatePreset = ({ id, data }) => {
	const pi = mockViewLists.privadas.findIndex((v) => v.Id === id);
	if (pi !== -1) {
		if (data.Padrao) mockViewLists.privadas.forEach((v) => (v.Padrao = false));
		mockViewLists.privadas[pi] = {
			...mockViewLists.privadas[pi],
			Nome: data.Descricao,
			Padrao: data.Padrao,
			Administradores: data.IdsUsuarios ?? mockViewLists.privadas[pi].Administradores,
			...(data.Filtros?.length ? { Filtros: data.Filtros } : {}),
			...(data.ColunasConfiguracao?.length ? { Colunas: data.ColunasConfiguracao } : {})
		};
	}
	const pub = mockViewLists.publicas.findIndex((v) => v.Id === id);
	if (pub !== -1) {
		if (data.Padrao) mockViewLists.publicas.forEach((v) => (v.Padrao = false));
		mockViewLists.publicas[pub] = {
			...mockViewLists.publicas[pub],
			Nome: data.Descricao,
			Padrao: data.Padrao,
			Administradores: data.IdsUsuarios ?? mockViewLists.publicas[pub].Administradores,
			...(data.Filtros?.length ? { Filtros: data.Filtros } : {}),
			...(data.ColunasConfiguracao?.length ? { Colunas: data.ColunasConfiguracao } : {})
		};
	}
	addLog(`update:preset → id=${id} ("${data.Descricao}")`);
};

const onDeletePreset = ({ id }) => {
	const pi = mockViewLists.privadas.findIndex((v) => v.Id === id);
	if (pi !== -1) mockViewLists.privadas.splice(pi, 1);
	const pub = mockViewLists.publicas.findIndex((v) => v.Id === id);
	if (pub !== -1) mockViewLists.publicas.splice(pub, 1);
	addLog(`delete:preset → id=${id}`);
};
</script>

<template>
	<div class="d-flex flex-column gap-4">
		<LxToast />

		<div class="p-3 rounded border d-flex flex-column gap-3">
			<div class="d-flex align-items-center gap-3">
				<span class="fw-semibold small">Modo:</span>
				<label class="form-check-label small d-flex align-items-center gap-1">
					<input type="radio" v-model="demoMode" value="static" class="form-check-input m-0" />
					Estático (emits)
				</label>
				<label class="form-check-label small d-flex align-items-center gap-1">
					<input type="radio" v-model="demoMode" value="real" class="form-check-input m-0" />
					API real (URL + JWT)
				</label>
			</div>

			<!-- Configuração do backend real -->
			<div v-if="demoMode === 'real'" class="p-3 rounded border bg-body-tertiary d-flex flex-column gap-2">
				<p class="mb-0 fw-semibold small"><i class="fas fa-plug" /> Configuração da API</p>

				<template v-if="!apiConnected">
					<div>
						<label class="form-label small mb-1">ID da Página (viewPageId) <span class="text-danger">*</span></label>
						<input v-model.number="viewPageId" class="form-control form-control-sm" type="number" placeholder="Ex: 42" />
					</div>
					<div>
						<label class="form-label small mb-1">Base URL <span class="text-muted">(opcional)</span></label>
						<input v-model="apiBaseUrl" class="form-control form-control-sm" type="text" placeholder="Ex: https://localhost:7020 (vazio = proxy Vite)" />
					</div>
					<div>
						<label class="form-label small mb-1">JWT Token <span class="text-danger">*</span></label>
						<textarea v-model="apiJwt" class="form-control form-control-sm" rows="3" placeholder="Cole o token JWT aqui (sem Bearer)..." />
					</div>
					<small class="text-muted">Sem Base URL, as requisições passam pelo proxy do Vite.</small>
					<div class="d-flex align-items-center gap-2">
						<button class="btn btn-sm btn-primary" :disabled="!canConnect" @click="connectApi"><i class="fas fa-bolt" /> Conectar</button>
						<small v-if="!canConnect" class="text-muted">Informe o ID da página e o JWT para conectar</small>
					</div>
				</template>

				<div v-else class="d-flex align-items-center gap-2">
					<span class="text-success small"><i class="fas fa-circle-check" /> Conectado{{ _baseUrl ? ` em ${_baseUrl}` : ' via proxy local' }}</span>
					<button class="btn btn-sm btn-outline-secondary" @click="disconnectApi"><i class="fas fa-xmark" /> Desconectar</button>
				</div>

				<div v-if="apiError" class="text-danger small"><i class="fas fa-triangle-exclamation" /> {{ apiError }}</div>
			</div>
		</div>

		<div class="d-flex align-items-center justify-content-between p-3 bg-body-secondary rounded border">
			<div class="d-flex align-items-center gap-3">
				<span class="fw-semibold">Gestão Fiscal</span>
				<span v-if="appliedViewName" class="text-body-secondary small">{{ appliedViewName }}</span>
				<span class="badge bg-info-subtle text-info-emphasis small">{{ demoMode }}</span>
			</div>
			<LxReportPresetsTrigger
				v-if="demoMode === 'static'"
				ref="reportPresetsTrigger"
				id="painel-pref-heart-btn"
				:applied-view="appliedView"
				:view-lists="mockViewLists"
				:current-filters="currentFilters"
				:current-columns="currentColumns"
				:show-checkbox-public="true"
				:show-checkbox-dates="true"
				:show-checkbox-companies="true"
				:can-add-public-view="true"
				:users-list="mockUsers"
				@apply:view="onApply"
				@deactivate:view="onDeactivate"
				@notify:message="onNotify"
				@insert:preset="onSavePreset"
				@update:preset="onUpdatePreset"
				@delete:preset="onDeletePreset"
			/>
			<template v-else>
				<span v-if="!apiConnected" class="text-muted small">Configure e conecte acima para testar</span>
				<LxReportPresetsTrigger
					v-else
					ref="reportPresetsTrigger"
					id="painel-pref-heart-btn-real"
					:applied-view="appliedView"
					:current-filters="currentFilters"
					:current-columns="currentColumns"
					:view-page-id="viewPageId"
					:show-checkbox-dates="true"
					:show-checkbox-companies="true"
					@apply:view="onApply"
					@deactivate:view="onDeactivate"
					@notify:message="onNotify"
				/>
			</template>
		</div>

		<div class="p-3 rounded border d-flex flex-column gap-3">
			<p class="mb-0 fw-semibold small">Filtros do painel</p>

			<LxCheckbox id="filter-pendente" v-model="filtersState.pendente" label="Somente pendentes" />

			<div>
				<label class="form-label small mb-1" for="filter-busca">Busca</label>
				<LxInputText id="filter-busca" v-model="filtersState.busca" placeholder="Ex: NF-e, 001..." size="sm" />
			</div>

			<div>
				<label class="form-label small mb-1" for="filter-situacoes">Situações</label>
				<LxMultiSelect
					id="filter-situacoes"
					v-model="filtersState.situacoes"
					:options="situacaoOptions"
					options-label="label"
					options-key="id"
					placeholder="Selecione as situações"
					size="sm"
				/>
			</div>

			<p class="mb-0 text-muted small">
				Filtros ativos:
				<code>{{ JSON.stringify(currentFilters) }}</code>
			</p>
		</div>

		<div v-if="eventLog.length" class="p-3 rounded border bg-body-secondary">
			<p class="mb-2 fw-semibold small">Eventos emitidos:</p>
			<ul class="mb-0 ps-3 small text-muted">
				<li v-for="(entry, i) in eventLog" :key="i">{{ entry }}</li>
			</ul>
		</div>
	</div>
</template>

Modo estático (prop viewLists)

Forneça a prop viewLists com as listas de preferências. O componente não realiza nenhuma chamada à API: toda leitura vem da prop e toda escrita é delegada ao host via eventos.

vue
<script setup>
import { ref, reactive } from 'vue'
import { LxReportPresets } from '@lde/lxcomponents'

// Listas gerenciadas pelo host (ex: carregadas de uma API própria)
const viewLists = reactive({ privadas: [...], publicas: [...] })
const appliedViewId = ref(null)
const visible = ref(false)
</script>

<template>
  <button @click="visible = true">Preferências Salvas</button>

  <LxReportPresets
    v-if="visible"
    :view-lists="viewLists"
    :applied-view-id="appliedViewId"
    :current-filters="currentFilters"
    :current-columns="currentColumns"
    @apply:view="onApplyView"
    @deactivate:view="onDeactivateView"
    @insert:preset="onSavePreset"
    @update:preset="onUpdatePreset"
    @delete:preset="onDeletePreset"
    @close="visible = false"
  />
</template>

Nos handlers de escrita (insert:preset, update:preset, delete:preset) o host é responsável por persistir e atualizar viewLists. O componente reagirá automaticamente às mudanças na prop.

Payload dos eventos de escrita (HostPresetPayload)

ts
interface HostPresetPayload {
  Descricao: string;           // Nome da preferência
  IdVisaoPagina: number;       // Prop viewPageId do componente
  Padrao: boolean;             // Preferência padrão
  IgnorarDatas: boolean;    // informado pelo formulário de edição
  IgnorarEmpresas: boolean; // informado pelo formulário de edição
  Filtros: Array<{ Id: string; Valor: string }>;
  ColunasConfiguracao: Array<{ Id: string; Visivel: boolean }>;
  IdsUsuarios: number[];
}

Os valores de Filtros e ColunasConfiguracao são capturados a partir das props currentFilters e currentColumns no momento da ação.

Modo via API

Quando viewLists não é fornecida, o componente busca e persiste as preferências internamente via HTTP. Para isso, o host precisa injetar um httpClient (axios ou compatível) de uma de duas formas.

Usando o Plugin (recomendado para erp-next)

Instale o plugin uma única vez no main.ts. A partir daí, cada LxReportPresets cria seu próprio serviço de API automaticamente usando o viewPageId.

ts
// main.ts
import { LxReportPresetsPlugin } from '@lde/lxcomponents'
import http from '@/api/http'

app.use(LxReportPresetsPlugin, { httpClient: http })
vue
<script setup>
import { ref } from 'vue'
import { LxReportPresets } from '@lde/lxcomponents'

const visible = ref(false)
</script>

<template>
  <button @click="visible = true">Preferências Salvas</button>

  <LxReportPresets
    v-if="visible"
    :view-page-id="42"
    :current-filters="currentFilters"
    :current-columns="currentColumns"
    :show-checkbox-public="true"
    @apply:view="onApplyView"
    @deactivate:view="onDeactivateView"
    @notify:message="showToast($event.text)"
    @close="visible = false"
  />
</template>

O plugin injeta o httpClient via REPORT_PRESETS_HTTP_KEY. O composable useReportPresets detecta o cliente e cria automaticamente o serviço que consome os endpoints da VisaoController (/api/Visao/Listar, /api/Visao/Obter, /api/Visao/Criar, /api/Visao/Atualizar, /api/Visao/Excluir).

Usando injeção manual via provide

Use quando os endpoints diferem do padrão ou quando você precisa de controle total sobre as chamadas HTTP. Forneça um serviço via provide com a chave REPORT_PRESETS_API_KEY.

vue
<script setup>
import { provide, ref } from 'vue'
import { LxReportPresets, REPORT_PRESETS_API_KEY } from '@lde/lxcomponents'
// Opção A: serviço customizado próprio
import { painelFiscalApiService } from '../services/painelFiscalApiService'
provide(REPORT_PRESETS_API_KEY, painelFiscalApiService)

// Opção B: usar a factory com seu httpClient
// import { createReportPresetsApi } from '@lde/lxcomponents'
// import http from '@/api/http'
// provide(REPORT_PRESETS_API_KEY, createReportPresetsApi(http, 42))

const visible = ref(false)
const isLoading = ref(false)
</script>

<template>
  <button @click="visible = true">Preferências Salvas</button>

  <LxReportPresets
    v-if="visible"
    :current-filters="currentFilters"
    :current-columns="currentColumns"
    :show-checkbox-public="true"
    @apply:view="onApplyView"
    @deactivate:view="onDeactivateView"
    @notify:message="showToast($event.text)"
    @update:loading="isLoading = $event"
    @close="visible = false"
  />
</template>

Contrato da API (IReportPresetsApi)

Ao usar a injeção manual via provide, implemente um objeto com os seguintes métodos:

MétodoAssinaturaDescrição
getPresets() => Promise<ReportPreset[]>Lista todas as preferências do usuário
savePreset(payload: UpdatePresetPayload) => Promise<ReportPreset>Cria uma nova preferência
updatePreset(id, payload: UpdatePresetPayload) => Promise<ReportPreset>Atualiza uma preferência existente
deletePreset(id) => Promise<void>Exclui uma preferência
updateAdministrators(id, userIds) => Promise<void>Atualiza administradores de uma preferência pública

Comportamentos relevantes

  • A aba Públicas só aparece quando showTabPublics for true e existir preferência pública ou canAddPublicView for true.
  • Ao abrir sem preferência aplicada e com aba privada habilitada, o componente inicia em criação rápida de preferência privada.

Propriedades

NomeDescriçãoTipoPadrão
viewListsListas de preferências fornecidas pelo host. Quando presente (!= null), não busca nem persiste via API interna e usa eventos de escrita para delegar ao host.ViewListsundefined
currentColumnsIDs das colunas atualmente visíveis no painel. Usados ao criar/salvar preferência no modo estático.ColumnsConfig[]
currentFiltersFiltros atualmente ativos. Usados ao criar/salvar preferência no modo estático.SavedFilter[][]
appliedViewIdIdentificador da preferência aplicada no host (number ou null para nenhuma).number | null | undefinedundefined
viewPageIdID da página/painel enviado no campo IdVisaoPagina do payload no modo estático.number0
showTabPrivatesExibe a aba "Minhas preferências" (preferências privadas).booleantrue
showTabPublicsExibe a aba "Públicas".booleantrue
showTabModelsExibe a aba "Modelos".booleanfalse
showCheckboxPublicExibe o checkbox "Tornar pública" no formulário de edição e habilita a aba "Públicas" quando há preferências públicas.booleanfalse
showCheckboxDatesExibe o checkbox "Ignorar datas" no formulário de edição.booleanfalse
showCheckboxCompaniesExibe o checkbox "Ignorar empresas" no formulário de edição.booleanfalse
canAddPublicViewPermite criar preferência pública mesmo quando ainda não existe item público listado.booleanfalse
usersListLista de usuários para seleção de administradores. Quando ausente e disponível, pode ser carregada via api.getUsers().PortalUser[]undefined

Eventos

NomePayloadDescrição
closeSidebar deve ser fechado; host controla via v-if
apply:viewReportPresetPreferência selecionada foi aplicada; host deve atualizar colunas/filtros
deactivate:viewReportPresetPreferência foi desativada sem ser removida; host pode limpar estado aplicado
notify:message{ text: string }Toast para o host exibir (ex: troca de preferência padrão)
update:loadingbooleanPropaga o estado de carregamento interno; use @update:loading="isLoading = $event" no host
insert:presetHostPresetPayloadCom viewLists. Nova preferência a ser criada pelo host.
update:preset{ id: number; data: HostPresetPayload }Com viewLists. Preferência existente a ser atualizada pelo host.
delete:preset{ id: number }Com viewLists. Preferência a ser excluída pelo host.

Desenvolvido pelo time Linx Microvix