@praxisui/settings-panel 3.0.0-beta.7 → 3.0.0-beta.9
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, SETTINGS_PANEL_DATA as SETTINGS_PANEL_DATA$1, SETTINGS_PANEL_BRIDGE, 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,21 +529,20 @@ 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
547
|
attachContent(component, injector, ref, inputs) {
|
|
91
548
|
this.ref = ref;
|
|
@@ -118,7 +575,6 @@ class SettingsPanelComponent {
|
|
|
118
575
|
this.cdr.markForCheck();
|
|
119
576
|
});
|
|
120
577
|
}
|
|
121
|
-
// Generic output bridging: if the embedded component emits `selected`, save and close.
|
|
122
578
|
try {
|
|
123
579
|
const selected$ = instance?.selected;
|
|
124
580
|
if (selected$ && typeof selected$.subscribe === 'function') {
|
|
@@ -126,7 +582,6 @@ class SettingsPanelComponent {
|
|
|
126
582
|
? selected$.pipe(takeUntilDestroyed(this.destroyRef))
|
|
127
583
|
: selected$;
|
|
128
584
|
obs.subscribe((value) => {
|
|
129
|
-
// Apply emits value to the opener without closing the panel.
|
|
130
585
|
this.ref.apply(value);
|
|
131
586
|
});
|
|
132
587
|
}
|
|
@@ -164,10 +619,10 @@ class SettingsPanelComponent {
|
|
|
164
619
|
}
|
|
165
620
|
onReset() {
|
|
166
621
|
const dialogData = {
|
|
167
|
-
title: '
|
|
168
|
-
message: '
|
|
169
|
-
confirmText: '
|
|
170
|
-
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'),
|
|
171
626
|
type: 'warning',
|
|
172
627
|
icon: 'restart_alt',
|
|
173
628
|
};
|
|
@@ -219,15 +674,21 @@ class SettingsPanelComponent {
|
|
|
219
674
|
this.cdr.markForCheck();
|
|
220
675
|
}
|
|
221
676
|
formatClock(timestamp) {
|
|
677
|
+
const options = {
|
|
678
|
+
hour: '2-digit',
|
|
679
|
+
minute: '2-digit',
|
|
680
|
+
second: '2-digit',
|
|
681
|
+
};
|
|
222
682
|
try {
|
|
223
|
-
return new Intl.DateTimeFormat(
|
|
224
|
-
hour: '2-digit',
|
|
225
|
-
minute: '2-digit',
|
|
226
|
-
second: '2-digit',
|
|
227
|
-
}).format(timestamp);
|
|
683
|
+
return new Intl.DateTimeFormat(this.i18n.getLocale(), options).format(timestamp);
|
|
228
684
|
}
|
|
229
685
|
catch {
|
|
230
|
-
|
|
686
|
+
try {
|
|
687
|
+
return new Intl.DateTimeFormat(this.i18n.getFallbackLocale(), options).format(timestamp);
|
|
688
|
+
}
|
|
689
|
+
catch {
|
|
690
|
+
return '';
|
|
691
|
+
}
|
|
231
692
|
}
|
|
232
693
|
}
|
|
233
694
|
toggleExpand() {
|
|
@@ -241,10 +702,10 @@ class SettingsPanelComponent {
|
|
|
241
702
|
return of(true);
|
|
242
703
|
}
|
|
243
704
|
const dialogData = {
|
|
244
|
-
title: '
|
|
245
|
-
message: '
|
|
246
|
-
confirmText: '
|
|
247
|
-
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'),
|
|
248
709
|
type: 'warning',
|
|
249
710
|
icon: 'warning',
|
|
250
711
|
};
|
|
@@ -265,13 +726,14 @@ class SettingsPanelComponent {
|
|
|
265
726
|
event.preventDefault();
|
|
266
727
|
this.onSave();
|
|
267
728
|
}
|
|
268
|
-
else if ((event.key === 's' || event.key === 'S') &&
|
|
729
|
+
else if ((event.key === 's' || event.key === 'S') &&
|
|
730
|
+
(event.ctrlKey || event.metaKey)) {
|
|
269
731
|
event.preventDefault();
|
|
270
732
|
this.onSave();
|
|
271
733
|
}
|
|
272
734
|
}
|
|
273
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 });
|
|
274
|
-
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%)}.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 });
|
|
275
737
|
}
|
|
276
738
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: SettingsPanelComponent, decorators: [{
|
|
277
739
|
type: Component,
|
|
@@ -284,7 +746,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
284
746
|
CdkTrapFocus,
|
|
285
747
|
MatProgressSpinnerModule,
|
|
286
748
|
MatDialogModule,
|
|
287
|
-
], 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%)}.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"] }]
|
|
288
750
|
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1.MatDialog }], propDecorators: { contentHost: [{
|
|
289
751
|
type: ViewChild,
|
|
290
752
|
args: ['contentHost', { read: ViewContainerRef, static: true }]
|
|
@@ -348,6 +810,7 @@ class SettingsPanelService {
|
|
|
348
810
|
overlay;
|
|
349
811
|
injector;
|
|
350
812
|
currentRef;
|
|
813
|
+
i18n = inject(PraxisI18nService);
|
|
351
814
|
constructor(overlay, injector) {
|
|
352
815
|
this.overlay = overlay;
|
|
353
816
|
this.injector = injector;
|
|
@@ -373,7 +836,9 @@ class SettingsPanelService {
|
|
|
373
836
|
const ref = new SettingsPanelRef(overlayRef);
|
|
374
837
|
const panelPortal = new ComponentPortal(SettingsPanelComponent);
|
|
375
838
|
const panelRef = overlayRef.attach(panelPortal);
|
|
376
|
-
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);
|
|
377
842
|
panelRef.instance.titleIcon = config.titleIcon;
|
|
378
843
|
panelRef.instance.expanded = config.expanded || false;
|
|
379
844
|
const inputs = config.content.inputs;
|
|
@@ -473,6 +938,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
473
938
|
args: [{ providedIn: 'root' }]
|
|
474
939
|
}] });
|
|
475
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
|
+
|
|
476
973
|
const TABLE_COMPACT_LENGTH_TOKEN$1 = '(?:0|(?:\\d+|\\d*\\.\\d+)(?:px|rem|em|%|vh|vw|svh|svw|lvh|lvw|dvh|dvw|ch|ex))';
|
|
477
974
|
const TABLE_COMPACT_SPACING_PATTERN = `^(?:var\\(.+\\)|calc\\(.+\\)|${TABLE_COMPACT_LENGTH_TOKEN$1}(?:\\s+${TABLE_COMPACT_LENGTH_TOKEN$1}){0,3})$`;
|
|
478
975
|
const TABLE_COMPACT_FONT_SIZE_PATTERN = `^(?:var\\(.+\\)|calc\\(.+\\)|${TABLE_COMPACT_LENGTH_TOKEN$1})$`;
|
|
@@ -483,30 +980,31 @@ function safeName(path) {
|
|
|
483
980
|
* Minimal FormConfig schema for the Global Config editor UI.
|
|
484
981
|
* This can be extended incrementally as new domains/settings are added.
|
|
485
982
|
*/
|
|
486
|
-
function buildGlobalConfigFormConfig() {
|
|
983
|
+
function buildGlobalConfigFormConfig(translate = (text) => text) {
|
|
984
|
+
const tx = (text, params) => translate(normalizeMojibakeText(text), params);
|
|
487
985
|
const fields = [
|
|
488
986
|
// CRUD
|
|
489
987
|
{
|
|
490
988
|
name: safeName('crud.defaults.openMode'),
|
|
491
|
-
label: 'Modo de abertura padrão',
|
|
989
|
+
label: tx('Modo de abertura padrão'),
|
|
492
990
|
controlType: FieldControlType.SELECT,
|
|
493
991
|
selectOptions: [
|
|
494
|
-
{ text: 'Rota', value: 'route' },
|
|
992
|
+
{ text: tx('Rota'), value: 'route' },
|
|
495
993
|
{ text: 'Modal', value: 'modal' },
|
|
496
994
|
{ text: 'Drawer', value: 'drawer' },
|
|
497
995
|
],
|
|
498
|
-
hint: 'Aplicado quando ação/metadado não definem modo.',
|
|
996
|
+
hint: tx('Aplicado quando ação/metadado não definem modo.'),
|
|
499
997
|
dataAttributes: { globalPath: 'crud.defaults.openMode' },
|
|
500
998
|
},
|
|
501
999
|
{
|
|
502
1000
|
name: safeName('crud.defaults.back.confirmOnDirty'),
|
|
503
|
-
label: 'Confirmar ao sair com alterações',
|
|
1001
|
+
label: tx('Confirmar ao sair com alterações'),
|
|
504
1002
|
controlType: FieldControlType.TOGGLE,
|
|
505
1003
|
dataAttributes: { globalPath: 'crud.defaults.back.confirmOnDirty' },
|
|
506
1004
|
},
|
|
507
1005
|
{
|
|
508
1006
|
name: safeName('crud.defaults.back.strategy'),
|
|
509
|
-
label: 'Back: estratégia',
|
|
1007
|
+
label: tx('Back: estratégia'),
|
|
510
1008
|
controlType: FieldControlType.SELECT,
|
|
511
1009
|
selectOptions: [
|
|
512
1010
|
{ text: 'auto', value: 'auto' },
|
|
@@ -517,13 +1015,13 @@ function buildGlobalConfigFormConfig() {
|
|
|
517
1015
|
},
|
|
518
1016
|
{
|
|
519
1017
|
name: safeName('crud.defaults.header.showBack'),
|
|
520
|
-
label: 'Header:
|
|
1018
|
+
label: tx('Header: show back'),
|
|
521
1019
|
controlType: FieldControlType.TOGGLE,
|
|
522
1020
|
dataAttributes: { globalPath: 'crud.defaults.header.showBack' },
|
|
523
1021
|
},
|
|
524
1022
|
{
|
|
525
1023
|
name: safeName('crud.defaults.header.variant'),
|
|
526
|
-
label: 'Header:
|
|
1024
|
+
label: tx('Header: variant'),
|
|
527
1025
|
controlType: FieldControlType.SELECT,
|
|
528
1026
|
selectOptions: [
|
|
529
1027
|
{ text: 'ghost', value: 'ghost' },
|
|
@@ -534,31 +1032,31 @@ function buildGlobalConfigFormConfig() {
|
|
|
534
1032
|
},
|
|
535
1033
|
{
|
|
536
1034
|
name: safeName('crud.defaults.header.sticky'),
|
|
537
|
-
label: 'Header:
|
|
1035
|
+
label: tx('Header: sticky'),
|
|
538
1036
|
controlType: FieldControlType.TOGGLE,
|
|
539
1037
|
dataAttributes: { globalPath: 'crud.defaults.header.sticky' },
|
|
540
1038
|
},
|
|
541
1039
|
{
|
|
542
1040
|
name: safeName('crud.defaults.header.divider'),
|
|
543
|
-
label: 'Header:
|
|
1041
|
+
label: tx('Header: show divider'),
|
|
544
1042
|
controlType: FieldControlType.TOGGLE,
|
|
545
1043
|
dataAttributes: { globalPath: 'crud.defaults.header.divider' },
|
|
546
1044
|
},
|
|
547
1045
|
{
|
|
548
1046
|
name: safeName('crud.defaults.modal.width'),
|
|
549
|
-
label: 'Modal:
|
|
1047
|
+
label: tx('Modal: width (e.g. 900px)'),
|
|
550
1048
|
controlType: FieldControlType.INPUT,
|
|
551
1049
|
dataAttributes: { globalPath: 'crud.defaults.modal.width' },
|
|
552
1050
|
},
|
|
553
1051
|
{
|
|
554
1052
|
name: safeName('crud.defaults.modal.maxWidth'),
|
|
555
|
-
label: 'Modal: largura máxima (ex.: 96vw)',
|
|
1053
|
+
label: tx('Modal: largura máxima (ex.: 96vw)'),
|
|
556
1054
|
controlType: FieldControlType.INPUT,
|
|
557
1055
|
dataAttributes: { globalPath: 'crud.defaults.modal.maxWidth' },
|
|
558
1056
|
},
|
|
559
1057
|
{
|
|
560
1058
|
name: safeName('crud.defaults.modal.backdropStyle'),
|
|
561
|
-
label: 'Modal: backdrop',
|
|
1059
|
+
label: tx('Modal: backdrop'),
|
|
562
1060
|
controlType: FieldControlType.SELECT,
|
|
563
1061
|
selectOptions: [
|
|
564
1062
|
{ text: 'blur', value: 'blur' },
|
|
@@ -570,25 +1068,25 @@ function buildGlobalConfigFormConfig() {
|
|
|
570
1068
|
// Dynamic Fields
|
|
571
1069
|
{
|
|
572
1070
|
name: safeName('dynamicFields.asyncSelect.loadOn'),
|
|
573
|
-
label: 'Async Select: loadOn',
|
|
1071
|
+
label: tx('Async Select: loadOn'),
|
|
574
1072
|
controlType: FieldControlType.SELECT,
|
|
575
1073
|
selectOptions: [
|
|
576
1074
|
{ text: 'open', value: 'open' },
|
|
577
1075
|
{ text: 'init', value: 'init' },
|
|
578
1076
|
{ text: 'none', value: 'none' },
|
|
579
1077
|
],
|
|
580
|
-
hint: 'Estratégia de primeira carga quando metadado não definir.',
|
|
1078
|
+
hint: tx('Estratégia de primeira carga quando metadado não definir.'),
|
|
581
1079
|
dataAttributes: { globalPath: 'dynamicFields.asyncSelect.loadOn' },
|
|
582
1080
|
},
|
|
583
1081
|
{
|
|
584
1082
|
name: safeName('dynamicFields.cascade.enable'),
|
|
585
|
-
label: '
|
|
1083
|
+
label: tx('Native cascade enabled'),
|
|
586
1084
|
controlType: FieldControlType.TOGGLE,
|
|
587
1085
|
dataAttributes: { globalPath: 'dynamicFields.cascade.enable' },
|
|
588
1086
|
},
|
|
589
1087
|
{
|
|
590
1088
|
name: safeName('dynamicFields.cascade.loadOnChange'),
|
|
591
|
-
label: '
|
|
1089
|
+
label: tx('Cascade: loadOnChange'),
|
|
592
1090
|
controlType: FieldControlType.SELECT,
|
|
593
1091
|
selectOptions: [
|
|
594
1092
|
{ text: 'respectLoadOn', value: 'respectLoadOn' },
|
|
@@ -599,42 +1097,42 @@ function buildGlobalConfigFormConfig() {
|
|
|
599
1097
|
},
|
|
600
1098
|
{
|
|
601
1099
|
name: safeName('dynamicFields.cascade.debounceMs'),
|
|
602
|
-
label: '
|
|
1100
|
+
label: tx('Cascade: debounce (ms)'),
|
|
603
1101
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
604
1102
|
dataAttributes: { globalPath: 'dynamicFields.cascade.debounceMs' },
|
|
605
1103
|
},
|
|
606
1104
|
// Dynamic Fields async-select extra
|
|
607
1105
|
{
|
|
608
1106
|
name: safeName('dynamicFields.asyncSelect.pageSize'),
|
|
609
|
-
label: 'Async Select: pageSize',
|
|
1107
|
+
label: tx('Async Select: pageSize'),
|
|
610
1108
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
611
1109
|
dataAttributes: { globalPath: 'dynamicFields.asyncSelect.pageSize' },
|
|
612
1110
|
},
|
|
613
1111
|
{
|
|
614
1112
|
name: safeName('dynamicFields.asyncSelect.useCursor'),
|
|
615
|
-
label: 'Async Select:
|
|
1113
|
+
label: tx('Async Select: use cursor'),
|
|
616
1114
|
controlType: FieldControlType.TOGGLE,
|
|
617
1115
|
dataAttributes: { globalPath: 'dynamicFields.asyncSelect.useCursor' },
|
|
618
1116
|
},
|
|
619
1117
|
// AI
|
|
620
1118
|
{
|
|
621
1119
|
name: safeName('ai.provider'),
|
|
622
|
-
label: '
|
|
1120
|
+
label: tx('LLM provider'),
|
|
623
1121
|
controlType: FieldControlType.SELECT,
|
|
624
1122
|
selectOptions: [],
|
|
625
|
-
hint: '
|
|
1123
|
+
hint: tx('Select the provider to list models and test the key.'),
|
|
626
1124
|
dataAttributes: { globalPath: 'ai.provider' },
|
|
627
1125
|
},
|
|
628
1126
|
{
|
|
629
1127
|
name: safeName('ai.apiKey'),
|
|
630
|
-
label: '
|
|
1128
|
+
label: tx('API key'),
|
|
631
1129
|
controlType: FieldControlType.INPUT,
|
|
632
|
-
hint: '
|
|
1130
|
+
hint: tx('Enter the selected provider key to test.'),
|
|
633
1131
|
dataAttributes: { globalPath: 'ai.apiKey' },
|
|
634
1132
|
},
|
|
635
1133
|
{
|
|
636
1134
|
name: safeName('ai.model'),
|
|
637
|
-
label: '
|
|
1135
|
+
label: tx('AI model'),
|
|
638
1136
|
controlType: FieldControlType.SEARCHABLE_SELECT,
|
|
639
1137
|
selectOptions: [],
|
|
640
1138
|
resourcePath: '',
|
|
@@ -642,113 +1140,113 @@ function buildGlobalConfigFormConfig() {
|
|
|
642
1140
|
},
|
|
643
1141
|
{
|
|
644
1142
|
name: safeName('ai.temperature'),
|
|
645
|
-
label: '
|
|
1143
|
+
label: tx('Temperature (Creativity)'),
|
|
646
1144
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
647
|
-
hint: '0.0 (
|
|
1145
|
+
hint: tx('0.0 (deterministic) to 1.0 (creative)'),
|
|
648
1146
|
dataAttributes: { globalPath: 'ai.temperature' },
|
|
649
1147
|
},
|
|
650
1148
|
{
|
|
651
1149
|
name: safeName('ai.maxTokens'),
|
|
652
|
-
label: 'Max tokens',
|
|
1150
|
+
label: tx('Max tokens'),
|
|
653
1151
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
654
|
-
hint: '
|
|
1152
|
+
hint: tx('Maximum token limit for the response.'),
|
|
655
1153
|
dataAttributes: { globalPath: 'ai.maxTokens' },
|
|
656
1154
|
},
|
|
657
1155
|
{
|
|
658
1156
|
name: safeName('ai.riskPolicy'),
|
|
659
|
-
label: '
|
|
1157
|
+
label: tx('Assistant: risk validation'),
|
|
660
1158
|
controlType: FieldControlType.SELECT,
|
|
661
1159
|
selectOptions: [
|
|
662
|
-
{ text: '
|
|
663
|
-
{ text: '
|
|
1160
|
+
{ text: 'Strict (recommended)', value: 'strict' },
|
|
1161
|
+
{ text: tx('Standard'), value: 'standard' },
|
|
664
1162
|
],
|
|
665
|
-
hint: '
|
|
1163
|
+
hint: tx('Strict requires confirmation for medium/high risk. Standard follows the indication returned by the backend.'),
|
|
666
1164
|
dataAttributes: { globalPath: 'ai.riskPolicy' },
|
|
667
1165
|
},
|
|
668
1166
|
{
|
|
669
1167
|
name: safeName('ai.embedding.useSameAsLlm'),
|
|
670
|
-
label: '
|
|
1168
|
+
label: tx('Use same LLM for embeddings'),
|
|
671
1169
|
controlType: FieldControlType.TOGGLE,
|
|
672
|
-
hint: '
|
|
1170
|
+
hint: tx('Replicates the LLM provider and key for embeddings.'),
|
|
673
1171
|
dataAttributes: { globalPath: 'ai.embedding.useSameAsLlm' },
|
|
674
1172
|
},
|
|
675
1173
|
{
|
|
676
1174
|
name: safeName('ai.embedding.provider'),
|
|
677
|
-
label: 'Embeddings
|
|
1175
|
+
label: tx('Embeddings provider'),
|
|
678
1176
|
controlType: FieldControlType.SELECT,
|
|
679
1177
|
selectOptions: [],
|
|
680
|
-
hint: '
|
|
1178
|
+
hint: tx('Provider used to generate embeddings (RAG).'),
|
|
681
1179
|
dataAttributes: { globalPath: 'ai.embedding.provider' },
|
|
682
1180
|
},
|
|
683
1181
|
{
|
|
684
1182
|
name: safeName('ai.embedding.apiKey'),
|
|
685
|
-
label: 'Embeddings
|
|
1183
|
+
label: tx('Embeddings API key'),
|
|
686
1184
|
controlType: FieldControlType.INPUT,
|
|
687
|
-
hint: '
|
|
1185
|
+
hint: tx('Embeddings provider key.'),
|
|
688
1186
|
dataAttributes: { globalPath: 'ai.embedding.apiKey' },
|
|
689
1187
|
},
|
|
690
1188
|
{
|
|
691
1189
|
name: safeName('ai.embedding.model'),
|
|
692
|
-
label: 'Embeddings
|
|
1190
|
+
label: tx('Embeddings model'),
|
|
693
1191
|
controlType: FieldControlType.SEARCHABLE_SELECT,
|
|
694
1192
|
selectOptions: [
|
|
695
1193
|
{ text: 'text-embedding-3-large', value: 'text-embedding-3-large' },
|
|
696
1194
|
{ text: 'text-embedding-3-small', value: 'text-embedding-3-small' },
|
|
697
1195
|
{ text: 'text-embedding-ada-002 (legacy)', value: 'text-embedding-ada-002' },
|
|
698
1196
|
],
|
|
699
|
-
emptyOptionText: '
|
|
700
|
-
hint: '
|
|
1197
|
+
emptyOptionText: tx('Provider default'),
|
|
1198
|
+
hint: tx('OpenAI models for embeddings.'),
|
|
701
1199
|
dataAttributes: { globalPath: 'ai.embedding.model' },
|
|
702
1200
|
},
|
|
703
1201
|
{
|
|
704
1202
|
name: safeName('ai.embedding.dimensions'),
|
|
705
|
-
label: 'Embeddings:
|
|
1203
|
+
label: tx('Embeddings: dimensions'),
|
|
706
1204
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
707
|
-
hint: '
|
|
1205
|
+
hint: tx('Embedding vector dimensions (default 768).'),
|
|
708
1206
|
dataAttributes: { globalPath: 'ai.embedding.dimensions' },
|
|
709
1207
|
},
|
|
710
|
-
// Cache
|
|
1208
|
+
// Cache // Cache
|
|
711
1209
|
{
|
|
712
1210
|
name: safeName('cache.disableSchemaCache'),
|
|
713
|
-
label: 'Desabilitar cache de schema (LocalStorage)',
|
|
1211
|
+
label: tx('Desabilitar cache de schema (LocalStorage)'),
|
|
714
1212
|
controlType: FieldControlType.TOGGLE,
|
|
715
|
-
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.'),
|
|
716
1214
|
dataAttributes: { globalPath: 'cache.disableSchemaCache' },
|
|
717
1215
|
},
|
|
718
1216
|
// Table
|
|
719
1217
|
{
|
|
720
1218
|
name: safeName('table.behavior.pagination.enabled'),
|
|
721
|
-
label: 'Paginação habilitada',
|
|
1219
|
+
label: tx('Paginação habilitada'),
|
|
722
1220
|
controlType: FieldControlType.TOGGLE,
|
|
723
1221
|
dataAttributes: { globalPath: 'table.behavior.pagination.enabled' },
|
|
724
1222
|
},
|
|
725
1223
|
{
|
|
726
1224
|
name: safeName('table.behavior.pagination.pageSize'),
|
|
727
|
-
label: 'Tamanho da página',
|
|
1225
|
+
label: tx('Tamanho da página'),
|
|
728
1226
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
729
1227
|
dataAttributes: { globalPath: 'table.behavior.pagination.pageSize' },
|
|
730
1228
|
},
|
|
731
1229
|
{
|
|
732
1230
|
name: safeName('table.behavior.filtering.debounceTime'),
|
|
733
|
-
label: '
|
|
1231
|
+
label: tx('Filter debounce (ms)'),
|
|
734
1232
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
735
1233
|
dataAttributes: { globalPath: 'table.behavior.filtering.debounceTime' },
|
|
736
1234
|
},
|
|
737
1235
|
{
|
|
738
1236
|
name: safeName('table.behavior.sorting.enabled'),
|
|
739
|
-
label: 'Ordenação habilitada',
|
|
1237
|
+
label: tx('Ordenação habilitada'),
|
|
740
1238
|
controlType: FieldControlType.TOGGLE,
|
|
741
1239
|
dataAttributes: { globalPath: 'table.behavior.sorting.enabled' },
|
|
742
1240
|
},
|
|
743
1241
|
{
|
|
744
1242
|
name: safeName('table.behavior.selection.enabled'),
|
|
745
|
-
label: 'Seleção habilitada',
|
|
1243
|
+
label: tx('Seleção habilitada'),
|
|
746
1244
|
controlType: FieldControlType.TOGGLE,
|
|
747
1245
|
dataAttributes: { globalPath: 'table.behavior.selection.enabled' },
|
|
748
1246
|
},
|
|
749
1247
|
{
|
|
750
1248
|
name: safeName('table.behavior.pagination.strategy'),
|
|
751
|
-
label: 'Paginação: estratégia',
|
|
1249
|
+
label: tx('Paginação: estratégia'),
|
|
752
1250
|
controlType: FieldControlType.SELECT,
|
|
753
1251
|
selectOptions: [
|
|
754
1252
|
{ text: 'client', value: 'client' },
|
|
@@ -758,7 +1256,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
758
1256
|
},
|
|
759
1257
|
{
|
|
760
1258
|
name: safeName('table.behavior.sorting.strategy'),
|
|
761
|
-
label: 'Ordenação: estratégia',
|
|
1259
|
+
label: tx('Ordenação: estratégia'),
|
|
762
1260
|
controlType: FieldControlType.SELECT,
|
|
763
1261
|
selectOptions: [
|
|
764
1262
|
{ text: 'client', value: 'client' },
|
|
@@ -768,114 +1266,113 @@ function buildGlobalConfigFormConfig() {
|
|
|
768
1266
|
},
|
|
769
1267
|
{
|
|
770
1268
|
name: safeName('table.behavior.pagination.showFirstLastButtons'),
|
|
771
|
-
label: 'Paginação: botões Primeiro/Último',
|
|
1269
|
+
label: tx('Paginação: botões Primeiro/Último'),
|
|
772
1270
|
controlType: FieldControlType.CHECKBOX,
|
|
773
1271
|
dataAttributes: { globalPath: 'table.behavior.pagination.showFirstLastButtons' },
|
|
774
1272
|
},
|
|
775
1273
|
{
|
|
776
1274
|
name: safeName('table.toolbar.visible'),
|
|
777
|
-
label: 'Toolbar visível',
|
|
1275
|
+
label: tx('Toolbar visível'),
|
|
778
1276
|
controlType: FieldControlType.CHECKBOX,
|
|
779
1277
|
dataAttributes: { globalPath: 'table.toolbar.visible' },
|
|
780
1278
|
},
|
|
781
1279
|
{
|
|
782
1280
|
name: safeName('table.appearance.density'),
|
|
783
|
-
label: '
|
|
1281
|
+
label: tx('Appearance: density'),
|
|
784
1282
|
controlType: FieldControlType.SELECT,
|
|
785
1283
|
selectOptions: [
|
|
786
|
-
{ text: 'compact', value: 'compact' },
|
|
787
|
-
{ text: 'comfortable', value: 'comfortable' },
|
|
788
|
-
{ text: 'spacious', value: 'spacious' },
|
|
1284
|
+
{ text: tx('compact'), value: 'compact' },
|
|
1285
|
+
{ text: tx('comfortable'), value: 'comfortable' },
|
|
1286
|
+
{ text: tx('spacious'), value: 'spacious' },
|
|
789
1287
|
],
|
|
790
1288
|
dataAttributes: { globalPath: 'table.appearance.density' },
|
|
791
1289
|
},
|
|
792
1290
|
{
|
|
793
1291
|
name: safeName('table.appearance.spacing.cellPadding'),
|
|
794
|
-
label: '
|
|
1292
|
+
label: tx('Appearance: cell padding'),
|
|
795
1293
|
controlType: FieldControlType.INPUT,
|
|
796
|
-
hint: '
|
|
1294
|
+
hint: tx('Accepts 1 to 4 CSS measures with units, var(...) or calc(...). Example: 6px 12px'),
|
|
797
1295
|
pattern: TABLE_COMPACT_SPACING_PATTERN,
|
|
798
|
-
patternMessage: 'Use 1
|
|
1296
|
+
patternMessage: tx('Use 1 to 4 valid CSS measures, such as 6px 12px.'),
|
|
799
1297
|
dataAttributes: { globalPath: 'table.appearance.spacing.cellPadding' },
|
|
800
1298
|
},
|
|
801
1299
|
{
|
|
802
1300
|
name: safeName('table.appearance.spacing.headerPadding'),
|
|
803
|
-
label: '
|
|
1301
|
+
label: tx('Appearance: header padding'),
|
|
804
1302
|
controlType: FieldControlType.INPUT,
|
|
805
|
-
hint: '
|
|
1303
|
+
hint: tx('Accepts 1 to 4 CSS measures with units, var(...) or calc(...). Example: 8px 12px'),
|
|
806
1304
|
pattern: TABLE_COMPACT_SPACING_PATTERN,
|
|
807
|
-
patternMessage: 'Use 1
|
|
1305
|
+
patternMessage: tx('Use 1 to 4 valid CSS measures, such as 8px 12px.'),
|
|
808
1306
|
dataAttributes: { globalPath: 'table.appearance.spacing.headerPadding' },
|
|
809
1307
|
},
|
|
810
1308
|
{
|
|
811
1309
|
name: safeName('table.appearance.typography.fontSize'),
|
|
812
|
-
label: '
|
|
1310
|
+
label: tx('Appearance: cell font size'),
|
|
813
1311
|
controlType: FieldControlType.INPUT,
|
|
814
|
-
hint: '
|
|
1312
|
+
hint: tx('Accepts a CSS measure with units, var(...) or calc(...). Example: 13px'),
|
|
815
1313
|
pattern: TABLE_COMPACT_FONT_SIZE_PATTERN,
|
|
816
|
-
patternMessage: 'Use
|
|
1314
|
+
patternMessage: tx('Use a valid CSS measure, such as 13px.'),
|
|
817
1315
|
dataAttributes: { globalPath: 'table.appearance.typography.fontSize' },
|
|
818
1316
|
},
|
|
819
1317
|
{
|
|
820
1318
|
name: safeName('table.appearance.typography.headerFontSize'),
|
|
821
|
-
label: '
|
|
1319
|
+
label: tx('Appearance: header font size'),
|
|
822
1320
|
controlType: FieldControlType.INPUT,
|
|
823
|
-
hint: '
|
|
1321
|
+
hint: tx('Accepts a CSS measure with units, var(...) or calc(...). Example: 13px'),
|
|
824
1322
|
pattern: TABLE_COMPACT_FONT_SIZE_PATTERN,
|
|
825
|
-
patternMessage: 'Use
|
|
1323
|
+
patternMessage: tx('Use a valid CSS measure, such as 13px.'),
|
|
826
1324
|
dataAttributes: { globalPath: 'table.appearance.typography.headerFontSize' },
|
|
827
|
-
},
|
|
828
|
-
{
|
|
1325
|
+
}, {
|
|
829
1326
|
name: safeName('table.filteringUi.advancedOpenMode'),
|
|
830
|
-
label: 'Filtro: modo de abertura',
|
|
1327
|
+
label: tx('Filtro: modo de abertura'),
|
|
831
1328
|
controlType: FieldControlType.SELECT,
|
|
832
1329
|
selectOptions: [
|
|
833
|
-
{ text: 'overlay', value: 'overlay' },
|
|
834
|
-
{ text: 'modal', value: 'modal' },
|
|
835
|
-
{ text: 'drawer', value: 'drawer' },
|
|
1330
|
+
{ text: tx('overlay'), value: 'overlay' },
|
|
1331
|
+
{ text: tx('modal'), value: 'modal' },
|
|
1332
|
+
{ text: tx('drawer'), value: 'drawer' },
|
|
836
1333
|
],
|
|
837
1334
|
dataAttributes: { globalPath: 'table.filteringUi.advancedOpenMode' },
|
|
838
1335
|
},
|
|
839
1336
|
{
|
|
840
1337
|
name: safeName('table.filteringUi.overlayVariant'),
|
|
841
|
-
label: 'Filtro: overlay (visual)',
|
|
1338
|
+
label: tx('Filtro: overlay (visual)'),
|
|
842
1339
|
controlType: FieldControlType.SELECT,
|
|
843
1340
|
selectOptions: [
|
|
844
|
-
{ text: 'card', value: 'card' },
|
|
845
|
-
{ text: 'frosted', value: 'frosted' },
|
|
1341
|
+
{ text: tx('card'), value: 'card' },
|
|
1342
|
+
{ text: tx('frosted'), value: 'frosted' },
|
|
846
1343
|
],
|
|
847
1344
|
dataAttributes: { globalPath: 'table.filteringUi.overlayVariant' },
|
|
848
1345
|
},
|
|
849
1346
|
{
|
|
850
1347
|
name: safeName('table.filteringUi.overlayBackdrop'),
|
|
851
|
-
label: 'Filtro: backdrop no overlay',
|
|
1348
|
+
label: tx('Filtro: backdrop no overlay'),
|
|
852
1349
|
controlType: FieldControlType.CHECKBOX,
|
|
853
1350
|
dataAttributes: { globalPath: 'table.filteringUi.overlayBackdrop' },
|
|
854
1351
|
},
|
|
855
1352
|
// Table messages - confirmations
|
|
856
|
-
{ name: safeName('table.messages.actions.confirmations.delete'), label: 'Excluir — confirmação', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.confirmations.delete' } },
|
|
857
|
-
{ name: safeName('table.messages.actions.confirmations.deleteMultiple'), label: 'Excluir (múltiplos) — confirmação', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.confirmations.deleteMultiple' } },
|
|
858
|
-
{ name: safeName('table.messages.actions.confirmations.save'), label: 'Salvar — confirmação', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.confirmations.save' } },
|
|
859
|
-
{ name: safeName('table.messages.actions.confirmations.cancel'), label: 'Cancelar — confirmação', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.confirmations.cancel' } },
|
|
860
|
-
{ 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' } },
|
|
861
1358
|
// Table messages - progress
|
|
862
|
-
{ name: safeName('table.messages.actions.progress.delete'), label: 'Excluir — progresso', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.progress.delete' } },
|
|
863
|
-
{ 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' } },
|
|
864
1361
|
// Table messages - success
|
|
865
|
-
{ name: safeName('table.messages.actions.success.delete'), label: 'Excluir — sucesso', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.success.delete' } },
|
|
866
|
-
{ name: safeName('table.messages.actions.success.save'), label: 'Salvar — sucesso', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.success.save' } },
|
|
867
|
-
{ name: safeName('table.messages.actions.success.export'), label: 'Exportar — sucesso', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.success.export' } },
|
|
868
|
-
{ 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' } },
|
|
869
1366
|
// Table messages - errors
|
|
870
|
-
{ name: safeName('table.messages.actions.errors.delete'), label: 'Excluir — erro', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.delete' } },
|
|
871
|
-
{ name: safeName('table.messages.actions.errors.save'), label: 'Salvar — erro', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.save' } },
|
|
872
|
-
{ name: safeName('table.messages.actions.errors.export'), label: 'Exportar — erro', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.export' } },
|
|
873
|
-
{ name: safeName('table.messages.actions.errors.network'), label: 'Rede — erro', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.network' } },
|
|
874
|
-
{ name: safeName('table.messages.actions.errors.permission'), label: 'Permissão — erro', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.permission' } },
|
|
875
|
-
// 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
|
|
876
1373
|
{
|
|
877
1374
|
name: safeName('dialog.defaults.confirm.ariaRole'),
|
|
878
|
-
label: 'Dialog
|
|
1375
|
+
label: tx('Dialog defaults: confirm - ariaRole'),
|
|
879
1376
|
controlType: FieldControlType.SELECT,
|
|
880
1377
|
selectOptions: [
|
|
881
1378
|
{ text: 'dialog', value: 'dialog' },
|
|
@@ -883,24 +1380,24 @@ function buildGlobalConfigFormConfig() {
|
|
|
883
1380
|
],
|
|
884
1381
|
dataAttributes: { globalPath: 'dialog.defaults.confirm.ariaRole' },
|
|
885
1382
|
},
|
|
886
|
-
{ name: safeName('dialog.defaults.confirm.title'), label: 'Dialog
|
|
887
|
-
{ name: safeName('dialog.defaults.confirm.icon'), label: 'Dialog
|
|
888
|
-
{ name: safeName('dialog.defaults.confirm.message'), label: 'Dialog
|
|
889
|
-
{ 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' } },
|
|
890
1387
|
{
|
|
891
1388
|
name: safeName('dialog.defaults.confirm.closeOnBackdropClick'),
|
|
892
|
-
label: 'Dialog
|
|
1389
|
+
label: tx('Dialog defaults: confirm - close on backdrop click'),
|
|
893
1390
|
controlType: FieldControlType.TOGGLE,
|
|
894
1391
|
dataAttributes: { globalPath: 'dialog.defaults.confirm.closeOnBackdropClick' },
|
|
895
1392
|
},
|
|
896
|
-
{ name: safeName('dialog.defaults.confirm.disableClose'), label: 'Dialog
|
|
897
|
-
{ name: safeName('dialog.defaults.confirm.hasBackdrop'), label: 'Dialog
|
|
898
|
-
{ name: safeName('dialog.defaults.confirm.panelClass'), label: 'Dialog
|
|
899
|
-
{ name: safeName('dialog.defaults.confirm.styles'), label: 'Dialog
|
|
900
|
-
{ 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 } },
|
|
901
1398
|
{
|
|
902
1399
|
name: safeName('dialog.defaults.alert.ariaRole'),
|
|
903
|
-
label: 'Dialog
|
|
1400
|
+
label: tx('Dialog defaults: alert - ariaRole'),
|
|
904
1401
|
controlType: FieldControlType.SELECT,
|
|
905
1402
|
selectOptions: [
|
|
906
1403
|
{ text: 'dialog', value: 'dialog' },
|
|
@@ -908,24 +1405,24 @@ function buildGlobalConfigFormConfig() {
|
|
|
908
1405
|
],
|
|
909
1406
|
dataAttributes: { globalPath: 'dialog.defaults.alert.ariaRole' },
|
|
910
1407
|
},
|
|
911
|
-
{ name: safeName('dialog.defaults.alert.title'), label: 'Dialog
|
|
912
|
-
{ name: safeName('dialog.defaults.alert.icon'), label: 'Dialog
|
|
913
|
-
{ name: safeName('dialog.defaults.alert.message'), label: 'Dialog
|
|
914
|
-
{ 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' } },
|
|
915
1412
|
{
|
|
916
1413
|
name: safeName('dialog.defaults.alert.closeOnBackdropClick'),
|
|
917
|
-
label: 'Dialog
|
|
1414
|
+
label: tx('Dialog defaults: alert - close on backdrop click'),
|
|
918
1415
|
controlType: FieldControlType.TOGGLE,
|
|
919
1416
|
dataAttributes: { globalPath: 'dialog.defaults.alert.closeOnBackdropClick' },
|
|
920
1417
|
},
|
|
921
|
-
{ name: safeName('dialog.defaults.alert.disableClose'), label: 'Dialog
|
|
922
|
-
{ name: safeName('dialog.defaults.alert.hasBackdrop'), label: 'Dialog
|
|
923
|
-
{ name: safeName('dialog.defaults.alert.panelClass'), label: 'Dialog
|
|
924
|
-
{ name: safeName('dialog.defaults.alert.styles'), label: 'Dialog
|
|
925
|
-
{ 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 } },
|
|
926
1423
|
{
|
|
927
1424
|
name: safeName('dialog.defaults.prompt.ariaRole'),
|
|
928
|
-
label: 'Dialog
|
|
1425
|
+
label: tx('Dialog defaults: prompt - ariaRole'),
|
|
929
1426
|
controlType: FieldControlType.SELECT,
|
|
930
1427
|
selectOptions: [
|
|
931
1428
|
{ text: 'dialog', value: 'dialog' },
|
|
@@ -933,79 +1430,79 @@ function buildGlobalConfigFormConfig() {
|
|
|
933
1430
|
],
|
|
934
1431
|
dataAttributes: { globalPath: 'dialog.defaults.prompt.ariaRole' },
|
|
935
1432
|
},
|
|
936
|
-
{ name: safeName('dialog.defaults.prompt.title'), label: 'Dialog
|
|
937
|
-
{ name: safeName('dialog.defaults.prompt.icon'), label: 'Dialog
|
|
938
|
-
{ name: safeName('dialog.defaults.prompt.message'), label: 'Dialog
|
|
939
|
-
{ 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' } },
|
|
940
1437
|
{
|
|
941
1438
|
name: safeName('dialog.defaults.prompt.closeOnBackdropClick'),
|
|
942
|
-
label: 'Dialog
|
|
1439
|
+
label: tx('Dialog defaults: prompt - close on backdrop click'),
|
|
943
1440
|
controlType: FieldControlType.TOGGLE,
|
|
944
1441
|
dataAttributes: { globalPath: 'dialog.defaults.prompt.closeOnBackdropClick' },
|
|
945
1442
|
},
|
|
946
|
-
{ name: safeName('dialog.defaults.prompt.disableClose'), label: 'Dialog
|
|
947
|
-
{ name: safeName('dialog.defaults.prompt.hasBackdrop'), label: 'Dialog
|
|
948
|
-
{ name: safeName('dialog.defaults.prompt.panelClass'), label: 'Dialog
|
|
949
|
-
{ name: safeName('dialog.defaults.prompt.styles'), label: 'Dialog
|
|
950
|
-
{ name: safeName('dialog.defaults.prompt.animation'), label: 'Dialog
|
|
951
|
-
// 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)
|
|
952
1449
|
// Each variant exposes commonly customized fields + JSON editors for actions/styles
|
|
953
1450
|
// danger
|
|
954
|
-
{ name: safeName('dialog.variants.danger.title'), label: 'Variant danger
|
|
955
|
-
{ name: safeName('dialog.variants.danger.icon'), label: 'Variant danger
|
|
956
|
-
{ name: safeName('dialog.variants.danger.message'), label: 'Variant danger
|
|
957
|
-
{ name: safeName('dialog.variants.danger.ariaRole'), label: 'Variant danger
|
|
958
|
-
{ name: safeName('dialog.variants.danger.closeOnBackdropClick'), label: 'Variant danger
|
|
959
|
-
{ name: safeName('dialog.variants.danger.panelClass'), label: 'Variant danger
|
|
960
|
-
{ name: safeName('dialog.variants.danger.actions'), label: 'Variant danger
|
|
961
|
-
{ name: safeName('dialog.variants.danger.styles'), label: 'Variant danger
|
|
962
|
-
{ 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 } },
|
|
963
1460
|
// info
|
|
964
|
-
{ name: safeName('dialog.variants.info.title'), label: 'Variant info
|
|
965
|
-
{ name: safeName('dialog.variants.info.icon'), label: 'Variant info
|
|
966
|
-
{ name: safeName('dialog.variants.info.message'), label: 'Variant info
|
|
967
|
-
{ name: safeName('dialog.variants.info.ariaRole'), label: 'Variant info
|
|
968
|
-
{ name: safeName('dialog.variants.info.closeOnBackdropClick'), label: 'Variant info
|
|
969
|
-
{ name: safeName('dialog.variants.info.panelClass'), label: 'Variant info
|
|
970
|
-
{ name: safeName('dialog.variants.info.actions'), label: 'Variant info
|
|
971
|
-
{ name: safeName('dialog.variants.info.styles'), label: 'Variant info
|
|
972
|
-
{ 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 } },
|
|
973
1470
|
// success
|
|
974
|
-
{ name: safeName('dialog.variants.success.title'), label: 'Variant success
|
|
975
|
-
{ name: safeName('dialog.variants.success.icon'), label: 'Variant success
|
|
976
|
-
{ name: safeName('dialog.variants.success.message'), label: 'Variant success
|
|
977
|
-
{ name: safeName('dialog.variants.success.ariaRole'), label: 'Variant success
|
|
978
|
-
{ name: safeName('dialog.variants.success.closeOnBackdropClick'), label: 'Variant success
|
|
979
|
-
{ name: safeName('dialog.variants.success.panelClass'), label: 'Variant success
|
|
980
|
-
{ name: safeName('dialog.variants.success.actions'), label: 'Variant success
|
|
981
|
-
{ name: safeName('dialog.variants.success.styles'), label: 'Variant success
|
|
982
|
-
{ 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 } },
|
|
983
1480
|
// question
|
|
984
|
-
{ name: safeName('dialog.variants.question.title'), label: 'Variant question
|
|
985
|
-
{ name: safeName('dialog.variants.question.icon'), label: 'Variant question
|
|
986
|
-
{ name: safeName('dialog.variants.question.message'), label: 'Variant question
|
|
987
|
-
{ name: safeName('dialog.variants.question.ariaRole'), label: 'Variant question
|
|
988
|
-
{ name: safeName('dialog.variants.question.closeOnBackdropClick'), label: 'Variant question
|
|
989
|
-
{ name: safeName('dialog.variants.question.panelClass'), label: 'Variant question
|
|
990
|
-
{ name: safeName('dialog.variants.question.actions'), label: 'Variant question
|
|
991
|
-
{ name: safeName('dialog.variants.question.styles'), label: 'Variant question
|
|
992
|
-
{ 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 } },
|
|
993
1490
|
// error
|
|
994
|
-
{ name: safeName('dialog.variants.error.title'), label: 'Variant error
|
|
995
|
-
{ name: safeName('dialog.variants.error.icon'), label: 'Variant error
|
|
996
|
-
{ name: safeName('dialog.variants.error.message'), label: 'Variant error
|
|
997
|
-
{ name: safeName('dialog.variants.error.ariaRole'), label: 'Variant error
|
|
998
|
-
{ name: safeName('dialog.variants.error.closeOnBackdropClick'), label: 'Variant error
|
|
999
|
-
{ name: safeName('dialog.variants.error.panelClass'), label: 'Variant error
|
|
1000
|
-
{ name: safeName('dialog.variants.error.actions'), label: 'Variant error
|
|
1001
|
-
{ name: safeName('dialog.variants.error.styles'), label: 'Variant error
|
|
1002
|
-
{ 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 } },
|
|
1003
1500
|
];
|
|
1004
1501
|
const cfg = {
|
|
1005
1502
|
sections: [
|
|
1006
1503
|
{
|
|
1007
1504
|
id: 'crud',
|
|
1008
|
-
title: 'CRUD',
|
|
1505
|
+
title: tx('CRUD'),
|
|
1009
1506
|
rows: [
|
|
1010
1507
|
{
|
|
1011
1508
|
id: 'crud-row-1',
|
|
@@ -1032,7 +1529,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1032
1529
|
},
|
|
1033
1530
|
{
|
|
1034
1531
|
id: 'dynamic-fields',
|
|
1035
|
-
title: 'Dynamic Fields',
|
|
1532
|
+
title: tx('Dynamic Fields'),
|
|
1036
1533
|
rows: [
|
|
1037
1534
|
{
|
|
1038
1535
|
id: 'df-row-1',
|
|
@@ -1053,7 +1550,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1053
1550
|
},
|
|
1054
1551
|
{
|
|
1055
1552
|
id: 'ai-credentials',
|
|
1056
|
-
title: '
|
|
1553
|
+
title: tx('Credentials'), // Internal title, UI might override
|
|
1057
1554
|
rows: [
|
|
1058
1555
|
{
|
|
1059
1556
|
id: 'ai-cred-row-1',
|
|
@@ -1066,7 +1563,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1066
1563
|
},
|
|
1067
1564
|
{
|
|
1068
1565
|
id: 'ai-model',
|
|
1069
|
-
title: '
|
|
1566
|
+
title: tx('Model & Behavior'),
|
|
1070
1567
|
rows: [
|
|
1071
1568
|
{
|
|
1072
1569
|
id: 'ai-mod-row-1',
|
|
@@ -1079,7 +1576,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1079
1576
|
},
|
|
1080
1577
|
{
|
|
1081
1578
|
id: 'ai-embedding',
|
|
1082
|
-
title: 'Embeddings',
|
|
1579
|
+
title: tx('Embeddings (RAG)'),
|
|
1083
1580
|
rows: [
|
|
1084
1581
|
{
|
|
1085
1582
|
id: 'ai-embed-row-1',
|
|
@@ -1093,7 +1590,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1093
1590
|
},
|
|
1094
1591
|
{
|
|
1095
1592
|
id: 'cache',
|
|
1096
|
-
title: 'Cache & Persistência',
|
|
1593
|
+
title: tx('Cache & Persistência'),
|
|
1097
1594
|
rows: [
|
|
1098
1595
|
{
|
|
1099
1596
|
id: 'cache-row-1',
|
|
@@ -1105,7 +1602,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1105
1602
|
},
|
|
1106
1603
|
{
|
|
1107
1604
|
id: 'table',
|
|
1108
|
-
title: 'Tabela',
|
|
1605
|
+
title: tx('Tabela'),
|
|
1109
1606
|
rows: [
|
|
1110
1607
|
{
|
|
1111
1608
|
id: 'tbl-row-1',
|
|
@@ -1166,7 +1663,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1166
1663
|
},
|
|
1167
1664
|
{
|
|
1168
1665
|
id: 'dialog',
|
|
1169
|
-
title: 'Dialog',
|
|
1666
|
+
title: tx('Dialog'),
|
|
1170
1667
|
rows: [
|
|
1171
1668
|
{
|
|
1172
1669
|
id: 'dlg-row-defaults',
|
|
@@ -1291,9 +1788,9 @@ function buildGlobalConfigFormConfig() {
|
|
|
1291
1788
|
actions: {
|
|
1292
1789
|
placement: 'afterSections',
|
|
1293
1790
|
// Hide internal form actions; Settings Panel footer handles Apply/Save
|
|
1294
|
-
submit: { visible: false, label: 'Salvar' },
|
|
1295
|
-
cancel: { visible: false, label: 'Cancelar' },
|
|
1296
|
-
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' },
|
|
1297
1794
|
},
|
|
1298
1795
|
fieldMetadata: fields,
|
|
1299
1796
|
};
|
|
@@ -1319,10 +1816,10 @@ const TABLE_COMPACT_FONT_SIZE_PATHS = new Set([
|
|
|
1319
1816
|
'table.appearance.typography.headerFontSize',
|
|
1320
1817
|
]);
|
|
1321
1818
|
const TABLE_COMPACT_FIELD_LABELS = {
|
|
1322
|
-
'table.appearance.spacing.cellPadding': 'padding
|
|
1323
|
-
'table.appearance.spacing.headerPadding': 'padding
|
|
1324
|
-
'table.appearance.typography.fontSize': '
|
|
1325
|
-
'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',
|
|
1326
1823
|
};
|
|
1327
1824
|
const TABLE_COMPACT_LENGTH_TOKEN = '(?:0|(?:\\d+|\\d*\\.\\d+)(?:px|rem|em|%|vh|vw|svh|svw|lvh|lvw|dvh|dvw|ch|ex))';
|
|
1328
1825
|
const TABLE_COMPACT_SPACING_REGEX = new RegExp(`^(?:var\\(.+\\)|calc\\(.+\\)|${TABLE_COMPACT_LENGTH_TOKEN}(?:\\s+${TABLE_COMPACT_LENGTH_TOKEN}){0,3})$`, 'i');
|
|
@@ -1349,6 +1846,7 @@ class GlobalConfigEditorComponent {
|
|
|
1349
1846
|
hostAiModel;
|
|
1350
1847
|
hostAiEmbedding;
|
|
1351
1848
|
destroyRef = inject(DestroyRef);
|
|
1849
|
+
i18n = inject(PraxisI18nService);
|
|
1352
1850
|
iconPicker = inject(IconPickerService);
|
|
1353
1851
|
aiApi = inject(AiBackendApiService);
|
|
1354
1852
|
cdr = inject(ChangeDetectorRef);
|
|
@@ -1382,7 +1880,7 @@ class GlobalConfigEditorComponent {
|
|
|
1382
1880
|
apiKeyLast4 = null;
|
|
1383
1881
|
hasStoredApiKey = false;
|
|
1384
1882
|
hasStoredGlobalConfig = false;
|
|
1385
|
-
configSourceLabel = '
|
|
1883
|
+
configSourceLabel = this.tx('Server defaults (env vars)');
|
|
1386
1884
|
// UX: API Key monitoring
|
|
1387
1885
|
apiKeyChanged$ = new Subject();
|
|
1388
1886
|
hasApiKey = false;
|
|
@@ -1394,12 +1892,12 @@ class GlobalConfigEditorComponent {
|
|
|
1394
1892
|
get apiKeyStatusLabel() {
|
|
1395
1893
|
const apiKey = this.currentValues?.[this.safeName('ai.apiKey')] || '';
|
|
1396
1894
|
if (apiKey)
|
|
1397
|
-
return '
|
|
1895
|
+
return this.tx('Key provided');
|
|
1398
1896
|
if (this.apiKeyLast4)
|
|
1399
|
-
return
|
|
1897
|
+
return this.tx('Saved key (****{{last4}})', { last4: this.apiKeyLast4 });
|
|
1400
1898
|
if (this.hasStoredApiKey)
|
|
1401
|
-
return '
|
|
1402
|
-
return '
|
|
1899
|
+
return this.tx('Saved key');
|
|
1900
|
+
return this.tx('No saved key');
|
|
1403
1901
|
}
|
|
1404
1902
|
constructor(admin, snack) {
|
|
1405
1903
|
this.admin = admin;
|
|
@@ -1408,7 +1906,7 @@ class GlobalConfigEditorComponent {
|
|
|
1408
1906
|
async ngOnInit() {
|
|
1409
1907
|
const cfg = this.admin.getEffectiveConfig();
|
|
1410
1908
|
const flat = this.flatten(cfg);
|
|
1411
|
-
this.formConfig = buildGlobalConfigFormConfig();
|
|
1909
|
+
this.formConfig = buildGlobalConfigFormConfig(this.tx.bind(this));
|
|
1412
1910
|
this.applyConfigSnapshot(flat, { resetForms: false });
|
|
1413
1911
|
await this.loadProviderCatalog();
|
|
1414
1912
|
this.applyProviderOptions();
|
|
@@ -1553,7 +2051,7 @@ class GlobalConfigEditorComponent {
|
|
|
1553
2051
|
const ref = g.host.createComponent(this.dynamicFormCtor);
|
|
1554
2052
|
ref.setInput('config', g.cfg);
|
|
1555
2053
|
ref.setInput('mode', 'edit');
|
|
1556
|
-
// 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
|
|
1557
2055
|
ref.setInput('enableCustomization', false);
|
|
1558
2056
|
const inst = ref.instance;
|
|
1559
2057
|
// FORÇAR estado de sucesso para renderizar o formulário sem resourcePath
|
|
@@ -1626,7 +2124,7 @@ class GlobalConfigEditorComponent {
|
|
|
1626
2124
|
{
|
|
1627
2125
|
id: 'gemini',
|
|
1628
2126
|
label: 'Google Gemini',
|
|
1629
|
-
description: '
|
|
2127
|
+
description: this.tx('Fast multimodal models from Google.'),
|
|
1630
2128
|
defaultModel: 'gemini-2.0-flash',
|
|
1631
2129
|
requiresApiKey: true,
|
|
1632
2130
|
supportsModels: true,
|
|
@@ -1636,7 +2134,7 @@ class GlobalConfigEditorComponent {
|
|
|
1636
2134
|
{
|
|
1637
2135
|
id: 'openai',
|
|
1638
2136
|
label: 'OpenAI',
|
|
1639
|
-
description: '
|
|
2137
|
+
description: this.tx('GPT models for text and chat.'),
|
|
1640
2138
|
defaultModel: 'gpt-4o-mini',
|
|
1641
2139
|
requiresApiKey: true,
|
|
1642
2140
|
supportsModels: true,
|
|
@@ -1646,7 +2144,7 @@ class GlobalConfigEditorComponent {
|
|
|
1646
2144
|
{
|
|
1647
2145
|
id: 'xai',
|
|
1648
2146
|
label: 'xAI (Grok)',
|
|
1649
|
-
description: '
|
|
2147
|
+
description: this.tx('Grok models focused on reasoning.'),
|
|
1650
2148
|
defaultModel: 'grok-2-latest',
|
|
1651
2149
|
requiresApiKey: true,
|
|
1652
2150
|
supportsModels: true,
|
|
@@ -1656,7 +2154,7 @@ class GlobalConfigEditorComponent {
|
|
|
1656
2154
|
{
|
|
1657
2155
|
id: 'mock',
|
|
1658
2156
|
label: 'Mock (dev)',
|
|
1659
|
-
description: '
|
|
2157
|
+
description: this.tx('Local mode for tests without a key.'),
|
|
1660
2158
|
defaultModel: 'mock-default',
|
|
1661
2159
|
requiresApiKey: false,
|
|
1662
2160
|
supportsModels: true,
|
|
@@ -1845,8 +2343,8 @@ class GlobalConfigEditorComponent {
|
|
|
1845
2343
|
this.hasStoredGlobalConfig = false;
|
|
1846
2344
|
}
|
|
1847
2345
|
this.configSourceLabel = this.hasStoredGlobalConfig
|
|
1848
|
-
? '
|
|
1849
|
-
: '
|
|
2346
|
+
? this.tx('Saved configuration (UI) - overrides server defaults')
|
|
2347
|
+
: this.tx('Server defaults (env vars)');
|
|
1850
2348
|
}
|
|
1851
2349
|
async clearStoredConfig() {
|
|
1852
2350
|
if (this.isClearingGlobalConfig)
|
|
@@ -1861,13 +2359,13 @@ class GlobalConfigEditorComponent {
|
|
|
1861
2359
|
this.refreshAiStateAfterConfig();
|
|
1862
2360
|
await this.refreshStoredConfigState();
|
|
1863
2361
|
try {
|
|
1864
|
-
this.snack.open('
|
|
2362
|
+
this.snack.open(this.tx('Global config cleared. Using server defaults.'), undefined, { duration: 2500 });
|
|
1865
2363
|
}
|
|
1866
2364
|
catch { }
|
|
1867
2365
|
}
|
|
1868
2366
|
catch (err) {
|
|
1869
2367
|
try {
|
|
1870
|
-
this.snack.open('
|
|
2368
|
+
this.snack.open(this.tx('Failed to clear global config.'), undefined, { duration: 4000 });
|
|
1871
2369
|
}
|
|
1872
2370
|
catch { }
|
|
1873
2371
|
}
|
|
@@ -1994,10 +2492,10 @@ class GlobalConfigEditorComponent {
|
|
|
1994
2492
|
const model = this.availableModels.find(m => m.name.endsWith(modelName));
|
|
1995
2493
|
if (model) {
|
|
1996
2494
|
const formatLimit = (n) => n ? (n >= 1000 ? (n / 1000).toFixed(0) + 'k' : n) : 'N/A';
|
|
1997
|
-
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' });
|
|
1998
2496
|
}
|
|
1999
2497
|
else {
|
|
2000
|
-
this.selectedModelDetails = '
|
|
2498
|
+
this.selectedModelDetails = this.tx('No model details available.');
|
|
2001
2499
|
}
|
|
2002
2500
|
}
|
|
2003
2501
|
// SettingsPanel expects these methods
|
|
@@ -2033,7 +2531,7 @@ class GlobalConfigEditorComponent {
|
|
|
2033
2531
|
this.initialValues = { ...this.currentValues };
|
|
2034
2532
|
this.isDirty$.next(false);
|
|
2035
2533
|
try {
|
|
2036
|
-
this.snack.open('
|
|
2534
|
+
this.snack.open(this.tx('Settings saved'), undefined, { duration: 2000 });
|
|
2037
2535
|
}
|
|
2038
2536
|
catch { }
|
|
2039
2537
|
return partial;
|
|
@@ -2056,7 +2554,7 @@ class GlobalConfigEditorComponent {
|
|
|
2056
2554
|
const meta = this.findProvider(provider);
|
|
2057
2555
|
if (meta?.supportsModels === false) {
|
|
2058
2556
|
if (!silent) {
|
|
2059
|
-
this.aiTestResult = { success: false, message: '
|
|
2557
|
+
this.aiTestResult = { success: false, message: this.tx('This provider has no model catalog.') };
|
|
2060
2558
|
this.cdr.detectChanges();
|
|
2061
2559
|
}
|
|
2062
2560
|
return;
|
|
@@ -2064,7 +2562,7 @@ class GlobalConfigEditorComponent {
|
|
|
2064
2562
|
const requiresKey = meta?.requiresApiKey !== false;
|
|
2065
2563
|
const hasKey = !!apiKey || this.hasStoredApiKey || !requiresKey;
|
|
2066
2564
|
if (requiresKey && !hasKey) {
|
|
2067
|
-
this.aiTestResult = { success: false, message: '
|
|
2565
|
+
this.aiTestResult = { success: false, message: this.tx('Enter an API key to fetch models.') };
|
|
2068
2566
|
this.cdr.detectChanges();
|
|
2069
2567
|
return;
|
|
2070
2568
|
}
|
|
@@ -2079,8 +2577,7 @@ class GlobalConfigEditorComponent {
|
|
|
2079
2577
|
request.apiKey = apiKey;
|
|
2080
2578
|
const response = await firstValueFrom(this.aiApi.listModels(request));
|
|
2081
2579
|
if (!response?.success) {
|
|
2082
|
-
|
|
2083
|
-
throw new Error(msg);
|
|
2580
|
+
throw new Error(this.tx('Error fetching models.'));
|
|
2084
2581
|
}
|
|
2085
2582
|
const models = response.models || [];
|
|
2086
2583
|
this.availableModels = models; // Store available models
|
|
@@ -2101,9 +2598,9 @@ class GlobalConfigEditorComponent {
|
|
|
2101
2598
|
}
|
|
2102
2599
|
catch (error) {
|
|
2103
2600
|
this.logger.error('[GlobalConfigEditor] Error fetching models', this.buildLogOptions({ error, provider }, { context: { actionId: 'models.fetch' } }));
|
|
2104
|
-
this.aiTestResult = { success: false, message:
|
|
2601
|
+
this.aiTestResult = { success: false, message: this.tx('Error fetching models.') };
|
|
2105
2602
|
if (!silent) {
|
|
2106
|
-
this.snack.open('
|
|
2603
|
+
this.snack.open(this.tx('Error fetching models. Check your API key.'), this.tx('Close'), { duration: 5000 });
|
|
2107
2604
|
}
|
|
2108
2605
|
}
|
|
2109
2606
|
finally {
|
|
@@ -2133,7 +2630,7 @@ class GlobalConfigEditorComponent {
|
|
|
2133
2630
|
this.recreateAiModelForm();
|
|
2134
2631
|
if (!silent) {
|
|
2135
2632
|
try {
|
|
2136
|
-
this.snack.open(
|
|
2633
|
+
this.snack.open(this.tx('Model list updated ({{count}} models)', { count: modelOptions.length }), undefined, { duration: 3000 });
|
|
2137
2634
|
}
|
|
2138
2635
|
catch { }
|
|
2139
2636
|
}
|
|
@@ -2151,7 +2648,7 @@ class GlobalConfigEditorComponent {
|
|
|
2151
2648
|
const requiresKey = meta?.requiresApiKey !== false;
|
|
2152
2649
|
const hasKey = !!apiKey || this.hasStoredApiKey || !requiresKey;
|
|
2153
2650
|
if (requiresKey && !hasKey) {
|
|
2154
|
-
this.aiTestResult = { success: false, message: '
|
|
2651
|
+
this.aiTestResult = { success: false, message: this.tx('Enter an API key to test.') };
|
|
2155
2652
|
this.isTestingAi = false;
|
|
2156
2653
|
this.cdr.detectChanges();
|
|
2157
2654
|
return;
|
|
@@ -2162,17 +2659,16 @@ class GlobalConfigEditorComponent {
|
|
|
2162
2659
|
request.apiKey = apiKey;
|
|
2163
2660
|
const response = await firstValueFrom(this.aiApi.testProvider(request));
|
|
2164
2661
|
if (!response?.success) {
|
|
2165
|
-
throw new Error(
|
|
2662
|
+
throw new Error(this.tx('Failed to test connection.'));
|
|
2166
2663
|
}
|
|
2167
|
-
this.aiTestResult = { success: true, message:
|
|
2664
|
+
this.aiTestResult = { success: true, message: this.tx('Connection established successfully!') };
|
|
2168
2665
|
this.hasApiKey = true; // Garantir desbloqueio da seção de modelo após sucesso
|
|
2169
2666
|
// Após validar a chave, já buscar a lista de modelos para preencher o select
|
|
2170
2667
|
await this.refreshModels(true);
|
|
2171
2668
|
}
|
|
2172
2669
|
catch (err) {
|
|
2173
2670
|
this.logger.error('[GlobalConfigEditor] AI Connection Test Error', this.buildLogOptions({ error: err, provider, model: selectedModel }, { context: { actionId: 'provider.test-connection' } }));
|
|
2174
|
-
|
|
2175
|
-
this.aiTestResult = { success: false, message: msg };
|
|
2671
|
+
this.aiTestResult = { success: false, message: this.tx('Failed to test connection.') };
|
|
2176
2672
|
}
|
|
2177
2673
|
finally {
|
|
2178
2674
|
this.isTestingAi = false;
|
|
@@ -2193,6 +2689,10 @@ class GlobalConfigEditorComponent {
|
|
|
2193
2689
|
safeName(path) {
|
|
2194
2690
|
return path.replace(/[^a-zA-Z0-9_]/g, '_');
|
|
2195
2691
|
}
|
|
2692
|
+
tx(text, params) {
|
|
2693
|
+
const normalized = normalizeMojibakeText(text);
|
|
2694
|
+
return this.i18n.t(normalized, params, normalized, PRAXIS_SETTINGS_PANEL_I18N_NAMESPACE);
|
|
2695
|
+
}
|
|
2196
2696
|
buildChangedValues() {
|
|
2197
2697
|
const out = {};
|
|
2198
2698
|
for (const [safe, value] of Object.entries(this.currentValues)) {
|
|
@@ -2217,21 +2717,7 @@ class GlobalConfigEditorComponent {
|
|
|
2217
2717
|
return initial !== current;
|
|
2218
2718
|
}
|
|
2219
2719
|
resolveSaveErrorMessage(err) {
|
|
2220
|
-
|
|
2221
|
-
const details = err?.error?.details;
|
|
2222
|
-
if (apiMessage && apiMessage.trim()) {
|
|
2223
|
-
return apiMessage;
|
|
2224
|
-
}
|
|
2225
|
-
if (details && typeof details === 'object') {
|
|
2226
|
-
const first = Object.values(details).find((v) => typeof v === 'string' && v.trim());
|
|
2227
|
-
if (typeof first === 'string') {
|
|
2228
|
-
return first;
|
|
2229
|
-
}
|
|
2230
|
-
}
|
|
2231
|
-
if (typeof err?.message === 'string' && err.message.trim()) {
|
|
2232
|
-
return err.message;
|
|
2233
|
-
}
|
|
2234
|
-
return 'Falha ao salvar configurações.';
|
|
2720
|
+
return this.tx('Save failed.');
|
|
2235
2721
|
}
|
|
2236
2722
|
normalizeFieldValue(path, value) {
|
|
2237
2723
|
if (typeof value !== 'string')
|
|
@@ -2278,7 +2764,7 @@ class GlobalConfigEditorComponent {
|
|
|
2278
2764
|
if (!normalized)
|
|
2279
2765
|
continue;
|
|
2280
2766
|
if (!check.regex.test(normalized)) {
|
|
2281
|
-
return `
|
|
2767
|
+
return `Invalid value in ${TABLE_COMPACT_FIELD_LABELS[check.path]}. Use a simple CSS string, such as ${check.example}.`;
|
|
2282
2768
|
}
|
|
2283
2769
|
}
|
|
2284
2770
|
return null;
|
|
@@ -2388,9 +2874,9 @@ class GlobalConfigEditorComponent {
|
|
|
2388
2874
|
<mat-expansion-panel-header>
|
|
2389
2875
|
<mat-panel-title>
|
|
2390
2876
|
<mat-icon class="panel-icon">construction</mat-icon>
|
|
2391
|
-
CRUD
|
|
2877
|
+
{{ tx('CRUD') }}
|
|
2392
2878
|
</mat-panel-title>
|
|
2393
|
-
<mat-panel-description>
|
|
2879
|
+
<mat-panel-description>{{ tx('Global policies for opening, back and header') }}</mat-panel-description>
|
|
2394
2880
|
</mat-expansion-panel-header>
|
|
2395
2881
|
<ng-template #hostCrud></ng-template>
|
|
2396
2882
|
</mat-expansion-panel>
|
|
@@ -2398,9 +2884,9 @@ class GlobalConfigEditorComponent {
|
|
|
2398
2884
|
<mat-expansion-panel-header>
|
|
2399
2885
|
<mat-panel-title>
|
|
2400
2886
|
<mat-icon class="panel-icon">dynamic_form</mat-icon>
|
|
2401
|
-
Dynamic Fields
|
|
2887
|
+
{{ tx('Dynamic Fields') }}
|
|
2402
2888
|
</mat-panel-title>
|
|
2403
|
-
<mat-panel-description>Async Select,
|
|
2889
|
+
<mat-panel-description>{{ tx('Async Select, cascade and pagination') }}</mat-panel-description>
|
|
2404
2890
|
</mat-expansion-panel-header>
|
|
2405
2891
|
<ng-template #hostFields></ng-template>
|
|
2406
2892
|
</mat-expansion-panel>
|
|
@@ -2408,9 +2894,9 @@ class GlobalConfigEditorComponent {
|
|
|
2408
2894
|
<mat-expansion-panel-header>
|
|
2409
2895
|
<mat-panel-title>
|
|
2410
2896
|
<mat-icon class="panel-icon">cached</mat-icon>
|
|
2411
|
-
Cache &
|
|
2897
|
+
{{ tx('Cache & Persistence') }}
|
|
2412
2898
|
</mat-panel-title>
|
|
2413
|
-
<mat-panel-description>
|
|
2899
|
+
<mat-panel-description>{{ tx('Schema cache strategy (local vs server)') }}</mat-panel-description>
|
|
2414
2900
|
</mat-expansion-panel-header>
|
|
2415
2901
|
<ng-template #hostCache></ng-template>
|
|
2416
2902
|
</mat-expansion-panel>
|
|
@@ -2418,9 +2904,9 @@ class GlobalConfigEditorComponent {
|
|
|
2418
2904
|
<mat-expansion-panel-header>
|
|
2419
2905
|
<mat-panel-title>
|
|
2420
2906
|
<mat-icon class="panel-icon">psychology</mat-icon>
|
|
2421
|
-
|
|
2907
|
+
{{ tx('Artificial Intelligence') }}
|
|
2422
2908
|
</mat-panel-title>
|
|
2423
|
-
<mat-panel-description>
|
|
2909
|
+
<mat-panel-description>{{ tx('LLM integration') }}</mat-panel-description>
|
|
2424
2910
|
</mat-expansion-panel-header>
|
|
2425
2911
|
|
|
2426
2912
|
<div class="ai-config-container">
|
|
@@ -2429,23 +2915,23 @@ class GlobalConfigEditorComponent {
|
|
|
2429
2915
|
<mat-icon>settings_suggest</mat-icon>
|
|
2430
2916
|
<span>{{ configSourceLabel }}</span>
|
|
2431
2917
|
</div>
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
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')"
|
|
2441
2927
|
>
|
|
2442
2928
|
<ng-container *ngIf="isClearingGlobalConfig; else clearContent">
|
|
2443
2929
|
<mat-spinner diameter="16" class="btn-spinner"></mat-spinner>
|
|
2444
|
-
<span class="ai-action-label">
|
|
2930
|
+
<span class="ai-action-label">{{ tx('Clearing...') }}</span>
|
|
2445
2931
|
</ng-container>
|
|
2446
2932
|
<ng-template #clearContent>
|
|
2447
2933
|
<mat-icon>delete_sweep</mat-icon>
|
|
2448
|
-
<span class="ai-action-label">
|
|
2934
|
+
<span class="ai-action-label">{{ tx('Clear saved config') }}</span>
|
|
2449
2935
|
</ng-template>
|
|
2450
2936
|
</button>
|
|
2451
2937
|
</div>
|
|
@@ -2453,7 +2939,7 @@ class GlobalConfigEditorComponent {
|
|
|
2453
2939
|
<div class="ai-group">
|
|
2454
2940
|
<div class="ai-group-header">
|
|
2455
2941
|
<div class="ai-group-title">
|
|
2456
|
-
<mat-icon>vpn_key</mat-icon>
|
|
2942
|
+
<mat-icon>vpn_key</mat-icon> {{ tx('Credentials') }}
|
|
2457
2943
|
</div>
|
|
2458
2944
|
<button mat-stroked-button
|
|
2459
2945
|
type="button"
|
|
@@ -2462,15 +2948,15 @@ class GlobalConfigEditorComponent {
|
|
|
2462
2948
|
[attr.aria-busy]="isTestingAi ? 'true' : null"
|
|
2463
2949
|
(click)="testAiConnection()"
|
|
2464
2950
|
[disabled]="isTestingAi || !hasApiKey"
|
|
2465
|
-
matTooltip="
|
|
2951
|
+
[matTooltip]="tx('Test connection with the provided key')">
|
|
2466
2952
|
<ng-container *ngIf="isTestingAi; else btnContent">
|
|
2467
2953
|
<mat-spinner diameter="16" class="btn-spinner"></mat-spinner>
|
|
2468
|
-
<span class="ai-action-label">
|
|
2954
|
+
<span class="ai-action-label">{{ tx('Connecting...') }}</span>
|
|
2469
2955
|
</ng-container>
|
|
2470
2956
|
<ng-template #btnContent>
|
|
2471
2957
|
<mat-icon>{{ aiTestResult?.success ? 'check' : 'bolt' }}</mat-icon>
|
|
2472
2958
|
<span class="ai-action-label">
|
|
2473
|
-
{{ aiTestResult?.success ? '
|
|
2959
|
+
{{ aiTestResult?.success ? tx('Connected') : tx('Test connection') }}
|
|
2474
2960
|
</span>
|
|
2475
2961
|
</ng-template>
|
|
2476
2962
|
</button>
|
|
@@ -2512,7 +2998,7 @@ class GlobalConfigEditorComponent {
|
|
|
2512
2998
|
</div>
|
|
2513
2999
|
<div class="ai-provider-key is-unlocked" *ngIf="selectedProvider?.requiresApiKey === false">
|
|
2514
3000
|
<mat-icon>check_circle</mat-icon>
|
|
2515
|
-
<span>
|
|
3001
|
+
<span>{{ tx('No key required') }}</span>
|
|
2516
3002
|
</div>
|
|
2517
3003
|
</div>
|
|
2518
3004
|
<div class="ai-credentials-row">
|
|
@@ -2532,12 +3018,12 @@ class GlobalConfigEditorComponent {
|
|
|
2532
3018
|
<div class="ai-group" [class.disabled-group]="!hasApiKey">
|
|
2533
3019
|
<div class="ai-group-header">
|
|
2534
3020
|
<div class="ai-group-title">
|
|
2535
|
-
<mat-icon>smart_toy</mat-icon>
|
|
3021
|
+
<mat-icon>smart_toy</mat-icon> {{ tx('Model & Behavior') }}
|
|
2536
3022
|
</div>
|
|
2537
3023
|
<div class="ai-header-actions">
|
|
2538
|
-
<span class="ai-subtext" *ngIf="hasApiKey">
|
|
2539
|
-
<mat-chip-option *ngIf="!hasApiKey" disabled>
|
|
2540
|
-
<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')">
|
|
2541
3027
|
<mat-icon [class.spin]="isRefetchingModels">sync</mat-icon>
|
|
2542
3028
|
</button>
|
|
2543
3029
|
</div>
|
|
@@ -2556,7 +3042,7 @@ class GlobalConfigEditorComponent {
|
|
|
2556
3042
|
|
|
2557
3043
|
<div class="ai-placeholder" *ngIf="!hasApiKey">
|
|
2558
3044
|
<mat-icon>lock</mat-icon>
|
|
2559
|
-
<span>Configure
|
|
3045
|
+
<span>{{ tx('Configure and test your API key to unlock model selection.') }}</span>
|
|
2560
3046
|
</div>
|
|
2561
3047
|
</div>
|
|
2562
3048
|
|
|
@@ -2564,7 +3050,7 @@ class GlobalConfigEditorComponent {
|
|
|
2564
3050
|
<div class="ai-group">
|
|
2565
3051
|
<div class="ai-group-header">
|
|
2566
3052
|
<div class="ai-group-title">
|
|
2567
|
-
<mat-icon>scatter_plot</mat-icon> Embeddings (RAG)
|
|
3053
|
+
<mat-icon>scatter_plot</mat-icon> {{ tx('Embeddings (RAG)') }}
|
|
2568
3054
|
</div>
|
|
2569
3055
|
<div class="ai-header-actions">
|
|
2570
3056
|
<button
|
|
@@ -2573,19 +3059,19 @@ class GlobalConfigEditorComponent {
|
|
|
2573
3059
|
class="ai-action-btn"
|
|
2574
3060
|
(click)="useLlmForEmbeddings()"
|
|
2575
3061
|
[disabled]="!canUseLlmForEmbeddings"
|
|
2576
|
-
matTooltip="
|
|
3062
|
+
[matTooltip]="tx('Use the LLM provider and key for embeddings')"
|
|
2577
3063
|
>
|
|
2578
3064
|
<mat-icon>merge_type</mat-icon>
|
|
2579
|
-
<span class="ai-action-label">
|
|
3065
|
+
<span class="ai-action-label">{{ tx('Use the LLM provider and key for embeddings') }}</span>
|
|
2580
3066
|
</button>
|
|
2581
|
-
<mat-chip-option *ngIf="!canUseLlmForEmbeddings" disabled>
|
|
3067
|
+
<mat-chip-option *ngIf="!canUseLlmForEmbeddings" disabled>{{ tx('Provider has no embeddings') }}</mat-chip-option>
|
|
2582
3068
|
</div>
|
|
2583
3069
|
</div>
|
|
2584
3070
|
<div class="ai-subtext">
|
|
2585
|
-
Configure
|
|
3071
|
+
{{ tx('Configure the embeddings provider for vector search (templates and schemas).') }}
|
|
2586
3072
|
</div>
|
|
2587
3073
|
<div class="ai-subtext" *ngIf="embeddingUseSameAsLlm">
|
|
2588
|
-
|
|
3074
|
+
{{ tx('Synchronized with the LLM. The fields below follow the primary credential.') }}
|
|
2589
3075
|
</div>
|
|
2590
3076
|
<div class="ai-embedding-row">
|
|
2591
3077
|
<ng-template #hostAiEmbedding></ng-template>
|
|
@@ -2593,7 +3079,7 @@ class GlobalConfigEditorComponent {
|
|
|
2593
3079
|
<div class="ai-feedback ai-feedback--warn" *ngIf="embeddingDimensionMismatch">
|
|
2594
3080
|
<mat-icon>warning</mat-icon>
|
|
2595
3081
|
<span class="error-text">
|
|
2596
|
-
|
|
3082
|
+
{{ tx('Embedding dimension mismatch with database (768). Adjust to 768 or redo the migration.') }}
|
|
2597
3083
|
</span>
|
|
2598
3084
|
</div>
|
|
2599
3085
|
</div>
|
|
@@ -2604,9 +3090,9 @@ class GlobalConfigEditorComponent {
|
|
|
2604
3090
|
<mat-expansion-panel-header>
|
|
2605
3091
|
<mat-panel-title>
|
|
2606
3092
|
<mat-icon class="panel-icon">table_chart</mat-icon>
|
|
2607
|
-
|
|
3093
|
+
{{ tx('Table') }}
|
|
2608
3094
|
</mat-panel-title>
|
|
2609
|
-
<mat-panel-description>Toolbar,
|
|
3095
|
+
<mat-panel-description>{{ tx('Toolbar, appearance and advanced filter') }}</mat-panel-description>
|
|
2610
3096
|
</mat-expansion-panel-header>
|
|
2611
3097
|
<ng-template #hostTable></ng-template>
|
|
2612
3098
|
</mat-expansion-panel>
|
|
@@ -2614,27 +3100,27 @@ class GlobalConfigEditorComponent {
|
|
|
2614
3100
|
<mat-expansion-panel-header>
|
|
2615
3101
|
<mat-panel-title>
|
|
2616
3102
|
<mat-icon class="panel-icon">forum</mat-icon>
|
|
2617
|
-
Dialog
|
|
3103
|
+
{{ tx('Dialog') }}
|
|
2618
3104
|
</mat-panel-title>
|
|
2619
|
-
<mat-panel-description>Defaults
|
|
3105
|
+
<mat-panel-description>{{ tx('Defaults and variants (danger, info, success, question, error)') }}</mat-panel-description>
|
|
2620
3106
|
</mat-expansion-panel-header>
|
|
2621
3107
|
<ng-template #hostDialog></ng-template>
|
|
2622
3108
|
<!-- Icon UX helpers for Dialog variants -->
|
|
2623
3109
|
<div class="dlg-icon-helpers">
|
|
2624
|
-
<div class="dlg-icon-helpers__head"
|
|
3110
|
+
<div class="dlg-icon-helpers__head">{{ tx('Icons by profile (shortcuts)') }}</div>
|
|
2625
3111
|
<div class="dlg-icon-helpers__row" *ngFor="let k of dialogVariantKeys">
|
|
2626
3112
|
<div class="dlg-icon-helpers__label">{{ k }}</div>
|
|
2627
3113
|
<mat-icon aria-hidden="true" [praxisIcon]="getVariantIcon(k) || 'mi:help_outline'" class="dlg-icon-helpers__preview"></mat-icon>
|
|
2628
|
-
<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 })">
|
|
2629
3115
|
<mat-icon>search</mat-icon>
|
|
2630
|
-
|
|
3116
|
+
{{ tx('Pick icon') }}
|
|
2631
3117
|
</button>
|
|
2632
|
-
<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')">
|
|
2633
3119
|
<mat-icon>backspace</mat-icon>
|
|
2634
3120
|
</button>
|
|
2635
3121
|
<span class="dlg-icon-helpers__value" *ngIf="getVariantIcon(k)">{{ getVariantIcon(k) }}</span>
|
|
2636
3122
|
</div>
|
|
2637
|
-
<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>
|
|
2638
3124
|
</div>
|
|
2639
3125
|
</mat-expansion-panel>
|
|
2640
3126
|
</mat-accordion>
|
|
@@ -2648,9 +3134,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2648
3134
|
<mat-expansion-panel-header>
|
|
2649
3135
|
<mat-panel-title>
|
|
2650
3136
|
<mat-icon class="panel-icon">construction</mat-icon>
|
|
2651
|
-
CRUD
|
|
3137
|
+
{{ tx('CRUD') }}
|
|
2652
3138
|
</mat-panel-title>
|
|
2653
|
-
<mat-panel-description>
|
|
3139
|
+
<mat-panel-description>{{ tx('Global policies for opening, back and header') }}</mat-panel-description>
|
|
2654
3140
|
</mat-expansion-panel-header>
|
|
2655
3141
|
<ng-template #hostCrud></ng-template>
|
|
2656
3142
|
</mat-expansion-panel>
|
|
@@ -2658,9 +3144,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2658
3144
|
<mat-expansion-panel-header>
|
|
2659
3145
|
<mat-panel-title>
|
|
2660
3146
|
<mat-icon class="panel-icon">dynamic_form</mat-icon>
|
|
2661
|
-
Dynamic Fields
|
|
3147
|
+
{{ tx('Dynamic Fields') }}
|
|
2662
3148
|
</mat-panel-title>
|
|
2663
|
-
<mat-panel-description>Async Select,
|
|
3149
|
+
<mat-panel-description>{{ tx('Async Select, cascade and pagination') }}</mat-panel-description>
|
|
2664
3150
|
</mat-expansion-panel-header>
|
|
2665
3151
|
<ng-template #hostFields></ng-template>
|
|
2666
3152
|
</mat-expansion-panel>
|
|
@@ -2668,9 +3154,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2668
3154
|
<mat-expansion-panel-header>
|
|
2669
3155
|
<mat-panel-title>
|
|
2670
3156
|
<mat-icon class="panel-icon">cached</mat-icon>
|
|
2671
|
-
Cache &
|
|
3157
|
+
{{ tx('Cache & Persistence') }}
|
|
2672
3158
|
</mat-panel-title>
|
|
2673
|
-
<mat-panel-description>
|
|
3159
|
+
<mat-panel-description>{{ tx('Schema cache strategy (local vs server)') }}</mat-panel-description>
|
|
2674
3160
|
</mat-expansion-panel-header>
|
|
2675
3161
|
<ng-template #hostCache></ng-template>
|
|
2676
3162
|
</mat-expansion-panel>
|
|
@@ -2678,9 +3164,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2678
3164
|
<mat-expansion-panel-header>
|
|
2679
3165
|
<mat-panel-title>
|
|
2680
3166
|
<mat-icon class="panel-icon">psychology</mat-icon>
|
|
2681
|
-
|
|
3167
|
+
{{ tx('Artificial Intelligence') }}
|
|
2682
3168
|
</mat-panel-title>
|
|
2683
|
-
<mat-panel-description>
|
|
3169
|
+
<mat-panel-description>{{ tx('LLM integration') }}</mat-panel-description>
|
|
2684
3170
|
</mat-expansion-panel-header>
|
|
2685
3171
|
|
|
2686
3172
|
<div class="ai-config-container">
|
|
@@ -2689,23 +3175,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2689
3175
|
<mat-icon>settings_suggest</mat-icon>
|
|
2690
3176
|
<span>{{ configSourceLabel }}</span>
|
|
2691
3177
|
</div>
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
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')"
|
|
2701
3187
|
>
|
|
2702
3188
|
<ng-container *ngIf="isClearingGlobalConfig; else clearContent">
|
|
2703
3189
|
<mat-spinner diameter="16" class="btn-spinner"></mat-spinner>
|
|
2704
|
-
<span class="ai-action-label">
|
|
3190
|
+
<span class="ai-action-label">{{ tx('Clearing...') }}</span>
|
|
2705
3191
|
</ng-container>
|
|
2706
3192
|
<ng-template #clearContent>
|
|
2707
3193
|
<mat-icon>delete_sweep</mat-icon>
|
|
2708
|
-
<span class="ai-action-label">
|
|
3194
|
+
<span class="ai-action-label">{{ tx('Clear saved config') }}</span>
|
|
2709
3195
|
</ng-template>
|
|
2710
3196
|
</button>
|
|
2711
3197
|
</div>
|
|
@@ -2713,7 +3199,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2713
3199
|
<div class="ai-group">
|
|
2714
3200
|
<div class="ai-group-header">
|
|
2715
3201
|
<div class="ai-group-title">
|
|
2716
|
-
<mat-icon>vpn_key</mat-icon>
|
|
3202
|
+
<mat-icon>vpn_key</mat-icon> {{ tx('Credentials') }}
|
|
2717
3203
|
</div>
|
|
2718
3204
|
<button mat-stroked-button
|
|
2719
3205
|
type="button"
|
|
@@ -2722,15 +3208,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2722
3208
|
[attr.aria-busy]="isTestingAi ? 'true' : null"
|
|
2723
3209
|
(click)="testAiConnection()"
|
|
2724
3210
|
[disabled]="isTestingAi || !hasApiKey"
|
|
2725
|
-
matTooltip="
|
|
3211
|
+
[matTooltip]="tx('Test connection with the provided key')">
|
|
2726
3212
|
<ng-container *ngIf="isTestingAi; else btnContent">
|
|
2727
3213
|
<mat-spinner diameter="16" class="btn-spinner"></mat-spinner>
|
|
2728
|
-
<span class="ai-action-label">
|
|
3214
|
+
<span class="ai-action-label">{{ tx('Connecting...') }}</span>
|
|
2729
3215
|
</ng-container>
|
|
2730
3216
|
<ng-template #btnContent>
|
|
2731
3217
|
<mat-icon>{{ aiTestResult?.success ? 'check' : 'bolt' }}</mat-icon>
|
|
2732
3218
|
<span class="ai-action-label">
|
|
2733
|
-
{{ aiTestResult?.success ? '
|
|
3219
|
+
{{ aiTestResult?.success ? tx('Connected') : tx('Test connection') }}
|
|
2734
3220
|
</span>
|
|
2735
3221
|
</ng-template>
|
|
2736
3222
|
</button>
|
|
@@ -2772,7 +3258,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2772
3258
|
</div>
|
|
2773
3259
|
<div class="ai-provider-key is-unlocked" *ngIf="selectedProvider?.requiresApiKey === false">
|
|
2774
3260
|
<mat-icon>check_circle</mat-icon>
|
|
2775
|
-
<span>
|
|
3261
|
+
<span>{{ tx('No key required') }}</span>
|
|
2776
3262
|
</div>
|
|
2777
3263
|
</div>
|
|
2778
3264
|
<div class="ai-credentials-row">
|
|
@@ -2792,12 +3278,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2792
3278
|
<div class="ai-group" [class.disabled-group]="!hasApiKey">
|
|
2793
3279
|
<div class="ai-group-header">
|
|
2794
3280
|
<div class="ai-group-title">
|
|
2795
|
-
<mat-icon>smart_toy</mat-icon>
|
|
3281
|
+
<mat-icon>smart_toy</mat-icon> {{ tx('Model & Behavior') }}
|
|
2796
3282
|
</div>
|
|
2797
3283
|
<div class="ai-header-actions">
|
|
2798
|
-
<span class="ai-subtext" *ngIf="hasApiKey">
|
|
2799
|
-
<mat-chip-option *ngIf="!hasApiKey" disabled>
|
|
2800
|
-
<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')">
|
|
2801
3287
|
<mat-icon [class.spin]="isRefetchingModels">sync</mat-icon>
|
|
2802
3288
|
</button>
|
|
2803
3289
|
</div>
|
|
@@ -2816,7 +3302,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2816
3302
|
|
|
2817
3303
|
<div class="ai-placeholder" *ngIf="!hasApiKey">
|
|
2818
3304
|
<mat-icon>lock</mat-icon>
|
|
2819
|
-
<span>Configure
|
|
3305
|
+
<span>{{ tx('Configure and test your API key to unlock model selection.') }}</span>
|
|
2820
3306
|
</div>
|
|
2821
3307
|
</div>
|
|
2822
3308
|
|
|
@@ -2824,7 +3310,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2824
3310
|
<div class="ai-group">
|
|
2825
3311
|
<div class="ai-group-header">
|
|
2826
3312
|
<div class="ai-group-title">
|
|
2827
|
-
<mat-icon>scatter_plot</mat-icon> Embeddings (RAG)
|
|
3313
|
+
<mat-icon>scatter_plot</mat-icon> {{ tx('Embeddings (RAG)') }}
|
|
2828
3314
|
</div>
|
|
2829
3315
|
<div class="ai-header-actions">
|
|
2830
3316
|
<button
|
|
@@ -2833,19 +3319,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2833
3319
|
class="ai-action-btn"
|
|
2834
3320
|
(click)="useLlmForEmbeddings()"
|
|
2835
3321
|
[disabled]="!canUseLlmForEmbeddings"
|
|
2836
|
-
matTooltip="
|
|
3322
|
+
[matTooltip]="tx('Use the LLM provider and key for embeddings')"
|
|
2837
3323
|
>
|
|
2838
3324
|
<mat-icon>merge_type</mat-icon>
|
|
2839
|
-
<span class="ai-action-label">
|
|
3325
|
+
<span class="ai-action-label">{{ tx('Use the LLM provider and key for embeddings') }}</span>
|
|
2840
3326
|
</button>
|
|
2841
|
-
<mat-chip-option *ngIf="!canUseLlmForEmbeddings" disabled>
|
|
3327
|
+
<mat-chip-option *ngIf="!canUseLlmForEmbeddings" disabled>{{ tx('Provider has no embeddings') }}</mat-chip-option>
|
|
2842
3328
|
</div>
|
|
2843
3329
|
</div>
|
|
2844
3330
|
<div class="ai-subtext">
|
|
2845
|
-
Configure
|
|
3331
|
+
{{ tx('Configure the embeddings provider for vector search (templates and schemas).') }}
|
|
2846
3332
|
</div>
|
|
2847
3333
|
<div class="ai-subtext" *ngIf="embeddingUseSameAsLlm">
|
|
2848
|
-
|
|
3334
|
+
{{ tx('Synchronized with the LLM. The fields below follow the primary credential.') }}
|
|
2849
3335
|
</div>
|
|
2850
3336
|
<div class="ai-embedding-row">
|
|
2851
3337
|
<ng-template #hostAiEmbedding></ng-template>
|
|
@@ -2853,7 +3339,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2853
3339
|
<div class="ai-feedback ai-feedback--warn" *ngIf="embeddingDimensionMismatch">
|
|
2854
3340
|
<mat-icon>warning</mat-icon>
|
|
2855
3341
|
<span class="error-text">
|
|
2856
|
-
|
|
3342
|
+
{{ tx('Embedding dimension mismatch with database (768). Adjust to 768 or redo the migration.') }}
|
|
2857
3343
|
</span>
|
|
2858
3344
|
</div>
|
|
2859
3345
|
</div>
|
|
@@ -2864,9 +3350,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2864
3350
|
<mat-expansion-panel-header>
|
|
2865
3351
|
<mat-panel-title>
|
|
2866
3352
|
<mat-icon class="panel-icon">table_chart</mat-icon>
|
|
2867
|
-
|
|
3353
|
+
{{ tx('Table') }}
|
|
2868
3354
|
</mat-panel-title>
|
|
2869
|
-
<mat-panel-description>Toolbar,
|
|
3355
|
+
<mat-panel-description>{{ tx('Toolbar, appearance and advanced filter') }}</mat-panel-description>
|
|
2870
3356
|
</mat-expansion-panel-header>
|
|
2871
3357
|
<ng-template #hostTable></ng-template>
|
|
2872
3358
|
</mat-expansion-panel>
|
|
@@ -2874,27 +3360,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2874
3360
|
<mat-expansion-panel-header>
|
|
2875
3361
|
<mat-panel-title>
|
|
2876
3362
|
<mat-icon class="panel-icon">forum</mat-icon>
|
|
2877
|
-
Dialog
|
|
3363
|
+
{{ tx('Dialog') }}
|
|
2878
3364
|
</mat-panel-title>
|
|
2879
|
-
<mat-panel-description>Defaults
|
|
3365
|
+
<mat-panel-description>{{ tx('Defaults and variants (danger, info, success, question, error)') }}</mat-panel-description>
|
|
2880
3366
|
</mat-expansion-panel-header>
|
|
2881
3367
|
<ng-template #hostDialog></ng-template>
|
|
2882
3368
|
<!-- Icon UX helpers for Dialog variants -->
|
|
2883
3369
|
<div class="dlg-icon-helpers">
|
|
2884
|
-
<div class="dlg-icon-helpers__head"
|
|
3370
|
+
<div class="dlg-icon-helpers__head">{{ tx('Icons by profile (shortcuts)') }}</div>
|
|
2885
3371
|
<div class="dlg-icon-helpers__row" *ngFor="let k of dialogVariantKeys">
|
|
2886
3372
|
<div class="dlg-icon-helpers__label">{{ k }}</div>
|
|
2887
3373
|
<mat-icon aria-hidden="true" [praxisIcon]="getVariantIcon(k) || 'mi:help_outline'" class="dlg-icon-helpers__preview"></mat-icon>
|
|
2888
|
-
<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 })">
|
|
2889
3375
|
<mat-icon>search</mat-icon>
|
|
2890
|
-
|
|
3376
|
+
{{ tx('Pick icon') }}
|
|
2891
3377
|
</button>
|
|
2892
|
-
<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')">
|
|
2893
3379
|
<mat-icon>backspace</mat-icon>
|
|
2894
3380
|
</button>
|
|
2895
3381
|
<span class="dlg-icon-helpers__value" *ngIf="getVariantIcon(k)">{{ getVariantIcon(k) }}</span>
|
|
2896
3382
|
</div>
|
|
2897
|
-
<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>
|
|
2898
3384
|
</div>
|
|
2899
3385
|
</mat-expansion-panel>
|
|
2900
3386
|
</mat-accordion>
|
|
@@ -2933,7 +3419,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2933
3419
|
function openGlobalConfigEditor(settings, opts) {
|
|
2934
3420
|
settings.open({
|
|
2935
3421
|
id: opts?.id ?? 'global-config',
|
|
2936
|
-
title: opts?.title
|
|
3422
|
+
title: opts?.title,
|
|
2937
3423
|
titleIcon: opts?.titleIcon ?? 'tune',
|
|
2938
3424
|
content: { component: GlobalConfigEditorComponent, inputs: {} },
|
|
2939
3425
|
});
|
|
@@ -2978,4 +3464,3 @@ const SETTINGS_PANEL_AI_CAPABILITIES = {
|
|
|
2978
3464
|
*/
|
|
2979
3465
|
|
|
2980
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 };
|
|
2981
|
-
//# sourceMappingURL=praxisui-settings-panel.mjs.map
|