@praxisui/settings-panel 3.0.0-beta.0 → 3.0.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -3,21 +3,21 @@ import { inject, DestroyRef, ViewContainerRef, HostListener, ViewChild, ChangeDe
|
|
|
3
3
|
import { ComponentPortal } from '@angular/cdk/portal';
|
|
4
4
|
import * as i3 from '@angular/common';
|
|
5
5
|
import { CommonModule } from '@angular/common';
|
|
6
|
+
import { CdkTrapFocus } from '@angular/cdk/a11y';
|
|
6
7
|
import * as i3$1 from '@angular/material/button';
|
|
7
8
|
import { MatButtonModule } from '@angular/material/button';
|
|
9
|
+
import * as i1 from '@angular/material/dialog';
|
|
10
|
+
import { MatDialogModule } from '@angular/material/dialog';
|
|
8
11
|
import * as i4 from '@angular/material/icon';
|
|
9
12
|
import { MatIconModule } from '@angular/material/icon';
|
|
10
|
-
import { PraxisIconDirective, GlobalConfigService, FieldControlType, IconPickerService, LoggerService } from '@praxisui/core';
|
|
11
|
-
import * as i5 from '@angular/material/tooltip';
|
|
12
|
-
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
13
|
-
import { CdkTrapFocus } from '@angular/cdk/a11y';
|
|
14
13
|
import * as i6 from '@angular/material/progress-spinner';
|
|
15
14
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
16
|
-
import * as
|
|
17
|
-
import {
|
|
15
|
+
import * as i5 from '@angular/material/tooltip';
|
|
16
|
+
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
18
17
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
19
|
-
import { isObservable, firstValueFrom, of, Subject, BehaviorSubject } from 'rxjs';
|
|
20
18
|
import { filter, switchMap, debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
|
19
|
+
import { isObservable, firstValueFrom, of, Subject, BehaviorSubject } from 'rxjs';
|
|
20
|
+
import { providePraxisI18n, PraxisI18nService, PraxisIconDirective, SETTINGS_PANEL_DATA as SETTINGS_PANEL_DATA$1, SETTINGS_PANEL_BRIDGE, GlobalConfigService, FieldControlType, IconPickerService, LoggerService } from '@praxisui/core';
|
|
21
21
|
import { ConfirmDialogComponent } from '@praxisui/dynamic-fields';
|
|
22
22
|
import * as i1$1 from '@angular/cdk/overlay';
|
|
23
23
|
import * as i2 from '@angular/material/snack-bar';
|
|
@@ -28,6 +28,457 @@ import * as i9 from '@angular/material/chips';
|
|
|
28
28
|
import { MatChipsModule } from '@angular/material/chips';
|
|
29
29
|
import { AiBackendApiService } from '@praxisui/ai';
|
|
30
30
|
|
|
31
|
+
const PRAXIS_SETTINGS_PANEL_GLOBAL_CONFIG_EDITOR_PT_BR = {
|
|
32
|
+
CRUD: 'CRUD',
|
|
33
|
+
'Dynamic Fields': 'Campos Dinâmicos',
|
|
34
|
+
'Cache & Persistence': 'Cache & Persistência',
|
|
35
|
+
Table: 'Tabela',
|
|
36
|
+
Dialog: 'Dialog',
|
|
37
|
+
'Settings saved': 'Configurações salvas',
|
|
38
|
+
'Save failed.': 'Falha ao salvar configurações.',
|
|
39
|
+
'Global settings': 'Configurações globais',
|
|
40
|
+
'Global policies for opening, back and header': 'Políticas globais de abertura, back e header',
|
|
41
|
+
'Server defaults (env vars)': 'Padrões do servidor (env vars)',
|
|
42
|
+
'Saved configuration (UI) - overrides server defaults': 'Configuração salva (UI) - sobrescreve os defaults do servidor',
|
|
43
|
+
'Failed to test connection.': 'Falha ao testar conexão.',
|
|
44
|
+
'Connection established successfully!': 'Conexão estabelecida com sucesso!',
|
|
45
|
+
'Unknown error': 'Erro desconhecido',
|
|
46
|
+
'Key provided': 'Chave informada',
|
|
47
|
+
'Saved key (****{{last4}})': 'Chave salva (****{{last4}})',
|
|
48
|
+
'Saved key': 'Chave salva',
|
|
49
|
+
'Test connection with the provided key': 'Testar conexão com a chave informada',
|
|
50
|
+
'Test connection': 'Testar conexão',
|
|
51
|
+
'Refresh model list': 'Atualizar lista de modelos',
|
|
52
|
+
Close: 'Fechar',
|
|
53
|
+
'This provider has no model catalog.': 'Este provedor não oferece catálogo de modelos.',
|
|
54
|
+
'Enter an API key to fetch models.': 'Insira uma chave de API para buscar modelos.',
|
|
55
|
+
'Error fetching models.': 'Erro ao buscar modelos.',
|
|
56
|
+
'Error fetching models. Check your API key.': 'Erro ao buscar modelos. Verifique a chave de API.',
|
|
57
|
+
'Model list updated ({{count}} models)': 'Lista de modelos atualizada ({{count}} modelos)',
|
|
58
|
+
'Enter an API key to test.': 'Insira uma chave de API para testar.',
|
|
59
|
+
'No model details available.': 'Detalhes do modelo não disponíveis.',
|
|
60
|
+
'Model: {{model}} | Tokens (in/out): {{in}}/{{out}} | Methods: {{methods}}': 'Modelo: {{model}} | Tokens (in/out): {{in}}/{{out}} | Métodos: {{methods}}',
|
|
61
|
+
'Global config cleared. Using server defaults.': 'Configuração global limpa. Usando defaults do servidor.',
|
|
62
|
+
'Clear saved config and return to server defaults': 'Apaga o config salvo e volta aos defaults do servidor',
|
|
63
|
+
'Failed to clear global config.': 'Falha ao limpar a configuração global.',
|
|
64
|
+
'No key required': 'Sem chave necessária',
|
|
65
|
+
'Model & Behavior': 'Modelo & Comportamento',
|
|
66
|
+
'Choose the model after validating the key.': 'Escolha o modelo após validar a chave.',
|
|
67
|
+
'API key validated required': 'Requer chave de API validada',
|
|
68
|
+
'Configure and test your API key to unlock model selection.': 'Configure e teste sua chave de API para desbloquear a seleção de modelos.',
|
|
69
|
+
'Embeddings (RAG)': 'Embeddings (RAG)',
|
|
70
|
+
'Use the LLM provider and key for embeddings': 'Aplicar provedor e chave do LLM aos embeddings',
|
|
71
|
+
'Provider has no embeddings': 'Provedor sem embeddings',
|
|
72
|
+
'Configure the embeddings provider for vector search (templates and schemas).': 'Configure o provedor de embeddings para buscas vetoriais (templates e schemas).',
|
|
73
|
+
'Embedding dimension mismatch with database (768). Adjust to 768 or redo the migration.': 'Dimensão de embeddings diferente do banco (768). Ajuste para 768 ou refaça a migração.',
|
|
74
|
+
'Toolbar, appearance and advanced filter': 'Toolbar, aparência e filtro avançado',
|
|
75
|
+
'Defaults and variants (danger, info, success, question, error)': 'Defaults e variants (danger, info, success, question, error)',
|
|
76
|
+
'Icons by profile (shortcuts)': 'Ícones por perfil (atalhos)',
|
|
77
|
+
'Pick icon': 'Escolher ícone',
|
|
78
|
+
'Pick icon for {{key}}': 'Escolher ícone para {{key}}',
|
|
79
|
+
'Clear icon': 'Limpar ícone',
|
|
80
|
+
'Clear icon for {{key}}': 'Limpar ícone de {{key}}',
|
|
81
|
+
'The text field above remains editable. These buttons only help with selection/clear preview.': 'O campo de texto acima permanece editável. Estes botões apenas ajudam na seleção/limpeza com preview.',
|
|
82
|
+
'Fast multimodal models from Google.': 'Modelos rápidos e multimodais do Google.',
|
|
83
|
+
'Grok models focused on reasoning.': 'Modelos Grok focados em raciocínio.',
|
|
84
|
+
'Local mode for tests without a key.': 'Modo local para testes sem chave.',
|
|
85
|
+
'No saved key': 'Sem chave salva',
|
|
86
|
+
'Aparência: densidade': 'Aparência: densidade',
|
|
87
|
+
compact: 'compact',
|
|
88
|
+
comfortable: 'comfortable',
|
|
89
|
+
spacious: 'spacious',
|
|
90
|
+
'Aparência: padding das células': 'Aparência: padding das células',
|
|
91
|
+
'Aceita 1 a 4 medidas CSS com unidade, var(...) ou calc(...). Ex.: 6px 12px': 'Aceita 1 a 4 medidas CSS com unidade, var(...) ou calc(...). Ex.: 6px 12px',
|
|
92
|
+
'Use 1 a 4 medidas CSS válidas, como 6px 12px.': 'Use 1 a 4 medidas CSS válidas, como 6px 12px.',
|
|
93
|
+
'Aparência: padding do cabeçalho': 'Aparência: padding do cabeçalho',
|
|
94
|
+
'Aceita 1 a 4 medidas CSS com unidade, var(...) ou calc(...). Ex.: 8px 12px': 'Aceita 1 a 4 medidas CSS com unidade, var(...) ou calc(...). Ex.: 8px 12px',
|
|
95
|
+
'Use 1 a 4 medidas CSS válidas, como 8px 12px.': 'Use 1 a 4 medidas CSS válidas, como 8px 12px.',
|
|
96
|
+
'Aparência: fonte das células': 'Aparência: fonte das células',
|
|
97
|
+
'Aceita uma medida CSS com unidade, var(...) ou calc(...). Ex.: 13px': 'Aceita uma medida CSS com unidade, var(...) ou calc(...). Ex.: 13px',
|
|
98
|
+
'Use uma medida CSS válida, como 13px.': 'Use uma medida CSS válida, como 13px.',
|
|
99
|
+
'Aparência: fonte do cabeçalho': 'Aparência: fonte do cabeçalho',
|
|
100
|
+
'Filtro: modo de abertura': 'Filtro: modo de abertura',
|
|
101
|
+
overlay: 'overlay',
|
|
102
|
+
'Filtro: overlay (visual)': 'Filtro: overlay (visual)',
|
|
103
|
+
card: 'card',
|
|
104
|
+
frosted: 'frosted',
|
|
105
|
+
'Filtro: backdrop no overlay': 'Filtro: backdrop no overlay',
|
|
106
|
+
'Excluir — confirmação': 'Excluir — confirmação',
|
|
107
|
+
'Excluir (múltiplos) — confirmação': 'Excluir (múltiplos) — confirmação',
|
|
108
|
+
'Salvar — confirmação': 'Salvar — confirmação',
|
|
109
|
+
'Cancelar — confirmação': 'Cancelar — confirmação',
|
|
110
|
+
'Exportar — confirmação': 'Exportar — confirmação',
|
|
111
|
+
'Excluir — progresso': 'Excluir — progresso',
|
|
112
|
+
'Excluir (múltiplos) — progresso': 'Excluir (múltiplos) — progresso',
|
|
113
|
+
'Excluir — sucesso': 'Excluir — sucesso',
|
|
114
|
+
'Salvar — sucesso': 'Salvar — sucesso',
|
|
115
|
+
'Exportar — sucesso': 'Exportar — sucesso',
|
|
116
|
+
'Importar — sucesso': 'Importar — sucesso',
|
|
117
|
+
'Excluir — erro': 'Excluir — erro',
|
|
118
|
+
'Salvar — erro': 'Salvar — erro',
|
|
119
|
+
'Exportar — erro': 'Exportar — erro',
|
|
120
|
+
'Rede — erro': 'Rede — erro',
|
|
121
|
+
'Permissão — erro': 'Permissão — erro',
|
|
122
|
+
'Modo de abertura padrão': 'Modo de abertura padrão',
|
|
123
|
+
Rota: 'Rota',
|
|
124
|
+
'Aplicado quando ação/metadado não definem modo.': 'Aplicado quando ação/metadado não definem modo.',
|
|
125
|
+
'Confirmar ao sair com alterações': 'Confirmar ao sair com alterações',
|
|
126
|
+
'Back: estratégia': 'Back: estratégia',
|
|
127
|
+
'Modal: largura (ex.: 900px)': 'Modal: largura (ex.: 900px)',
|
|
128
|
+
'Modal: largura máxima (ex.: 96vw)': 'Modal: largura máxima (ex.: 96vw)',
|
|
129
|
+
'Modal: backdrop': 'Modal: backdrop',
|
|
130
|
+
blur: 'blur',
|
|
131
|
+
dim: 'dim',
|
|
132
|
+
transparent: 'transparent',
|
|
133
|
+
'Estratégia de primeira carga quando metadado não definir.': 'Estratégia de primeira carga quando metadado não definir.',
|
|
134
|
+
'Async Select, cascade and pagination': 'Async Select, cascata e paginação',
|
|
135
|
+
'Cascata nativa habilitada': 'Cascata nativa habilitada',
|
|
136
|
+
'Cascata: loadOnChange': 'Cascata: loadOnChange',
|
|
137
|
+
respectLoadOn: 'respectLoadOn',
|
|
138
|
+
immediate: 'immediate',
|
|
139
|
+
manual: 'manual',
|
|
140
|
+
'Cascata: debounce (ms)': 'Cascata: debounce (ms)',
|
|
141
|
+
'Async Select: loadOn': 'Async Select: loadOn',
|
|
142
|
+
open: 'open',
|
|
143
|
+
init: 'init',
|
|
144
|
+
none: 'none',
|
|
145
|
+
'Async Select: pageSize': 'Async Select: pageSize',
|
|
146
|
+
'Async Select: usar cursor': 'Async Select: usar cursor',
|
|
147
|
+
'LLM provider': 'Provedor LLM',
|
|
148
|
+
'Select the provider to list models and test the key.': 'Selecione o provedor para listar modelos e testar a chave.',
|
|
149
|
+
'API key': 'Chave de API',
|
|
150
|
+
'Enter the selected provider key to test.': 'Informe a chave do provedor selecionado para testar.',
|
|
151
|
+
'AI model': 'Modelo de IA',
|
|
152
|
+
'Temperature (Creativity)': 'Temperatura (Criatividade)',
|
|
153
|
+
'0.0 (deterministic) to 1.0 (creative)': '0.0 (determinístico) a 1.0 (criativo)',
|
|
154
|
+
'Assistant: risk validation': 'Assistente: validação de risco',
|
|
155
|
+
'Standard': 'Padrão',
|
|
156
|
+
'Strict requires confirmation for medium/high risk. Standard follows the indication returned by the backend.': 'Estrito exige confirmação em risco médio/alto. Padrão segue a indicação retornada pelo backend.',
|
|
157
|
+
'Use same LLM for embeddings': 'Embeddings: usar mesmo LLM',
|
|
158
|
+
'Replicates the LLM provider and key for embeddings.': 'Replica provedor e chave do LLM para embeddings.',
|
|
159
|
+
'Embeddings provider': 'Embeddings: provedor',
|
|
160
|
+
'Provider used to generate embeddings (RAG).': 'Provedor usado para gerar embeddings (RAG).',
|
|
161
|
+
'Embeddings API key': 'Embeddings: chave de API',
|
|
162
|
+
'Embeddings provider key.': 'Chave do provedor de embeddings.',
|
|
163
|
+
'Embeddings model': 'Embeddings: modelo',
|
|
164
|
+
'Provider default': 'Padrão do provedor',
|
|
165
|
+
'OpenAI models for embeddings.': 'Modelos OpenAI para embeddings.',
|
|
166
|
+
'Embeddings: dimensions': 'Embeddings: dimensões',
|
|
167
|
+
'Embedding vector dimensions (default 768).': 'Dimensões do vetor de embedding (default 768).',
|
|
168
|
+
'Artificial Intelligence': 'Inteligência Artificial',
|
|
169
|
+
'LLM integration': 'Integração com LLM',
|
|
170
|
+
'Appearance: density': 'Aparência: densidade',
|
|
171
|
+
'Appearance: cell padding': 'Aparência: padding das células',
|
|
172
|
+
'Accepts 1 to 4 CSS measures with units, var(...) or calc(...). Example: 6px 12px': 'Aceita 1 a 4 medidas CSS com unidade, var(...) ou calc(...). Ex.: 6px 12px',
|
|
173
|
+
'Use 1 to 4 valid CSS measures, such as 6px 12px.': 'Use 1 a 4 medidas CSS válidas, como 6px 12px.',
|
|
174
|
+
'Appearance: header padding': 'Aparência: padding do cabeçalho',
|
|
175
|
+
'Accepts 1 to 4 CSS measures with units, var(...) or calc(...). Example: 8px 12px': 'Aceita 1 a 4 medidas CSS com unidade, var(...) ou calc(...). Ex.: 8px 12px',
|
|
176
|
+
'Use 1 to 4 valid CSS measures, such as 8px 12px.': 'Use 1 a 4 medidas CSS válidas, como 8px 12px.',
|
|
177
|
+
'Appearance: cell font size': 'Aparência: fonte das células',
|
|
178
|
+
'Accepts a CSS measure with units, var(...) or calc(...). Example: 13px': 'Aceita uma medida CSS com unidade, var(...) ou calc(...). Ex.: 13px',
|
|
179
|
+
'Use a valid CSS measure, such as 13px.': 'Use uma medida CSS válida, como 13px.',
|
|
180
|
+
'Appearance: header font size': 'Aparência: fonte do cabeçalho',
|
|
181
|
+
'Provedor LLM': 'Provedor LLM',
|
|
182
|
+
'Selecione o provedor para listar modelos e testar a chave.': 'Selecione o provedor para listar modelos e testar a chave.',
|
|
183
|
+
'Chave de API': 'Chave de API',
|
|
184
|
+
'Informe a chave do provedor selecionado para testar.': 'Informe a chave do provedor selecionado para testar.',
|
|
185
|
+
'Modelo de IA': 'Modelo de IA',
|
|
186
|
+
'Temperatura (Criatividade)': 'Temperatura (Criatividade)',
|
|
187
|
+
'0.0 (determinístico) a 1.0 (criativo)': '0.0 (determinístico) a 1.0 (criativo)',
|
|
188
|
+
'Max tokens': 'Max tokens',
|
|
189
|
+
'Limite maximo de tokens na resposta.': 'Limite maximo de tokens na resposta.',
|
|
190
|
+
'Assistente: validação de risco': 'Assistente: validação de risco',
|
|
191
|
+
'Estrito (recomendado)': 'Estrito (recomendado)',
|
|
192
|
+
'Padrão': 'Padrão',
|
|
193
|
+
'Estrito exige confirmação em risco médio/alto. Padrão segue a indicação retornada pelo backend.': 'Estrito exige confirmação em risco médio/alto. Padrão segue a indicação retornada pelo backend.',
|
|
194
|
+
'Embeddings: usar mesmo LLM': 'Embeddings: usar mesmo LLM',
|
|
195
|
+
'Replica provedor e chave do LLM para embeddings.': 'Replica provedor e chave do LLM para embeddings.',
|
|
196
|
+
'Embeddings: provedor': 'Embeddings: provedor',
|
|
197
|
+
'Provedor usado para gerar embeddings (RAG).': 'Provedor usado para gerar embeddings (RAG).',
|
|
198
|
+
'Embeddings: chave de API': 'Embeddings: chave de API',
|
|
199
|
+
'Chave do provedor de embeddings.': 'Chave do provedor de embeddings.',
|
|
200
|
+
'Embeddings: modelo': 'Embeddings: modelo',
|
|
201
|
+
'Padrão do provedor': 'Padrão do provedor',
|
|
202
|
+
'Modelos OpenAI para embeddings.': 'Modelos OpenAI para embeddings.',
|
|
203
|
+
'Embeddings: dimensoes': 'Embeddings: dimensões',
|
|
204
|
+
'Dimensoes do vetor de embedding (default 768).': 'Dimensões do vetor de embedding (default 768).',
|
|
205
|
+
'GPT models for text and chat.': 'Modelos GPT para texto e chat.',
|
|
206
|
+
'Synchronized with the LLM. The fields below follow the primary credential.': 'Sincronizado com o LLM. Os campos abaixo acompanham a credencial principal.',
|
|
207
|
+
'Example JSON: {"containerColor":"var(--md-sys-color-surface)","containerBorderColor":"var(--md-sys-color-outline-variant)","backdropColor":"var(--md-sys-color-scrim)"}': 'Ex.: {"containerColor":"var(--md-sys-color-surface)","containerBorderColor":"var(--md-sys-color-outline-variant)","backdropColor":"var(--md-sys-color-scrim)"}',
|
|
208
|
+
'Example JSON array: [{"id":"cancel","text":"Cancel","role":"secondary","close":true,"cssClass":"btn"},{"id":"confirm","text":"Delete","role":"primary","close":true,"cssClass":"btn btn-danger","icon":"delete"}]': 'Ex.: [{"id":"cancel","text":"Cancelar","role":"secondary","close":true,"cssClass":"btn"},{"id":"confirm","text":"Excluir","role":"primary","close":true,"cssClass":"btn btn-danger","icon":"delete"}]',
|
|
209
|
+
'Example JSON: {"containerColor":"var(--md-sys-color-surface)","containerBorderColor":"var(--md-sys-color-outline-variant)","backdropColor":"var(--md-sys-color-scrim)","actionButtonRadius":"8px"}': 'Ex.: {"containerColor":"var(--md-sys-color-surface)","containerBorderColor":"var(--md-sys-color-outline-variant)","backdropColor":"var(--md-sys-color-scrim)","actionButtonRadius":"8px"}',
|
|
210
|
+
'Desabilitar cache de schema (LocalStorage)': 'Desabilitar cache de schema (LocalStorage)',
|
|
211
|
+
'Se ativo, sempre baixa o schema do servidor (ignora cache local). Útil para desenvolvimento.': 'Se ativo, sempre baixa o schema do servidor (ignora cache local). Útil para desenvolvimento.',
|
|
212
|
+
'Paginação habilitada': 'Paginação habilitada',
|
|
213
|
+
'Tamanho da página': 'Tamanho da página',
|
|
214
|
+
'Ordenação habilitada': 'Ordenação habilitada',
|
|
215
|
+
'Seleção habilitada': 'Seleção habilitada',
|
|
216
|
+
'Paginação: estratégia': 'Paginação: estratégia',
|
|
217
|
+
'Ordenação: estratégia': 'Ordenação: estratégia',
|
|
218
|
+
'Paginação: botões Primeiro/Último': 'Paginação: botões Primeiro/Último',
|
|
219
|
+
'Toolbar visível': 'Toolbar visível',
|
|
220
|
+
'Cache & Persistência': 'Cache & Persistence',
|
|
221
|
+
Tabela: 'Table',
|
|
222
|
+
Salvar: 'Save',
|
|
223
|
+
Cancelar: 'Cancel',
|
|
224
|
+
Redefinir: 'Reset',
|
|
225
|
+
};
|
|
226
|
+
const PRAXIS_SETTINGS_PANEL_GLOBAL_CONFIG_EDITOR_EN_US = {
|
|
227
|
+
CRUD: 'CRUD',
|
|
228
|
+
'Dynamic Fields': 'Dynamic Fields',
|
|
229
|
+
'Cache & Persistence': 'Cache & Persistence',
|
|
230
|
+
Table: 'Table',
|
|
231
|
+
Dialog: 'Dialog',
|
|
232
|
+
'Settings saved': 'Settings saved',
|
|
233
|
+
'Save failed.': 'Save failed.',
|
|
234
|
+
'Global settings': 'Global settings',
|
|
235
|
+
'Global policies for opening, back and header': 'Global policies for opening, back and header',
|
|
236
|
+
'Server defaults (env vars)': 'Server defaults (env vars)',
|
|
237
|
+
'Saved configuration (UI) - overrides server defaults': 'Saved configuration (UI) - overrides server defaults',
|
|
238
|
+
'Failed to test connection.': 'Failed to test connection.',
|
|
239
|
+
'Connection established successfully!': 'Connection established successfully!',
|
|
240
|
+
'Unknown error': 'Unknown error',
|
|
241
|
+
'Key provided': 'Key provided',
|
|
242
|
+
'Saved key (****{{last4}})': 'Saved key (****{{last4}})',
|
|
243
|
+
'Saved key': 'Saved key',
|
|
244
|
+
'Test connection with the provided key': 'Test connection with the provided key',
|
|
245
|
+
'Test connection': 'Test connection',
|
|
246
|
+
'Refresh model list': 'Refresh model list',
|
|
247
|
+
Close: 'Close',
|
|
248
|
+
'This provider has no model catalog.': 'This provider has no model catalog.',
|
|
249
|
+
'Enter an API key to fetch models.': 'Enter an API key to fetch models.',
|
|
250
|
+
'Error fetching models.': 'Error fetching models.',
|
|
251
|
+
'Error fetching models. Check your API key.': 'Error fetching models. Check your API key.',
|
|
252
|
+
'Model list updated ({{count}} models)': 'Model list updated ({{count}} models)',
|
|
253
|
+
'Enter an API key to test.': 'Enter an API key to test.',
|
|
254
|
+
'No model details available.': 'No model details available.',
|
|
255
|
+
'Model: {{model}} | Tokens (in/out): {{in}}/{{out}} | Methods: {{methods}}': 'Model: {{model}} | Tokens (in/out): {{in}}/{{out}} | Methods: {{methods}}',
|
|
256
|
+
'Global config cleared. Using server defaults.': 'Global config cleared. Using server defaults.',
|
|
257
|
+
'Clear saved config and return to server defaults': 'Clear saved config and return to server defaults',
|
|
258
|
+
'Failed to clear global config.': 'Failed to clear global config.',
|
|
259
|
+
'No key required': 'No key required',
|
|
260
|
+
'Model & Behavior': 'Model & Behavior',
|
|
261
|
+
'Choose the model after validating the key.': 'Choose the model after validating the key.',
|
|
262
|
+
'API key validated required': 'Validated API key required',
|
|
263
|
+
'Configure and test your API key to unlock model selection.': 'Configure and test your API key to unlock model selection.',
|
|
264
|
+
'Embeddings (RAG)': 'Embeddings (RAG)',
|
|
265
|
+
'Use the LLM provider and key for embeddings': 'Apply the LLM provider and key to embeddings',
|
|
266
|
+
'Provider has no embeddings': 'Provider has no embeddings',
|
|
267
|
+
'Configure the embeddings provider for vector search (templates and schemas).': 'Configure the embeddings provider for vector search (templates and schemas).',
|
|
268
|
+
'Embedding dimension mismatch with database (768). Adjust to 768 or redo the migration.': 'Embedding dimension mismatch with the database (768). Adjust to 768 or redo the migration.',
|
|
269
|
+
'Toolbar, appearance and advanced filter': 'Toolbar, appearance and advanced filter',
|
|
270
|
+
'Defaults and variants (danger, info, success, question, error)': 'Defaults and variants (danger, info, success, question, error)',
|
|
271
|
+
'Icons by profile (shortcuts)': 'Icons by profile (shortcuts)',
|
|
272
|
+
'Pick icon': 'Pick icon',
|
|
273
|
+
'Pick icon for {{key}}': 'Pick icon for {{key}}',
|
|
274
|
+
'Clear icon': 'Clear icon',
|
|
275
|
+
'Clear icon for {{key}}': 'Clear icon for {{key}}',
|
|
276
|
+
'The text field above remains editable. These buttons only help with selection/clear preview.': 'The text field above remains editable. These buttons only help with selection/clear preview.',
|
|
277
|
+
'No saved key': 'No saved key',
|
|
278
|
+
'Aparência: densidade': 'Appearance: density',
|
|
279
|
+
compact: 'compact',
|
|
280
|
+
comfortable: 'comfortable',
|
|
281
|
+
spacious: 'spacious',
|
|
282
|
+
'Aparência: padding das células': 'Appearance: cell padding',
|
|
283
|
+
'Aceita 1 a 4 medidas CSS com unidade, var(...) ou calc(...). Ex.: 6px 12px': 'Accepts 1 to 4 CSS measures with units, var(...) or calc(...). Example: 6px 12px',
|
|
284
|
+
'Use 1 a 4 medidas CSS válidas, como 6px 12px.': 'Use 1 to 4 valid CSS measures, such as 6px 12px.',
|
|
285
|
+
'Aparência: padding do cabeçalho': 'Appearance: header padding',
|
|
286
|
+
'Aceita 1 a 4 medidas CSS com unidade, var(...) ou calc(...). Ex.: 8px 12px': 'Accepts 1 to 4 CSS measures with units, var(...) or calc(...). Example: 8px 12px',
|
|
287
|
+
'Use 1 a 4 medidas CSS válidas, como 8px 12px.': 'Use 1 to 4 valid CSS measures, such as 8px 12px.',
|
|
288
|
+
'Aparência: fonte das células': 'Appearance: cell font size',
|
|
289
|
+
'Aceita uma medida CSS com unidade, var(...) ou calc(...). Ex.: 13px': 'Accepts a CSS measure with units, var(...) or calc(...). Example: 13px',
|
|
290
|
+
'Use uma medida CSS válida, como 13px.': 'Use a valid CSS measure, such as 13px.',
|
|
291
|
+
'Aparência: fonte do cabeçalho': 'Appearance: header font size',
|
|
292
|
+
'Filtro: modo de abertura': 'Filter: open mode',
|
|
293
|
+
overlay: 'overlay',
|
|
294
|
+
'Filtro: overlay (visual)': 'Filter: overlay (visual)',
|
|
295
|
+
card: 'card',
|
|
296
|
+
frosted: 'frosted',
|
|
297
|
+
'Filtro: backdrop no overlay': 'Filter: overlay backdrop',
|
|
298
|
+
'Excluir — confirmação': 'Delete - confirmation',
|
|
299
|
+
'Excluir (múltiplos) — confirmação': 'Delete (multiple) - confirmation',
|
|
300
|
+
'Salvar — confirmação': 'Save - confirmation',
|
|
301
|
+
'Cancelar — confirmação': 'Cancel - confirmation',
|
|
302
|
+
'Exportar — confirmação': 'Export - confirmation',
|
|
303
|
+
'Excluir — progresso': 'Delete - progress',
|
|
304
|
+
'Excluir (múltiplos) — progresso': 'Delete (multiple) - progress',
|
|
305
|
+
'Excluir — sucesso': 'Delete - success',
|
|
306
|
+
'Salvar — sucesso': 'Save - success',
|
|
307
|
+
'Exportar — sucesso': 'Export - success',
|
|
308
|
+
'Importar — sucesso': 'Import - success',
|
|
309
|
+
'Excluir — erro': 'Delete - error',
|
|
310
|
+
'Salvar — erro': 'Save - error',
|
|
311
|
+
'Exportar — erro': 'Export - error',
|
|
312
|
+
'Rede — erro': 'Network - error',
|
|
313
|
+
'Permissão — erro': 'Permission - error',
|
|
314
|
+
'Modo de abertura padrão': 'Default opening mode',
|
|
315
|
+
Rota: 'Route',
|
|
316
|
+
'Aplicado quando ação/metadado não definem modo.': 'Applied when the action/metadata does not define a mode.',
|
|
317
|
+
'Confirmar ao sair com alterações': 'Confirm when leaving with unsaved changes',
|
|
318
|
+
'Back: estratégia': 'Back: strategy',
|
|
319
|
+
'Modal: largura (ex.: 900px)': 'Modal: width (e.g. 900px)',
|
|
320
|
+
'Modal: largura máxima (ex.: 96vw)': 'Modal: max width (e.g. 96vw)',
|
|
321
|
+
'Modal: backdrop': 'Modal: backdrop',
|
|
322
|
+
blur: 'blur',
|
|
323
|
+
dim: 'dim',
|
|
324
|
+
transparent: 'transparent',
|
|
325
|
+
'Estratégia de primeira carga quando metadado não definir.': 'First-load strategy when metadata does not define one.',
|
|
326
|
+
'Async Select, cascade and pagination': 'Async Select, cascade and pagination',
|
|
327
|
+
'Cascata nativa habilitada': 'Native cascade enabled',
|
|
328
|
+
'Cascata: loadOnChange': 'Cascade: loadOnChange',
|
|
329
|
+
respectLoadOn: 'respectLoadOn',
|
|
330
|
+
immediate: 'immediate',
|
|
331
|
+
manual: 'manual',
|
|
332
|
+
'Cascata: debounce (ms)': 'Cascade: debounce (ms)',
|
|
333
|
+
'Async Select: loadOn': 'Async Select: loadOn',
|
|
334
|
+
open: 'open',
|
|
335
|
+
init: 'init',
|
|
336
|
+
none: 'none',
|
|
337
|
+
'Async Select: pageSize': 'Async Select: pageSize',
|
|
338
|
+
'Async Select: usar cursor': 'Async Select: use cursor',
|
|
339
|
+
'LLM provider': 'LLM provider',
|
|
340
|
+
'Select the provider to list models and test the key.': 'Select the provider to list models and test the key.',
|
|
341
|
+
'API key': 'API key',
|
|
342
|
+
'Enter the selected provider key to test.': 'Enter the selected provider key to test.',
|
|
343
|
+
'AI model': 'AI model',
|
|
344
|
+
'Temperature (Creativity)': 'Temperature (Creativity)',
|
|
345
|
+
'0.0 (deterministic) to 1.0 (creative)': '0.0 (deterministic) to 1.0 (creative)',
|
|
346
|
+
'Assistant: risk validation': 'Assistant: risk validation',
|
|
347
|
+
'Standard': 'Standard',
|
|
348
|
+
'Strict requires confirmation for medium/high risk. Standard follows the indication returned by the backend.': 'Strict requires confirmation for medium/high risk. Standard follows the indication returned by the backend.',
|
|
349
|
+
'Use same LLM for embeddings': 'Use same LLM for embeddings',
|
|
350
|
+
'Replicates the LLM provider and key for embeddings.': 'Replicates the LLM provider and key for embeddings.',
|
|
351
|
+
'Embeddings provider': 'Embeddings provider',
|
|
352
|
+
'Provider used to generate embeddings (RAG).': 'Provider used to generate embeddings (RAG).',
|
|
353
|
+
'Embeddings API key': 'Embeddings API key',
|
|
354
|
+
'Embeddings provider key.': 'Embeddings provider key.',
|
|
355
|
+
'Embeddings model': 'Embeddings model',
|
|
356
|
+
'Provider default': 'Provider default',
|
|
357
|
+
'OpenAI models for embeddings.': 'OpenAI models for embeddings.',
|
|
358
|
+
'Embeddings: dimensions': 'Embeddings: dimensions',
|
|
359
|
+
'Embedding vector dimensions (default 768).': 'Embedding vector dimensions (default 768).',
|
|
360
|
+
'Artificial Intelligence': 'Artificial Intelligence',
|
|
361
|
+
'LLM integration': 'LLM integration',
|
|
362
|
+
'Appearance: density': 'Appearance: density',
|
|
363
|
+
'Appearance: cell padding': 'Appearance: cell padding',
|
|
364
|
+
'Accepts 1 to 4 CSS measures with units, var(...) or calc(...). Example: 6px 12px': 'Accepts 1 to 4 CSS measures with units, var(...) or calc(...). Example: 6px 12px',
|
|
365
|
+
'Use 1 to 4 valid CSS measures, such as 6px 12px.': 'Use 1 to 4 valid CSS measures, such as 6px 12px.',
|
|
366
|
+
'Appearance: header padding': 'Appearance: header padding',
|
|
367
|
+
'Accepts 1 to 4 CSS measures with units, var(...) or calc(...). Example: 8px 12px': 'Accepts 1 to 4 CSS measures with units, var(...) or calc(...). Example: 8px 12px',
|
|
368
|
+
'Use 1 to 4 valid CSS measures, such as 8px 12px.': 'Use 1 to 4 valid CSS measures, such as 8px 12px.',
|
|
369
|
+
'Appearance: cell font size': 'Appearance: cell font size',
|
|
370
|
+
'Accepts a CSS measure with units, var(...) or calc(...). Example: 13px': 'Accepts a CSS measure with units, var(...) or calc(...). Example: 13px',
|
|
371
|
+
'Use a valid CSS measure, such as 13px.': 'Use a valid CSS measure, such as 13px.',
|
|
372
|
+
'Appearance: header font size': 'Appearance: header font size',
|
|
373
|
+
'Provedor LLM': 'LLM provider',
|
|
374
|
+
'Selecione o provedor para listar modelos e testar a chave.': 'Select the provider to list models and test the key.',
|
|
375
|
+
'Chave de API': 'API key',
|
|
376
|
+
'Informe a chave do provedor selecionado para testar.': 'Enter the selected provider key to test.',
|
|
377
|
+
'Modelo de IA': 'AI model',
|
|
378
|
+
'Temperatura (Criatividade)': 'Temperature (Creativity)',
|
|
379
|
+
'0.0 (determinístico) a 1.0 (criativo)': '0.0 (deterministic) to 1.0 (creative)',
|
|
380
|
+
'Max tokens': 'Max tokens',
|
|
381
|
+
'Limite maximo de tokens na resposta.': 'Maximum token limit for the response.',
|
|
382
|
+
'Assistente: validação de risco': 'Assistant: risk validation',
|
|
383
|
+
'Estrito (recomendado)': 'Strict (recommended)',
|
|
384
|
+
'Padrão': 'Standard',
|
|
385
|
+
'Estrito exige confirmação em risco médio/alto. Padrão segue a indicação retornada pelo backend.': 'Strict requires confirmation for medium/high risk. Standard follows the indication returned by the backend.',
|
|
386
|
+
'Embeddings: usar mesmo LLM': 'Embeddings: use same LLM',
|
|
387
|
+
'Replica provedor e chave do LLM para embeddings.': 'Replicates the LLM provider and key for embeddings.',
|
|
388
|
+
'Embeddings: provedor': 'Embeddings: provider',
|
|
389
|
+
'Provedor usado para gerar embeddings (RAG).': 'Provider used to generate embeddings (RAG).',
|
|
390
|
+
'Embeddings: chave de API': 'Embeddings: API key',
|
|
391
|
+
'Chave do provedor de embeddings.': 'Embeddings provider key.',
|
|
392
|
+
'Embeddings: modelo': 'Embeddings: model',
|
|
393
|
+
'Padrão do provedor': 'Provider default',
|
|
394
|
+
'Modelos OpenAI para embeddings.': 'OpenAI models for embeddings.',
|
|
395
|
+
'Embeddings: dimensoes': 'Embeddings: dimensions',
|
|
396
|
+
'Dimensoes do vetor de embedding (default 768).': 'Embedding vector dimensions (default 768).',
|
|
397
|
+
'GPT models for text and chat.': 'GPT models for text and chat.',
|
|
398
|
+
'Synchronized with the LLM. The fields below follow the primary credential.': 'Synchronized with the LLM. The fields below follow the primary credential.',
|
|
399
|
+
'Example JSON: {"containerColor":"var(--md-sys-color-surface)","containerBorderColor":"var(--md-sys-color-outline-variant)","backdropColor":"var(--md-sys-color-scrim)"}': 'Example: {"containerColor":"var(--md-sys-color-surface)","containerBorderColor":"var(--md-sys-color-outline-variant)","backdropColor":"var(--md-sys-color-scrim)"}',
|
|
400
|
+
'Example JSON array: [{"id":"cancel","text":"Cancel","role":"secondary","close":true,"cssClass":"btn"},{"id":"confirm","text":"Delete","role":"primary","close":true,"cssClass":"btn btn-danger","icon":"delete"}]': 'Example: [{"id":"cancel","text":"Cancel","role":"secondary","close":true,"cssClass":"btn"},{"id":"confirm","text":"Delete","role":"primary","close":true,"cssClass":"btn btn-danger","icon":"delete"}]',
|
|
401
|
+
'Example JSON: {"containerColor":"var(--md-sys-color-surface)","containerBorderColor":"var(--md-sys-color-outline-variant)","backdropColor":"var(--md-sys-color-scrim)","actionButtonRadius":"8px"}': 'Example: {"containerColor":"var(--md-sys-color-surface)","containerBorderColor":"var(--md-sys-color-outline-variant)","backdropColor":"var(--md-sys-color-scrim)","actionButtonRadius":"8px"}',
|
|
402
|
+
'Desabilitar cache de schema (LocalStorage)': 'Disable schema cache (LocalStorage)',
|
|
403
|
+
'Se ativo, sempre baixa o schema do servidor (ignora cache local). Útil para desenvolvimento.': 'If enabled, always downloads the schema from the server (ignores local cache). Useful for development.',
|
|
404
|
+
'Paginação habilitada': 'Pagination enabled',
|
|
405
|
+
'Tamanho da página': 'Page size',
|
|
406
|
+
'Ordenação habilitada': 'Sorting enabled',
|
|
407
|
+
'Seleção habilitada': 'Selection enabled',
|
|
408
|
+
'Paginação: estratégia': 'Pagination: strategy',
|
|
409
|
+
'Ordenação: estratégia': 'Sorting: strategy',
|
|
410
|
+
'Paginação: botões Primeiro/Último': 'Pagination: First/Last buttons',
|
|
411
|
+
'Toolbar visível': 'Toolbar visible',
|
|
412
|
+
'Cache & Persistência': 'Cache & Persistence',
|
|
413
|
+
Tabela: 'Table',
|
|
414
|
+
Salvar: 'Save',
|
|
415
|
+
Cancelar: 'Cancel',
|
|
416
|
+
Redefinir: 'Reset',
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
const PRAXIS_SETTINGS_PANEL_EN_US = {
|
|
420
|
+
'Operation in progress...': 'Operation in progress...',
|
|
421
|
+
'The form contains errors that need to be fixed.': 'The form contains errors that need to be fixed.',
|
|
422
|
+
'No changes to apply or save.': 'No changes to apply or save.',
|
|
423
|
+
'Unsaved changes': 'Unsaved changes',
|
|
424
|
+
'Saved at {{time}}': 'Saved at {{time}}',
|
|
425
|
+
'No changes': 'No changes',
|
|
426
|
+
'Reset Changes': 'Reset Changes',
|
|
427
|
+
'Are you sure you want to reset all changes?': 'Are you sure you want to reset all changes?',
|
|
428
|
+
Reset: 'Reset',
|
|
429
|
+
Cancel: 'Cancel',
|
|
430
|
+
'Discard Changes': 'Discard Changes',
|
|
431
|
+
'You have unsaved changes. Are you sure you want to discard them?': 'You have unsaved changes. Are you sure you want to discard them?',
|
|
432
|
+
Discard: 'Discard',
|
|
433
|
+
'Continue Editing': 'Continue Editing',
|
|
434
|
+
'Collapse panel': 'Collapse panel',
|
|
435
|
+
'Expand panel': 'Expand panel',
|
|
436
|
+
Close: 'Close',
|
|
437
|
+
Apply: 'Apply',
|
|
438
|
+
'Save & Close': 'Save & Close',
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
const PRAXIS_SETTINGS_PANEL_PT_BR = {
|
|
442
|
+
'Operation in progress...': 'Operação em andamento...',
|
|
443
|
+
'The form contains errors that need to be fixed.': 'O formulário contém erros que precisam ser corrigidos.',
|
|
444
|
+
'No changes to apply or save.': 'Nenhuma alteração para aplicar ou salvar.',
|
|
445
|
+
'Unsaved changes': 'Alterações não salvas',
|
|
446
|
+
'Saved at {{time}}': 'Salvo às {{time}}',
|
|
447
|
+
'No changes': 'Sem alterações',
|
|
448
|
+
'Reset Changes': 'Redefinir Alterações',
|
|
449
|
+
'Are you sure you want to reset all changes?': 'Tem certeza de que deseja redefinir todas as alterações?',
|
|
450
|
+
Reset: 'Redefinir',
|
|
451
|
+
Cancel: 'Cancelar',
|
|
452
|
+
'Discard Changes': 'Descartar Alterações',
|
|
453
|
+
'You have unsaved changes. Are you sure you want to discard them?': 'Você tem alterações não salvas. Tem certeza de que deseja descartá-las?',
|
|
454
|
+
Discard: 'Descartar',
|
|
455
|
+
'Continue Editing': 'Continuar Editando',
|
|
456
|
+
'Collapse panel': 'Reduzir painel',
|
|
457
|
+
'Expand panel': 'Expandir painel',
|
|
458
|
+
Close: 'Fechar',
|
|
459
|
+
Apply: 'Aplicar',
|
|
460
|
+
'Save & Close': 'Salvar & Fechar',
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
const PRAXIS_SETTINGS_PANEL_I18N_NAMESPACE = 'praxis-settings-panel';
|
|
464
|
+
const PRAXIS_SETTINGS_PANEL_DEFAULT_TITLE = 'Global settings';
|
|
465
|
+
function providePraxisSettingsPanelI18n() {
|
|
466
|
+
return providePraxisI18n({
|
|
467
|
+
namespaces: {
|
|
468
|
+
[PRAXIS_SETTINGS_PANEL_I18N_NAMESPACE]: {
|
|
469
|
+
'pt-BR': {
|
|
470
|
+
...PRAXIS_SETTINGS_PANEL_PT_BR,
|
|
471
|
+
...PRAXIS_SETTINGS_PANEL_GLOBAL_CONFIG_EDITOR_PT_BR,
|
|
472
|
+
},
|
|
473
|
+
'en-US': {
|
|
474
|
+
...PRAXIS_SETTINGS_PANEL_EN_US,
|
|
475
|
+
...PRAXIS_SETTINGS_PANEL_GLOBAL_CONFIG_EDITOR_EN_US,
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
},
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
|
|
31
482
|
class SettingsPanelComponent {
|
|
32
483
|
cdr;
|
|
33
484
|
dialog;
|
|
@@ -42,6 +493,13 @@ class SettingsPanelComponent {
|
|
|
42
493
|
isValid = true;
|
|
43
494
|
isBusy = false;
|
|
44
495
|
lastSavedAt = null;
|
|
496
|
+
destroyRef = inject(DestroyRef);
|
|
497
|
+
i18n = inject(PraxisI18nService);
|
|
498
|
+
contentHost;
|
|
499
|
+
constructor(cdr, dialog) {
|
|
500
|
+
this.cdr = cdr;
|
|
501
|
+
this.dialog = dialog;
|
|
502
|
+
}
|
|
45
503
|
get canApply() {
|
|
46
504
|
return this.isDirty && this.isValid && !this.isBusy;
|
|
47
505
|
}
|
|
@@ -50,13 +508,13 @@ class SettingsPanelComponent {
|
|
|
50
508
|
}
|
|
51
509
|
get disabledReason() {
|
|
52
510
|
if (this.isBusy) {
|
|
53
|
-
return '
|
|
511
|
+
return this.tx('Operation in progress...');
|
|
54
512
|
}
|
|
55
513
|
if (!this.isValid) {
|
|
56
|
-
return '
|
|
514
|
+
return this.tx('The form contains errors that need to be fixed.');
|
|
57
515
|
}
|
|
58
516
|
if (!this.isDirty) {
|
|
59
|
-
return '
|
|
517
|
+
return this.tx('No changes to apply or save.');
|
|
60
518
|
}
|
|
61
519
|
return '';
|
|
62
520
|
}
|
|
@@ -71,27 +529,27 @@ class SettingsPanelComponent {
|
|
|
71
529
|
}
|
|
72
530
|
get statusMessage() {
|
|
73
531
|
if (this.statusTone === 'busy') {
|
|
74
|
-
return '
|
|
532
|
+
return this.tx('Operation in progress...');
|
|
75
533
|
}
|
|
76
534
|
if (this.statusTone === 'dirty') {
|
|
77
|
-
return '
|
|
535
|
+
return this.tx('Unsaved changes');
|
|
78
536
|
}
|
|
79
537
|
if (this.statusTone === 'saved' && this.lastSavedAt) {
|
|
80
|
-
return
|
|
538
|
+
return this.tx('Saved at {{time}}', {
|
|
539
|
+
time: this.formatClock(this.lastSavedAt),
|
|
540
|
+
});
|
|
81
541
|
}
|
|
82
|
-
return '
|
|
542
|
+
return this.tx('No changes');
|
|
83
543
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
constructor(cdr, dialog) {
|
|
87
|
-
this.cdr = cdr;
|
|
88
|
-
this.dialog = dialog;
|
|
544
|
+
tx(text, params) {
|
|
545
|
+
return this.i18n.t(text, params, text, PRAXIS_SETTINGS_PANEL_I18N_NAMESPACE);
|
|
89
546
|
}
|
|
90
|
-
attachContent(component, injector, ref) {
|
|
547
|
+
attachContent(component, injector, ref, inputs) {
|
|
91
548
|
this.ref = ref;
|
|
92
549
|
this.contentRef = this.contentHost.createComponent(component, {
|
|
93
550
|
injector,
|
|
94
551
|
});
|
|
552
|
+
this.applyInputs(this.contentRef, inputs);
|
|
95
553
|
const instance = this.contentRef.instance;
|
|
96
554
|
if (instance.isDirty$) {
|
|
97
555
|
instance.isDirty$
|
|
@@ -117,7 +575,6 @@ class SettingsPanelComponent {
|
|
|
117
575
|
this.cdr.markForCheck();
|
|
118
576
|
});
|
|
119
577
|
}
|
|
120
|
-
// Generic output bridging: if the embedded component emits `selected`, save and close.
|
|
121
578
|
try {
|
|
122
579
|
const selected$ = instance?.selected;
|
|
123
580
|
if (selected$ && typeof selected$.subscribe === 'function') {
|
|
@@ -125,19 +582,47 @@ class SettingsPanelComponent {
|
|
|
125
582
|
? selected$.pipe(takeUntilDestroyed(this.destroyRef))
|
|
126
583
|
: selected$;
|
|
127
584
|
obs.subscribe((value) => {
|
|
128
|
-
// Apply emits value to the opener without closing the panel.
|
|
129
585
|
this.ref.apply(value);
|
|
130
586
|
});
|
|
131
587
|
}
|
|
132
588
|
}
|
|
133
589
|
catch { }
|
|
134
590
|
}
|
|
591
|
+
applyInputs(contentRef, inputs) {
|
|
592
|
+
if (!inputs) {
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
const supportedInputs = this.resolveSupportedInputs(contentRef);
|
|
596
|
+
for (const [key, value] of Object.entries(inputs)) {
|
|
597
|
+
if (supportedInputs && !supportedInputs.has(key)) {
|
|
598
|
+
continue;
|
|
599
|
+
}
|
|
600
|
+
try {
|
|
601
|
+
if (typeof contentRef.setInput === 'function') {
|
|
602
|
+
contentRef.setInput(key, value);
|
|
603
|
+
}
|
|
604
|
+
else {
|
|
605
|
+
contentRef.instance[key] = value;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
catch { }
|
|
609
|
+
}
|
|
610
|
+
contentRef.changeDetectorRef.detectChanges();
|
|
611
|
+
}
|
|
612
|
+
resolveSupportedInputs(contentRef) {
|
|
613
|
+
const componentDef = contentRef.componentType?.ɵcmp;
|
|
614
|
+
const declaredInputs = componentDef?.inputs;
|
|
615
|
+
if (!declaredInputs || typeof declaredInputs !== 'object') {
|
|
616
|
+
return null;
|
|
617
|
+
}
|
|
618
|
+
return new Set(Object.keys(declaredInputs));
|
|
619
|
+
}
|
|
135
620
|
onReset() {
|
|
136
621
|
const dialogData = {
|
|
137
|
-
title: '
|
|
138
|
-
message: '
|
|
139
|
-
confirmText: '
|
|
140
|
-
cancelText: '
|
|
622
|
+
title: this.tx('Reset Changes'),
|
|
623
|
+
message: this.tx('Are you sure you want to reset all changes?'),
|
|
624
|
+
confirmText: this.tx('Reset'),
|
|
625
|
+
cancelText: this.tx('Cancel'),
|
|
141
626
|
type: 'warning',
|
|
142
627
|
icon: 'restart_alt',
|
|
143
628
|
};
|
|
@@ -189,15 +674,21 @@ class SettingsPanelComponent {
|
|
|
189
674
|
this.cdr.markForCheck();
|
|
190
675
|
}
|
|
191
676
|
formatClock(timestamp) {
|
|
677
|
+
const options = {
|
|
678
|
+
hour: '2-digit',
|
|
679
|
+
minute: '2-digit',
|
|
680
|
+
second: '2-digit',
|
|
681
|
+
};
|
|
192
682
|
try {
|
|
193
|
-
return new Intl.DateTimeFormat(
|
|
194
|
-
hour: '2-digit',
|
|
195
|
-
minute: '2-digit',
|
|
196
|
-
second: '2-digit',
|
|
197
|
-
}).format(timestamp);
|
|
683
|
+
return new Intl.DateTimeFormat(this.i18n.getLocale(), options).format(timestamp);
|
|
198
684
|
}
|
|
199
685
|
catch {
|
|
200
|
-
|
|
686
|
+
try {
|
|
687
|
+
return new Intl.DateTimeFormat(this.i18n.getFallbackLocale(), options).format(timestamp);
|
|
688
|
+
}
|
|
689
|
+
catch {
|
|
690
|
+
return '';
|
|
691
|
+
}
|
|
201
692
|
}
|
|
202
693
|
}
|
|
203
694
|
toggleExpand() {
|
|
@@ -211,10 +702,10 @@ class SettingsPanelComponent {
|
|
|
211
702
|
return of(true);
|
|
212
703
|
}
|
|
213
704
|
const dialogData = {
|
|
214
|
-
title: '
|
|
215
|
-
message: '
|
|
216
|
-
confirmText: '
|
|
217
|
-
cancelText: '
|
|
705
|
+
title: this.tx('Discard Changes'),
|
|
706
|
+
message: this.tx('You have unsaved changes. Are you sure you want to discard them?'),
|
|
707
|
+
confirmText: this.tx('Discard'),
|
|
708
|
+
cancelText: this.tx('Continue Editing'),
|
|
218
709
|
type: 'warning',
|
|
219
710
|
icon: 'warning',
|
|
220
711
|
};
|
|
@@ -235,13 +726,14 @@ class SettingsPanelComponent {
|
|
|
235
726
|
event.preventDefault();
|
|
236
727
|
this.onSave();
|
|
237
728
|
}
|
|
238
|
-
else if ((event.key === 's' || event.key === 'S') &&
|
|
729
|
+
else if ((event.key === 's' || event.key === 'S') &&
|
|
730
|
+
(event.ctrlKey || event.metaKey)) {
|
|
239
731
|
event.preventDefault();
|
|
240
732
|
this.onSave();
|
|
241
733
|
}
|
|
242
734
|
}
|
|
243
735
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: SettingsPanelComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
|
|
244
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: SettingsPanelComponent, isStandalone: true, selector: "praxis-settings-panel", host: { listeners: { "document:keydown": "handleKeydown($event)" } }, viewQueries: [{ propertyName: "contentHost", first: true, predicate: ["contentHost"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: "<div\n class=\"settings-panel\"\n data-testid=\"settings-panel-root\"\n [class.expanded]=\"expanded\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"titleId\"\n cdkTrapFocus\n cdkTrapFocusAutoCapture\n>\n <header class=\"settings-panel-header\">\n <h2 class=\"settings-panel-title\" [id]=\"titleId\">\n <mat-icon *ngIf=\"titleIcon\" class=\"title-icon\" [praxisIcon]=\"titleIcon\"></mat-icon>\n <span>{{ title }}</span>\n </h2>\n <span class=\"spacer\"></span>\n <button\n mat-icon-button\n type=\"button\"\n data-testid=\"settings-panel-toggle-expand\"\n [attr.aria-label]=\"expanded ? 'Reduzir painel' : 'Expandir painel'\"\n [attr.aria-expanded]=\"expanded\"\n [matTooltip]=\"expanded ? 'Reduzir painel' : 'Expandir painel'\"\n (click)=\"toggleExpand()\"\n >\n <mat-icon [praxisIcon]=\"expanded ? 'close_fullscreen' : 'open_in_full'\"></mat-icon>\n </button>\n <button\n mat-icon-button\n type=\"button\"\n data-testid=\"settings-panel-close-icon\"\n aria-label=\"Fechar\"\n matTooltip=\"Fechar\"\n (click)=\"onCancel()\"\n >\n <mat-icon [praxisIcon]=\"'close'\"></mat-icon>\n </button>\n </header>\n <div\n class=\"settings-panel-status\"\n [attr.data-status]=\"statusTone\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <mat-icon\n aria-hidden=\"true\"\n [praxisIcon]=\"\n statusTone === 'dirty'\n ? 'warning'\n : statusTone === 'saved'\n ? 'check_circle'\n : statusTone === 'busy'\n ? 'autorenew'\n : 'info'\n \"\n ></mat-icon>\n <span>{{ statusMessage }}</span>\n </div>\n <div class=\"settings-panel-body\">\n <ng-template #contentHost></ng-template>\n </div>\n <footer class=\"settings-panel-footer\">\n <button mat-button type=\"button\" data-testid=\"settings-panel-reset\" (click)=\"onReset()\" [disabled]=\"isBusy\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'restart_alt'\"></mat-icon>\n <span>Redefinir</span>\n </button>\n <span class=\"spacer\"></span>\n <button\n mat-button\n type=\"button\"\n data-testid=\"settings-panel-cancel\"\n (click)=\"onCancel()\"\n [disabled]=\"isBusy\"\n >\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'close'\"></mat-icon>\n <span>Cancelar</span>\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n data-testid=\"settings-panel-apply\"\n (click)=\"onApply()\"\n [disabled]=\"!canApply\"\n [matTooltip]=\"disabledReason\"\n [matTooltipDisabled]=\"canApply\"\n [attr.aria-busy]=\"isBusy\"\n >\n <mat-progress-spinner\n *ngIf=\"isBusy\"\n mode=\"indeterminate\"\n diameter=\"20\"\n ></mat-progress-spinner>\n <ng-container *ngIf=\"!isBusy\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'done'\"></mat-icon>\n <span>Aplicar</span>\n </ng-container>\n </button>\n <button\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n data-testid=\"settings-panel-save\"\n (click)=\"onSave()\"\n [disabled]=\"!canSave\"\n [matTooltip]=\"disabledReason\"\n [matTooltipDisabled]=\"canSave\"\n [attr.aria-busy]=\"isBusy\"\n >\n <mat-progress-spinner\n *ngIf=\"isBusy\"\n mode=\"indeterminate\"\n diameter=\"20\"\n ></mat-progress-spinner>\n <ng-container *ngIf=\"!isBusy\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'save'\"></mat-icon>\n <span>Salvar & Fechar</span>\n </ng-container>\n </button>\n </footer>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;height:100%}.settings-panel{display:grid;grid-template-rows:auto auto 1fr auto;grid-template-areas:\"header\" \"status\" \"body\" \"footer\";height:100%;background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface);border-left:1px solid var(--md-sys-color-outline-variant);width:var(--pfx-settings-panel-width, 720px);transition:width .3s ease;overflow:hidden}.settings-panel.expanded{width:min(var(--pfx-settings-panel-width-expanded, 95vw),var(--pfx-settings-panel-max-width, 2400px))}.settings-panel-header{grid-area:header;display:flex;align-items:center;gap:var(--pfx-settings-panel-header-gap, 8px);padding:0 var(--pfx-settings-panel-header-padding-x, 16px);height:var(--pfx-settings-panel-header-height, 64px);border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-high);box-shadow:var(--pfx-settings-panel-header-shadow, var(--md-sys-elevation-level1, 0 2px 6px rgba(0, 0, 0, .08)));flex-shrink:0}.settings-panel-header .spacer{flex:1}.settings-panel-status{grid-area:status;display:flex;align-items:center;gap:8px;min-height:36px;padding:6px 16px;border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface);font-size:.85rem;font-weight:500}.settings-panel-status mat-icon{width:18px;height:18px;font-size:18px}.settings-panel-status[data-status=dirty]{color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error-container) 30%,var(--md-sys-color-surface-container-high))}.settings-panel-status[data-status=saved]{color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 28%,var(--md-sys-color-surface-container-high))}.settings-panel-body{grid-area:body;overflow-y:auto;min-height:0;padding:var(--pfx-settings-panel-body-padding, 8px 8px 24px 8px);background:var(--md-sys-color-surface);display:flex;flex-direction:column}.settings-panel-content{display:block}.settings-panel-footer{grid-area:footer;border-top:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-high);box-shadow:var(--pfx-settings-panel-footer-shadow, var(--md-sys-elevation-level1, 0 -2px 6px rgba(0, 0, 0, .08)));display:flex;align-items:center;padding:var(--pfx-settings-panel-footer-padding, 12px 16px);column-gap:var(--pfx-settings-panel-footer-gap, 12px);flex-shrink:0}.spacer{flex:1}.settings-panel-title{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-title-gap, 8px);font-weight:700;letter-spacing:.2px;margin:0}.settings-panel-title mat-icon{color:var(--md-sys-color-primary)}.settings-panel-title .title-icon{width:20px;height:20px;font-size:20px}.settings-panel-footer button+button{margin-left:var(--pfx-settings-panel-footer-gap, 12px)}.settings-panel-footer button{display:inline-flex;align-items:center}.settings-panel-footer button .mat-icon{font-size:20px;width:20px;height:20px;line-height:1;display:inline-flex;align-items:center;justify-content:center}.settings-panel-footer .mat-button-wrapper{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-button-gap, 8px)}.settings-panel-footer .mat-progress-spinner{margin-right:8px}.settings-panel-footer .mat-flat-button[color=primary]{font-weight:600}:host ::ng-deep .settings-panel .mdc-button__label{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-button-gap, 8px);line-height:1}:host ::ng-deep .settings-panel .mdc-button__label>span{display:inline-flex;align-items:center;line-height:1}:host ::ng-deep .settings-panel .mdc-button__label .mat-icon{display:inline-flex;align-items:center;justify-content:center;line-height:1}:host ::ng-deep .praxis-settings-panel-backdrop{background:var(--pfx-backdrop, var(--md-sys-color-scrim, rgba(0, 0, 0, .45)));backdrop-filter:blur(var(--pfx-backdrop-blur, 6px)) saturate(110%);-webkit-backdrop-filter:blur(var(--pfx-backdrop-blur, 6px)) saturate(110%)}.settings-panel .mat-divider{background-color:var(--md-sys-color-outline-variant)!important}.settings-panel .mat-expansion-panel{background:var(--md-sys-color-surface-container);border:1px solid var(--md-sys-color-outline-variant);border-radius:var(--md-sys-shape-corner-medium, 12px);box-shadow:var(--md-sys-elevation-level1, 0 2px 8px rgba(0, 0, 0, .08))}.settings-panel .mat-expansion-panel-header{background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface)}.settings-panel .mat-expansion-panel-header mat-icon,.settings-panel .mat-expansion-panel-header .mat-icon{color:var(--md-sys-color-on-surface)!important}.settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-title,.settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description{color:var(--md-sys-color-on-surface)}.settings-panel .mat-expansion-panel-header .mat-expansion-indicator,.settings-panel .mat-expansion-panel-header .mat-expansion-indicator:after{color:var(--md-sys-color-on-surface-variant);border-color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .settings-panel .mat-expansion-panel .mat-expansion-panel-body{padding:8px}.settings-panel .mat-mdc-tab-group .mat-mdc-tab-header{border-bottom:1px solid var(--md-sys-color-outline-variant)}.settings-panel .mat-mdc-tab-group .mdc-tab .mdc-tab__text-label{color:var(--md-sys-color-on-surface-variant)}.settings-panel .mat-mdc-tab-group .mdc-tab.mdc-tab--active .mdc-tab__text-label{color:var(--md-sys-color-on-surface)}.settings-panel .mat-mdc-tab-group .mdc-tab-indicator__content--underline{border-color:var(--md-sys-color-primary)}.settings-panel .mat-mdc-form-field{--mdc-outlined-text-field-outline-color: var(--md-sys-color-outline-variant);--mdc-outlined-text-field-hover-outline-color: var(--md-sys-color-secondary, var(--md-sys-color-primary));--mdc-outlined-text-field-focus-outline-color: var(--md-sys-color-primary)}:host ::ng-deep .praxis-settings-panel-pane{position:fixed!important;top:0!important;right:0!important;height:100vh!important;z-index:1000}:host ::ng-deep .praxis-settings-panel-pane .settings-panel{pointer-events:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i6.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatDialogModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
736
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: SettingsPanelComponent, isStandalone: true, selector: "praxis-settings-panel", host: { listeners: { "document:keydown": "handleKeydown($event)" } }, providers: [providePraxisSettingsPanelI18n()], viewQueries: [{ propertyName: "contentHost", first: true, predicate: ["contentHost"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: "<div\n class=\"settings-panel\"\n data-testid=\"settings-panel-root\"\n [class.expanded]=\"expanded\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"titleId\"\n cdkTrapFocus\n cdkTrapFocusAutoCapture\n>\n <header class=\"settings-panel-header\">\n <h2 class=\"settings-panel-title\" [id]=\"titleId\">\n <mat-icon *ngIf=\"titleIcon\" class=\"title-icon\" [praxisIcon]=\"titleIcon\"></mat-icon>\n <span>{{ title }}</span>\n </h2>\n <span class=\"spacer\"></span>\n <button\n mat-icon-button\n type=\"button\"\n data-testid=\"settings-panel-toggle-expand\"\n [attr.aria-label]=\"expanded ? tx('Collapse panel') : tx('Expand panel')\"\n [attr.aria-expanded]=\"expanded\"\n [matTooltip]=\"expanded ? tx('Collapse panel') : tx('Expand panel')\"\n (click)=\"toggleExpand()\"\n >\n <mat-icon [praxisIcon]=\"expanded ? 'close_fullscreen' : 'open_in_full'\"></mat-icon>\n </button>\n <button\n mat-icon-button\n type=\"button\"\n data-testid=\"settings-panel-close-icon\"\n [attr.aria-label]=\"tx('Close')\"\n [matTooltip]=\"tx('Close')\"\n (click)=\"onCancel()\"\n >\n <mat-icon [praxisIcon]=\"'close'\"></mat-icon>\n </button>\n </header>\n <div\n class=\"settings-panel-status\"\n [attr.data-status]=\"statusTone\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <mat-icon\n aria-hidden=\"true\"\n [praxisIcon]=\"\n statusTone === 'dirty'\n ? 'warning'\n : statusTone === 'saved'\n ? 'check_circle'\n : statusTone === 'busy'\n ? 'autorenew'\n : 'info'\n \"\n ></mat-icon>\n <span>{{ statusMessage }}</span>\n </div>\n <div class=\"settings-panel-body\">\n <ng-template #contentHost></ng-template>\n </div>\n <footer class=\"settings-panel-footer\">\n <button mat-button type=\"button\" data-testid=\"settings-panel-reset\" (click)=\"onReset()\" [disabled]=\"isBusy\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'restart_alt'\"></mat-icon>\n <span>{{ tx('Reset') }}</span>\n </button>\n <span class=\"spacer\"></span>\n <button\n mat-button\n type=\"button\"\n data-testid=\"settings-panel-cancel\"\n (click)=\"onCancel()\"\n [disabled]=\"isBusy\"\n >\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'close'\"></mat-icon>\n <span>{{ tx('Cancel') }}</span>\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n data-testid=\"settings-panel-apply\"\n (click)=\"onApply()\"\n [disabled]=\"!canApply\"\n [matTooltip]=\"disabledReason\"\n [matTooltipDisabled]=\"canApply\"\n [attr.aria-busy]=\"isBusy\"\n >\n <mat-progress-spinner\n *ngIf=\"isBusy\"\n mode=\"indeterminate\"\n diameter=\"20\"\n ></mat-progress-spinner>\n <ng-container *ngIf=\"!isBusy\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'done'\"></mat-icon>\n <span>{{ tx('Apply') }}</span>\n </ng-container>\n </button>\n <button\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n data-testid=\"settings-panel-save\"\n (click)=\"onSave()\"\n [disabled]=\"!canSave\"\n [matTooltip]=\"disabledReason\"\n [matTooltipDisabled]=\"canSave\"\n [attr.aria-busy]=\"isBusy\"\n >\n <mat-progress-spinner\n *ngIf=\"isBusy\"\n mode=\"indeterminate\"\n diameter=\"20\"\n ></mat-progress-spinner>\n <ng-container *ngIf=\"!isBusy\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'save'\"></mat-icon>\n <span>{{ tx('Save & Close') }}</span>\n </ng-container>\n </button>\n </footer>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;height:100%}.settings-panel{display:grid;grid-template-rows:auto auto 1fr auto;grid-template-areas:\"header\" \"status\" \"body\" \"footer\";height:100%;background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface);border-left:1px solid var(--md-sys-color-outline-variant);width:var(--pfx-settings-panel-width, 720px);transition:width .3s ease;overflow:hidden}.settings-panel.expanded{width:min(var(--pfx-settings-panel-width-expanded, 95vw),var(--pfx-settings-panel-max-width, 2400px))}.settings-panel-header{grid-area:header;display:flex;align-items:center;gap:var(--pfx-settings-panel-header-gap, 8px);padding:0 var(--pfx-settings-panel-header-padding-x, 16px);height:var(--pfx-settings-panel-header-height, 64px);border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-high);box-shadow:var(--pfx-settings-panel-header-shadow, var(--md-sys-elevation-level1, 0 2px 6px rgba(0, 0, 0, .08)));flex-shrink:0}.settings-panel-header .spacer{flex:1}.settings-panel-status{grid-area:status;display:flex;align-items:center;gap:8px;min-height:36px;padding:6px 16px;border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface);font-size:.85rem;font-weight:500}.settings-panel-status mat-icon{width:18px;height:18px;font-size:18px}.settings-panel-status[data-status=dirty]{color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error-container) 30%,var(--md-sys-color-surface-container-high))}.settings-panel-status[data-status=saved]{color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 28%,var(--md-sys-color-surface-container-high))}.settings-panel-body{grid-area:body;overflow-y:auto;min-height:0;padding:var(--pfx-settings-panel-body-padding, 8px 8px 24px 8px);background:var(--md-sys-color-surface);display:flex;flex-direction:column}.settings-panel-content{display:block}.settings-panel-footer{grid-area:footer;border-top:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-high);box-shadow:var(--pfx-settings-panel-footer-shadow, var(--md-sys-elevation-level1, 0 -2px 6px rgba(0, 0, 0, .08)));display:flex;align-items:center;padding:var(--pfx-settings-panel-footer-padding, 12px 16px);column-gap:var(--pfx-settings-panel-footer-gap, 12px);flex-shrink:0}.spacer{flex:1}.settings-panel-title{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-title-gap, 8px);font-weight:700;letter-spacing:.2px;margin:0}.settings-panel-title mat-icon{color:var(--md-sys-color-primary)}.settings-panel-title .title-icon{width:20px;height:20px;font-size:20px}.settings-panel-footer button+button{margin-left:var(--pfx-settings-panel-footer-gap, 12px)}.settings-panel-footer button{display:inline-flex;align-items:center}.settings-panel-footer button .mat-icon{font-size:20px;width:20px;height:20px;line-height:1;display:inline-flex;align-items:center;justify-content:center}.settings-panel-footer .mat-button-wrapper{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-button-gap, 8px)}.settings-panel-footer .mat-progress-spinner{margin-right:8px}.settings-panel-footer .mat-flat-button[color=primary]{font-weight:600}:host ::ng-deep .settings-panel .mdc-button__label{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-button-gap, 8px);line-height:1}:host ::ng-deep .settings-panel .mdc-button__label>span{display:inline-flex;align-items:center;line-height:1}:host ::ng-deep .settings-panel .mdc-button__label .mat-icon{display:inline-flex;align-items:center;justify-content:center;line-height:1}:host ::ng-deep .praxis-settings-panel-backdrop{background:var(--pfx-backdrop, var(--md-sys-color-scrim, rgba(0, 0, 0, .45)));backdrop-filter:blur(var(--pfx-backdrop-blur, 6px)) saturate(110%);-webkit-backdrop-filter:blur(var(--pfx-backdrop-blur, 6px)) saturate(110%)}:host ::ng-deep .settings-panel .mat-divider{background-color:var(--md-sys-color-outline-variant)!important}:host ::ng-deep .settings-panel .mat-expansion-panel{background:var(--md-sys-color-surface-container);border:1px solid var(--md-sys-color-outline-variant);border-radius:var(--md-sys-shape-corner-medium, 12px);box-shadow:var(--md-sys-elevation-level1, 0 2px 8px rgba(0, 0, 0, .08));color:var(--md-sys-color-on-surface)}:host ::ng-deep .settings-panel .mat-expansion-panel-header{background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface)}:host ::ng-deep .settings-panel .mat-expansion-panel:not(.mat-expanded) .mat-expansion-panel-header:hover{background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 84%,var(--md-sys-color-primary) 16%)}:host ::ng-deep .settings-panel .mat-expansion-panel.mat-expanded>.mat-expansion-panel-header{background:var(--md-sys-color-surface-container-high)}:host ::ng-deep .settings-panel .mat-expansion-panel-header mat-icon,:host ::ng-deep .settings-panel .mat-expansion-panel-header .mat-icon{color:var(--md-sys-color-on-surface)!important}:host ::ng-deep .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-title,:host ::ng-deep .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description{color:var(--md-sys-color-on-surface)}:host ::ng-deep .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description{color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .settings-panel .mat-expansion-panel-header .mat-expansion-indicator,:host ::ng-deep .settings-panel .mat-expansion-panel-header .mat-expansion-indicator:after{color:var(--md-sys-color-on-surface-variant);border-color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .settings-panel .mat-expansion-panel .mat-action-row{border-top-color:var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low)}:host ::ng-deep .settings-panel .mat-expansion-panel .mat-expansion-panel-body{padding:8px}:host ::ng-deep .settings-panel .mat-mdc-tab-group .mat-mdc-tab-header{border-bottom:1px solid var(--md-sys-color-outline-variant);background:transparent}:host ::ng-deep .settings-panel .mat-mdc-tab-group .mdc-tab .mdc-tab__text-label{color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .settings-panel .mat-mdc-tab-group .mdc-tab.mdc-tab--active .mdc-tab__text-label{color:var(--md-sys-color-on-surface)}:host ::ng-deep .settings-panel .mat-mdc-tab-group .mdc-tab-indicator__content--underline{border-color:var(--md-sys-color-primary)}:host ::ng-deep .settings-panel .mat-mdc-card{background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface);box-shadow:var(--md-sys-elevation-level1, 0 2px 8px rgba(0, 0, 0, .08))}:host ::ng-deep .settings-panel .mat-mdc-card-subtitle,:host ::ng-deep .settings-panel .mat-mdc-card-content{color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .settings-panel .mat-mdc-card-title{color:var(--md-sys-color-on-surface)}:host ::ng-deep .settings-panel .mat-mdc-form-field{width:100%;--mdc-filled-text-field-container-color: var(--md-sys-color-surface-container);--mdc-filled-text-field-hover-container-color: var( --md-sys-color-surface-container-high );--mdc-filled-text-field-focus-container-color: var( --md-sys-color-surface-container-high );--mdc-filled-text-field-active-indicator-color: var( --md-sys-color-outline-variant );--mdc-filled-text-field-hover-active-indicator-color: var( --md-sys-color-secondary, var(--md-sys-color-primary) );--mdc-filled-text-field-focus-active-indicator-color: var( --md-sys-color-primary );--mdc-filled-text-field-label-text-color: var( --md-sys-color-on-surface-variant );--mdc-filled-text-field-focus-label-text-color: var(--md-sys-color-primary);--mdc-filled-text-field-input-text-color: var(--md-sys-color-on-surface);--mdc-filled-text-field-caret-color: var(--md-sys-color-primary);--mdc-outlined-text-field-outline-color: var(--md-sys-color-outline-variant);--mdc-outlined-text-field-hover-outline-color: var( --md-sys-color-secondary, var(--md-sys-color-primary) );--mdc-outlined-text-field-focus-outline-color: var(--md-sys-color-primary);--mdc-outlined-text-field-label-text-color: var( --md-sys-color-on-surface-variant );--mdc-outlined-text-field-focus-label-text-color: var(--md-sys-color-primary);--mdc-outlined-text-field-input-text-color: var(--md-sys-color-on-surface);--mdc-outlined-text-field-caret-color: var(--md-sys-color-primary);--mat-form-field-focus-select-arrow-color: var(--md-sys-color-primary);--mat-form-field-enabled-select-arrow-color: var( --md-sys-color-on-surface-variant )}:host ::ng-deep .settings-panel .mdc-text-field--filled{border-radius:var(--md-sys-shape-corner-small, 8px) var(--md-sys-shape-corner-small, 8px) 0 0}:host ::ng-deep .settings-panel .mat-mdc-form-field-subscript-wrapper,:host ::ng-deep .settings-panel .mat-mdc-form-field-hint-wrapper,:host ::ng-deep .settings-panel .mat-mdc-form-field-error-wrapper,:host ::ng-deep .settings-panel .mat-mdc-hint{color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .settings-panel .mat-button-toggle-group{border-color:var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low)}:host ::ng-deep .settings-panel .mat-button-toggle{background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .settings-panel .mat-button-toggle+.mat-button-toggle{border-left-color:var(--md-sys-color-outline-variant)}:host ::ng-deep .settings-panel .mat-button-toggle-checked{background:var(--md-sys-color-primary-container)!important;color:var(--md-sys-color-on-primary-container)!important}:host ::ng-deep .settings-panel .mat-button-toggle .mat-icon,:host ::ng-deep .settings-panel .mat-button-toggle-checked .mat-icon{color:inherit}:host ::ng-deep .praxis-settings-panel-pane{position:fixed!important;top:0!important;right:0!important;height:100vh!important;z-index:1000}:host ::ng-deep .praxis-settings-panel-pane .settings-panel{pointer-events:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i6.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatDialogModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
245
737
|
}
|
|
246
738
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: SettingsPanelComponent, decorators: [{
|
|
247
739
|
type: Component,
|
|
@@ -254,7 +746,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
254
746
|
CdkTrapFocus,
|
|
255
747
|
MatProgressSpinnerModule,
|
|
256
748
|
MatDialogModule,
|
|
257
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"settings-panel\"\n data-testid=\"settings-panel-root\"\n [class.expanded]=\"expanded\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"titleId\"\n cdkTrapFocus\n cdkTrapFocusAutoCapture\n>\n <header class=\"settings-panel-header\">\n <h2 class=\"settings-panel-title\" [id]=\"titleId\">\n <mat-icon *ngIf=\"titleIcon\" class=\"title-icon\" [praxisIcon]=\"titleIcon\"></mat-icon>\n <span>{{ title }}</span>\n </h2>\n <span class=\"spacer\"></span>\n <button\n mat-icon-button\n type=\"button\"\n data-testid=\"settings-panel-toggle-expand\"\n [attr.aria-label]=\"expanded ? 'Reduzir painel' : 'Expandir painel'\"\n [attr.aria-expanded]=\"expanded\"\n [matTooltip]=\"expanded ? 'Reduzir painel' : 'Expandir painel'\"\n (click)=\"toggleExpand()\"\n >\n <mat-icon [praxisIcon]=\"expanded ? 'close_fullscreen' : 'open_in_full'\"></mat-icon>\n </button>\n <button\n mat-icon-button\n type=\"button\"\n data-testid=\"settings-panel-close-icon\"\n aria-label=\"Fechar\"\n matTooltip=\"Fechar\"\n (click)=\"onCancel()\"\n >\n <mat-icon [praxisIcon]=\"'close'\"></mat-icon>\n </button>\n </header>\n <div\n class=\"settings-panel-status\"\n [attr.data-status]=\"statusTone\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <mat-icon\n aria-hidden=\"true\"\n [praxisIcon]=\"\n statusTone === 'dirty'\n ? 'warning'\n : statusTone === 'saved'\n ? 'check_circle'\n : statusTone === 'busy'\n ? 'autorenew'\n : 'info'\n \"\n ></mat-icon>\n <span>{{ statusMessage }}</span>\n </div>\n <div class=\"settings-panel-body\">\n <ng-template #contentHost></ng-template>\n </div>\n <footer class=\"settings-panel-footer\">\n <button mat-button type=\"button\" data-testid=\"settings-panel-reset\" (click)=\"onReset()\" [disabled]=\"isBusy\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'restart_alt'\"></mat-icon>\n <span>Redefinir</span>\n </button>\n <span class=\"spacer\"></span>\n <button\n mat-button\n type=\"button\"\n data-testid=\"settings-panel-cancel\"\n (click)=\"onCancel()\"\n [disabled]=\"isBusy\"\n >\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'close'\"></mat-icon>\n <span>Cancelar</span>\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n data-testid=\"settings-panel-apply\"\n (click)=\"onApply()\"\n [disabled]=\"!canApply\"\n [matTooltip]=\"disabledReason\"\n [matTooltipDisabled]=\"canApply\"\n [attr.aria-busy]=\"isBusy\"\n >\n <mat-progress-spinner\n *ngIf=\"isBusy\"\n mode=\"indeterminate\"\n diameter=\"20\"\n ></mat-progress-spinner>\n <ng-container *ngIf=\"!isBusy\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'done'\"></mat-icon>\n <span>Aplicar</span>\n </ng-container>\n </button>\n <button\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n data-testid=\"settings-panel-save\"\n (click)=\"onSave()\"\n [disabled]=\"!canSave\"\n [matTooltip]=\"disabledReason\"\n [matTooltipDisabled]=\"canSave\"\n [attr.aria-busy]=\"isBusy\"\n >\n <mat-progress-spinner\n *ngIf=\"isBusy\"\n mode=\"indeterminate\"\n diameter=\"20\"\n ></mat-progress-spinner>\n <ng-container *ngIf=\"!isBusy\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'save'\"></mat-icon>\n <span>Salvar & Fechar</span>\n </ng-container>\n </button>\n </footer>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;height:100%}.settings-panel{display:grid;grid-template-rows:auto auto 1fr auto;grid-template-areas:\"header\" \"status\" \"body\" \"footer\";height:100%;background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface);border-left:1px solid var(--md-sys-color-outline-variant);width:var(--pfx-settings-panel-width, 720px);transition:width .3s ease;overflow:hidden}.settings-panel.expanded{width:min(var(--pfx-settings-panel-width-expanded, 95vw),var(--pfx-settings-panel-max-width, 2400px))}.settings-panel-header{grid-area:header;display:flex;align-items:center;gap:var(--pfx-settings-panel-header-gap, 8px);padding:0 var(--pfx-settings-panel-header-padding-x, 16px);height:var(--pfx-settings-panel-header-height, 64px);border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-high);box-shadow:var(--pfx-settings-panel-header-shadow, var(--md-sys-elevation-level1, 0 2px 6px rgba(0, 0, 0, .08)));flex-shrink:0}.settings-panel-header .spacer{flex:1}.settings-panel-status{grid-area:status;display:flex;align-items:center;gap:8px;min-height:36px;padding:6px 16px;border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface);font-size:.85rem;font-weight:500}.settings-panel-status mat-icon{width:18px;height:18px;font-size:18px}.settings-panel-status[data-status=dirty]{color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error-container) 30%,var(--md-sys-color-surface-container-high))}.settings-panel-status[data-status=saved]{color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 28%,var(--md-sys-color-surface-container-high))}.settings-panel-body{grid-area:body;overflow-y:auto;min-height:0;padding:var(--pfx-settings-panel-body-padding, 8px 8px 24px 8px);background:var(--md-sys-color-surface);display:flex;flex-direction:column}.settings-panel-content{display:block}.settings-panel-footer{grid-area:footer;border-top:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-high);box-shadow:var(--pfx-settings-panel-footer-shadow, var(--md-sys-elevation-level1, 0 -2px 6px rgba(0, 0, 0, .08)));display:flex;align-items:center;padding:var(--pfx-settings-panel-footer-padding, 12px 16px);column-gap:var(--pfx-settings-panel-footer-gap, 12px);flex-shrink:0}.spacer{flex:1}.settings-panel-title{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-title-gap, 8px);font-weight:700;letter-spacing:.2px;margin:0}.settings-panel-title mat-icon{color:var(--md-sys-color-primary)}.settings-panel-title .title-icon{width:20px;height:20px;font-size:20px}.settings-panel-footer button+button{margin-left:var(--pfx-settings-panel-footer-gap, 12px)}.settings-panel-footer button{display:inline-flex;align-items:center}.settings-panel-footer button .mat-icon{font-size:20px;width:20px;height:20px;line-height:1;display:inline-flex;align-items:center;justify-content:center}.settings-panel-footer .mat-button-wrapper{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-button-gap, 8px)}.settings-panel-footer .mat-progress-spinner{margin-right:8px}.settings-panel-footer .mat-flat-button[color=primary]{font-weight:600}:host ::ng-deep .settings-panel .mdc-button__label{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-button-gap, 8px);line-height:1}:host ::ng-deep .settings-panel .mdc-button__label>span{display:inline-flex;align-items:center;line-height:1}:host ::ng-deep .settings-panel .mdc-button__label .mat-icon{display:inline-flex;align-items:center;justify-content:center;line-height:1}:host ::ng-deep .praxis-settings-panel-backdrop{background:var(--pfx-backdrop, var(--md-sys-color-scrim, rgba(0, 0, 0, .45)));backdrop-filter:blur(var(--pfx-backdrop-blur, 6px)) saturate(110%);-webkit-backdrop-filter:blur(var(--pfx-backdrop-blur, 6px)) saturate(110%)}.settings-panel .mat-divider{background-color:var(--md-sys-color-outline-variant)!important}.settings-panel .mat-expansion-panel{background:var(--md-sys-color-surface-container);border:1px solid var(--md-sys-color-outline-variant);border-radius:var(--md-sys-shape-corner-medium, 12px);box-shadow:var(--md-sys-elevation-level1, 0 2px 8px rgba(0, 0, 0, .08))}.settings-panel .mat-expansion-panel-header{background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface)}.settings-panel .mat-expansion-panel-header mat-icon,.settings-panel .mat-expansion-panel-header .mat-icon{color:var(--md-sys-color-on-surface)!important}.settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-title,.settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description{color:var(--md-sys-color-on-surface)}.settings-panel .mat-expansion-panel-header .mat-expansion-indicator,.settings-panel .mat-expansion-panel-header .mat-expansion-indicator:after{color:var(--md-sys-color-on-surface-variant);border-color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .settings-panel .mat-expansion-panel .mat-expansion-panel-body{padding:8px}.settings-panel .mat-mdc-tab-group .mat-mdc-tab-header{border-bottom:1px solid var(--md-sys-color-outline-variant)}.settings-panel .mat-mdc-tab-group .mdc-tab .mdc-tab__text-label{color:var(--md-sys-color-on-surface-variant)}.settings-panel .mat-mdc-tab-group .mdc-tab.mdc-tab--active .mdc-tab__text-label{color:var(--md-sys-color-on-surface)}.settings-panel .mat-mdc-tab-group .mdc-tab-indicator__content--underline{border-color:var(--md-sys-color-primary)}.settings-panel .mat-mdc-form-field{--mdc-outlined-text-field-outline-color: var(--md-sys-color-outline-variant);--mdc-outlined-text-field-hover-outline-color: var(--md-sys-color-secondary, var(--md-sys-color-primary));--mdc-outlined-text-field-focus-outline-color: var(--md-sys-color-primary)}:host ::ng-deep .praxis-settings-panel-pane{position:fixed!important;top:0!important;right:0!important;height:100vh!important;z-index:1000}:host ::ng-deep .praxis-settings-panel-pane .settings-panel{pointer-events:auto}\n"] }]
|
|
749
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, providers: [providePraxisSettingsPanelI18n()], template: "<div\n class=\"settings-panel\"\n data-testid=\"settings-panel-root\"\n [class.expanded]=\"expanded\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"titleId\"\n cdkTrapFocus\n cdkTrapFocusAutoCapture\n>\n <header class=\"settings-panel-header\">\n <h2 class=\"settings-panel-title\" [id]=\"titleId\">\n <mat-icon *ngIf=\"titleIcon\" class=\"title-icon\" [praxisIcon]=\"titleIcon\"></mat-icon>\n <span>{{ title }}</span>\n </h2>\n <span class=\"spacer\"></span>\n <button\n mat-icon-button\n type=\"button\"\n data-testid=\"settings-panel-toggle-expand\"\n [attr.aria-label]=\"expanded ? tx('Collapse panel') : tx('Expand panel')\"\n [attr.aria-expanded]=\"expanded\"\n [matTooltip]=\"expanded ? tx('Collapse panel') : tx('Expand panel')\"\n (click)=\"toggleExpand()\"\n >\n <mat-icon [praxisIcon]=\"expanded ? 'close_fullscreen' : 'open_in_full'\"></mat-icon>\n </button>\n <button\n mat-icon-button\n type=\"button\"\n data-testid=\"settings-panel-close-icon\"\n [attr.aria-label]=\"tx('Close')\"\n [matTooltip]=\"tx('Close')\"\n (click)=\"onCancel()\"\n >\n <mat-icon [praxisIcon]=\"'close'\"></mat-icon>\n </button>\n </header>\n <div\n class=\"settings-panel-status\"\n [attr.data-status]=\"statusTone\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <mat-icon\n aria-hidden=\"true\"\n [praxisIcon]=\"\n statusTone === 'dirty'\n ? 'warning'\n : statusTone === 'saved'\n ? 'check_circle'\n : statusTone === 'busy'\n ? 'autorenew'\n : 'info'\n \"\n ></mat-icon>\n <span>{{ statusMessage }}</span>\n </div>\n <div class=\"settings-panel-body\">\n <ng-template #contentHost></ng-template>\n </div>\n <footer class=\"settings-panel-footer\">\n <button mat-button type=\"button\" data-testid=\"settings-panel-reset\" (click)=\"onReset()\" [disabled]=\"isBusy\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'restart_alt'\"></mat-icon>\n <span>{{ tx('Reset') }}</span>\n </button>\n <span class=\"spacer\"></span>\n <button\n mat-button\n type=\"button\"\n data-testid=\"settings-panel-cancel\"\n (click)=\"onCancel()\"\n [disabled]=\"isBusy\"\n >\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'close'\"></mat-icon>\n <span>{{ tx('Cancel') }}</span>\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n data-testid=\"settings-panel-apply\"\n (click)=\"onApply()\"\n [disabled]=\"!canApply\"\n [matTooltip]=\"disabledReason\"\n [matTooltipDisabled]=\"canApply\"\n [attr.aria-busy]=\"isBusy\"\n >\n <mat-progress-spinner\n *ngIf=\"isBusy\"\n mode=\"indeterminate\"\n diameter=\"20\"\n ></mat-progress-spinner>\n <ng-container *ngIf=\"!isBusy\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'done'\"></mat-icon>\n <span>{{ tx('Apply') }}</span>\n </ng-container>\n </button>\n <button\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n data-testid=\"settings-panel-save\"\n (click)=\"onSave()\"\n [disabled]=\"!canSave\"\n [matTooltip]=\"disabledReason\"\n [matTooltipDisabled]=\"canSave\"\n [attr.aria-busy]=\"isBusy\"\n >\n <mat-progress-spinner\n *ngIf=\"isBusy\"\n mode=\"indeterminate\"\n diameter=\"20\"\n ></mat-progress-spinner>\n <ng-container *ngIf=\"!isBusy\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'save'\"></mat-icon>\n <span>{{ tx('Save & Close') }}</span>\n </ng-container>\n </button>\n </footer>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;height:100%}.settings-panel{display:grid;grid-template-rows:auto auto 1fr auto;grid-template-areas:\"header\" \"status\" \"body\" \"footer\";height:100%;background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface);border-left:1px solid var(--md-sys-color-outline-variant);width:var(--pfx-settings-panel-width, 720px);transition:width .3s ease;overflow:hidden}.settings-panel.expanded{width:min(var(--pfx-settings-panel-width-expanded, 95vw),var(--pfx-settings-panel-max-width, 2400px))}.settings-panel-header{grid-area:header;display:flex;align-items:center;gap:var(--pfx-settings-panel-header-gap, 8px);padding:0 var(--pfx-settings-panel-header-padding-x, 16px);height:var(--pfx-settings-panel-header-height, 64px);border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-high);box-shadow:var(--pfx-settings-panel-header-shadow, var(--md-sys-elevation-level1, 0 2px 6px rgba(0, 0, 0, .08)));flex-shrink:0}.settings-panel-header .spacer{flex:1}.settings-panel-status{grid-area:status;display:flex;align-items:center;gap:8px;min-height:36px;padding:6px 16px;border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface);font-size:.85rem;font-weight:500}.settings-panel-status mat-icon{width:18px;height:18px;font-size:18px}.settings-panel-status[data-status=dirty]{color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error-container) 30%,var(--md-sys-color-surface-container-high))}.settings-panel-status[data-status=saved]{color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 28%,var(--md-sys-color-surface-container-high))}.settings-panel-body{grid-area:body;overflow-y:auto;min-height:0;padding:var(--pfx-settings-panel-body-padding, 8px 8px 24px 8px);background:var(--md-sys-color-surface);display:flex;flex-direction:column}.settings-panel-content{display:block}.settings-panel-footer{grid-area:footer;border-top:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-high);box-shadow:var(--pfx-settings-panel-footer-shadow, var(--md-sys-elevation-level1, 0 -2px 6px rgba(0, 0, 0, .08)));display:flex;align-items:center;padding:var(--pfx-settings-panel-footer-padding, 12px 16px);column-gap:var(--pfx-settings-panel-footer-gap, 12px);flex-shrink:0}.spacer{flex:1}.settings-panel-title{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-title-gap, 8px);font-weight:700;letter-spacing:.2px;margin:0}.settings-panel-title mat-icon{color:var(--md-sys-color-primary)}.settings-panel-title .title-icon{width:20px;height:20px;font-size:20px}.settings-panel-footer button+button{margin-left:var(--pfx-settings-panel-footer-gap, 12px)}.settings-panel-footer button{display:inline-flex;align-items:center}.settings-panel-footer button .mat-icon{font-size:20px;width:20px;height:20px;line-height:1;display:inline-flex;align-items:center;justify-content:center}.settings-panel-footer .mat-button-wrapper{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-button-gap, 8px)}.settings-panel-footer .mat-progress-spinner{margin-right:8px}.settings-panel-footer .mat-flat-button[color=primary]{font-weight:600}:host ::ng-deep .settings-panel .mdc-button__label{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-button-gap, 8px);line-height:1}:host ::ng-deep .settings-panel .mdc-button__label>span{display:inline-flex;align-items:center;line-height:1}:host ::ng-deep .settings-panel .mdc-button__label .mat-icon{display:inline-flex;align-items:center;justify-content:center;line-height:1}:host ::ng-deep .praxis-settings-panel-backdrop{background:var(--pfx-backdrop, var(--md-sys-color-scrim, rgba(0, 0, 0, .45)));backdrop-filter:blur(var(--pfx-backdrop-blur, 6px)) saturate(110%);-webkit-backdrop-filter:blur(var(--pfx-backdrop-blur, 6px)) saturate(110%)}:host ::ng-deep .settings-panel .mat-divider{background-color:var(--md-sys-color-outline-variant)!important}:host ::ng-deep .settings-panel .mat-expansion-panel{background:var(--md-sys-color-surface-container);border:1px solid var(--md-sys-color-outline-variant);border-radius:var(--md-sys-shape-corner-medium, 12px);box-shadow:var(--md-sys-elevation-level1, 0 2px 8px rgba(0, 0, 0, .08));color:var(--md-sys-color-on-surface)}:host ::ng-deep .settings-panel .mat-expansion-panel-header{background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface)}:host ::ng-deep .settings-panel .mat-expansion-panel:not(.mat-expanded) .mat-expansion-panel-header:hover{background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 84%,var(--md-sys-color-primary) 16%)}:host ::ng-deep .settings-panel .mat-expansion-panel.mat-expanded>.mat-expansion-panel-header{background:var(--md-sys-color-surface-container-high)}:host ::ng-deep .settings-panel .mat-expansion-panel-header mat-icon,:host ::ng-deep .settings-panel .mat-expansion-panel-header .mat-icon{color:var(--md-sys-color-on-surface)!important}:host ::ng-deep .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-title,:host ::ng-deep .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description{color:var(--md-sys-color-on-surface)}:host ::ng-deep .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description{color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .settings-panel .mat-expansion-panel-header .mat-expansion-indicator,:host ::ng-deep .settings-panel .mat-expansion-panel-header .mat-expansion-indicator:after{color:var(--md-sys-color-on-surface-variant);border-color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .settings-panel .mat-expansion-panel .mat-action-row{border-top-color:var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low)}:host ::ng-deep .settings-panel .mat-expansion-panel .mat-expansion-panel-body{padding:8px}:host ::ng-deep .settings-panel .mat-mdc-tab-group .mat-mdc-tab-header{border-bottom:1px solid var(--md-sys-color-outline-variant);background:transparent}:host ::ng-deep .settings-panel .mat-mdc-tab-group .mdc-tab .mdc-tab__text-label{color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .settings-panel .mat-mdc-tab-group .mdc-tab.mdc-tab--active .mdc-tab__text-label{color:var(--md-sys-color-on-surface)}:host ::ng-deep .settings-panel .mat-mdc-tab-group .mdc-tab-indicator__content--underline{border-color:var(--md-sys-color-primary)}:host ::ng-deep .settings-panel .mat-mdc-card{background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface);box-shadow:var(--md-sys-elevation-level1, 0 2px 8px rgba(0, 0, 0, .08))}:host ::ng-deep .settings-panel .mat-mdc-card-subtitle,:host ::ng-deep .settings-panel .mat-mdc-card-content{color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .settings-panel .mat-mdc-card-title{color:var(--md-sys-color-on-surface)}:host ::ng-deep .settings-panel .mat-mdc-form-field{width:100%;--mdc-filled-text-field-container-color: var(--md-sys-color-surface-container);--mdc-filled-text-field-hover-container-color: var( --md-sys-color-surface-container-high );--mdc-filled-text-field-focus-container-color: var( --md-sys-color-surface-container-high );--mdc-filled-text-field-active-indicator-color: var( --md-sys-color-outline-variant );--mdc-filled-text-field-hover-active-indicator-color: var( --md-sys-color-secondary, var(--md-sys-color-primary) );--mdc-filled-text-field-focus-active-indicator-color: var( --md-sys-color-primary );--mdc-filled-text-field-label-text-color: var( --md-sys-color-on-surface-variant );--mdc-filled-text-field-focus-label-text-color: var(--md-sys-color-primary);--mdc-filled-text-field-input-text-color: var(--md-sys-color-on-surface);--mdc-filled-text-field-caret-color: var(--md-sys-color-primary);--mdc-outlined-text-field-outline-color: var(--md-sys-color-outline-variant);--mdc-outlined-text-field-hover-outline-color: var( --md-sys-color-secondary, var(--md-sys-color-primary) );--mdc-outlined-text-field-focus-outline-color: var(--md-sys-color-primary);--mdc-outlined-text-field-label-text-color: var( --md-sys-color-on-surface-variant );--mdc-outlined-text-field-focus-label-text-color: var(--md-sys-color-primary);--mdc-outlined-text-field-input-text-color: var(--md-sys-color-on-surface);--mdc-outlined-text-field-caret-color: var(--md-sys-color-primary);--mat-form-field-focus-select-arrow-color: var(--md-sys-color-primary);--mat-form-field-enabled-select-arrow-color: var( --md-sys-color-on-surface-variant )}:host ::ng-deep .settings-panel .mdc-text-field--filled{border-radius:var(--md-sys-shape-corner-small, 8px) var(--md-sys-shape-corner-small, 8px) 0 0}:host ::ng-deep .settings-panel .mat-mdc-form-field-subscript-wrapper,:host ::ng-deep .settings-panel .mat-mdc-form-field-hint-wrapper,:host ::ng-deep .settings-panel .mat-mdc-form-field-error-wrapper,:host ::ng-deep .settings-panel .mat-mdc-hint{color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .settings-panel .mat-button-toggle-group{border-color:var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low)}:host ::ng-deep .settings-panel .mat-button-toggle{background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .settings-panel .mat-button-toggle+.mat-button-toggle{border-left-color:var(--md-sys-color-outline-variant)}:host ::ng-deep .settings-panel .mat-button-toggle-checked{background:var(--md-sys-color-primary-container)!important;color:var(--md-sys-color-on-primary-container)!important}:host ::ng-deep .settings-panel .mat-button-toggle .mat-icon,:host ::ng-deep .settings-panel .mat-button-toggle-checked .mat-icon{color:inherit}:host ::ng-deep .praxis-settings-panel-pane{position:fixed!important;top:0!important;right:0!important;height:100vh!important;z-index:1000}:host ::ng-deep .praxis-settings-panel-pane .settings-panel{pointer-events:auto}\n"] }]
|
|
258
750
|
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1.MatDialog }], propDecorators: { contentHost: [{
|
|
259
751
|
type: ViewChild,
|
|
260
752
|
args: ['contentHost', { read: ViewContainerRef, static: true }]
|
|
@@ -311,13 +803,14 @@ class SettingsPanelRef {
|
|
|
311
803
|
}
|
|
312
804
|
}
|
|
313
805
|
|
|
314
|
-
const SETTINGS_PANEL_DATA =
|
|
806
|
+
const SETTINGS_PANEL_DATA = SETTINGS_PANEL_DATA$1;
|
|
315
807
|
const SETTINGS_PANEL_REF = new InjectionToken('SETTINGS_PANEL_REF');
|
|
316
808
|
|
|
317
809
|
class SettingsPanelService {
|
|
318
810
|
overlay;
|
|
319
811
|
injector;
|
|
320
812
|
currentRef;
|
|
813
|
+
i18n = inject(PraxisI18nService);
|
|
321
814
|
constructor(overlay, injector) {
|
|
322
815
|
this.overlay = overlay;
|
|
323
816
|
this.injector = injector;
|
|
@@ -343,7 +836,9 @@ class SettingsPanelService {
|
|
|
343
836
|
const ref = new SettingsPanelRef(overlayRef);
|
|
344
837
|
const panelPortal = new ComponentPortal(SettingsPanelComponent);
|
|
345
838
|
const panelRef = overlayRef.attach(panelPortal);
|
|
346
|
-
panelRef.instance.title = config.title
|
|
839
|
+
panelRef.instance.title = config.title?.trim()
|
|
840
|
+
? config.title
|
|
841
|
+
: this.i18n.t(PRAXIS_SETTINGS_PANEL_DEFAULT_TITLE, undefined, PRAXIS_SETTINGS_PANEL_DEFAULT_TITLE, PRAXIS_SETTINGS_PANEL_I18N_NAMESPACE);
|
|
347
842
|
panelRef.instance.titleIcon = config.titleIcon;
|
|
348
843
|
panelRef.instance.expanded = config.expanded || false;
|
|
349
844
|
const inputs = config.content.inputs;
|
|
@@ -359,7 +854,7 @@ class SettingsPanelService {
|
|
|
359
854
|
],
|
|
360
855
|
parent: this.injector,
|
|
361
856
|
});
|
|
362
|
-
panelRef.instance.attachContent(config.content.component, injector, ref);
|
|
857
|
+
panelRef.instance.attachContent(config.content.component, injector, ref, inputs);
|
|
363
858
|
overlayRef.backdropClick().subscribe(() => ref.close('backdrop'));
|
|
364
859
|
overlayRef.keydownEvents().subscribe((event) => {
|
|
365
860
|
if (event.key === 'Escape') {
|
|
@@ -386,6 +881,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
386
881
|
args: [{ providedIn: 'root' }]
|
|
387
882
|
}], ctorParameters: () => [{ type: i1$1.Overlay }, { type: i0.Injector }] });
|
|
388
883
|
|
|
884
|
+
function providePraxisSettingsPanelBridge() {
|
|
885
|
+
return {
|
|
886
|
+
provide: SETTINGS_PANEL_BRIDGE,
|
|
887
|
+
useFactory: (service) => ({
|
|
888
|
+
open: (opts) => service.open({
|
|
889
|
+
id: opts.id,
|
|
890
|
+
title: opts.title,
|
|
891
|
+
titleIcon: opts.titleIcon,
|
|
892
|
+
content: {
|
|
893
|
+
component: opts.content.component,
|
|
894
|
+
inputs: (opts.content.inputs || undefined),
|
|
895
|
+
},
|
|
896
|
+
}),
|
|
897
|
+
}),
|
|
898
|
+
deps: [SettingsPanelService],
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
|
|
389
902
|
/**
|
|
390
903
|
* Admin helper to load, patch and persist GlobalConfig.
|
|
391
904
|
* Intended to be used by the Global Config Editor UI.
|
|
@@ -425,6 +938,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
425
938
|
args: [{ providedIn: 'root' }]
|
|
426
939
|
}] });
|
|
427
940
|
|
|
941
|
+
function normalizeMojibakeText(text) {
|
|
942
|
+
if (!text.includes('\u00C3') &&
|
|
943
|
+
!text.includes('\u00C2') &&
|
|
944
|
+
!text.includes('\u00E2') &&
|
|
945
|
+
!text.includes('\u00AA') &&
|
|
946
|
+
!text.includes('\u00AB')) {
|
|
947
|
+
return text;
|
|
948
|
+
}
|
|
949
|
+
let current = text;
|
|
950
|
+
for (let i = 0; i < 3; i++) {
|
|
951
|
+
let next = current;
|
|
952
|
+
try {
|
|
953
|
+
next = decodeURIComponent(escape(current));
|
|
954
|
+
}
|
|
955
|
+
catch {
|
|
956
|
+
break;
|
|
957
|
+
}
|
|
958
|
+
if (next === current) {
|
|
959
|
+
break;
|
|
960
|
+
}
|
|
961
|
+
current = next;
|
|
962
|
+
if (!current.includes('\u00C3') &&
|
|
963
|
+
!current.includes('\u00C2') &&
|
|
964
|
+
!current.includes('\u00E2') &&
|
|
965
|
+
!current.includes('\u00AA') &&
|
|
966
|
+
!current.includes('\u00AB')) {
|
|
967
|
+
break;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
return current;
|
|
971
|
+
}
|
|
972
|
+
|
|
428
973
|
const TABLE_COMPACT_LENGTH_TOKEN$1 = '(?:0|(?:\\d+|\\d*\\.\\d+)(?:px|rem|em|%|vh|vw|svh|svw|lvh|lvw|dvh|dvw|ch|ex))';
|
|
429
974
|
const TABLE_COMPACT_SPACING_PATTERN = `^(?:var\\(.+\\)|calc\\(.+\\)|${TABLE_COMPACT_LENGTH_TOKEN$1}(?:\\s+${TABLE_COMPACT_LENGTH_TOKEN$1}){0,3})$`;
|
|
430
975
|
const TABLE_COMPACT_FONT_SIZE_PATTERN = `^(?:var\\(.+\\)|calc\\(.+\\)|${TABLE_COMPACT_LENGTH_TOKEN$1})$`;
|
|
@@ -435,30 +980,31 @@ function safeName(path) {
|
|
|
435
980
|
* Minimal FormConfig schema for the Global Config editor UI.
|
|
436
981
|
* This can be extended incrementally as new domains/settings are added.
|
|
437
982
|
*/
|
|
438
|
-
function buildGlobalConfigFormConfig() {
|
|
983
|
+
function buildGlobalConfigFormConfig(translate = (text) => text) {
|
|
984
|
+
const tx = (text, params) => translate(normalizeMojibakeText(text), params);
|
|
439
985
|
const fields = [
|
|
440
986
|
// CRUD
|
|
441
987
|
{
|
|
442
988
|
name: safeName('crud.defaults.openMode'),
|
|
443
|
-
label: 'Modo de abertura padrão',
|
|
989
|
+
label: tx('Modo de abertura padrão'),
|
|
444
990
|
controlType: FieldControlType.SELECT,
|
|
445
991
|
selectOptions: [
|
|
446
|
-
{ text: 'Rota', value: 'route' },
|
|
992
|
+
{ text: tx('Rota'), value: 'route' },
|
|
447
993
|
{ text: 'Modal', value: 'modal' },
|
|
448
994
|
{ text: 'Drawer', value: 'drawer' },
|
|
449
995
|
],
|
|
450
|
-
hint: 'Aplicado quando ação/metadado não definem modo.',
|
|
996
|
+
hint: tx('Aplicado quando ação/metadado não definem modo.'),
|
|
451
997
|
dataAttributes: { globalPath: 'crud.defaults.openMode' },
|
|
452
998
|
},
|
|
453
999
|
{
|
|
454
1000
|
name: safeName('crud.defaults.back.confirmOnDirty'),
|
|
455
|
-
label: 'Confirmar ao sair com alterações',
|
|
1001
|
+
label: tx('Confirmar ao sair com alterações'),
|
|
456
1002
|
controlType: FieldControlType.TOGGLE,
|
|
457
1003
|
dataAttributes: { globalPath: 'crud.defaults.back.confirmOnDirty' },
|
|
458
1004
|
},
|
|
459
1005
|
{
|
|
460
1006
|
name: safeName('crud.defaults.back.strategy'),
|
|
461
|
-
label: 'Back: estratégia',
|
|
1007
|
+
label: tx('Back: estratégia'),
|
|
462
1008
|
controlType: FieldControlType.SELECT,
|
|
463
1009
|
selectOptions: [
|
|
464
1010
|
{ text: 'auto', value: 'auto' },
|
|
@@ -469,13 +1015,13 @@ function buildGlobalConfigFormConfig() {
|
|
|
469
1015
|
},
|
|
470
1016
|
{
|
|
471
1017
|
name: safeName('crud.defaults.header.showBack'),
|
|
472
|
-
label: 'Header:
|
|
1018
|
+
label: tx('Header: show back'),
|
|
473
1019
|
controlType: FieldControlType.TOGGLE,
|
|
474
1020
|
dataAttributes: { globalPath: 'crud.defaults.header.showBack' },
|
|
475
1021
|
},
|
|
476
1022
|
{
|
|
477
1023
|
name: safeName('crud.defaults.header.variant'),
|
|
478
|
-
label: 'Header:
|
|
1024
|
+
label: tx('Header: variant'),
|
|
479
1025
|
controlType: FieldControlType.SELECT,
|
|
480
1026
|
selectOptions: [
|
|
481
1027
|
{ text: 'ghost', value: 'ghost' },
|
|
@@ -486,31 +1032,31 @@ function buildGlobalConfigFormConfig() {
|
|
|
486
1032
|
},
|
|
487
1033
|
{
|
|
488
1034
|
name: safeName('crud.defaults.header.sticky'),
|
|
489
|
-
label: 'Header:
|
|
1035
|
+
label: tx('Header: sticky'),
|
|
490
1036
|
controlType: FieldControlType.TOGGLE,
|
|
491
1037
|
dataAttributes: { globalPath: 'crud.defaults.header.sticky' },
|
|
492
1038
|
},
|
|
493
1039
|
{
|
|
494
1040
|
name: safeName('crud.defaults.header.divider'),
|
|
495
|
-
label: 'Header:
|
|
1041
|
+
label: tx('Header: show divider'),
|
|
496
1042
|
controlType: FieldControlType.TOGGLE,
|
|
497
1043
|
dataAttributes: { globalPath: 'crud.defaults.header.divider' },
|
|
498
1044
|
},
|
|
499
1045
|
{
|
|
500
1046
|
name: safeName('crud.defaults.modal.width'),
|
|
501
|
-
label: 'Modal:
|
|
1047
|
+
label: tx('Modal: width (e.g. 900px)'),
|
|
502
1048
|
controlType: FieldControlType.INPUT,
|
|
503
1049
|
dataAttributes: { globalPath: 'crud.defaults.modal.width' },
|
|
504
1050
|
},
|
|
505
1051
|
{
|
|
506
1052
|
name: safeName('crud.defaults.modal.maxWidth'),
|
|
507
|
-
label: 'Modal: largura máxima (ex.: 96vw)',
|
|
1053
|
+
label: tx('Modal: largura máxima (ex.: 96vw)'),
|
|
508
1054
|
controlType: FieldControlType.INPUT,
|
|
509
1055
|
dataAttributes: { globalPath: 'crud.defaults.modal.maxWidth' },
|
|
510
1056
|
},
|
|
511
1057
|
{
|
|
512
1058
|
name: safeName('crud.defaults.modal.backdropStyle'),
|
|
513
|
-
label: 'Modal: backdrop',
|
|
1059
|
+
label: tx('Modal: backdrop'),
|
|
514
1060
|
controlType: FieldControlType.SELECT,
|
|
515
1061
|
selectOptions: [
|
|
516
1062
|
{ text: 'blur', value: 'blur' },
|
|
@@ -522,25 +1068,25 @@ function buildGlobalConfigFormConfig() {
|
|
|
522
1068
|
// Dynamic Fields
|
|
523
1069
|
{
|
|
524
1070
|
name: safeName('dynamicFields.asyncSelect.loadOn'),
|
|
525
|
-
label: 'Async Select: loadOn',
|
|
1071
|
+
label: tx('Async Select: loadOn'),
|
|
526
1072
|
controlType: FieldControlType.SELECT,
|
|
527
1073
|
selectOptions: [
|
|
528
1074
|
{ text: 'open', value: 'open' },
|
|
529
1075
|
{ text: 'init', value: 'init' },
|
|
530
1076
|
{ text: 'none', value: 'none' },
|
|
531
1077
|
],
|
|
532
|
-
hint: 'Estratégia de primeira carga quando metadado não definir.',
|
|
1078
|
+
hint: tx('Estratégia de primeira carga quando metadado não definir.'),
|
|
533
1079
|
dataAttributes: { globalPath: 'dynamicFields.asyncSelect.loadOn' },
|
|
534
1080
|
},
|
|
535
1081
|
{
|
|
536
1082
|
name: safeName('dynamicFields.cascade.enable'),
|
|
537
|
-
label: '
|
|
1083
|
+
label: tx('Native cascade enabled'),
|
|
538
1084
|
controlType: FieldControlType.TOGGLE,
|
|
539
1085
|
dataAttributes: { globalPath: 'dynamicFields.cascade.enable' },
|
|
540
1086
|
},
|
|
541
1087
|
{
|
|
542
1088
|
name: safeName('dynamicFields.cascade.loadOnChange'),
|
|
543
|
-
label: '
|
|
1089
|
+
label: tx('Cascade: loadOnChange'),
|
|
544
1090
|
controlType: FieldControlType.SELECT,
|
|
545
1091
|
selectOptions: [
|
|
546
1092
|
{ text: 'respectLoadOn', value: 'respectLoadOn' },
|
|
@@ -551,42 +1097,42 @@ function buildGlobalConfigFormConfig() {
|
|
|
551
1097
|
},
|
|
552
1098
|
{
|
|
553
1099
|
name: safeName('dynamicFields.cascade.debounceMs'),
|
|
554
|
-
label: '
|
|
1100
|
+
label: tx('Cascade: debounce (ms)'),
|
|
555
1101
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
556
1102
|
dataAttributes: { globalPath: 'dynamicFields.cascade.debounceMs' },
|
|
557
1103
|
},
|
|
558
1104
|
// Dynamic Fields async-select extra
|
|
559
1105
|
{
|
|
560
1106
|
name: safeName('dynamicFields.asyncSelect.pageSize'),
|
|
561
|
-
label: 'Async Select: pageSize',
|
|
1107
|
+
label: tx('Async Select: pageSize'),
|
|
562
1108
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
563
1109
|
dataAttributes: { globalPath: 'dynamicFields.asyncSelect.pageSize' },
|
|
564
1110
|
},
|
|
565
1111
|
{
|
|
566
1112
|
name: safeName('dynamicFields.asyncSelect.useCursor'),
|
|
567
|
-
label: 'Async Select:
|
|
1113
|
+
label: tx('Async Select: use cursor'),
|
|
568
1114
|
controlType: FieldControlType.TOGGLE,
|
|
569
1115
|
dataAttributes: { globalPath: 'dynamicFields.asyncSelect.useCursor' },
|
|
570
1116
|
},
|
|
571
1117
|
// AI
|
|
572
1118
|
{
|
|
573
1119
|
name: safeName('ai.provider'),
|
|
574
|
-
label: '
|
|
1120
|
+
label: tx('LLM provider'),
|
|
575
1121
|
controlType: FieldControlType.SELECT,
|
|
576
1122
|
selectOptions: [],
|
|
577
|
-
hint: '
|
|
1123
|
+
hint: tx('Select the provider to list models and test the key.'),
|
|
578
1124
|
dataAttributes: { globalPath: 'ai.provider' },
|
|
579
1125
|
},
|
|
580
1126
|
{
|
|
581
1127
|
name: safeName('ai.apiKey'),
|
|
582
|
-
label: '
|
|
1128
|
+
label: tx('API key'),
|
|
583
1129
|
controlType: FieldControlType.INPUT,
|
|
584
|
-
hint: '
|
|
1130
|
+
hint: tx('Enter the selected provider key to test.'),
|
|
585
1131
|
dataAttributes: { globalPath: 'ai.apiKey' },
|
|
586
1132
|
},
|
|
587
1133
|
{
|
|
588
1134
|
name: safeName('ai.model'),
|
|
589
|
-
label: '
|
|
1135
|
+
label: tx('AI model'),
|
|
590
1136
|
controlType: FieldControlType.SEARCHABLE_SELECT,
|
|
591
1137
|
selectOptions: [],
|
|
592
1138
|
resourcePath: '',
|
|
@@ -594,113 +1140,113 @@ function buildGlobalConfigFormConfig() {
|
|
|
594
1140
|
},
|
|
595
1141
|
{
|
|
596
1142
|
name: safeName('ai.temperature'),
|
|
597
|
-
label: '
|
|
1143
|
+
label: tx('Temperature (Creativity)'),
|
|
598
1144
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
599
|
-
hint: '0.0 (
|
|
1145
|
+
hint: tx('0.0 (deterministic) to 1.0 (creative)'),
|
|
600
1146
|
dataAttributes: { globalPath: 'ai.temperature' },
|
|
601
1147
|
},
|
|
602
1148
|
{
|
|
603
1149
|
name: safeName('ai.maxTokens'),
|
|
604
|
-
label: 'Max tokens',
|
|
1150
|
+
label: tx('Max tokens'),
|
|
605
1151
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
606
|
-
hint: '
|
|
1152
|
+
hint: tx('Maximum token limit for the response.'),
|
|
607
1153
|
dataAttributes: { globalPath: 'ai.maxTokens' },
|
|
608
1154
|
},
|
|
609
1155
|
{
|
|
610
1156
|
name: safeName('ai.riskPolicy'),
|
|
611
|
-
label: '
|
|
1157
|
+
label: tx('Assistant: risk validation'),
|
|
612
1158
|
controlType: FieldControlType.SELECT,
|
|
613
1159
|
selectOptions: [
|
|
614
|
-
{ text: '
|
|
615
|
-
{ text: '
|
|
1160
|
+
{ text: 'Strict (recommended)', value: 'strict' },
|
|
1161
|
+
{ text: tx('Standard'), value: 'standard' },
|
|
616
1162
|
],
|
|
617
|
-
hint: '
|
|
1163
|
+
hint: tx('Strict requires confirmation for medium/high risk. Standard follows the indication returned by the backend.'),
|
|
618
1164
|
dataAttributes: { globalPath: 'ai.riskPolicy' },
|
|
619
1165
|
},
|
|
620
1166
|
{
|
|
621
1167
|
name: safeName('ai.embedding.useSameAsLlm'),
|
|
622
|
-
label: '
|
|
1168
|
+
label: tx('Use same LLM for embeddings'),
|
|
623
1169
|
controlType: FieldControlType.TOGGLE,
|
|
624
|
-
hint: '
|
|
1170
|
+
hint: tx('Replicates the LLM provider and key for embeddings.'),
|
|
625
1171
|
dataAttributes: { globalPath: 'ai.embedding.useSameAsLlm' },
|
|
626
1172
|
},
|
|
627
1173
|
{
|
|
628
1174
|
name: safeName('ai.embedding.provider'),
|
|
629
|
-
label: 'Embeddings
|
|
1175
|
+
label: tx('Embeddings provider'),
|
|
630
1176
|
controlType: FieldControlType.SELECT,
|
|
631
1177
|
selectOptions: [],
|
|
632
|
-
hint: '
|
|
1178
|
+
hint: tx('Provider used to generate embeddings (RAG).'),
|
|
633
1179
|
dataAttributes: { globalPath: 'ai.embedding.provider' },
|
|
634
1180
|
},
|
|
635
1181
|
{
|
|
636
1182
|
name: safeName('ai.embedding.apiKey'),
|
|
637
|
-
label: 'Embeddings
|
|
1183
|
+
label: tx('Embeddings API key'),
|
|
638
1184
|
controlType: FieldControlType.INPUT,
|
|
639
|
-
hint: '
|
|
1185
|
+
hint: tx('Embeddings provider key.'),
|
|
640
1186
|
dataAttributes: { globalPath: 'ai.embedding.apiKey' },
|
|
641
1187
|
},
|
|
642
1188
|
{
|
|
643
1189
|
name: safeName('ai.embedding.model'),
|
|
644
|
-
label: 'Embeddings
|
|
1190
|
+
label: tx('Embeddings model'),
|
|
645
1191
|
controlType: FieldControlType.SEARCHABLE_SELECT,
|
|
646
1192
|
selectOptions: [
|
|
647
1193
|
{ text: 'text-embedding-3-large', value: 'text-embedding-3-large' },
|
|
648
1194
|
{ text: 'text-embedding-3-small', value: 'text-embedding-3-small' },
|
|
649
1195
|
{ text: 'text-embedding-ada-002 (legacy)', value: 'text-embedding-ada-002' },
|
|
650
1196
|
],
|
|
651
|
-
emptyOptionText: '
|
|
652
|
-
hint: '
|
|
1197
|
+
emptyOptionText: tx('Provider default'),
|
|
1198
|
+
hint: tx('OpenAI models for embeddings.'),
|
|
653
1199
|
dataAttributes: { globalPath: 'ai.embedding.model' },
|
|
654
1200
|
},
|
|
655
1201
|
{
|
|
656
1202
|
name: safeName('ai.embedding.dimensions'),
|
|
657
|
-
label: 'Embeddings:
|
|
1203
|
+
label: tx('Embeddings: dimensions'),
|
|
658
1204
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
659
|
-
hint: '
|
|
1205
|
+
hint: tx('Embedding vector dimensions (default 768).'),
|
|
660
1206
|
dataAttributes: { globalPath: 'ai.embedding.dimensions' },
|
|
661
1207
|
},
|
|
662
|
-
// Cache
|
|
1208
|
+
// Cache // Cache
|
|
663
1209
|
{
|
|
664
1210
|
name: safeName('cache.disableSchemaCache'),
|
|
665
|
-
label: 'Desabilitar cache de schema (LocalStorage)',
|
|
1211
|
+
label: tx('Desabilitar cache de schema (LocalStorage)'),
|
|
666
1212
|
controlType: FieldControlType.TOGGLE,
|
|
667
|
-
hint: 'Se ativo, sempre baixa o schema do servidor (ignora cache local). Útil para desenvolvimento.',
|
|
1213
|
+
hint: tx('Se ativo, sempre baixa o schema do servidor (ignora cache local). Útil para desenvolvimento.'),
|
|
668
1214
|
dataAttributes: { globalPath: 'cache.disableSchemaCache' },
|
|
669
1215
|
},
|
|
670
1216
|
// Table
|
|
671
1217
|
{
|
|
672
1218
|
name: safeName('table.behavior.pagination.enabled'),
|
|
673
|
-
label: 'Paginação habilitada',
|
|
1219
|
+
label: tx('Paginação habilitada'),
|
|
674
1220
|
controlType: FieldControlType.TOGGLE,
|
|
675
1221
|
dataAttributes: { globalPath: 'table.behavior.pagination.enabled' },
|
|
676
1222
|
},
|
|
677
1223
|
{
|
|
678
1224
|
name: safeName('table.behavior.pagination.pageSize'),
|
|
679
|
-
label: 'Tamanho da página',
|
|
1225
|
+
label: tx('Tamanho da página'),
|
|
680
1226
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
681
1227
|
dataAttributes: { globalPath: 'table.behavior.pagination.pageSize' },
|
|
682
1228
|
},
|
|
683
1229
|
{
|
|
684
1230
|
name: safeName('table.behavior.filtering.debounceTime'),
|
|
685
|
-
label: '
|
|
1231
|
+
label: tx('Filter debounce (ms)'),
|
|
686
1232
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
687
1233
|
dataAttributes: { globalPath: 'table.behavior.filtering.debounceTime' },
|
|
688
1234
|
},
|
|
689
1235
|
{
|
|
690
1236
|
name: safeName('table.behavior.sorting.enabled'),
|
|
691
|
-
label: 'Ordenação habilitada',
|
|
1237
|
+
label: tx('Ordenação habilitada'),
|
|
692
1238
|
controlType: FieldControlType.TOGGLE,
|
|
693
1239
|
dataAttributes: { globalPath: 'table.behavior.sorting.enabled' },
|
|
694
1240
|
},
|
|
695
1241
|
{
|
|
696
1242
|
name: safeName('table.behavior.selection.enabled'),
|
|
697
|
-
label: 'Seleção habilitada',
|
|
1243
|
+
label: tx('Seleção habilitada'),
|
|
698
1244
|
controlType: FieldControlType.TOGGLE,
|
|
699
1245
|
dataAttributes: { globalPath: 'table.behavior.selection.enabled' },
|
|
700
1246
|
},
|
|
701
1247
|
{
|
|
702
1248
|
name: safeName('table.behavior.pagination.strategy'),
|
|
703
|
-
label: 'Paginação: estratégia',
|
|
1249
|
+
label: tx('Paginação: estratégia'),
|
|
704
1250
|
controlType: FieldControlType.SELECT,
|
|
705
1251
|
selectOptions: [
|
|
706
1252
|
{ text: 'client', value: 'client' },
|
|
@@ -710,7 +1256,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
710
1256
|
},
|
|
711
1257
|
{
|
|
712
1258
|
name: safeName('table.behavior.sorting.strategy'),
|
|
713
|
-
label: 'Ordenação: estratégia',
|
|
1259
|
+
label: tx('Ordenação: estratégia'),
|
|
714
1260
|
controlType: FieldControlType.SELECT,
|
|
715
1261
|
selectOptions: [
|
|
716
1262
|
{ text: 'client', value: 'client' },
|
|
@@ -720,114 +1266,113 @@ function buildGlobalConfigFormConfig() {
|
|
|
720
1266
|
},
|
|
721
1267
|
{
|
|
722
1268
|
name: safeName('table.behavior.pagination.showFirstLastButtons'),
|
|
723
|
-
label: 'Paginação: botões Primeiro/Último',
|
|
1269
|
+
label: tx('Paginação: botões Primeiro/Último'),
|
|
724
1270
|
controlType: FieldControlType.CHECKBOX,
|
|
725
1271
|
dataAttributes: { globalPath: 'table.behavior.pagination.showFirstLastButtons' },
|
|
726
1272
|
},
|
|
727
1273
|
{
|
|
728
1274
|
name: safeName('table.toolbar.visible'),
|
|
729
|
-
label: 'Toolbar visível',
|
|
1275
|
+
label: tx('Toolbar visível'),
|
|
730
1276
|
controlType: FieldControlType.CHECKBOX,
|
|
731
1277
|
dataAttributes: { globalPath: 'table.toolbar.visible' },
|
|
732
1278
|
},
|
|
733
1279
|
{
|
|
734
1280
|
name: safeName('table.appearance.density'),
|
|
735
|
-
label: '
|
|
1281
|
+
label: tx('Appearance: density'),
|
|
736
1282
|
controlType: FieldControlType.SELECT,
|
|
737
1283
|
selectOptions: [
|
|
738
|
-
{ text: 'compact', value: 'compact' },
|
|
739
|
-
{ text: 'comfortable', value: 'comfortable' },
|
|
740
|
-
{ text: 'spacious', value: 'spacious' },
|
|
1284
|
+
{ text: tx('compact'), value: 'compact' },
|
|
1285
|
+
{ text: tx('comfortable'), value: 'comfortable' },
|
|
1286
|
+
{ text: tx('spacious'), value: 'spacious' },
|
|
741
1287
|
],
|
|
742
1288
|
dataAttributes: { globalPath: 'table.appearance.density' },
|
|
743
1289
|
},
|
|
744
1290
|
{
|
|
745
1291
|
name: safeName('table.appearance.spacing.cellPadding'),
|
|
746
|
-
label: '
|
|
1292
|
+
label: tx('Appearance: cell padding'),
|
|
747
1293
|
controlType: FieldControlType.INPUT,
|
|
748
|
-
hint: '
|
|
1294
|
+
hint: tx('Accepts 1 to 4 CSS measures with units, var(...) or calc(...). Example: 6px 12px'),
|
|
749
1295
|
pattern: TABLE_COMPACT_SPACING_PATTERN,
|
|
750
|
-
patternMessage: 'Use 1
|
|
1296
|
+
patternMessage: tx('Use 1 to 4 valid CSS measures, such as 6px 12px.'),
|
|
751
1297
|
dataAttributes: { globalPath: 'table.appearance.spacing.cellPadding' },
|
|
752
1298
|
},
|
|
753
1299
|
{
|
|
754
1300
|
name: safeName('table.appearance.spacing.headerPadding'),
|
|
755
|
-
label: '
|
|
1301
|
+
label: tx('Appearance: header padding'),
|
|
756
1302
|
controlType: FieldControlType.INPUT,
|
|
757
|
-
hint: '
|
|
1303
|
+
hint: tx('Accepts 1 to 4 CSS measures with units, var(...) or calc(...). Example: 8px 12px'),
|
|
758
1304
|
pattern: TABLE_COMPACT_SPACING_PATTERN,
|
|
759
|
-
patternMessage: 'Use 1
|
|
1305
|
+
patternMessage: tx('Use 1 to 4 valid CSS measures, such as 8px 12px.'),
|
|
760
1306
|
dataAttributes: { globalPath: 'table.appearance.spacing.headerPadding' },
|
|
761
1307
|
},
|
|
762
1308
|
{
|
|
763
1309
|
name: safeName('table.appearance.typography.fontSize'),
|
|
764
|
-
label: '
|
|
1310
|
+
label: tx('Appearance: cell font size'),
|
|
765
1311
|
controlType: FieldControlType.INPUT,
|
|
766
|
-
hint: '
|
|
1312
|
+
hint: tx('Accepts a CSS measure with units, var(...) or calc(...). Example: 13px'),
|
|
767
1313
|
pattern: TABLE_COMPACT_FONT_SIZE_PATTERN,
|
|
768
|
-
patternMessage: 'Use
|
|
1314
|
+
patternMessage: tx('Use a valid CSS measure, such as 13px.'),
|
|
769
1315
|
dataAttributes: { globalPath: 'table.appearance.typography.fontSize' },
|
|
770
1316
|
},
|
|
771
1317
|
{
|
|
772
1318
|
name: safeName('table.appearance.typography.headerFontSize'),
|
|
773
|
-
label: '
|
|
1319
|
+
label: tx('Appearance: header font size'),
|
|
774
1320
|
controlType: FieldControlType.INPUT,
|
|
775
|
-
hint: '
|
|
1321
|
+
hint: tx('Accepts a CSS measure with units, var(...) or calc(...). Example: 13px'),
|
|
776
1322
|
pattern: TABLE_COMPACT_FONT_SIZE_PATTERN,
|
|
777
|
-
patternMessage: 'Use
|
|
1323
|
+
patternMessage: tx('Use a valid CSS measure, such as 13px.'),
|
|
778
1324
|
dataAttributes: { globalPath: 'table.appearance.typography.headerFontSize' },
|
|
779
|
-
},
|
|
780
|
-
{
|
|
1325
|
+
}, {
|
|
781
1326
|
name: safeName('table.filteringUi.advancedOpenMode'),
|
|
782
|
-
label: 'Filtro: modo de abertura',
|
|
1327
|
+
label: tx('Filtro: modo de abertura'),
|
|
783
1328
|
controlType: FieldControlType.SELECT,
|
|
784
1329
|
selectOptions: [
|
|
785
|
-
{ text: 'overlay', value: 'overlay' },
|
|
786
|
-
{ text: 'modal', value: 'modal' },
|
|
787
|
-
{ text: 'drawer', value: 'drawer' },
|
|
1330
|
+
{ text: tx('overlay'), value: 'overlay' },
|
|
1331
|
+
{ text: tx('modal'), value: 'modal' },
|
|
1332
|
+
{ text: tx('drawer'), value: 'drawer' },
|
|
788
1333
|
],
|
|
789
1334
|
dataAttributes: { globalPath: 'table.filteringUi.advancedOpenMode' },
|
|
790
1335
|
},
|
|
791
1336
|
{
|
|
792
1337
|
name: safeName('table.filteringUi.overlayVariant'),
|
|
793
|
-
label: 'Filtro: overlay (visual)',
|
|
1338
|
+
label: tx('Filtro: overlay (visual)'),
|
|
794
1339
|
controlType: FieldControlType.SELECT,
|
|
795
1340
|
selectOptions: [
|
|
796
|
-
{ text: 'card', value: 'card' },
|
|
797
|
-
{ text: 'frosted', value: 'frosted' },
|
|
1341
|
+
{ text: tx('card'), value: 'card' },
|
|
1342
|
+
{ text: tx('frosted'), value: 'frosted' },
|
|
798
1343
|
],
|
|
799
1344
|
dataAttributes: { globalPath: 'table.filteringUi.overlayVariant' },
|
|
800
1345
|
},
|
|
801
1346
|
{
|
|
802
1347
|
name: safeName('table.filteringUi.overlayBackdrop'),
|
|
803
|
-
label: 'Filtro: backdrop no overlay',
|
|
1348
|
+
label: tx('Filtro: backdrop no overlay'),
|
|
804
1349
|
controlType: FieldControlType.CHECKBOX,
|
|
805
1350
|
dataAttributes: { globalPath: 'table.filteringUi.overlayBackdrop' },
|
|
806
1351
|
},
|
|
807
1352
|
// Table messages - confirmations
|
|
808
|
-
{ name: safeName('table.messages.actions.confirmations.delete'), label: 'Excluir — confirmação', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.confirmations.delete' } },
|
|
809
|
-
{ name: safeName('table.messages.actions.confirmations.deleteMultiple'), label: 'Excluir (múltiplos) — confirmação', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.confirmations.deleteMultiple' } },
|
|
810
|
-
{ name: safeName('table.messages.actions.confirmations.save'), label: 'Salvar — confirmação', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.confirmations.save' } },
|
|
811
|
-
{ name: safeName('table.messages.actions.confirmations.cancel'), label: 'Cancelar — confirmação', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.confirmations.cancel' } },
|
|
812
|
-
{ name: safeName('table.messages.actions.confirmations.export'), label: 'Exportar — confirmação', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.confirmations.export' } },
|
|
1353
|
+
{ name: safeName('table.messages.actions.confirmations.delete'), label: tx('Excluir — confirmação'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.confirmations.delete' } },
|
|
1354
|
+
{ name: safeName('table.messages.actions.confirmations.deleteMultiple'), label: tx('Excluir (múltiplos) — confirmação'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.confirmations.deleteMultiple' } },
|
|
1355
|
+
{ name: safeName('table.messages.actions.confirmations.save'), label: tx('Salvar — confirmação'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.confirmations.save' } },
|
|
1356
|
+
{ name: safeName('table.messages.actions.confirmations.cancel'), label: tx('Cancelar — confirmação'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.confirmations.cancel' } },
|
|
1357
|
+
{ name: safeName('table.messages.actions.confirmations.export'), label: tx('Exportar — confirmação'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.confirmations.export' } },
|
|
813
1358
|
// Table messages - progress
|
|
814
|
-
{ name: safeName('table.messages.actions.progress.delete'), label: 'Excluir — progresso', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.progress.delete' } },
|
|
815
|
-
{ name: safeName('table.messages.actions.progress.deleteMultiple'), label: 'Excluir (múltiplos) — progresso', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.progress.deleteMultiple' } },
|
|
1359
|
+
{ name: safeName('table.messages.actions.progress.delete'), label: tx('Excluir — progresso'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.progress.delete' } },
|
|
1360
|
+
{ name: safeName('table.messages.actions.progress.deleteMultiple'), label: tx('Excluir (múltiplos) — progresso'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.progress.deleteMultiple' } },
|
|
816
1361
|
// Table messages - success
|
|
817
|
-
{ name: safeName('table.messages.actions.success.delete'), label: 'Excluir — sucesso', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.success.delete' } },
|
|
818
|
-
{ name: safeName('table.messages.actions.success.save'), label: 'Salvar — sucesso', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.success.save' } },
|
|
819
|
-
{ name: safeName('table.messages.actions.success.export'), label: 'Exportar — sucesso', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.success.export' } },
|
|
820
|
-
{ name: safeName('table.messages.actions.success.import'), label: 'Importar — sucesso', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.success.import' } },
|
|
1362
|
+
{ name: safeName('table.messages.actions.success.delete'), label: tx('Excluir — sucesso'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.success.delete' } },
|
|
1363
|
+
{ name: safeName('table.messages.actions.success.save'), label: tx('Salvar — sucesso'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.success.save' } },
|
|
1364
|
+
{ name: safeName('table.messages.actions.success.export'), label: tx('Exportar — sucesso'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.success.export' } },
|
|
1365
|
+
{ name: safeName('table.messages.actions.success.import'), label: tx('Importar — sucesso'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.success.import' } },
|
|
821
1366
|
// Table messages - errors
|
|
822
|
-
{ name: safeName('table.messages.actions.errors.delete'), label: 'Excluir — erro', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.delete' } },
|
|
823
|
-
{ name: safeName('table.messages.actions.errors.save'), label: 'Salvar — erro', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.save' } },
|
|
824
|
-
{ name: safeName('table.messages.actions.errors.export'), label: 'Exportar — erro', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.export' } },
|
|
825
|
-
{ name: safeName('table.messages.actions.errors.network'), label: 'Rede — erro', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.network' } },
|
|
826
|
-
{ name: safeName('table.messages.actions.errors.permission'), label: 'Permissão — erro', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.permission' } },
|
|
827
|
-
// Dialog
|
|
1367
|
+
{ name: safeName('table.messages.actions.errors.delete'), label: tx('Excluir — erro'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.delete' } },
|
|
1368
|
+
{ name: safeName('table.messages.actions.errors.save'), label: tx('Salvar — erro'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.save' } },
|
|
1369
|
+
{ name: safeName('table.messages.actions.errors.export'), label: tx('Exportar — erro'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.export' } },
|
|
1370
|
+
{ name: safeName('table.messages.actions.errors.network'), label: tx('Rede — erro'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.network' } },
|
|
1371
|
+
{ name: safeName('table.messages.actions.errors.permission'), label: tx('Permissão — erro'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.permission' } },
|
|
1372
|
+
// Dialog - Defaults by type
|
|
828
1373
|
{
|
|
829
1374
|
name: safeName('dialog.defaults.confirm.ariaRole'),
|
|
830
|
-
label: 'Dialog
|
|
1375
|
+
label: tx('Dialog defaults: confirm - ariaRole'),
|
|
831
1376
|
controlType: FieldControlType.SELECT,
|
|
832
1377
|
selectOptions: [
|
|
833
1378
|
{ text: 'dialog', value: 'dialog' },
|
|
@@ -835,24 +1380,24 @@ function buildGlobalConfigFormConfig() {
|
|
|
835
1380
|
],
|
|
836
1381
|
dataAttributes: { globalPath: 'dialog.defaults.confirm.ariaRole' },
|
|
837
1382
|
},
|
|
838
|
-
{ name: safeName('dialog.defaults.confirm.title'), label: 'Dialog
|
|
839
|
-
{ name: safeName('dialog.defaults.confirm.icon'), label: 'Dialog
|
|
840
|
-
{ name: safeName('dialog.defaults.confirm.message'), label: 'Dialog
|
|
841
|
-
{ name: safeName('dialog.defaults.confirm.themeColor'), label: 'Dialog
|
|
1383
|
+
{ name: safeName('dialog.defaults.confirm.title'), label: tx('Dialog defaults: confirm - title'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.defaults.confirm.title' } },
|
|
1384
|
+
{ name: safeName('dialog.defaults.confirm.icon'), label: tx('Dialog defaults: confirm - icon'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.defaults.confirm.icon' } },
|
|
1385
|
+
{ name: safeName('dialog.defaults.confirm.message'), label: tx('Dialog defaults: confirm - message'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.defaults.confirm.message' } },
|
|
1386
|
+
{ name: safeName('dialog.defaults.confirm.themeColor'), label: tx('Dialog defaults: confirm - themeColor'), controlType: FieldControlType.SELECT, selectOptions: [{ text: 'light', value: 'light' }, { text: 'primary', value: 'primary' }, { text: 'dark', value: 'dark' }], dataAttributes: { globalPath: 'dialog.defaults.confirm.themeColor' } },
|
|
842
1387
|
{
|
|
843
1388
|
name: safeName('dialog.defaults.confirm.closeOnBackdropClick'),
|
|
844
|
-
label: 'Dialog
|
|
1389
|
+
label: tx('Dialog defaults: confirm - close on backdrop click'),
|
|
845
1390
|
controlType: FieldControlType.TOGGLE,
|
|
846
1391
|
dataAttributes: { globalPath: 'dialog.defaults.confirm.closeOnBackdropClick' },
|
|
847
1392
|
},
|
|
848
|
-
{ name: safeName('dialog.defaults.confirm.disableClose'), label: 'Dialog
|
|
849
|
-
{ name: safeName('dialog.defaults.confirm.hasBackdrop'), label: 'Dialog
|
|
850
|
-
{ name: safeName('dialog.defaults.confirm.panelClass'), label: 'Dialog
|
|
851
|
-
{ name: safeName('dialog.defaults.confirm.styles'), label: 'Dialog
|
|
852
|
-
{ name: safeName('dialog.defaults.confirm.animation'), label: 'Dialog
|
|
1393
|
+
{ name: safeName('dialog.defaults.confirm.disableClose'), label: tx('Dialog defaults: confirm - disableClose'), controlType: FieldControlType.TOGGLE, dataAttributes: { globalPath: 'dialog.defaults.confirm.disableClose' } },
|
|
1394
|
+
{ name: safeName('dialog.defaults.confirm.hasBackdrop'), label: tx('Dialog defaults: confirm - hasBackdrop'), controlType: FieldControlType.TOGGLE, dataAttributes: { globalPath: 'dialog.defaults.confirm.hasBackdrop' } },
|
|
1395
|
+
{ name: safeName('dialog.defaults.confirm.panelClass'), label: tx('Dialog defaults: confirm - panelClass'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.defaults.confirm.panelClass' } },
|
|
1396
|
+
{ name: safeName('dialog.defaults.confirm.styles'), label: tx('Dialog defaults: confirm - styles (JSON)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.defaults.confirm.styles', monospace: true }, hint: tx('Example JSON: {"containerColor":"var(--md-sys-color-surface)","containerBorderColor":"var(--md-sys-color-outline-variant)","backdropColor":"var(--md-sys-color-scrim)"}') },
|
|
1397
|
+
{ name: safeName('dialog.defaults.confirm.animation'), label: tx('Dialog defaults: confirm - animation (JSON/boolean)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.defaults.confirm.animation', monospace: true } },
|
|
853
1398
|
{
|
|
854
1399
|
name: safeName('dialog.defaults.alert.ariaRole'),
|
|
855
|
-
label: 'Dialog
|
|
1400
|
+
label: tx('Dialog defaults: alert - ariaRole'),
|
|
856
1401
|
controlType: FieldControlType.SELECT,
|
|
857
1402
|
selectOptions: [
|
|
858
1403
|
{ text: 'dialog', value: 'dialog' },
|
|
@@ -860,24 +1405,24 @@ function buildGlobalConfigFormConfig() {
|
|
|
860
1405
|
],
|
|
861
1406
|
dataAttributes: { globalPath: 'dialog.defaults.alert.ariaRole' },
|
|
862
1407
|
},
|
|
863
|
-
{ name: safeName('dialog.defaults.alert.title'), label: 'Dialog
|
|
864
|
-
{ name: safeName('dialog.defaults.alert.icon'), label: 'Dialog
|
|
865
|
-
{ name: safeName('dialog.defaults.alert.message'), label: 'Dialog
|
|
866
|
-
{ name: safeName('dialog.defaults.alert.themeColor'), label: 'Dialog
|
|
1408
|
+
{ name: safeName('dialog.defaults.alert.title'), label: tx('Dialog defaults: alert - title'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.defaults.alert.title' } },
|
|
1409
|
+
{ name: safeName('dialog.defaults.alert.icon'), label: tx('Dialog defaults: alert - icon'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.defaults.alert.icon' } },
|
|
1410
|
+
{ name: safeName('dialog.defaults.alert.message'), label: tx('Dialog defaults: alert - message'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.defaults.alert.message' } },
|
|
1411
|
+
{ name: safeName('dialog.defaults.alert.themeColor'), label: tx('Dialog defaults: alert - themeColor'), controlType: FieldControlType.SELECT, selectOptions: [{ text: 'light', value: 'light' }, { text: 'primary', value: 'primary' }, { text: 'dark', value: 'dark' }], dataAttributes: { globalPath: 'dialog.defaults.alert.themeColor' } },
|
|
867
1412
|
{
|
|
868
1413
|
name: safeName('dialog.defaults.alert.closeOnBackdropClick'),
|
|
869
|
-
label: 'Dialog
|
|
1414
|
+
label: tx('Dialog defaults: alert - close on backdrop click'),
|
|
870
1415
|
controlType: FieldControlType.TOGGLE,
|
|
871
1416
|
dataAttributes: { globalPath: 'dialog.defaults.alert.closeOnBackdropClick' },
|
|
872
1417
|
},
|
|
873
|
-
{ name: safeName('dialog.defaults.alert.disableClose'), label: 'Dialog
|
|
874
|
-
{ name: safeName('dialog.defaults.alert.hasBackdrop'), label: 'Dialog
|
|
875
|
-
{ name: safeName('dialog.defaults.alert.panelClass'), label: 'Dialog
|
|
876
|
-
{ name: safeName('dialog.defaults.alert.styles'), label: 'Dialog
|
|
877
|
-
{ name: safeName('dialog.defaults.alert.animation'), label: 'Dialog
|
|
1418
|
+
{ name: safeName('dialog.defaults.alert.disableClose'), label: tx('Dialog defaults: alert - disableClose'), controlType: FieldControlType.TOGGLE, dataAttributes: { globalPath: 'dialog.defaults.alert.disableClose' } },
|
|
1419
|
+
{ name: safeName('dialog.defaults.alert.hasBackdrop'), label: tx('Dialog defaults: alert - hasBackdrop'), controlType: FieldControlType.TOGGLE, dataAttributes: { globalPath: 'dialog.defaults.alert.hasBackdrop' } },
|
|
1420
|
+
{ name: safeName('dialog.defaults.alert.panelClass'), label: tx('Dialog defaults: alert - panelClass'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.defaults.alert.panelClass' } },
|
|
1421
|
+
{ name: safeName('dialog.defaults.alert.styles'), label: tx('Dialog defaults: alert - styles (JSON)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.defaults.alert.styles', monospace: true }, hint: tx('Example JSON: {"containerColor":"var(--md-sys-color-surface)","containerBorderColor":"var(--md-sys-color-outline-variant)","backdropColor":"var(--md-sys-color-scrim)"}') },
|
|
1422
|
+
{ name: safeName('dialog.defaults.alert.animation'), label: tx('Dialog defaults: alert - animation (JSON/boolean)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.defaults.alert.animation', monospace: true } },
|
|
878
1423
|
{
|
|
879
1424
|
name: safeName('dialog.defaults.prompt.ariaRole'),
|
|
880
|
-
label: 'Dialog
|
|
1425
|
+
label: tx('Dialog defaults: prompt - ariaRole'),
|
|
881
1426
|
controlType: FieldControlType.SELECT,
|
|
882
1427
|
selectOptions: [
|
|
883
1428
|
{ text: 'dialog', value: 'dialog' },
|
|
@@ -885,79 +1430,79 @@ function buildGlobalConfigFormConfig() {
|
|
|
885
1430
|
],
|
|
886
1431
|
dataAttributes: { globalPath: 'dialog.defaults.prompt.ariaRole' },
|
|
887
1432
|
},
|
|
888
|
-
{ name: safeName('dialog.defaults.prompt.title'), label: 'Dialog
|
|
889
|
-
{ name: safeName('dialog.defaults.prompt.icon'), label: 'Dialog
|
|
890
|
-
{ name: safeName('dialog.defaults.prompt.message'), label: 'Dialog
|
|
891
|
-
{ name: safeName('dialog.defaults.prompt.themeColor'), label: 'Dialog
|
|
1433
|
+
{ name: safeName('dialog.defaults.prompt.title'), label: tx('Dialog defaults: prompt - title'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.defaults.prompt.title' } },
|
|
1434
|
+
{ name: safeName('dialog.defaults.prompt.icon'), label: tx('Dialog defaults: prompt - icon'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.defaults.prompt.icon' } },
|
|
1435
|
+
{ name: safeName('dialog.defaults.prompt.message'), label: tx('Dialog defaults: prompt - message'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.defaults.prompt.message' } },
|
|
1436
|
+
{ name: safeName('dialog.defaults.prompt.themeColor'), label: tx('Dialog defaults: prompt - themeColor'), controlType: FieldControlType.SELECT, selectOptions: [{ text: 'light', value: 'light' }, { text: 'primary', value: 'primary' }, { text: 'dark', value: 'dark' }], dataAttributes: { globalPath: 'dialog.defaults.prompt.themeColor' } },
|
|
892
1437
|
{
|
|
893
1438
|
name: safeName('dialog.defaults.prompt.closeOnBackdropClick'),
|
|
894
|
-
label: 'Dialog
|
|
1439
|
+
label: tx('Dialog defaults: prompt - close on backdrop click'),
|
|
895
1440
|
controlType: FieldControlType.TOGGLE,
|
|
896
1441
|
dataAttributes: { globalPath: 'dialog.defaults.prompt.closeOnBackdropClick' },
|
|
897
1442
|
},
|
|
898
|
-
{ name: safeName('dialog.defaults.prompt.disableClose'), label: 'Dialog
|
|
899
|
-
{ name: safeName('dialog.defaults.prompt.hasBackdrop'), label: 'Dialog
|
|
900
|
-
{ name: safeName('dialog.defaults.prompt.panelClass'), label: 'Dialog
|
|
901
|
-
{ name: safeName('dialog.defaults.prompt.styles'), label: 'Dialog
|
|
902
|
-
{ name: safeName('dialog.defaults.prompt.animation'), label: 'Dialog
|
|
903
|
-
// Dialog
|
|
1443
|
+
{ name: safeName('dialog.defaults.prompt.disableClose'), label: tx('Dialog defaults: prompt - disableClose'), controlType: FieldControlType.TOGGLE, dataAttributes: { globalPath: 'dialog.defaults.prompt.disableClose' } },
|
|
1444
|
+
{ name: safeName('dialog.defaults.prompt.hasBackdrop'), label: tx('Dialog defaults: prompt - hasBackdrop'), controlType: FieldControlType.TOGGLE, dataAttributes: { globalPath: 'dialog.defaults.prompt.hasBackdrop' } },
|
|
1445
|
+
{ name: safeName('dialog.defaults.prompt.panelClass'), label: tx('Dialog defaults: prompt - panelClass'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.defaults.prompt.panelClass' } },
|
|
1446
|
+
{ name: safeName('dialog.defaults.prompt.styles'), label: tx('Dialog defaults: prompt - styles (JSON)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.defaults.prompt.styles', monospace: true }, hint: tx('Example JSON: {"containerColor":"var(--md-sys-color-surface)","containerBorderColor":"var(--md-sys-color-outline-variant)","backdropColor":"var(--md-sys-color-scrim)"}') },
|
|
1447
|
+
{ name: safeName('dialog.defaults.prompt.animation'), label: tx('Dialog defaults: prompt - animation (JSON/boolean)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.defaults.prompt.animation', monospace: true } },
|
|
1448
|
+
// Dialog - Variants per profile (danger, info, success, question, error)
|
|
904
1449
|
// Each variant exposes commonly customized fields + JSON editors for actions/styles
|
|
905
1450
|
// danger
|
|
906
|
-
{ name: safeName('dialog.variants.danger.title'), label: 'Variant danger
|
|
907
|
-
{ name: safeName('dialog.variants.danger.icon'), label: 'Variant danger
|
|
908
|
-
{ name: safeName('dialog.variants.danger.message'), label: 'Variant danger
|
|
909
|
-
{ name: safeName('dialog.variants.danger.ariaRole'), label: 'Variant danger
|
|
910
|
-
{ name: safeName('dialog.variants.danger.closeOnBackdropClick'), label: 'Variant danger
|
|
911
|
-
{ name: safeName('dialog.variants.danger.panelClass'), label: 'Variant danger
|
|
912
|
-
{ name: safeName('dialog.variants.danger.actions'), label: 'Variant danger
|
|
913
|
-
{ name: safeName('dialog.variants.danger.styles'), label: 'Variant danger
|
|
914
|
-
{ name: safeName('dialog.variants.danger.animation'), label: 'Variant danger
|
|
1451
|
+
{ name: safeName('dialog.variants.danger.title'), label: tx('Variant danger - title'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.variants.danger.title' } },
|
|
1452
|
+
{ name: safeName('dialog.variants.danger.icon'), label: tx('Variant danger - icon'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.variants.danger.icon' } },
|
|
1453
|
+
{ name: safeName('dialog.variants.danger.message'), label: tx('Variant danger - message'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.danger.message' } },
|
|
1454
|
+
{ name: safeName('dialog.variants.danger.ariaRole'), label: tx('Variant danger - ariaRole'), controlType: FieldControlType.SELECT, selectOptions: [{ text: 'dialog', value: 'dialog' }, { text: 'alertdialog', value: 'alertdialog' }], dataAttributes: { globalPath: 'dialog.variants.danger.ariaRole' } },
|
|
1455
|
+
{ name: safeName('dialog.variants.danger.closeOnBackdropClick'), label: tx('Variant danger - close on backdrop click'), controlType: FieldControlType.TOGGLE, dataAttributes: { globalPath: 'dialog.variants.danger.closeOnBackdropClick' } },
|
|
1456
|
+
{ name: safeName('dialog.variants.danger.panelClass'), label: tx('Variant danger - panelClass'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.variants.danger.panelClass' } },
|
|
1457
|
+
{ name: safeName('dialog.variants.danger.actions'), label: tx('Variant danger - actions (JSON array)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.danger.actions', monospace: true }, hint: tx('Example JSON array: [{"id":"cancel","text":"Cancel","role":"secondary","close":true,"cssClass":"btn"},{"id":"confirm","text":"Delete","role":"primary","close":true,"cssClass":"btn btn-danger","icon":"delete"}]') },
|
|
1458
|
+
{ name: safeName('dialog.variants.danger.styles'), label: tx('Variant danger - styles (JSON)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.danger.styles', monospace: true }, hint: tx('Example JSON: {"containerColor":"var(--md-sys-color-surface)","containerBorderColor":"var(--md-sys-color-outline-variant)","backdropColor":"var(--md-sys-color-scrim)","actionButtonRadius":"8px"}') },
|
|
1459
|
+
{ name: safeName('dialog.variants.danger.animation'), label: tx('Variant danger - animation (JSON/boolean)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.danger.animation', monospace: true } },
|
|
915
1460
|
// info
|
|
916
|
-
{ name: safeName('dialog.variants.info.title'), label: 'Variant info
|
|
917
|
-
{ name: safeName('dialog.variants.info.icon'), label: 'Variant info
|
|
918
|
-
{ name: safeName('dialog.variants.info.message'), label: 'Variant info
|
|
919
|
-
{ name: safeName('dialog.variants.info.ariaRole'), label: 'Variant info
|
|
920
|
-
{ name: safeName('dialog.variants.info.closeOnBackdropClick'), label: 'Variant info
|
|
921
|
-
{ name: safeName('dialog.variants.info.panelClass'), label: 'Variant info
|
|
922
|
-
{ name: safeName('dialog.variants.info.actions'), label: 'Variant info
|
|
923
|
-
{ name: safeName('dialog.variants.info.styles'), label: 'Variant info
|
|
924
|
-
{ name: safeName('dialog.variants.info.animation'), label: 'Variant info
|
|
1461
|
+
{ name: safeName('dialog.variants.info.title'), label: tx('Variant info - title'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.variants.info.title' } },
|
|
1462
|
+
{ name: safeName('dialog.variants.info.icon'), label: tx('Variant info - icon'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.variants.info.icon' } },
|
|
1463
|
+
{ name: safeName('dialog.variants.info.message'), label: tx('Variant info - message'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.info.message' } },
|
|
1464
|
+
{ name: safeName('dialog.variants.info.ariaRole'), label: tx('Variant info - ariaRole'), controlType: FieldControlType.SELECT, selectOptions: [{ text: 'dialog', value: 'dialog' }, { text: 'alertdialog', value: 'alertdialog' }], dataAttributes: { globalPath: 'dialog.variants.info.ariaRole' } },
|
|
1465
|
+
{ name: safeName('dialog.variants.info.closeOnBackdropClick'), label: tx('Variant info - close on backdrop click'), controlType: FieldControlType.TOGGLE, dataAttributes: { globalPath: 'dialog.variants.info.closeOnBackdropClick' } },
|
|
1466
|
+
{ name: safeName('dialog.variants.info.panelClass'), label: tx('Variant info - panelClass'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.variants.info.panelClass' } },
|
|
1467
|
+
{ name: safeName('dialog.variants.info.actions'), label: tx('Variant info - actions (JSON array)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.info.actions', monospace: true } },
|
|
1468
|
+
{ name: safeName('dialog.variants.info.styles'), label: tx('Variant info - styles (JSON)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.info.styles', monospace: true }, hint: tx('Example JSON: {"containerColor":"var(--md-sys-color-surface)","containerBorderColor":"var(--md-sys-color-outline-variant)","backdropColor":"var(--md-sys-color-scrim)","actionButtonRadius":"8px"}') },
|
|
1469
|
+
{ name: safeName('dialog.variants.info.animation'), label: tx('Variant info - animation (JSON/boolean)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.info.animation', monospace: true } },
|
|
925
1470
|
// success
|
|
926
|
-
{ name: safeName('dialog.variants.success.title'), label: 'Variant success
|
|
927
|
-
{ name: safeName('dialog.variants.success.icon'), label: 'Variant success
|
|
928
|
-
{ name: safeName('dialog.variants.success.message'), label: 'Variant success
|
|
929
|
-
{ name: safeName('dialog.variants.success.ariaRole'), label: 'Variant success
|
|
930
|
-
{ name: safeName('dialog.variants.success.closeOnBackdropClick'), label: 'Variant success
|
|
931
|
-
{ name: safeName('dialog.variants.success.panelClass'), label: 'Variant success
|
|
932
|
-
{ name: safeName('dialog.variants.success.actions'), label: 'Variant success
|
|
933
|
-
{ name: safeName('dialog.variants.success.styles'), label: 'Variant success
|
|
934
|
-
{ name: safeName('dialog.variants.success.animation'), label: 'Variant success
|
|
1471
|
+
{ name: safeName('dialog.variants.success.title'), label: tx('Variant success - title'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.variants.success.title' } },
|
|
1472
|
+
{ name: safeName('dialog.variants.success.icon'), label: tx('Variant success - icon'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.variants.success.icon' } },
|
|
1473
|
+
{ name: safeName('dialog.variants.success.message'), label: tx('Variant success - message'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.success.message' } },
|
|
1474
|
+
{ name: safeName('dialog.variants.success.ariaRole'), label: tx('Variant success - ariaRole'), controlType: FieldControlType.SELECT, selectOptions: [{ text: 'dialog', value: 'dialog' }, { text: 'alertdialog', value: 'alertdialog' }], dataAttributes: { globalPath: 'dialog.variants.success.ariaRole' } },
|
|
1475
|
+
{ name: safeName('dialog.variants.success.closeOnBackdropClick'), label: tx('Variant success - close on backdrop click'), controlType: FieldControlType.TOGGLE, dataAttributes: { globalPath: 'dialog.variants.success.closeOnBackdropClick' } },
|
|
1476
|
+
{ name: safeName('dialog.variants.success.panelClass'), label: tx('Variant success - panelClass'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.variants.success.panelClass' } },
|
|
1477
|
+
{ name: safeName('dialog.variants.success.actions'), label: tx('Variant success - actions (JSON array)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.success.actions', monospace: true } },
|
|
1478
|
+
{ name: safeName('dialog.variants.success.styles'), label: tx('Variant success - styles (JSON)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.success.styles', monospace: true }, hint: tx('Example JSON: {"containerColor":"var(--md-sys-color-surface)","containerBorderColor":"var(--md-sys-color-outline-variant)","backdropColor":"var(--md-sys-color-scrim)","actionButtonRadius":"8px"}') },
|
|
1479
|
+
{ name: safeName('dialog.variants.success.animation'), label: tx('Variant success - animation (JSON/boolean)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.success.animation', monospace: true } },
|
|
935
1480
|
// question
|
|
936
|
-
{ name: safeName('dialog.variants.question.title'), label: 'Variant question
|
|
937
|
-
{ name: safeName('dialog.variants.question.icon'), label: 'Variant question
|
|
938
|
-
{ name: safeName('dialog.variants.question.message'), label: 'Variant question
|
|
939
|
-
{ name: safeName('dialog.variants.question.ariaRole'), label: 'Variant question
|
|
940
|
-
{ name: safeName('dialog.variants.question.closeOnBackdropClick'), label: 'Variant question
|
|
941
|
-
{ name: safeName('dialog.variants.question.panelClass'), label: 'Variant question
|
|
942
|
-
{ name: safeName('dialog.variants.question.actions'), label: 'Variant question
|
|
943
|
-
{ name: safeName('dialog.variants.question.styles'), label: 'Variant question
|
|
944
|
-
{ name: safeName('dialog.variants.question.animation'), label: 'Variant question
|
|
1481
|
+
{ name: safeName('dialog.variants.question.title'), label: tx('Variant question - title'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.variants.question.title' } },
|
|
1482
|
+
{ name: safeName('dialog.variants.question.icon'), label: tx('Variant question - icon'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.variants.question.icon' } },
|
|
1483
|
+
{ name: safeName('dialog.variants.question.message'), label: tx('Variant question - message'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.question.message' } },
|
|
1484
|
+
{ name: safeName('dialog.variants.question.ariaRole'), label: tx('Variant question - ariaRole'), controlType: FieldControlType.SELECT, selectOptions: [{ text: 'dialog', value: 'dialog' }, { text: 'alertdialog', value: 'alertdialog' }], dataAttributes: { globalPath: 'dialog.variants.question.ariaRole' } },
|
|
1485
|
+
{ name: safeName('dialog.variants.question.closeOnBackdropClick'), label: tx('Variant question - close on backdrop click'), controlType: FieldControlType.TOGGLE, dataAttributes: { globalPath: 'dialog.variants.question.closeOnBackdropClick' } },
|
|
1486
|
+
{ name: safeName('dialog.variants.question.panelClass'), label: tx('Variant question - panelClass'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.variants.question.panelClass' } },
|
|
1487
|
+
{ name: safeName('dialog.variants.question.actions'), label: tx('Variant question - actions (JSON array)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.question.actions', monospace: true } },
|
|
1488
|
+
{ name: safeName('dialog.variants.question.styles'), label: tx('Variant question - styles (JSON)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.question.styles', monospace: true }, hint: tx('Example JSON: {"containerColor":"var(--md-sys-color-surface)","containerBorderColor":"var(--md-sys-color-outline-variant)","backdropColor":"var(--md-sys-color-scrim)","actionButtonRadius":"8px"}') },
|
|
1489
|
+
{ name: safeName('dialog.variants.question.animation'), label: tx('Variant question - animation (JSON/boolean)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.question.animation', monospace: true } },
|
|
945
1490
|
// error
|
|
946
|
-
{ name: safeName('dialog.variants.error.title'), label: 'Variant error
|
|
947
|
-
{ name: safeName('dialog.variants.error.icon'), label: 'Variant error
|
|
948
|
-
{ name: safeName('dialog.variants.error.message'), label: 'Variant error
|
|
949
|
-
{ name: safeName('dialog.variants.error.ariaRole'), label: 'Variant error
|
|
950
|
-
{ name: safeName('dialog.variants.error.closeOnBackdropClick'), label: 'Variant error
|
|
951
|
-
{ name: safeName('dialog.variants.error.panelClass'), label: 'Variant error
|
|
952
|
-
{ name: safeName('dialog.variants.error.actions'), label: 'Variant error
|
|
953
|
-
{ name: safeName('dialog.variants.error.styles'), label: 'Variant error
|
|
954
|
-
{ name: safeName('dialog.variants.error.animation'), label: 'Variant error
|
|
1491
|
+
{ name: safeName('dialog.variants.error.title'), label: tx('Variant error - title'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.variants.error.title' } },
|
|
1492
|
+
{ name: safeName('dialog.variants.error.icon'), label: tx('Variant error - icon'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.variants.error.icon' } },
|
|
1493
|
+
{ name: safeName('dialog.variants.error.message'), label: tx('Variant error - message'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.error.message' } },
|
|
1494
|
+
{ name: safeName('dialog.variants.error.ariaRole'), label: tx('Variant error - ariaRole'), controlType: FieldControlType.SELECT, selectOptions: [{ text: 'dialog', value: 'dialog' }, { text: 'alertdialog', value: 'alertdialog' }], dataAttributes: { globalPath: 'dialog.variants.error.ariaRole' } },
|
|
1495
|
+
{ name: safeName('dialog.variants.error.closeOnBackdropClick'), label: tx('Variant error - close on backdrop click'), controlType: FieldControlType.TOGGLE, dataAttributes: { globalPath: 'dialog.variants.error.closeOnBackdropClick' } },
|
|
1496
|
+
{ name: safeName('dialog.variants.error.panelClass'), label: tx('Variant error - panelClass'), controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'dialog.variants.error.panelClass' } },
|
|
1497
|
+
{ name: safeName('dialog.variants.error.actions'), label: tx('Variant error - actions (JSON array)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.error.actions', monospace: true } },
|
|
1498
|
+
{ name: safeName('dialog.variants.error.styles'), label: tx('Variant error - styles (JSON)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.error.styles', monospace: true }, hint: tx('Example JSON: {"containerColor":"var(--md-sys-color-surface)","containerBorderColor":"var(--md-sys-color-outline-variant)","backdropColor":"var(--md-sys-color-scrim)","actionButtonRadius":"8px"}') },
|
|
1499
|
+
{ name: safeName('dialog.variants.error.animation'), label: tx('Variant error - animation (JSON/boolean)'), controlType: FieldControlType.TEXTAREA, dataAttributes: { globalPath: 'dialog.variants.error.animation', monospace: true } },
|
|
955
1500
|
];
|
|
956
1501
|
const cfg = {
|
|
957
1502
|
sections: [
|
|
958
1503
|
{
|
|
959
1504
|
id: 'crud',
|
|
960
|
-
title: 'CRUD',
|
|
1505
|
+
title: tx('CRUD'),
|
|
961
1506
|
rows: [
|
|
962
1507
|
{
|
|
963
1508
|
id: 'crud-row-1',
|
|
@@ -984,7 +1529,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
984
1529
|
},
|
|
985
1530
|
{
|
|
986
1531
|
id: 'dynamic-fields',
|
|
987
|
-
title: 'Dynamic Fields',
|
|
1532
|
+
title: tx('Dynamic Fields'),
|
|
988
1533
|
rows: [
|
|
989
1534
|
{
|
|
990
1535
|
id: 'df-row-1',
|
|
@@ -1005,7 +1550,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1005
1550
|
},
|
|
1006
1551
|
{
|
|
1007
1552
|
id: 'ai-credentials',
|
|
1008
|
-
title: '
|
|
1553
|
+
title: tx('Credentials'), // Internal title, UI might override
|
|
1009
1554
|
rows: [
|
|
1010
1555
|
{
|
|
1011
1556
|
id: 'ai-cred-row-1',
|
|
@@ -1018,7 +1563,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1018
1563
|
},
|
|
1019
1564
|
{
|
|
1020
1565
|
id: 'ai-model',
|
|
1021
|
-
title: '
|
|
1566
|
+
title: tx('Model & Behavior'),
|
|
1022
1567
|
rows: [
|
|
1023
1568
|
{
|
|
1024
1569
|
id: 'ai-mod-row-1',
|
|
@@ -1031,7 +1576,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1031
1576
|
},
|
|
1032
1577
|
{
|
|
1033
1578
|
id: 'ai-embedding',
|
|
1034
|
-
title: 'Embeddings',
|
|
1579
|
+
title: tx('Embeddings (RAG)'),
|
|
1035
1580
|
rows: [
|
|
1036
1581
|
{
|
|
1037
1582
|
id: 'ai-embed-row-1',
|
|
@@ -1045,7 +1590,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1045
1590
|
},
|
|
1046
1591
|
{
|
|
1047
1592
|
id: 'cache',
|
|
1048
|
-
title: 'Cache & Persistência',
|
|
1593
|
+
title: tx('Cache & Persistência'),
|
|
1049
1594
|
rows: [
|
|
1050
1595
|
{
|
|
1051
1596
|
id: 'cache-row-1',
|
|
@@ -1057,7 +1602,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1057
1602
|
},
|
|
1058
1603
|
{
|
|
1059
1604
|
id: 'table',
|
|
1060
|
-
title: 'Tabela',
|
|
1605
|
+
title: tx('Tabela'),
|
|
1061
1606
|
rows: [
|
|
1062
1607
|
{
|
|
1063
1608
|
id: 'tbl-row-1',
|
|
@@ -1118,7 +1663,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1118
1663
|
},
|
|
1119
1664
|
{
|
|
1120
1665
|
id: 'dialog',
|
|
1121
|
-
title: 'Dialog',
|
|
1666
|
+
title: tx('Dialog'),
|
|
1122
1667
|
rows: [
|
|
1123
1668
|
{
|
|
1124
1669
|
id: 'dlg-row-defaults',
|
|
@@ -1243,9 +1788,9 @@ function buildGlobalConfigFormConfig() {
|
|
|
1243
1788
|
actions: {
|
|
1244
1789
|
placement: 'afterSections',
|
|
1245
1790
|
// Hide internal form actions; Settings Panel footer handles Apply/Save
|
|
1246
|
-
submit: { visible: false, label: 'Salvar' },
|
|
1247
|
-
cancel: { visible: false, label: 'Cancelar' },
|
|
1248
|
-
reset: { visible: false, label: 'Redefinir', type: 'reset' },
|
|
1791
|
+
submit: { visible: false, label: tx('Salvar') },
|
|
1792
|
+
cancel: { visible: false, label: tx('Cancelar') },
|
|
1793
|
+
reset: { visible: false, label: tx('Redefinir'), type: 'reset' },
|
|
1249
1794
|
},
|
|
1250
1795
|
fieldMetadata: fields,
|
|
1251
1796
|
};
|
|
@@ -1271,10 +1816,10 @@ const TABLE_COMPACT_FONT_SIZE_PATHS = new Set([
|
|
|
1271
1816
|
'table.appearance.typography.headerFontSize',
|
|
1272
1817
|
]);
|
|
1273
1818
|
const TABLE_COMPACT_FIELD_LABELS = {
|
|
1274
|
-
'table.appearance.spacing.cellPadding': 'padding
|
|
1275
|
-
'table.appearance.spacing.headerPadding': 'padding
|
|
1276
|
-
'table.appearance.typography.fontSize': '
|
|
1277
|
-
'table.appearance.typography.headerFontSize': '
|
|
1819
|
+
'table.appearance.spacing.cellPadding': 'cell padding',
|
|
1820
|
+
'table.appearance.spacing.headerPadding': 'header padding',
|
|
1821
|
+
'table.appearance.typography.fontSize': 'cell font size',
|
|
1822
|
+
'table.appearance.typography.headerFontSize': 'header font size',
|
|
1278
1823
|
};
|
|
1279
1824
|
const TABLE_COMPACT_LENGTH_TOKEN = '(?:0|(?:\\d+|\\d*\\.\\d+)(?:px|rem|em|%|vh|vw|svh|svw|lvh|lvw|dvh|dvw|ch|ex))';
|
|
1280
1825
|
const TABLE_COMPACT_SPACING_REGEX = new RegExp(`^(?:var\\(.+\\)|calc\\(.+\\)|${TABLE_COMPACT_LENGTH_TOKEN}(?:\\s+${TABLE_COMPACT_LENGTH_TOKEN}){0,3})$`, 'i');
|
|
@@ -1301,6 +1846,7 @@ class GlobalConfigEditorComponent {
|
|
|
1301
1846
|
hostAiModel;
|
|
1302
1847
|
hostAiEmbedding;
|
|
1303
1848
|
destroyRef = inject(DestroyRef);
|
|
1849
|
+
i18n = inject(PraxisI18nService);
|
|
1304
1850
|
iconPicker = inject(IconPickerService);
|
|
1305
1851
|
aiApi = inject(AiBackendApiService);
|
|
1306
1852
|
cdr = inject(ChangeDetectorRef);
|
|
@@ -1334,7 +1880,7 @@ class GlobalConfigEditorComponent {
|
|
|
1334
1880
|
apiKeyLast4 = null;
|
|
1335
1881
|
hasStoredApiKey = false;
|
|
1336
1882
|
hasStoredGlobalConfig = false;
|
|
1337
|
-
configSourceLabel = '
|
|
1883
|
+
configSourceLabel = this.tx('Server defaults (env vars)');
|
|
1338
1884
|
// UX: API Key monitoring
|
|
1339
1885
|
apiKeyChanged$ = new Subject();
|
|
1340
1886
|
hasApiKey = false;
|
|
@@ -1346,12 +1892,12 @@ class GlobalConfigEditorComponent {
|
|
|
1346
1892
|
get apiKeyStatusLabel() {
|
|
1347
1893
|
const apiKey = this.currentValues?.[this.safeName('ai.apiKey')] || '';
|
|
1348
1894
|
if (apiKey)
|
|
1349
|
-
return '
|
|
1895
|
+
return this.tx('Key provided');
|
|
1350
1896
|
if (this.apiKeyLast4)
|
|
1351
|
-
return
|
|
1897
|
+
return this.tx('Saved key (****{{last4}})', { last4: this.apiKeyLast4 });
|
|
1352
1898
|
if (this.hasStoredApiKey)
|
|
1353
|
-
return '
|
|
1354
|
-
return '
|
|
1899
|
+
return this.tx('Saved key');
|
|
1900
|
+
return this.tx('No saved key');
|
|
1355
1901
|
}
|
|
1356
1902
|
constructor(admin, snack) {
|
|
1357
1903
|
this.admin = admin;
|
|
@@ -1360,7 +1906,7 @@ class GlobalConfigEditorComponent {
|
|
|
1360
1906
|
async ngOnInit() {
|
|
1361
1907
|
const cfg = this.admin.getEffectiveConfig();
|
|
1362
1908
|
const flat = this.flatten(cfg);
|
|
1363
|
-
this.formConfig = buildGlobalConfigFormConfig();
|
|
1909
|
+
this.formConfig = buildGlobalConfigFormConfig(this.tx.bind(this));
|
|
1364
1910
|
this.applyConfigSnapshot(flat, { resetForms: false });
|
|
1365
1911
|
await this.loadProviderCatalog();
|
|
1366
1912
|
this.applyProviderOptions();
|
|
@@ -1505,7 +2051,7 @@ class GlobalConfigEditorComponent {
|
|
|
1505
2051
|
const ref = g.host.createComponent(this.dynamicFormCtor);
|
|
1506
2052
|
ref.setInput('config', g.cfg);
|
|
1507
2053
|
ref.setInput('mode', 'edit');
|
|
1508
|
-
// Não habilitar o modo de edição de layout (canvas)
|
|
2054
|
+
// Não habilitar o modo de edição de layout (canvas) - queremos apenas edição de valores
|
|
1509
2055
|
ref.setInput('enableCustomization', false);
|
|
1510
2056
|
const inst = ref.instance;
|
|
1511
2057
|
// FORÇAR estado de sucesso para renderizar o formulário sem resourcePath
|
|
@@ -1578,7 +2124,7 @@ class GlobalConfigEditorComponent {
|
|
|
1578
2124
|
{
|
|
1579
2125
|
id: 'gemini',
|
|
1580
2126
|
label: 'Google Gemini',
|
|
1581
|
-
description: '
|
|
2127
|
+
description: this.tx('Fast multimodal models from Google.'),
|
|
1582
2128
|
defaultModel: 'gemini-2.0-flash',
|
|
1583
2129
|
requiresApiKey: true,
|
|
1584
2130
|
supportsModels: true,
|
|
@@ -1588,7 +2134,7 @@ class GlobalConfigEditorComponent {
|
|
|
1588
2134
|
{
|
|
1589
2135
|
id: 'openai',
|
|
1590
2136
|
label: 'OpenAI',
|
|
1591
|
-
description: '
|
|
2137
|
+
description: this.tx('GPT models for text and chat.'),
|
|
1592
2138
|
defaultModel: 'gpt-4o-mini',
|
|
1593
2139
|
requiresApiKey: true,
|
|
1594
2140
|
supportsModels: true,
|
|
@@ -1598,7 +2144,7 @@ class GlobalConfigEditorComponent {
|
|
|
1598
2144
|
{
|
|
1599
2145
|
id: 'xai',
|
|
1600
2146
|
label: 'xAI (Grok)',
|
|
1601
|
-
description: '
|
|
2147
|
+
description: this.tx('Grok models focused on reasoning.'),
|
|
1602
2148
|
defaultModel: 'grok-2-latest',
|
|
1603
2149
|
requiresApiKey: true,
|
|
1604
2150
|
supportsModels: true,
|
|
@@ -1608,7 +2154,7 @@ class GlobalConfigEditorComponent {
|
|
|
1608
2154
|
{
|
|
1609
2155
|
id: 'mock',
|
|
1610
2156
|
label: 'Mock (dev)',
|
|
1611
|
-
description: '
|
|
2157
|
+
description: this.tx('Local mode for tests without a key.'),
|
|
1612
2158
|
defaultModel: 'mock-default',
|
|
1613
2159
|
requiresApiKey: false,
|
|
1614
2160
|
supportsModels: true,
|
|
@@ -1797,8 +2343,8 @@ class GlobalConfigEditorComponent {
|
|
|
1797
2343
|
this.hasStoredGlobalConfig = false;
|
|
1798
2344
|
}
|
|
1799
2345
|
this.configSourceLabel = this.hasStoredGlobalConfig
|
|
1800
|
-
? '
|
|
1801
|
-
: '
|
|
2346
|
+
? this.tx('Saved configuration (UI) - overrides server defaults')
|
|
2347
|
+
: this.tx('Server defaults (env vars)');
|
|
1802
2348
|
}
|
|
1803
2349
|
async clearStoredConfig() {
|
|
1804
2350
|
if (this.isClearingGlobalConfig)
|
|
@@ -1813,13 +2359,13 @@ class GlobalConfigEditorComponent {
|
|
|
1813
2359
|
this.refreshAiStateAfterConfig();
|
|
1814
2360
|
await this.refreshStoredConfigState();
|
|
1815
2361
|
try {
|
|
1816
|
-
this.snack.open('
|
|
2362
|
+
this.snack.open(this.tx('Global config cleared. Using server defaults.'), undefined, { duration: 2500 });
|
|
1817
2363
|
}
|
|
1818
2364
|
catch { }
|
|
1819
2365
|
}
|
|
1820
2366
|
catch (err) {
|
|
1821
2367
|
try {
|
|
1822
|
-
this.snack.open('
|
|
2368
|
+
this.snack.open(this.tx('Failed to clear global config.'), undefined, { duration: 4000 });
|
|
1823
2369
|
}
|
|
1824
2370
|
catch { }
|
|
1825
2371
|
}
|
|
@@ -1946,10 +2492,10 @@ class GlobalConfigEditorComponent {
|
|
|
1946
2492
|
const model = this.availableModels.find(m => m.name.endsWith(modelName));
|
|
1947
2493
|
if (model) {
|
|
1948
2494
|
const formatLimit = (n) => n ? (n >= 1000 ? (n / 1000).toFixed(0) + 'k' : n) : 'N/A';
|
|
1949
|
-
this.selectedModelDetails =
|
|
2495
|
+
this.selectedModelDetails = this.tx('Model: {{model}} | Tokens (in/out): {{in}}/{{out}} | Methods: {{methods}}', { model: model.displayName || modelName, in: formatLimit(model.inputTokenLimit), out: formatLimit(model.outputTokenLimit), methods: model.supportedGenerationMethods?.join(', ') || 'N/A' });
|
|
1950
2496
|
}
|
|
1951
2497
|
else {
|
|
1952
|
-
this.selectedModelDetails = '
|
|
2498
|
+
this.selectedModelDetails = this.tx('No model details available.');
|
|
1953
2499
|
}
|
|
1954
2500
|
}
|
|
1955
2501
|
// SettingsPanel expects these methods
|
|
@@ -1985,7 +2531,7 @@ class GlobalConfigEditorComponent {
|
|
|
1985
2531
|
this.initialValues = { ...this.currentValues };
|
|
1986
2532
|
this.isDirty$.next(false);
|
|
1987
2533
|
try {
|
|
1988
|
-
this.snack.open('
|
|
2534
|
+
this.snack.open(this.tx('Settings saved'), undefined, { duration: 2000 });
|
|
1989
2535
|
}
|
|
1990
2536
|
catch { }
|
|
1991
2537
|
return partial;
|
|
@@ -2008,7 +2554,7 @@ class GlobalConfigEditorComponent {
|
|
|
2008
2554
|
const meta = this.findProvider(provider);
|
|
2009
2555
|
if (meta?.supportsModels === false) {
|
|
2010
2556
|
if (!silent) {
|
|
2011
|
-
this.aiTestResult = { success: false, message: '
|
|
2557
|
+
this.aiTestResult = { success: false, message: this.tx('This provider has no model catalog.') };
|
|
2012
2558
|
this.cdr.detectChanges();
|
|
2013
2559
|
}
|
|
2014
2560
|
return;
|
|
@@ -2016,7 +2562,7 @@ class GlobalConfigEditorComponent {
|
|
|
2016
2562
|
const requiresKey = meta?.requiresApiKey !== false;
|
|
2017
2563
|
const hasKey = !!apiKey || this.hasStoredApiKey || !requiresKey;
|
|
2018
2564
|
if (requiresKey && !hasKey) {
|
|
2019
|
-
this.aiTestResult = { success: false, message: '
|
|
2565
|
+
this.aiTestResult = { success: false, message: this.tx('Enter an API key to fetch models.') };
|
|
2020
2566
|
this.cdr.detectChanges();
|
|
2021
2567
|
return;
|
|
2022
2568
|
}
|
|
@@ -2031,8 +2577,7 @@ class GlobalConfigEditorComponent {
|
|
|
2031
2577
|
request.apiKey = apiKey;
|
|
2032
2578
|
const response = await firstValueFrom(this.aiApi.listModels(request));
|
|
2033
2579
|
if (!response?.success) {
|
|
2034
|
-
|
|
2035
|
-
throw new Error(msg);
|
|
2580
|
+
throw new Error(this.tx('Error fetching models.'));
|
|
2036
2581
|
}
|
|
2037
2582
|
const models = response.models || [];
|
|
2038
2583
|
this.availableModels = models; // Store available models
|
|
@@ -2053,9 +2598,9 @@ class GlobalConfigEditorComponent {
|
|
|
2053
2598
|
}
|
|
2054
2599
|
catch (error) {
|
|
2055
2600
|
this.logger.error('[GlobalConfigEditor] Error fetching models', this.buildLogOptions({ error, provider }, { context: { actionId: 'models.fetch' } }));
|
|
2056
|
-
this.aiTestResult = { success: false, message:
|
|
2601
|
+
this.aiTestResult = { success: false, message: this.tx('Error fetching models.') };
|
|
2057
2602
|
if (!silent) {
|
|
2058
|
-
this.snack.open('
|
|
2603
|
+
this.snack.open(this.tx('Error fetching models. Check your API key.'), this.tx('Close'), { duration: 5000 });
|
|
2059
2604
|
}
|
|
2060
2605
|
}
|
|
2061
2606
|
finally {
|
|
@@ -2085,7 +2630,7 @@ class GlobalConfigEditorComponent {
|
|
|
2085
2630
|
this.recreateAiModelForm();
|
|
2086
2631
|
if (!silent) {
|
|
2087
2632
|
try {
|
|
2088
|
-
this.snack.open(
|
|
2633
|
+
this.snack.open(this.tx('Model list updated ({{count}} models)', { count: modelOptions.length }), undefined, { duration: 3000 });
|
|
2089
2634
|
}
|
|
2090
2635
|
catch { }
|
|
2091
2636
|
}
|
|
@@ -2103,7 +2648,7 @@ class GlobalConfigEditorComponent {
|
|
|
2103
2648
|
const requiresKey = meta?.requiresApiKey !== false;
|
|
2104
2649
|
const hasKey = !!apiKey || this.hasStoredApiKey || !requiresKey;
|
|
2105
2650
|
if (requiresKey && !hasKey) {
|
|
2106
|
-
this.aiTestResult = { success: false, message: '
|
|
2651
|
+
this.aiTestResult = { success: false, message: this.tx('Enter an API key to test.') };
|
|
2107
2652
|
this.isTestingAi = false;
|
|
2108
2653
|
this.cdr.detectChanges();
|
|
2109
2654
|
return;
|
|
@@ -2114,17 +2659,16 @@ class GlobalConfigEditorComponent {
|
|
|
2114
2659
|
request.apiKey = apiKey;
|
|
2115
2660
|
const response = await firstValueFrom(this.aiApi.testProvider(request));
|
|
2116
2661
|
if (!response?.success) {
|
|
2117
|
-
throw new Error(
|
|
2662
|
+
throw new Error(this.tx('Failed to test connection.'));
|
|
2118
2663
|
}
|
|
2119
|
-
this.aiTestResult = { success: true, message:
|
|
2664
|
+
this.aiTestResult = { success: true, message: this.tx('Connection established successfully!') };
|
|
2120
2665
|
this.hasApiKey = true; // Garantir desbloqueio da seção de modelo após sucesso
|
|
2121
2666
|
// Após validar a chave, já buscar a lista de modelos para preencher o select
|
|
2122
2667
|
await this.refreshModels(true);
|
|
2123
2668
|
}
|
|
2124
2669
|
catch (err) {
|
|
2125
2670
|
this.logger.error('[GlobalConfigEditor] AI Connection Test Error', this.buildLogOptions({ error: err, provider, model: selectedModel }, { context: { actionId: 'provider.test-connection' } }));
|
|
2126
|
-
|
|
2127
|
-
this.aiTestResult = { success: false, message: msg };
|
|
2671
|
+
this.aiTestResult = { success: false, message: this.tx('Failed to test connection.') };
|
|
2128
2672
|
}
|
|
2129
2673
|
finally {
|
|
2130
2674
|
this.isTestingAi = false;
|
|
@@ -2145,6 +2689,10 @@ class GlobalConfigEditorComponent {
|
|
|
2145
2689
|
safeName(path) {
|
|
2146
2690
|
return path.replace(/[^a-zA-Z0-9_]/g, '_');
|
|
2147
2691
|
}
|
|
2692
|
+
tx(text, params) {
|
|
2693
|
+
const normalized = normalizeMojibakeText(text);
|
|
2694
|
+
return this.i18n.t(normalized, params, normalized, PRAXIS_SETTINGS_PANEL_I18N_NAMESPACE);
|
|
2695
|
+
}
|
|
2148
2696
|
buildChangedValues() {
|
|
2149
2697
|
const out = {};
|
|
2150
2698
|
for (const [safe, value] of Object.entries(this.currentValues)) {
|
|
@@ -2169,21 +2717,7 @@ class GlobalConfigEditorComponent {
|
|
|
2169
2717
|
return initial !== current;
|
|
2170
2718
|
}
|
|
2171
2719
|
resolveSaveErrorMessage(err) {
|
|
2172
|
-
|
|
2173
|
-
const details = err?.error?.details;
|
|
2174
|
-
if (apiMessage && apiMessage.trim()) {
|
|
2175
|
-
return apiMessage;
|
|
2176
|
-
}
|
|
2177
|
-
if (details && typeof details === 'object') {
|
|
2178
|
-
const first = Object.values(details).find((v) => typeof v === 'string' && v.trim());
|
|
2179
|
-
if (typeof first === 'string') {
|
|
2180
|
-
return first;
|
|
2181
|
-
}
|
|
2182
|
-
}
|
|
2183
|
-
if (typeof err?.message === 'string' && err.message.trim()) {
|
|
2184
|
-
return err.message;
|
|
2185
|
-
}
|
|
2186
|
-
return 'Falha ao salvar configurações.';
|
|
2720
|
+
return this.tx('Save failed.');
|
|
2187
2721
|
}
|
|
2188
2722
|
normalizeFieldValue(path, value) {
|
|
2189
2723
|
if (typeof value !== 'string')
|
|
@@ -2230,7 +2764,7 @@ class GlobalConfigEditorComponent {
|
|
|
2230
2764
|
if (!normalized)
|
|
2231
2765
|
continue;
|
|
2232
2766
|
if (!check.regex.test(normalized)) {
|
|
2233
|
-
return `
|
|
2767
|
+
return `Invalid value in ${TABLE_COMPACT_FIELD_LABELS[check.path]}. Use a simple CSS string, such as ${check.example}.`;
|
|
2234
2768
|
}
|
|
2235
2769
|
}
|
|
2236
2770
|
return null;
|
|
@@ -2340,9 +2874,9 @@ class GlobalConfigEditorComponent {
|
|
|
2340
2874
|
<mat-expansion-panel-header>
|
|
2341
2875
|
<mat-panel-title>
|
|
2342
2876
|
<mat-icon class="panel-icon">construction</mat-icon>
|
|
2343
|
-
CRUD
|
|
2877
|
+
{{ tx('CRUD') }}
|
|
2344
2878
|
</mat-panel-title>
|
|
2345
|
-
<mat-panel-description>
|
|
2879
|
+
<mat-panel-description>{{ tx('Global policies for opening, back and header') }}</mat-panel-description>
|
|
2346
2880
|
</mat-expansion-panel-header>
|
|
2347
2881
|
<ng-template #hostCrud></ng-template>
|
|
2348
2882
|
</mat-expansion-panel>
|
|
@@ -2350,9 +2884,9 @@ class GlobalConfigEditorComponent {
|
|
|
2350
2884
|
<mat-expansion-panel-header>
|
|
2351
2885
|
<mat-panel-title>
|
|
2352
2886
|
<mat-icon class="panel-icon">dynamic_form</mat-icon>
|
|
2353
|
-
Dynamic Fields
|
|
2887
|
+
{{ tx('Dynamic Fields') }}
|
|
2354
2888
|
</mat-panel-title>
|
|
2355
|
-
<mat-panel-description>Async Select,
|
|
2889
|
+
<mat-panel-description>{{ tx('Async Select, cascade and pagination') }}</mat-panel-description>
|
|
2356
2890
|
</mat-expansion-panel-header>
|
|
2357
2891
|
<ng-template #hostFields></ng-template>
|
|
2358
2892
|
</mat-expansion-panel>
|
|
@@ -2360,9 +2894,9 @@ class GlobalConfigEditorComponent {
|
|
|
2360
2894
|
<mat-expansion-panel-header>
|
|
2361
2895
|
<mat-panel-title>
|
|
2362
2896
|
<mat-icon class="panel-icon">cached</mat-icon>
|
|
2363
|
-
Cache &
|
|
2897
|
+
{{ tx('Cache & Persistence') }}
|
|
2364
2898
|
</mat-panel-title>
|
|
2365
|
-
<mat-panel-description>
|
|
2899
|
+
<mat-panel-description>{{ tx('Schema cache strategy (local vs server)') }}</mat-panel-description>
|
|
2366
2900
|
</mat-expansion-panel-header>
|
|
2367
2901
|
<ng-template #hostCache></ng-template>
|
|
2368
2902
|
</mat-expansion-panel>
|
|
@@ -2370,9 +2904,9 @@ class GlobalConfigEditorComponent {
|
|
|
2370
2904
|
<mat-expansion-panel-header>
|
|
2371
2905
|
<mat-panel-title>
|
|
2372
2906
|
<mat-icon class="panel-icon">psychology</mat-icon>
|
|
2373
|
-
|
|
2907
|
+
{{ tx('Artificial Intelligence') }}
|
|
2374
2908
|
</mat-panel-title>
|
|
2375
|
-
<mat-panel-description>
|
|
2909
|
+
<mat-panel-description>{{ tx('LLM integration') }}</mat-panel-description>
|
|
2376
2910
|
</mat-expansion-panel-header>
|
|
2377
2911
|
|
|
2378
2912
|
<div class="ai-config-container">
|
|
@@ -2381,23 +2915,23 @@ class GlobalConfigEditorComponent {
|
|
|
2381
2915
|
<mat-icon>settings_suggest</mat-icon>
|
|
2382
2916
|
<span>{{ configSourceLabel }}</span>
|
|
2383
2917
|
</div>
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
matTooltip="
|
|
2918
|
+
<button
|
|
2919
|
+
mat-stroked-button
|
|
2920
|
+
type="button"
|
|
2921
|
+
class="ai-action-btn ai-action-btn--clear"
|
|
2922
|
+
*ngIf="hasStoredGlobalConfig"
|
|
2923
|
+
[attr.aria-busy]="isClearingGlobalConfig ? 'true' : null"
|
|
2924
|
+
[disabled]="isClearingGlobalConfig"
|
|
2925
|
+
(click)="clearStoredConfig()"
|
|
2926
|
+
[matTooltip]="tx('Clear saved config and return to server defaults')"
|
|
2393
2927
|
>
|
|
2394
2928
|
<ng-container *ngIf="isClearingGlobalConfig; else clearContent">
|
|
2395
2929
|
<mat-spinner diameter="16" class="btn-spinner"></mat-spinner>
|
|
2396
|
-
<span class="ai-action-label">
|
|
2930
|
+
<span class="ai-action-label">{{ tx('Clearing...') }}</span>
|
|
2397
2931
|
</ng-container>
|
|
2398
2932
|
<ng-template #clearContent>
|
|
2399
2933
|
<mat-icon>delete_sweep</mat-icon>
|
|
2400
|
-
<span class="ai-action-label">
|
|
2934
|
+
<span class="ai-action-label">{{ tx('Clear saved config') }}</span>
|
|
2401
2935
|
</ng-template>
|
|
2402
2936
|
</button>
|
|
2403
2937
|
</div>
|
|
@@ -2405,7 +2939,7 @@ class GlobalConfigEditorComponent {
|
|
|
2405
2939
|
<div class="ai-group">
|
|
2406
2940
|
<div class="ai-group-header">
|
|
2407
2941
|
<div class="ai-group-title">
|
|
2408
|
-
<mat-icon>vpn_key</mat-icon>
|
|
2942
|
+
<mat-icon>vpn_key</mat-icon> {{ tx('Credentials') }}
|
|
2409
2943
|
</div>
|
|
2410
2944
|
<button mat-stroked-button
|
|
2411
2945
|
type="button"
|
|
@@ -2414,15 +2948,15 @@ class GlobalConfigEditorComponent {
|
|
|
2414
2948
|
[attr.aria-busy]="isTestingAi ? 'true' : null"
|
|
2415
2949
|
(click)="testAiConnection()"
|
|
2416
2950
|
[disabled]="isTestingAi || !hasApiKey"
|
|
2417
|
-
matTooltip="
|
|
2951
|
+
[matTooltip]="tx('Test connection with the provided key')">
|
|
2418
2952
|
<ng-container *ngIf="isTestingAi; else btnContent">
|
|
2419
2953
|
<mat-spinner diameter="16" class="btn-spinner"></mat-spinner>
|
|
2420
|
-
<span class="ai-action-label">
|
|
2954
|
+
<span class="ai-action-label">{{ tx('Connecting...') }}</span>
|
|
2421
2955
|
</ng-container>
|
|
2422
2956
|
<ng-template #btnContent>
|
|
2423
2957
|
<mat-icon>{{ aiTestResult?.success ? 'check' : 'bolt' }}</mat-icon>
|
|
2424
2958
|
<span class="ai-action-label">
|
|
2425
|
-
{{ aiTestResult?.success ? '
|
|
2959
|
+
{{ aiTestResult?.success ? tx('Connected') : tx('Test connection') }}
|
|
2426
2960
|
</span>
|
|
2427
2961
|
</ng-template>
|
|
2428
2962
|
</button>
|
|
@@ -2464,7 +2998,7 @@ class GlobalConfigEditorComponent {
|
|
|
2464
2998
|
</div>
|
|
2465
2999
|
<div class="ai-provider-key is-unlocked" *ngIf="selectedProvider?.requiresApiKey === false">
|
|
2466
3000
|
<mat-icon>check_circle</mat-icon>
|
|
2467
|
-
<span>
|
|
3001
|
+
<span>{{ tx('No key required') }}</span>
|
|
2468
3002
|
</div>
|
|
2469
3003
|
</div>
|
|
2470
3004
|
<div class="ai-credentials-row">
|
|
@@ -2484,12 +3018,12 @@ class GlobalConfigEditorComponent {
|
|
|
2484
3018
|
<div class="ai-group" [class.disabled-group]="!hasApiKey">
|
|
2485
3019
|
<div class="ai-group-header">
|
|
2486
3020
|
<div class="ai-group-title">
|
|
2487
|
-
<mat-icon>smart_toy</mat-icon>
|
|
3021
|
+
<mat-icon>smart_toy</mat-icon> {{ tx('Model & Behavior') }}
|
|
2488
3022
|
</div>
|
|
2489
3023
|
<div class="ai-header-actions">
|
|
2490
|
-
<span class="ai-subtext" *ngIf="hasApiKey">
|
|
2491
|
-
<mat-chip-option *ngIf="!hasApiKey" disabled>
|
|
2492
|
-
<button mat-icon-button (click)="refreshModels(true)" [disabled]="isTestingAi || !hasApiKey" matTooltip="
|
|
3024
|
+
<span class="ai-subtext" *ngIf="hasApiKey">{{ tx('Choose the model after validating the key.') }}</span>
|
|
3025
|
+
<mat-chip-option *ngIf="!hasApiKey" disabled>{{ tx('API key validated required') }}</mat-chip-option>
|
|
3026
|
+
<button mat-icon-button (click)="refreshModels(true)" [disabled]="isTestingAi || !hasApiKey" [matTooltip]="tx('Refresh model list')" [attr.aria-label]="tx('Refresh model list')">
|
|
2493
3027
|
<mat-icon [class.spin]="isRefetchingModels">sync</mat-icon>
|
|
2494
3028
|
</button>
|
|
2495
3029
|
</div>
|
|
@@ -2508,7 +3042,7 @@ class GlobalConfigEditorComponent {
|
|
|
2508
3042
|
|
|
2509
3043
|
<div class="ai-placeholder" *ngIf="!hasApiKey">
|
|
2510
3044
|
<mat-icon>lock</mat-icon>
|
|
2511
|
-
<span>Configure
|
|
3045
|
+
<span>{{ tx('Configure and test your API key to unlock model selection.') }}</span>
|
|
2512
3046
|
</div>
|
|
2513
3047
|
</div>
|
|
2514
3048
|
|
|
@@ -2516,7 +3050,7 @@ class GlobalConfigEditorComponent {
|
|
|
2516
3050
|
<div class="ai-group">
|
|
2517
3051
|
<div class="ai-group-header">
|
|
2518
3052
|
<div class="ai-group-title">
|
|
2519
|
-
<mat-icon>scatter_plot</mat-icon> Embeddings (RAG)
|
|
3053
|
+
<mat-icon>scatter_plot</mat-icon> {{ tx('Embeddings (RAG)') }}
|
|
2520
3054
|
</div>
|
|
2521
3055
|
<div class="ai-header-actions">
|
|
2522
3056
|
<button
|
|
@@ -2525,19 +3059,19 @@ class GlobalConfigEditorComponent {
|
|
|
2525
3059
|
class="ai-action-btn"
|
|
2526
3060
|
(click)="useLlmForEmbeddings()"
|
|
2527
3061
|
[disabled]="!canUseLlmForEmbeddings"
|
|
2528
|
-
matTooltip="
|
|
3062
|
+
[matTooltip]="tx('Use the LLM provider and key for embeddings')"
|
|
2529
3063
|
>
|
|
2530
3064
|
<mat-icon>merge_type</mat-icon>
|
|
2531
|
-
<span class="ai-action-label">
|
|
3065
|
+
<span class="ai-action-label">{{ tx('Use the LLM provider and key for embeddings') }}</span>
|
|
2532
3066
|
</button>
|
|
2533
|
-
<mat-chip-option *ngIf="!canUseLlmForEmbeddings" disabled>
|
|
3067
|
+
<mat-chip-option *ngIf="!canUseLlmForEmbeddings" disabled>{{ tx('Provider has no embeddings') }}</mat-chip-option>
|
|
2534
3068
|
</div>
|
|
2535
3069
|
</div>
|
|
2536
3070
|
<div class="ai-subtext">
|
|
2537
|
-
Configure
|
|
3071
|
+
{{ tx('Configure the embeddings provider for vector search (templates and schemas).') }}
|
|
2538
3072
|
</div>
|
|
2539
3073
|
<div class="ai-subtext" *ngIf="embeddingUseSameAsLlm">
|
|
2540
|
-
|
|
3074
|
+
{{ tx('Synchronized with the LLM. The fields below follow the primary credential.') }}
|
|
2541
3075
|
</div>
|
|
2542
3076
|
<div class="ai-embedding-row">
|
|
2543
3077
|
<ng-template #hostAiEmbedding></ng-template>
|
|
@@ -2545,7 +3079,7 @@ class GlobalConfigEditorComponent {
|
|
|
2545
3079
|
<div class="ai-feedback ai-feedback--warn" *ngIf="embeddingDimensionMismatch">
|
|
2546
3080
|
<mat-icon>warning</mat-icon>
|
|
2547
3081
|
<span class="error-text">
|
|
2548
|
-
|
|
3082
|
+
{{ tx('Embedding dimension mismatch with database (768). Adjust to 768 or redo the migration.') }}
|
|
2549
3083
|
</span>
|
|
2550
3084
|
</div>
|
|
2551
3085
|
</div>
|
|
@@ -2556,9 +3090,9 @@ class GlobalConfigEditorComponent {
|
|
|
2556
3090
|
<mat-expansion-panel-header>
|
|
2557
3091
|
<mat-panel-title>
|
|
2558
3092
|
<mat-icon class="panel-icon">table_chart</mat-icon>
|
|
2559
|
-
|
|
3093
|
+
{{ tx('Table') }}
|
|
2560
3094
|
</mat-panel-title>
|
|
2561
|
-
<mat-panel-description>Toolbar,
|
|
3095
|
+
<mat-panel-description>{{ tx('Toolbar, appearance and advanced filter') }}</mat-panel-description>
|
|
2562
3096
|
</mat-expansion-panel-header>
|
|
2563
3097
|
<ng-template #hostTable></ng-template>
|
|
2564
3098
|
</mat-expansion-panel>
|
|
@@ -2566,27 +3100,27 @@ class GlobalConfigEditorComponent {
|
|
|
2566
3100
|
<mat-expansion-panel-header>
|
|
2567
3101
|
<mat-panel-title>
|
|
2568
3102
|
<mat-icon class="panel-icon">forum</mat-icon>
|
|
2569
|
-
Dialog
|
|
3103
|
+
{{ tx('Dialog') }}
|
|
2570
3104
|
</mat-panel-title>
|
|
2571
|
-
<mat-panel-description>Defaults
|
|
3105
|
+
<mat-panel-description>{{ tx('Defaults and variants (danger, info, success, question, error)') }}</mat-panel-description>
|
|
2572
3106
|
</mat-expansion-panel-header>
|
|
2573
3107
|
<ng-template #hostDialog></ng-template>
|
|
2574
3108
|
<!-- Icon UX helpers for Dialog variants -->
|
|
2575
3109
|
<div class="dlg-icon-helpers">
|
|
2576
|
-
<div class="dlg-icon-helpers__head"
|
|
3110
|
+
<div class="dlg-icon-helpers__head">{{ tx('Icons by profile (shortcuts)') }}</div>
|
|
2577
3111
|
<div class="dlg-icon-helpers__row" *ngFor="let k of dialogVariantKeys">
|
|
2578
3112
|
<div class="dlg-icon-helpers__label">{{ k }}</div>
|
|
2579
3113
|
<mat-icon aria-hidden="true" [praxisIcon]="getVariantIcon(k) || 'mi:help_outline'" class="dlg-icon-helpers__preview"></mat-icon>
|
|
2580
|
-
<button mat-stroked-button color="primary" type="button" (click)="pickVariantIcon(k)" matTooltip="
|
|
3114
|
+
<button mat-stroked-button color="primary" type="button" (click)="pickVariantIcon(k)" [matTooltip]="tx('Pick icon for {{key}}', { key: k })">
|
|
2581
3115
|
<mat-icon>search</mat-icon>
|
|
2582
|
-
|
|
3116
|
+
{{ tx('Pick icon') }}
|
|
2583
3117
|
</button>
|
|
2584
|
-
<button mat-icon-button type="button" *ngIf="getVariantIcon(k)" (click)="clearVariantIcon(k)" matTooltip="
|
|
3118
|
+
<button mat-icon-button type="button" *ngIf="getVariantIcon(k)" (click)="clearVariantIcon(k)" [matTooltip]="tx('Clear icon for {{key}}', { key: k })" [attr.aria-label]="tx('Clear icon')">
|
|
2585
3119
|
<mat-icon>backspace</mat-icon>
|
|
2586
3120
|
</button>
|
|
2587
3121
|
<span class="dlg-icon-helpers__value" *ngIf="getVariantIcon(k)">{{ getVariantIcon(k) }}</span>
|
|
2588
3122
|
</div>
|
|
2589
|
-
<div class="dlg-icon-helpers__hint">
|
|
3123
|
+
<div class="dlg-icon-helpers__hint">{{ tx('The text field above remains editable. These buttons only help with selection/clear preview.') }}</div>
|
|
2590
3124
|
</div>
|
|
2591
3125
|
</mat-expansion-panel>
|
|
2592
3126
|
</mat-accordion>
|
|
@@ -2600,9 +3134,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2600
3134
|
<mat-expansion-panel-header>
|
|
2601
3135
|
<mat-panel-title>
|
|
2602
3136
|
<mat-icon class="panel-icon">construction</mat-icon>
|
|
2603
|
-
CRUD
|
|
3137
|
+
{{ tx('CRUD') }}
|
|
2604
3138
|
</mat-panel-title>
|
|
2605
|
-
<mat-panel-description>
|
|
3139
|
+
<mat-panel-description>{{ tx('Global policies for opening, back and header') }}</mat-panel-description>
|
|
2606
3140
|
</mat-expansion-panel-header>
|
|
2607
3141
|
<ng-template #hostCrud></ng-template>
|
|
2608
3142
|
</mat-expansion-panel>
|
|
@@ -2610,9 +3144,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2610
3144
|
<mat-expansion-panel-header>
|
|
2611
3145
|
<mat-panel-title>
|
|
2612
3146
|
<mat-icon class="panel-icon">dynamic_form</mat-icon>
|
|
2613
|
-
Dynamic Fields
|
|
3147
|
+
{{ tx('Dynamic Fields') }}
|
|
2614
3148
|
</mat-panel-title>
|
|
2615
|
-
<mat-panel-description>Async Select,
|
|
3149
|
+
<mat-panel-description>{{ tx('Async Select, cascade and pagination') }}</mat-panel-description>
|
|
2616
3150
|
</mat-expansion-panel-header>
|
|
2617
3151
|
<ng-template #hostFields></ng-template>
|
|
2618
3152
|
</mat-expansion-panel>
|
|
@@ -2620,9 +3154,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2620
3154
|
<mat-expansion-panel-header>
|
|
2621
3155
|
<mat-panel-title>
|
|
2622
3156
|
<mat-icon class="panel-icon">cached</mat-icon>
|
|
2623
|
-
Cache &
|
|
3157
|
+
{{ tx('Cache & Persistence') }}
|
|
2624
3158
|
</mat-panel-title>
|
|
2625
|
-
<mat-panel-description>
|
|
3159
|
+
<mat-panel-description>{{ tx('Schema cache strategy (local vs server)') }}</mat-panel-description>
|
|
2626
3160
|
</mat-expansion-panel-header>
|
|
2627
3161
|
<ng-template #hostCache></ng-template>
|
|
2628
3162
|
</mat-expansion-panel>
|
|
@@ -2630,9 +3164,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2630
3164
|
<mat-expansion-panel-header>
|
|
2631
3165
|
<mat-panel-title>
|
|
2632
3166
|
<mat-icon class="panel-icon">psychology</mat-icon>
|
|
2633
|
-
|
|
3167
|
+
{{ tx('Artificial Intelligence') }}
|
|
2634
3168
|
</mat-panel-title>
|
|
2635
|
-
<mat-panel-description>
|
|
3169
|
+
<mat-panel-description>{{ tx('LLM integration') }}</mat-panel-description>
|
|
2636
3170
|
</mat-expansion-panel-header>
|
|
2637
3171
|
|
|
2638
3172
|
<div class="ai-config-container">
|
|
@@ -2641,23 +3175,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2641
3175
|
<mat-icon>settings_suggest</mat-icon>
|
|
2642
3176
|
<span>{{ configSourceLabel }}</span>
|
|
2643
3177
|
</div>
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
matTooltip="
|
|
3178
|
+
<button
|
|
3179
|
+
mat-stroked-button
|
|
3180
|
+
type="button"
|
|
3181
|
+
class="ai-action-btn ai-action-btn--clear"
|
|
3182
|
+
*ngIf="hasStoredGlobalConfig"
|
|
3183
|
+
[attr.aria-busy]="isClearingGlobalConfig ? 'true' : null"
|
|
3184
|
+
[disabled]="isClearingGlobalConfig"
|
|
3185
|
+
(click)="clearStoredConfig()"
|
|
3186
|
+
[matTooltip]="tx('Clear saved config and return to server defaults')"
|
|
2653
3187
|
>
|
|
2654
3188
|
<ng-container *ngIf="isClearingGlobalConfig; else clearContent">
|
|
2655
3189
|
<mat-spinner diameter="16" class="btn-spinner"></mat-spinner>
|
|
2656
|
-
<span class="ai-action-label">
|
|
3190
|
+
<span class="ai-action-label">{{ tx('Clearing...') }}</span>
|
|
2657
3191
|
</ng-container>
|
|
2658
3192
|
<ng-template #clearContent>
|
|
2659
3193
|
<mat-icon>delete_sweep</mat-icon>
|
|
2660
|
-
<span class="ai-action-label">
|
|
3194
|
+
<span class="ai-action-label">{{ tx('Clear saved config') }}</span>
|
|
2661
3195
|
</ng-template>
|
|
2662
3196
|
</button>
|
|
2663
3197
|
</div>
|
|
@@ -2665,7 +3199,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2665
3199
|
<div class="ai-group">
|
|
2666
3200
|
<div class="ai-group-header">
|
|
2667
3201
|
<div class="ai-group-title">
|
|
2668
|
-
<mat-icon>vpn_key</mat-icon>
|
|
3202
|
+
<mat-icon>vpn_key</mat-icon> {{ tx('Credentials') }}
|
|
2669
3203
|
</div>
|
|
2670
3204
|
<button mat-stroked-button
|
|
2671
3205
|
type="button"
|
|
@@ -2674,15 +3208,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2674
3208
|
[attr.aria-busy]="isTestingAi ? 'true' : null"
|
|
2675
3209
|
(click)="testAiConnection()"
|
|
2676
3210
|
[disabled]="isTestingAi || !hasApiKey"
|
|
2677
|
-
matTooltip="
|
|
3211
|
+
[matTooltip]="tx('Test connection with the provided key')">
|
|
2678
3212
|
<ng-container *ngIf="isTestingAi; else btnContent">
|
|
2679
3213
|
<mat-spinner diameter="16" class="btn-spinner"></mat-spinner>
|
|
2680
|
-
<span class="ai-action-label">
|
|
3214
|
+
<span class="ai-action-label">{{ tx('Connecting...') }}</span>
|
|
2681
3215
|
</ng-container>
|
|
2682
3216
|
<ng-template #btnContent>
|
|
2683
3217
|
<mat-icon>{{ aiTestResult?.success ? 'check' : 'bolt' }}</mat-icon>
|
|
2684
3218
|
<span class="ai-action-label">
|
|
2685
|
-
{{ aiTestResult?.success ? '
|
|
3219
|
+
{{ aiTestResult?.success ? tx('Connected') : tx('Test connection') }}
|
|
2686
3220
|
</span>
|
|
2687
3221
|
</ng-template>
|
|
2688
3222
|
</button>
|
|
@@ -2724,7 +3258,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2724
3258
|
</div>
|
|
2725
3259
|
<div class="ai-provider-key is-unlocked" *ngIf="selectedProvider?.requiresApiKey === false">
|
|
2726
3260
|
<mat-icon>check_circle</mat-icon>
|
|
2727
|
-
<span>
|
|
3261
|
+
<span>{{ tx('No key required') }}</span>
|
|
2728
3262
|
</div>
|
|
2729
3263
|
</div>
|
|
2730
3264
|
<div class="ai-credentials-row">
|
|
@@ -2744,12 +3278,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2744
3278
|
<div class="ai-group" [class.disabled-group]="!hasApiKey">
|
|
2745
3279
|
<div class="ai-group-header">
|
|
2746
3280
|
<div class="ai-group-title">
|
|
2747
|
-
<mat-icon>smart_toy</mat-icon>
|
|
3281
|
+
<mat-icon>smart_toy</mat-icon> {{ tx('Model & Behavior') }}
|
|
2748
3282
|
</div>
|
|
2749
3283
|
<div class="ai-header-actions">
|
|
2750
|
-
<span class="ai-subtext" *ngIf="hasApiKey">
|
|
2751
|
-
<mat-chip-option *ngIf="!hasApiKey" disabled>
|
|
2752
|
-
<button mat-icon-button (click)="refreshModels(true)" [disabled]="isTestingAi || !hasApiKey" matTooltip="
|
|
3284
|
+
<span class="ai-subtext" *ngIf="hasApiKey">{{ tx('Choose the model after validating the key.') }}</span>
|
|
3285
|
+
<mat-chip-option *ngIf="!hasApiKey" disabled>{{ tx('API key validated required') }}</mat-chip-option>
|
|
3286
|
+
<button mat-icon-button (click)="refreshModels(true)" [disabled]="isTestingAi || !hasApiKey" [matTooltip]="tx('Refresh model list')" [attr.aria-label]="tx('Refresh model list')">
|
|
2753
3287
|
<mat-icon [class.spin]="isRefetchingModels">sync</mat-icon>
|
|
2754
3288
|
</button>
|
|
2755
3289
|
</div>
|
|
@@ -2768,7 +3302,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2768
3302
|
|
|
2769
3303
|
<div class="ai-placeholder" *ngIf="!hasApiKey">
|
|
2770
3304
|
<mat-icon>lock</mat-icon>
|
|
2771
|
-
<span>Configure
|
|
3305
|
+
<span>{{ tx('Configure and test your API key to unlock model selection.') }}</span>
|
|
2772
3306
|
</div>
|
|
2773
3307
|
</div>
|
|
2774
3308
|
|
|
@@ -2776,7 +3310,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2776
3310
|
<div class="ai-group">
|
|
2777
3311
|
<div class="ai-group-header">
|
|
2778
3312
|
<div class="ai-group-title">
|
|
2779
|
-
<mat-icon>scatter_plot</mat-icon> Embeddings (RAG)
|
|
3313
|
+
<mat-icon>scatter_plot</mat-icon> {{ tx('Embeddings (RAG)') }}
|
|
2780
3314
|
</div>
|
|
2781
3315
|
<div class="ai-header-actions">
|
|
2782
3316
|
<button
|
|
@@ -2785,19 +3319,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2785
3319
|
class="ai-action-btn"
|
|
2786
3320
|
(click)="useLlmForEmbeddings()"
|
|
2787
3321
|
[disabled]="!canUseLlmForEmbeddings"
|
|
2788
|
-
matTooltip="
|
|
3322
|
+
[matTooltip]="tx('Use the LLM provider and key for embeddings')"
|
|
2789
3323
|
>
|
|
2790
3324
|
<mat-icon>merge_type</mat-icon>
|
|
2791
|
-
<span class="ai-action-label">
|
|
3325
|
+
<span class="ai-action-label">{{ tx('Use the LLM provider and key for embeddings') }}</span>
|
|
2792
3326
|
</button>
|
|
2793
|
-
<mat-chip-option *ngIf="!canUseLlmForEmbeddings" disabled>
|
|
3327
|
+
<mat-chip-option *ngIf="!canUseLlmForEmbeddings" disabled>{{ tx('Provider has no embeddings') }}</mat-chip-option>
|
|
2794
3328
|
</div>
|
|
2795
3329
|
</div>
|
|
2796
3330
|
<div class="ai-subtext">
|
|
2797
|
-
Configure
|
|
3331
|
+
{{ tx('Configure the embeddings provider for vector search (templates and schemas).') }}
|
|
2798
3332
|
</div>
|
|
2799
3333
|
<div class="ai-subtext" *ngIf="embeddingUseSameAsLlm">
|
|
2800
|
-
|
|
3334
|
+
{{ tx('Synchronized with the LLM. The fields below follow the primary credential.') }}
|
|
2801
3335
|
</div>
|
|
2802
3336
|
<div class="ai-embedding-row">
|
|
2803
3337
|
<ng-template #hostAiEmbedding></ng-template>
|
|
@@ -2805,7 +3339,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2805
3339
|
<div class="ai-feedback ai-feedback--warn" *ngIf="embeddingDimensionMismatch">
|
|
2806
3340
|
<mat-icon>warning</mat-icon>
|
|
2807
3341
|
<span class="error-text">
|
|
2808
|
-
|
|
3342
|
+
{{ tx('Embedding dimension mismatch with database (768). Adjust to 768 or redo the migration.') }}
|
|
2809
3343
|
</span>
|
|
2810
3344
|
</div>
|
|
2811
3345
|
</div>
|
|
@@ -2816,9 +3350,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2816
3350
|
<mat-expansion-panel-header>
|
|
2817
3351
|
<mat-panel-title>
|
|
2818
3352
|
<mat-icon class="panel-icon">table_chart</mat-icon>
|
|
2819
|
-
|
|
3353
|
+
{{ tx('Table') }}
|
|
2820
3354
|
</mat-panel-title>
|
|
2821
|
-
<mat-panel-description>Toolbar,
|
|
3355
|
+
<mat-panel-description>{{ tx('Toolbar, appearance and advanced filter') }}</mat-panel-description>
|
|
2822
3356
|
</mat-expansion-panel-header>
|
|
2823
3357
|
<ng-template #hostTable></ng-template>
|
|
2824
3358
|
</mat-expansion-panel>
|
|
@@ -2826,27 +3360,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2826
3360
|
<mat-expansion-panel-header>
|
|
2827
3361
|
<mat-panel-title>
|
|
2828
3362
|
<mat-icon class="panel-icon">forum</mat-icon>
|
|
2829
|
-
Dialog
|
|
3363
|
+
{{ tx('Dialog') }}
|
|
2830
3364
|
</mat-panel-title>
|
|
2831
|
-
<mat-panel-description>Defaults
|
|
3365
|
+
<mat-panel-description>{{ tx('Defaults and variants (danger, info, success, question, error)') }}</mat-panel-description>
|
|
2832
3366
|
</mat-expansion-panel-header>
|
|
2833
3367
|
<ng-template #hostDialog></ng-template>
|
|
2834
3368
|
<!-- Icon UX helpers for Dialog variants -->
|
|
2835
3369
|
<div class="dlg-icon-helpers">
|
|
2836
|
-
<div class="dlg-icon-helpers__head"
|
|
3370
|
+
<div class="dlg-icon-helpers__head">{{ tx('Icons by profile (shortcuts)') }}</div>
|
|
2837
3371
|
<div class="dlg-icon-helpers__row" *ngFor="let k of dialogVariantKeys">
|
|
2838
3372
|
<div class="dlg-icon-helpers__label">{{ k }}</div>
|
|
2839
3373
|
<mat-icon aria-hidden="true" [praxisIcon]="getVariantIcon(k) || 'mi:help_outline'" class="dlg-icon-helpers__preview"></mat-icon>
|
|
2840
|
-
<button mat-stroked-button color="primary" type="button" (click)="pickVariantIcon(k)" matTooltip="
|
|
3374
|
+
<button mat-stroked-button color="primary" type="button" (click)="pickVariantIcon(k)" [matTooltip]="tx('Pick icon for {{key}}', { key: k })">
|
|
2841
3375
|
<mat-icon>search</mat-icon>
|
|
2842
|
-
|
|
3376
|
+
{{ tx('Pick icon') }}
|
|
2843
3377
|
</button>
|
|
2844
|
-
<button mat-icon-button type="button" *ngIf="getVariantIcon(k)" (click)="clearVariantIcon(k)" matTooltip="
|
|
3378
|
+
<button mat-icon-button type="button" *ngIf="getVariantIcon(k)" (click)="clearVariantIcon(k)" [matTooltip]="tx('Clear icon for {{key}}', { key: k })" [attr.aria-label]="tx('Clear icon')">
|
|
2845
3379
|
<mat-icon>backspace</mat-icon>
|
|
2846
3380
|
</button>
|
|
2847
3381
|
<span class="dlg-icon-helpers__value" *ngIf="getVariantIcon(k)">{{ getVariantIcon(k) }}</span>
|
|
2848
3382
|
</div>
|
|
2849
|
-
<div class="dlg-icon-helpers__hint">
|
|
3383
|
+
<div class="dlg-icon-helpers__hint">{{ tx('The text field above remains editable. These buttons only help with selection/clear preview.') }}</div>
|
|
2850
3384
|
</div>
|
|
2851
3385
|
</mat-expansion-panel>
|
|
2852
3386
|
</mat-accordion>
|
|
@@ -2885,7 +3419,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2885
3419
|
function openGlobalConfigEditor(settings, opts) {
|
|
2886
3420
|
settings.open({
|
|
2887
3421
|
id: opts?.id ?? 'global-config',
|
|
2888
|
-
title: opts?.title
|
|
3422
|
+
title: opts?.title,
|
|
2889
3423
|
titleIcon: opts?.titleIcon ?? 'tune',
|
|
2890
3424
|
content: { component: GlobalConfigEditorComponent, inputs: {} },
|
|
2891
3425
|
});
|
|
@@ -2929,5 +3463,4 @@ const SETTINGS_PANEL_AI_CAPABILITIES = {
|
|
|
2929
3463
|
* Generated bundle index. Do not edit.
|
|
2930
3464
|
*/
|
|
2931
3465
|
|
|
2932
|
-
export { GLOBAL_CONFIG_DYNAMIC_FORM_COMPONENT, GlobalConfigAdminService, GlobalConfigEditorComponent, SETTINGS_PANEL_AI_CAPABILITIES, SETTINGS_PANEL_DATA, SETTINGS_PANEL_REF, SettingsPanelComponent, SettingsPanelRef, SettingsPanelService, buildGlobalConfigFormConfig, openGlobalConfigEditor };
|
|
2933
|
-
//# sourceMappingURL=praxisui-settings-panel.mjs.map
|
|
3466
|
+
export { GLOBAL_CONFIG_DYNAMIC_FORM_COMPONENT, GlobalConfigAdminService, GlobalConfigEditorComponent, SETTINGS_PANEL_AI_CAPABILITIES, SETTINGS_PANEL_DATA, SETTINGS_PANEL_REF, SettingsPanelComponent, SettingsPanelRef, SettingsPanelService, buildGlobalConfigFormConfig, openGlobalConfigEditor, providePraxisSettingsPanelBridge };
|