valtech-components 2.0.989 → 2.0.991
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/esm2022/lib/components/molecules/comment/comment.component.mjs +3 -3
- package/esm2022/lib/components/organisms/organization-view/organization-view.component.mjs +1065 -0
- package/esm2022/lib/components/organisms/organization-view/organization-view.i18n.mjs +148 -0
- package/esm2022/lib/components/organisms/organization-view/organization.routes.mjs +30 -0
- package/esm2022/lib/components/organisms/organization-view/types.mjs +2 -0
- package/esm2022/lib/services/preferences/preferences.service.mjs +10 -1
- package/esm2022/lib/version.mjs +2 -2
- package/esm2022/public-api.mjs +4 -1
- package/fesm2022/valtech-components.mjs +1505 -284
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/organisms/organization-view/organization-view.component.d.ts +104 -0
- package/lib/components/organisms/organization-view/organization-view.i18n.d.ts +9 -0
- package/lib/components/organisms/organization-view/organization.routes.d.ts +25 -0
- package/lib/components/organisms/organization-view/types.d.ts +61 -0
- package/lib/version.d.ts +1 -1
- package/package.json +1 -1
- package/public-api.d.ts +3 -0
|
@@ -54,7 +54,7 @@ import 'prismjs/components/prism-json';
|
|
|
54
54
|
* Current version of valtech-components.
|
|
55
55
|
* This is automatically updated during the publish process.
|
|
56
56
|
*/
|
|
57
|
-
const VERSION = '2.0.
|
|
57
|
+
const VERSION = '2.0.991';
|
|
58
58
|
|
|
59
59
|
// Control de estado de refresco (singleton a nivel de módulo)
|
|
60
60
|
let isRefreshing = false;
|
|
@@ -21657,7 +21657,7 @@ class CommentComponent {
|
|
|
21657
21657
|
</div>
|
|
21658
21658
|
}
|
|
21659
21659
|
</div>
|
|
21660
|
-
`, isInline: true, styles: [":host{display:block}.comment{--indent-size: 24px;--max-indent: 72px;padding:12px 0}.comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.08);border-radius:8px;padding:12px;margin:-4px}.comment.pinned{border-left:3px solid var(--ion-color-primary);padding-left:12px}.comment.collapsed{opacity:.7}.pinned-indicator{display:flex;align-items:center;gap:4px;font-size:.75rem;color:var(--ion-color-primary);margin-bottom:8px;padding-left:44px}.pinned-indicator ion-icon{font-size:.875rem}.comment-main{display:flex;gap:12px}.comment-avatar{flex-shrink:0;cursor:pointer}.comment-avatar val-avatar{--size: 36px}.comment-avatar .avatar-placeholder{width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,var(--ion-color-primary),var(--ion-color-secondary));display:flex;align-items:center;justify-content:center;color:#fff;font-size:.875rem;font-weight:600}.comment-body{flex:1;min-width:0}.comment-header{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-bottom:4px}.author-info{display:flex;align-items:center;gap:4px;cursor:pointer}.author-info:hover .author-name{text-decoration:underline}.author-name{font-weight:600;font-size:.875rem;color:var(--ion-text-color)}.verified-badge{color:var(--ion-color-primary);font-size:1rem}.author-username{font-size:.8125rem;color:var(--ion-color-medium)}.comment-meta{display:flex;align-items:center;gap:6px;margin-left:auto}.timestamp{font-size:.75rem;color:var(--ion-color-medium)}.edited-label{font-size:.6875rem;color:var(--ion-color-medium);font-style:italic}.more-button{--padding-start: 4px;--padding-end: 4px;margin:0;height:28px}.more-button ion-icon{font-size:1.125rem;color:var(--ion-color-medium)}.menu-divider{height:1px;background-color:var(--ion-color-light);margin:4px 0}.comment-content{font-size:.875rem;line-height:1.5;color:var(--ion-text-color);word-wrap:break-word;overflow-wrap:break-word}.comment-content :global(.comment-link){color:var(--ion-color-primary);text-decoration:none}.comment-content :global(.comment-link):hover{text-decoration:underline}.comment-content :global(.comment-mention){color:var(--ion-color-primary);font-weight:500;cursor:pointer}.comment-content :global(.comment-mention):hover{text-decoration:underline}.comment-content :global(.comment-hashtag){color:var(--ion-color-primary);cursor:pointer}.comment-content :global(.comment-hashtag):hover{text-decoration:underline}.comment-reactions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}.reaction-button{display:flex;align-items:center;gap:4px;background:none;border:none;padding:4px 8px;border-radius:16px;cursor:pointer;font-size:.8125rem;color:var(--reaction-color, var(--ion-color-medium));transition:all .2s ease;background-color:transparent}.reaction-button:hover{background-color:rgba(var(--ion-color-medium-rgb),.1)}.reaction-button.active{background-color:rgba(var(--ion-color-primary-rgb),.1)}.reaction-button.active ion-icon{transform:scale(1.1)}.reaction-button ion-icon{font-size:1.125rem;transition:transform .2s ease}.reaction-button .reaction-count{font-weight:500}.comment-actions{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;margin-left:-8px}.comment-actions ion-button{--padding-start: 8px;--padding-end: 8px;font-size:.8125rem;height:32px;text-transform:none;font-weight:500}.expand-button,.collapse-button,.load-more-button,.view-replies-button{display:flex;align-items:center;gap:6px;background:none;border:none;padding:8px 12px;cursor:pointer;font-size:.8125rem;color:var(--ion-color-primary);border-radius:8px;transition:background-color .2s}.expand-button:hover,.collapse-button:hover,.load-more-button:hover,.view-replies-button:hover{background-color:rgba(var(--ion-color-primary-rgb),.1)}.expand-button ion-icon,.collapse-button ion-icon,.load-more-button ion-icon,.view-replies-button ion-icon{font-size:1rem}.expand-button{margin-top:4px;color:var(--ion-color-medium)}.comment-children{margin-top:12px;padding-left:min(var(--indent-size),var(--max-indent));border-left:2px solid var(--ion-color-light-shade)}.comment-children val-comment{display:block}.comment-children val-comment:first-of-type .comment{padding-top:0}.load-more-button,.view-replies-button{margin-top:8px;margin-left:0}ion-popover{--width: 200px}ion-popover ion-list{padding:4px 0}ion-popover ion-item{--min-height: 40px;--padding-start: 12px;font-size:.875rem}ion-popover ion-item ion-icon{font-size:1.125rem;margin-right:8px}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 2px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 2px);height:max(28px,36px - 2px);font-size:max(11px,14px - 1px)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 4px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 4px);height:max(28px,36px - 4px);font-size:max(11px,14px - 2px)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 6px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 6px);height:max(28px,36px - 6px);font-size:max(11px,14px - 3px)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 8px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 8px);height:max(28px,36px - 8px);font-size:max(11px,14px - 4px)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 10px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 10px);height:max(28px,36px - 10px);font-size:max(11px,14px - 5px)}:host-context(.dark) .comment.highlighted,:host-context(.ion-palette-dark) .comment.highlighted,:host-context(html.ion-palette-dark) .comment.highlighted,:host-context(body.dark) .comment.highlighted,:host-context([data-theme=dark]) .comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.12)}:host-context(.dark) .avatar-placeholder,:host-context(.ion-palette-dark) .avatar-placeholder,:host-context(html.ion-palette-dark) .avatar-placeholder,:host-context(body.dark) .avatar-placeholder,:host-context([data-theme=dark]) .avatar-placeholder{background:linear-gradient(135deg,var(--ion-color-primary-shade),var(--ion-color-secondary-shade))}\n"], dependencies: [{ kind: "component", type: CommentComponent, selector: "val-comment", inputs: ["props"], outputs: ["authorClick", "reactionClick", "actionClick", "menuItemClick", "loadMoreClick", "collapseToggle"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonPopover, selector: "ion-popover" }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: AvatarComponent, selector: "val-avatar", inputs: ["preset", "props"], outputs: ["onClick"] }] }); }
|
|
21660
|
+
`, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}:host{display:block}.comment{--indent-size: 24px;--max-indent: 72px;padding:12px 0}.comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.08);border-radius:8px;padding:12px;margin:-4px}.comment.pinned{border-left:3px solid var(--ion-color-primary);padding-left:12px}.comment.collapsed{opacity:.7}.pinned-indicator{display:flex;align-items:center;gap:4px;font-size:.75rem;color:var(--ion-color-primary);margin-bottom:8px;padding-left:44px}.pinned-indicator ion-icon{font-size:.875rem}.comment-main{display:flex;gap:12px}.comment-avatar{flex-shrink:0;cursor:pointer}.comment-avatar val-avatar{--size: 36px}.comment-avatar .avatar-placeholder{width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,var(--ion-color-primary),var(--ion-color-secondary));display:flex;align-items:center;justify-content:center;color:#fff;font-size:.875rem;font-weight:600}.comment-body{flex:1;min-width:0}.comment-header{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-bottom:4px}.author-info{display:flex;align-items:center;gap:4px;cursor:pointer}.author-info:hover .author-name{text-decoration:underline}.author-name{font-weight:600;font-size:.875rem;color:var(--ion-text-color)}.verified-badge{color:var(--ion-color-primary);font-size:1rem}.author-username{font-size:.8125rem;color:var(--ion-color-medium)}.comment-meta{display:flex;align-items:center;gap:6px;margin-left:auto}.timestamp{font-size:.75rem;color:var(--ion-color-medium)}.edited-label{font-size:.6875rem;color:var(--ion-color-medium);font-style:italic}.more-button{--padding-start: 4px;--padding-end: 4px;margin:0;height:28px}.more-button ion-icon{font-size:1.125rem;color:var(--ion-color-medium)}.menu-divider{height:1px;background-color:var(--ion-color-light);margin:4px 0}.comment-content{font-size:.875rem;line-height:1.5;color:var(--ion-text-color);word-wrap:break-word;overflow-wrap:break-word}.comment-content :global(.comment-link){color:var(--ion-color-primary);text-decoration:none}.comment-content :global(.comment-link):hover{text-decoration:underline}.comment-content :global(.comment-mention){color:var(--ion-color-primary);font-weight:500;cursor:pointer}.comment-content :global(.comment-mention):hover{text-decoration:underline}.comment-content :global(.comment-hashtag){color:var(--ion-color-primary);cursor:pointer}.comment-content :global(.comment-hashtag):hover{text-decoration:underline}.comment-reactions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}.reaction-button{display:flex;align-items:center;gap:4px;background:none;border:none;padding:4px 8px;border-radius:16px;cursor:pointer;font-size:.8125rem;color:var(--reaction-color, var(--ion-color-medium));transition:all .2s ease;background-color:transparent}.reaction-button:hover{background-color:rgba(var(--ion-color-medium-rgb),.1)}.reaction-button.active{background-color:rgba(var(--ion-color-primary-rgb),.1)}.reaction-button.active ion-icon{transform:scale(1.1)}.reaction-button ion-icon{font-size:1.125rem;transition:transform .2s ease}.reaction-button .reaction-count{font-weight:500}.comment-actions{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;margin-left:-8px}.comment-actions ion-button{--padding-start: 8px;--padding-end: 8px;font-size:.8125rem;height:32px;text-transform:none;font-weight:500}.expand-button,.collapse-button,.load-more-button,.view-replies-button{display:flex;align-items:center;gap:6px;background:none;border:none;padding:8px 12px;cursor:pointer;font-size:.8125rem;color:var(--ion-color-primary);border-radius:8px;transition:background-color .2s}.expand-button:hover,.collapse-button:hover,.load-more-button:hover,.view-replies-button:hover{background-color:rgba(var(--ion-color-primary-rgb),.1)}.expand-button ion-icon,.collapse-button ion-icon,.load-more-button ion-icon,.view-replies-button ion-icon{font-size:1rem}.expand-button{margin-top:4px;color:var(--ion-color-medium)}.comment-children{margin-top:12px;padding-left:min(var(--indent-size),var(--max-indent));border-left:2px solid var(--ion-color-light-shade)}.comment-children val-comment{display:block}.comment-children val-comment:first-of-type .comment{padding-top:0}.load-more-button,.view-replies-button{margin-top:8px;margin-left:0}ion-popover{--width: 200px}ion-popover ion-list{padding:4px 0}ion-popover ion-item{--min-height: 40px;--padding-start: 12px;font-size:.875rem}ion-popover ion-item ion-icon{font-size:1.125rem;margin-right:8px}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 2px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 2px);height:max(28px,36px - 2px);font-size:max(.6875rem,.8125rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 4px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 4px);height:max(28px,36px - 4px);font-size:max(.6875rem,.75rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 6px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 6px);height:max(28px,36px - 6px);font-size:max(.6875rem,.6875rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 8px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 8px);height:max(28px,36px - 8px);font-size:max(.6875rem,.625rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 10px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 10px);height:max(28px,36px - 10px);font-size:max(.6875rem,.5625rem)}:host-context(.dark) .comment.highlighted,:host-context(.ion-palette-dark) .comment.highlighted,:host-context(html.ion-palette-dark) .comment.highlighted,:host-context(body.dark) .comment.highlighted,:host-context([data-theme=dark]) .comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.12)}:host-context(.dark) .avatar-placeholder,:host-context(.ion-palette-dark) .avatar-placeholder,:host-context(html.ion-palette-dark) .avatar-placeholder,:host-context(body.dark) .avatar-placeholder,:host-context([data-theme=dark]) .avatar-placeholder{background:linear-gradient(135deg,var(--ion-color-primary-shade),var(--ion-color-secondary-shade))}\n"], dependencies: [{ kind: "component", type: CommentComponent, selector: "val-comment", inputs: ["props"], outputs: ["authorClick", "reactionClick", "actionClick", "menuItemClick", "loadMoreClick", "collapseToggle"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonPopover, selector: "ion-popover" }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: AvatarComponent, selector: "val-avatar", inputs: ["preset", "props"], outputs: ["onClick"] }] }); }
|
|
21661
21661
|
}
|
|
21662
21662
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CommentComponent, decorators: [{
|
|
21663
21663
|
type: Component,
|
|
@@ -21847,7 +21847,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
21847
21847
|
</div>
|
|
21848
21848
|
}
|
|
21849
21849
|
</div>
|
|
21850
|
-
`, styles: [":host{display:block}.comment{--indent-size: 24px;--max-indent: 72px;padding:12px 0}.comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.08);border-radius:8px;padding:12px;margin:-4px}.comment.pinned{border-left:3px solid var(--ion-color-primary);padding-left:12px}.comment.collapsed{opacity:.7}.pinned-indicator{display:flex;align-items:center;gap:4px;font-size:.75rem;color:var(--ion-color-primary);margin-bottom:8px;padding-left:44px}.pinned-indicator ion-icon{font-size:.875rem}.comment-main{display:flex;gap:12px}.comment-avatar{flex-shrink:0;cursor:pointer}.comment-avatar val-avatar{--size: 36px}.comment-avatar .avatar-placeholder{width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,var(--ion-color-primary),var(--ion-color-secondary));display:flex;align-items:center;justify-content:center;color:#fff;font-size:.875rem;font-weight:600}.comment-body{flex:1;min-width:0}.comment-header{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-bottom:4px}.author-info{display:flex;align-items:center;gap:4px;cursor:pointer}.author-info:hover .author-name{text-decoration:underline}.author-name{font-weight:600;font-size:.875rem;color:var(--ion-text-color)}.verified-badge{color:var(--ion-color-primary);font-size:1rem}.author-username{font-size:.8125rem;color:var(--ion-color-medium)}.comment-meta{display:flex;align-items:center;gap:6px;margin-left:auto}.timestamp{font-size:.75rem;color:var(--ion-color-medium)}.edited-label{font-size:.6875rem;color:var(--ion-color-medium);font-style:italic}.more-button{--padding-start: 4px;--padding-end: 4px;margin:0;height:28px}.more-button ion-icon{font-size:1.125rem;color:var(--ion-color-medium)}.menu-divider{height:1px;background-color:var(--ion-color-light);margin:4px 0}.comment-content{font-size:.875rem;line-height:1.5;color:var(--ion-text-color);word-wrap:break-word;overflow-wrap:break-word}.comment-content :global(.comment-link){color:var(--ion-color-primary);text-decoration:none}.comment-content :global(.comment-link):hover{text-decoration:underline}.comment-content :global(.comment-mention){color:var(--ion-color-primary);font-weight:500;cursor:pointer}.comment-content :global(.comment-mention):hover{text-decoration:underline}.comment-content :global(.comment-hashtag){color:var(--ion-color-primary);cursor:pointer}.comment-content :global(.comment-hashtag):hover{text-decoration:underline}.comment-reactions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}.reaction-button{display:flex;align-items:center;gap:4px;background:none;border:none;padding:4px 8px;border-radius:16px;cursor:pointer;font-size:.8125rem;color:var(--reaction-color, var(--ion-color-medium));transition:all .2s ease;background-color:transparent}.reaction-button:hover{background-color:rgba(var(--ion-color-medium-rgb),.1)}.reaction-button.active{background-color:rgba(var(--ion-color-primary-rgb),.1)}.reaction-button.active ion-icon{transform:scale(1.1)}.reaction-button ion-icon{font-size:1.125rem;transition:transform .2s ease}.reaction-button .reaction-count{font-weight:500}.comment-actions{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;margin-left:-8px}.comment-actions ion-button{--padding-start: 8px;--padding-end: 8px;font-size:.8125rem;height:32px;text-transform:none;font-weight:500}.expand-button,.collapse-button,.load-more-button,.view-replies-button{display:flex;align-items:center;gap:6px;background:none;border:none;padding:8px 12px;cursor:pointer;font-size:.8125rem;color:var(--ion-color-primary);border-radius:8px;transition:background-color .2s}.expand-button:hover,.collapse-button:hover,.load-more-button:hover,.view-replies-button:hover{background-color:rgba(var(--ion-color-primary-rgb),.1)}.expand-button ion-icon,.collapse-button ion-icon,.load-more-button ion-icon,.view-replies-button ion-icon{font-size:1rem}.expand-button{margin-top:4px;color:var(--ion-color-medium)}.comment-children{margin-top:12px;padding-left:min(var(--indent-size),var(--max-indent));border-left:2px solid var(--ion-color-light-shade)}.comment-children val-comment{display:block}.comment-children val-comment:first-of-type .comment{padding-top:0}.load-more-button,.view-replies-button{margin-top:8px;margin-left:0}ion-popover{--width: 200px}ion-popover ion-list{padding:4px 0}ion-popover ion-item{--min-height: 40px;--padding-start: 12px;font-size:.875rem}ion-popover ion-item ion-icon{font-size:1.125rem;margin-right:8px}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 2px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 2px);height:max(28px,36px - 2px);font-size:max(
|
|
21850
|
+
`, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}:host{display:block}.comment{--indent-size: 24px;--max-indent: 72px;padding:12px 0}.comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.08);border-radius:8px;padding:12px;margin:-4px}.comment.pinned{border-left:3px solid var(--ion-color-primary);padding-left:12px}.comment.collapsed{opacity:.7}.pinned-indicator{display:flex;align-items:center;gap:4px;font-size:.75rem;color:var(--ion-color-primary);margin-bottom:8px;padding-left:44px}.pinned-indicator ion-icon{font-size:.875rem}.comment-main{display:flex;gap:12px}.comment-avatar{flex-shrink:0;cursor:pointer}.comment-avatar val-avatar{--size: 36px}.comment-avatar .avatar-placeholder{width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,var(--ion-color-primary),var(--ion-color-secondary));display:flex;align-items:center;justify-content:center;color:#fff;font-size:.875rem;font-weight:600}.comment-body{flex:1;min-width:0}.comment-header{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-bottom:4px}.author-info{display:flex;align-items:center;gap:4px;cursor:pointer}.author-info:hover .author-name{text-decoration:underline}.author-name{font-weight:600;font-size:.875rem;color:var(--ion-text-color)}.verified-badge{color:var(--ion-color-primary);font-size:1rem}.author-username{font-size:.8125rem;color:var(--ion-color-medium)}.comment-meta{display:flex;align-items:center;gap:6px;margin-left:auto}.timestamp{font-size:.75rem;color:var(--ion-color-medium)}.edited-label{font-size:.6875rem;color:var(--ion-color-medium);font-style:italic}.more-button{--padding-start: 4px;--padding-end: 4px;margin:0;height:28px}.more-button ion-icon{font-size:1.125rem;color:var(--ion-color-medium)}.menu-divider{height:1px;background-color:var(--ion-color-light);margin:4px 0}.comment-content{font-size:.875rem;line-height:1.5;color:var(--ion-text-color);word-wrap:break-word;overflow-wrap:break-word}.comment-content :global(.comment-link){color:var(--ion-color-primary);text-decoration:none}.comment-content :global(.comment-link):hover{text-decoration:underline}.comment-content :global(.comment-mention){color:var(--ion-color-primary);font-weight:500;cursor:pointer}.comment-content :global(.comment-mention):hover{text-decoration:underline}.comment-content :global(.comment-hashtag){color:var(--ion-color-primary);cursor:pointer}.comment-content :global(.comment-hashtag):hover{text-decoration:underline}.comment-reactions{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}.reaction-button{display:flex;align-items:center;gap:4px;background:none;border:none;padding:4px 8px;border-radius:16px;cursor:pointer;font-size:.8125rem;color:var(--reaction-color, var(--ion-color-medium));transition:all .2s ease;background-color:transparent}.reaction-button:hover{background-color:rgba(var(--ion-color-medium-rgb),.1)}.reaction-button.active{background-color:rgba(var(--ion-color-primary-rgb),.1)}.reaction-button.active ion-icon{transform:scale(1.1)}.reaction-button ion-icon{font-size:1.125rem;transition:transform .2s ease}.reaction-button .reaction-count{font-weight:500}.comment-actions{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;margin-left:-8px}.comment-actions ion-button{--padding-start: 8px;--padding-end: 8px;font-size:.8125rem;height:32px;text-transform:none;font-weight:500}.expand-button,.collapse-button,.load-more-button,.view-replies-button{display:flex;align-items:center;gap:6px;background:none;border:none;padding:8px 12px;cursor:pointer;font-size:.8125rem;color:var(--ion-color-primary);border-radius:8px;transition:background-color .2s}.expand-button:hover,.collapse-button:hover,.load-more-button:hover,.view-replies-button:hover{background-color:rgba(var(--ion-color-primary-rgb),.1)}.expand-button ion-icon,.collapse-button ion-icon,.load-more-button ion-icon,.view-replies-button ion-icon{font-size:1rem}.expand-button{margin-top:4px;color:var(--ion-color-medium)}.comment-children{margin-top:12px;padding-left:min(var(--indent-size),var(--max-indent));border-left:2px solid var(--ion-color-light-shade)}.comment-children val-comment{display:block}.comment-children val-comment:first-of-type .comment{padding-top:0}.load-more-button,.view-replies-button{margin-top:8px;margin-left:0}ion-popover{--width: 200px}ion-popover ion-list{padding:4px 0}ion-popover ion-item{--min-height: 40px;--padding-start: 12px;font-size:.875rem}ion-popover ion-item ion-icon{font-size:1.125rem;margin-right:8px}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 2px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 2px);height:max(28px,36px - 2px);font-size:max(.6875rem,.8125rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 4px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 4px);height:max(28px,36px - 4px);font-size:max(.6875rem,.75rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 6px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 6px);height:max(28px,36px - 6px);font-size:max(.6875rem,.6875rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 8px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 8px);height:max(28px,36px - 8px);font-size:max(.6875rem,.625rem)}:host-context(val-comment) .comment-avatar val-avatar{--size: max(28px, 36px - 10px)}:host-context(val-comment) .comment-avatar .avatar-placeholder{width:max(28px,36px - 10px);height:max(28px,36px - 10px);font-size:max(.6875rem,.5625rem)}:host-context(.dark) .comment.highlighted,:host-context(.ion-palette-dark) .comment.highlighted,:host-context(html.ion-palette-dark) .comment.highlighted,:host-context(body.dark) .comment.highlighted,:host-context([data-theme=dark]) .comment.highlighted{background-color:rgba(var(--ion-color-primary-rgb),.12)}:host-context(.dark) .avatar-placeholder,:host-context(.ion-palette-dark) .avatar-placeholder,:host-context(html.ion-palette-dark) .avatar-placeholder,:host-context(body.dark) .avatar-placeholder,:host-context([data-theme=dark]) .avatar-placeholder{background:linear-gradient(135deg,var(--ion-color-primary-shade),var(--ion-color-secondary-shade))}\n"] }]
|
|
21851
21851
|
}], propDecorators: { props: [{
|
|
21852
21852
|
type: Input
|
|
21853
21853
|
}], authorClick: [{
|
|
@@ -41737,7 +41737,7 @@ const PROFILE_VIEW_I18N = {
|
|
|
41737
41737
|
const HANDLE_PATTERN = /^[a-z_][a-z0-9_]*$/;
|
|
41738
41738
|
const HANDLE_MIN = 3;
|
|
41739
41739
|
const HANDLE_MAX = 20;
|
|
41740
|
-
const DEFAULT_NAMESPACE$
|
|
41740
|
+
const DEFAULT_NAMESPACE$c = 'Settings.Profile';
|
|
41741
41741
|
/**
|
|
41742
41742
|
* `val-profile-view` — vista Perfil full-feature autocontenida (organism).
|
|
41743
41743
|
*
|
|
@@ -41787,7 +41787,7 @@ class ProfileViewComponent {
|
|
|
41787
41787
|
showPhone: merged.showPhone ?? true,
|
|
41788
41788
|
showShareCta: merged.showShareCta ?? true,
|
|
41789
41789
|
profileBaseUrl: merged.profileBaseUrl ?? '',
|
|
41790
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
41790
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$c,
|
|
41791
41791
|
onSaved: merged.onSaved,
|
|
41792
41792
|
onAvatarUploaded: merged.onAvatarUploaded,
|
|
41793
41793
|
};
|
|
@@ -42489,6 +42489,15 @@ class PreferencesService {
|
|
|
42489
42489
|
this._updateInFlight = false;
|
|
42490
42490
|
const destroyRef = inject(DestroyRef);
|
|
42491
42491
|
destroyRef.onDestroy(() => this.unbind());
|
|
42492
|
+
// Seed `_fontSize` con el valor que FontSizeService ya restauró desde
|
|
42493
|
+
// localStorage en su constructor (providedIn root → ya corrió al inyectarlo
|
|
42494
|
+
// acá). Sin esto, el signal arranca en 'medium' y el effect de abajo —que
|
|
42495
|
+
// dispara al marcarse `synced`— forzaría 'medium' pisando el tamaño
|
|
42496
|
+
// restaurado cuando el snapshot Firestore NO trae `fontSize` (user sin ese
|
|
42497
|
+
// campo en el mirror). Bug: cambias el tamaño, refrescas y se pierde.
|
|
42498
|
+
if (this.fontSizeService) {
|
|
42499
|
+
this._fontSize.set(this.fontSizeService.size());
|
|
42500
|
+
}
|
|
42492
42501
|
// Auto-bind al user actual. effect() corre en injection context (constructor OK).
|
|
42493
42502
|
// allowSignalWrites: bindToUser/unbind escriben `_synced` (señal interna sin
|
|
42494
42503
|
// dependencias del propio effect) → seguro y necesario.
|
|
@@ -42703,7 +42712,7 @@ const PREFERENCES_VIEW_I18N = {
|
|
|
42703
42712
|
},
|
|
42704
42713
|
};
|
|
42705
42714
|
|
|
42706
|
-
const DEFAULT_NAMESPACE$
|
|
42715
|
+
const DEFAULT_NAMESPACE$b = 'Settings.General';
|
|
42707
42716
|
const DEFAULT_LANGUAGES = ['es', 'en'];
|
|
42708
42717
|
/**
|
|
42709
42718
|
* `val-preferences-view` — vista de preferencias de UI cross-app (tema +
|
|
@@ -42740,7 +42749,7 @@ class PreferencesViewComponent {
|
|
|
42740
42749
|
showLanguage: merged.showLanguage ?? true,
|
|
42741
42750
|
showFontSize: merged.showFontSize ?? true,
|
|
42742
42751
|
supportedLanguages: merged.supportedLanguages ?? DEFAULT_LANGUAGES,
|
|
42743
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
42752
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$b,
|
|
42744
42753
|
onThemeChanged: merged.onThemeChanged,
|
|
42745
42754
|
onLanguageChanged: merged.onLanguageChanged,
|
|
42746
42755
|
onFontSizeChanged: merged.onFontSizeChanged,
|
|
@@ -44552,7 +44561,7 @@ const SECURITY_VIEW_I18N = {
|
|
|
44552
44561
|
};
|
|
44553
44562
|
|
|
44554
44563
|
addIcons({ laptopOutline, phonePortraitOutline });
|
|
44555
|
-
const DEFAULT_NAMESPACE$
|
|
44564
|
+
const DEFAULT_NAMESPACE$a = 'Settings.Security';
|
|
44556
44565
|
/**
|
|
44557
44566
|
* `val-security-view` — vista Seguridad full-feature autocontenida (organism).
|
|
44558
44567
|
*
|
|
@@ -44601,7 +44610,7 @@ class SecurityViewComponent {
|
|
|
44601
44610
|
showChangeEmail: merged.showChangeEmail ?? true,
|
|
44602
44611
|
showMfa: merged.showMfa ?? true,
|
|
44603
44612
|
showPolicies: merged.showPolicies ?? true,
|
|
44604
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
44613
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$a,
|
|
44605
44614
|
handleDeepLinks: merged.handleDeepLinks ?? true,
|
|
44606
44615
|
homeRoute: merged.homeRoute ?? '/app/home',
|
|
44607
44616
|
onMfaCompleted: merged.onMfaCompleted,
|
|
@@ -45507,7 +45516,7 @@ const CREATE_ORG_MODAL_I18N = {
|
|
|
45507
45516
|
},
|
|
45508
45517
|
};
|
|
45509
45518
|
|
|
45510
|
-
const DEFAULT_NAMESPACE$
|
|
45519
|
+
const DEFAULT_NAMESPACE$9 = 'CreateOrgModal';
|
|
45511
45520
|
/**
|
|
45512
45521
|
* `val-create-org-modal` — modal de creación de organización (organism
|
|
45513
45522
|
* compartido). Promovido desde `showcase` bajo el proceso de ADR-021. Reusado por
|
|
@@ -45533,10 +45542,10 @@ class CreateOrgModalComponent {
|
|
|
45533
45542
|
this.toast = inject(ToastService);
|
|
45534
45543
|
this.errors = inject(ValtechErrorService);
|
|
45535
45544
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
45536
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
45545
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$9;
|
|
45537
45546
|
this._busy = signal(false);
|
|
45538
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
45539
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
45547
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$9)) {
|
|
45548
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$9, CREATE_ORG_MODAL_I18N);
|
|
45540
45549
|
}
|
|
45541
45550
|
this.formMeta = signal(this.buildFormMeta());
|
|
45542
45551
|
effect(() => {
|
|
@@ -45772,7 +45781,7 @@ const DELETE_ACCOUNT_MODAL_I18N = {
|
|
|
45772
45781
|
},
|
|
45773
45782
|
};
|
|
45774
45783
|
|
|
45775
|
-
const DEFAULT_NAMESPACE$
|
|
45784
|
+
const DEFAULT_NAMESPACE$8 = 'Settings.DeleteAccount';
|
|
45776
45785
|
/**
|
|
45777
45786
|
* `val-delete-account-modal` — modal de eliminación de cuenta (organism,
|
|
45778
45787
|
* cuenta-específico). Promovido desde `showcase` bajo el proceso de ADR-021.
|
|
@@ -45798,7 +45807,7 @@ class DeleteAccountModalComponent {
|
|
|
45798
45807
|
this.i18n = inject(I18nService);
|
|
45799
45808
|
this.toast = inject(ToastService);
|
|
45800
45809
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
45801
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
45810
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$8;
|
|
45802
45811
|
this.hasPassword = signal(null);
|
|
45803
45812
|
this.codeSent = signal(false);
|
|
45804
45813
|
this.formState = signal(ComponentStates.ENABLED);
|
|
@@ -45865,8 +45874,8 @@ class DeleteAccountModalComponent {
|
|
|
45865
45874
|
],
|
|
45866
45875
|
actions: this.submitBtn('delete-code-submit', 'confirmCta'),
|
|
45867
45876
|
}));
|
|
45868
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
45869
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
45877
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$8)) {
|
|
45878
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$8, DELETE_ACCOUNT_MODAL_I18N);
|
|
45870
45879
|
}
|
|
45871
45880
|
}
|
|
45872
45881
|
ngOnInit() {
|
|
@@ -46067,7 +46076,7 @@ const ORG_INFO_SHEET_I18N = {
|
|
|
46067
46076
|
},
|
|
46068
46077
|
};
|
|
46069
46078
|
|
|
46070
|
-
const DEFAULT_NAMESPACE$
|
|
46079
|
+
const DEFAULT_NAMESPACE$7 = 'OrgInfoSheet';
|
|
46071
46080
|
/**
|
|
46072
46081
|
* `val-org-info-sheet` — sheet informativo "¿Qué son las organizaciones?".
|
|
46073
46082
|
* Extraído del `OrgInfoSheetComponent` inline de `AccountPage` bajo el proceso de
|
|
@@ -46112,15 +46121,15 @@ class OrgInfoSheetComponent {
|
|
|
46112
46121
|
text: this.closeProps.text || this.resolvedCloseLabel(),
|
|
46113
46122
|
}));
|
|
46114
46123
|
addIcons({ peopleOutline, swapHorizontalOutline, mailOutline });
|
|
46115
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
46116
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
46124
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$7)) {
|
|
46125
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$7, ORG_INFO_SHEET_I18N);
|
|
46117
46126
|
}
|
|
46118
46127
|
}
|
|
46119
46128
|
dismiss() {
|
|
46120
46129
|
this._modalRef?.dismiss(null, 'cancel');
|
|
46121
46130
|
}
|
|
46122
46131
|
tt(key) {
|
|
46123
|
-
return this.i18n.t(key, DEFAULT_NAMESPACE$
|
|
46132
|
+
return this.i18n.t(key, DEFAULT_NAMESPACE$7);
|
|
46124
46133
|
}
|
|
46125
46134
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OrgInfoSheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
46126
46135
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: OrgInfoSheetComponent, isStandalone: true, selector: "val-org-info-sheet", inputs: { title: "title", subtitle: "subtitle", body: "body", closeLabel: "closeLabel", closeProps: "closeProps", _modalRef: "_modalRef" }, ngImport: i0, template: `
|
|
@@ -46287,7 +46296,7 @@ const SWITCH_ORG_MODAL_I18N = {
|
|
|
46287
46296
|
},
|
|
46288
46297
|
};
|
|
46289
46298
|
|
|
46290
|
-
const DEFAULT_NAMESPACE$
|
|
46299
|
+
const DEFAULT_NAMESPACE$6 = 'Settings.SwitchOrg';
|
|
46291
46300
|
addIcons({ businessOutline, checkmarkCircleOutline });
|
|
46292
46301
|
/**
|
|
46293
46302
|
* `val-switch-org-modal` — modal de cambio de organización activa (organism
|
|
@@ -46313,7 +46322,7 @@ class SwitchOrgModalComponent {
|
|
|
46313
46322
|
this.orgSwitch = inject(OrgSwitchService);
|
|
46314
46323
|
this.errors = inject(ValtechErrorService);
|
|
46315
46324
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
46316
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
46325
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$6;
|
|
46317
46326
|
this.orgs = signal([]);
|
|
46318
46327
|
this.loading = signal(false);
|
|
46319
46328
|
this.query = signal('');
|
|
@@ -46329,8 +46338,8 @@ class SwitchOrgModalComponent {
|
|
|
46329
46338
|
return list;
|
|
46330
46339
|
return list.filter(o => o.name.toLowerCase().includes(q));
|
|
46331
46340
|
});
|
|
46332
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
46333
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
46341
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$6)) {
|
|
46342
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$6, SWITCH_ORG_MODAL_I18N);
|
|
46334
46343
|
}
|
|
46335
46344
|
this.loadOrgs();
|
|
46336
46345
|
}
|
|
@@ -46648,7 +46657,7 @@ const ACCOUNT_VIEW_I18N = {
|
|
|
46648
46657
|
};
|
|
46649
46658
|
|
|
46650
46659
|
addIcons({ peopleOutline, businessOutline, chevronForwardOutline, swapHorizontalOutline, mailOutline });
|
|
46651
|
-
const DEFAULT_NAMESPACE$
|
|
46660
|
+
const DEFAULT_NAMESPACE$5 = 'Settings.Account';
|
|
46652
46661
|
const DEFAULT_MANAGE_ORG_ROUTE = '/app/settings/organization';
|
|
46653
46662
|
/**
|
|
46654
46663
|
* `val-account-view` — vista Cuenta full-feature autocontenida (organism).
|
|
@@ -46689,7 +46698,7 @@ class AccountViewComponent {
|
|
|
46689
46698
|
showNewOrgCta: merged.showNewOrgCta ?? true,
|
|
46690
46699
|
showLogout: merged.showLogout ?? true,
|
|
46691
46700
|
showDeleteAccount: merged.showDeleteAccount ?? true,
|
|
46692
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
46701
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$5,
|
|
46693
46702
|
manageOrgRoute: merged.manageOrgRoute ?? DEFAULT_MANAGE_ORG_ROUTE,
|
|
46694
46703
|
onOrgSwitched: merged.onOrgSwitched,
|
|
46695
46704
|
onOrgCreated: merged.onOrgCreated,
|
|
@@ -47376,6 +47385,258 @@ function provideValtechAccountRoutes(opts) {
|
|
|
47376
47385
|
];
|
|
47377
47386
|
}
|
|
47378
47387
|
|
|
47388
|
+
/**
|
|
47389
|
+
* Defaults i18n (es/en) embebidos en `val-edit-org-modal`. Auto-registrados en
|
|
47390
|
+
* el constructor del componente si el consumer no proveyó el namespace
|
|
47391
|
+
* (`EditOrgModal` por default). SOLO incluye las keys que el modal usa.
|
|
47392
|
+
*/
|
|
47393
|
+
const EDIT_ORG_MODAL_I18N = {
|
|
47394
|
+
es: {
|
|
47395
|
+
title: 'Editar organización',
|
|
47396
|
+
subtitle: 'Actualiza el nombre y descripción.',
|
|
47397
|
+
nameLabel: 'Nombre',
|
|
47398
|
+
namePlaceholder: 'Nombre de la organización',
|
|
47399
|
+
nameRequired: 'El nombre es obligatorio.',
|
|
47400
|
+
nameMin: 'Mínimo 2 caracteres.',
|
|
47401
|
+
descriptionLabel: 'Descripción (opcional)',
|
|
47402
|
+
descriptionPlaceholder: 'Describe tu organización',
|
|
47403
|
+
saveCta: 'Guardar cambios',
|
|
47404
|
+
close: 'Cancelar',
|
|
47405
|
+
saveSuccess: 'Organización actualizada.',
|
|
47406
|
+
saveError: 'No se pudo guardar. Intenta de nuevo.',
|
|
47407
|
+
fillRequired: 'Completa todos los campos requeridos.',
|
|
47408
|
+
},
|
|
47409
|
+
en: {
|
|
47410
|
+
title: 'Edit organization',
|
|
47411
|
+
subtitle: 'Update the name and description.',
|
|
47412
|
+
nameLabel: 'Name',
|
|
47413
|
+
namePlaceholder: 'Organization name',
|
|
47414
|
+
nameRequired: 'Name is required.',
|
|
47415
|
+
nameMin: 'Minimum 2 characters.',
|
|
47416
|
+
descriptionLabel: 'Description (optional)',
|
|
47417
|
+
descriptionPlaceholder: 'Describe your organization',
|
|
47418
|
+
saveCta: 'Save changes',
|
|
47419
|
+
close: 'Cancel',
|
|
47420
|
+
saveSuccess: 'Organization updated.',
|
|
47421
|
+
saveError: 'Could not save. Please try again.',
|
|
47422
|
+
fillRequired: 'Please fill in all required fields.',
|
|
47423
|
+
},
|
|
47424
|
+
};
|
|
47425
|
+
|
|
47426
|
+
const DEFAULT_NAMESPACE$4 = 'EditOrgModal';
|
|
47427
|
+
/**
|
|
47428
|
+
* `val-edit-org-modal` — modal de edición de organización (nombre + descripción).
|
|
47429
|
+
* Promovido desde `showcase` bajo el proceso de ADR-021. Reusado por la vista de
|
|
47430
|
+
* gestión de organización (y futuras vistas org-aware).
|
|
47431
|
+
*
|
|
47432
|
+
* Edita la org vía `OrgService.updateOrg`. El formulario se construye una vez y se
|
|
47433
|
+
* mantiene reactivo a idioma + estado de trabajo vía effects `allowSignalWrites`.
|
|
47434
|
+
* Si el consumer no pasa `org`, cae al `activeOrgId` del `AuthService`.
|
|
47435
|
+
*
|
|
47436
|
+
* Abierto vía `ModalService` — recibe `_modalRef` por `componentProps` + callback
|
|
47437
|
+
* `onSuccess(updated)`. Header canónico (Regla #5): sin `ion-title`, botón Cerrar
|
|
47438
|
+
* texto en `slot=end`, título/subtítulo en el body con `val-display`/`val-title`.
|
|
47439
|
+
*
|
|
47440
|
+
* Auto-registra sus defaults i18n (es/en) si el consumer no proveyó el namespace
|
|
47441
|
+
* `EditOrgModal`.
|
|
47442
|
+
*/
|
|
47443
|
+
class EditOrgModalComponent {
|
|
47444
|
+
constructor() {
|
|
47445
|
+
this.i18n = inject(I18nService);
|
|
47446
|
+
this.orgService = inject(OrgService);
|
|
47447
|
+
this.toast = inject(ToastService);
|
|
47448
|
+
this.errors = inject(ValtechErrorService);
|
|
47449
|
+
this.auth = inject(AuthService);
|
|
47450
|
+
/** Organización a editar (pasada por `componentProps`). */
|
|
47451
|
+
this.org = null;
|
|
47452
|
+
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
47453
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$4;
|
|
47454
|
+
this.saving = signal(false);
|
|
47455
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$4)) {
|
|
47456
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$4, EDIT_ORG_MODAL_I18N);
|
|
47457
|
+
}
|
|
47458
|
+
this.formMeta = signal(this.buildFormMeta());
|
|
47459
|
+
effect(() => {
|
|
47460
|
+
this.i18n.lang();
|
|
47461
|
+
this.formMeta.set(this.buildFormMeta());
|
|
47462
|
+
}, { allowSignalWrites: true });
|
|
47463
|
+
effect(() => {
|
|
47464
|
+
const w = this.saving();
|
|
47465
|
+
this.formMeta.update(m => ({
|
|
47466
|
+
...m,
|
|
47467
|
+
state: w ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
47468
|
+
actions: {
|
|
47469
|
+
...m.actions,
|
|
47470
|
+
state: w ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
47471
|
+
},
|
|
47472
|
+
}));
|
|
47473
|
+
}, { allowSignalWrites: true });
|
|
47474
|
+
}
|
|
47475
|
+
ngOnInit() {
|
|
47476
|
+
this.formMeta.set(this.buildFormMeta());
|
|
47477
|
+
}
|
|
47478
|
+
get activeOrgId() {
|
|
47479
|
+
const u = this.auth.user();
|
|
47480
|
+
return u?.activeOrgId ?? u?.activeOrg ?? '';
|
|
47481
|
+
}
|
|
47482
|
+
buildFormMeta() {
|
|
47483
|
+
const nameField = {
|
|
47484
|
+
token: 'edit-org-name',
|
|
47485
|
+
name: 'name',
|
|
47486
|
+
label: this.t('nameLabel'),
|
|
47487
|
+
hint: '',
|
|
47488
|
+
placeholder: this.t('namePlaceholder'),
|
|
47489
|
+
type: InputType.TEXT,
|
|
47490
|
+
order: 1,
|
|
47491
|
+
validators: [Validators.required, Validators.minLength(2), Validators.maxLength(100)],
|
|
47492
|
+
errors: {
|
|
47493
|
+
required: this.t('nameRequired'),
|
|
47494
|
+
minlength: this.t('nameMin'),
|
|
47495
|
+
},
|
|
47496
|
+
value: this.org?.name ?? '',
|
|
47497
|
+
state: ComponentStates.ENABLED,
|
|
47498
|
+
};
|
|
47499
|
+
const descField = {
|
|
47500
|
+
token: 'edit-org-desc',
|
|
47501
|
+
name: 'description',
|
|
47502
|
+
label: this.t('descriptionLabel'),
|
|
47503
|
+
hint: '',
|
|
47504
|
+
placeholder: this.t('descriptionPlaceholder'),
|
|
47505
|
+
type: InputType.TEXTAREA,
|
|
47506
|
+
order: 2,
|
|
47507
|
+
validators: [],
|
|
47508
|
+
errors: {},
|
|
47509
|
+
value: this.org?.description ?? '',
|
|
47510
|
+
state: ComponentStates.ENABLED,
|
|
47511
|
+
};
|
|
47512
|
+
return {
|
|
47513
|
+
name: '',
|
|
47514
|
+
state: ComponentStates.ENABLED,
|
|
47515
|
+
sections: [{ name: '', order: 1, fields: [nameField, descField] }],
|
|
47516
|
+
actions: {
|
|
47517
|
+
text: this.t('saveCta'),
|
|
47518
|
+
color: 'dark',
|
|
47519
|
+
type: 'submit',
|
|
47520
|
+
fill: 'solid',
|
|
47521
|
+
size: 'default',
|
|
47522
|
+
shape: 'round',
|
|
47523
|
+
expand: 'block',
|
|
47524
|
+
state: ComponentStates.ENABLED,
|
|
47525
|
+
token: 'edit-org-submit',
|
|
47526
|
+
},
|
|
47527
|
+
};
|
|
47528
|
+
}
|
|
47529
|
+
onFormSubmit(event) {
|
|
47530
|
+
const name = event.fields['name'];
|
|
47531
|
+
if (!name?.trim()) {
|
|
47532
|
+
this.toast.show({
|
|
47533
|
+
message: this.t('fillRequired'),
|
|
47534
|
+
duration: 3000,
|
|
47535
|
+
color: 'dark',
|
|
47536
|
+
position: 'top',
|
|
47537
|
+
});
|
|
47538
|
+
return;
|
|
47539
|
+
}
|
|
47540
|
+
const description = event.fields['description'] ?? '';
|
|
47541
|
+
void this.save(name, description);
|
|
47542
|
+
}
|
|
47543
|
+
async save(name, description) {
|
|
47544
|
+
const orgId = this.org?.id ?? this.activeOrgId;
|
|
47545
|
+
if (!orgId || this.saving())
|
|
47546
|
+
return;
|
|
47547
|
+
this.saving.set(true);
|
|
47548
|
+
try {
|
|
47549
|
+
const updated = await firstValueFrom(this.orgService.updateOrg(orgId, { name, description }));
|
|
47550
|
+
this.toast.show({
|
|
47551
|
+
message: this.t('saveSuccess'),
|
|
47552
|
+
color: 'dark',
|
|
47553
|
+
duration: 3500,
|
|
47554
|
+
});
|
|
47555
|
+
this.onSuccess?.(updated);
|
|
47556
|
+
this._modalRef?.dismiss(updated, 'confirm');
|
|
47557
|
+
}
|
|
47558
|
+
catch (err) {
|
|
47559
|
+
this.errors.handle(err, {
|
|
47560
|
+
context: 'editOrgModal.save',
|
|
47561
|
+
fallbackKey: 'saveError',
|
|
47562
|
+
i18nNamespace: this.i18nNamespace,
|
|
47563
|
+
});
|
|
47564
|
+
}
|
|
47565
|
+
finally {
|
|
47566
|
+
this.saving.set(false);
|
|
47567
|
+
}
|
|
47568
|
+
}
|
|
47569
|
+
dismiss() {
|
|
47570
|
+
this._modalRef?.dismiss(null, 'cancel');
|
|
47571
|
+
}
|
|
47572
|
+
t(key) {
|
|
47573
|
+
return this.i18n.t(key, this.i18nNamespace);
|
|
47574
|
+
}
|
|
47575
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: EditOrgModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
47576
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: EditOrgModalComponent, isStandalone: true, selector: "val-edit-org-modal", inputs: { _modalRef: "_modalRef", org: "org", onSuccess: "onSuccess", i18nNamespace: "i18nNamespace" }, ngImport: i0, template: `
|
|
47577
|
+
<ion-header>
|
|
47578
|
+
<ion-toolbar>
|
|
47579
|
+
<ion-buttons slot="end">
|
|
47580
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
47581
|
+
<strong>{{ t('close') }}</strong>
|
|
47582
|
+
</ion-button>
|
|
47583
|
+
</ion-buttons>
|
|
47584
|
+
</ion-toolbar>
|
|
47585
|
+
</ion-header>
|
|
47586
|
+
<ion-content class="ion-padding">
|
|
47587
|
+
<val-display [props]="{ content: t('title'), size: 'small', color: 'dark' }" />
|
|
47588
|
+
<val-title
|
|
47589
|
+
[props]="{
|
|
47590
|
+
content: t('subtitle'),
|
|
47591
|
+
size: 'large',
|
|
47592
|
+
color: '',
|
|
47593
|
+
bold: false,
|
|
47594
|
+
}"
|
|
47595
|
+
/>
|
|
47596
|
+
<val-form [props]="formMeta()" (onSubmit)="onFormSubmit($event)" />
|
|
47597
|
+
</ion-content>
|
|
47598
|
+
`, isInline: true, dependencies: [{ kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: FormComponent, selector: "val-form", inputs: ["props"], outputs: ["onSubmit", "onInvalid", "onSelectChange"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }] }); }
|
|
47599
|
+
}
|
|
47600
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: EditOrgModalComponent, decorators: [{
|
|
47601
|
+
type: Component,
|
|
47602
|
+
args: [{
|
|
47603
|
+
selector: 'val-edit-org-modal',
|
|
47604
|
+
standalone: true,
|
|
47605
|
+
imports: [IonHeader, IonToolbar, IonButtons, IonButton, IonContent, FormComponent, DisplayComponent, TitleComponent],
|
|
47606
|
+
template: `
|
|
47607
|
+
<ion-header>
|
|
47608
|
+
<ion-toolbar>
|
|
47609
|
+
<ion-buttons slot="end">
|
|
47610
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
47611
|
+
<strong>{{ t('close') }}</strong>
|
|
47612
|
+
</ion-button>
|
|
47613
|
+
</ion-buttons>
|
|
47614
|
+
</ion-toolbar>
|
|
47615
|
+
</ion-header>
|
|
47616
|
+
<ion-content class="ion-padding">
|
|
47617
|
+
<val-display [props]="{ content: t('title'), size: 'small', color: 'dark' }" />
|
|
47618
|
+
<val-title
|
|
47619
|
+
[props]="{
|
|
47620
|
+
content: t('subtitle'),
|
|
47621
|
+
size: 'large',
|
|
47622
|
+
color: '',
|
|
47623
|
+
bold: false,
|
|
47624
|
+
}"
|
|
47625
|
+
/>
|
|
47626
|
+
<val-form [props]="formMeta()" (onSubmit)="onFormSubmit($event)" />
|
|
47627
|
+
</ion-content>
|
|
47628
|
+
`,
|
|
47629
|
+
}]
|
|
47630
|
+
}], ctorParameters: () => [], propDecorators: { _modalRef: [{
|
|
47631
|
+
type: Input
|
|
47632
|
+
}], org: [{
|
|
47633
|
+
type: Input
|
|
47634
|
+
}], onSuccess: [{
|
|
47635
|
+
type: Input
|
|
47636
|
+
}], i18nNamespace: [{
|
|
47637
|
+
type: Input
|
|
47638
|
+
}] } });
|
|
47639
|
+
|
|
47379
47640
|
/**
|
|
47380
47641
|
* Defaults i18n (es/en) embebidos en `val-invite-member-modal`. Auto-registrados
|
|
47381
47642
|
* en el constructor del componente si el consumer no proveyó el namespace
|
|
@@ -48386,258 +48647,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
48386
48647
|
type: Input
|
|
48387
48648
|
}] } });
|
|
48388
48649
|
|
|
48389
|
-
/**
|
|
48390
|
-
* Defaults i18n (es/en) embebidos en `val-edit-org-modal`. Auto-registrados en
|
|
48391
|
-
* el constructor del componente si el consumer no proveyó el namespace
|
|
48392
|
-
* (`EditOrgModal` por default). SOLO incluye las keys que el modal usa.
|
|
48393
|
-
*/
|
|
48394
|
-
const EDIT_ORG_MODAL_I18N = {
|
|
48395
|
-
es: {
|
|
48396
|
-
title: 'Editar organización',
|
|
48397
|
-
subtitle: 'Actualiza el nombre y descripción.',
|
|
48398
|
-
nameLabel: 'Nombre',
|
|
48399
|
-
namePlaceholder: 'Nombre de la organización',
|
|
48400
|
-
nameRequired: 'El nombre es obligatorio.',
|
|
48401
|
-
nameMin: 'Mínimo 2 caracteres.',
|
|
48402
|
-
descriptionLabel: 'Descripción (opcional)',
|
|
48403
|
-
descriptionPlaceholder: 'Describe tu organización',
|
|
48404
|
-
saveCta: 'Guardar cambios',
|
|
48405
|
-
close: 'Cancelar',
|
|
48406
|
-
saveSuccess: 'Organización actualizada.',
|
|
48407
|
-
saveError: 'No se pudo guardar. Intenta de nuevo.',
|
|
48408
|
-
fillRequired: 'Completa todos los campos requeridos.',
|
|
48409
|
-
},
|
|
48410
|
-
en: {
|
|
48411
|
-
title: 'Edit organization',
|
|
48412
|
-
subtitle: 'Update the name and description.',
|
|
48413
|
-
nameLabel: 'Name',
|
|
48414
|
-
namePlaceholder: 'Organization name',
|
|
48415
|
-
nameRequired: 'Name is required.',
|
|
48416
|
-
nameMin: 'Minimum 2 characters.',
|
|
48417
|
-
descriptionLabel: 'Description (optional)',
|
|
48418
|
-
descriptionPlaceholder: 'Describe your organization',
|
|
48419
|
-
saveCta: 'Save changes',
|
|
48420
|
-
close: 'Cancel',
|
|
48421
|
-
saveSuccess: 'Organization updated.',
|
|
48422
|
-
saveError: 'Could not save. Please try again.',
|
|
48423
|
-
fillRequired: 'Please fill in all required fields.',
|
|
48424
|
-
},
|
|
48425
|
-
};
|
|
48426
|
-
|
|
48427
|
-
const DEFAULT_NAMESPACE$1 = 'EditOrgModal';
|
|
48428
|
-
/**
|
|
48429
|
-
* `val-edit-org-modal` — modal de edición de organización (nombre + descripción).
|
|
48430
|
-
* Promovido desde `showcase` bajo el proceso de ADR-021. Reusado por la vista de
|
|
48431
|
-
* gestión de organización (y futuras vistas org-aware).
|
|
48432
|
-
*
|
|
48433
|
-
* Edita la org vía `OrgService.updateOrg`. El formulario se construye una vez y se
|
|
48434
|
-
* mantiene reactivo a idioma + estado de trabajo vía effects `allowSignalWrites`.
|
|
48435
|
-
* Si el consumer no pasa `org`, cae al `activeOrgId` del `AuthService`.
|
|
48436
|
-
*
|
|
48437
|
-
* Abierto vía `ModalService` — recibe `_modalRef` por `componentProps` + callback
|
|
48438
|
-
* `onSuccess(updated)`. Header canónico (Regla #5): sin `ion-title`, botón Cerrar
|
|
48439
|
-
* texto en `slot=end`, título/subtítulo en el body con `val-display`/`val-title`.
|
|
48440
|
-
*
|
|
48441
|
-
* Auto-registra sus defaults i18n (es/en) si el consumer no proveyó el namespace
|
|
48442
|
-
* `EditOrgModal`.
|
|
48443
|
-
*/
|
|
48444
|
-
class EditOrgModalComponent {
|
|
48445
|
-
constructor() {
|
|
48446
|
-
this.i18n = inject(I18nService);
|
|
48447
|
-
this.orgService = inject(OrgService);
|
|
48448
|
-
this.toast = inject(ToastService);
|
|
48449
|
-
this.errors = inject(ValtechErrorService);
|
|
48450
|
-
this.auth = inject(AuthService);
|
|
48451
|
-
/** Organización a editar (pasada por `componentProps`). */
|
|
48452
|
-
this.org = null;
|
|
48453
|
-
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
48454
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$1;
|
|
48455
|
-
this.saving = signal(false);
|
|
48456
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$1)) {
|
|
48457
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$1, EDIT_ORG_MODAL_I18N);
|
|
48458
|
-
}
|
|
48459
|
-
this.formMeta = signal(this.buildFormMeta());
|
|
48460
|
-
effect(() => {
|
|
48461
|
-
this.i18n.lang();
|
|
48462
|
-
this.formMeta.set(this.buildFormMeta());
|
|
48463
|
-
}, { allowSignalWrites: true });
|
|
48464
|
-
effect(() => {
|
|
48465
|
-
const w = this.saving();
|
|
48466
|
-
this.formMeta.update(m => ({
|
|
48467
|
-
...m,
|
|
48468
|
-
state: w ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
48469
|
-
actions: {
|
|
48470
|
-
...m.actions,
|
|
48471
|
-
state: w ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
48472
|
-
},
|
|
48473
|
-
}));
|
|
48474
|
-
}, { allowSignalWrites: true });
|
|
48475
|
-
}
|
|
48476
|
-
ngOnInit() {
|
|
48477
|
-
this.formMeta.set(this.buildFormMeta());
|
|
48478
|
-
}
|
|
48479
|
-
get activeOrgId() {
|
|
48480
|
-
const u = this.auth.user();
|
|
48481
|
-
return u?.activeOrgId ?? u?.activeOrg ?? '';
|
|
48482
|
-
}
|
|
48483
|
-
buildFormMeta() {
|
|
48484
|
-
const nameField = {
|
|
48485
|
-
token: 'edit-org-name',
|
|
48486
|
-
name: 'name',
|
|
48487
|
-
label: this.t('nameLabel'),
|
|
48488
|
-
hint: '',
|
|
48489
|
-
placeholder: this.t('namePlaceholder'),
|
|
48490
|
-
type: InputType.TEXT,
|
|
48491
|
-
order: 1,
|
|
48492
|
-
validators: [Validators.required, Validators.minLength(2), Validators.maxLength(100)],
|
|
48493
|
-
errors: {
|
|
48494
|
-
required: this.t('nameRequired'),
|
|
48495
|
-
minlength: this.t('nameMin'),
|
|
48496
|
-
},
|
|
48497
|
-
value: this.org?.name ?? '',
|
|
48498
|
-
state: ComponentStates.ENABLED,
|
|
48499
|
-
};
|
|
48500
|
-
const descField = {
|
|
48501
|
-
token: 'edit-org-desc',
|
|
48502
|
-
name: 'description',
|
|
48503
|
-
label: this.t('descriptionLabel'),
|
|
48504
|
-
hint: '',
|
|
48505
|
-
placeholder: this.t('descriptionPlaceholder'),
|
|
48506
|
-
type: InputType.TEXTAREA,
|
|
48507
|
-
order: 2,
|
|
48508
|
-
validators: [],
|
|
48509
|
-
errors: {},
|
|
48510
|
-
value: this.org?.description ?? '',
|
|
48511
|
-
state: ComponentStates.ENABLED,
|
|
48512
|
-
};
|
|
48513
|
-
return {
|
|
48514
|
-
name: '',
|
|
48515
|
-
state: ComponentStates.ENABLED,
|
|
48516
|
-
sections: [{ name: '', order: 1, fields: [nameField, descField] }],
|
|
48517
|
-
actions: {
|
|
48518
|
-
text: this.t('saveCta'),
|
|
48519
|
-
color: 'dark',
|
|
48520
|
-
type: 'submit',
|
|
48521
|
-
fill: 'solid',
|
|
48522
|
-
size: 'default',
|
|
48523
|
-
shape: 'round',
|
|
48524
|
-
expand: 'block',
|
|
48525
|
-
state: ComponentStates.ENABLED,
|
|
48526
|
-
token: 'edit-org-submit',
|
|
48527
|
-
},
|
|
48528
|
-
};
|
|
48529
|
-
}
|
|
48530
|
-
onFormSubmit(event) {
|
|
48531
|
-
const name = event.fields['name'];
|
|
48532
|
-
if (!name?.trim()) {
|
|
48533
|
-
this.toast.show({
|
|
48534
|
-
message: this.t('fillRequired'),
|
|
48535
|
-
duration: 3000,
|
|
48536
|
-
color: 'dark',
|
|
48537
|
-
position: 'top',
|
|
48538
|
-
});
|
|
48539
|
-
return;
|
|
48540
|
-
}
|
|
48541
|
-
const description = event.fields['description'] ?? '';
|
|
48542
|
-
void this.save(name, description);
|
|
48543
|
-
}
|
|
48544
|
-
async save(name, description) {
|
|
48545
|
-
const orgId = this.org?.id ?? this.activeOrgId;
|
|
48546
|
-
if (!orgId || this.saving())
|
|
48547
|
-
return;
|
|
48548
|
-
this.saving.set(true);
|
|
48549
|
-
try {
|
|
48550
|
-
const updated = await firstValueFrom(this.orgService.updateOrg(orgId, { name, description }));
|
|
48551
|
-
this.toast.show({
|
|
48552
|
-
message: this.t('saveSuccess'),
|
|
48553
|
-
color: 'dark',
|
|
48554
|
-
duration: 3500,
|
|
48555
|
-
});
|
|
48556
|
-
this.onSuccess?.(updated);
|
|
48557
|
-
this._modalRef?.dismiss(updated, 'confirm');
|
|
48558
|
-
}
|
|
48559
|
-
catch (err) {
|
|
48560
|
-
this.errors.handle(err, {
|
|
48561
|
-
context: 'editOrgModal.save',
|
|
48562
|
-
fallbackKey: 'saveError',
|
|
48563
|
-
i18nNamespace: this.i18nNamespace,
|
|
48564
|
-
});
|
|
48565
|
-
}
|
|
48566
|
-
finally {
|
|
48567
|
-
this.saving.set(false);
|
|
48568
|
-
}
|
|
48569
|
-
}
|
|
48570
|
-
dismiss() {
|
|
48571
|
-
this._modalRef?.dismiss(null, 'cancel');
|
|
48572
|
-
}
|
|
48573
|
-
t(key) {
|
|
48574
|
-
return this.i18n.t(key, this.i18nNamespace);
|
|
48575
|
-
}
|
|
48576
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: EditOrgModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
48577
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: EditOrgModalComponent, isStandalone: true, selector: "val-edit-org-modal", inputs: { _modalRef: "_modalRef", org: "org", onSuccess: "onSuccess", i18nNamespace: "i18nNamespace" }, ngImport: i0, template: `
|
|
48578
|
-
<ion-header>
|
|
48579
|
-
<ion-toolbar>
|
|
48580
|
-
<ion-buttons slot="end">
|
|
48581
|
-
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
48582
|
-
<strong>{{ t('close') }}</strong>
|
|
48583
|
-
</ion-button>
|
|
48584
|
-
</ion-buttons>
|
|
48585
|
-
</ion-toolbar>
|
|
48586
|
-
</ion-header>
|
|
48587
|
-
<ion-content class="ion-padding">
|
|
48588
|
-
<val-display [props]="{ content: t('title'), size: 'small', color: 'dark' }" />
|
|
48589
|
-
<val-title
|
|
48590
|
-
[props]="{
|
|
48591
|
-
content: t('subtitle'),
|
|
48592
|
-
size: 'large',
|
|
48593
|
-
color: '',
|
|
48594
|
-
bold: false,
|
|
48595
|
-
}"
|
|
48596
|
-
/>
|
|
48597
|
-
<val-form [props]="formMeta()" (onSubmit)="onFormSubmit($event)" />
|
|
48598
|
-
</ion-content>
|
|
48599
|
-
`, isInline: true, dependencies: [{ kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: FormComponent, selector: "val-form", inputs: ["props"], outputs: ["onSubmit", "onInvalid", "onSelectChange"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }] }); }
|
|
48600
|
-
}
|
|
48601
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: EditOrgModalComponent, decorators: [{
|
|
48602
|
-
type: Component,
|
|
48603
|
-
args: [{
|
|
48604
|
-
selector: 'val-edit-org-modal',
|
|
48605
|
-
standalone: true,
|
|
48606
|
-
imports: [IonHeader, IonToolbar, IonButtons, IonButton, IonContent, FormComponent, DisplayComponent, TitleComponent],
|
|
48607
|
-
template: `
|
|
48608
|
-
<ion-header>
|
|
48609
|
-
<ion-toolbar>
|
|
48610
|
-
<ion-buttons slot="end">
|
|
48611
|
-
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
48612
|
-
<strong>{{ t('close') }}</strong>
|
|
48613
|
-
</ion-button>
|
|
48614
|
-
</ion-buttons>
|
|
48615
|
-
</ion-toolbar>
|
|
48616
|
-
</ion-header>
|
|
48617
|
-
<ion-content class="ion-padding">
|
|
48618
|
-
<val-display [props]="{ content: t('title'), size: 'small', color: 'dark' }" />
|
|
48619
|
-
<val-title
|
|
48620
|
-
[props]="{
|
|
48621
|
-
content: t('subtitle'),
|
|
48622
|
-
size: 'large',
|
|
48623
|
-
color: '',
|
|
48624
|
-
bold: false,
|
|
48625
|
-
}"
|
|
48626
|
-
/>
|
|
48627
|
-
<val-form [props]="formMeta()" (onSubmit)="onFormSubmit($event)" />
|
|
48628
|
-
</ion-content>
|
|
48629
|
-
`,
|
|
48630
|
-
}]
|
|
48631
|
-
}], ctorParameters: () => [], propDecorators: { _modalRef: [{
|
|
48632
|
-
type: Input
|
|
48633
|
-
}], org: [{
|
|
48634
|
-
type: Input
|
|
48635
|
-
}], onSuccess: [{
|
|
48636
|
-
type: Input
|
|
48637
|
-
}], i18nNamespace: [{
|
|
48638
|
-
type: Input
|
|
48639
|
-
}] } });
|
|
48640
|
-
|
|
48641
48650
|
/**
|
|
48642
48651
|
* Defaults i18n (es/en) embebidos en `val-transfer-ownership-modal`.
|
|
48643
48652
|
* Auto-registrados en el constructor del componente si el consumer no proveyó el
|
|
@@ -48665,7 +48674,7 @@ const TRANSFER_OWNERSHIP_MODAL_I18N = {
|
|
|
48665
48674
|
},
|
|
48666
48675
|
};
|
|
48667
48676
|
|
|
48668
|
-
const DEFAULT_NAMESPACE = 'Settings.TransferModal';
|
|
48677
|
+
const DEFAULT_NAMESPACE$1 = 'Settings.TransferModal';
|
|
48669
48678
|
/**
|
|
48670
48679
|
* `val-transfer-ownership-modal` — selector de miembro para transferir la
|
|
48671
48680
|
* propiedad de la organización. Promovido desde `showcase` bajo el proceso de
|
|
@@ -48689,7 +48698,7 @@ class TransferOwnershipModalComponent {
|
|
|
48689
48698
|
/** Lista de miembros transferibles (todos excepto el owner actual). */
|
|
48690
48699
|
this.members = [];
|
|
48691
48700
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
48692
|
-
this.i18nNamespace = DEFAULT_NAMESPACE;
|
|
48701
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$1;
|
|
48693
48702
|
this.query = signal('');
|
|
48694
48703
|
this.selectedId = signal('');
|
|
48695
48704
|
this.filtered = computed(() => {
|
|
@@ -48701,8 +48710,8 @@ class TransferOwnershipModalComponent {
|
|
|
48701
48710
|
m.userId.toLowerCase().includes(q));
|
|
48702
48711
|
});
|
|
48703
48712
|
this.noResultsLabel = computed(() => `${this.t('noResults')} "${this.query()}"`);
|
|
48704
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE)) {
|
|
48705
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE, TRANSFER_OWNERSHIP_MODAL_I18N);
|
|
48713
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$1)) {
|
|
48714
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$1, TRANSFER_OWNERSHIP_MODAL_I18N);
|
|
48706
48715
|
}
|
|
48707
48716
|
}
|
|
48708
48717
|
ngOnInit() {
|
|
@@ -48887,6 +48896,1218 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
48887
48896
|
type: Input
|
|
48888
48897
|
}] } });
|
|
48889
48898
|
|
|
48899
|
+
/**
|
|
48900
|
+
* Defaults i18n (es/en) embebidos en `val-organization-view`. Auto-registrados en
|
|
48901
|
+
* el constructor del componente si el consumer no proveyó el namespace
|
|
48902
|
+
* (`Settings.Organization` por default). SOLO incluye las keys que la vista usa.
|
|
48903
|
+
*
|
|
48904
|
+
* Portado de `ORG_I18N_CONTENT` (showcase) bajo el proceso de ADR-021.
|
|
48905
|
+
*/
|
|
48906
|
+
const ORGANIZATION_VIEW_I18N = {
|
|
48907
|
+
es: {
|
|
48908
|
+
pageTitle: 'Organización',
|
|
48909
|
+
pageDescription: 'Gestiona tu organización activa',
|
|
48910
|
+
infoTitle: 'Información',
|
|
48911
|
+
infoName: 'Nombre',
|
|
48912
|
+
infoDescription: 'Descripción',
|
|
48913
|
+
infoPlan: 'Plan',
|
|
48914
|
+
infoType: 'Tipo',
|
|
48915
|
+
editCta: 'Editar',
|
|
48916
|
+
saveCta: 'Guardar',
|
|
48917
|
+
cancelCta: 'Cancelar',
|
|
48918
|
+
membersTitle: 'Miembros',
|
|
48919
|
+
membersEmpty: 'Sin miembros aún.',
|
|
48920
|
+
memberRoles: 'Roles',
|
|
48921
|
+
inviteTitle: 'Invitar',
|
|
48922
|
+
inviteEmail: 'Correo electrónico',
|
|
48923
|
+
inviteRole: 'Rol',
|
|
48924
|
+
inviteCta: 'Invitar',
|
|
48925
|
+
inviteSuccess: 'Invitación enviada.',
|
|
48926
|
+
inviteError: 'No se pudo enviar la invitación.',
|
|
48927
|
+
membersError: 'No se pudieron cargar los miembros.',
|
|
48928
|
+
leaveTitle: 'Salir de la organización',
|
|
48929
|
+
leaveHint: 'Dejarás de tener acceso a esta organización.',
|
|
48930
|
+
leaveCta: 'Salir',
|
|
48931
|
+
leaveOwnerHint: 'Eres el propietario. Transfiere la propiedad antes de salir.',
|
|
48932
|
+
leaveConfirm: '¿Salir de la organización?',
|
|
48933
|
+
planFree: 'Gratuito',
|
|
48934
|
+
planPro: 'Pro',
|
|
48935
|
+
planEnterprise: 'Empresa',
|
|
48936
|
+
saveSuccess: 'Organización actualizada.',
|
|
48937
|
+
leaveSuccess: 'Has salido de la organización.',
|
|
48938
|
+
errorTitle: 'No se pudo cargar la organización',
|
|
48939
|
+
offlineTitle: 'Sin conexión',
|
|
48940
|
+
offlineHint: 'Verifica tu conexión e intenta de nuevo.',
|
|
48941
|
+
retry: 'Reintentar',
|
|
48942
|
+
saveError: 'No se pudo guardar. Intenta de nuevo.',
|
|
48943
|
+
leaveError: 'No se pudo salir. Intenta de nuevo.',
|
|
48944
|
+
transferTitle: 'Transferir propiedad',
|
|
48945
|
+
transferHint: 'Elige un miembro para transferirle la propiedad de la organización.',
|
|
48946
|
+
transferSelect: 'Seleccionar nuevo propietario',
|
|
48947
|
+
transferCta: 'Transferir',
|
|
48948
|
+
transferConfirm: '¿Transferir la propiedad a este miembro? Perderás el rol de propietario.',
|
|
48949
|
+
transferSuccess: 'Propiedad transferida.',
|
|
48950
|
+
transferError: 'No se pudo transferir la propiedad.',
|
|
48951
|
+
inviteCtaTitle: '¿Deseas agregar a alguien?',
|
|
48952
|
+
inviteCtaHint: 'Invita a usuarios a unirse a tu organización.',
|
|
48953
|
+
inviteOpen: 'Invitar',
|
|
48954
|
+
viewMemberCta: 'Ver miembro',
|
|
48955
|
+
roleViewer: 'Visor',
|
|
48956
|
+
roleEditor: 'Editor',
|
|
48957
|
+
roleAdmin: 'Admin',
|
|
48958
|
+
roleSuperAdmin: 'Super Admin',
|
|
48959
|
+
rolesSectionTitle: 'Roles y permisos',
|
|
48960
|
+
rolesHint: 'Tu organización tiene roles que controlan lo que cada miembro puede ver y hacer. Cada rol lleva un conjunto de permisos asociados.',
|
|
48961
|
+
rolesViewPerms: 'Ver roles y permisos',
|
|
48962
|
+
rolesSystemBadge: 'Sistema',
|
|
48963
|
+
permAll: 'Todo',
|
|
48964
|
+
permUsers: 'Usuarios',
|
|
48965
|
+
permDocuments: 'Documentos',
|
|
48966
|
+
permRoles: 'Roles',
|
|
48967
|
+
permMedia: 'Media',
|
|
48968
|
+
permTemplates: 'Plantillas',
|
|
48969
|
+
permRead: 'Leer',
|
|
48970
|
+
permWrite: 'Escribir',
|
|
48971
|
+
permCreate: 'Crear',
|
|
48972
|
+
permDelete: 'Eliminar',
|
|
48973
|
+
permManage: 'Gestionar',
|
|
48974
|
+
membersShowMore: 'Ver más',
|
|
48975
|
+
},
|
|
48976
|
+
en: {
|
|
48977
|
+
pageTitle: 'Organization',
|
|
48978
|
+
pageDescription: 'Manage your active organization',
|
|
48979
|
+
infoTitle: 'Information',
|
|
48980
|
+
infoName: 'Name',
|
|
48981
|
+
infoDescription: 'Description',
|
|
48982
|
+
infoPlan: 'Plan',
|
|
48983
|
+
infoType: 'Type',
|
|
48984
|
+
editCta: 'Edit',
|
|
48985
|
+
saveCta: 'Save',
|
|
48986
|
+
cancelCta: 'Cancel',
|
|
48987
|
+
membersTitle: 'Members',
|
|
48988
|
+
membersEmpty: 'No members yet.',
|
|
48989
|
+
memberRoles: 'Roles',
|
|
48990
|
+
inviteTitle: 'Invite',
|
|
48991
|
+
inviteEmail: 'Email address',
|
|
48992
|
+
inviteRole: 'Role',
|
|
48993
|
+
inviteCta: 'Invite',
|
|
48994
|
+
inviteSuccess: 'Invitation sent.',
|
|
48995
|
+
inviteError: 'Could not send invitation.',
|
|
48996
|
+
membersError: 'Could not load members.',
|
|
48997
|
+
leaveTitle: 'Leave organization',
|
|
48998
|
+
leaveHint: 'You will lose access to this organization.',
|
|
48999
|
+
leaveCta: 'Leave',
|
|
49000
|
+
leaveOwnerHint: 'You are the owner. Transfer ownership before leaving.',
|
|
49001
|
+
leaveConfirm: 'Leave this organization?',
|
|
49002
|
+
planFree: 'Free',
|
|
49003
|
+
planPro: 'Pro',
|
|
49004
|
+
planEnterprise: 'Enterprise',
|
|
49005
|
+
saveSuccess: 'Organization updated.',
|
|
49006
|
+
leaveSuccess: 'You have left the organization.',
|
|
49007
|
+
errorTitle: 'Could not load organization',
|
|
49008
|
+
offlineTitle: 'No connection',
|
|
49009
|
+
offlineHint: 'Check your connection and try again.',
|
|
49010
|
+
retry: 'Retry',
|
|
49011
|
+
saveError: 'Could not save. Please try again.',
|
|
49012
|
+
leaveError: 'Could not leave. Please try again.',
|
|
49013
|
+
transferTitle: 'Transfer ownership',
|
|
49014
|
+
transferHint: 'Choose a member to transfer ownership of this organization.',
|
|
49015
|
+
transferSelect: 'Select new owner',
|
|
49016
|
+
transferCta: 'Transfer',
|
|
49017
|
+
transferConfirm: 'Transfer ownership to this member? You will lose the owner role.',
|
|
49018
|
+
transferSuccess: 'Ownership transferred.',
|
|
49019
|
+
transferError: 'Could not transfer ownership.',
|
|
49020
|
+
inviteCtaTitle: 'Want to add someone?',
|
|
49021
|
+
inviteCtaHint: 'Invite users to join your organization.',
|
|
49022
|
+
inviteOpen: 'Invite',
|
|
49023
|
+
viewMemberCta: 'View member',
|
|
49024
|
+
roleViewer: 'Viewer',
|
|
49025
|
+
roleEditor: 'Editor',
|
|
49026
|
+
roleAdmin: 'Admin',
|
|
49027
|
+
roleSuperAdmin: 'Super Admin',
|
|
49028
|
+
rolesSectionTitle: 'Roles & permissions',
|
|
49029
|
+
rolesHint: 'Your organization has roles that control what each member can see and do. Each role carries a set of associated permissions.',
|
|
49030
|
+
rolesViewPerms: 'View roles & permissions',
|
|
49031
|
+
rolesSystemBadge: 'System',
|
|
49032
|
+
permAll: 'All',
|
|
49033
|
+
permUsers: 'Users',
|
|
49034
|
+
permDocuments: 'Documents',
|
|
49035
|
+
permRoles: 'Roles',
|
|
49036
|
+
permMedia: 'Media',
|
|
49037
|
+
permTemplates: 'Templates',
|
|
49038
|
+
permRead: 'Read',
|
|
49039
|
+
permWrite: 'Write',
|
|
49040
|
+
permCreate: 'Create',
|
|
49041
|
+
permDelete: 'Delete',
|
|
49042
|
+
permManage: 'Manage',
|
|
49043
|
+
membersShowMore: 'Show more',
|
|
49044
|
+
},
|
|
49045
|
+
};
|
|
49046
|
+
|
|
49047
|
+
const DEFAULT_NAMESPACE = 'Settings.Organization';
|
|
49048
|
+
const DEFAULT_VIEW_PERMISSIONS_ROUTE = '/app/settings/permissions';
|
|
49049
|
+
const DEFAULT_LEAVE_REDIRECT_ROUTE = '/app/settings/account';
|
|
49050
|
+
/**
|
|
49051
|
+
* `val-organization-view` — vista Gestión de organización full-feature
|
|
49052
|
+
* autocontenida (organism). Promovida desde `showcase` bajo el proceso de
|
|
49053
|
+
* ADR-021. Reúne:
|
|
49054
|
+
* - **Información** — nombre, descripción, plan y tipo de la org activa; editar
|
|
49055
|
+
* vía modal `val-edit-org-modal` (solo si `canEditOrg()`).
|
|
49056
|
+
* - **Miembros** — lista paginada (`val-member-card`) enriquecida con perfiles
|
|
49057
|
+
* públicos (Firestore); ver detalle vía `val-member-detail-modal`.
|
|
49058
|
+
* - **Roles y permisos** — sección explicativa con CTA a la ruta de permisos.
|
|
49059
|
+
* - **Invitar** — CTA que abre `val-invite-member-modal` (gateada por `users:*`).
|
|
49060
|
+
* - **Transferir propiedad** — `val-transfer-ownership-modal` (solo owner).
|
|
49061
|
+
* - **Salir de la organización** — `OrgService.leaveOrg` con confirmación
|
|
49062
|
+
* destructiva.
|
|
49063
|
+
*
|
|
49064
|
+
* **RBAC interno** (decisión CTO, ADR-021): el gating fino se resuelve dentro de
|
|
49065
|
+
* la vista vía `AuthService.hasPermission()` + `*valHasPermission` + computeds
|
|
49066
|
+
* `isOwner()`/`canManageMembers()`/`canEditOrg()`. NO se expone como config.
|
|
49067
|
+
*
|
|
49068
|
+
* **Auto-reload en org-switch**: un `effect` reactiona a `activeOrgId()` y recarga
|
|
49069
|
+
* org + miembros cuando el usuario cambia de organización activa mientras la vista
|
|
49070
|
+
* está montada. El effect cubre también la carga inicial (sin doble carga).
|
|
49071
|
+
*
|
|
49072
|
+
* NO renderiza ion-content — vive dentro de val-page-wrapper. `ActivatedRoute` se
|
|
49073
|
+
* inyecta `{ optional: true }` solo para leer el route data de config (no-op
|
|
49074
|
+
* embebido). Auto-registra sus defaults i18n (es/en) si el consumer no proveyó el
|
|
49075
|
+
* namespace (default `Settings.Organization`).
|
|
49076
|
+
*/
|
|
49077
|
+
class OrganizationViewComponent {
|
|
49078
|
+
/** Namespace i18n resuelto (capturado para llamadas no-reactivas). */
|
|
49079
|
+
get ns() {
|
|
49080
|
+
return this.resolvedConfig().i18nNamespace;
|
|
49081
|
+
}
|
|
49082
|
+
constructor() {
|
|
49083
|
+
this.nav = inject(NavigationService);
|
|
49084
|
+
this.i18n = inject(I18nService);
|
|
49085
|
+
this.auth = inject(AuthService);
|
|
49086
|
+
this.orgService = inject(OrgService);
|
|
49087
|
+
this.toast = inject(ToastService);
|
|
49088
|
+
this.errors = inject(ValtechErrorService);
|
|
49089
|
+
this.modalService = inject(ModalService);
|
|
49090
|
+
this.firestore = inject(Firestore);
|
|
49091
|
+
this.confirmDialog = inject(ConfirmationDialogService);
|
|
49092
|
+
this.route = inject(ActivatedRoute, { optional: true });
|
|
49093
|
+
this.isDebug = isDevMode();
|
|
49094
|
+
this.resolvedConfig = computed(() => {
|
|
49095
|
+
const fromRoute = (this.route?.snapshot.data['organizationConfig'] ?? {});
|
|
49096
|
+
const merged = { ...fromRoute, ...(this.config ?? {}) };
|
|
49097
|
+
return {
|
|
49098
|
+
showInfo: merged.showInfo ?? true,
|
|
49099
|
+
showMembers: merged.showMembers ?? true,
|
|
49100
|
+
showRoles: merged.showRoles ?? true,
|
|
49101
|
+
showInvite: merged.showInvite ?? true,
|
|
49102
|
+
showTransferOwnership: merged.showTransferOwnership ?? true,
|
|
49103
|
+
showLeave: merged.showLeave ?? true,
|
|
49104
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE,
|
|
49105
|
+
viewPermissionsRoute: merged.viewPermissionsRoute ?? DEFAULT_VIEW_PERMISSIONS_ROUTE,
|
|
49106
|
+
leaveRedirectRoute: merged.leaveRedirectRoute ?? DEFAULT_LEAVE_REDIRECT_ROUTE,
|
|
49107
|
+
onOrgEdited: merged.onOrgEdited,
|
|
49108
|
+
onMemberInvited: merged.onMemberInvited,
|
|
49109
|
+
onOwnershipTransferred: merged.onOwnershipTransferred,
|
|
49110
|
+
onLeftOrg: merged.onLeftOrg,
|
|
49111
|
+
};
|
|
49112
|
+
});
|
|
49113
|
+
this.org = signal(null);
|
|
49114
|
+
this.loading = signal(false);
|
|
49115
|
+
this.leaving = signal(false);
|
|
49116
|
+
this.orgLoadError = signal(null);
|
|
49117
|
+
this.orgErrorState = computed(() => {
|
|
49118
|
+
this.i18n.lang();
|
|
49119
|
+
const err = this.orgLoadError();
|
|
49120
|
+
if (!err)
|
|
49121
|
+
return null;
|
|
49122
|
+
return createErrorStateProps(err, {
|
|
49123
|
+
title: { offline: this.tt('offlineTitle'), error: this.tt('errorTitle') },
|
|
49124
|
+
description: {
|
|
49125
|
+
offline: this.tt('offlineHint'),
|
|
49126
|
+
error: interpretError(err).message,
|
|
49127
|
+
},
|
|
49128
|
+
retryLabel: this.tt('retry'),
|
|
49129
|
+
onRetry: () => this.loadOrg(),
|
|
49130
|
+
retrying: this.loading(),
|
|
49131
|
+
});
|
|
49132
|
+
});
|
|
49133
|
+
this.members = signal([]);
|
|
49134
|
+
this.membersLoading = signal(false);
|
|
49135
|
+
this.membersLoadError = signal(null);
|
|
49136
|
+
this.membersNextToken = signal(null);
|
|
49137
|
+
this.loadingMoreMembers = signal(false);
|
|
49138
|
+
this.showAllMembers = signal(false);
|
|
49139
|
+
this.visibleMembers = computed(() => (this.showAllMembers() ? this.members() : this.members().slice(0, 3)));
|
|
49140
|
+
this.transferring = signal(false);
|
|
49141
|
+
this.availableRoles = signal([
|
|
49142
|
+
{ id: 'viewer', name: 'viewer' },
|
|
49143
|
+
{ id: 'editor', name: 'editor' },
|
|
49144
|
+
{ id: 'admin', name: 'admin' },
|
|
49145
|
+
]);
|
|
49146
|
+
this.activeOrgId = computed(() => {
|
|
49147
|
+
const u = this.auth.user();
|
|
49148
|
+
return u?.activeOrgId ?? u?.activeOrg ?? '';
|
|
49149
|
+
});
|
|
49150
|
+
this.userId = computed(() => this.auth.user()?.userId ?? '');
|
|
49151
|
+
this.isOwner = computed(() => {
|
|
49152
|
+
const o = this.org();
|
|
49153
|
+
const uid = this.userId();
|
|
49154
|
+
return !!o && !!uid && o.ownerId === uid;
|
|
49155
|
+
});
|
|
49156
|
+
this.canEditOrg = computed(() => this.isOwner() || this.auth.hasPermission('org:manage'));
|
|
49157
|
+
this.canManageMembers = computed(() => {
|
|
49158
|
+
if (this.isOwner())
|
|
49159
|
+
return true;
|
|
49160
|
+
const uid = this.userId();
|
|
49161
|
+
const me = this.members().find(m => m.userId === uid);
|
|
49162
|
+
if (!me)
|
|
49163
|
+
return false;
|
|
49164
|
+
return me.roles.some(r => r === 'admin' || r === 'super_admin');
|
|
49165
|
+
});
|
|
49166
|
+
this.pageTitle = computed(() => this.tt('pageTitle'));
|
|
49167
|
+
this.pageDescription = computed(() => this.tt('pageDescription'));
|
|
49168
|
+
this.planLabel = computed(() => {
|
|
49169
|
+
const plan = this.org()?.plan;
|
|
49170
|
+
if (plan === 'pro')
|
|
49171
|
+
return this.tt('planPro');
|
|
49172
|
+
if (plan === 'enterprise')
|
|
49173
|
+
return this.tt('planEnterprise');
|
|
49174
|
+
return this.tt('planFree');
|
|
49175
|
+
});
|
|
49176
|
+
this.editButtonProps = computed(() => ({
|
|
49177
|
+
text: this.tt('editCta'),
|
|
49178
|
+
color: 'primary',
|
|
49179
|
+
fill: 'outline',
|
|
49180
|
+
size: 'small',
|
|
49181
|
+
shape: 'round',
|
|
49182
|
+
type: 'button',
|
|
49183
|
+
}));
|
|
49184
|
+
this.leaveButtonProps = computed(() => ({
|
|
49185
|
+
text: this.tt('leaveCta'),
|
|
49186
|
+
token: 'org-leave',
|
|
49187
|
+
color: 'dark',
|
|
49188
|
+
fill: 'outline',
|
|
49189
|
+
size: 'default',
|
|
49190
|
+
shape: 'round',
|
|
49191
|
+
type: 'button',
|
|
49192
|
+
state: this.isOwner() || this.leaving() ? ComponentStates.DISABLED : ComponentStates.ENABLED,
|
|
49193
|
+
}));
|
|
49194
|
+
this.transferableMembers = computed(() => this.members().filter(m => m.userId !== this.userId()));
|
|
49195
|
+
this.viewPermissionsButtonProps = computed(() => ({
|
|
49196
|
+
text: this.tt('rolesViewPerms'),
|
|
49197
|
+
color: 'primary',
|
|
49198
|
+
fill: 'outline',
|
|
49199
|
+
size: 'default',
|
|
49200
|
+
shape: 'round',
|
|
49201
|
+
type: 'button',
|
|
49202
|
+
token: 'org-view-permissions',
|
|
49203
|
+
}));
|
|
49204
|
+
this.transferButtonProps = computed(() => ({
|
|
49205
|
+
text: this.tt('transferCta'),
|
|
49206
|
+
token: 'org-transfer-submit',
|
|
49207
|
+
color: 'dark',
|
|
49208
|
+
fill: 'outline',
|
|
49209
|
+
size: 'default',
|
|
49210
|
+
shape: 'round',
|
|
49211
|
+
type: 'button',
|
|
49212
|
+
state: this.transferring() ? ComponentStates.DISABLED : ComponentStates.ENABLED,
|
|
49213
|
+
}));
|
|
49214
|
+
this.openInviteButtonProps = computed(() => ({
|
|
49215
|
+
text: this.tt('inviteOpen'),
|
|
49216
|
+
color: 'primary',
|
|
49217
|
+
fill: 'solid',
|
|
49218
|
+
size: 'default',
|
|
49219
|
+
shape: 'round',
|
|
49220
|
+
type: 'button',
|
|
49221
|
+
}));
|
|
49222
|
+
/** Guarda para detectar el primer disparo del effect (evita doble carga). */
|
|
49223
|
+
this.lastLoadedOrgId = null;
|
|
49224
|
+
const ns = this.ns;
|
|
49225
|
+
if (!this.i18n.hasNamespace(ns)) {
|
|
49226
|
+
this.i18n.registerContent(ns, ORGANIZATION_VIEW_I18N);
|
|
49227
|
+
}
|
|
49228
|
+
this.nav.setBackHeader('pageTitle', ns, { withMenu: true });
|
|
49229
|
+
// Auto-reload en org-switch: reacciona a activeOrgId() y recarga org + miembros
|
|
49230
|
+
// cuando el usuario cambia de organización activa mientras la vista está
|
|
49231
|
+
// montada. Cubre también la carga inicial — `lastLoadedOrgId` evita recargar
|
|
49232
|
+
// dos veces el mismo id (p.ej. si el effect re-corre por otra dependencia).
|
|
49233
|
+
// `allowSignalWrites` porque las load fns escriben signals síncronamente
|
|
49234
|
+
// (loading/error/token) — Angular 18 bloquea writes en effect sin el flag.
|
|
49235
|
+
effect(() => {
|
|
49236
|
+
const orgId = this.activeOrgId();
|
|
49237
|
+
if (orgId === this.lastLoadedOrgId)
|
|
49238
|
+
return;
|
|
49239
|
+
this.lastLoadedOrgId = orgId;
|
|
49240
|
+
this.loadOrg();
|
|
49241
|
+
this.loadMembers();
|
|
49242
|
+
this.loadRoles();
|
|
49243
|
+
}, { allowSignalWrites: true });
|
|
49244
|
+
connectPageRefresh(async () => {
|
|
49245
|
+
await Promise.all([this.loadOrg(), this.loadMembers()]);
|
|
49246
|
+
});
|
|
49247
|
+
}
|
|
49248
|
+
onEdit() {
|
|
49249
|
+
void this.modalService.open({
|
|
49250
|
+
component: EditOrgModalComponent,
|
|
49251
|
+
componentProps: {
|
|
49252
|
+
org: this.org(),
|
|
49253
|
+
onSuccess: (updated) => {
|
|
49254
|
+
this.org.set(updated);
|
|
49255
|
+
this.resolvedConfig().onOrgEdited?.();
|
|
49256
|
+
},
|
|
49257
|
+
},
|
|
49258
|
+
breakpoints: {
|
|
49259
|
+
breakpoints: [0, 0.85],
|
|
49260
|
+
initialBreakpoint: 0.85,
|
|
49261
|
+
showHandle: true,
|
|
49262
|
+
},
|
|
49263
|
+
backdropDismiss: true,
|
|
49264
|
+
});
|
|
49265
|
+
}
|
|
49266
|
+
async onLeave() {
|
|
49267
|
+
if (this.isOwner() || this.leaving())
|
|
49268
|
+
return;
|
|
49269
|
+
const result = await this.confirmDialog.confirmDestructive({
|
|
49270
|
+
title: this.tt('leaveTitle'),
|
|
49271
|
+
message: this.tt('leaveConfirm'),
|
|
49272
|
+
confirmButton: { text: this.tt('leaveCta') },
|
|
49273
|
+
cancelButton: { text: this.tt('cancelCta') },
|
|
49274
|
+
});
|
|
49275
|
+
if (!result.confirmed)
|
|
49276
|
+
return;
|
|
49277
|
+
const orgId = this.activeOrgId();
|
|
49278
|
+
if (!orgId)
|
|
49279
|
+
return;
|
|
49280
|
+
this.leaving.set(true);
|
|
49281
|
+
try {
|
|
49282
|
+
await firstValueFrom(this.orgService.leaveOrg(orgId));
|
|
49283
|
+
this.toast.show({
|
|
49284
|
+
message: this.tt('leaveSuccess'),
|
|
49285
|
+
color: 'dark',
|
|
49286
|
+
duration: 3500,
|
|
49287
|
+
});
|
|
49288
|
+
const cfg = this.resolvedConfig();
|
|
49289
|
+
this.nav.navigateByUrl(cfg.leaveRedirectRoute);
|
|
49290
|
+
cfg.onLeftOrg?.();
|
|
49291
|
+
}
|
|
49292
|
+
catch (err) {
|
|
49293
|
+
this.errors.handle(err, {
|
|
49294
|
+
context: 'organization.leave',
|
|
49295
|
+
fallbackKey: 'leaveError',
|
|
49296
|
+
i18nNamespace: this.ns,
|
|
49297
|
+
});
|
|
49298
|
+
}
|
|
49299
|
+
finally {
|
|
49300
|
+
this.leaving.set(false);
|
|
49301
|
+
}
|
|
49302
|
+
}
|
|
49303
|
+
onOpenInvite() {
|
|
49304
|
+
void this.modalService.open({
|
|
49305
|
+
component: InviteMemberModalComponent,
|
|
49306
|
+
componentProps: {
|
|
49307
|
+
orgId: this.activeOrgId(),
|
|
49308
|
+
existingMemberIds: this.members().map(m => m.userId),
|
|
49309
|
+
onSuccess: () => {
|
|
49310
|
+
this.loadMembers();
|
|
49311
|
+
this.resolvedConfig().onMemberInvited?.();
|
|
49312
|
+
},
|
|
49313
|
+
},
|
|
49314
|
+
breakpoints: {
|
|
49315
|
+
breakpoints: [0, 0.92],
|
|
49316
|
+
initialBreakpoint: 0.92,
|
|
49317
|
+
showHandle: true,
|
|
49318
|
+
},
|
|
49319
|
+
backdropDismiss: true,
|
|
49320
|
+
});
|
|
49321
|
+
}
|
|
49322
|
+
onViewPermissions() {
|
|
49323
|
+
this.nav.navigateByUrl(this.resolvedConfig().viewPermissionsRoute);
|
|
49324
|
+
}
|
|
49325
|
+
onOpenTransfer() {
|
|
49326
|
+
void this.modalService.open({
|
|
49327
|
+
component: TransferOwnershipModalComponent,
|
|
49328
|
+
componentProps: {
|
|
49329
|
+
members: this.transferableMembers(),
|
|
49330
|
+
onConfirm: (newOwnerId) => void this.onTransfer(newOwnerId),
|
|
49331
|
+
},
|
|
49332
|
+
breakpoints: {
|
|
49333
|
+
breakpoints: [0, 0.75],
|
|
49334
|
+
initialBreakpoint: 0.75,
|
|
49335
|
+
showHandle: true,
|
|
49336
|
+
},
|
|
49337
|
+
backdropDismiss: true,
|
|
49338
|
+
});
|
|
49339
|
+
}
|
|
49340
|
+
async onTransfer(newOwnerId) {
|
|
49341
|
+
if (!newOwnerId || this.transferring())
|
|
49342
|
+
return;
|
|
49343
|
+
const result = await this.confirmDialog.confirmDestructive({
|
|
49344
|
+
title: this.tt('transferTitle'),
|
|
49345
|
+
message: this.tt('transferConfirm'),
|
|
49346
|
+
confirmButton: { text: this.tt('transferCta') },
|
|
49347
|
+
cancelButton: { text: this.tt('cancelCta') },
|
|
49348
|
+
});
|
|
49349
|
+
if (!result.confirmed)
|
|
49350
|
+
return;
|
|
49351
|
+
const orgId = this.activeOrgId();
|
|
49352
|
+
if (!orgId)
|
|
49353
|
+
return;
|
|
49354
|
+
this.transferring.set(true);
|
|
49355
|
+
try {
|
|
49356
|
+
await firstValueFrom(this.orgService.transferOwnership(orgId, newOwnerId));
|
|
49357
|
+
this.toast.show({
|
|
49358
|
+
message: this.tt('transferSuccess'),
|
|
49359
|
+
color: 'dark',
|
|
49360
|
+
duration: 3500,
|
|
49361
|
+
});
|
|
49362
|
+
this.loadOrg();
|
|
49363
|
+
this.loadMembers();
|
|
49364
|
+
this.resolvedConfig().onOwnershipTransferred?.();
|
|
49365
|
+
}
|
|
49366
|
+
catch (err) {
|
|
49367
|
+
this.errors.handle(err, {
|
|
49368
|
+
context: 'organization.transfer',
|
|
49369
|
+
fallbackKey: 'transferError',
|
|
49370
|
+
i18nNamespace: this.ns,
|
|
49371
|
+
});
|
|
49372
|
+
}
|
|
49373
|
+
finally {
|
|
49374
|
+
this.transferring.set(false);
|
|
49375
|
+
}
|
|
49376
|
+
}
|
|
49377
|
+
loadOrg() {
|
|
49378
|
+
const orgId = this.activeOrgId();
|
|
49379
|
+
if (!orgId)
|
|
49380
|
+
return Promise.resolve();
|
|
49381
|
+
this.loading.set(true);
|
|
49382
|
+
this.orgLoadError.set(null);
|
|
49383
|
+
return new Promise(resolve => {
|
|
49384
|
+
this.orgService.getOrg(orgId).subscribe({
|
|
49385
|
+
next: org => {
|
|
49386
|
+
this.org.set(org);
|
|
49387
|
+
this.loading.set(false);
|
|
49388
|
+
resolve();
|
|
49389
|
+
},
|
|
49390
|
+
error: err => {
|
|
49391
|
+
this.orgLoadError.set(err);
|
|
49392
|
+
this.loading.set(false);
|
|
49393
|
+
resolve();
|
|
49394
|
+
},
|
|
49395
|
+
});
|
|
49396
|
+
});
|
|
49397
|
+
}
|
|
49398
|
+
loadMembers() {
|
|
49399
|
+
const orgId = this.activeOrgId();
|
|
49400
|
+
if (!orgId)
|
|
49401
|
+
return Promise.resolve();
|
|
49402
|
+
this.membersLoading.set(true);
|
|
49403
|
+
this.membersNextToken.set(null);
|
|
49404
|
+
this.showAllMembers.set(false);
|
|
49405
|
+
return new Promise(resolve => {
|
|
49406
|
+
this.orgService.getOrgMembers(orgId, { limit: 20 }).subscribe({
|
|
49407
|
+
next: async (res) => {
|
|
49408
|
+
const cards = await this.enrichWithProfiles(res.members);
|
|
49409
|
+
this.members.set(cards);
|
|
49410
|
+
this.membersNextToken.set(res.nextToken ?? null);
|
|
49411
|
+
this.membersLoading.set(false);
|
|
49412
|
+
resolve();
|
|
49413
|
+
},
|
|
49414
|
+
error: err => {
|
|
49415
|
+
this.membersLoadError.set(err);
|
|
49416
|
+
this.membersLoading.set(false);
|
|
49417
|
+
resolve();
|
|
49418
|
+
},
|
|
49419
|
+
});
|
|
49420
|
+
});
|
|
49421
|
+
}
|
|
49422
|
+
loadMoreMembers() {
|
|
49423
|
+
const orgId = this.activeOrgId();
|
|
49424
|
+
const token = this.membersNextToken();
|
|
49425
|
+
if (!orgId || !token || this.loadingMoreMembers())
|
|
49426
|
+
return;
|
|
49427
|
+
this.loadingMoreMembers.set(true);
|
|
49428
|
+
this.orgService.getOrgMembers(orgId, { limit: 20, nextToken: token }).subscribe({
|
|
49429
|
+
next: async (res) => {
|
|
49430
|
+
const cards = await this.enrichWithProfiles(res.members);
|
|
49431
|
+
this.members.update(prev => [...prev, ...cards]);
|
|
49432
|
+
this.membersNextToken.set(res.nextToken ?? null);
|
|
49433
|
+
this.loadingMoreMembers.set(false);
|
|
49434
|
+
},
|
|
49435
|
+
error: err => {
|
|
49436
|
+
this.errors.handle(err, {
|
|
49437
|
+
context: 'organization.loadMoreMembers',
|
|
49438
|
+
fallbackKey: 'membersError',
|
|
49439
|
+
i18nNamespace: this.ns,
|
|
49440
|
+
});
|
|
49441
|
+
this.loadingMoreMembers.set(false);
|
|
49442
|
+
},
|
|
49443
|
+
});
|
|
49444
|
+
}
|
|
49445
|
+
async enrichWithProfiles(members) {
|
|
49446
|
+
const results = await Promise.allSettled(members.map(async (m) => {
|
|
49447
|
+
try {
|
|
49448
|
+
const snap = await getDoc(doc(this.firestore, `profiles/${m.userId}`));
|
|
49449
|
+
const p = snap.exists() ? snap.data() : {};
|
|
49450
|
+
return {
|
|
49451
|
+
...m,
|
|
49452
|
+
handle: p['handle'],
|
|
49453
|
+
avatar: (p['avatarUrl'] ?? p['avatar']),
|
|
49454
|
+
name: p['name'] || m.name,
|
|
49455
|
+
};
|
|
49456
|
+
}
|
|
49457
|
+
catch {
|
|
49458
|
+
return m;
|
|
49459
|
+
}
|
|
49460
|
+
}));
|
|
49461
|
+
return results.map(r => (r.status === 'fulfilled' ? r.value : {}));
|
|
49462
|
+
}
|
|
49463
|
+
loadRoles() {
|
|
49464
|
+
const orgId = this.activeOrgId();
|
|
49465
|
+
if (!orgId)
|
|
49466
|
+
return;
|
|
49467
|
+
this.orgService.listOrgRoles(orgId).subscribe({
|
|
49468
|
+
next: roles => {
|
|
49469
|
+
if (roles.length)
|
|
49470
|
+
this.availableRoles.set(roles);
|
|
49471
|
+
},
|
|
49472
|
+
});
|
|
49473
|
+
}
|
|
49474
|
+
roleLabel(roleIdOrName) {
|
|
49475
|
+
// Try to find by id first (UUID), then by name
|
|
49476
|
+
const found = this.availableRoles().find(r => r.id === roleIdOrName || r.name === roleIdOrName);
|
|
49477
|
+
const name = found?.name ?? roleIdOrName;
|
|
49478
|
+
const keyMap = {
|
|
49479
|
+
viewer: 'roleViewer',
|
|
49480
|
+
editor: 'roleEditor',
|
|
49481
|
+
admin: 'roleAdmin',
|
|
49482
|
+
super_admin: 'roleSuperAdmin',
|
|
49483
|
+
};
|
|
49484
|
+
const key = keyMap[name] ?? name;
|
|
49485
|
+
const label = this.tt(key);
|
|
49486
|
+
return label && !label.startsWith('[') ? label : name;
|
|
49487
|
+
}
|
|
49488
|
+
permissionLabel(perm) {
|
|
49489
|
+
if (perm === '*:*')
|
|
49490
|
+
return this.tt('permAll');
|
|
49491
|
+
const [resource, action] = perm.split(':');
|
|
49492
|
+
const resKey = {
|
|
49493
|
+
users: 'permUsers',
|
|
49494
|
+
documents: 'permDocuments',
|
|
49495
|
+
roles: 'permRoles',
|
|
49496
|
+
media: 'permMedia',
|
|
49497
|
+
templates: 'permTemplates',
|
|
49498
|
+
'*': 'permAll',
|
|
49499
|
+
};
|
|
49500
|
+
const actKey = {
|
|
49501
|
+
read: 'permRead',
|
|
49502
|
+
write: 'permWrite',
|
|
49503
|
+
create: 'permCreate',
|
|
49504
|
+
delete: 'permDelete',
|
|
49505
|
+
manage: 'permManage',
|
|
49506
|
+
'*': 'permAll',
|
|
49507
|
+
};
|
|
49508
|
+
const res = this.tt(resKey[resource] ?? resource);
|
|
49509
|
+
const act = this.tt(actKey[action] ?? action);
|
|
49510
|
+
return `${res}: ${act}`;
|
|
49511
|
+
}
|
|
49512
|
+
onViewMember(member) {
|
|
49513
|
+
void this.modalService.open({
|
|
49514
|
+
component: MemberDetailModalComponent,
|
|
49515
|
+
componentProps: {
|
|
49516
|
+
member,
|
|
49517
|
+
orgId: this.activeOrgId(),
|
|
49518
|
+
availableRoles: this.availableRoles(),
|
|
49519
|
+
canManage: this.canManageMembers() && member.userId !== this.userId(),
|
|
49520
|
+
isSelf: member.userId === this.userId(),
|
|
49521
|
+
onChanged: () => this.loadMembers(),
|
|
49522
|
+
},
|
|
49523
|
+
breakpoints: {
|
|
49524
|
+
breakpoints: [0, 0.7],
|
|
49525
|
+
initialBreakpoint: 0.7,
|
|
49526
|
+
showHandle: true,
|
|
49527
|
+
},
|
|
49528
|
+
backdropDismiss: true,
|
|
49529
|
+
});
|
|
49530
|
+
}
|
|
49531
|
+
tt(key) {
|
|
49532
|
+
return this.i18n.t(key, this.ns);
|
|
49533
|
+
}
|
|
49534
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OrganizationViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
49535
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: OrganizationViewComponent, isStandalone: true, selector: "val-organization-view", inputs: { config: "config" }, ngImport: i0, template: `
|
|
49536
|
+
<div class="page">
|
|
49537
|
+
<header class="page-header">
|
|
49538
|
+
<val-display [props]="{ size: 'small', color: 'dark', content: pageTitle() }" />
|
|
49539
|
+
<val-title
|
|
49540
|
+
[props]="{
|
|
49541
|
+
size: 'large',
|
|
49542
|
+
color: 'dark',
|
|
49543
|
+
bold: false,
|
|
49544
|
+
content: pageDescription(),
|
|
49545
|
+
}"
|
|
49546
|
+
/>
|
|
49547
|
+
</header>
|
|
49548
|
+
|
|
49549
|
+
@if (resolvedConfig().showInfo) {
|
|
49550
|
+
<!-- Org Info -->
|
|
49551
|
+
<section class="settings-section">
|
|
49552
|
+
<div class="section-header-row">
|
|
49553
|
+
<val-title
|
|
49554
|
+
[props]="{
|
|
49555
|
+
size: 'medium',
|
|
49556
|
+
color: 'dark',
|
|
49557
|
+
bold: true,
|
|
49558
|
+
content: tt('infoTitle'),
|
|
49559
|
+
}"
|
|
49560
|
+
/>
|
|
49561
|
+
@if (canEditOrg()) {
|
|
49562
|
+
<val-button [props]="editButtonProps()" (click)="onEdit()" />
|
|
49563
|
+
}
|
|
49564
|
+
</div>
|
|
49565
|
+
|
|
49566
|
+
<div class="section-body">
|
|
49567
|
+
@if (loading()) {
|
|
49568
|
+
<val-skeleton-layout [props]="{ preset: 'detail', rows: 4 }" />
|
|
49569
|
+
} @else if (orgErrorState()) {
|
|
49570
|
+
<val-empty-state [props]="orgErrorState()!" />
|
|
49571
|
+
} @else {
|
|
49572
|
+
@if (org(); as o) {
|
|
49573
|
+
<div class="org-info-card">
|
|
49574
|
+
<div class="org-info-field org-info-field--full">
|
|
49575
|
+
<span class="org-info-label">{{ tt('infoName') }}</span>
|
|
49576
|
+
<span class="org-info-value">{{ o.name }}</span>
|
|
49577
|
+
</div>
|
|
49578
|
+
<div class="org-info-field org-info-field--full">
|
|
49579
|
+
<span class="org-info-label">{{ tt('infoDescription') }}</span>
|
|
49580
|
+
<span class="org-info-value org-info-value--muted">{{ o.description || '—' }}</span>
|
|
49581
|
+
</div>
|
|
49582
|
+
<div class="org-info-row">
|
|
49583
|
+
<div class="org-info-field">
|
|
49584
|
+
<span class="org-info-label">{{ tt('infoPlan') }}</span>
|
|
49585
|
+
<span class="plan-badge plan-badge--{{ o.plan }}">{{ planLabel() }}</span>
|
|
49586
|
+
</div>
|
|
49587
|
+
<div class="org-info-field">
|
|
49588
|
+
<span class="org-info-label">{{ tt('infoType') }}</span>
|
|
49589
|
+
<span class="org-info-value">{{ o.type }}</span>
|
|
49590
|
+
</div>
|
|
49591
|
+
</div>
|
|
49592
|
+
</div>
|
|
49593
|
+
}
|
|
49594
|
+
}
|
|
49595
|
+
</div>
|
|
49596
|
+
</section>
|
|
49597
|
+
}
|
|
49598
|
+
|
|
49599
|
+
@if (resolvedConfig().showMembers) {
|
|
49600
|
+
<!-- Members -->
|
|
49601
|
+
<section class="settings-section">
|
|
49602
|
+
<val-title
|
|
49603
|
+
[props]="{
|
|
49604
|
+
size: 'medium',
|
|
49605
|
+
color: 'dark',
|
|
49606
|
+
bold: true,
|
|
49607
|
+
content: tt('membersTitle'),
|
|
49608
|
+
}"
|
|
49609
|
+
/>
|
|
49610
|
+
<div class="section-body">
|
|
49611
|
+
@if (membersLoading()) {
|
|
49612
|
+
<val-skeleton-layout [props]="{ preset: 'list', rows: 3 }" />
|
|
49613
|
+
} @else if (members().length === 0) {
|
|
49614
|
+
<val-text
|
|
49615
|
+
[props]="{
|
|
49616
|
+
content: tt('membersEmpty'),
|
|
49617
|
+
size: 'medium',
|
|
49618
|
+
color: 'dark',
|
|
49619
|
+
bold: false,
|
|
49620
|
+
}"
|
|
49621
|
+
/>
|
|
49622
|
+
} @else {
|
|
49623
|
+
<div class="members-list">
|
|
49624
|
+
@for (m of visibleMembers(); track m.userId) {
|
|
49625
|
+
<val-member-card
|
|
49626
|
+
[attr.data-testid]="'org-member-' + m.userId"
|
|
49627
|
+
[props]="{
|
|
49628
|
+
id: m.userId,
|
|
49629
|
+
name: m.name,
|
|
49630
|
+
handle: m.handle,
|
|
49631
|
+
email: m.email,
|
|
49632
|
+
avatarUrl: m.avatar,
|
|
49633
|
+
roleLabel: m.roles[0] ? roleLabel(m.roles[0]) : '',
|
|
49634
|
+
actionAriaLabel: tt('viewMemberCta'),
|
|
49635
|
+
}"
|
|
49636
|
+
(onAction)="onViewMember(m)"
|
|
49637
|
+
/>
|
|
49638
|
+
}
|
|
49639
|
+
</div>
|
|
49640
|
+
@if (!showAllMembers() && members().length > 3) {
|
|
49641
|
+
<button class="members-show-more" (click)="showAllMembers.set(true)">
|
|
49642
|
+
{{ tt('membersShowMore') }} ({{ members().length - 3 }})
|
|
49643
|
+
</button>
|
|
49644
|
+
}
|
|
49645
|
+
@if (showAllMembers() && membersNextToken()) {
|
|
49646
|
+
<button class="members-show-more" [disabled]="loadingMoreMembers()" (click)="loadMoreMembers()">
|
|
49647
|
+
{{ loadingMoreMembers() ? '…' : tt('membersShowMore') }}
|
|
49648
|
+
</button>
|
|
49649
|
+
}
|
|
49650
|
+
}
|
|
49651
|
+
</div>
|
|
49652
|
+
</section>
|
|
49653
|
+
}
|
|
49654
|
+
|
|
49655
|
+
@if (resolvedConfig().showRoles) {
|
|
49656
|
+
<!-- Roles y permisos: seccion explicativa, detalle en la ruta de permisos -->
|
|
49657
|
+
<section class="settings-section">
|
|
49658
|
+
<val-title
|
|
49659
|
+
[props]="{
|
|
49660
|
+
size: 'medium',
|
|
49661
|
+
color: 'dark',
|
|
49662
|
+
bold: true,
|
|
49663
|
+
content: tt('rolesSectionTitle'),
|
|
49664
|
+
}"
|
|
49665
|
+
/>
|
|
49666
|
+
<div class="section-body">
|
|
49667
|
+
<val-text
|
|
49668
|
+
[props]="{
|
|
49669
|
+
content: tt('rolesHint'),
|
|
49670
|
+
size: 'medium',
|
|
49671
|
+
color: 'dark',
|
|
49672
|
+
bold: false,
|
|
49673
|
+
}"
|
|
49674
|
+
/>
|
|
49675
|
+
<div class="row-actions">
|
|
49676
|
+
<val-button [props]="viewPermissionsButtonProps()" (click)="onViewPermissions()" />
|
|
49677
|
+
</div>
|
|
49678
|
+
</div>
|
|
49679
|
+
</section>
|
|
49680
|
+
}
|
|
49681
|
+
|
|
49682
|
+
@if (resolvedConfig().showInvite) {
|
|
49683
|
+
<!-- Invite: solo admin+ (gating RBAC interno) -->
|
|
49684
|
+
<section *valHasPermission="'users:*'" class="settings-section" data-testid="org-invite-section">
|
|
49685
|
+
<div class="invite-cta">
|
|
49686
|
+
<div class="invite-cta__text">
|
|
49687
|
+
<val-title
|
|
49688
|
+
[props]="{
|
|
49689
|
+
size: 'medium',
|
|
49690
|
+
color: 'dark',
|
|
49691
|
+
bold: true,
|
|
49692
|
+
content: tt('inviteCtaTitle'),
|
|
49693
|
+
}"
|
|
49694
|
+
/>
|
|
49695
|
+
<val-text
|
|
49696
|
+
[props]="{
|
|
49697
|
+
size: 'medium',
|
|
49698
|
+
color: 'dark',
|
|
49699
|
+
bold: false,
|
|
49700
|
+
content: tt('inviteCtaHint'),
|
|
49701
|
+
}"
|
|
49702
|
+
/>
|
|
49703
|
+
</div>
|
|
49704
|
+
<val-button [props]="openInviteButtonProps()" (click)="onOpenInvite()" />
|
|
49705
|
+
</div>
|
|
49706
|
+
</section>
|
|
49707
|
+
}
|
|
49708
|
+
|
|
49709
|
+
@if (resolvedConfig().showTransferOwnership && isOwner()) {
|
|
49710
|
+
<!-- Transfer ownership: solo owner (gating RBAC interno) -->
|
|
49711
|
+
<section class="settings-section" data-testid="org-transfer-section">
|
|
49712
|
+
<val-title
|
|
49713
|
+
[props]="{
|
|
49714
|
+
size: 'medium',
|
|
49715
|
+
color: 'dark',
|
|
49716
|
+
bold: true,
|
|
49717
|
+
content: tt('transferTitle'),
|
|
49718
|
+
}"
|
|
49719
|
+
/>
|
|
49720
|
+
<div class="section-body">
|
|
49721
|
+
<val-text
|
|
49722
|
+
[props]="{
|
|
49723
|
+
content: tt('transferHint'),
|
|
49724
|
+
size: 'medium',
|
|
49725
|
+
color: 'dark',
|
|
49726
|
+
bold: false,
|
|
49727
|
+
}"
|
|
49728
|
+
/>
|
|
49729
|
+
@if (transferableMembers().length > 0) {
|
|
49730
|
+
<div class="row-actions">
|
|
49731
|
+
<val-button [props]="transferButtonProps()" (click)="onOpenTransfer()" />
|
|
49732
|
+
</div>
|
|
49733
|
+
} @else {
|
|
49734
|
+
<val-text
|
|
49735
|
+
[props]="{
|
|
49736
|
+
content: tt('membersEmpty'),
|
|
49737
|
+
size: 'medium',
|
|
49738
|
+
color: 'dark',
|
|
49739
|
+
bold: false,
|
|
49740
|
+
}"
|
|
49741
|
+
/>
|
|
49742
|
+
}
|
|
49743
|
+
</div>
|
|
49744
|
+
</section>
|
|
49745
|
+
}
|
|
49746
|
+
|
|
49747
|
+
@if (resolvedConfig().showLeave) {
|
|
49748
|
+
<!-- Leave org -->
|
|
49749
|
+
<section class="settings-section">
|
|
49750
|
+
<val-title
|
|
49751
|
+
[props]="{
|
|
49752
|
+
size: 'medium',
|
|
49753
|
+
color: 'dark',
|
|
49754
|
+
bold: true,
|
|
49755
|
+
content: tt('leaveTitle'),
|
|
49756
|
+
}"
|
|
49757
|
+
/>
|
|
49758
|
+
<div class="section-body">
|
|
49759
|
+
<val-text
|
|
49760
|
+
[props]="{
|
|
49761
|
+
content: isOwner() ? tt('leaveOwnerHint') : tt('leaveHint'),
|
|
49762
|
+
size: 'medium',
|
|
49763
|
+
color: 'dark',
|
|
49764
|
+
bold: false,
|
|
49765
|
+
}"
|
|
49766
|
+
/>
|
|
49767
|
+
<div class="row-actions">
|
|
49768
|
+
<val-button [props]="leaveButtonProps()" (click)="onLeave()" />
|
|
49769
|
+
</div>
|
|
49770
|
+
</div>
|
|
49771
|
+
</section>
|
|
49772
|
+
}
|
|
49773
|
+
|
|
49774
|
+
@if (isDebug) {
|
|
49775
|
+
<section class="settings-section rbac-debug">
|
|
49776
|
+
<div class="section-header-row">
|
|
49777
|
+
<val-title
|
|
49778
|
+
[props]="{
|
|
49779
|
+
content: 'RBAC (live)',
|
|
49780
|
+
size: 'small',
|
|
49781
|
+
color: 'medium',
|
|
49782
|
+
bold: false,
|
|
49783
|
+
}"
|
|
49784
|
+
/>
|
|
49785
|
+
</div>
|
|
49786
|
+
<div class="rbac-debug__body">
|
|
49787
|
+
<div class="rbac-debug__row">
|
|
49788
|
+
<span class="rbac-debug__label">Roles</span>
|
|
49789
|
+
<span class="rbac-debug__value">{{ auth.roles().join(', ') || '—' }}</span>
|
|
49790
|
+
</div>
|
|
49791
|
+
<div class="rbac-debug__row">
|
|
49792
|
+
<span class="rbac-debug__label">Permisos</span>
|
|
49793
|
+
<span class="rbac-debug__value rbac-debug__value--perms">{{ auth.permissions().join(', ') || '—' }}</span>
|
|
49794
|
+
</div>
|
|
49795
|
+
</div>
|
|
49796
|
+
</section>
|
|
49797
|
+
}
|
|
49798
|
+
</div>
|
|
49799
|
+
`, isInline: true, styles: [".page{padding:16px 0;max-width:720px;margin:0 auto}.page-header{margin-bottom:16px}.settings-section{padding:16px 0}.settings-section+.settings-section{border-top:1px solid var(--val-border-color, rgba(0, 0, 0, .08))}.section-header-row{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}.section-body{display:flex;flex-direction:column;gap:10px}.row-actions{margin-top:12px}.row-actions--gap{display:flex;gap:8px}.invite-cta{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;flex-wrap:wrap}.invite-cta__text{display:flex;flex-direction:column;gap:4px;flex:1}.org-info-card{border-radius:14px;background:var(--ion-color-light, #f4f5f8);overflow:hidden}:host-context(body.dark) .org-info-card,:host-context(html.ion-palette-dark) .org-info-card,:host-context([data-theme=\"dark\"]) .org-info-card{background:#ffffff0d}.org-info-field{padding:12px 16px;display:flex;flex-direction:column;gap:4px;border-bottom:1px solid var(--val-border-color, rgba(0, 0, 0, .06))}.org-info-field--full{width:100%}.org-info-field:last-child{border-bottom:none}.org-info-row{display:flex}.org-info-row .org-info-field{flex:1}.org-info-row .org-info-field:first-child{border-right:1px solid var(--val-border-color, rgba(0, 0, 0, .06))}.org-info-label{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--ion-color-medium)}.org-info-value{font-size:.95rem;font-weight:500;color:var(--ion-color-dark)}.org-info-value--muted{color:var(--ion-color-medium);font-weight:400}.plan-badge{display:inline-block;font-size:.78rem;font-weight:700;padding:3px 10px;border-radius:20px;width:fit-content}.plan-badge--free{background:var(--ion-color-light-shade, #d7d8da);color:var(--ion-color-dark)}.plan-badge--pro{background:var(--ion-color-primary);color:#fff}.plan-badge--enterprise{background:#f5c542;color:#222}.members-list{display:flex;flex-direction:column;gap:8px}.members-show-more{background:none;border:none;color:var(--ion-color-primary);font-size:14px;font-weight:500;cursor:pointer;padding:8px 0}.rbac-debug{opacity:.7}.rbac-debug__body{display:flex;flex-direction:column;gap:6px;font-family:monospace;font-size:.78rem}.rbac-debug__row{display:flex;gap:8px;align-items:flex-start}.rbac-debug__label{color:var(--ion-color-medium);min-width:72px;flex-shrink:0}.rbac-debug__value{color:var(--ion-color-dark);word-break:break-all}.rbac-debug__value--perms{color:var(--ion-color-medium)}\n"], dependencies: [{ kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: EmptyStateComponent, selector: "val-empty-state", inputs: ["props"] }, { kind: "directive", type: HasPermissionDirective, selector: "[valHasPermission]", inputs: ["valHasPermission"] }, { kind: "component", type: SkeletonLayoutComponent, selector: "val-skeleton-layout", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["preset", "props"], outputs: ["onClick"] }, { kind: "component", type: MemberCardComponent, selector: "val-member-card", inputs: ["props"], outputs: ["onAction"] }] }); }
|
|
49800
|
+
}
|
|
49801
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OrganizationViewComponent, decorators: [{
|
|
49802
|
+
type: Component,
|
|
49803
|
+
args: [{ selector: 'val-organization-view', standalone: true, imports: [
|
|
49804
|
+
DisplayComponent,
|
|
49805
|
+
EmptyStateComponent,
|
|
49806
|
+
HasPermissionDirective,
|
|
49807
|
+
SkeletonLayoutComponent,
|
|
49808
|
+
TitleComponent,
|
|
49809
|
+
TextComponent,
|
|
49810
|
+
ButtonComponent,
|
|
49811
|
+
MemberCardComponent,
|
|
49812
|
+
TransferOwnershipModalComponent,
|
|
49813
|
+
], template: `
|
|
49814
|
+
<div class="page">
|
|
49815
|
+
<header class="page-header">
|
|
49816
|
+
<val-display [props]="{ size: 'small', color: 'dark', content: pageTitle() }" />
|
|
49817
|
+
<val-title
|
|
49818
|
+
[props]="{
|
|
49819
|
+
size: 'large',
|
|
49820
|
+
color: 'dark',
|
|
49821
|
+
bold: false,
|
|
49822
|
+
content: pageDescription(),
|
|
49823
|
+
}"
|
|
49824
|
+
/>
|
|
49825
|
+
</header>
|
|
49826
|
+
|
|
49827
|
+
@if (resolvedConfig().showInfo) {
|
|
49828
|
+
<!-- Org Info -->
|
|
49829
|
+
<section class="settings-section">
|
|
49830
|
+
<div class="section-header-row">
|
|
49831
|
+
<val-title
|
|
49832
|
+
[props]="{
|
|
49833
|
+
size: 'medium',
|
|
49834
|
+
color: 'dark',
|
|
49835
|
+
bold: true,
|
|
49836
|
+
content: tt('infoTitle'),
|
|
49837
|
+
}"
|
|
49838
|
+
/>
|
|
49839
|
+
@if (canEditOrg()) {
|
|
49840
|
+
<val-button [props]="editButtonProps()" (click)="onEdit()" />
|
|
49841
|
+
}
|
|
49842
|
+
</div>
|
|
49843
|
+
|
|
49844
|
+
<div class="section-body">
|
|
49845
|
+
@if (loading()) {
|
|
49846
|
+
<val-skeleton-layout [props]="{ preset: 'detail', rows: 4 }" />
|
|
49847
|
+
} @else if (orgErrorState()) {
|
|
49848
|
+
<val-empty-state [props]="orgErrorState()!" />
|
|
49849
|
+
} @else {
|
|
49850
|
+
@if (org(); as o) {
|
|
49851
|
+
<div class="org-info-card">
|
|
49852
|
+
<div class="org-info-field org-info-field--full">
|
|
49853
|
+
<span class="org-info-label">{{ tt('infoName') }}</span>
|
|
49854
|
+
<span class="org-info-value">{{ o.name }}</span>
|
|
49855
|
+
</div>
|
|
49856
|
+
<div class="org-info-field org-info-field--full">
|
|
49857
|
+
<span class="org-info-label">{{ tt('infoDescription') }}</span>
|
|
49858
|
+
<span class="org-info-value org-info-value--muted">{{ o.description || '—' }}</span>
|
|
49859
|
+
</div>
|
|
49860
|
+
<div class="org-info-row">
|
|
49861
|
+
<div class="org-info-field">
|
|
49862
|
+
<span class="org-info-label">{{ tt('infoPlan') }}</span>
|
|
49863
|
+
<span class="plan-badge plan-badge--{{ o.plan }}">{{ planLabel() }}</span>
|
|
49864
|
+
</div>
|
|
49865
|
+
<div class="org-info-field">
|
|
49866
|
+
<span class="org-info-label">{{ tt('infoType') }}</span>
|
|
49867
|
+
<span class="org-info-value">{{ o.type }}</span>
|
|
49868
|
+
</div>
|
|
49869
|
+
</div>
|
|
49870
|
+
</div>
|
|
49871
|
+
}
|
|
49872
|
+
}
|
|
49873
|
+
</div>
|
|
49874
|
+
</section>
|
|
49875
|
+
}
|
|
49876
|
+
|
|
49877
|
+
@if (resolvedConfig().showMembers) {
|
|
49878
|
+
<!-- Members -->
|
|
49879
|
+
<section class="settings-section">
|
|
49880
|
+
<val-title
|
|
49881
|
+
[props]="{
|
|
49882
|
+
size: 'medium',
|
|
49883
|
+
color: 'dark',
|
|
49884
|
+
bold: true,
|
|
49885
|
+
content: tt('membersTitle'),
|
|
49886
|
+
}"
|
|
49887
|
+
/>
|
|
49888
|
+
<div class="section-body">
|
|
49889
|
+
@if (membersLoading()) {
|
|
49890
|
+
<val-skeleton-layout [props]="{ preset: 'list', rows: 3 }" />
|
|
49891
|
+
} @else if (members().length === 0) {
|
|
49892
|
+
<val-text
|
|
49893
|
+
[props]="{
|
|
49894
|
+
content: tt('membersEmpty'),
|
|
49895
|
+
size: 'medium',
|
|
49896
|
+
color: 'dark',
|
|
49897
|
+
bold: false,
|
|
49898
|
+
}"
|
|
49899
|
+
/>
|
|
49900
|
+
} @else {
|
|
49901
|
+
<div class="members-list">
|
|
49902
|
+
@for (m of visibleMembers(); track m.userId) {
|
|
49903
|
+
<val-member-card
|
|
49904
|
+
[attr.data-testid]="'org-member-' + m.userId"
|
|
49905
|
+
[props]="{
|
|
49906
|
+
id: m.userId,
|
|
49907
|
+
name: m.name,
|
|
49908
|
+
handle: m.handle,
|
|
49909
|
+
email: m.email,
|
|
49910
|
+
avatarUrl: m.avatar,
|
|
49911
|
+
roleLabel: m.roles[0] ? roleLabel(m.roles[0]) : '',
|
|
49912
|
+
actionAriaLabel: tt('viewMemberCta'),
|
|
49913
|
+
}"
|
|
49914
|
+
(onAction)="onViewMember(m)"
|
|
49915
|
+
/>
|
|
49916
|
+
}
|
|
49917
|
+
</div>
|
|
49918
|
+
@if (!showAllMembers() && members().length > 3) {
|
|
49919
|
+
<button class="members-show-more" (click)="showAllMembers.set(true)">
|
|
49920
|
+
{{ tt('membersShowMore') }} ({{ members().length - 3 }})
|
|
49921
|
+
</button>
|
|
49922
|
+
}
|
|
49923
|
+
@if (showAllMembers() && membersNextToken()) {
|
|
49924
|
+
<button class="members-show-more" [disabled]="loadingMoreMembers()" (click)="loadMoreMembers()">
|
|
49925
|
+
{{ loadingMoreMembers() ? '…' : tt('membersShowMore') }}
|
|
49926
|
+
</button>
|
|
49927
|
+
}
|
|
49928
|
+
}
|
|
49929
|
+
</div>
|
|
49930
|
+
</section>
|
|
49931
|
+
}
|
|
49932
|
+
|
|
49933
|
+
@if (resolvedConfig().showRoles) {
|
|
49934
|
+
<!-- Roles y permisos: seccion explicativa, detalle en la ruta de permisos -->
|
|
49935
|
+
<section class="settings-section">
|
|
49936
|
+
<val-title
|
|
49937
|
+
[props]="{
|
|
49938
|
+
size: 'medium',
|
|
49939
|
+
color: 'dark',
|
|
49940
|
+
bold: true,
|
|
49941
|
+
content: tt('rolesSectionTitle'),
|
|
49942
|
+
}"
|
|
49943
|
+
/>
|
|
49944
|
+
<div class="section-body">
|
|
49945
|
+
<val-text
|
|
49946
|
+
[props]="{
|
|
49947
|
+
content: tt('rolesHint'),
|
|
49948
|
+
size: 'medium',
|
|
49949
|
+
color: 'dark',
|
|
49950
|
+
bold: false,
|
|
49951
|
+
}"
|
|
49952
|
+
/>
|
|
49953
|
+
<div class="row-actions">
|
|
49954
|
+
<val-button [props]="viewPermissionsButtonProps()" (click)="onViewPermissions()" />
|
|
49955
|
+
</div>
|
|
49956
|
+
</div>
|
|
49957
|
+
</section>
|
|
49958
|
+
}
|
|
49959
|
+
|
|
49960
|
+
@if (resolvedConfig().showInvite) {
|
|
49961
|
+
<!-- Invite: solo admin+ (gating RBAC interno) -->
|
|
49962
|
+
<section *valHasPermission="'users:*'" class="settings-section" data-testid="org-invite-section">
|
|
49963
|
+
<div class="invite-cta">
|
|
49964
|
+
<div class="invite-cta__text">
|
|
49965
|
+
<val-title
|
|
49966
|
+
[props]="{
|
|
49967
|
+
size: 'medium',
|
|
49968
|
+
color: 'dark',
|
|
49969
|
+
bold: true,
|
|
49970
|
+
content: tt('inviteCtaTitle'),
|
|
49971
|
+
}"
|
|
49972
|
+
/>
|
|
49973
|
+
<val-text
|
|
49974
|
+
[props]="{
|
|
49975
|
+
size: 'medium',
|
|
49976
|
+
color: 'dark',
|
|
49977
|
+
bold: false,
|
|
49978
|
+
content: tt('inviteCtaHint'),
|
|
49979
|
+
}"
|
|
49980
|
+
/>
|
|
49981
|
+
</div>
|
|
49982
|
+
<val-button [props]="openInviteButtonProps()" (click)="onOpenInvite()" />
|
|
49983
|
+
</div>
|
|
49984
|
+
</section>
|
|
49985
|
+
}
|
|
49986
|
+
|
|
49987
|
+
@if (resolvedConfig().showTransferOwnership && isOwner()) {
|
|
49988
|
+
<!-- Transfer ownership: solo owner (gating RBAC interno) -->
|
|
49989
|
+
<section class="settings-section" data-testid="org-transfer-section">
|
|
49990
|
+
<val-title
|
|
49991
|
+
[props]="{
|
|
49992
|
+
size: 'medium',
|
|
49993
|
+
color: 'dark',
|
|
49994
|
+
bold: true,
|
|
49995
|
+
content: tt('transferTitle'),
|
|
49996
|
+
}"
|
|
49997
|
+
/>
|
|
49998
|
+
<div class="section-body">
|
|
49999
|
+
<val-text
|
|
50000
|
+
[props]="{
|
|
50001
|
+
content: tt('transferHint'),
|
|
50002
|
+
size: 'medium',
|
|
50003
|
+
color: 'dark',
|
|
50004
|
+
bold: false,
|
|
50005
|
+
}"
|
|
50006
|
+
/>
|
|
50007
|
+
@if (transferableMembers().length > 0) {
|
|
50008
|
+
<div class="row-actions">
|
|
50009
|
+
<val-button [props]="transferButtonProps()" (click)="onOpenTransfer()" />
|
|
50010
|
+
</div>
|
|
50011
|
+
} @else {
|
|
50012
|
+
<val-text
|
|
50013
|
+
[props]="{
|
|
50014
|
+
content: tt('membersEmpty'),
|
|
50015
|
+
size: 'medium',
|
|
50016
|
+
color: 'dark',
|
|
50017
|
+
bold: false,
|
|
50018
|
+
}"
|
|
50019
|
+
/>
|
|
50020
|
+
}
|
|
50021
|
+
</div>
|
|
50022
|
+
</section>
|
|
50023
|
+
}
|
|
50024
|
+
|
|
50025
|
+
@if (resolvedConfig().showLeave) {
|
|
50026
|
+
<!-- Leave org -->
|
|
50027
|
+
<section class="settings-section">
|
|
50028
|
+
<val-title
|
|
50029
|
+
[props]="{
|
|
50030
|
+
size: 'medium',
|
|
50031
|
+
color: 'dark',
|
|
50032
|
+
bold: true,
|
|
50033
|
+
content: tt('leaveTitle'),
|
|
50034
|
+
}"
|
|
50035
|
+
/>
|
|
50036
|
+
<div class="section-body">
|
|
50037
|
+
<val-text
|
|
50038
|
+
[props]="{
|
|
50039
|
+
content: isOwner() ? tt('leaveOwnerHint') : tt('leaveHint'),
|
|
50040
|
+
size: 'medium',
|
|
50041
|
+
color: 'dark',
|
|
50042
|
+
bold: false,
|
|
50043
|
+
}"
|
|
50044
|
+
/>
|
|
50045
|
+
<div class="row-actions">
|
|
50046
|
+
<val-button [props]="leaveButtonProps()" (click)="onLeave()" />
|
|
50047
|
+
</div>
|
|
50048
|
+
</div>
|
|
50049
|
+
</section>
|
|
50050
|
+
}
|
|
50051
|
+
|
|
50052
|
+
@if (isDebug) {
|
|
50053
|
+
<section class="settings-section rbac-debug">
|
|
50054
|
+
<div class="section-header-row">
|
|
50055
|
+
<val-title
|
|
50056
|
+
[props]="{
|
|
50057
|
+
content: 'RBAC (live)',
|
|
50058
|
+
size: 'small',
|
|
50059
|
+
color: 'medium',
|
|
50060
|
+
bold: false,
|
|
50061
|
+
}"
|
|
50062
|
+
/>
|
|
50063
|
+
</div>
|
|
50064
|
+
<div class="rbac-debug__body">
|
|
50065
|
+
<div class="rbac-debug__row">
|
|
50066
|
+
<span class="rbac-debug__label">Roles</span>
|
|
50067
|
+
<span class="rbac-debug__value">{{ auth.roles().join(', ') || '—' }}</span>
|
|
50068
|
+
</div>
|
|
50069
|
+
<div class="rbac-debug__row">
|
|
50070
|
+
<span class="rbac-debug__label">Permisos</span>
|
|
50071
|
+
<span class="rbac-debug__value rbac-debug__value--perms">{{ auth.permissions().join(', ') || '—' }}</span>
|
|
50072
|
+
</div>
|
|
50073
|
+
</div>
|
|
50074
|
+
</section>
|
|
50075
|
+
}
|
|
50076
|
+
</div>
|
|
50077
|
+
`, styles: [".page{padding:16px 0;max-width:720px;margin:0 auto}.page-header{margin-bottom:16px}.settings-section{padding:16px 0}.settings-section+.settings-section{border-top:1px solid var(--val-border-color, rgba(0, 0, 0, .08))}.section-header-row{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}.section-body{display:flex;flex-direction:column;gap:10px}.row-actions{margin-top:12px}.row-actions--gap{display:flex;gap:8px}.invite-cta{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;flex-wrap:wrap}.invite-cta__text{display:flex;flex-direction:column;gap:4px;flex:1}.org-info-card{border-radius:14px;background:var(--ion-color-light, #f4f5f8);overflow:hidden}:host-context(body.dark) .org-info-card,:host-context(html.ion-palette-dark) .org-info-card,:host-context([data-theme=\"dark\"]) .org-info-card{background:#ffffff0d}.org-info-field{padding:12px 16px;display:flex;flex-direction:column;gap:4px;border-bottom:1px solid var(--val-border-color, rgba(0, 0, 0, .06))}.org-info-field--full{width:100%}.org-info-field:last-child{border-bottom:none}.org-info-row{display:flex}.org-info-row .org-info-field{flex:1}.org-info-row .org-info-field:first-child{border-right:1px solid var(--val-border-color, rgba(0, 0, 0, .06))}.org-info-label{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--ion-color-medium)}.org-info-value{font-size:.95rem;font-weight:500;color:var(--ion-color-dark)}.org-info-value--muted{color:var(--ion-color-medium);font-weight:400}.plan-badge{display:inline-block;font-size:.78rem;font-weight:700;padding:3px 10px;border-radius:20px;width:fit-content}.plan-badge--free{background:var(--ion-color-light-shade, #d7d8da);color:var(--ion-color-dark)}.plan-badge--pro{background:var(--ion-color-primary);color:#fff}.plan-badge--enterprise{background:#f5c542;color:#222}.members-list{display:flex;flex-direction:column;gap:8px}.members-show-more{background:none;border:none;color:var(--ion-color-primary);font-size:14px;font-weight:500;cursor:pointer;padding:8px 0}.rbac-debug{opacity:.7}.rbac-debug__body{display:flex;flex-direction:column;gap:6px;font-family:monospace;font-size:.78rem}.rbac-debug__row{display:flex;gap:8px;align-items:flex-start}.rbac-debug__label{color:var(--ion-color-medium);min-width:72px;flex-shrink:0}.rbac-debug__value{color:var(--ion-color-dark);word-break:break-all}.rbac-debug__value--perms{color:var(--ion-color-medium)}\n"] }]
|
|
50078
|
+
}], ctorParameters: () => [], propDecorators: { config: [{
|
|
50079
|
+
type: Input
|
|
50080
|
+
}] } });
|
|
50081
|
+
|
|
50082
|
+
/**
|
|
50083
|
+
* Helper para montar la vista Gestión de organización (`val-organization-view`)
|
|
50084
|
+
* como ruta en una app del factory. El `config` se pasa por route `data`
|
|
50085
|
+
* (`organizationConfig`) y el componente lo lee como fallback de su
|
|
50086
|
+
* `@Input() config`.
|
|
50087
|
+
*
|
|
50088
|
+
* @example
|
|
50089
|
+
* ```ts
|
|
50090
|
+
* // settings.routes.ts
|
|
50091
|
+
* export const settingsRoutes: Routes = [
|
|
50092
|
+
* ...provideValtechOrganizationRoutes(), // → /app/settings/organization
|
|
50093
|
+
* { path: 'preferences', loadComponent: () => ... },
|
|
50094
|
+
* ];
|
|
50095
|
+
*
|
|
50096
|
+
* // con config acotada:
|
|
50097
|
+
* ...provideValtechOrganizationRoutes({ config: { showLeave: false } }),
|
|
50098
|
+
* ...provideValtechOrganizationRoutes({ config: { viewPermissionsRoute: '/app/roles' } }),
|
|
50099
|
+
* ```
|
|
50100
|
+
*/
|
|
50101
|
+
function provideValtechOrganizationRoutes(opts) {
|
|
50102
|
+
return [
|
|
50103
|
+
{
|
|
50104
|
+
path: opts?.path ?? 'organization',
|
|
50105
|
+
component: OrganizationViewComponent,
|
|
50106
|
+
data: { organizationConfig: opts?.config },
|
|
50107
|
+
},
|
|
50108
|
+
];
|
|
50109
|
+
}
|
|
50110
|
+
|
|
48890
50111
|
/** Built-in label sets for the three platform locales. */
|
|
48891
50112
|
const CALLOUT_LABELS = {
|
|
48892
50113
|
es: {
|
|
@@ -59211,5 +60432,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
59211
60432
|
* Generated bundle index. Do not edit.
|
|
59212
60433
|
*/
|
|
59213
60434
|
|
|
59214
|
-
export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, ARTICLE_CARD_DEFAULTS, ARTICLE_SPACING, ARTICLE_STRIP_DEFAULTS, AUTH_CTA_DEFAULTS, AVATAR_UPLOAD_DEFAULTS, AccordionComponent, AccountViewComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AnimatedTerminalComponent, AppConfigService, AppVersionService, ArticleBuilder, ArticleCardComponent, ArticleComponent, ArticleStripComponent, AttachmentUploaderComponent, AuthBackgroundComponent, AuthCtaComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BaseDefault, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, CALLOUT_LABELS, CHEV_KEYS, CIRCLE_KEYS, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CONTENT_CARD_DEFAULTS, CORNER_KEYS, CTA_CARD_DEFAULTS, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, ChangeEmailModalComponent, ChangePasswordModalComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContainerComponent, ContentCardComponent, ContentLoaderComponent, ContentReactionComponent, ContentService, ContentTransformer, CookieBannerComponent, CountdownComponent, CreateOrgModalComponent, CtaCardComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_APP_VERSION_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_CANCEL_BUTTON, DEFAULT_CHECK_INTERVAL_MS, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_DEBUG_CONSOLE_CONFIG, DEFAULT_DONATION_CONFIG, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_SPLASH_SCREEN_CONFIG, DataTableComponent, DateInputComponent, DateRangeInputComponent, DebugConsoleComponent, DeleteAccountModalComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DonationService, DownloadService, EditOrgModalComponent, EmailInputComponent, EmptyStateComponent, ExpandableTextComponent, FEATURES_LIST_DEFAULTS, FUN_MODAL_DEFAULTS, FabComponent, FaqComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FontSizeOption, FontSizeService, FooterComponent, FooterLinksComponent, FormComponent, FormSkeletonComponent, FunHeaderComponent, FunModalComponent, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, HasPermissionDirective, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, I18nService, IMAGE_DEFAULTS, INFO_CARD_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, INVITATION_CARD_DEFAULTS, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoCardComponent, InfoComponent, InputI18nHelper, InputType, InvitationCardComponent, InviteMemberModalComponent, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGIN_DEFAULTS, LandingSplitComponent, LandingStepsComponent, LanguageSelectorComponent, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginAttemptModalComponent, LoginComponent, MEDIA_OBJECT_DEFAULTS, MEMBER_CARD_DEFAULTS, METRIC_CARD_DEFAULTS, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MediaObjectComponent, MemberCardComponent, MemberDetailModalComponent, MenuComponent, MessagingService, MetaService, MetricCardComponent, MfaModalComponent, ModalService, ModalShellComponent, MultiSelectSearchComponent, NUM_KEYS, NavigationService, NetworkBannerComponent, NetworkStatusService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationsService, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OrgInfoSheetComponent, OrgService, OrgSwitchService, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PATTERN_MOTIFS, PATTERN_PALETTES, PATTERN_STYLE_CONFIGS, PLATFORM_CONFIGS, PageContentComponent, PageLinksComponent, PageRefreshService, PageTemplateComponent, PageWavesComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PatternComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PreferencesViewComponent, PresetService, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProfileSkeletonComponent, ProfileViewComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QueryBuilder, QuoteBoxComponent, REQUEST_STATUSES, RadioInputComponent, RangeInputComponent, RatingComponent, RefresherComponent, RequestFirestoreService, RequestFormBuilderService, RequestService, RightsFooterComponent, RotatingTextComponent, SEARCH_HEADER_DEFAULTS, SETTINGS_SECTIONS_CATALOG, SHAPE_KEYS, SHARE_PROFILE_MODAL_DEFAULTS, SKELETON_LAYOUT_DEFAULT_ROWS, SKELETON_PRESETS, SOLID_KEYS, STATS_BAR_DEFAULTS, STROKE_KEYS, SearchHeaderComponent, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SecurityViewComponent, SegmentControlComponent, SelectSearchComponent, SessionListModalComponent, SessionService, SettingsHubComponent, ShareButtonsComponent, ShareProfileModalComponent, SimpleComponent, SkeletonComponent, SkeletonLayoutComponent, SkeletonService, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, SplashScreenService, StatsBarComponent, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, SwitchOrgModalComponent, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TransferOwnershipModalComponent, TranslatePipe, TypedCollection, UPDATE_BANNER_DEFAULT_CONTENT, UPDATE_BANNER_I18N_NAMESPACE, UpdateBannerComponent, UserAvatarComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_APP_VERSION, VALTECH_AUTH_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_CONTENT_CONFIG, VALTECH_DEBUG_CONSOLE, VALTECH_DEFAULT_CONTENT, VALTECH_DONATION_CONFIG, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_NETWORK_ERROR_KEY, VALTECH_SITE_PATHS, VALTECH_SOCIAL_LINKS, VALTECH_SPLASH_SCREEN, VALTECH_WEB_BASE_URLS, VERSION, ValtechErrorService, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, authPasswordValidator, beautifyLegalArticle, blogPost, buildCompanyFooterProps, buildFooterLinks, buildLegalLinkResolver, buildPath, buildSettingsCards, collections, connectPageRefresh, createErrorStateProps, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createRefreshableStream, createTitleProps, docs, errorLoggingInterceptor, extractPathParams, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, guestGuard, hasEmulators, interpretError, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, provideSplashScreen, provideValtechAccountRoutes, provideValtechAds, provideValtechAppConfig, provideValtechAppVersion, provideValtechAuth, provideValtechAuthInterceptor, provideValtechContent, provideValtechDebugConsole, provideValtechDonations, provideValtechErrorHandling, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechPreferencesRoutes, provideValtechPresets, provideValtechProfileRoutes, provideValtechSecurityRoutes, provideValtechSettingsRoutes, provideValtechSite, provideValtechSkeleton, query, renderPatternSvgInner, replaceSpecialChars, resolveColor$1 as resolveColor, resolveInputDefaultValue, resolveWebBaseUrl, roleGuard, storagePaths, superAdminGuard, toArticle };
|
|
60435
|
+
export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, ARTICLE_CARD_DEFAULTS, ARTICLE_SPACING, ARTICLE_STRIP_DEFAULTS, AUTH_CTA_DEFAULTS, AVATAR_UPLOAD_DEFAULTS, AccordionComponent, AccountViewComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AnimatedTerminalComponent, AppConfigService, AppVersionService, ArticleBuilder, ArticleCardComponent, ArticleComponent, ArticleStripComponent, AttachmentUploaderComponent, AuthBackgroundComponent, AuthCtaComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BaseDefault, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, CALLOUT_LABELS, CHEV_KEYS, CIRCLE_KEYS, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CONTENT_CARD_DEFAULTS, CORNER_KEYS, CTA_CARD_DEFAULTS, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, ChangeEmailModalComponent, ChangePasswordModalComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContainerComponent, ContentCardComponent, ContentLoaderComponent, ContentReactionComponent, ContentService, ContentTransformer, CookieBannerComponent, CountdownComponent, CreateOrgModalComponent, CtaCardComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_APP_VERSION_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_CANCEL_BUTTON, DEFAULT_CHECK_INTERVAL_MS, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_DEBUG_CONSOLE_CONFIG, DEFAULT_DONATION_CONFIG, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_SPLASH_SCREEN_CONFIG, DataTableComponent, DateInputComponent, DateRangeInputComponent, DebugConsoleComponent, DeleteAccountModalComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DonationService, DownloadService, EditOrgModalComponent, EmailInputComponent, EmptyStateComponent, ExpandableTextComponent, FEATURES_LIST_DEFAULTS, FUN_MODAL_DEFAULTS, FabComponent, FaqComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FontSizeOption, FontSizeService, FooterComponent, FooterLinksComponent, FormComponent, FormSkeletonComponent, FunHeaderComponent, FunModalComponent, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, HasPermissionDirective, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, I18nService, IMAGE_DEFAULTS, INFO_CARD_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, INVITATION_CARD_DEFAULTS, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoCardComponent, InfoComponent, InputI18nHelper, InputType, InvitationCardComponent, InviteMemberModalComponent, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGIN_DEFAULTS, LandingSplitComponent, LandingStepsComponent, LanguageSelectorComponent, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginAttemptModalComponent, LoginComponent, MEDIA_OBJECT_DEFAULTS, MEMBER_CARD_DEFAULTS, METRIC_CARD_DEFAULTS, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MediaObjectComponent, MemberCardComponent, MemberDetailModalComponent, MenuComponent, MessagingService, MetaService, MetricCardComponent, MfaModalComponent, ModalService, ModalShellComponent, MultiSelectSearchComponent, NUM_KEYS, NavigationService, NetworkBannerComponent, NetworkStatusService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationsService, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OrgInfoSheetComponent, OrgService, OrgSwitchService, OrganizationViewComponent, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PATTERN_MOTIFS, PATTERN_PALETTES, PATTERN_STYLE_CONFIGS, PLATFORM_CONFIGS, PageContentComponent, PageLinksComponent, PageRefreshService, PageTemplateComponent, PageWavesComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PatternComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PreferencesViewComponent, PresetService, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProfileSkeletonComponent, ProfileViewComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QueryBuilder, QuoteBoxComponent, REQUEST_STATUSES, RadioInputComponent, RangeInputComponent, RatingComponent, RefresherComponent, RequestFirestoreService, RequestFormBuilderService, RequestService, RightsFooterComponent, RotatingTextComponent, SEARCH_HEADER_DEFAULTS, SETTINGS_SECTIONS_CATALOG, SHAPE_KEYS, SHARE_PROFILE_MODAL_DEFAULTS, SKELETON_LAYOUT_DEFAULT_ROWS, SKELETON_PRESETS, SOLID_KEYS, STATS_BAR_DEFAULTS, STROKE_KEYS, SearchHeaderComponent, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SecurityViewComponent, SegmentControlComponent, SelectSearchComponent, SessionListModalComponent, SessionService, SettingsHubComponent, ShareButtonsComponent, ShareProfileModalComponent, SimpleComponent, SkeletonComponent, SkeletonLayoutComponent, SkeletonService, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, SplashScreenService, StatsBarComponent, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, SwitchOrgModalComponent, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TransferOwnershipModalComponent, TranslatePipe, TypedCollection, UPDATE_BANNER_DEFAULT_CONTENT, UPDATE_BANNER_I18N_NAMESPACE, UpdateBannerComponent, UserAvatarComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_APP_VERSION, VALTECH_AUTH_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_CONTENT_CONFIG, VALTECH_DEBUG_CONSOLE, VALTECH_DEFAULT_CONTENT, VALTECH_DONATION_CONFIG, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_NETWORK_ERROR_KEY, VALTECH_SITE_PATHS, VALTECH_SOCIAL_LINKS, VALTECH_SPLASH_SCREEN, VALTECH_WEB_BASE_URLS, VERSION, ValtechErrorService, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, authPasswordValidator, beautifyLegalArticle, blogPost, buildCompanyFooterProps, buildFooterLinks, buildLegalLinkResolver, buildPath, buildSettingsCards, collections, connectPageRefresh, createErrorStateProps, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createRefreshableStream, createTitleProps, docs, errorLoggingInterceptor, extractPathParams, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, guestGuard, hasEmulators, interpretError, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, provideSplashScreen, provideValtechAccountRoutes, provideValtechAds, provideValtechAppConfig, provideValtechAppVersion, provideValtechAuth, provideValtechAuthInterceptor, provideValtechContent, provideValtechDebugConsole, provideValtechDonations, provideValtechErrorHandling, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechOrganizationRoutes, provideValtechPreferencesRoutes, provideValtechPresets, provideValtechProfileRoutes, provideValtechSecurityRoutes, provideValtechSettingsRoutes, provideValtechSite, provideValtechSkeleton, query, renderPatternSvgInner, replaceSpecialChars, resolveColor$1 as resolveColor, resolveInputDefaultValue, resolveWebBaseUrl, roleGuard, storagePaths, superAdminGuard, toArticle };
|
|
59215
60436
|
//# sourceMappingURL=valtech-components.mjs.map
|