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:
| Modo | Quando usar |
|---|---|
| Estático | Quando o host já possui os dados localmente e quer controle total sobre persistência. |
| Via API | Quando 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étodo | Assinatura | Descriçã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
showTabPublicsfortruee existir preferência pública oucanAddPublicViewfortrue. - Ao abrir sem preferência aplicada e com aba privada habilitada, o componente inicia em criação rápida de preferência privada.
Propriedades
| Nome | Descrição | Tipo | Padrão |
|---|---|---|---|
| viewLists | Listas 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. | ViewLists | undefined |
| currentColumns | IDs das colunas atualmente visíveis no painel. Usados ao criar/salvar preferência no modo estático. | ColumnsConfig | [] |
| currentFilters | Filtros atualmente ativos. Usados ao criar/salvar preferência no modo estático. | SavedFilter[] | [] |
| appliedViewId | Identificador da preferência aplicada no host (number ou null para nenhuma). | number | null | undefined | undefined |
| viewPageId | ID da página/painel enviado no campo IdVisaoPagina do payload no modo estático. | number | 0 |
| showTabPrivates | Exibe a aba "Minhas preferências" (preferências privadas). | boolean | true |
| showTabPublics | Exibe a aba "Públicas". | boolean | true |
| showTabModels | Exibe a aba "Modelos". | boolean | false |
| showCheckboxPublic | Exibe o checkbox "Tornar pública" no formulário de edição e habilita a aba "Públicas" quando há preferências públicas. | boolean | false |
| showCheckboxDates | Exibe o checkbox "Ignorar datas" no formulário de edição. | boolean | false |
| showCheckboxCompanies | Exibe o checkbox "Ignorar empresas" no formulário de edição. | boolean | false |
| canAddPublicView | Permite criar preferência pública mesmo quando ainda não existe item público listado. | boolean | false |
| usersList | Lista de usuários para seleção de administradores. Quando ausente e disponível, pode ser carregada via api.getUsers(). | PortalUser[] | undefined |
Eventos
| Nome | Payload | Descrição |
|---|---|---|
| close | — | Sidebar deve ser fechado; host controla via v-if |
| apply:view | ReportPreset | Preferência selecionada foi aplicada; host deve atualizar colunas/filtros |
| deactivate:view | ReportPreset | Preferê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:loading | boolean | Propaga o estado de carregamento interno; use @update:loading="isLoading = $event" no host |
| insert:preset | HostPresetPayload | Com 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. |
LxComponents