@trismegisto/spine 3.3.0 → 3.3.2
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.
- package/README.md +19 -11
- package/fesm2022/trismegisto-spine-audit.mjs +16 -12
- package/fesm2022/trismegisto-spine-audit.mjs.map +1 -1
- package/fesm2022/{trismegisto-spine-auto-service-auto-service-audit.component-tfGcVR3i.mjs → trismegisto-spine-auto-service-auto-service-audit.component-D8HUpZtA.mjs} +4 -4
- package/fesm2022/{trismegisto-spine-auto-service-auto-service-audit.component-tfGcVR3i.mjs.map → trismegisto-spine-auto-service-auto-service-audit.component-D8HUpZtA.mjs.map} +1 -1
- package/fesm2022/trismegisto-spine-auto-service-auto-service-client-picker.component-NawbfdLW.mjs +65 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service-client-picker.component-NawbfdLW.mjs.map +1 -0
- package/fesm2022/{trismegisto-spine-auto-service-auto-service-client.component-IATeedbr.mjs → trismegisto-spine-auto-service-auto-service-client.component-BAfeLyTB.mjs} +27 -19
- package/fesm2022/trismegisto-spine-auto-service-auto-service-client.component-BAfeLyTB.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service-groups.component-BYjIQ9ID.mjs +635 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service-groups.component-BYjIQ9ID.mjs.map +1 -0
- package/fesm2022/{trismegisto-spine-auto-service-auto-service-login-attempts.component-CRvxfSWD.mjs → trismegisto-spine-auto-service-auto-service-login-attempts.component-DoyhkSYc.mjs} +4 -4
- package/fesm2022/{trismegisto-spine-auto-service-auto-service-login-attempts.component-CRvxfSWD.mjs.map → trismegisto-spine-auto-service-auto-service-login-attempts.component-DoyhkSYc.mjs.map} +1 -1
- package/fesm2022/trismegisto-spine-auto-service-auto-service-news-page.component-CBemH4hr.mjs +432 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service-news-page.component-CBemH4hr.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service-ratings-page.component-C_THGTkw.mjs +769 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service-ratings-page.component-C_THGTkw.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service-suggestions-page.component-DIeunpQ9.mjs +2123 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service-suggestions-page.component-DIeunpQ9.mjs.map +1 -0
- package/fesm2022/{trismegisto-spine-auto-service-auto-service.component-DGrs_Jvw.mjs → trismegisto-spine-auto-service-auto-service.component-QsIQ61w2.mjs} +31 -23
- package/fesm2022/trismegisto-spine-auto-service-auto-service.component-QsIQ61w2.mjs.map +1 -0
- package/fesm2022/{trismegisto-spine-auto-service-client.usage-C_2zBCRN.mjs → trismegisto-spine-auto-service-client.usage-CJxn9Ysz.mjs} +5 -3
- package/fesm2022/trismegisto-spine-auto-service-client.usage-CJxn9Ysz.mjs.map +1 -0
- package/fesm2022/{trismegisto-spine-auto-service-groups.technical-9aPPulhy.mjs → trismegisto-spine-auto-service-groups.technical-_jQrg1Qh.mjs} +7 -5
- package/fesm2022/trismegisto-spine-auto-service-groups.technical-_jQrg1Qh.mjs.map +1 -0
- package/fesm2022/{trismegisto-spine-auto-service-groups.usage-CYh61LFL.mjs → trismegisto-spine-auto-service-groups.usage-OvWjNeeT.mjs} +7 -6
- package/fesm2022/{trismegisto-spine-auto-service-groups.usage-CYh61LFL.mjs.map → trismegisto-spine-auto-service-groups.usage-OvWjNeeT.mjs.map} +1 -1
- package/fesm2022/trismegisto-spine-auto-service-home.component-rQ3dIGIE.mjs +315 -0
- package/fesm2022/trismegisto-spine-auto-service-home.component-rQ3dIGIE.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service-home.technical-Ce7oYRdg.mjs +46 -0
- package/fesm2022/trismegisto-spine-auto-service-home.technical-Ce7oYRdg.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service-home.usage-D9R_ZMuU.mjs +48 -0
- package/fesm2022/trismegisto-spine-auto-service-home.usage-D9R_ZMuU.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service-news.technical-DV9UpobG.mjs +38 -0
- package/fesm2022/trismegisto-spine-auto-service-news.technical-DV9UpobG.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service-news.usage-CeuZnG0V.mjs +48 -0
- package/fesm2022/trismegisto-spine-auto-service-news.usage-CeuZnG0V.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service-ratings.technical-QIVj6HBU.mjs +52 -0
- package/fesm2022/trismegisto-spine-auto-service-ratings.technical-QIVj6HBU.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service-ratings.usage-BkteY8lz.mjs +45 -0
- package/fesm2022/trismegisto-spine-auto-service-ratings.usage-BkteY8lz.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service-suggestions.technical-BtUK6sKD.mjs +69 -0
- package/fesm2022/trismegisto-spine-auto-service-suggestions.technical-BtUK6sKD.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service-suggestions.usage-BwO9Hjsx.mjs +72 -0
- package/fesm2022/trismegisto-spine-auto-service-suggestions.usage-BwO9Hjsx.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service.mjs +49 -19
- package/fesm2022/trismegisto-spine-auto-service.mjs.map +1 -1
- package/fesm2022/trismegisto-spine-graphql.mjs +11 -2
- package/fesm2022/trismegisto-spine-graphql.mjs.map +1 -1
- package/fesm2022/trismegisto-spine-layout.mjs +3113 -1221
- package/fesm2022/trismegisto-spine-layout.mjs.map +1 -1
- package/fesm2022/trismegisto-spine-modal.mjs +7 -5
- package/fesm2022/trismegisto-spine-modal.mjs.map +1 -1
- package/fesm2022/trismegisto-spine-routing.mjs +12 -20
- package/fesm2022/trismegisto-spine-routing.mjs.map +1 -1
- package/fesm2022/trismegisto-spine-shell.mjs +15 -39
- package/fesm2022/trismegisto-spine-shell.mjs.map +1 -1
- package/fesm2022/trismegisto-spine-side-panel.mjs +7 -5
- package/fesm2022/trismegisto-spine-side-panel.mjs.map +1 -1
- package/fesm2022/trismegisto-spine.mjs +1969 -279
- package/fesm2022/trismegisto-spine.mjs.map +1 -1
- package/package.json +6 -6
- package/types/trismegisto-spine-audit.d.ts +2 -12
- package/types/trismegisto-spine-audit.d.ts.map +1 -1
- package/types/trismegisto-spine-auto-service.d.ts +22 -5
- package/types/trismegisto-spine-auto-service.d.ts.map +1 -1
- package/types/trismegisto-spine-layout.d.ts +1083 -283
- package/types/trismegisto-spine-layout.d.ts.map +1 -1
- package/types/trismegisto-spine-modal.d.ts +1 -0
- package/types/trismegisto-spine-modal.d.ts.map +1 -1
- package/types/trismegisto-spine-routing.d.ts +3 -12
- package/types/trismegisto-spine-routing.d.ts.map +1 -1
- package/types/trismegisto-spine-shell.d.ts +2 -15
- package/types/trismegisto-spine-shell.d.ts.map +1 -1
- package/types/trismegisto-spine-side-panel.d.ts +1 -0
- package/types/trismegisto-spine-side-panel.d.ts.map +1 -1
- package/types/trismegisto-spine.d.ts +739 -165
- package/types/trismegisto-spine.d.ts.map +1 -1
- package/fesm2022/trismegisto-spine-auto-service-auto-service-client-picker.component-Cl7ahisu.mjs +0 -65
- package/fesm2022/trismegisto-spine-auto-service-auto-service-client-picker.component-Cl7ahisu.mjs.map +0 -1
- package/fesm2022/trismegisto-spine-auto-service-auto-service-client.component-IATeedbr.mjs.map +0 -1
- package/fesm2022/trismegisto-spine-auto-service-auto-service-groups.component-D6L0gTmd.mjs +0 -605
- package/fesm2022/trismegisto-spine-auto-service-auto-service-groups.component-D6L0gTmd.mjs.map +0 -1
- package/fesm2022/trismegisto-spine-auto-service-auto-service.component-DGrs_Jvw.mjs.map +0 -1
- package/fesm2022/trismegisto-spine-auto-service-client.usage-C_2zBCRN.mjs.map +0 -1
- package/fesm2022/trismegisto-spine-auto-service-groups.technical-9aPPulhy.mjs.map +0 -1
- package/fesm2022/trismegisto-spine-auto-service-home.component-5_aji1hf.mjs +0 -239
- package/fesm2022/trismegisto-spine-auto-service-home.component-5_aji1hf.mjs.map +0 -1
- package/fesm2022/trismegisto-spine-auto-service-home.technical-BrVhcgDO.mjs +0 -35
- package/fesm2022/trismegisto-spine-auto-service-home.technical-BrVhcgDO.mjs.map +0 -1
- package/fesm2022/trismegisto-spine-auto-service-home.usage-DWYGtngX.mjs +0 -43
- package/fesm2022/trismegisto-spine-auto-service-home.usage-DWYGtngX.mjs.map +0 -1
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, Injectable, input, signal, computed, effect, untracked, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { A as AutoServiceClientPickerComponent } from './trismegisto-spine-auto-service-auto-service-client-picker.component-NawbfdLW.mjs';
|
|
4
|
+
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
|
|
5
|
+
import { HermesDialogService, AccountAvatarComponent, AlertComponent, ButtonComponent, ComboboxMultiComponent, DataGridComponent, DataGridCellDirective, DatePickerComponent, IconComponent, InputComponent, ListEditorComponent, ModalComponent, RichTextComponent, SegmentedControlComponent, TagComponent, TextareaComponent, TimePickerComponent } from '@trismegisto/angular';
|
|
6
|
+
import { urlPath, formatMessage } from '@trismegisto/primitives';
|
|
7
|
+
import { SPINE_MESSAGES } from '@trismegisto/spine';
|
|
8
|
+
import { A as AutoServiceDeleteFeedback } from './trismegisto-spine-auto-service-auto-service-delete-CV_t9vxm.mjs';
|
|
9
|
+
import { firstValueFrom } from 'rxjs';
|
|
10
|
+
import { AuthorizationService } from '@orfeu/angular/core';
|
|
11
|
+
import { AUTO_SERVICE_CONFIG } from './trismegisto-spine-auto-service.mjs';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Novidades do app no auto-serviço (`{adminApi}/auto-service/:clientId/news*`): o servidor recorta pelo client da URL
|
|
15
|
+
* e exige o grupo de administração com o crachá Administrador. Próprio da aba (o `AutoServiceService` é o das outras
|
|
16
|
+
* telas).
|
|
17
|
+
*/
|
|
18
|
+
class AutoServiceNewsService {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.http = inject(HttpClient);
|
|
21
|
+
this.auth = inject(AuthorizationService);
|
|
22
|
+
this.config = inject(AUTO_SERVICE_CONFIG);
|
|
23
|
+
}
|
|
24
|
+
url(clientId, rest = '') {
|
|
25
|
+
return `${this.config.adminApi}/auto-service${urlPath `/${clientId}`}/news${rest}`;
|
|
26
|
+
}
|
|
27
|
+
get headers() {
|
|
28
|
+
return new HttpHeaders({ 'x-access-token': this.auth.getToken() ?? '' });
|
|
29
|
+
}
|
|
30
|
+
list(clientId, page, limit) {
|
|
31
|
+
return firstValueFrom(this.http.get(this.url(clientId), { headers: this.headers, params: { page, limit } }));
|
|
32
|
+
}
|
|
33
|
+
get(clientId, newsId) {
|
|
34
|
+
return firstValueFrom(this.http.get(this.url(clientId, urlPath `/${newsId}`), { headers: this.headers }));
|
|
35
|
+
}
|
|
36
|
+
audience(clientId) {
|
|
37
|
+
return firstValueFrom(this.http.get(this.url(clientId, '/audience'), { headers: this.headers }));
|
|
38
|
+
}
|
|
39
|
+
create(clientId, body) {
|
|
40
|
+
return firstValueFrom(this.http.post(this.url(clientId), body, { headers: this.headers }));
|
|
41
|
+
}
|
|
42
|
+
update(clientId, newsId, body) {
|
|
43
|
+
return firstValueFrom(this.http.put(this.url(clientId, urlPath `/${newsId}`), body, { headers: this.headers }));
|
|
44
|
+
}
|
|
45
|
+
remove(clientId, newsId) {
|
|
46
|
+
return firstValueFrom(this.http.delete(this.url(clientId, urlPath `/${newsId}`), { headers: this.headers }));
|
|
47
|
+
}
|
|
48
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: AutoServiceNewsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
49
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: AutoServiceNewsService, providedIn: 'root' }); }
|
|
50
|
+
}
|
|
51
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: AutoServiceNewsService, decorators: [{
|
|
52
|
+
type: Injectable,
|
|
53
|
+
args: [{ providedIn: 'root' }]
|
|
54
|
+
}] });
|
|
55
|
+
|
|
56
|
+
const PAGE_SIZE = 20;
|
|
57
|
+
const TITLE_MAX = 140;
|
|
58
|
+
const SUMMARY_MAX = 300;
|
|
59
|
+
let sequence = 0;
|
|
60
|
+
/** Teto da lista de mudanças (implementação) e de cada item -- os mesmos do servidor. */
|
|
61
|
+
const ITEMS_MAX = 30;
|
|
62
|
+
const ITEM_MAX = 300;
|
|
63
|
+
/** Ícone de cada tipo (seletor do topo e prévia). */
|
|
64
|
+
const KIND_ICONS = {
|
|
65
|
+
informativo: 'file-text',
|
|
66
|
+
implementacao: 'rocket-diagonal',
|
|
67
|
+
alteracao: 'two-way-arrows',
|
|
68
|
+
};
|
|
69
|
+
/** HTML de rich text com texto de verdade (não só tags vazias). */
|
|
70
|
+
function newsHtmlHasText(html) {
|
|
71
|
+
return !!html && html.replace(/<[^>]*>/g, '').replace(/ | /g, ' ').trim() !== '';
|
|
72
|
+
}
|
|
73
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
74
|
+
/** Data e hora LOCAIS (do navegador) de um instante ISO, no formato dos campos (`AAAA-MM-DD`, `HH:mm`). */
|
|
75
|
+
function newsLocalParts(iso) {
|
|
76
|
+
const d = new Date(iso);
|
|
77
|
+
if (Number.isNaN(d.getTime()))
|
|
78
|
+
return { date: null, time: null };
|
|
79
|
+
return { date: `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`, time: `${pad(d.getHours())}:${pad(d.getMinutes())}` };
|
|
80
|
+
}
|
|
81
|
+
/** Instante ISO (UTC) da data e hora locais dos campos; sem data = null (o servidor publica ao salvar); sem hora = 00:00. */
|
|
82
|
+
function newsPublishedAt(date, time) {
|
|
83
|
+
if (!date)
|
|
84
|
+
return null;
|
|
85
|
+
const d = new Date(`${date}T${time || '00:00'}:00`);
|
|
86
|
+
return Number.isNaN(d.getTime()) ? null : d.toISOString();
|
|
87
|
+
}
|
|
88
|
+
/** Código do argos-admin (`{ error }`) → texto no idioma ativo; desconhecido, o `detail` do servidor ou `fallback`. */
|
|
89
|
+
function newsErrorText(err, text, fallback) {
|
|
90
|
+
if (!(err instanceof HttpErrorResponse))
|
|
91
|
+
return fallback;
|
|
92
|
+
const body = err.error;
|
|
93
|
+
const known = {
|
|
94
|
+
invalid_title: text.errors.invalidTitle,
|
|
95
|
+
invalid_summary: text.errors.invalidSummary,
|
|
96
|
+
body_too_large: text.errors.bodyTooLarge,
|
|
97
|
+
invalid_published_at: text.errors.invalidPublishedAt,
|
|
98
|
+
invalid_until: text.errors.invalidUntil,
|
|
99
|
+
invalid_group_ids: text.errors.invalidGroupIds,
|
|
100
|
+
invalid_kind: text.errors.invalidKind,
|
|
101
|
+
invalid_items: text.errors.invalidItems,
|
|
102
|
+
invalid_compare: text.errors.invalidCompare,
|
|
103
|
+
compare_too_large: text.errors.compareTooLarge,
|
|
104
|
+
};
|
|
105
|
+
const code = typeof body?.error === 'string' ? body.error : '';
|
|
106
|
+
if (Object.prototype.hasOwnProperty.call(known, code))
|
|
107
|
+
return known[code];
|
|
108
|
+
return typeof body?.detail === 'string' && body.detail ? body.detail : fallback;
|
|
109
|
+
}
|
|
110
|
+
const emptyForm = () => ({
|
|
111
|
+
kind: 'informativo', title: '', summary: '', body: '', items: [], before: '', after: '', publishDate: null, publishTime: null,
|
|
112
|
+
until: null, groupIds: [],
|
|
113
|
+
});
|
|
114
|
+
/**
|
|
115
|
+
* Aba Novidades do Cliente: o que o spine mostra em "Novidades" (menu do perfil, aviso da entrada, card do Início)
|
|
116
|
+
* para quem entra no app. Grade paginada no servidor (agendadas e vencidas também), criar/editar num modal e excluir
|
|
117
|
+
* com confirmação (no menu da linha ou no rodapé do modal, ao editar). O modal é um editor em seções numeradas
|
|
118
|
+
* (título e resumo, texto em rich text, publicação, validade e público) com a prévia ao vivo do card do Início ao
|
|
119
|
+
* lado. Sem rascunho: a novidade não tem esse estado (sem data, sai ao salvar). O texto é saneado pelo argos-admin ao
|
|
120
|
+
* gravar; o público vazio é todo mundo que entra no app.
|
|
121
|
+
*/
|
|
122
|
+
class AutoServiceNewsComponent {
|
|
123
|
+
/** Validade antes do dia da publicação: a novidade nunca apareceria. */
|
|
124
|
+
get untilBeforePublish() {
|
|
125
|
+
const publishDay = this.form.publishDate ?? newsLocalParts(new Date().toISOString()).date;
|
|
126
|
+
return !!this.form.until && !!publishDay && this.form.until < publishDay;
|
|
127
|
+
}
|
|
128
|
+
/** Data e hora da prévia: as dos campos; sem data, "ao salvar". */
|
|
129
|
+
get previewDate() {
|
|
130
|
+
const at = newsPublishedAt(this.form.publishDate, this.form.publishTime);
|
|
131
|
+
return at ? this.formatDate(at) : this.text.previewNow;
|
|
132
|
+
}
|
|
133
|
+
/** Publicação no futuro: a prévia marca "Agendada". */
|
|
134
|
+
get previewScheduled() {
|
|
135
|
+
const at = newsPublishedAt(this.form.publishDate, this.form.publishTime);
|
|
136
|
+
return !!at && new Date(at).getTime() > Date.now();
|
|
137
|
+
}
|
|
138
|
+
get canSave() {
|
|
139
|
+
const title = this.form.title.trim();
|
|
140
|
+
return !!title && title.length <= TITLE_MAX && this.form.summary.trim().length <= SUMMARY_MAX && !this.untilBeforePublish
|
|
141
|
+
&& this.kindReady;
|
|
142
|
+
}
|
|
143
|
+
/** O conteúdo do tipo está completo: a implementação com ao menos uma mudança; a alteração com o antes e o agora. */
|
|
144
|
+
get kindReady() {
|
|
145
|
+
if (this.form.kind === 'implementacao')
|
|
146
|
+
return this.form.items.length > 0 && this.form.items.length <= ITEMS_MAX;
|
|
147
|
+
if (this.form.kind === 'alteracao')
|
|
148
|
+
return newsHtmlHasText(this.form.before) && newsHtmlHasText(this.form.after);
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
get kindIcon() {
|
|
152
|
+
return KIND_ICONS[this.form.kind];
|
|
153
|
+
}
|
|
154
|
+
get kindLabel() {
|
|
155
|
+
return this.kindOptions.find((o) => o.value === this.form.kind)?.label ?? '';
|
|
156
|
+
}
|
|
157
|
+
setKind(kind) {
|
|
158
|
+
if (kind === 'informativo' || kind === 'implementacao' || kind === 'alteracao')
|
|
159
|
+
this.form = { ...this.form, kind };
|
|
160
|
+
this.saveError.set(null);
|
|
161
|
+
}
|
|
162
|
+
constructor() {
|
|
163
|
+
this.service = inject(AutoServiceNewsService);
|
|
164
|
+
this.deletion = inject(AutoServiceDeleteFeedback);
|
|
165
|
+
this.dialogs = inject(HermesDialogService);
|
|
166
|
+
this.text = inject(SPINE_MESSAGES).autoServiceNews;
|
|
167
|
+
this.common = inject(SPINE_MESSAGES).autoService;
|
|
168
|
+
/** Rótulos do card Novidades do Início, repetidos na prévia. */
|
|
169
|
+
this.home = inject(SPINE_MESSAGES).home;
|
|
170
|
+
this.uid = `spine-as-news-${++sequence}`;
|
|
171
|
+
this.dateFormat = new Intl.DateTimeFormat(inject(SPINE_MESSAGES).meta.locale, { dateStyle: 'short', timeStyle: 'short' });
|
|
172
|
+
this.dayFormat = new Intl.DateTimeFormat(inject(SPINE_MESSAGES).meta.locale, { dateStyle: 'short', timeZone: 'UTC' });
|
|
173
|
+
this.TITLE_MAX = TITLE_MAX;
|
|
174
|
+
this.SUMMARY_MAX = SUMMARY_MAX;
|
|
175
|
+
this.ITEMS_MAX = ITEMS_MAX;
|
|
176
|
+
/** Tipos do seletor do topo, com ícone. */
|
|
177
|
+
this.kindOptions = [
|
|
178
|
+
{ value: 'informativo', label: this.text.kindInformativo, icon: KIND_ICONS.informativo },
|
|
179
|
+
{ value: 'implementacao', label: this.text.kindImplementacao, icon: KIND_ICONS.implementacao },
|
|
180
|
+
{ value: 'alteracao', label: this.text.kindAlteracao, icon: KIND_ICONS.alteracao },
|
|
181
|
+
];
|
|
182
|
+
/** Cada mudança até 300 caracteres (o vazio e o repetido o próprio hm-list-editor recusa). */
|
|
183
|
+
this.itemRule = (item) => item.length > ITEM_MAX ? this.text.errors.invalidItems : null;
|
|
184
|
+
this.clientId = input('', ...(ngDevMode ? [{ debugName: "clientId" }] : /* istanbul ignore next */ []));
|
|
185
|
+
this.rows = signal([], ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
|
|
186
|
+
this.total = signal(0, ...(ngDevMode ? [{ debugName: "total" }] : /* istanbul ignore next */ []));
|
|
187
|
+
this.pageState = signal({ page: 1, size: PAGE_SIZE }, ...(ngDevMode ? [{ debugName: "pageState" }] : /* istanbul ignore next */ []));
|
|
188
|
+
this.loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
189
|
+
this.loadError = signal('', ...(ngDevMode ? [{ debugName: "loadError" }] : /* istanbul ignore next */ []));
|
|
190
|
+
this.audienceOptions = signal([], ...(ngDevMode ? [{ debugName: "audienceOptions" }] : /* istanbul ignore next */ []));
|
|
191
|
+
this.modalOpen = signal(false, ...(ngDevMode ? [{ debugName: "modalOpen" }] : /* istanbul ignore next */ []));
|
|
192
|
+
this.editingId = signal('', ...(ngDevMode ? [{ debugName: "editingId" }] : /* istanbul ignore next */ []));
|
|
193
|
+
this.form = emptyForm();
|
|
194
|
+
this.saving = signal(false, ...(ngDevMode ? [{ debugName: "saving" }] : /* istanbul ignore next */ []));
|
|
195
|
+
this.saveError = signal(null, ...(ngDevMode ? [{ debugName: "saveError" }] : /* istanbul ignore next */ []));
|
|
196
|
+
/** O texto da novidade em edição ainda está vindo (o editor espera). */
|
|
197
|
+
this.loadingBody = signal(false, ...(ngDevMode ? [{ debugName: "loadingBody" }] : /* istanbul ignore next */ []));
|
|
198
|
+
/** Excluindo pelo rodapé do modal. */
|
|
199
|
+
this.removing = signal(false, ...(ngDevMode ? [{ debugName: "removing" }] : /* istanbul ignore next */ []));
|
|
200
|
+
this.rowId = (n) => n.id;
|
|
201
|
+
this.columns = computed(() => [
|
|
202
|
+
{ key: 'title', title: this.text.colTitle, value: (n) => n.title },
|
|
203
|
+
{ key: 'status', title: this.text.colStatus, value: (n) => this.statusLabel(n.status) },
|
|
204
|
+
{ key: 'published_at', title: this.text.colPublishedAt, value: (n) => this.formatDate(n.published_at) },
|
|
205
|
+
{ key: 'until', title: this.text.colUntil, value: (n) => this.formatDay(n.until) },
|
|
206
|
+
{ key: 'groups', title: this.text.colAudience, value: (n) => n.groups.map((g) => g.name).join(', ') || this.text.audienceAll },
|
|
207
|
+
{ key: 'author', title: this.text.colAuthor, value: (n) => n.author?.name || n.author?.username || '' },
|
|
208
|
+
], ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
|
|
209
|
+
this.rowActions = computed(() => [
|
|
210
|
+
{ id: 'edit', icon: 'pencil', label: this.common.edit },
|
|
211
|
+
{
|
|
212
|
+
id: 'delete', icon: 'trash', label: this.common.delete, danger: true, separatorAbove: true,
|
|
213
|
+
confirm: (n) => ({ heading: this.text.confirmDeleteHeading, message: formatMessage(this.text.confirmDelete, { title: n.title }) }),
|
|
214
|
+
},
|
|
215
|
+
], ...(ngDevMode ? [{ debugName: "rowActions" }] : /* istanbul ignore next */ []));
|
|
216
|
+
effect(() => {
|
|
217
|
+
const id = this.clientId();
|
|
218
|
+
untracked(() => {
|
|
219
|
+
this.pageState.set({ page: 1, size: this.pageState().size });
|
|
220
|
+
void this.load();
|
|
221
|
+
void this.loadAudience(id);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
statusLabel(status) {
|
|
226
|
+
return status === 'scheduled' ? this.text.statusScheduled : status === 'expired' ? this.text.statusExpired : this.text.statusPublished;
|
|
227
|
+
}
|
|
228
|
+
statusColor(status) {
|
|
229
|
+
return status === 'scheduled' ? 'info' : status === 'expired' ? 'neutral' : 'success';
|
|
230
|
+
}
|
|
231
|
+
formatDate(iso) {
|
|
232
|
+
const d = new Date(iso);
|
|
233
|
+
return Number.isNaN(d.getTime()) ? '' : this.dateFormat.format(d);
|
|
234
|
+
}
|
|
235
|
+
/** `until` é um dia (AAAA-MM-DD), sem fuso: formatado em UTC para não mudar de dia. */
|
|
236
|
+
formatDay(day) {
|
|
237
|
+
if (!day)
|
|
238
|
+
return this.text.noUntil;
|
|
239
|
+
const d = new Date(`${day}T00:00:00Z`);
|
|
240
|
+
return Number.isNaN(d.getTime()) ? day : this.dayFormat.format(d);
|
|
241
|
+
}
|
|
242
|
+
async load(page = this.pageState().page, size = this.pageState().size) {
|
|
243
|
+
const clientId = this.clientId();
|
|
244
|
+
if (!clientId) {
|
|
245
|
+
this.rows.set([]);
|
|
246
|
+
this.total.set(0);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
this.loading.set(true);
|
|
250
|
+
this.loadError.set('');
|
|
251
|
+
try {
|
|
252
|
+
const res = await this.service.list(clientId, page, size);
|
|
253
|
+
this.rows.set(res.news ?? []);
|
|
254
|
+
this.total.set(res.total ?? 0);
|
|
255
|
+
this.pageState.set({ page, size });
|
|
256
|
+
}
|
|
257
|
+
catch (err) {
|
|
258
|
+
this.rows.set([]);
|
|
259
|
+
this.total.set(0);
|
|
260
|
+
this.loadError.set(newsErrorText(err, this.text, this.text.loadError));
|
|
261
|
+
}
|
|
262
|
+
finally {
|
|
263
|
+
this.loading.set(false);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
/** Sem a lista de público o campo fica sem opção (a novidade sai para todos). */
|
|
267
|
+
async loadAudience(clientId) {
|
|
268
|
+
if (!clientId) {
|
|
269
|
+
this.audienceOptions.set([]);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
try {
|
|
273
|
+
const res = await this.service.audience(clientId);
|
|
274
|
+
this.audienceOptions.set((res.groups ?? []).map((g) => ({ value: g.id, label: g.name })));
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
this.audienceOptions.set([]);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
onPageStateChange(state) {
|
|
281
|
+
void this.load(state.page, state.size);
|
|
282
|
+
}
|
|
283
|
+
openCreate() {
|
|
284
|
+
this.editingId.set('');
|
|
285
|
+
this.form = emptyForm();
|
|
286
|
+
this.saveError.set(null);
|
|
287
|
+
this.loadingBody.set(false);
|
|
288
|
+
this.removing.set(false);
|
|
289
|
+
this.modalOpen.set(true);
|
|
290
|
+
}
|
|
291
|
+
/** O corpo não vem na lista: busca o detalhe antes de liberar o editor. */
|
|
292
|
+
async openEdit(row) {
|
|
293
|
+
const parts = newsLocalParts(row.published_at);
|
|
294
|
+
this.editingId.set(row.id);
|
|
295
|
+
this.form = {
|
|
296
|
+
kind: row.kind ?? 'informativo', title: row.title, summary: row.summary, body: '', items: [], before: '', after: '',
|
|
297
|
+
publishDate: parts.date, publishTime: parts.time, until: row.until, groupIds: row.groups.map((g) => g.id),
|
|
298
|
+
};
|
|
299
|
+
this.saveError.set(null);
|
|
300
|
+
this.loadingBody.set(true);
|
|
301
|
+
this.removing.set(false);
|
|
302
|
+
this.modalOpen.set(true);
|
|
303
|
+
try {
|
|
304
|
+
const full = await this.service.get(this.clientId(), row.id);
|
|
305
|
+
if (this.editingId() === row.id) {
|
|
306
|
+
this.form = {
|
|
307
|
+
...this.form, kind: full.kind ?? this.form.kind, body: full.body_html ?? '', items: [...(full.items ?? [])],
|
|
308
|
+
before: full.before_html ?? '', after: full.after_html ?? '',
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
catch (err) {
|
|
313
|
+
this.saveError.set(newsErrorText(err, this.text, this.text.loadError));
|
|
314
|
+
}
|
|
315
|
+
finally {
|
|
316
|
+
this.loadingBody.set(false);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
async save() {
|
|
320
|
+
if (!this.canSave || this.saving() || this.loadingBody())
|
|
321
|
+
return;
|
|
322
|
+
const body = {
|
|
323
|
+
kind: this.form.kind,
|
|
324
|
+
title: this.form.title.trim(),
|
|
325
|
+
summary: this.form.summary.trim(),
|
|
326
|
+
body_html: this.form.body,
|
|
327
|
+
// Só o conteúdo do tipo escolhido; o resto vai vazio (o servidor zera também).
|
|
328
|
+
items: this.form.kind === 'implementacao' ? [...this.form.items] : [],
|
|
329
|
+
before_html: this.form.kind === 'alteracao' ? this.form.before : '',
|
|
330
|
+
after_html: this.form.kind === 'alteracao' ? this.form.after : '',
|
|
331
|
+
published_at: newsPublishedAt(this.form.publishDate, this.form.publishTime),
|
|
332
|
+
until: this.form.until || null,
|
|
333
|
+
group_ids: [...this.form.groupIds],
|
|
334
|
+
};
|
|
335
|
+
this.saving.set(true);
|
|
336
|
+
this.saveError.set(null);
|
|
337
|
+
try {
|
|
338
|
+
if (this.editingId())
|
|
339
|
+
await this.service.update(this.clientId(), this.editingId(), body);
|
|
340
|
+
else
|
|
341
|
+
await this.service.create(this.clientId(), body);
|
|
342
|
+
}
|
|
343
|
+
catch (err) {
|
|
344
|
+
// O modal fica aberto com o motivo no idioma ativo.
|
|
345
|
+
this.saveError.set(newsErrorText(err, this.text, this.text.saveError));
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
finally {
|
|
349
|
+
this.saving.set(false);
|
|
350
|
+
}
|
|
351
|
+
this.modalOpen.set(false);
|
|
352
|
+
await this.load(this.editingId() ? this.pageState().page : 1);
|
|
353
|
+
}
|
|
354
|
+
/** "Excluir" no rodapé do modal (só ao editar): confirma, exclui, fecha e recarrega; falha deixa o modal aberto. */
|
|
355
|
+
async removeFromModal() {
|
|
356
|
+
const id = this.editingId();
|
|
357
|
+
if (!id || this.saving() || this.removing())
|
|
358
|
+
return;
|
|
359
|
+
const title = this.form.title.trim();
|
|
360
|
+
const ok = await this.dialogs.confirm({
|
|
361
|
+
heading: this.text.confirmDeleteHeading, message: formatMessage(this.text.confirmDelete, { title }),
|
|
362
|
+
confirmLabel: this.common.delete, danger: true,
|
|
363
|
+
});
|
|
364
|
+
if (!ok || this.editingId() !== id || !this.modalOpen())
|
|
365
|
+
return;
|
|
366
|
+
this.removing.set(true);
|
|
367
|
+
try {
|
|
368
|
+
if (!(await this.deletion.run(() => this.service.remove(this.clientId(), id))))
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
finally {
|
|
372
|
+
this.removing.set(false);
|
|
373
|
+
}
|
|
374
|
+
this.modalOpen.set(false);
|
|
375
|
+
await this.load();
|
|
376
|
+
}
|
|
377
|
+
/** Já confirmado pelo `confirm` da ação na grade. */
|
|
378
|
+
async remove(row) {
|
|
379
|
+
if (await this.deletion.run(() => this.service.remove(this.clientId(), row.id)))
|
|
380
|
+
await this.load();
|
|
381
|
+
}
|
|
382
|
+
onAction(e) {
|
|
383
|
+
if (e.action === 'edit')
|
|
384
|
+
void this.openEdit(e.row);
|
|
385
|
+
if (e.action === 'delete')
|
|
386
|
+
void this.remove(e.row);
|
|
387
|
+
}
|
|
388
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: AutoServiceNewsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
389
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: AutoServiceNewsComponent, isStandalone: true, selector: "spine-auto-service-news", inputs: { clientId: { classPropertyName: "clientId", publicName: "clientId", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<!-- Pagina\u00E7\u00E3o no servidor (agendadas e vencidas tamb\u00E9m); a busca/filtro local da grade fica desligada. -->\n<hm-data-grid\n [columns]=\"columns()\"\n [rows]=\"rows()\"\n [rowId]=\"rowId\"\n [caption]=\"text.caption\"\n [loading]=\"loading()\"\n [error]=\"loadError()\"\n [emptyMessage]=\"text.empty\"\n [rowActions]=\"rowActions()\"\n [filterable]=\"false\"\n [paginated]=\"false\"\n [totalItems]=\"total()\"\n [pageState]=\"pageState()\"\n (pageStateChange)=\"onPageStateChange($event)\"\n [pageSizes]=\"[10, 20, 50, 100]\"\n (actionTriggered)=\"onAction($event)\"\n>\n <hm-button dataGridActions icon=\"plus\" (clicked)=\"openCreate()\">{{ text.newNews }}</hm-button>\n <ng-template hmCell=\"title\" let-n>\n <span class=\"news-title\">\n <span>{{ n.title }}</span>\n @if (n.summary) { <span class=\"news-title__summary\">{{ n.summary }}</span> }\n </span>\n </ng-template>\n <ng-template hmCell=\"status\" let-n>\n <hm-tag [name]=\"statusLabel(n.status)\" [color]=\"statusColor(n.status)\" />\n </ng-template>\n <ng-template hmCell=\"groups\" let-n>\n @if (n.groups.length) {\n <span class=\"news-tags\">\n @for (g of n.groups; track g.id) { <hm-tag [name]=\"g.name\" color=\"info\" /> }\n </span>\n } @else {\n <span class=\"muted\">{{ text.audienceAll }}</span>\n }\n </ng-template>\n <ng-template hmCell=\"author\" let-n>\n @if (n.author; as a) {\n <span class=\"news-author\">\n <hm-account-avatar size=\"small\" [name]=\"a.name || a.username\" [imageUrl]=\"a.picture\" />\n <span>{{ a.name || a.username }}</span>\n </span>\n }\n </ng-template>\n</hm-data-grid>\n\n<!-- Modal: criar/editar novidade. O cabe\u00E7alho do hm-modal some da vista (o t\u00EDtulo segue como nome do di\u00E1logo, ver o\n .scss) e o editor desenha o seu: \u00EDcone, t\u00EDtulo e subt\u00EDtulo. Pensado para caber sem rolagem num notebook: em cima,\n \"1. Informa\u00E7\u00F5es principais\" (t\u00EDtulo) com o resumo ao lado; embaixo, o conte\u00FAdo do tipo escolhido no topo (texto;\n introdu\u00E7\u00E3o + lista; ou introdu\u00E7\u00E3o + antes e agora), que estica e rola por dentro, ao lado do painel com publica\u00E7\u00E3o,\n validade, p\u00FAblico, dica e a pr\u00E9via do In\u00EDcio no fim. O modal n\u00E3o rola; em tela estreita, tudo empilha. -->\n<hm-modal [open]=\"modalOpen()\" (openChange)=\"modalOpen.set($event)\" [heading]=\"editingId() ? text.editNews : text.newNews\" size=\"xlarge\"\n (closed)=\"modalOpen.set(false)\">\n <div class=\"ne\">\n <header class=\"ne-head\">\n <span class=\"ne-head__icon\" aria-hidden=\"true\"><hm-icon shape=\"announcement\" size=\"md\" /></span>\n <span class=\"ne-head__text\">\n <!-- O h2 do hm-modal j\u00E1 d\u00E1 o nome ao di\u00E1logo: este \u00E9 s\u00F3 o visual. -->\n <span class=\"ne-head__title\" aria-hidden=\"true\">{{ editingId() ? text.editNews : text.newNews }}</span>\n <span class=\"ne-head__intro\">{{ editingId() ? text.editNewsIntro : text.newNewsIntro }}</span>\n </span>\n <!-- Tipo de publica\u00E7\u00E3o: muda os campos do conte\u00FAdo e a pr\u00E9via. -->\n <hm-segmented-control class=\"ne-kind\" [label]=\"text.kind\" [options]=\"kindOptions\" [value]=\"form.kind\" (valueChange)=\"setKind($event)\" />\n </header>\n\n <div class=\"ne-scroll\">\n @if (saveError()) { <hm-alert variant=\"error\">{{ saveError() }}</hm-alert> }\n\n <div class=\"ne-grid\">\n <!-- Linha de cima: a se\u00E7\u00E3o 1 ocupa as duas colunas (subgrid): t\u00EDtulo \u00E0 esquerda, resumo \u00E0 direita. -->\n <section class=\"ne-section ne-intro\" [attr.aria-labelledby]=\"uid + '-main'\">\n <div class=\"ne-intro__lead\">\n <div class=\"ne-section__head\">\n <h3 class=\"ne-section__title\" [id]=\"uid + '-main'\"><span class=\"ne-step\" aria-hidden=\"true\">1</span>{{ text.sectionMain }}</h3>\n <p class=\"ne-section__hint\">{{ text.sectionMainHint }}</p>\n </div>\n <hm-input [label]=\"text.title\" required [maxLength]=\"TITLE_MAX\" [(value)]=\"form.title\" (valueChange)=\"saveError.set(null)\" />\n </div>\n <hm-textarea class=\"ne-intro__summary\" [label]=\"text.summary\" [hint]=\"text.summaryHint\" [rows]=\"3\" [maxLength]=\"SUMMARY_MAX\"\n [(value)]=\"form.summary\" />\n </section>\n\n <section class=\"ne-section ne-content\" [attr.aria-labelledby]=\"uid + '-body'\">\n <div class=\"ne-section__head\">\n <h3 class=\"ne-section__title\" [id]=\"uid + '-body'\"><span class=\"ne-step\" aria-hidden=\"true\">2</span>{{ text.sectionBody }}</h3>\n <p class=\"ne-section__hint\">\n {{ form.kind === 'implementacao' ? text.sectionBodyHintImpl : form.kind === 'alteracao' ? text.sectionBodyHintAlt : text.sectionBodyHint }}\n </p>\n </div>\n <!-- Estica at\u00E9 o fim da linha; quem rola \u00E9 o texto (ou a lista), n\u00E3o o modal. -->\n @switch (form.kind) {\n @case ('implementacao') {\n <hm-rich-text class=\"ne-content__intro\" [label]=\"text.intro\" [rows]=\"2\" [maxRows]=\"4\" [loading]=\"loadingBody()\"\n [(value)]=\"form.body\" />\n <div class=\"ne-content__items\">\n <hm-list-editor [label]=\"text.items\" [hint]=\"text.itemsHint\" [placeholder]=\"text.itemPlaceholder\" [emptyText]=\"text.itemsEmpty\"\n [max]=\"ITEMS_MAX\" [validate]=\"itemRule\" editable [items]=\"form.items\" (itemsChange)=\"form.items = [...$event]\" />\n </div>\n }\n @case ('alteracao') {\n <hm-rich-text class=\"ne-content__intro\" [label]=\"text.intro\" [rows]=\"2\" [maxRows]=\"4\" [loading]=\"loadingBody()\"\n [(value)]=\"form.body\" />\n <div class=\"ne-content__compare\">\n <hm-rich-text class=\"ne-content__editor ne-content__editor--labelled\" [label]=\"text.before\" required [rows]=\"4\" [maxRows]=\"16\" [loading]=\"loadingBody()\"\n [(value)]=\"form.before\" />\n <hm-rich-text class=\"ne-content__editor ne-content__editor--labelled\" [label]=\"text.after\" required [rows]=\"4\" [maxRows]=\"16\" [loading]=\"loadingBody()\"\n [(value)]=\"form.after\" />\n </div>\n }\n @default {\n <hm-rich-text class=\"ne-content__editor\" [label]=\"text.sectionBody\" labelHidden [hint]=\"text.bodyHint\" [rows]=\"6\" [maxRows]=\"24\"\n showCounter [loading]=\"loadingBody()\" [(value)]=\"form.body\" />\n }\n }\n </section>\n\n <aside class=\"ne-side\">\n <section class=\"ne-section ne-side__publish\" [attr.aria-labelledby]=\"uid + '-publish'\">\n <h3 class=\"ne-section__title\" [id]=\"uid + '-publish'\"><span class=\"ne-step\" aria-hidden=\"true\">3</span>{{ text.sectionPublish }}</h3>\n <div class=\"ne-row\">\n <hm-date-picker [label]=\"text.publishDate\" [(value)]=\"form.publishDate\" />\n <hm-time-picker [label]=\"text.publishTime\" [(value)]=\"form.publishTime\" />\n </div>\n <p class=\"ne-note\">{{ text.publishHint }}</p>\n </section>\n\n <section class=\"ne-section ne-side__until\" [attr.aria-labelledby]=\"uid + '-until'\">\n <h3 class=\"ne-section__title\" [id]=\"uid + '-until'\"><span class=\"ne-step\" aria-hidden=\"true\">4</span>{{ text.sectionUntil }}</h3>\n <hm-date-picker [label]=\"text.untilDate\" [hint]=\"text.untilHint\" [min]=\"form.publishDate\" [(value)]=\"form.until\" />\n @if (untilBeforePublish) { <hm-alert variant=\"warning\">{{ text.errors.untilBeforePublish }}</hm-alert> }\n </section>\n\n <section class=\"ne-section ne-side__audience\" [attr.aria-labelledby]=\"uid + '-audience'\">\n <h3 class=\"ne-section__title\" [id]=\"uid + '-audience'\"><span class=\"ne-step\" aria-hidden=\"true\">5</span>{{ text.sectionAudience }}</h3>\n <!-- Vazio = todos que entram no app. -->\n <hm-combobox-multi [label]=\"text.audienceGroups\" [hint]=\"text.audienceHint\" [placeholder]=\"text.audienceAll\" [options]=\"audienceOptions()\"\n [visibleChipsLimit]=\"null\" [selected]=\"form.groupIds\" (selectedChange)=\"form.groupIds = [...$event]\" />\n </section>\n\n <p class=\"ne-tip\"><hm-icon class=\"ne-tip__icon\" shape=\"lightbulb\" size=\"sm\" /><span><strong>{{ text.tipTitle }}</strong> {{ text.tipText }}</span></p>\n\n <section class=\"ne-section ne-side__preview\" [attr.aria-labelledby]=\"uid + '-preview'\">\n <h3 class=\"ne-section__title\" [id]=\"uid + '-preview'\"><hm-icon class=\"ne-section__icon\" shape=\"eye\" size=\"sm\" />{{ text.preview }}</h3>\n <!-- Mesmo desenho do card Novidades do In\u00EDcio; repete o que est\u00E1 nos campos, ent\u00E3o fica fora da leitura. -->\n <div class=\"ne-preview\" aria-hidden=\"true\">\n <div class=\"ne-preview__head\">\n <span class=\"ne-preview__heading\">{{ home.news }}</span>\n <span class=\"ne-preview__badge\">{{ home.newsBadge }}</span>\n </div>\n <div class=\"ne-preview__item\">\n <span class=\"ne-preview__icon\"><hm-icon [shape]=\"kindIcon\" size=\"sm\" /></span>\n <span class=\"ne-preview__text\">\n <span class=\"ne-preview__title\" [class.ne-preview__placeholder]=\"!form.title.trim()\">{{ form.title.trim() || text.previewTitle }}</span>\n <span class=\"ne-preview__summary\" [class.ne-preview__placeholder]=\"!form.summary.trim()\">{{ form.summary.trim() || text.previewSummary }}</span>\n <span class=\"ne-preview__date\">\n <hm-icon shape=\"calendar\" size=\"xs\" />{{ previewDate }}\n @if (previewScheduled) { <span class=\"ne-preview__status\">{{ text.statusScheduled }}</span> }\n <span class=\"ne-preview__kind\">{{ kindLabel }}</span>\n </span>\n </span>\n <hm-icon class=\"ne-preview__chevron\" shape=\"angle-right\" size=\"sm\" />\n </div>\n </div>\n </section>\n </aside>\n </div>\n </div>\n </div>\n\n <ng-container footer>\n <!-- Sem rascunho: a novidade n\u00E3o tem esse estado (sem data = publica ao salvar). -->\n @if (editingId()) {\n <hm-button class=\"ne-delete\" emphasis=\"medium\" intent=\"danger\" icon=\"trash\" [disabled]=\"saving() || removing()\" [loading]=\"removing()\"\n (clicked)=\"removeFromModal()\">{{ common.delete }}</hm-button>\n }\n <hm-button emphasis=\"medium\" (clicked)=\"modalOpen.set(false)\">{{ common.cancel }}</hm-button>\n <hm-button [disabled]=\"!canSave || loadingBody() || removing()\" [loading]=\"saving()\" (clicked)=\"save()\">\n {{ editingId() ? common.save : common.create }}\n </hm-button>\n </ng-container>\n</hm-modal>\n", styles: [".as-stack{display:flex;flex-direction:column;gap:var(--hm-space-md);min-inline-size:0}.as-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--hm-space-xs)}.as-field-row{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--hm-space-sm)}.as-field-row>hm-combobox{flex:1 1 16rem;min-inline-size:0}.as-summary{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-sm)}.as-summary__info{display:flex;flex:1 1 16rem;flex-direction:column;gap:var(--hm-space-micro);min-inline-size:0}.as-summary__title{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs);margin:0;color:var(--hm-text);font-size:var(--hm-font-size-md);font-weight:var(--hm-font-weight-semibold)}.as-summary__detail{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.muted{color:var(--hm-muted)}.as-empty{margin:var(--hm-space-xs) 0 0;font-size:var(--hm-font-size-sm)}.as-secret{display:grid;gap:var(--hm-space-micro)}.as-secret__label{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.as-secret__row{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.as-secret__value{flex:1 1 240px;min-width:0;border:var(--hm-border-hairline) solid var(--hm-divider);border-radius:var(--hm-radius-control);padding:var(--hm-space-xs) var(--hm-space-sm);background:var(--hm-surface-muted);color:var(--hm-text);font-family:var(--hm-font-mono);font-size:var(--hm-font-size-sm);overflow-wrap:anywhere;-webkit-user-select:all;user-select:all}:host{display:block}.news-title{display:flex;flex-direction:column;gap:2px;min-inline-size:0}.news-title__summary{overflow:hidden;color:var(--hm-muted);font-size:var(--hm-font-size-xs);text-overflow:ellipsis;white-space:nowrap}.news-tags,.news-author{display:inline-flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}:host ::ng-deep .hm-modal__window:has(>.hm-modal__body>.ne){block-size:min(100dvh - 2 * var(--hm-space-md),60rem);max-block-size:none;grid-template-rows:minmax(0,1fr) auto}:host ::ng-deep .hm-modal__window:has(>.hm-modal__body>.ne)>.hm-modal__header{position:absolute;z-index:1;inset-block-start:0;inset-inline-end:0;border:0;padding:var(--hm-space-sm)}:host ::ng-deep .hm-modal__window:has(>.hm-modal__body>.ne) .hm-modal__heading{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}:host ::ng-deep .hm-modal__window:has(>.hm-modal__body>.ne)>.hm-modal__body{display:flex;flex-direction:column;min-block-size:0;overflow:hidden;padding:0}.ne{container:ne/inline-size;display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0}.ne-head{display:flex;flex:none;flex-wrap:wrap;align-items:center;gap:var(--hm-space-sm);padding:var(--hm-space-sm) var(--hm-space-md);padding-inline-end:calc(var(--hm-space-md) + var(--hm-control-height) + var(--hm-space-sm));border-block-end:var(--hm-border-hairline) solid var(--hm-divider)}.ne-head__icon{display:grid;flex:none;place-items:center;inline-size:2.5rem;block-size:2.5rem;border-radius:var(--hm-radius);background:var(--hm-accent-subtle);color:var(--hm-accent)}.ne-head__text{display:flex;flex-direction:column;gap:var(--hm-space-nano);min-inline-size:0}.ne-head__title{color:var(--hm-text);font-size:var(--hm-font-size-xl);font-weight:var(--hm-font-weight-bold);line-height:var(--hm-line-height-tight)}.ne-head__intro{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.ne-kind{margin-inline-start:auto}.ne-content__intro{flex:none}.ne-content__compare{display:flex;flex-direction:column;gap:var(--hm-space-sm)}.ne-preview__kind{padding:var(--hm-space-nano) var(--hm-space-xs);border:var(--hm-border-hairline) solid var(--hm-divider);border-radius:var(--hm-radius-pill);color:var(--hm-text);font-size:var(--hm-font-size-3xs)}.ne-scroll{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--hm-space-sm);min-block-size:0;overflow-y:auto;padding:var(--hm-space-md)}.ne-grid{display:grid;flex:1 0 auto;grid-template-columns:minmax(0,1fr);gap:var(--hm-space-md)}.ne-section{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-inline-size:0}.ne-section__head{display:flex;flex-direction:column;gap:var(--hm-space-nano)}.ne-section__title{display:flex;align-items:center;gap:var(--hm-space-xs);margin:0;color:var(--hm-text);font-size:var(--hm-font-size-md);font-weight:var(--hm-font-weight-semibold)}.ne-section__icon{flex:none;color:var(--hm-accent)}.ne-section__hint{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.ne-step{display:inline-grid;flex:none;place-items:center;inline-size:1.5rem;block-size:1.5rem;border-radius:var(--hm-radius-pill);background:var(--hm-accent-subtle);color:var(--hm-accent);font-size:var(--hm-font-size-xs);font-weight:var(--hm-font-weight-bold)}.ne-intro{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--hm-space-sm) var(--hm-space-md)}.ne-intro__lead{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-inline-size:0}.ne-side{container:ne-side/inline-size;display:grid;grid-template-areas:\"publish\" \"until\" \"audience\" \"tip\" \"preview\";grid-template-columns:minmax(0,1fr);grid-template-rows:auto auto auto auto 1fr;gap:var(--hm-space-md);min-inline-size:0;padding:var(--hm-space-sm) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-divider);border-radius:var(--hm-radius);background:var(--hm-surface-muted)}.ne-side__publish{grid-area:publish}.ne-side__until{grid-area:until}.ne-side__audience{grid-area:audience}.ne-tip{grid-area:tip}.ne-side__preview{grid-area:preview;align-self:end}@container ne (min-width: 52rem){.ne-scroll{overflow:hidden}.ne-grid{flex:1 1 auto;grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:auto minmax(0,1fr);min-block-size:0}.ne-intro{grid-column:1/-1;grid-template-columns:subgrid}.ne-content{min-block-size:0;overflow:hidden}.ne-side{min-block-size:0;overflow-y:auto}.ne-content__items{flex:1 1 0;min-block-size:0;overflow-y:auto}.ne-content__compare{display:grid;flex:1 1 0;grid-template-columns:repeat(2,minmax(0,1fr));min-block-size:0}.ne-content__editor{flex:1 1 0;grid-template-rows:minmax(0,1fr);grid-auto-rows:auto;min-block-size:0}.ne-content__editor ::ng-deep .hm-rich-text__frame,.ne-content__editor ::ng-deep .hm-rich-text__loading{min-block-size:0}.ne-content__editor ::ng-deep .hm-rich-text__body{display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0}.ne-content__editor ::ng-deep .hm-rich-text__area{flex:1 1 0;min-block-size:2lh;max-block-size:none;overflow-y:auto}.ne-content__editor--labelled{grid-template-rows:auto minmax(0,1fr)}}@media(max-height:55rem){@container ne-side (min-width: 34rem){.ne-side{grid-template-areas:\"publish audience\" \"until preview\" \"tip preview\";grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:auto auto 1fr}}}.ne-row{display:flex;flex-wrap:wrap;gap:var(--hm-space-sm)}.ne-row>*{flex:1 1 8rem;min-inline-size:0}.ne-note{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.ne-preview{display:flex;flex-direction:column;gap:var(--hm-space-micro);padding:var(--hm-space-sm) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-divider);border-radius:var(--hm-radius);background:var(--hm-surface-raised)}.ne-preview__head{display:flex;align-items:center;gap:var(--hm-space-xs)}.ne-preview__heading{color:var(--hm-text);font-size:var(--hm-font-size-md);font-weight:var(--hm-font-weight-semibold)}.ne-preview__badge,.ne-preview__status{flex:none;padding:var(--hm-space-nano) var(--hm-space-xs);border-radius:var(--hm-radius-micro);background:var(--hm-accent-subtle);color:var(--hm-accent);font-size:var(--hm-font-size-3xs);font-weight:var(--hm-font-weight-semibold);letter-spacing:.04em;text-transform:uppercase}.ne-preview__item{display:flex;align-items:center;gap:var(--hm-space-sm);padding:var(--hm-space-xs) 0;border-block-start:var(--hm-border-hairline) solid var(--hm-divider)}.ne-preview__icon{display:grid;flex:none;place-items:center;inline-size:2rem;block-size:2rem;border-radius:var(--hm-radius-control);background:var(--hm-accent-subtle);color:var(--hm-accent)}.ne-preview__text{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--hm-space-nano);min-inline-size:0}.ne-preview__title{overflow:hidden;color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold);text-overflow:ellipsis;white-space:nowrap}.ne-preview__summary{display:-webkit-box;overflow:hidden;color:var(--hm-muted);font-size:var(--hm-font-size-xs);overflow-wrap:anywhere;-webkit-box-orient:vertical;-webkit-line-clamp:2}.ne-preview__placeholder{color:var(--hm-muted);font-style:italic;font-weight:var(--hm-font-weight-regular)}.ne-preview__date{display:inline-flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-micro);color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.ne-preview__chevron{flex:none;color:var(--hm-muted)}.ne-tip{display:flex;align-items:flex-start;gap:var(--hm-space-xs);margin:0;padding:var(--hm-space-xs) var(--hm-space-sm);border-inline-start:var(--hm-border-thin) solid var(--hm-info);border-radius:var(--hm-radius-control);background:var(--hm-info-bg);color:var(--hm-text);font-size:var(--hm-font-size-xs)}@media(forced-colors:active){.ne-tip{border:var(--hm-border-hairline) solid CanvasText}}.ne-tip__icon{flex:none;color:var(--hm-info)}.ne-delete{margin-inline-end:auto}\n"], dependencies: [{ kind: "component", type: AccountAvatarComponent, selector: "hm-account-avatar", inputs: ["name", "imageUrl", "size", "loading"] }, { kind: "component", type: AlertComponent, selector: "hm-alert", inputs: ["variant", "appearance", "heading", "closable", "size", "showIcon", "link", "linkLabel", "linkTarget", "dismissKey", "duration"], outputs: ["closed"] }, { kind: "component", type: ButtonComponent, selector: "hm-button", inputs: ["emphasis", "intent", "size", "type", "icon", "iconDirection", "iconEnd", "disabled", "loading", "loadingState", "block", "link", "newTab", "caret", "inMenu", "toggle", "pressed"], outputs: ["loadingStateChange", "pressedChange", "clicked"] }, { kind: "component", type: ComboboxMultiComponent, selector: "hm-combobox-multi", inputs: ["label", "options", "selected", "extraOptions", "unknownLabel", "placeholder", "hint", "max", "visibleChipsLimit"], outputs: ["selectedChange"] }, { kind: "component", type: DataGridComponent, selector: "hm-data-grid", inputs: ["columns", "rows", "rowId", "caption", "rowActions", "loading", "error", "emptyMessage", "noResultsMessage", "filterable", "paginated", "pageState", "pagination", "totalItems", "sort", "selectable", "selectionMode", "selection", "rowSelectable", "rowSelectableReason", "rowDetailDisabled", "rowDetailHidden", "virtual", "rowHeight", "pinnedColumns", "columnState", "pageSizes", "fillHeight", "maxHeight", "bordered", "rowState", "rowClickable", "remoteSearch", "remoteSort", "itemsLabel", "pageSizeLabel", "exportable", "exportFileName", "groupBy", "aggregates", "aggregateFormatter", "persistKey", "persistStorage", "advancedFilter", "filterQuery", "columnManager", "columnOrder", "searchTerm"], outputs: ["pageStateChange", "sortChange", "selectionChange", "pinnedColumnsChange", "columnStateChange", "actionTriggered", "detailToggled", "rowClicked", "clearFiltersRequested", "filteredChange", "searchTermChanged", "groupByChange", "filterQueryChange", "columnOrderChange", "searchTermChange", "detailPaneToggled"] }, { kind: "directive", type: DataGridCellDirective, selector: "ng-template[hmCell]", inputs: ["hmCell"] }, { kind: "component", type: DatePickerComponent, selector: "hm-date-picker", inputs: ["value", "label", "labelHidden", "hint", "placeholder", "min", "max", "valueFormat"], outputs: ["valueChange"] }, { kind: "component", type: IconComponent, selector: "hm-icon", inputs: ["shape", "direction", "size", "solid", "badge", "status", "flip", "inverse", "label"] }, { kind: "component", type: InputComponent, selector: "hm-input", inputs: ["value", "label", "type", "placeholder", "icon", "labelHidden", "hint", "prefix", "suffix", "prefixIcon", "mask", "maskValue", "min", "max", "step", "stepButtons", "maxLength", "autocomplete", "inputMode"], outputs: ["valueChange"] }, { kind: "component", type: ListEditorComponent, selector: "hm-list-editor", inputs: ["items", "label", "labelHidden", "hint", "placeholder", "descriptionPlaceholder", "pair", "itemLabel", "titleLabel", "descriptionLabel", "addLabel", "emptyText", "descriptionRequired", "allowDuplicates", "ignoreCase", "max", "validate", "editable", "readonly"], outputs: ["itemsChange", "added", "removed", "moved", "edited"] }, { kind: "component", type: ModalComponent, selector: "hm-modal", inputs: ["open", "heading", "size", "closeLabel", "closable", "beforeClose"], outputs: ["openChange", "closed"] }, { kind: "component", type: RichTextComponent, selector: "hm-rich-text", inputs: ["value", "label", "labelHidden", "hint", "placeholder", "readonly", "loading", "tools", "headingLevels", "hideToolbar", "rows", "maxRows", "maxLength", "showCounter", "pasteMode", "linkProtocols", "allowRelativeLinks", "spellcheck"], outputs: ["valueChange", "focusChange"] }, { kind: "component", type: SegmentedControlComponent, selector: "hm-segmented-control", inputs: ["options", "value", "label", "size", "emphasis"], outputs: ["valueChange"] }, { kind: "component", type: TagComponent, selector: "hm-tag", inputs: ["name", "color", "compact"] }, { kind: "component", type: TextareaComponent, selector: "hm-textarea", inputs: ["value", "label", "hint", "placeholder", "maxLength", "rows", "autoGrow", "labelHidden", "loading", "maxRows", "submitKey"], outputs: ["valueChange", "submitted"] }, { kind: "component", type: TimePickerComponent, selector: "hm-time-picker", inputs: ["value", "label", "labelHidden", "hint", "placeholder", "min", "max", "interval", "hourCycle"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
390
|
+
}
|
|
391
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: AutoServiceNewsComponent, decorators: [{
|
|
392
|
+
type: Component,
|
|
393
|
+
args: [{ selector: 'spine-auto-service-news', imports: [
|
|
394
|
+
AccountAvatarComponent, AlertComponent, ButtonComponent, ComboboxMultiComponent, DataGridComponent, DataGridCellDirective,
|
|
395
|
+
DatePickerComponent, IconComponent, InputComponent, ListEditorComponent, ModalComponent, RichTextComponent, SegmentedControlComponent,
|
|
396
|
+
TagComponent, TextareaComponent, TimePickerComponent,
|
|
397
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Pagina\u00E7\u00E3o no servidor (agendadas e vencidas tamb\u00E9m); a busca/filtro local da grade fica desligada. -->\n<hm-data-grid\n [columns]=\"columns()\"\n [rows]=\"rows()\"\n [rowId]=\"rowId\"\n [caption]=\"text.caption\"\n [loading]=\"loading()\"\n [error]=\"loadError()\"\n [emptyMessage]=\"text.empty\"\n [rowActions]=\"rowActions()\"\n [filterable]=\"false\"\n [paginated]=\"false\"\n [totalItems]=\"total()\"\n [pageState]=\"pageState()\"\n (pageStateChange)=\"onPageStateChange($event)\"\n [pageSizes]=\"[10, 20, 50, 100]\"\n (actionTriggered)=\"onAction($event)\"\n>\n <hm-button dataGridActions icon=\"plus\" (clicked)=\"openCreate()\">{{ text.newNews }}</hm-button>\n <ng-template hmCell=\"title\" let-n>\n <span class=\"news-title\">\n <span>{{ n.title }}</span>\n @if (n.summary) { <span class=\"news-title__summary\">{{ n.summary }}</span> }\n </span>\n </ng-template>\n <ng-template hmCell=\"status\" let-n>\n <hm-tag [name]=\"statusLabel(n.status)\" [color]=\"statusColor(n.status)\" />\n </ng-template>\n <ng-template hmCell=\"groups\" let-n>\n @if (n.groups.length) {\n <span class=\"news-tags\">\n @for (g of n.groups; track g.id) { <hm-tag [name]=\"g.name\" color=\"info\" /> }\n </span>\n } @else {\n <span class=\"muted\">{{ text.audienceAll }}</span>\n }\n </ng-template>\n <ng-template hmCell=\"author\" let-n>\n @if (n.author; as a) {\n <span class=\"news-author\">\n <hm-account-avatar size=\"small\" [name]=\"a.name || a.username\" [imageUrl]=\"a.picture\" />\n <span>{{ a.name || a.username }}</span>\n </span>\n }\n </ng-template>\n</hm-data-grid>\n\n<!-- Modal: criar/editar novidade. O cabe\u00E7alho do hm-modal some da vista (o t\u00EDtulo segue como nome do di\u00E1logo, ver o\n .scss) e o editor desenha o seu: \u00EDcone, t\u00EDtulo e subt\u00EDtulo. Pensado para caber sem rolagem num notebook: em cima,\n \"1. Informa\u00E7\u00F5es principais\" (t\u00EDtulo) com o resumo ao lado; embaixo, o conte\u00FAdo do tipo escolhido no topo (texto;\n introdu\u00E7\u00E3o + lista; ou introdu\u00E7\u00E3o + antes e agora), que estica e rola por dentro, ao lado do painel com publica\u00E7\u00E3o,\n validade, p\u00FAblico, dica e a pr\u00E9via do In\u00EDcio no fim. O modal n\u00E3o rola; em tela estreita, tudo empilha. -->\n<hm-modal [open]=\"modalOpen()\" (openChange)=\"modalOpen.set($event)\" [heading]=\"editingId() ? text.editNews : text.newNews\" size=\"xlarge\"\n (closed)=\"modalOpen.set(false)\">\n <div class=\"ne\">\n <header class=\"ne-head\">\n <span class=\"ne-head__icon\" aria-hidden=\"true\"><hm-icon shape=\"announcement\" size=\"md\" /></span>\n <span class=\"ne-head__text\">\n <!-- O h2 do hm-modal j\u00E1 d\u00E1 o nome ao di\u00E1logo: este \u00E9 s\u00F3 o visual. -->\n <span class=\"ne-head__title\" aria-hidden=\"true\">{{ editingId() ? text.editNews : text.newNews }}</span>\n <span class=\"ne-head__intro\">{{ editingId() ? text.editNewsIntro : text.newNewsIntro }}</span>\n </span>\n <!-- Tipo de publica\u00E7\u00E3o: muda os campos do conte\u00FAdo e a pr\u00E9via. -->\n <hm-segmented-control class=\"ne-kind\" [label]=\"text.kind\" [options]=\"kindOptions\" [value]=\"form.kind\" (valueChange)=\"setKind($event)\" />\n </header>\n\n <div class=\"ne-scroll\">\n @if (saveError()) { <hm-alert variant=\"error\">{{ saveError() }}</hm-alert> }\n\n <div class=\"ne-grid\">\n <!-- Linha de cima: a se\u00E7\u00E3o 1 ocupa as duas colunas (subgrid): t\u00EDtulo \u00E0 esquerda, resumo \u00E0 direita. -->\n <section class=\"ne-section ne-intro\" [attr.aria-labelledby]=\"uid + '-main'\">\n <div class=\"ne-intro__lead\">\n <div class=\"ne-section__head\">\n <h3 class=\"ne-section__title\" [id]=\"uid + '-main'\"><span class=\"ne-step\" aria-hidden=\"true\">1</span>{{ text.sectionMain }}</h3>\n <p class=\"ne-section__hint\">{{ text.sectionMainHint }}</p>\n </div>\n <hm-input [label]=\"text.title\" required [maxLength]=\"TITLE_MAX\" [(value)]=\"form.title\" (valueChange)=\"saveError.set(null)\" />\n </div>\n <hm-textarea class=\"ne-intro__summary\" [label]=\"text.summary\" [hint]=\"text.summaryHint\" [rows]=\"3\" [maxLength]=\"SUMMARY_MAX\"\n [(value)]=\"form.summary\" />\n </section>\n\n <section class=\"ne-section ne-content\" [attr.aria-labelledby]=\"uid + '-body'\">\n <div class=\"ne-section__head\">\n <h3 class=\"ne-section__title\" [id]=\"uid + '-body'\"><span class=\"ne-step\" aria-hidden=\"true\">2</span>{{ text.sectionBody }}</h3>\n <p class=\"ne-section__hint\">\n {{ form.kind === 'implementacao' ? text.sectionBodyHintImpl : form.kind === 'alteracao' ? text.sectionBodyHintAlt : text.sectionBodyHint }}\n </p>\n </div>\n <!-- Estica at\u00E9 o fim da linha; quem rola \u00E9 o texto (ou a lista), n\u00E3o o modal. -->\n @switch (form.kind) {\n @case ('implementacao') {\n <hm-rich-text class=\"ne-content__intro\" [label]=\"text.intro\" [rows]=\"2\" [maxRows]=\"4\" [loading]=\"loadingBody()\"\n [(value)]=\"form.body\" />\n <div class=\"ne-content__items\">\n <hm-list-editor [label]=\"text.items\" [hint]=\"text.itemsHint\" [placeholder]=\"text.itemPlaceholder\" [emptyText]=\"text.itemsEmpty\"\n [max]=\"ITEMS_MAX\" [validate]=\"itemRule\" editable [items]=\"form.items\" (itemsChange)=\"form.items = [...$event]\" />\n </div>\n }\n @case ('alteracao') {\n <hm-rich-text class=\"ne-content__intro\" [label]=\"text.intro\" [rows]=\"2\" [maxRows]=\"4\" [loading]=\"loadingBody()\"\n [(value)]=\"form.body\" />\n <div class=\"ne-content__compare\">\n <hm-rich-text class=\"ne-content__editor ne-content__editor--labelled\" [label]=\"text.before\" required [rows]=\"4\" [maxRows]=\"16\" [loading]=\"loadingBody()\"\n [(value)]=\"form.before\" />\n <hm-rich-text class=\"ne-content__editor ne-content__editor--labelled\" [label]=\"text.after\" required [rows]=\"4\" [maxRows]=\"16\" [loading]=\"loadingBody()\"\n [(value)]=\"form.after\" />\n </div>\n }\n @default {\n <hm-rich-text class=\"ne-content__editor\" [label]=\"text.sectionBody\" labelHidden [hint]=\"text.bodyHint\" [rows]=\"6\" [maxRows]=\"24\"\n showCounter [loading]=\"loadingBody()\" [(value)]=\"form.body\" />\n }\n }\n </section>\n\n <aside class=\"ne-side\">\n <section class=\"ne-section ne-side__publish\" [attr.aria-labelledby]=\"uid + '-publish'\">\n <h3 class=\"ne-section__title\" [id]=\"uid + '-publish'\"><span class=\"ne-step\" aria-hidden=\"true\">3</span>{{ text.sectionPublish }}</h3>\n <div class=\"ne-row\">\n <hm-date-picker [label]=\"text.publishDate\" [(value)]=\"form.publishDate\" />\n <hm-time-picker [label]=\"text.publishTime\" [(value)]=\"form.publishTime\" />\n </div>\n <p class=\"ne-note\">{{ text.publishHint }}</p>\n </section>\n\n <section class=\"ne-section ne-side__until\" [attr.aria-labelledby]=\"uid + '-until'\">\n <h3 class=\"ne-section__title\" [id]=\"uid + '-until'\"><span class=\"ne-step\" aria-hidden=\"true\">4</span>{{ text.sectionUntil }}</h3>\n <hm-date-picker [label]=\"text.untilDate\" [hint]=\"text.untilHint\" [min]=\"form.publishDate\" [(value)]=\"form.until\" />\n @if (untilBeforePublish) { <hm-alert variant=\"warning\">{{ text.errors.untilBeforePublish }}</hm-alert> }\n </section>\n\n <section class=\"ne-section ne-side__audience\" [attr.aria-labelledby]=\"uid + '-audience'\">\n <h3 class=\"ne-section__title\" [id]=\"uid + '-audience'\"><span class=\"ne-step\" aria-hidden=\"true\">5</span>{{ text.sectionAudience }}</h3>\n <!-- Vazio = todos que entram no app. -->\n <hm-combobox-multi [label]=\"text.audienceGroups\" [hint]=\"text.audienceHint\" [placeholder]=\"text.audienceAll\" [options]=\"audienceOptions()\"\n [visibleChipsLimit]=\"null\" [selected]=\"form.groupIds\" (selectedChange)=\"form.groupIds = [...$event]\" />\n </section>\n\n <p class=\"ne-tip\"><hm-icon class=\"ne-tip__icon\" shape=\"lightbulb\" size=\"sm\" /><span><strong>{{ text.tipTitle }}</strong> {{ text.tipText }}</span></p>\n\n <section class=\"ne-section ne-side__preview\" [attr.aria-labelledby]=\"uid + '-preview'\">\n <h3 class=\"ne-section__title\" [id]=\"uid + '-preview'\"><hm-icon class=\"ne-section__icon\" shape=\"eye\" size=\"sm\" />{{ text.preview }}</h3>\n <!-- Mesmo desenho do card Novidades do In\u00EDcio; repete o que est\u00E1 nos campos, ent\u00E3o fica fora da leitura. -->\n <div class=\"ne-preview\" aria-hidden=\"true\">\n <div class=\"ne-preview__head\">\n <span class=\"ne-preview__heading\">{{ home.news }}</span>\n <span class=\"ne-preview__badge\">{{ home.newsBadge }}</span>\n </div>\n <div class=\"ne-preview__item\">\n <span class=\"ne-preview__icon\"><hm-icon [shape]=\"kindIcon\" size=\"sm\" /></span>\n <span class=\"ne-preview__text\">\n <span class=\"ne-preview__title\" [class.ne-preview__placeholder]=\"!form.title.trim()\">{{ form.title.trim() || text.previewTitle }}</span>\n <span class=\"ne-preview__summary\" [class.ne-preview__placeholder]=\"!form.summary.trim()\">{{ form.summary.trim() || text.previewSummary }}</span>\n <span class=\"ne-preview__date\">\n <hm-icon shape=\"calendar\" size=\"xs\" />{{ previewDate }}\n @if (previewScheduled) { <span class=\"ne-preview__status\">{{ text.statusScheduled }}</span> }\n <span class=\"ne-preview__kind\">{{ kindLabel }}</span>\n </span>\n </span>\n <hm-icon class=\"ne-preview__chevron\" shape=\"angle-right\" size=\"sm\" />\n </div>\n </div>\n </section>\n </aside>\n </div>\n </div>\n </div>\n\n <ng-container footer>\n <!-- Sem rascunho: a novidade n\u00E3o tem esse estado (sem data = publica ao salvar). -->\n @if (editingId()) {\n <hm-button class=\"ne-delete\" emphasis=\"medium\" intent=\"danger\" icon=\"trash\" [disabled]=\"saving() || removing()\" [loading]=\"removing()\"\n (clicked)=\"removeFromModal()\">{{ common.delete }}</hm-button>\n }\n <hm-button emphasis=\"medium\" (clicked)=\"modalOpen.set(false)\">{{ common.cancel }}</hm-button>\n <hm-button [disabled]=\"!canSave || loadingBody() || removing()\" [loading]=\"saving()\" (clicked)=\"save()\">\n {{ editingId() ? common.save : common.create }}\n </hm-button>\n </ng-container>\n</hm-modal>\n", styles: [".as-stack{display:flex;flex-direction:column;gap:var(--hm-space-md);min-inline-size:0}.as-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--hm-space-xs)}.as-field-row{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--hm-space-sm)}.as-field-row>hm-combobox{flex:1 1 16rem;min-inline-size:0}.as-summary{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-sm)}.as-summary__info{display:flex;flex:1 1 16rem;flex-direction:column;gap:var(--hm-space-micro);min-inline-size:0}.as-summary__title{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs);margin:0;color:var(--hm-text);font-size:var(--hm-font-size-md);font-weight:var(--hm-font-weight-semibold)}.as-summary__detail{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.muted{color:var(--hm-muted)}.as-empty{margin:var(--hm-space-xs) 0 0;font-size:var(--hm-font-size-sm)}.as-secret{display:grid;gap:var(--hm-space-micro)}.as-secret__label{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.as-secret__row{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.as-secret__value{flex:1 1 240px;min-width:0;border:var(--hm-border-hairline) solid var(--hm-divider);border-radius:var(--hm-radius-control);padding:var(--hm-space-xs) var(--hm-space-sm);background:var(--hm-surface-muted);color:var(--hm-text);font-family:var(--hm-font-mono);font-size:var(--hm-font-size-sm);overflow-wrap:anywhere;-webkit-user-select:all;user-select:all}:host{display:block}.news-title{display:flex;flex-direction:column;gap:2px;min-inline-size:0}.news-title__summary{overflow:hidden;color:var(--hm-muted);font-size:var(--hm-font-size-xs);text-overflow:ellipsis;white-space:nowrap}.news-tags,.news-author{display:inline-flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}:host ::ng-deep .hm-modal__window:has(>.hm-modal__body>.ne){block-size:min(100dvh - 2 * var(--hm-space-md),60rem);max-block-size:none;grid-template-rows:minmax(0,1fr) auto}:host ::ng-deep .hm-modal__window:has(>.hm-modal__body>.ne)>.hm-modal__header{position:absolute;z-index:1;inset-block-start:0;inset-inline-end:0;border:0;padding:var(--hm-space-sm)}:host ::ng-deep .hm-modal__window:has(>.hm-modal__body>.ne) .hm-modal__heading{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}:host ::ng-deep .hm-modal__window:has(>.hm-modal__body>.ne)>.hm-modal__body{display:flex;flex-direction:column;min-block-size:0;overflow:hidden;padding:0}.ne{container:ne/inline-size;display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0}.ne-head{display:flex;flex:none;flex-wrap:wrap;align-items:center;gap:var(--hm-space-sm);padding:var(--hm-space-sm) var(--hm-space-md);padding-inline-end:calc(var(--hm-space-md) + var(--hm-control-height) + var(--hm-space-sm));border-block-end:var(--hm-border-hairline) solid var(--hm-divider)}.ne-head__icon{display:grid;flex:none;place-items:center;inline-size:2.5rem;block-size:2.5rem;border-radius:var(--hm-radius);background:var(--hm-accent-subtle);color:var(--hm-accent)}.ne-head__text{display:flex;flex-direction:column;gap:var(--hm-space-nano);min-inline-size:0}.ne-head__title{color:var(--hm-text);font-size:var(--hm-font-size-xl);font-weight:var(--hm-font-weight-bold);line-height:var(--hm-line-height-tight)}.ne-head__intro{color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.ne-kind{margin-inline-start:auto}.ne-content__intro{flex:none}.ne-content__compare{display:flex;flex-direction:column;gap:var(--hm-space-sm)}.ne-preview__kind{padding:var(--hm-space-nano) var(--hm-space-xs);border:var(--hm-border-hairline) solid var(--hm-divider);border-radius:var(--hm-radius-pill);color:var(--hm-text);font-size:var(--hm-font-size-3xs)}.ne-scroll{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--hm-space-sm);min-block-size:0;overflow-y:auto;padding:var(--hm-space-md)}.ne-grid{display:grid;flex:1 0 auto;grid-template-columns:minmax(0,1fr);gap:var(--hm-space-md)}.ne-section{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-inline-size:0}.ne-section__head{display:flex;flex-direction:column;gap:var(--hm-space-nano)}.ne-section__title{display:flex;align-items:center;gap:var(--hm-space-xs);margin:0;color:var(--hm-text);font-size:var(--hm-font-size-md);font-weight:var(--hm-font-weight-semibold)}.ne-section__icon{flex:none;color:var(--hm-accent)}.ne-section__hint{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.ne-step{display:inline-grid;flex:none;place-items:center;inline-size:1.5rem;block-size:1.5rem;border-radius:var(--hm-radius-pill);background:var(--hm-accent-subtle);color:var(--hm-accent);font-size:var(--hm-font-size-xs);font-weight:var(--hm-font-weight-bold)}.ne-intro{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--hm-space-sm) var(--hm-space-md)}.ne-intro__lead{display:flex;flex-direction:column;gap:var(--hm-space-xs);min-inline-size:0}.ne-side{container:ne-side/inline-size;display:grid;grid-template-areas:\"publish\" \"until\" \"audience\" \"tip\" \"preview\";grid-template-columns:minmax(0,1fr);grid-template-rows:auto auto auto auto 1fr;gap:var(--hm-space-md);min-inline-size:0;padding:var(--hm-space-sm) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-divider);border-radius:var(--hm-radius);background:var(--hm-surface-muted)}.ne-side__publish{grid-area:publish}.ne-side__until{grid-area:until}.ne-side__audience{grid-area:audience}.ne-tip{grid-area:tip}.ne-side__preview{grid-area:preview;align-self:end}@container ne (min-width: 52rem){.ne-scroll{overflow:hidden}.ne-grid{flex:1 1 auto;grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:auto minmax(0,1fr);min-block-size:0}.ne-intro{grid-column:1/-1;grid-template-columns:subgrid}.ne-content{min-block-size:0;overflow:hidden}.ne-side{min-block-size:0;overflow-y:auto}.ne-content__items{flex:1 1 0;min-block-size:0;overflow-y:auto}.ne-content__compare{display:grid;flex:1 1 0;grid-template-columns:repeat(2,minmax(0,1fr));min-block-size:0}.ne-content__editor{flex:1 1 0;grid-template-rows:minmax(0,1fr);grid-auto-rows:auto;min-block-size:0}.ne-content__editor ::ng-deep .hm-rich-text__frame,.ne-content__editor ::ng-deep .hm-rich-text__loading{min-block-size:0}.ne-content__editor ::ng-deep .hm-rich-text__body{display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0}.ne-content__editor ::ng-deep .hm-rich-text__area{flex:1 1 0;min-block-size:2lh;max-block-size:none;overflow-y:auto}.ne-content__editor--labelled{grid-template-rows:auto minmax(0,1fr)}}@media(max-height:55rem){@container ne-side (min-width: 34rem){.ne-side{grid-template-areas:\"publish audience\" \"until preview\" \"tip preview\";grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:auto auto 1fr}}}.ne-row{display:flex;flex-wrap:wrap;gap:var(--hm-space-sm)}.ne-row>*{flex:1 1 8rem;min-inline-size:0}.ne-note{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.ne-preview{display:flex;flex-direction:column;gap:var(--hm-space-micro);padding:var(--hm-space-sm) var(--hm-space-md);border:var(--hm-border-hairline) solid var(--hm-divider);border-radius:var(--hm-radius);background:var(--hm-surface-raised)}.ne-preview__head{display:flex;align-items:center;gap:var(--hm-space-xs)}.ne-preview__heading{color:var(--hm-text);font-size:var(--hm-font-size-md);font-weight:var(--hm-font-weight-semibold)}.ne-preview__badge,.ne-preview__status{flex:none;padding:var(--hm-space-nano) var(--hm-space-xs);border-radius:var(--hm-radius-micro);background:var(--hm-accent-subtle);color:var(--hm-accent);font-size:var(--hm-font-size-3xs);font-weight:var(--hm-font-weight-semibold);letter-spacing:.04em;text-transform:uppercase}.ne-preview__item{display:flex;align-items:center;gap:var(--hm-space-sm);padding:var(--hm-space-xs) 0;border-block-start:var(--hm-border-hairline) solid var(--hm-divider)}.ne-preview__icon{display:grid;flex:none;place-items:center;inline-size:2rem;block-size:2rem;border-radius:var(--hm-radius-control);background:var(--hm-accent-subtle);color:var(--hm-accent)}.ne-preview__text{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--hm-space-nano);min-inline-size:0}.ne-preview__title{overflow:hidden;color:var(--hm-text);font-size:var(--hm-font-size-sm);font-weight:var(--hm-font-weight-semibold);text-overflow:ellipsis;white-space:nowrap}.ne-preview__summary{display:-webkit-box;overflow:hidden;color:var(--hm-muted);font-size:var(--hm-font-size-xs);overflow-wrap:anywhere;-webkit-box-orient:vertical;-webkit-line-clamp:2}.ne-preview__placeholder{color:var(--hm-muted);font-style:italic;font-weight:var(--hm-font-weight-regular)}.ne-preview__date{display:inline-flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-micro);color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.ne-preview__chevron{flex:none;color:var(--hm-muted)}.ne-tip{display:flex;align-items:flex-start;gap:var(--hm-space-xs);margin:0;padding:var(--hm-space-xs) var(--hm-space-sm);border-inline-start:var(--hm-border-thin) solid var(--hm-info);border-radius:var(--hm-radius-control);background:var(--hm-info-bg);color:var(--hm-text);font-size:var(--hm-font-size-xs)}@media(forced-colors:active){.ne-tip{border:var(--hm-border-hairline) solid CanvasText}}.ne-tip__icon{flex:none;color:var(--hm-info)}.ne-delete{margin-inline-end:auto}\n"] }]
|
|
398
|
+
}], ctorParameters: () => [], propDecorators: { clientId: [{ type: i0.Input, args: [{ isSignal: true, alias: "clientId", required: false }] }] } });
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Tela "Novidades" do auto-serviço (router `AUTO_SERVICE_NEWS_TEMPLATE_ROUTER_ID`, na raiz do menu; migration 0036 do
|
|
402
|
+
* argos): o seletor de client + o painel de novidades que era a aba Cliente › Novidades. Carregada só por
|
|
403
|
+
* `AUTO_SERVICE_SCREENS.news` -- nunca exportada pelo ponto de entrada (ver `public-api.ts`).
|
|
404
|
+
*/
|
|
405
|
+
class AutoServiceNewsPageComponent {
|
|
406
|
+
constructor() {
|
|
407
|
+
this.client = signal(null, ...(ngDevMode ? [{ debugName: "client" }] : /* istanbul ignore next */ []));
|
|
408
|
+
}
|
|
409
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: AutoServiceNewsPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
410
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: AutoServiceNewsPageComponent, isStandalone: true, selector: "spine-auto-service-news-page", ngImport: i0, template: `
|
|
411
|
+
<div class="as-stack">
|
|
412
|
+
<spine-auto-service-client-picker (clientChange)="client.set($event)" />
|
|
413
|
+
@if (client(); as c) {
|
|
414
|
+
<spine-auto-service-news [clientId]="c.id" />
|
|
415
|
+
}
|
|
416
|
+
</div>
|
|
417
|
+
`, isInline: true, styles: [".as-stack{display:flex;flex-direction:column;gap:var(--hm-space-md);min-inline-size:0}.as-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--hm-space-xs)}.as-field-row{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--hm-space-sm)}.as-field-row>hm-combobox{flex:1 1 16rem;min-inline-size:0}.as-summary{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-sm)}.as-summary__info{display:flex;flex:1 1 16rem;flex-direction:column;gap:var(--hm-space-micro);min-inline-size:0}.as-summary__title{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs);margin:0;color:var(--hm-text);font-size:var(--hm-font-size-md);font-weight:var(--hm-font-weight-semibold)}.as-summary__detail{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.muted{color:var(--hm-muted)}.as-empty{margin:var(--hm-space-xs) 0 0;font-size:var(--hm-font-size-sm)}.as-secret{display:grid;gap:var(--hm-space-micro)}.as-secret__label{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.as-secret__row{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.as-secret__value{flex:1 1 240px;min-width:0;border:var(--hm-border-hairline) solid var(--hm-divider);border-radius:var(--hm-radius-control);padding:var(--hm-space-xs) var(--hm-space-sm);background:var(--hm-surface-muted);color:var(--hm-text);font-family:var(--hm-font-mono);font-size:var(--hm-font-size-sm);overflow-wrap:anywhere;-webkit-user-select:all;user-select:all}:host{display:block;min-inline-size:0}\n"], dependencies: [{ kind: "component", type: AutoServiceClientPickerComponent, selector: "spine-auto-service-client-picker", outputs: ["clientChange"] }, { kind: "component", type: AutoServiceNewsComponent, selector: "spine-auto-service-news", inputs: ["clientId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
418
|
+
}
|
|
419
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: AutoServiceNewsPageComponent, decorators: [{
|
|
420
|
+
type: Component,
|
|
421
|
+
args: [{ selector: 'spine-auto-service-news-page', imports: [AutoServiceClientPickerComponent, AutoServiceNewsComponent], template: `
|
|
422
|
+
<div class="as-stack">
|
|
423
|
+
<spine-auto-service-client-picker (clientChange)="client.set($event)" />
|
|
424
|
+
@if (client(); as c) {
|
|
425
|
+
<spine-auto-service-news [clientId]="c.id" />
|
|
426
|
+
}
|
|
427
|
+
</div>
|
|
428
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".as-stack{display:flex;flex-direction:column;gap:var(--hm-space-md);min-inline-size:0}.as-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--hm-space-xs)}.as-field-row{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--hm-space-sm)}.as-field-row>hm-combobox{flex:1 1 16rem;min-inline-size:0}.as-summary{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-sm)}.as-summary__info{display:flex;flex:1 1 16rem;flex-direction:column;gap:var(--hm-space-micro);min-inline-size:0}.as-summary__title{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs);margin:0;color:var(--hm-text);font-size:var(--hm-font-size-md);font-weight:var(--hm-font-weight-semibold)}.as-summary__detail{margin:0;color:var(--hm-muted);font-size:var(--hm-font-size-sm)}.muted{color:var(--hm-muted)}.as-empty{margin:var(--hm-space-xs) 0 0;font-size:var(--hm-font-size-sm)}.as-secret{display:grid;gap:var(--hm-space-micro)}.as-secret__label{color:var(--hm-muted);font-size:var(--hm-font-size-xs)}.as-secret__row{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hm-space-xs)}.as-secret__value{flex:1 1 240px;min-width:0;border:var(--hm-border-hairline) solid var(--hm-divider);border-radius:var(--hm-radius-control);padding:var(--hm-space-xs) var(--hm-space-sm);background:var(--hm-surface-muted);color:var(--hm-text);font-family:var(--hm-font-mono);font-size:var(--hm-font-size-sm);overflow-wrap:anywhere;-webkit-user-select:all;user-select:all}:host{display:block;min-inline-size:0}\n"] }]
|
|
429
|
+
}] });
|
|
430
|
+
|
|
431
|
+
export { AutoServiceNewsPageComponent };
|
|
432
|
+
//# sourceMappingURL=trismegisto-spine-auto-service-auto-service-news-page.component-CBemH4hr.mjs.map
|