@praxisui/settings-panel 3.0.0-beta.6 → 3.0.0-beta.8
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, 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;
|
|
@@ -416,6 +881,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
416
881
|
args: [{ providedIn: 'root' }]
|
|
417
882
|
}], ctorParameters: () => [{ type: i1$1.Overlay }, { type: i0.Injector }] });
|
|
418
883
|
|
|
884
|
+
function providePraxisSettingsPanelBridge() {
|
|
885
|
+
return {
|
|
886
|
+
provide: SETTINGS_PANEL_BRIDGE,
|
|
887
|
+
useFactory: (service) => ({
|
|
888
|
+
open: (opts) => service.open({
|
|
889
|
+
id: opts.id,
|
|
890
|
+
title: opts.title,
|
|
891
|
+
titleIcon: opts.titleIcon,
|
|
892
|
+
content: {
|
|
893
|
+
component: opts.content.component,
|
|
894
|
+
inputs: (opts.content.inputs || undefined),
|
|
895
|
+
},
|
|
896
|
+
}),
|
|
897
|
+
}),
|
|
898
|
+
deps: [SettingsPanelService],
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
|
|
419
902
|
/**
|
|
420
903
|
* Admin helper to load, patch and persist GlobalConfig.
|
|
421
904
|
* Intended to be used by the Global Config Editor UI.
|
|
@@ -455,6 +938,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
455
938
|
args: [{ providedIn: 'root' }]
|
|
456
939
|
}] });
|
|
457
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
|
+
|
|
458
973
|
const TABLE_COMPACT_LENGTH_TOKEN$1 = '(?:0|(?:\\d+|\\d*\\.\\d+)(?:px|rem|em|%|vh|vw|svh|svw|lvh|lvw|dvh|dvw|ch|ex))';
|
|
459
974
|
const TABLE_COMPACT_SPACING_PATTERN = `^(?:var\\(.+\\)|calc\\(.+\\)|${TABLE_COMPACT_LENGTH_TOKEN$1}(?:\\s+${TABLE_COMPACT_LENGTH_TOKEN$1}){0,3})$`;
|
|
460
975
|
const TABLE_COMPACT_FONT_SIZE_PATTERN = `^(?:var\\(.+\\)|calc\\(.+\\)|${TABLE_COMPACT_LENGTH_TOKEN$1})$`;
|
|
@@ -465,30 +980,31 @@ function safeName(path) {
|
|
|
465
980
|
* Minimal FormConfig schema for the Global Config editor UI.
|
|
466
981
|
* This can be extended incrementally as new domains/settings are added.
|
|
467
982
|
*/
|
|
468
|
-
function buildGlobalConfigFormConfig() {
|
|
983
|
+
function buildGlobalConfigFormConfig(translate = (text) => text) {
|
|
984
|
+
const tx = (text, params) => translate(normalizeMojibakeText(text), params);
|
|
469
985
|
const fields = [
|
|
470
986
|
// CRUD
|
|
471
987
|
{
|
|
472
988
|
name: safeName('crud.defaults.openMode'),
|
|
473
|
-
label: 'Modo de abertura padrão',
|
|
989
|
+
label: tx('Modo de abertura padrão'),
|
|
474
990
|
controlType: FieldControlType.SELECT,
|
|
475
991
|
selectOptions: [
|
|
476
|
-
{ text: 'Rota', value: 'route' },
|
|
992
|
+
{ text: tx('Rota'), value: 'route' },
|
|
477
993
|
{ text: 'Modal', value: 'modal' },
|
|
478
994
|
{ text: 'Drawer', value: 'drawer' },
|
|
479
995
|
],
|
|
480
|
-
hint: 'Aplicado quando ação/metadado não definem modo.',
|
|
996
|
+
hint: tx('Aplicado quando ação/metadado não definem modo.'),
|
|
481
997
|
dataAttributes: { globalPath: 'crud.defaults.openMode' },
|
|
482
998
|
},
|
|
483
999
|
{
|
|
484
1000
|
name: safeName('crud.defaults.back.confirmOnDirty'),
|
|
485
|
-
label: 'Confirmar ao sair com alterações',
|
|
1001
|
+
label: tx('Confirmar ao sair com alterações'),
|
|
486
1002
|
controlType: FieldControlType.TOGGLE,
|
|
487
1003
|
dataAttributes: { globalPath: 'crud.defaults.back.confirmOnDirty' },
|
|
488
1004
|
},
|
|
489
1005
|
{
|
|
490
1006
|
name: safeName('crud.defaults.back.strategy'),
|
|
491
|
-
label: 'Back: estratégia',
|
|
1007
|
+
label: tx('Back: estratégia'),
|
|
492
1008
|
controlType: FieldControlType.SELECT,
|
|
493
1009
|
selectOptions: [
|
|
494
1010
|
{ text: 'auto', value: 'auto' },
|
|
@@ -499,13 +1015,13 @@ function buildGlobalConfigFormConfig() {
|
|
|
499
1015
|
},
|
|
500
1016
|
{
|
|
501
1017
|
name: safeName('crud.defaults.header.showBack'),
|
|
502
|
-
label: 'Header:
|
|
1018
|
+
label: tx('Header: show back'),
|
|
503
1019
|
controlType: FieldControlType.TOGGLE,
|
|
504
1020
|
dataAttributes: { globalPath: 'crud.defaults.header.showBack' },
|
|
505
1021
|
},
|
|
506
1022
|
{
|
|
507
1023
|
name: safeName('crud.defaults.header.variant'),
|
|
508
|
-
label: 'Header:
|
|
1024
|
+
label: tx('Header: variant'),
|
|
509
1025
|
controlType: FieldControlType.SELECT,
|
|
510
1026
|
selectOptions: [
|
|
511
1027
|
{ text: 'ghost', value: 'ghost' },
|
|
@@ -516,31 +1032,31 @@ function buildGlobalConfigFormConfig() {
|
|
|
516
1032
|
},
|
|
517
1033
|
{
|
|
518
1034
|
name: safeName('crud.defaults.header.sticky'),
|
|
519
|
-
label: 'Header:
|
|
1035
|
+
label: tx('Header: sticky'),
|
|
520
1036
|
controlType: FieldControlType.TOGGLE,
|
|
521
1037
|
dataAttributes: { globalPath: 'crud.defaults.header.sticky' },
|
|
522
1038
|
},
|
|
523
1039
|
{
|
|
524
1040
|
name: safeName('crud.defaults.header.divider'),
|
|
525
|
-
label: 'Header:
|
|
1041
|
+
label: tx('Header: show divider'),
|
|
526
1042
|
controlType: FieldControlType.TOGGLE,
|
|
527
1043
|
dataAttributes: { globalPath: 'crud.defaults.header.divider' },
|
|
528
1044
|
},
|
|
529
1045
|
{
|
|
530
1046
|
name: safeName('crud.defaults.modal.width'),
|
|
531
|
-
label: 'Modal:
|
|
1047
|
+
label: tx('Modal: width (e.g. 900px)'),
|
|
532
1048
|
controlType: FieldControlType.INPUT,
|
|
533
1049
|
dataAttributes: { globalPath: 'crud.defaults.modal.width' },
|
|
534
1050
|
},
|
|
535
1051
|
{
|
|
536
1052
|
name: safeName('crud.defaults.modal.maxWidth'),
|
|
537
|
-
label: 'Modal: largura máxima (ex.: 96vw)',
|
|
1053
|
+
label: tx('Modal: largura máxima (ex.: 96vw)'),
|
|
538
1054
|
controlType: FieldControlType.INPUT,
|
|
539
1055
|
dataAttributes: { globalPath: 'crud.defaults.modal.maxWidth' },
|
|
540
1056
|
},
|
|
541
1057
|
{
|
|
542
1058
|
name: safeName('crud.defaults.modal.backdropStyle'),
|
|
543
|
-
label: 'Modal: backdrop',
|
|
1059
|
+
label: tx('Modal: backdrop'),
|
|
544
1060
|
controlType: FieldControlType.SELECT,
|
|
545
1061
|
selectOptions: [
|
|
546
1062
|
{ text: 'blur', value: 'blur' },
|
|
@@ -552,25 +1068,25 @@ function buildGlobalConfigFormConfig() {
|
|
|
552
1068
|
// Dynamic Fields
|
|
553
1069
|
{
|
|
554
1070
|
name: safeName('dynamicFields.asyncSelect.loadOn'),
|
|
555
|
-
label: 'Async Select: loadOn',
|
|
1071
|
+
label: tx('Async Select: loadOn'),
|
|
556
1072
|
controlType: FieldControlType.SELECT,
|
|
557
1073
|
selectOptions: [
|
|
558
1074
|
{ text: 'open', value: 'open' },
|
|
559
1075
|
{ text: 'init', value: 'init' },
|
|
560
1076
|
{ text: 'none', value: 'none' },
|
|
561
1077
|
],
|
|
562
|
-
hint: 'Estratégia de primeira carga quando metadado não definir.',
|
|
1078
|
+
hint: tx('Estratégia de primeira carga quando metadado não definir.'),
|
|
563
1079
|
dataAttributes: { globalPath: 'dynamicFields.asyncSelect.loadOn' },
|
|
564
1080
|
},
|
|
565
1081
|
{
|
|
566
1082
|
name: safeName('dynamicFields.cascade.enable'),
|
|
567
|
-
label: '
|
|
1083
|
+
label: tx('Native cascade enabled'),
|
|
568
1084
|
controlType: FieldControlType.TOGGLE,
|
|
569
1085
|
dataAttributes: { globalPath: 'dynamicFields.cascade.enable' },
|
|
570
1086
|
},
|
|
571
1087
|
{
|
|
572
1088
|
name: safeName('dynamicFields.cascade.loadOnChange'),
|
|
573
|
-
label: '
|
|
1089
|
+
label: tx('Cascade: loadOnChange'),
|
|
574
1090
|
controlType: FieldControlType.SELECT,
|
|
575
1091
|
selectOptions: [
|
|
576
1092
|
{ text: 'respectLoadOn', value: 'respectLoadOn' },
|
|
@@ -581,42 +1097,42 @@ function buildGlobalConfigFormConfig() {
|
|
|
581
1097
|
},
|
|
582
1098
|
{
|
|
583
1099
|
name: safeName('dynamicFields.cascade.debounceMs'),
|
|
584
|
-
label: '
|
|
1100
|
+
label: tx('Cascade: debounce (ms)'),
|
|
585
1101
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
586
1102
|
dataAttributes: { globalPath: 'dynamicFields.cascade.debounceMs' },
|
|
587
1103
|
},
|
|
588
1104
|
// Dynamic Fields async-select extra
|
|
589
1105
|
{
|
|
590
1106
|
name: safeName('dynamicFields.asyncSelect.pageSize'),
|
|
591
|
-
label: 'Async Select: pageSize',
|
|
1107
|
+
label: tx('Async Select: pageSize'),
|
|
592
1108
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
593
1109
|
dataAttributes: { globalPath: 'dynamicFields.asyncSelect.pageSize' },
|
|
594
1110
|
},
|
|
595
1111
|
{
|
|
596
1112
|
name: safeName('dynamicFields.asyncSelect.useCursor'),
|
|
597
|
-
label: 'Async Select:
|
|
1113
|
+
label: tx('Async Select: use cursor'),
|
|
598
1114
|
controlType: FieldControlType.TOGGLE,
|
|
599
1115
|
dataAttributes: { globalPath: 'dynamicFields.asyncSelect.useCursor' },
|
|
600
1116
|
},
|
|
601
1117
|
// AI
|
|
602
1118
|
{
|
|
603
1119
|
name: safeName('ai.provider'),
|
|
604
|
-
label: '
|
|
1120
|
+
label: tx('LLM provider'),
|
|
605
1121
|
controlType: FieldControlType.SELECT,
|
|
606
1122
|
selectOptions: [],
|
|
607
|
-
hint: '
|
|
1123
|
+
hint: tx('Select the provider to list models and test the key.'),
|
|
608
1124
|
dataAttributes: { globalPath: 'ai.provider' },
|
|
609
1125
|
},
|
|
610
1126
|
{
|
|
611
1127
|
name: safeName('ai.apiKey'),
|
|
612
|
-
label: '
|
|
1128
|
+
label: tx('API key'),
|
|
613
1129
|
controlType: FieldControlType.INPUT,
|
|
614
|
-
hint: '
|
|
1130
|
+
hint: tx('Enter the selected provider key to test.'),
|
|
615
1131
|
dataAttributes: { globalPath: 'ai.apiKey' },
|
|
616
1132
|
},
|
|
617
1133
|
{
|
|
618
1134
|
name: safeName('ai.model'),
|
|
619
|
-
label: '
|
|
1135
|
+
label: tx('AI model'),
|
|
620
1136
|
controlType: FieldControlType.SEARCHABLE_SELECT,
|
|
621
1137
|
selectOptions: [],
|
|
622
1138
|
resourcePath: '',
|
|
@@ -624,113 +1140,113 @@ function buildGlobalConfigFormConfig() {
|
|
|
624
1140
|
},
|
|
625
1141
|
{
|
|
626
1142
|
name: safeName('ai.temperature'),
|
|
627
|
-
label: '
|
|
1143
|
+
label: tx('Temperature (Creativity)'),
|
|
628
1144
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
629
|
-
hint: '0.0 (
|
|
1145
|
+
hint: tx('0.0 (deterministic) to 1.0 (creative)'),
|
|
630
1146
|
dataAttributes: { globalPath: 'ai.temperature' },
|
|
631
1147
|
},
|
|
632
1148
|
{
|
|
633
1149
|
name: safeName('ai.maxTokens'),
|
|
634
|
-
label: 'Max tokens',
|
|
1150
|
+
label: tx('Max tokens'),
|
|
635
1151
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
636
|
-
hint: '
|
|
1152
|
+
hint: tx('Maximum token limit for the response.'),
|
|
637
1153
|
dataAttributes: { globalPath: 'ai.maxTokens' },
|
|
638
1154
|
},
|
|
639
1155
|
{
|
|
640
1156
|
name: safeName('ai.riskPolicy'),
|
|
641
|
-
label: '
|
|
1157
|
+
label: tx('Assistant: risk validation'),
|
|
642
1158
|
controlType: FieldControlType.SELECT,
|
|
643
1159
|
selectOptions: [
|
|
644
|
-
{ text: '
|
|
645
|
-
{ text: '
|
|
1160
|
+
{ text: 'Strict (recommended)', value: 'strict' },
|
|
1161
|
+
{ text: tx('Standard'), value: 'standard' },
|
|
646
1162
|
],
|
|
647
|
-
hint: '
|
|
1163
|
+
hint: tx('Strict requires confirmation for medium/high risk. Standard follows the indication returned by the backend.'),
|
|
648
1164
|
dataAttributes: { globalPath: 'ai.riskPolicy' },
|
|
649
1165
|
},
|
|
650
1166
|
{
|
|
651
1167
|
name: safeName('ai.embedding.useSameAsLlm'),
|
|
652
|
-
label: '
|
|
1168
|
+
label: tx('Use same LLM for embeddings'),
|
|
653
1169
|
controlType: FieldControlType.TOGGLE,
|
|
654
|
-
hint: '
|
|
1170
|
+
hint: tx('Replicates the LLM provider and key for embeddings.'),
|
|
655
1171
|
dataAttributes: { globalPath: 'ai.embedding.useSameAsLlm' },
|
|
656
1172
|
},
|
|
657
1173
|
{
|
|
658
1174
|
name: safeName('ai.embedding.provider'),
|
|
659
|
-
label: 'Embeddings
|
|
1175
|
+
label: tx('Embeddings provider'),
|
|
660
1176
|
controlType: FieldControlType.SELECT,
|
|
661
1177
|
selectOptions: [],
|
|
662
|
-
hint: '
|
|
1178
|
+
hint: tx('Provider used to generate embeddings (RAG).'),
|
|
663
1179
|
dataAttributes: { globalPath: 'ai.embedding.provider' },
|
|
664
1180
|
},
|
|
665
1181
|
{
|
|
666
1182
|
name: safeName('ai.embedding.apiKey'),
|
|
667
|
-
label: 'Embeddings
|
|
1183
|
+
label: tx('Embeddings API key'),
|
|
668
1184
|
controlType: FieldControlType.INPUT,
|
|
669
|
-
hint: '
|
|
1185
|
+
hint: tx('Embeddings provider key.'),
|
|
670
1186
|
dataAttributes: { globalPath: 'ai.embedding.apiKey' },
|
|
671
1187
|
},
|
|
672
1188
|
{
|
|
673
1189
|
name: safeName('ai.embedding.model'),
|
|
674
|
-
label: 'Embeddings
|
|
1190
|
+
label: tx('Embeddings model'),
|
|
675
1191
|
controlType: FieldControlType.SEARCHABLE_SELECT,
|
|
676
1192
|
selectOptions: [
|
|
677
1193
|
{ text: 'text-embedding-3-large', value: 'text-embedding-3-large' },
|
|
678
1194
|
{ text: 'text-embedding-3-small', value: 'text-embedding-3-small' },
|
|
679
1195
|
{ text: 'text-embedding-ada-002 (legacy)', value: 'text-embedding-ada-002' },
|
|
680
1196
|
],
|
|
681
|
-
emptyOptionText: '
|
|
682
|
-
hint: '
|
|
1197
|
+
emptyOptionText: tx('Provider default'),
|
|
1198
|
+
hint: tx('OpenAI models for embeddings.'),
|
|
683
1199
|
dataAttributes: { globalPath: 'ai.embedding.model' },
|
|
684
1200
|
},
|
|
685
1201
|
{
|
|
686
1202
|
name: safeName('ai.embedding.dimensions'),
|
|
687
|
-
label: 'Embeddings:
|
|
1203
|
+
label: tx('Embeddings: dimensions'),
|
|
688
1204
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
689
|
-
hint: '
|
|
1205
|
+
hint: tx('Embedding vector dimensions (default 768).'),
|
|
690
1206
|
dataAttributes: { globalPath: 'ai.embedding.dimensions' },
|
|
691
1207
|
},
|
|
692
|
-
// Cache
|
|
1208
|
+
// Cache // Cache
|
|
693
1209
|
{
|
|
694
1210
|
name: safeName('cache.disableSchemaCache'),
|
|
695
|
-
label: 'Desabilitar cache de schema (LocalStorage)',
|
|
1211
|
+
label: tx('Desabilitar cache de schema (LocalStorage)'),
|
|
696
1212
|
controlType: FieldControlType.TOGGLE,
|
|
697
|
-
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.'),
|
|
698
1214
|
dataAttributes: { globalPath: 'cache.disableSchemaCache' },
|
|
699
1215
|
},
|
|
700
1216
|
// Table
|
|
701
1217
|
{
|
|
702
1218
|
name: safeName('table.behavior.pagination.enabled'),
|
|
703
|
-
label: 'Paginação habilitada',
|
|
1219
|
+
label: tx('Paginação habilitada'),
|
|
704
1220
|
controlType: FieldControlType.TOGGLE,
|
|
705
1221
|
dataAttributes: { globalPath: 'table.behavior.pagination.enabled' },
|
|
706
1222
|
},
|
|
707
1223
|
{
|
|
708
1224
|
name: safeName('table.behavior.pagination.pageSize'),
|
|
709
|
-
label: 'Tamanho da página',
|
|
1225
|
+
label: tx('Tamanho da página'),
|
|
710
1226
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
711
1227
|
dataAttributes: { globalPath: 'table.behavior.pagination.pageSize' },
|
|
712
1228
|
},
|
|
713
1229
|
{
|
|
714
1230
|
name: safeName('table.behavior.filtering.debounceTime'),
|
|
715
|
-
label: '
|
|
1231
|
+
label: tx('Filter debounce (ms)'),
|
|
716
1232
|
controlType: FieldControlType.NUMERIC_TEXT_BOX,
|
|
717
1233
|
dataAttributes: { globalPath: 'table.behavior.filtering.debounceTime' },
|
|
718
1234
|
},
|
|
719
1235
|
{
|
|
720
1236
|
name: safeName('table.behavior.sorting.enabled'),
|
|
721
|
-
label: 'Ordenação habilitada',
|
|
1237
|
+
label: tx('Ordenação habilitada'),
|
|
722
1238
|
controlType: FieldControlType.TOGGLE,
|
|
723
1239
|
dataAttributes: { globalPath: 'table.behavior.sorting.enabled' },
|
|
724
1240
|
},
|
|
725
1241
|
{
|
|
726
1242
|
name: safeName('table.behavior.selection.enabled'),
|
|
727
|
-
label: 'Seleção habilitada',
|
|
1243
|
+
label: tx('Seleção habilitada'),
|
|
728
1244
|
controlType: FieldControlType.TOGGLE,
|
|
729
1245
|
dataAttributes: { globalPath: 'table.behavior.selection.enabled' },
|
|
730
1246
|
},
|
|
731
1247
|
{
|
|
732
1248
|
name: safeName('table.behavior.pagination.strategy'),
|
|
733
|
-
label: 'Paginação: estratégia',
|
|
1249
|
+
label: tx('Paginação: estratégia'),
|
|
734
1250
|
controlType: FieldControlType.SELECT,
|
|
735
1251
|
selectOptions: [
|
|
736
1252
|
{ text: 'client', value: 'client' },
|
|
@@ -740,7 +1256,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
740
1256
|
},
|
|
741
1257
|
{
|
|
742
1258
|
name: safeName('table.behavior.sorting.strategy'),
|
|
743
|
-
label: 'Ordenação: estratégia',
|
|
1259
|
+
label: tx('Ordenação: estratégia'),
|
|
744
1260
|
controlType: FieldControlType.SELECT,
|
|
745
1261
|
selectOptions: [
|
|
746
1262
|
{ text: 'client', value: 'client' },
|
|
@@ -750,114 +1266,113 @@ function buildGlobalConfigFormConfig() {
|
|
|
750
1266
|
},
|
|
751
1267
|
{
|
|
752
1268
|
name: safeName('table.behavior.pagination.showFirstLastButtons'),
|
|
753
|
-
label: 'Paginação: botões Primeiro/Último',
|
|
1269
|
+
label: tx('Paginação: botões Primeiro/Último'),
|
|
754
1270
|
controlType: FieldControlType.CHECKBOX,
|
|
755
1271
|
dataAttributes: { globalPath: 'table.behavior.pagination.showFirstLastButtons' },
|
|
756
1272
|
},
|
|
757
1273
|
{
|
|
758
1274
|
name: safeName('table.toolbar.visible'),
|
|
759
|
-
label: 'Toolbar visível',
|
|
1275
|
+
label: tx('Toolbar visível'),
|
|
760
1276
|
controlType: FieldControlType.CHECKBOX,
|
|
761
1277
|
dataAttributes: { globalPath: 'table.toolbar.visible' },
|
|
762
1278
|
},
|
|
763
1279
|
{
|
|
764
1280
|
name: safeName('table.appearance.density'),
|
|
765
|
-
label: '
|
|
1281
|
+
label: tx('Appearance: density'),
|
|
766
1282
|
controlType: FieldControlType.SELECT,
|
|
767
1283
|
selectOptions: [
|
|
768
|
-
{ text: 'compact', value: 'compact' },
|
|
769
|
-
{ text: 'comfortable', value: 'comfortable' },
|
|
770
|
-
{ text: 'spacious', value: 'spacious' },
|
|
1284
|
+
{ text: tx('compact'), value: 'compact' },
|
|
1285
|
+
{ text: tx('comfortable'), value: 'comfortable' },
|
|
1286
|
+
{ text: tx('spacious'), value: 'spacious' },
|
|
771
1287
|
],
|
|
772
1288
|
dataAttributes: { globalPath: 'table.appearance.density' },
|
|
773
1289
|
},
|
|
774
1290
|
{
|
|
775
1291
|
name: safeName('table.appearance.spacing.cellPadding'),
|
|
776
|
-
label: '
|
|
1292
|
+
label: tx('Appearance: cell padding'),
|
|
777
1293
|
controlType: FieldControlType.INPUT,
|
|
778
|
-
hint: '
|
|
1294
|
+
hint: tx('Accepts 1 to 4 CSS measures with units, var(...) or calc(...). Example: 6px 12px'),
|
|
779
1295
|
pattern: TABLE_COMPACT_SPACING_PATTERN,
|
|
780
|
-
patternMessage: 'Use 1
|
|
1296
|
+
patternMessage: tx('Use 1 to 4 valid CSS measures, such as 6px 12px.'),
|
|
781
1297
|
dataAttributes: { globalPath: 'table.appearance.spacing.cellPadding' },
|
|
782
1298
|
},
|
|
783
1299
|
{
|
|
784
1300
|
name: safeName('table.appearance.spacing.headerPadding'),
|
|
785
|
-
label: '
|
|
1301
|
+
label: tx('Appearance: header padding'),
|
|
786
1302
|
controlType: FieldControlType.INPUT,
|
|
787
|
-
hint: '
|
|
1303
|
+
hint: tx('Accepts 1 to 4 CSS measures with units, var(...) or calc(...). Example: 8px 12px'),
|
|
788
1304
|
pattern: TABLE_COMPACT_SPACING_PATTERN,
|
|
789
|
-
patternMessage: 'Use 1
|
|
1305
|
+
patternMessage: tx('Use 1 to 4 valid CSS measures, such as 8px 12px.'),
|
|
790
1306
|
dataAttributes: { globalPath: 'table.appearance.spacing.headerPadding' },
|
|
791
1307
|
},
|
|
792
1308
|
{
|
|
793
1309
|
name: safeName('table.appearance.typography.fontSize'),
|
|
794
|
-
label: '
|
|
1310
|
+
label: tx('Appearance: cell font size'),
|
|
795
1311
|
controlType: FieldControlType.INPUT,
|
|
796
|
-
hint: '
|
|
1312
|
+
hint: tx('Accepts a CSS measure with units, var(...) or calc(...). Example: 13px'),
|
|
797
1313
|
pattern: TABLE_COMPACT_FONT_SIZE_PATTERN,
|
|
798
|
-
patternMessage: 'Use
|
|
1314
|
+
patternMessage: tx('Use a valid CSS measure, such as 13px.'),
|
|
799
1315
|
dataAttributes: { globalPath: 'table.appearance.typography.fontSize' },
|
|
800
1316
|
},
|
|
801
1317
|
{
|
|
802
1318
|
name: safeName('table.appearance.typography.headerFontSize'),
|
|
803
|
-
label: '
|
|
1319
|
+
label: tx('Appearance: header font size'),
|
|
804
1320
|
controlType: FieldControlType.INPUT,
|
|
805
|
-
hint: '
|
|
1321
|
+
hint: tx('Accepts a CSS measure with units, var(...) or calc(...). Example: 13px'),
|
|
806
1322
|
pattern: TABLE_COMPACT_FONT_SIZE_PATTERN,
|
|
807
|
-
patternMessage: 'Use
|
|
1323
|
+
patternMessage: tx('Use a valid CSS measure, such as 13px.'),
|
|
808
1324
|
dataAttributes: { globalPath: 'table.appearance.typography.headerFontSize' },
|
|
809
|
-
},
|
|
810
|
-
{
|
|
1325
|
+
}, {
|
|
811
1326
|
name: safeName('table.filteringUi.advancedOpenMode'),
|
|
812
|
-
label: 'Filtro: modo de abertura',
|
|
1327
|
+
label: tx('Filtro: modo de abertura'),
|
|
813
1328
|
controlType: FieldControlType.SELECT,
|
|
814
1329
|
selectOptions: [
|
|
815
|
-
{ text: 'overlay', value: 'overlay' },
|
|
816
|
-
{ text: 'modal', value: 'modal' },
|
|
817
|
-
{ text: 'drawer', value: 'drawer' },
|
|
1330
|
+
{ text: tx('overlay'), value: 'overlay' },
|
|
1331
|
+
{ text: tx('modal'), value: 'modal' },
|
|
1332
|
+
{ text: tx('drawer'), value: 'drawer' },
|
|
818
1333
|
],
|
|
819
1334
|
dataAttributes: { globalPath: 'table.filteringUi.advancedOpenMode' },
|
|
820
1335
|
},
|
|
821
1336
|
{
|
|
822
1337
|
name: safeName('table.filteringUi.overlayVariant'),
|
|
823
|
-
label: 'Filtro: overlay (visual)',
|
|
1338
|
+
label: tx('Filtro: overlay (visual)'),
|
|
824
1339
|
controlType: FieldControlType.SELECT,
|
|
825
1340
|
selectOptions: [
|
|
826
|
-
{ text: 'card', value: 'card' },
|
|
827
|
-
{ text: 'frosted', value: 'frosted' },
|
|
1341
|
+
{ text: tx('card'), value: 'card' },
|
|
1342
|
+
{ text: tx('frosted'), value: 'frosted' },
|
|
828
1343
|
],
|
|
829
1344
|
dataAttributes: { globalPath: 'table.filteringUi.overlayVariant' },
|
|
830
1345
|
},
|
|
831
1346
|
{
|
|
832
1347
|
name: safeName('table.filteringUi.overlayBackdrop'),
|
|
833
|
-
label: 'Filtro: backdrop no overlay',
|
|
1348
|
+
label: tx('Filtro: backdrop no overlay'),
|
|
834
1349
|
controlType: FieldControlType.CHECKBOX,
|
|
835
1350
|
dataAttributes: { globalPath: 'table.filteringUi.overlayBackdrop' },
|
|
836
1351
|
},
|
|
837
1352
|
// Table messages - confirmations
|
|
838
|
-
{ name: safeName('table.messages.actions.confirmations.delete'), label: 'Excluir — confirmação', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.confirmations.delete' } },
|
|
839
|
-
{ name: safeName('table.messages.actions.confirmations.deleteMultiple'), label: 'Excluir (múltiplos) — confirmação', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.confirmations.deleteMultiple' } },
|
|
840
|
-
{ name: safeName('table.messages.actions.confirmations.save'), label: 'Salvar — confirmação', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.confirmations.save' } },
|
|
841
|
-
{ name: safeName('table.messages.actions.confirmations.cancel'), label: 'Cancelar — confirmação', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.confirmations.cancel' } },
|
|
842
|
-
{ 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' } },
|
|
843
1358
|
// Table messages - progress
|
|
844
|
-
{ name: safeName('table.messages.actions.progress.delete'), label: 'Excluir — progresso', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.progress.delete' } },
|
|
845
|
-
{ 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' } },
|
|
846
1361
|
// Table messages - success
|
|
847
|
-
{ name: safeName('table.messages.actions.success.delete'), label: 'Excluir — sucesso', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.success.delete' } },
|
|
848
|
-
{ name: safeName('table.messages.actions.success.save'), label: 'Salvar — sucesso', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.success.save' } },
|
|
849
|
-
{ name: safeName('table.messages.actions.success.export'), label: 'Exportar — sucesso', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.success.export' } },
|
|
850
|
-
{ 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' } },
|
|
851
1366
|
// Table messages - errors
|
|
852
|
-
{ name: safeName('table.messages.actions.errors.delete'), label: 'Excluir — erro', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.delete' } },
|
|
853
|
-
{ name: safeName('table.messages.actions.errors.save'), label: 'Salvar — erro', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.save' } },
|
|
854
|
-
{ name: safeName('table.messages.actions.errors.export'), label: 'Exportar — erro', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.export' } },
|
|
855
|
-
{ name: safeName('table.messages.actions.errors.network'), label: 'Rede — erro', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.network' } },
|
|
856
|
-
{ name: safeName('table.messages.actions.errors.permission'), label: 'Permissão — erro', controlType: FieldControlType.INPUT, dataAttributes: { globalPath: 'table.messages.actions.errors.permission' } },
|
|
857
|
-
// 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
|
|
858
1373
|
{
|
|
859
1374
|
name: safeName('dialog.defaults.confirm.ariaRole'),
|
|
860
|
-
label: 'Dialog
|
|
1375
|
+
label: tx('Dialog defaults: confirm - ariaRole'),
|
|
861
1376
|
controlType: FieldControlType.SELECT,
|
|
862
1377
|
selectOptions: [
|
|
863
1378
|
{ text: 'dialog', value: 'dialog' },
|
|
@@ -865,24 +1380,24 @@ function buildGlobalConfigFormConfig() {
|
|
|
865
1380
|
],
|
|
866
1381
|
dataAttributes: { globalPath: 'dialog.defaults.confirm.ariaRole' },
|
|
867
1382
|
},
|
|
868
|
-
{ name: safeName('dialog.defaults.confirm.title'), label: 'Dialog
|
|
869
|
-
{ name: safeName('dialog.defaults.confirm.icon'), label: 'Dialog
|
|
870
|
-
{ name: safeName('dialog.defaults.confirm.message'), label: 'Dialog
|
|
871
|
-
{ 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' } },
|
|
872
1387
|
{
|
|
873
1388
|
name: safeName('dialog.defaults.confirm.closeOnBackdropClick'),
|
|
874
|
-
label: 'Dialog
|
|
1389
|
+
label: tx('Dialog defaults: confirm - close on backdrop click'),
|
|
875
1390
|
controlType: FieldControlType.TOGGLE,
|
|
876
1391
|
dataAttributes: { globalPath: 'dialog.defaults.confirm.closeOnBackdropClick' },
|
|
877
1392
|
},
|
|
878
|
-
{ name: safeName('dialog.defaults.confirm.disableClose'), label: 'Dialog
|
|
879
|
-
{ name: safeName('dialog.defaults.confirm.hasBackdrop'), label: 'Dialog
|
|
880
|
-
{ name: safeName('dialog.defaults.confirm.panelClass'), label: 'Dialog
|
|
881
|
-
{ name: safeName('dialog.defaults.confirm.styles'), label: 'Dialog
|
|
882
|
-
{ 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 } },
|
|
883
1398
|
{
|
|
884
1399
|
name: safeName('dialog.defaults.alert.ariaRole'),
|
|
885
|
-
label: 'Dialog
|
|
1400
|
+
label: tx('Dialog defaults: alert - ariaRole'),
|
|
886
1401
|
controlType: FieldControlType.SELECT,
|
|
887
1402
|
selectOptions: [
|
|
888
1403
|
{ text: 'dialog', value: 'dialog' },
|
|
@@ -890,24 +1405,24 @@ function buildGlobalConfigFormConfig() {
|
|
|
890
1405
|
],
|
|
891
1406
|
dataAttributes: { globalPath: 'dialog.defaults.alert.ariaRole' },
|
|
892
1407
|
},
|
|
893
|
-
{ name: safeName('dialog.defaults.alert.title'), label: 'Dialog
|
|
894
|
-
{ name: safeName('dialog.defaults.alert.icon'), label: 'Dialog
|
|
895
|
-
{ name: safeName('dialog.defaults.alert.message'), label: 'Dialog
|
|
896
|
-
{ 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' } },
|
|
897
1412
|
{
|
|
898
1413
|
name: safeName('dialog.defaults.alert.closeOnBackdropClick'),
|
|
899
|
-
label: 'Dialog
|
|
1414
|
+
label: tx('Dialog defaults: alert - close on backdrop click'),
|
|
900
1415
|
controlType: FieldControlType.TOGGLE,
|
|
901
1416
|
dataAttributes: { globalPath: 'dialog.defaults.alert.closeOnBackdropClick' },
|
|
902
1417
|
},
|
|
903
|
-
{ name: safeName('dialog.defaults.alert.disableClose'), label: 'Dialog
|
|
904
|
-
{ name: safeName('dialog.defaults.alert.hasBackdrop'), label: 'Dialog
|
|
905
|
-
{ name: safeName('dialog.defaults.alert.panelClass'), label: 'Dialog
|
|
906
|
-
{ name: safeName('dialog.defaults.alert.styles'), label: 'Dialog
|
|
907
|
-
{ 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 } },
|
|
908
1423
|
{
|
|
909
1424
|
name: safeName('dialog.defaults.prompt.ariaRole'),
|
|
910
|
-
label: 'Dialog
|
|
1425
|
+
label: tx('Dialog defaults: prompt - ariaRole'),
|
|
911
1426
|
controlType: FieldControlType.SELECT,
|
|
912
1427
|
selectOptions: [
|
|
913
1428
|
{ text: 'dialog', value: 'dialog' },
|
|
@@ -915,79 +1430,79 @@ function buildGlobalConfigFormConfig() {
|
|
|
915
1430
|
],
|
|
916
1431
|
dataAttributes: { globalPath: 'dialog.defaults.prompt.ariaRole' },
|
|
917
1432
|
},
|
|
918
|
-
{ name: safeName('dialog.defaults.prompt.title'), label: 'Dialog
|
|
919
|
-
{ name: safeName('dialog.defaults.prompt.icon'), label: 'Dialog
|
|
920
|
-
{ name: safeName('dialog.defaults.prompt.message'), label: 'Dialog
|
|
921
|
-
{ 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' } },
|
|
922
1437
|
{
|
|
923
1438
|
name: safeName('dialog.defaults.prompt.closeOnBackdropClick'),
|
|
924
|
-
label: 'Dialog
|
|
1439
|
+
label: tx('Dialog defaults: prompt - close on backdrop click'),
|
|
925
1440
|
controlType: FieldControlType.TOGGLE,
|
|
926
1441
|
dataAttributes: { globalPath: 'dialog.defaults.prompt.closeOnBackdropClick' },
|
|
927
1442
|
},
|
|
928
|
-
{ name: safeName('dialog.defaults.prompt.disableClose'), label: 'Dialog
|
|
929
|
-
{ name: safeName('dialog.defaults.prompt.hasBackdrop'), label: 'Dialog
|
|
930
|
-
{ name: safeName('dialog.defaults.prompt.panelClass'), label: 'Dialog
|
|
931
|
-
{ name: safeName('dialog.defaults.prompt.styles'), label: 'Dialog
|
|
932
|
-
{ name: safeName('dialog.defaults.prompt.animation'), label: 'Dialog
|
|
933
|
-
// 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)
|
|
934
1449
|
// Each variant exposes commonly customized fields + JSON editors for actions/styles
|
|
935
1450
|
// danger
|
|
936
|
-
{ name: safeName('dialog.variants.danger.title'), label: 'Variant danger
|
|
937
|
-
{ name: safeName('dialog.variants.danger.icon'), label: 'Variant danger
|
|
938
|
-
{ name: safeName('dialog.variants.danger.message'), label: 'Variant danger
|
|
939
|
-
{ name: safeName('dialog.variants.danger.ariaRole'), label: 'Variant danger
|
|
940
|
-
{ name: safeName('dialog.variants.danger.closeOnBackdropClick'), label: 'Variant danger
|
|
941
|
-
{ name: safeName('dialog.variants.danger.panelClass'), label: 'Variant danger
|
|
942
|
-
{ name: safeName('dialog.variants.danger.actions'), label: 'Variant danger
|
|
943
|
-
{ name: safeName('dialog.variants.danger.styles'), label: 'Variant danger
|
|
944
|
-
{ 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 } },
|
|
945
1460
|
// info
|
|
946
|
-
{ name: safeName('dialog.variants.info.title'), label: 'Variant info
|
|
947
|
-
{ name: safeName('dialog.variants.info.icon'), label: 'Variant info
|
|
948
|
-
{ name: safeName('dialog.variants.info.message'), label: 'Variant info
|
|
949
|
-
{ name: safeName('dialog.variants.info.ariaRole'), label: 'Variant info
|
|
950
|
-
{ name: safeName('dialog.variants.info.closeOnBackdropClick'), label: 'Variant info
|
|
951
|
-
{ name: safeName('dialog.variants.info.panelClass'), label: 'Variant info
|
|
952
|
-
{ name: safeName('dialog.variants.info.actions'), label: 'Variant info
|
|
953
|
-
{ name: safeName('dialog.variants.info.styles'), label: 'Variant info
|
|
954
|
-
{ 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 } },
|
|
955
1470
|
// success
|
|
956
|
-
{ name: safeName('dialog.variants.success.title'), label: 'Variant success
|
|
957
|
-
{ name: safeName('dialog.variants.success.icon'), label: 'Variant success
|
|
958
|
-
{ name: safeName('dialog.variants.success.message'), label: 'Variant success
|
|
959
|
-
{ name: safeName('dialog.variants.success.ariaRole'), label: 'Variant success
|
|
960
|
-
{ name: safeName('dialog.variants.success.closeOnBackdropClick'), label: 'Variant success
|
|
961
|
-
{ name: safeName('dialog.variants.success.panelClass'), label: 'Variant success
|
|
962
|
-
{ name: safeName('dialog.variants.success.actions'), label: 'Variant success
|
|
963
|
-
{ name: safeName('dialog.variants.success.styles'), label: 'Variant success
|
|
964
|
-
{ 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 } },
|
|
965
1480
|
// question
|
|
966
|
-
{ name: safeName('dialog.variants.question.title'), label: 'Variant question
|
|
967
|
-
{ name: safeName('dialog.variants.question.icon'), label: 'Variant question
|
|
968
|
-
{ name: safeName('dialog.variants.question.message'), label: 'Variant question
|
|
969
|
-
{ name: safeName('dialog.variants.question.ariaRole'), label: 'Variant question
|
|
970
|
-
{ name: safeName('dialog.variants.question.closeOnBackdropClick'), label: 'Variant question
|
|
971
|
-
{ name: safeName('dialog.variants.question.panelClass'), label: 'Variant question
|
|
972
|
-
{ name: safeName('dialog.variants.question.actions'), label: 'Variant question
|
|
973
|
-
{ name: safeName('dialog.variants.question.styles'), label: 'Variant question
|
|
974
|
-
{ 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 } },
|
|
975
1490
|
// error
|
|
976
|
-
{ name: safeName('dialog.variants.error.title'), label: 'Variant error
|
|
977
|
-
{ name: safeName('dialog.variants.error.icon'), label: 'Variant error
|
|
978
|
-
{ name: safeName('dialog.variants.error.message'), label: 'Variant error
|
|
979
|
-
{ name: safeName('dialog.variants.error.ariaRole'), label: 'Variant error
|
|
980
|
-
{ name: safeName('dialog.variants.error.closeOnBackdropClick'), label: 'Variant error
|
|
981
|
-
{ name: safeName('dialog.variants.error.panelClass'), label: 'Variant error
|
|
982
|
-
{ name: safeName('dialog.variants.error.actions'), label: 'Variant error
|
|
983
|
-
{ name: safeName('dialog.variants.error.styles'), label: 'Variant error
|
|
984
|
-
{ 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 } },
|
|
985
1500
|
];
|
|
986
1501
|
const cfg = {
|
|
987
1502
|
sections: [
|
|
988
1503
|
{
|
|
989
1504
|
id: 'crud',
|
|
990
|
-
title: 'CRUD',
|
|
1505
|
+
title: tx('CRUD'),
|
|
991
1506
|
rows: [
|
|
992
1507
|
{
|
|
993
1508
|
id: 'crud-row-1',
|
|
@@ -1014,7 +1529,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1014
1529
|
},
|
|
1015
1530
|
{
|
|
1016
1531
|
id: 'dynamic-fields',
|
|
1017
|
-
title: 'Dynamic Fields',
|
|
1532
|
+
title: tx('Dynamic Fields'),
|
|
1018
1533
|
rows: [
|
|
1019
1534
|
{
|
|
1020
1535
|
id: 'df-row-1',
|
|
@@ -1035,7 +1550,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1035
1550
|
},
|
|
1036
1551
|
{
|
|
1037
1552
|
id: 'ai-credentials',
|
|
1038
|
-
title: '
|
|
1553
|
+
title: tx('Credentials'), // Internal title, UI might override
|
|
1039
1554
|
rows: [
|
|
1040
1555
|
{
|
|
1041
1556
|
id: 'ai-cred-row-1',
|
|
@@ -1048,7 +1563,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1048
1563
|
},
|
|
1049
1564
|
{
|
|
1050
1565
|
id: 'ai-model',
|
|
1051
|
-
title: '
|
|
1566
|
+
title: tx('Model & Behavior'),
|
|
1052
1567
|
rows: [
|
|
1053
1568
|
{
|
|
1054
1569
|
id: 'ai-mod-row-1',
|
|
@@ -1061,7 +1576,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1061
1576
|
},
|
|
1062
1577
|
{
|
|
1063
1578
|
id: 'ai-embedding',
|
|
1064
|
-
title: 'Embeddings',
|
|
1579
|
+
title: tx('Embeddings (RAG)'),
|
|
1065
1580
|
rows: [
|
|
1066
1581
|
{
|
|
1067
1582
|
id: 'ai-embed-row-1',
|
|
@@ -1075,7 +1590,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1075
1590
|
},
|
|
1076
1591
|
{
|
|
1077
1592
|
id: 'cache',
|
|
1078
|
-
title: 'Cache & Persistência',
|
|
1593
|
+
title: tx('Cache & Persistência'),
|
|
1079
1594
|
rows: [
|
|
1080
1595
|
{
|
|
1081
1596
|
id: 'cache-row-1',
|
|
@@ -1087,7 +1602,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1087
1602
|
},
|
|
1088
1603
|
{
|
|
1089
1604
|
id: 'table',
|
|
1090
|
-
title: 'Tabela',
|
|
1605
|
+
title: tx('Tabela'),
|
|
1091
1606
|
rows: [
|
|
1092
1607
|
{
|
|
1093
1608
|
id: 'tbl-row-1',
|
|
@@ -1148,7 +1663,7 @@ function buildGlobalConfigFormConfig() {
|
|
|
1148
1663
|
},
|
|
1149
1664
|
{
|
|
1150
1665
|
id: 'dialog',
|
|
1151
|
-
title: 'Dialog',
|
|
1666
|
+
title: tx('Dialog'),
|
|
1152
1667
|
rows: [
|
|
1153
1668
|
{
|
|
1154
1669
|
id: 'dlg-row-defaults',
|
|
@@ -1273,9 +1788,9 @@ function buildGlobalConfigFormConfig() {
|
|
|
1273
1788
|
actions: {
|
|
1274
1789
|
placement: 'afterSections',
|
|
1275
1790
|
// Hide internal form actions; Settings Panel footer handles Apply/Save
|
|
1276
|
-
submit: { visible: false, label: 'Salvar' },
|
|
1277
|
-
cancel: { visible: false, label: 'Cancelar' },
|
|
1278
|
-
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' },
|
|
1279
1794
|
},
|
|
1280
1795
|
fieldMetadata: fields,
|
|
1281
1796
|
};
|
|
@@ -1301,10 +1816,10 @@ const TABLE_COMPACT_FONT_SIZE_PATHS = new Set([
|
|
|
1301
1816
|
'table.appearance.typography.headerFontSize',
|
|
1302
1817
|
]);
|
|
1303
1818
|
const TABLE_COMPACT_FIELD_LABELS = {
|
|
1304
|
-
'table.appearance.spacing.cellPadding': 'padding
|
|
1305
|
-
'table.appearance.spacing.headerPadding': 'padding
|
|
1306
|
-
'table.appearance.typography.fontSize': '
|
|
1307
|
-
'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',
|
|
1308
1823
|
};
|
|
1309
1824
|
const TABLE_COMPACT_LENGTH_TOKEN = '(?:0|(?:\\d+|\\d*\\.\\d+)(?:px|rem|em|%|vh|vw|svh|svw|lvh|lvw|dvh|dvw|ch|ex))';
|
|
1310
1825
|
const TABLE_COMPACT_SPACING_REGEX = new RegExp(`^(?:var\\(.+\\)|calc\\(.+\\)|${TABLE_COMPACT_LENGTH_TOKEN}(?:\\s+${TABLE_COMPACT_LENGTH_TOKEN}){0,3})$`, 'i');
|
|
@@ -1331,6 +1846,7 @@ class GlobalConfigEditorComponent {
|
|
|
1331
1846
|
hostAiModel;
|
|
1332
1847
|
hostAiEmbedding;
|
|
1333
1848
|
destroyRef = inject(DestroyRef);
|
|
1849
|
+
i18n = inject(PraxisI18nService);
|
|
1334
1850
|
iconPicker = inject(IconPickerService);
|
|
1335
1851
|
aiApi = inject(AiBackendApiService);
|
|
1336
1852
|
cdr = inject(ChangeDetectorRef);
|
|
@@ -1364,7 +1880,7 @@ class GlobalConfigEditorComponent {
|
|
|
1364
1880
|
apiKeyLast4 = null;
|
|
1365
1881
|
hasStoredApiKey = false;
|
|
1366
1882
|
hasStoredGlobalConfig = false;
|
|
1367
|
-
configSourceLabel = '
|
|
1883
|
+
configSourceLabel = this.tx('Server defaults (env vars)');
|
|
1368
1884
|
// UX: API Key monitoring
|
|
1369
1885
|
apiKeyChanged$ = new Subject();
|
|
1370
1886
|
hasApiKey = false;
|
|
@@ -1376,12 +1892,12 @@ class GlobalConfigEditorComponent {
|
|
|
1376
1892
|
get apiKeyStatusLabel() {
|
|
1377
1893
|
const apiKey = this.currentValues?.[this.safeName('ai.apiKey')] || '';
|
|
1378
1894
|
if (apiKey)
|
|
1379
|
-
return '
|
|
1895
|
+
return this.tx('Key provided');
|
|
1380
1896
|
if (this.apiKeyLast4)
|
|
1381
|
-
return
|
|
1897
|
+
return this.tx('Saved key (****{{last4}})', { last4: this.apiKeyLast4 });
|
|
1382
1898
|
if (this.hasStoredApiKey)
|
|
1383
|
-
return '
|
|
1384
|
-
return '
|
|
1899
|
+
return this.tx('Saved key');
|
|
1900
|
+
return this.tx('No saved key');
|
|
1385
1901
|
}
|
|
1386
1902
|
constructor(admin, snack) {
|
|
1387
1903
|
this.admin = admin;
|
|
@@ -1390,7 +1906,7 @@ class GlobalConfigEditorComponent {
|
|
|
1390
1906
|
async ngOnInit() {
|
|
1391
1907
|
const cfg = this.admin.getEffectiveConfig();
|
|
1392
1908
|
const flat = this.flatten(cfg);
|
|
1393
|
-
this.formConfig = buildGlobalConfigFormConfig();
|
|
1909
|
+
this.formConfig = buildGlobalConfigFormConfig(this.tx.bind(this));
|
|
1394
1910
|
this.applyConfigSnapshot(flat, { resetForms: false });
|
|
1395
1911
|
await this.loadProviderCatalog();
|
|
1396
1912
|
this.applyProviderOptions();
|
|
@@ -1535,7 +2051,7 @@ class GlobalConfigEditorComponent {
|
|
|
1535
2051
|
const ref = g.host.createComponent(this.dynamicFormCtor);
|
|
1536
2052
|
ref.setInput('config', g.cfg);
|
|
1537
2053
|
ref.setInput('mode', 'edit');
|
|
1538
|
-
// 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
|
|
1539
2055
|
ref.setInput('enableCustomization', false);
|
|
1540
2056
|
const inst = ref.instance;
|
|
1541
2057
|
// FORÇAR estado de sucesso para renderizar o formulário sem resourcePath
|
|
@@ -1608,7 +2124,7 @@ class GlobalConfigEditorComponent {
|
|
|
1608
2124
|
{
|
|
1609
2125
|
id: 'gemini',
|
|
1610
2126
|
label: 'Google Gemini',
|
|
1611
|
-
description: '
|
|
2127
|
+
description: this.tx('Fast multimodal models from Google.'),
|
|
1612
2128
|
defaultModel: 'gemini-2.0-flash',
|
|
1613
2129
|
requiresApiKey: true,
|
|
1614
2130
|
supportsModels: true,
|
|
@@ -1618,7 +2134,7 @@ class GlobalConfigEditorComponent {
|
|
|
1618
2134
|
{
|
|
1619
2135
|
id: 'openai',
|
|
1620
2136
|
label: 'OpenAI',
|
|
1621
|
-
description: '
|
|
2137
|
+
description: this.tx('GPT models for text and chat.'),
|
|
1622
2138
|
defaultModel: 'gpt-4o-mini',
|
|
1623
2139
|
requiresApiKey: true,
|
|
1624
2140
|
supportsModels: true,
|
|
@@ -1628,7 +2144,7 @@ class GlobalConfigEditorComponent {
|
|
|
1628
2144
|
{
|
|
1629
2145
|
id: 'xai',
|
|
1630
2146
|
label: 'xAI (Grok)',
|
|
1631
|
-
description: '
|
|
2147
|
+
description: this.tx('Grok models focused on reasoning.'),
|
|
1632
2148
|
defaultModel: 'grok-2-latest',
|
|
1633
2149
|
requiresApiKey: true,
|
|
1634
2150
|
supportsModels: true,
|
|
@@ -1638,7 +2154,7 @@ class GlobalConfigEditorComponent {
|
|
|
1638
2154
|
{
|
|
1639
2155
|
id: 'mock',
|
|
1640
2156
|
label: 'Mock (dev)',
|
|
1641
|
-
description: '
|
|
2157
|
+
description: this.tx('Local mode for tests without a key.'),
|
|
1642
2158
|
defaultModel: 'mock-default',
|
|
1643
2159
|
requiresApiKey: false,
|
|
1644
2160
|
supportsModels: true,
|
|
@@ -1827,8 +2343,8 @@ class GlobalConfigEditorComponent {
|
|
|
1827
2343
|
this.hasStoredGlobalConfig = false;
|
|
1828
2344
|
}
|
|
1829
2345
|
this.configSourceLabel = this.hasStoredGlobalConfig
|
|
1830
|
-
? '
|
|
1831
|
-
: '
|
|
2346
|
+
? this.tx('Saved configuration (UI) - overrides server defaults')
|
|
2347
|
+
: this.tx('Server defaults (env vars)');
|
|
1832
2348
|
}
|
|
1833
2349
|
async clearStoredConfig() {
|
|
1834
2350
|
if (this.isClearingGlobalConfig)
|
|
@@ -1843,13 +2359,13 @@ class GlobalConfigEditorComponent {
|
|
|
1843
2359
|
this.refreshAiStateAfterConfig();
|
|
1844
2360
|
await this.refreshStoredConfigState();
|
|
1845
2361
|
try {
|
|
1846
|
-
this.snack.open('
|
|
2362
|
+
this.snack.open(this.tx('Global config cleared. Using server defaults.'), undefined, { duration: 2500 });
|
|
1847
2363
|
}
|
|
1848
2364
|
catch { }
|
|
1849
2365
|
}
|
|
1850
2366
|
catch (err) {
|
|
1851
2367
|
try {
|
|
1852
|
-
this.snack.open('
|
|
2368
|
+
this.snack.open(this.tx('Failed to clear global config.'), undefined, { duration: 4000 });
|
|
1853
2369
|
}
|
|
1854
2370
|
catch { }
|
|
1855
2371
|
}
|
|
@@ -1976,10 +2492,10 @@ class GlobalConfigEditorComponent {
|
|
|
1976
2492
|
const model = this.availableModels.find(m => m.name.endsWith(modelName));
|
|
1977
2493
|
if (model) {
|
|
1978
2494
|
const formatLimit = (n) => n ? (n >= 1000 ? (n / 1000).toFixed(0) + 'k' : n) : 'N/A';
|
|
1979
|
-
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' });
|
|
1980
2496
|
}
|
|
1981
2497
|
else {
|
|
1982
|
-
this.selectedModelDetails = '
|
|
2498
|
+
this.selectedModelDetails = this.tx('No model details available.');
|
|
1983
2499
|
}
|
|
1984
2500
|
}
|
|
1985
2501
|
// SettingsPanel expects these methods
|
|
@@ -2015,7 +2531,7 @@ class GlobalConfigEditorComponent {
|
|
|
2015
2531
|
this.initialValues = { ...this.currentValues };
|
|
2016
2532
|
this.isDirty$.next(false);
|
|
2017
2533
|
try {
|
|
2018
|
-
this.snack.open('
|
|
2534
|
+
this.snack.open(this.tx('Settings saved'), undefined, { duration: 2000 });
|
|
2019
2535
|
}
|
|
2020
2536
|
catch { }
|
|
2021
2537
|
return partial;
|
|
@@ -2038,7 +2554,7 @@ class GlobalConfigEditorComponent {
|
|
|
2038
2554
|
const meta = this.findProvider(provider);
|
|
2039
2555
|
if (meta?.supportsModels === false) {
|
|
2040
2556
|
if (!silent) {
|
|
2041
|
-
this.aiTestResult = { success: false, message: '
|
|
2557
|
+
this.aiTestResult = { success: false, message: this.tx('This provider has no model catalog.') };
|
|
2042
2558
|
this.cdr.detectChanges();
|
|
2043
2559
|
}
|
|
2044
2560
|
return;
|
|
@@ -2046,7 +2562,7 @@ class GlobalConfigEditorComponent {
|
|
|
2046
2562
|
const requiresKey = meta?.requiresApiKey !== false;
|
|
2047
2563
|
const hasKey = !!apiKey || this.hasStoredApiKey || !requiresKey;
|
|
2048
2564
|
if (requiresKey && !hasKey) {
|
|
2049
|
-
this.aiTestResult = { success: false, message: '
|
|
2565
|
+
this.aiTestResult = { success: false, message: this.tx('Enter an API key to fetch models.') };
|
|
2050
2566
|
this.cdr.detectChanges();
|
|
2051
2567
|
return;
|
|
2052
2568
|
}
|
|
@@ -2061,8 +2577,7 @@ class GlobalConfigEditorComponent {
|
|
|
2061
2577
|
request.apiKey = apiKey;
|
|
2062
2578
|
const response = await firstValueFrom(this.aiApi.listModels(request));
|
|
2063
2579
|
if (!response?.success) {
|
|
2064
|
-
|
|
2065
|
-
throw new Error(msg);
|
|
2580
|
+
throw new Error(this.tx('Error fetching models.'));
|
|
2066
2581
|
}
|
|
2067
2582
|
const models = response.models || [];
|
|
2068
2583
|
this.availableModels = models; // Store available models
|
|
@@ -2083,9 +2598,9 @@ class GlobalConfigEditorComponent {
|
|
|
2083
2598
|
}
|
|
2084
2599
|
catch (error) {
|
|
2085
2600
|
this.logger.error('[GlobalConfigEditor] Error fetching models', this.buildLogOptions({ error, provider }, { context: { actionId: 'models.fetch' } }));
|
|
2086
|
-
this.aiTestResult = { success: false, message:
|
|
2601
|
+
this.aiTestResult = { success: false, message: this.tx('Error fetching models.') };
|
|
2087
2602
|
if (!silent) {
|
|
2088
|
-
this.snack.open('
|
|
2603
|
+
this.snack.open(this.tx('Error fetching models. Check your API key.'), this.tx('Close'), { duration: 5000 });
|
|
2089
2604
|
}
|
|
2090
2605
|
}
|
|
2091
2606
|
finally {
|
|
@@ -2115,7 +2630,7 @@ class GlobalConfigEditorComponent {
|
|
|
2115
2630
|
this.recreateAiModelForm();
|
|
2116
2631
|
if (!silent) {
|
|
2117
2632
|
try {
|
|
2118
|
-
this.snack.open(
|
|
2633
|
+
this.snack.open(this.tx('Model list updated ({{count}} models)', { count: modelOptions.length }), undefined, { duration: 3000 });
|
|
2119
2634
|
}
|
|
2120
2635
|
catch { }
|
|
2121
2636
|
}
|
|
@@ -2133,7 +2648,7 @@ class GlobalConfigEditorComponent {
|
|
|
2133
2648
|
const requiresKey = meta?.requiresApiKey !== false;
|
|
2134
2649
|
const hasKey = !!apiKey || this.hasStoredApiKey || !requiresKey;
|
|
2135
2650
|
if (requiresKey && !hasKey) {
|
|
2136
|
-
this.aiTestResult = { success: false, message: '
|
|
2651
|
+
this.aiTestResult = { success: false, message: this.tx('Enter an API key to test.') };
|
|
2137
2652
|
this.isTestingAi = false;
|
|
2138
2653
|
this.cdr.detectChanges();
|
|
2139
2654
|
return;
|
|
@@ -2144,17 +2659,16 @@ class GlobalConfigEditorComponent {
|
|
|
2144
2659
|
request.apiKey = apiKey;
|
|
2145
2660
|
const response = await firstValueFrom(this.aiApi.testProvider(request));
|
|
2146
2661
|
if (!response?.success) {
|
|
2147
|
-
throw new Error(
|
|
2662
|
+
throw new Error(this.tx('Failed to test connection.'));
|
|
2148
2663
|
}
|
|
2149
|
-
this.aiTestResult = { success: true, message:
|
|
2664
|
+
this.aiTestResult = { success: true, message: this.tx('Connection established successfully!') };
|
|
2150
2665
|
this.hasApiKey = true; // Garantir desbloqueio da seção de modelo após sucesso
|
|
2151
2666
|
// Após validar a chave, já buscar a lista de modelos para preencher o select
|
|
2152
2667
|
await this.refreshModels(true);
|
|
2153
2668
|
}
|
|
2154
2669
|
catch (err) {
|
|
2155
2670
|
this.logger.error('[GlobalConfigEditor] AI Connection Test Error', this.buildLogOptions({ error: err, provider, model: selectedModel }, { context: { actionId: 'provider.test-connection' } }));
|
|
2156
|
-
|
|
2157
|
-
this.aiTestResult = { success: false, message: msg };
|
|
2671
|
+
this.aiTestResult = { success: false, message: this.tx('Failed to test connection.') };
|
|
2158
2672
|
}
|
|
2159
2673
|
finally {
|
|
2160
2674
|
this.isTestingAi = false;
|
|
@@ -2175,6 +2689,10 @@ class GlobalConfigEditorComponent {
|
|
|
2175
2689
|
safeName(path) {
|
|
2176
2690
|
return path.replace(/[^a-zA-Z0-9_]/g, '_');
|
|
2177
2691
|
}
|
|
2692
|
+
tx(text, params) {
|
|
2693
|
+
const normalized = normalizeMojibakeText(text);
|
|
2694
|
+
return this.i18n.t(normalized, params, normalized, PRAXIS_SETTINGS_PANEL_I18N_NAMESPACE);
|
|
2695
|
+
}
|
|
2178
2696
|
buildChangedValues() {
|
|
2179
2697
|
const out = {};
|
|
2180
2698
|
for (const [safe, value] of Object.entries(this.currentValues)) {
|
|
@@ -2199,21 +2717,7 @@ class GlobalConfigEditorComponent {
|
|
|
2199
2717
|
return initial !== current;
|
|
2200
2718
|
}
|
|
2201
2719
|
resolveSaveErrorMessage(err) {
|
|
2202
|
-
|
|
2203
|
-
const details = err?.error?.details;
|
|
2204
|
-
if (apiMessage && apiMessage.trim()) {
|
|
2205
|
-
return apiMessage;
|
|
2206
|
-
}
|
|
2207
|
-
if (details && typeof details === 'object') {
|
|
2208
|
-
const first = Object.values(details).find((v) => typeof v === 'string' && v.trim());
|
|
2209
|
-
if (typeof first === 'string') {
|
|
2210
|
-
return first;
|
|
2211
|
-
}
|
|
2212
|
-
}
|
|
2213
|
-
if (typeof err?.message === 'string' && err.message.trim()) {
|
|
2214
|
-
return err.message;
|
|
2215
|
-
}
|
|
2216
|
-
return 'Falha ao salvar configurações.';
|
|
2720
|
+
return this.tx('Save failed.');
|
|
2217
2721
|
}
|
|
2218
2722
|
normalizeFieldValue(path, value) {
|
|
2219
2723
|
if (typeof value !== 'string')
|
|
@@ -2260,7 +2764,7 @@ class GlobalConfigEditorComponent {
|
|
|
2260
2764
|
if (!normalized)
|
|
2261
2765
|
continue;
|
|
2262
2766
|
if (!check.regex.test(normalized)) {
|
|
2263
|
-
return `
|
|
2767
|
+
return `Invalid value in ${TABLE_COMPACT_FIELD_LABELS[check.path]}. Use a simple CSS string, such as ${check.example}.`;
|
|
2264
2768
|
}
|
|
2265
2769
|
}
|
|
2266
2770
|
return null;
|
|
@@ -2370,9 +2874,9 @@ class GlobalConfigEditorComponent {
|
|
|
2370
2874
|
<mat-expansion-panel-header>
|
|
2371
2875
|
<mat-panel-title>
|
|
2372
2876
|
<mat-icon class="panel-icon">construction</mat-icon>
|
|
2373
|
-
CRUD
|
|
2877
|
+
{{ tx('CRUD') }}
|
|
2374
2878
|
</mat-panel-title>
|
|
2375
|
-
<mat-panel-description>
|
|
2879
|
+
<mat-panel-description>{{ tx('Global policies for opening, back and header') }}</mat-panel-description>
|
|
2376
2880
|
</mat-expansion-panel-header>
|
|
2377
2881
|
<ng-template #hostCrud></ng-template>
|
|
2378
2882
|
</mat-expansion-panel>
|
|
@@ -2380,9 +2884,9 @@ class GlobalConfigEditorComponent {
|
|
|
2380
2884
|
<mat-expansion-panel-header>
|
|
2381
2885
|
<mat-panel-title>
|
|
2382
2886
|
<mat-icon class="panel-icon">dynamic_form</mat-icon>
|
|
2383
|
-
Dynamic Fields
|
|
2887
|
+
{{ tx('Dynamic Fields') }}
|
|
2384
2888
|
</mat-panel-title>
|
|
2385
|
-
<mat-panel-description>Async Select,
|
|
2889
|
+
<mat-panel-description>{{ tx('Async Select, cascade and pagination') }}</mat-panel-description>
|
|
2386
2890
|
</mat-expansion-panel-header>
|
|
2387
2891
|
<ng-template #hostFields></ng-template>
|
|
2388
2892
|
</mat-expansion-panel>
|
|
@@ -2390,9 +2894,9 @@ class GlobalConfigEditorComponent {
|
|
|
2390
2894
|
<mat-expansion-panel-header>
|
|
2391
2895
|
<mat-panel-title>
|
|
2392
2896
|
<mat-icon class="panel-icon">cached</mat-icon>
|
|
2393
|
-
Cache &
|
|
2897
|
+
{{ tx('Cache & Persistence') }}
|
|
2394
2898
|
</mat-panel-title>
|
|
2395
|
-
<mat-panel-description>
|
|
2899
|
+
<mat-panel-description>{{ tx('Schema cache strategy (local vs server)') }}</mat-panel-description>
|
|
2396
2900
|
</mat-expansion-panel-header>
|
|
2397
2901
|
<ng-template #hostCache></ng-template>
|
|
2398
2902
|
</mat-expansion-panel>
|
|
@@ -2400,9 +2904,9 @@ class GlobalConfigEditorComponent {
|
|
|
2400
2904
|
<mat-expansion-panel-header>
|
|
2401
2905
|
<mat-panel-title>
|
|
2402
2906
|
<mat-icon class="panel-icon">psychology</mat-icon>
|
|
2403
|
-
|
|
2907
|
+
{{ tx('Artificial Intelligence') }}
|
|
2404
2908
|
</mat-panel-title>
|
|
2405
|
-
<mat-panel-description>
|
|
2909
|
+
<mat-panel-description>{{ tx('LLM integration') }}</mat-panel-description>
|
|
2406
2910
|
</mat-expansion-panel-header>
|
|
2407
2911
|
|
|
2408
2912
|
<div class="ai-config-container">
|
|
@@ -2411,23 +2915,23 @@ class GlobalConfigEditorComponent {
|
|
|
2411
2915
|
<mat-icon>settings_suggest</mat-icon>
|
|
2412
2916
|
<span>{{ configSourceLabel }}</span>
|
|
2413
2917
|
</div>
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
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')"
|
|
2423
2927
|
>
|
|
2424
2928
|
<ng-container *ngIf="isClearingGlobalConfig; else clearContent">
|
|
2425
2929
|
<mat-spinner diameter="16" class="btn-spinner"></mat-spinner>
|
|
2426
|
-
<span class="ai-action-label">
|
|
2930
|
+
<span class="ai-action-label">{{ tx('Clearing...') }}</span>
|
|
2427
2931
|
</ng-container>
|
|
2428
2932
|
<ng-template #clearContent>
|
|
2429
2933
|
<mat-icon>delete_sweep</mat-icon>
|
|
2430
|
-
<span class="ai-action-label">
|
|
2934
|
+
<span class="ai-action-label">{{ tx('Clear saved config') }}</span>
|
|
2431
2935
|
</ng-template>
|
|
2432
2936
|
</button>
|
|
2433
2937
|
</div>
|
|
@@ -2435,7 +2939,7 @@ class GlobalConfigEditorComponent {
|
|
|
2435
2939
|
<div class="ai-group">
|
|
2436
2940
|
<div class="ai-group-header">
|
|
2437
2941
|
<div class="ai-group-title">
|
|
2438
|
-
<mat-icon>vpn_key</mat-icon>
|
|
2942
|
+
<mat-icon>vpn_key</mat-icon> {{ tx('Credentials') }}
|
|
2439
2943
|
</div>
|
|
2440
2944
|
<button mat-stroked-button
|
|
2441
2945
|
type="button"
|
|
@@ -2444,15 +2948,15 @@ class GlobalConfigEditorComponent {
|
|
|
2444
2948
|
[attr.aria-busy]="isTestingAi ? 'true' : null"
|
|
2445
2949
|
(click)="testAiConnection()"
|
|
2446
2950
|
[disabled]="isTestingAi || !hasApiKey"
|
|
2447
|
-
matTooltip="
|
|
2951
|
+
[matTooltip]="tx('Test connection with the provided key')">
|
|
2448
2952
|
<ng-container *ngIf="isTestingAi; else btnContent">
|
|
2449
2953
|
<mat-spinner diameter="16" class="btn-spinner"></mat-spinner>
|
|
2450
|
-
<span class="ai-action-label">
|
|
2954
|
+
<span class="ai-action-label">{{ tx('Connecting...') }}</span>
|
|
2451
2955
|
</ng-container>
|
|
2452
2956
|
<ng-template #btnContent>
|
|
2453
2957
|
<mat-icon>{{ aiTestResult?.success ? 'check' : 'bolt' }}</mat-icon>
|
|
2454
2958
|
<span class="ai-action-label">
|
|
2455
|
-
{{ aiTestResult?.success ? '
|
|
2959
|
+
{{ aiTestResult?.success ? tx('Connected') : tx('Test connection') }}
|
|
2456
2960
|
</span>
|
|
2457
2961
|
</ng-template>
|
|
2458
2962
|
</button>
|
|
@@ -2494,7 +2998,7 @@ class GlobalConfigEditorComponent {
|
|
|
2494
2998
|
</div>
|
|
2495
2999
|
<div class="ai-provider-key is-unlocked" *ngIf="selectedProvider?.requiresApiKey === false">
|
|
2496
3000
|
<mat-icon>check_circle</mat-icon>
|
|
2497
|
-
<span>
|
|
3001
|
+
<span>{{ tx('No key required') }}</span>
|
|
2498
3002
|
</div>
|
|
2499
3003
|
</div>
|
|
2500
3004
|
<div class="ai-credentials-row">
|
|
@@ -2514,12 +3018,12 @@ class GlobalConfigEditorComponent {
|
|
|
2514
3018
|
<div class="ai-group" [class.disabled-group]="!hasApiKey">
|
|
2515
3019
|
<div class="ai-group-header">
|
|
2516
3020
|
<div class="ai-group-title">
|
|
2517
|
-
<mat-icon>smart_toy</mat-icon>
|
|
3021
|
+
<mat-icon>smart_toy</mat-icon> {{ tx('Model & Behavior') }}
|
|
2518
3022
|
</div>
|
|
2519
3023
|
<div class="ai-header-actions">
|
|
2520
|
-
<span class="ai-subtext" *ngIf="hasApiKey">
|
|
2521
|
-
<mat-chip-option *ngIf="!hasApiKey" disabled>
|
|
2522
|
-
<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')">
|
|
2523
3027
|
<mat-icon [class.spin]="isRefetchingModels">sync</mat-icon>
|
|
2524
3028
|
</button>
|
|
2525
3029
|
</div>
|
|
@@ -2538,7 +3042,7 @@ class GlobalConfigEditorComponent {
|
|
|
2538
3042
|
|
|
2539
3043
|
<div class="ai-placeholder" *ngIf="!hasApiKey">
|
|
2540
3044
|
<mat-icon>lock</mat-icon>
|
|
2541
|
-
<span>Configure
|
|
3045
|
+
<span>{{ tx('Configure and test your API key to unlock model selection.') }}</span>
|
|
2542
3046
|
</div>
|
|
2543
3047
|
</div>
|
|
2544
3048
|
|
|
@@ -2546,7 +3050,7 @@ class GlobalConfigEditorComponent {
|
|
|
2546
3050
|
<div class="ai-group">
|
|
2547
3051
|
<div class="ai-group-header">
|
|
2548
3052
|
<div class="ai-group-title">
|
|
2549
|
-
<mat-icon>scatter_plot</mat-icon> Embeddings (RAG)
|
|
3053
|
+
<mat-icon>scatter_plot</mat-icon> {{ tx('Embeddings (RAG)') }}
|
|
2550
3054
|
</div>
|
|
2551
3055
|
<div class="ai-header-actions">
|
|
2552
3056
|
<button
|
|
@@ -2555,19 +3059,19 @@ class GlobalConfigEditorComponent {
|
|
|
2555
3059
|
class="ai-action-btn"
|
|
2556
3060
|
(click)="useLlmForEmbeddings()"
|
|
2557
3061
|
[disabled]="!canUseLlmForEmbeddings"
|
|
2558
|
-
matTooltip="
|
|
3062
|
+
[matTooltip]="tx('Use the LLM provider and key for embeddings')"
|
|
2559
3063
|
>
|
|
2560
3064
|
<mat-icon>merge_type</mat-icon>
|
|
2561
|
-
<span class="ai-action-label">
|
|
3065
|
+
<span class="ai-action-label">{{ tx('Use the LLM provider and key for embeddings') }}</span>
|
|
2562
3066
|
</button>
|
|
2563
|
-
<mat-chip-option *ngIf="!canUseLlmForEmbeddings" disabled>
|
|
3067
|
+
<mat-chip-option *ngIf="!canUseLlmForEmbeddings" disabled>{{ tx('Provider has no embeddings') }}</mat-chip-option>
|
|
2564
3068
|
</div>
|
|
2565
3069
|
</div>
|
|
2566
3070
|
<div class="ai-subtext">
|
|
2567
|
-
Configure
|
|
3071
|
+
{{ tx('Configure the embeddings provider for vector search (templates and schemas).') }}
|
|
2568
3072
|
</div>
|
|
2569
3073
|
<div class="ai-subtext" *ngIf="embeddingUseSameAsLlm">
|
|
2570
|
-
|
|
3074
|
+
{{ tx('Synchronized with the LLM. The fields below follow the primary credential.') }}
|
|
2571
3075
|
</div>
|
|
2572
3076
|
<div class="ai-embedding-row">
|
|
2573
3077
|
<ng-template #hostAiEmbedding></ng-template>
|
|
@@ -2575,7 +3079,7 @@ class GlobalConfigEditorComponent {
|
|
|
2575
3079
|
<div class="ai-feedback ai-feedback--warn" *ngIf="embeddingDimensionMismatch">
|
|
2576
3080
|
<mat-icon>warning</mat-icon>
|
|
2577
3081
|
<span class="error-text">
|
|
2578
|
-
|
|
3082
|
+
{{ tx('Embedding dimension mismatch with database (768). Adjust to 768 or redo the migration.') }}
|
|
2579
3083
|
</span>
|
|
2580
3084
|
</div>
|
|
2581
3085
|
</div>
|
|
@@ -2586,9 +3090,9 @@ class GlobalConfigEditorComponent {
|
|
|
2586
3090
|
<mat-expansion-panel-header>
|
|
2587
3091
|
<mat-panel-title>
|
|
2588
3092
|
<mat-icon class="panel-icon">table_chart</mat-icon>
|
|
2589
|
-
|
|
3093
|
+
{{ tx('Table') }}
|
|
2590
3094
|
</mat-panel-title>
|
|
2591
|
-
<mat-panel-description>Toolbar,
|
|
3095
|
+
<mat-panel-description>{{ tx('Toolbar, appearance and advanced filter') }}</mat-panel-description>
|
|
2592
3096
|
</mat-expansion-panel-header>
|
|
2593
3097
|
<ng-template #hostTable></ng-template>
|
|
2594
3098
|
</mat-expansion-panel>
|
|
@@ -2596,27 +3100,27 @@ class GlobalConfigEditorComponent {
|
|
|
2596
3100
|
<mat-expansion-panel-header>
|
|
2597
3101
|
<mat-panel-title>
|
|
2598
3102
|
<mat-icon class="panel-icon">forum</mat-icon>
|
|
2599
|
-
Dialog
|
|
3103
|
+
{{ tx('Dialog') }}
|
|
2600
3104
|
</mat-panel-title>
|
|
2601
|
-
<mat-panel-description>Defaults
|
|
3105
|
+
<mat-panel-description>{{ tx('Defaults and variants (danger, info, success, question, error)') }}</mat-panel-description>
|
|
2602
3106
|
</mat-expansion-panel-header>
|
|
2603
3107
|
<ng-template #hostDialog></ng-template>
|
|
2604
3108
|
<!-- Icon UX helpers for Dialog variants -->
|
|
2605
3109
|
<div class="dlg-icon-helpers">
|
|
2606
|
-
<div class="dlg-icon-helpers__head"
|
|
3110
|
+
<div class="dlg-icon-helpers__head">{{ tx('Icons by profile (shortcuts)') }}</div>
|
|
2607
3111
|
<div class="dlg-icon-helpers__row" *ngFor="let k of dialogVariantKeys">
|
|
2608
3112
|
<div class="dlg-icon-helpers__label">{{ k }}</div>
|
|
2609
3113
|
<mat-icon aria-hidden="true" [praxisIcon]="getVariantIcon(k) || 'mi:help_outline'" class="dlg-icon-helpers__preview"></mat-icon>
|
|
2610
|
-
<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 })">
|
|
2611
3115
|
<mat-icon>search</mat-icon>
|
|
2612
|
-
|
|
3116
|
+
{{ tx('Pick icon') }}
|
|
2613
3117
|
</button>
|
|
2614
|
-
<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')">
|
|
2615
3119
|
<mat-icon>backspace</mat-icon>
|
|
2616
3120
|
</button>
|
|
2617
3121
|
<span class="dlg-icon-helpers__value" *ngIf="getVariantIcon(k)">{{ getVariantIcon(k) }}</span>
|
|
2618
3122
|
</div>
|
|
2619
|
-
<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>
|
|
2620
3124
|
</div>
|
|
2621
3125
|
</mat-expansion-panel>
|
|
2622
3126
|
</mat-accordion>
|
|
@@ -2630,9 +3134,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2630
3134
|
<mat-expansion-panel-header>
|
|
2631
3135
|
<mat-panel-title>
|
|
2632
3136
|
<mat-icon class="panel-icon">construction</mat-icon>
|
|
2633
|
-
CRUD
|
|
3137
|
+
{{ tx('CRUD') }}
|
|
2634
3138
|
</mat-panel-title>
|
|
2635
|
-
<mat-panel-description>
|
|
3139
|
+
<mat-panel-description>{{ tx('Global policies for opening, back and header') }}</mat-panel-description>
|
|
2636
3140
|
</mat-expansion-panel-header>
|
|
2637
3141
|
<ng-template #hostCrud></ng-template>
|
|
2638
3142
|
</mat-expansion-panel>
|
|
@@ -2640,9 +3144,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2640
3144
|
<mat-expansion-panel-header>
|
|
2641
3145
|
<mat-panel-title>
|
|
2642
3146
|
<mat-icon class="panel-icon">dynamic_form</mat-icon>
|
|
2643
|
-
Dynamic Fields
|
|
3147
|
+
{{ tx('Dynamic Fields') }}
|
|
2644
3148
|
</mat-panel-title>
|
|
2645
|
-
<mat-panel-description>Async Select,
|
|
3149
|
+
<mat-panel-description>{{ tx('Async Select, cascade and pagination') }}</mat-panel-description>
|
|
2646
3150
|
</mat-expansion-panel-header>
|
|
2647
3151
|
<ng-template #hostFields></ng-template>
|
|
2648
3152
|
</mat-expansion-panel>
|
|
@@ -2650,9 +3154,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2650
3154
|
<mat-expansion-panel-header>
|
|
2651
3155
|
<mat-panel-title>
|
|
2652
3156
|
<mat-icon class="panel-icon">cached</mat-icon>
|
|
2653
|
-
Cache &
|
|
3157
|
+
{{ tx('Cache & Persistence') }}
|
|
2654
3158
|
</mat-panel-title>
|
|
2655
|
-
<mat-panel-description>
|
|
3159
|
+
<mat-panel-description>{{ tx('Schema cache strategy (local vs server)') }}</mat-panel-description>
|
|
2656
3160
|
</mat-expansion-panel-header>
|
|
2657
3161
|
<ng-template #hostCache></ng-template>
|
|
2658
3162
|
</mat-expansion-panel>
|
|
@@ -2660,9 +3164,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2660
3164
|
<mat-expansion-panel-header>
|
|
2661
3165
|
<mat-panel-title>
|
|
2662
3166
|
<mat-icon class="panel-icon">psychology</mat-icon>
|
|
2663
|
-
|
|
3167
|
+
{{ tx('Artificial Intelligence') }}
|
|
2664
3168
|
</mat-panel-title>
|
|
2665
|
-
<mat-panel-description>
|
|
3169
|
+
<mat-panel-description>{{ tx('LLM integration') }}</mat-panel-description>
|
|
2666
3170
|
</mat-expansion-panel-header>
|
|
2667
3171
|
|
|
2668
3172
|
<div class="ai-config-container">
|
|
@@ -2671,23 +3175,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2671
3175
|
<mat-icon>settings_suggest</mat-icon>
|
|
2672
3176
|
<span>{{ configSourceLabel }}</span>
|
|
2673
3177
|
</div>
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
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')"
|
|
2683
3187
|
>
|
|
2684
3188
|
<ng-container *ngIf="isClearingGlobalConfig; else clearContent">
|
|
2685
3189
|
<mat-spinner diameter="16" class="btn-spinner"></mat-spinner>
|
|
2686
|
-
<span class="ai-action-label">
|
|
3190
|
+
<span class="ai-action-label">{{ tx('Clearing...') }}</span>
|
|
2687
3191
|
</ng-container>
|
|
2688
3192
|
<ng-template #clearContent>
|
|
2689
3193
|
<mat-icon>delete_sweep</mat-icon>
|
|
2690
|
-
<span class="ai-action-label">
|
|
3194
|
+
<span class="ai-action-label">{{ tx('Clear saved config') }}</span>
|
|
2691
3195
|
</ng-template>
|
|
2692
3196
|
</button>
|
|
2693
3197
|
</div>
|
|
@@ -2695,7 +3199,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2695
3199
|
<div class="ai-group">
|
|
2696
3200
|
<div class="ai-group-header">
|
|
2697
3201
|
<div class="ai-group-title">
|
|
2698
|
-
<mat-icon>vpn_key</mat-icon>
|
|
3202
|
+
<mat-icon>vpn_key</mat-icon> {{ tx('Credentials') }}
|
|
2699
3203
|
</div>
|
|
2700
3204
|
<button mat-stroked-button
|
|
2701
3205
|
type="button"
|
|
@@ -2704,15 +3208,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2704
3208
|
[attr.aria-busy]="isTestingAi ? 'true' : null"
|
|
2705
3209
|
(click)="testAiConnection()"
|
|
2706
3210
|
[disabled]="isTestingAi || !hasApiKey"
|
|
2707
|
-
matTooltip="
|
|
3211
|
+
[matTooltip]="tx('Test connection with the provided key')">
|
|
2708
3212
|
<ng-container *ngIf="isTestingAi; else btnContent">
|
|
2709
3213
|
<mat-spinner diameter="16" class="btn-spinner"></mat-spinner>
|
|
2710
|
-
<span class="ai-action-label">
|
|
3214
|
+
<span class="ai-action-label">{{ tx('Connecting...') }}</span>
|
|
2711
3215
|
</ng-container>
|
|
2712
3216
|
<ng-template #btnContent>
|
|
2713
3217
|
<mat-icon>{{ aiTestResult?.success ? 'check' : 'bolt' }}</mat-icon>
|
|
2714
3218
|
<span class="ai-action-label">
|
|
2715
|
-
{{ aiTestResult?.success ? '
|
|
3219
|
+
{{ aiTestResult?.success ? tx('Connected') : tx('Test connection') }}
|
|
2716
3220
|
</span>
|
|
2717
3221
|
</ng-template>
|
|
2718
3222
|
</button>
|
|
@@ -2754,7 +3258,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2754
3258
|
</div>
|
|
2755
3259
|
<div class="ai-provider-key is-unlocked" *ngIf="selectedProvider?.requiresApiKey === false">
|
|
2756
3260
|
<mat-icon>check_circle</mat-icon>
|
|
2757
|
-
<span>
|
|
3261
|
+
<span>{{ tx('No key required') }}</span>
|
|
2758
3262
|
</div>
|
|
2759
3263
|
</div>
|
|
2760
3264
|
<div class="ai-credentials-row">
|
|
@@ -2774,12 +3278,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2774
3278
|
<div class="ai-group" [class.disabled-group]="!hasApiKey">
|
|
2775
3279
|
<div class="ai-group-header">
|
|
2776
3280
|
<div class="ai-group-title">
|
|
2777
|
-
<mat-icon>smart_toy</mat-icon>
|
|
3281
|
+
<mat-icon>smart_toy</mat-icon> {{ tx('Model & Behavior') }}
|
|
2778
3282
|
</div>
|
|
2779
3283
|
<div class="ai-header-actions">
|
|
2780
|
-
<span class="ai-subtext" *ngIf="hasApiKey">
|
|
2781
|
-
<mat-chip-option *ngIf="!hasApiKey" disabled>
|
|
2782
|
-
<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')">
|
|
2783
3287
|
<mat-icon [class.spin]="isRefetchingModels">sync</mat-icon>
|
|
2784
3288
|
</button>
|
|
2785
3289
|
</div>
|
|
@@ -2798,7 +3302,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2798
3302
|
|
|
2799
3303
|
<div class="ai-placeholder" *ngIf="!hasApiKey">
|
|
2800
3304
|
<mat-icon>lock</mat-icon>
|
|
2801
|
-
<span>Configure
|
|
3305
|
+
<span>{{ tx('Configure and test your API key to unlock model selection.') }}</span>
|
|
2802
3306
|
</div>
|
|
2803
3307
|
</div>
|
|
2804
3308
|
|
|
@@ -2806,7 +3310,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2806
3310
|
<div class="ai-group">
|
|
2807
3311
|
<div class="ai-group-header">
|
|
2808
3312
|
<div class="ai-group-title">
|
|
2809
|
-
<mat-icon>scatter_plot</mat-icon> Embeddings (RAG)
|
|
3313
|
+
<mat-icon>scatter_plot</mat-icon> {{ tx('Embeddings (RAG)') }}
|
|
2810
3314
|
</div>
|
|
2811
3315
|
<div class="ai-header-actions">
|
|
2812
3316
|
<button
|
|
@@ -2815,19 +3319,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2815
3319
|
class="ai-action-btn"
|
|
2816
3320
|
(click)="useLlmForEmbeddings()"
|
|
2817
3321
|
[disabled]="!canUseLlmForEmbeddings"
|
|
2818
|
-
matTooltip="
|
|
3322
|
+
[matTooltip]="tx('Use the LLM provider and key for embeddings')"
|
|
2819
3323
|
>
|
|
2820
3324
|
<mat-icon>merge_type</mat-icon>
|
|
2821
|
-
<span class="ai-action-label">
|
|
3325
|
+
<span class="ai-action-label">{{ tx('Use the LLM provider and key for embeddings') }}</span>
|
|
2822
3326
|
</button>
|
|
2823
|
-
<mat-chip-option *ngIf="!canUseLlmForEmbeddings" disabled>
|
|
3327
|
+
<mat-chip-option *ngIf="!canUseLlmForEmbeddings" disabled>{{ tx('Provider has no embeddings') }}</mat-chip-option>
|
|
2824
3328
|
</div>
|
|
2825
3329
|
</div>
|
|
2826
3330
|
<div class="ai-subtext">
|
|
2827
|
-
Configure
|
|
3331
|
+
{{ tx('Configure the embeddings provider for vector search (templates and schemas).') }}
|
|
2828
3332
|
</div>
|
|
2829
3333
|
<div class="ai-subtext" *ngIf="embeddingUseSameAsLlm">
|
|
2830
|
-
|
|
3334
|
+
{{ tx('Synchronized with the LLM. The fields below follow the primary credential.') }}
|
|
2831
3335
|
</div>
|
|
2832
3336
|
<div class="ai-embedding-row">
|
|
2833
3337
|
<ng-template #hostAiEmbedding></ng-template>
|
|
@@ -2835,7 +3339,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2835
3339
|
<div class="ai-feedback ai-feedback--warn" *ngIf="embeddingDimensionMismatch">
|
|
2836
3340
|
<mat-icon>warning</mat-icon>
|
|
2837
3341
|
<span class="error-text">
|
|
2838
|
-
|
|
3342
|
+
{{ tx('Embedding dimension mismatch with database (768). Adjust to 768 or redo the migration.') }}
|
|
2839
3343
|
</span>
|
|
2840
3344
|
</div>
|
|
2841
3345
|
</div>
|
|
@@ -2846,9 +3350,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2846
3350
|
<mat-expansion-panel-header>
|
|
2847
3351
|
<mat-panel-title>
|
|
2848
3352
|
<mat-icon class="panel-icon">table_chart</mat-icon>
|
|
2849
|
-
|
|
3353
|
+
{{ tx('Table') }}
|
|
2850
3354
|
</mat-panel-title>
|
|
2851
|
-
<mat-panel-description>Toolbar,
|
|
3355
|
+
<mat-panel-description>{{ tx('Toolbar, appearance and advanced filter') }}</mat-panel-description>
|
|
2852
3356
|
</mat-expansion-panel-header>
|
|
2853
3357
|
<ng-template #hostTable></ng-template>
|
|
2854
3358
|
</mat-expansion-panel>
|
|
@@ -2856,27 +3360,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2856
3360
|
<mat-expansion-panel-header>
|
|
2857
3361
|
<mat-panel-title>
|
|
2858
3362
|
<mat-icon class="panel-icon">forum</mat-icon>
|
|
2859
|
-
Dialog
|
|
3363
|
+
{{ tx('Dialog') }}
|
|
2860
3364
|
</mat-panel-title>
|
|
2861
|
-
<mat-panel-description>Defaults
|
|
3365
|
+
<mat-panel-description>{{ tx('Defaults and variants (danger, info, success, question, error)') }}</mat-panel-description>
|
|
2862
3366
|
</mat-expansion-panel-header>
|
|
2863
3367
|
<ng-template #hostDialog></ng-template>
|
|
2864
3368
|
<!-- Icon UX helpers for Dialog variants -->
|
|
2865
3369
|
<div class="dlg-icon-helpers">
|
|
2866
|
-
<div class="dlg-icon-helpers__head"
|
|
3370
|
+
<div class="dlg-icon-helpers__head">{{ tx('Icons by profile (shortcuts)') }}</div>
|
|
2867
3371
|
<div class="dlg-icon-helpers__row" *ngFor="let k of dialogVariantKeys">
|
|
2868
3372
|
<div class="dlg-icon-helpers__label">{{ k }}</div>
|
|
2869
3373
|
<mat-icon aria-hidden="true" [praxisIcon]="getVariantIcon(k) || 'mi:help_outline'" class="dlg-icon-helpers__preview"></mat-icon>
|
|
2870
|
-
<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 })">
|
|
2871
3375
|
<mat-icon>search</mat-icon>
|
|
2872
|
-
|
|
3376
|
+
{{ tx('Pick icon') }}
|
|
2873
3377
|
</button>
|
|
2874
|
-
<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')">
|
|
2875
3379
|
<mat-icon>backspace</mat-icon>
|
|
2876
3380
|
</button>
|
|
2877
3381
|
<span class="dlg-icon-helpers__value" *ngIf="getVariantIcon(k)">{{ getVariantIcon(k) }}</span>
|
|
2878
3382
|
</div>
|
|
2879
|
-
<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>
|
|
2880
3384
|
</div>
|
|
2881
3385
|
</mat-expansion-panel>
|
|
2882
3386
|
</mat-accordion>
|
|
@@ -2915,7 +3419,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2915
3419
|
function openGlobalConfigEditor(settings, opts) {
|
|
2916
3420
|
settings.open({
|
|
2917
3421
|
id: opts?.id ?? 'global-config',
|
|
2918
|
-
title: opts?.title
|
|
3422
|
+
title: opts?.title,
|
|
2919
3423
|
titleIcon: opts?.titleIcon ?? 'tune',
|
|
2920
3424
|
content: { component: GlobalConfigEditorComponent, inputs: {} },
|
|
2921
3425
|
});
|
|
@@ -2959,5 +3463,5 @@ const SETTINGS_PANEL_AI_CAPABILITIES = {
|
|
|
2959
3463
|
* Generated bundle index. Do not edit.
|
|
2960
3464
|
*/
|
|
2961
3465
|
|
|
2962
|
-
export { GLOBAL_CONFIG_DYNAMIC_FORM_COMPONENT, GlobalConfigAdminService, GlobalConfigEditorComponent, SETTINGS_PANEL_AI_CAPABILITIES, SETTINGS_PANEL_DATA, SETTINGS_PANEL_REF, SettingsPanelComponent, SettingsPanelRef, SettingsPanelService, buildGlobalConfigFormConfig, openGlobalConfigEditor };
|
|
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 };
|
|
2963
3467
|
//# sourceMappingURL=praxisui-settings-panel.mjs.map
|