@avora-labs/meta-forge 1.3.0 → 1.5.1
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/fesm2022/{avora-labs-meta-forge-login.page-BW-RWCQM.mjs → avora-labs-meta-forge-login.page-D72_EUGF.mjs} +58 -44
- package/fesm2022/{avora-labs-meta-forge-login.page-BW-RWCQM.mjs.map → avora-labs-meta-forge-login.page-D72_EUGF.mjs.map} +1 -1
- package/fesm2022/avora-labs-meta-forge.mjs +234 -387
- package/fesm2022/avora-labs-meta-forge.mjs.map +1 -1
- package/package.json +1 -1
- package/types/avora-labs-meta-forge.d.ts +54 -170
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { signal, Injectable, computed, inject, ViewContainerRef, ViewChild, Input, Component, DestroyRef, effect, InjectionToken, forwardRef, EventEmitter, Output, APP_INITIALIZER } from '@angular/core';
|
|
3
|
-
import * as i1 from '@angular/router';
|
|
3
|
+
import * as i1$2 from '@angular/router';
|
|
4
4
|
import { Router, ActivatedRoute, NavigationEnd, RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router';
|
|
5
5
|
import { Title, DomSanitizer } from '@angular/platform-browser';
|
|
6
6
|
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
|
|
7
7
|
import { Subject, timeout, firstValueFrom, retry, throwError, timer, filter, catchError as catchError$1 } from 'rxjs';
|
|
8
8
|
import { catchError, map, distinctUntilChanged } from 'rxjs/operators';
|
|
9
9
|
import { toSignal } from '@angular/core/rxjs-interop';
|
|
10
|
-
import * as i1
|
|
10
|
+
import * as i1 from '@angular/common';
|
|
11
11
|
import { CommonModule, TitleCasePipe, DatePipe, CurrencyPipe } from '@angular/common';
|
|
12
|
-
import * as i1$
|
|
12
|
+
import * as i1$1 from '@angular/forms';
|
|
13
13
|
import { Validators, FormControl, FormGroup, ReactiveFormsModule, FormArray, FormsModule } from '@angular/forms';
|
|
14
14
|
import * as i2 from '@angular/cdk/drag-drop';
|
|
15
15
|
import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';
|
|
@@ -1860,141 +1860,189 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
1860
1860
|
`, styles: [".amf-page-wrapper{display:flex;flex-direction:column;gap:24px;width:100%}.amf-section{display:block;width:100%}.amf-animate-fade{animation:amfFadeIn .3s ease-out}.amf-animate-slide-up{animation:amfSlideUp .3s ease-out}.amf-animate-zoom{animation:amfZoom .3s ease-out}@keyframes amfFadeIn{0%{opacity:0}to{opacity:1}}@keyframes amfSlideUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes amfZoom{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}\n"] }]
|
|
1861
1861
|
}], ctorParameters: () => [] });
|
|
1862
1862
|
|
|
1863
|
-
/**
|
|
1864
|
-
* ╔══════════════════════════════════════════════════════════════════╗
|
|
1865
|
-
* ║ DEMO / PROTOTYPE AUTH SERVICE — NOT FOR PRODUCTION ║
|
|
1866
|
-
* ╠══════════════════════════════════════════════════════════════════╣
|
|
1867
|
-
* ║ This service simulates authentication entirely on the client. ║
|
|
1868
|
-
* ║ The login() method accepts ANY email and password and creates ║
|
|
1869
|
-
* ║ a fake JWT-shaped token. There is NO real credential check. ║
|
|
1870
|
-
* ║ ║
|
|
1871
|
-
* ║ Purpose: let framework developers demo the full auth UI flow ║
|
|
1872
|
-
* ║ (login → guard → interceptor → logout) without a live backend. ║
|
|
1873
|
-
* ║ ║
|
|
1874
|
-
* ║ ── TO SWITCH TO REAL AUTH ─────────────────────────────────── ║
|
|
1875
|
-
* ║ Option A (recommended): Use MetaAuthService directly. ║
|
|
1876
|
-
* ║ • Configure `auth.loginEndpoint` in AppMeta to a real endpoint ║
|
|
1877
|
-
* ║ • Remove mock:true from that endpoint definition ║
|
|
1878
|
-
* ║ • MetaAuthService handles token storage + auto-refresh ║
|
|
1879
|
-
* ║ ║
|
|
1880
|
-
* ║ Option B: Keep this service but replace _mockLogin() body with ║
|
|
1881
|
-
* ║ a real HTTP call (e.g. via HttpClient or MetaApiService). ║
|
|
1882
|
-
* ║ ║
|
|
1883
|
-
* ║ See FRAMEWORK_GUIDE.md §3 for a step-by-step migration guide. ║
|
|
1884
|
-
* ╚══════════════════════════════════════════════════════════════════╝
|
|
1885
|
-
*/
|
|
1886
1863
|
class AuthService {
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1864
|
+
state = inject(MetaStateService);
|
|
1865
|
+
apiService = inject(MetaApiService);
|
|
1866
|
+
router = inject(Router);
|
|
1867
|
+
config = null;
|
|
1868
|
+
refreshTimer;
|
|
1869
|
+
isDevMode = false;
|
|
1870
|
+
REDIRECT_KEY = 'amf_auth_redirect';
|
|
1871
|
+
// ──────────────────────────────────────────────────────────────
|
|
1872
|
+
// Reactive Signals (For UI Binding)
|
|
1873
|
+
// ──────────────────────────────────────────────────────────────
|
|
1874
|
+
user = this.state.select('auth.user');
|
|
1875
|
+
isAuthenticated = computed(() => {
|
|
1876
|
+
const isAuth = this.state.select('auth.isAuthenticated')();
|
|
1877
|
+
if (!isAuth)
|
|
1878
|
+
return false;
|
|
1879
|
+
return !this.isTokenExpired();
|
|
1880
|
+
}, ...(ngDevMode ? [{ debugName: "isAuthenticated" }] : /* istanbul ignore next */ []));
|
|
1881
|
+
// ──────────────────────────────────────────────────────────────
|
|
1882
|
+
// Configuration
|
|
1883
|
+
// ──────────────────────────────────────────────────────────────
|
|
1884
|
+
configure(authConfig, isDevMode = false) {
|
|
1885
|
+
this.config = authConfig;
|
|
1886
|
+
this.isDevMode = isDevMode;
|
|
1887
|
+
// Load persisted token on startup
|
|
1888
|
+
const token = this.getStoredToken();
|
|
1889
|
+
if (token) {
|
|
1890
|
+
this.state.set('auth.token', token);
|
|
1891
|
+
this.state.set('auth.isAuthenticated', true);
|
|
1892
|
+
if (authConfig.autoRefresh) {
|
|
1893
|
+
this.scheduleTokenRefresh();
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
// Load persisted user
|
|
1897
|
+
const userRaw = this.getFromStorage(`${authConfig.tokenKey || 'amf_auth'}_user`);
|
|
1898
|
+
if (userRaw) {
|
|
1899
|
+
try {
|
|
1900
|
+
const user = JSON.parse(userRaw);
|
|
1901
|
+
this.state.set('auth.user', user);
|
|
1902
|
+
}
|
|
1903
|
+
catch { /* invalid stored user */ }
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
// ──────────────────────────────────────────────────────────────
|
|
1907
|
+
// Token Management
|
|
1908
|
+
// ──────────────────────────────────────────────────────────────
|
|
1909
|
+
setToken(token, refreshToken) {
|
|
1910
|
+
const storage = this.getStorage();
|
|
1911
|
+
const tokenKey = this.config?.tokenKey || 'amf_auth_token';
|
|
1912
|
+
storage.setItem(tokenKey, token);
|
|
1913
|
+
this.state.set('auth.token', token);
|
|
1914
|
+
this.state.set('auth.isAuthenticated', true);
|
|
1915
|
+
if (refreshToken) {
|
|
1916
|
+
const refreshKey = this.config?.refreshTokenKey || 'amf_auth_refresh';
|
|
1917
|
+
storage.setItem(refreshKey, refreshToken);
|
|
1918
|
+
this.state.set('auth.refreshToken', refreshToken);
|
|
1919
|
+
}
|
|
1920
|
+
if (this.config?.autoRefresh) {
|
|
1921
|
+
this.scheduleTokenRefresh();
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
getToken() {
|
|
1925
|
+
return this.state.get('auth.token') || this.getStoredToken();
|
|
1926
|
+
}
|
|
1927
|
+
getRefreshToken() {
|
|
1928
|
+
const refreshKey = this.config?.refreshTokenKey || 'amf_auth_refresh';
|
|
1929
|
+
return this.getFromStorage(refreshKey);
|
|
1930
|
+
}
|
|
1931
|
+
// ──────────────────────────────────────────────────────────────
|
|
1932
|
+
// User Management
|
|
1933
|
+
// ──────────────────────────────────────────────────────────────
|
|
1934
|
+
setUser(user) {
|
|
1935
|
+
this.state.set('auth.user', user);
|
|
1936
|
+
this.state.set('auth.roles', user.roles || []);
|
|
1937
|
+
this.state.set('auth.permissions', user.permissions || []);
|
|
1938
|
+
const tokenKey = this.config?.tokenKey || 'amf_auth';
|
|
1939
|
+
const storage = this.getStorage();
|
|
1940
|
+
storage.setItem(`${tokenKey}_user`, JSON.stringify(user));
|
|
1941
|
+
}
|
|
1942
|
+
getUserProfile() {
|
|
1943
|
+
return this.state.get('auth.user') || null;
|
|
1903
1944
|
}
|
|
1904
|
-
|
|
1905
|
-
const
|
|
1906
|
-
if
|
|
1907
|
-
|
|
1908
|
-
|
|
1945
|
+
hasRole(role) {
|
|
1946
|
+
const roles = this.state.get('auth.roles') || [];
|
|
1947
|
+
// Check fallback if single role property is mapped directly
|
|
1948
|
+
const singleRole = this.user()?.role;
|
|
1949
|
+
if (singleRole && Array.isArray(role) && role.includes(singleRole))
|
|
1950
|
+
return true;
|
|
1951
|
+
if (singleRole && !Array.isArray(role) && role === singleRole)
|
|
1952
|
+
return true;
|
|
1953
|
+
if (Array.isArray(role)) {
|
|
1954
|
+
return role.some(r => roles.includes(r));
|
|
1909
1955
|
}
|
|
1910
|
-
return
|
|
1956
|
+
return roles.includes(role);
|
|
1911
1957
|
}
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
* ⚠️ DEMO IMPLEMENTATION — accepts any credentials.
|
|
1916
|
-
* Internally delegates to `_mockLogin()` which fabricates a JWT-shaped
|
|
1917
|
-
* token without contacting any server.
|
|
1918
|
-
*
|
|
1919
|
-
* To use real auth, replace the body of `_mockLogin()` (or this method)
|
|
1920
|
-
* with an actual API call. See FRAMEWORK_GUIDE.md §3.
|
|
1921
|
-
*/
|
|
1922
|
-
login(email, password) {
|
|
1923
|
-
// DEMO ONLY — delegates to the client-side mock implementation.
|
|
1924
|
-
// Replace this with a real API call for production use.
|
|
1925
|
-
return this._mockLogin(email, password);
|
|
1958
|
+
hasPermission(permission) {
|
|
1959
|
+
const permissions = this.state.get('auth.permissions') || [];
|
|
1960
|
+
return permissions.includes(permission);
|
|
1926
1961
|
}
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1962
|
+
// ──────────────────────────────────────────────────────────────
|
|
1963
|
+
// Login / Logout
|
|
1964
|
+
// ──────────────────────────────────────────────────────────────
|
|
1965
|
+
async login(credentials, preventRedirect = false) {
|
|
1966
|
+
// DEV MODE MOCK LOGIN
|
|
1967
|
+
if (this.isDevMode && (!this.config || !this.config.loginEndpoint || this.config.mock)) {
|
|
1968
|
+
return this._mockLogin(credentials['email'], credentials['password'], preventRedirect);
|
|
1969
|
+
}
|
|
1970
|
+
if (!this.config?.loginEndpoint) {
|
|
1971
|
+
throw new Error('[AvoraMetaForge] No login endpoint configured. Set loginEndpoint in AppMeta or enable devMode mock auth.');
|
|
1972
|
+
}
|
|
1973
|
+
const response = await this.apiService.call(this.config.loginEndpoint, undefined, credentials);
|
|
1974
|
+
if (response?.token) {
|
|
1975
|
+
this.setToken(response.token, response.refreshToken);
|
|
1976
|
+
}
|
|
1977
|
+
if (response?.user) {
|
|
1978
|
+
this.setUser(response.user);
|
|
1979
|
+
}
|
|
1980
|
+
if (!preventRedirect) {
|
|
1981
|
+
this.handleRedirect();
|
|
1982
|
+
}
|
|
1983
|
+
return response;
|
|
1984
|
+
}
|
|
1985
|
+
async logout() {
|
|
1986
|
+
if (this.config?.logoutEndpoint && !this.isDevMode) {
|
|
1987
|
+
try {
|
|
1988
|
+
await this.apiService.call(this.config.logoutEndpoint);
|
|
1989
|
+
}
|
|
1990
|
+
catch { /* ignore logout errors */ }
|
|
1991
|
+
}
|
|
1992
|
+
const storage = this.getStorage();
|
|
1993
|
+
const tokenKey = this.config?.tokenKey || 'amf_auth_token';
|
|
1994
|
+
const refreshKey = this.config?.refreshTokenKey || 'amf_auth_refresh';
|
|
1995
|
+
storage.removeItem(tokenKey);
|
|
1996
|
+
storage.removeItem(refreshKey);
|
|
1997
|
+
storage.removeItem(`${this.config?.tokenKey || 'amf_auth'}_user`);
|
|
1998
|
+
this.state.clearNamespace('auth');
|
|
1999
|
+
if (this.refreshTimer) {
|
|
2000
|
+
clearTimeout(this.refreshTimer);
|
|
2001
|
+
this.refreshTimer = null;
|
|
2002
|
+
}
|
|
2003
|
+
this.router.navigateByUrl('/login');
|
|
2004
|
+
}
|
|
2005
|
+
_mockLogin(email, _password, preventRedirect = false) {
|
|
2006
|
+
const isStaff = email && email.toLowerCase().includes('staff');
|
|
1937
2007
|
const role = isStaff ? 'STAFF' : 'ADMIN';
|
|
1938
2008
|
const company = isStaff ? 'AvoraMetaForge Support' : 'AvoraMetaForge Inc.';
|
|
1939
|
-
// Create a mock JWT payload (base64-encoded JSON)
|
|
1940
2009
|
const payload = {
|
|
1941
2010
|
sub: isStaff ? 'user-002' : 'user-001',
|
|
1942
|
-
email,
|
|
1943
|
-
name: email.split('@')[0].replace(/[^a-zA-Z]/g, ' ').replace(/\b\w/g, c => c.toUpperCase()),
|
|
2011
|
+
email: email || 'demo@example.com',
|
|
2012
|
+
name: (email || 'demo').split('@')[0].replace(/[^a-zA-Z]/g, ' ').replace(/\b\w/g, c => c.toUpperCase()),
|
|
1944
2013
|
role,
|
|
1945
2014
|
company,
|
|
1946
2015
|
iat: Date.now(),
|
|
1947
|
-
exp: Date.now() + 24 * 60 * 60 * 1000,
|
|
2016
|
+
exp: Date.now() + 24 * 60 * 60 * 1000,
|
|
1948
2017
|
};
|
|
1949
|
-
// ⚠️ This is NOT a real signed JWT — it is a demo token for UI testing only.
|
|
1950
2018
|
const token = `mock.${btoa(JSON.stringify(payload))}.demo-signature`;
|
|
1951
2019
|
const profile = {
|
|
1952
2020
|
id: payload.sub,
|
|
1953
2021
|
name: payload.name,
|
|
1954
2022
|
email: payload.email,
|
|
1955
2023
|
avatar: '',
|
|
2024
|
+
roles: [payload.role],
|
|
1956
2025
|
role: payload.role,
|
|
1957
2026
|
company: payload.company,
|
|
1958
2027
|
};
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
const redirect = localStorage.getItem(this.REDIRECT_KEY) || '/dashboard';
|
|
1964
|
-
localStorage.removeItem(this.REDIRECT_KEY);
|
|
1965
|
-
this.router.navigateByUrl(redirect);
|
|
1966
|
-
return true;
|
|
1967
|
-
}
|
|
1968
|
-
/** Clear session and navigate to login */
|
|
1969
|
-
logout() {
|
|
1970
|
-
localStorage.removeItem(this.TOKEN_KEY);
|
|
1971
|
-
localStorage.removeItem(this.USER_KEY);
|
|
1972
|
-
this._user.set(null);
|
|
1973
|
-
this.router.navigateByUrl('/login');
|
|
1974
|
-
}
|
|
1975
|
-
/** Get the raw token string */
|
|
1976
|
-
getToken() {
|
|
1977
|
-
return localStorage.getItem(this.TOKEN_KEY);
|
|
1978
|
-
}
|
|
1979
|
-
/** Get the current user profile */
|
|
1980
|
-
getUserProfile() {
|
|
1981
|
-
return this._user();
|
|
1982
|
-
}
|
|
1983
|
-
/** Check if the current user has a specific role */
|
|
1984
|
-
hasRole(role) {
|
|
1985
|
-
const user = this._user();
|
|
1986
|
-
if (!user)
|
|
1987
|
-
return false;
|
|
1988
|
-
if (Array.isArray(role)) {
|
|
1989
|
-
return role.includes(user.role);
|
|
2028
|
+
this.setToken(token);
|
|
2029
|
+
this.setUser(profile);
|
|
2030
|
+
if (!preventRedirect) {
|
|
2031
|
+
this.handleRedirect();
|
|
1990
2032
|
}
|
|
1991
|
-
return user
|
|
2033
|
+
return { token, user: profile };
|
|
1992
2034
|
}
|
|
1993
|
-
|
|
2035
|
+
// ──────────────────────────────────────────────────────────────
|
|
2036
|
+
// Navigation & Expiry
|
|
2037
|
+
// ──────────────────────────────────────────────────────────────
|
|
1994
2038
|
storeRedirectUrl(url) {
|
|
1995
2039
|
localStorage.setItem(this.REDIRECT_KEY, url);
|
|
1996
2040
|
}
|
|
1997
|
-
|
|
2041
|
+
handleRedirect() {
|
|
2042
|
+
const redirect = localStorage.getItem(this.REDIRECT_KEY) || '/dashboard';
|
|
2043
|
+
localStorage.removeItem(this.REDIRECT_KEY);
|
|
2044
|
+
this.router.navigateByUrl(redirect);
|
|
2045
|
+
}
|
|
1998
2046
|
isTokenExpired(token) {
|
|
1999
2047
|
const rawToken = token || this.getToken();
|
|
2000
2048
|
if (!rawToken)
|
|
@@ -2004,19 +2052,75 @@ class AuthService {
|
|
|
2004
2052
|
if (parts.length < 2)
|
|
2005
2053
|
return true;
|
|
2006
2054
|
const payload = JSON.parse(atob(parts[1]));
|
|
2007
|
-
return payload.exp < Date.now();
|
|
2055
|
+
return payload.exp ? payload.exp * 1000 < Date.now() : false;
|
|
2008
2056
|
}
|
|
2009
2057
|
catch {
|
|
2010
2058
|
return true;
|
|
2011
2059
|
}
|
|
2012
2060
|
}
|
|
2013
|
-
|
|
2061
|
+
// ──────────────────────────────────────────────────────────────
|
|
2062
|
+
// Token Refresh
|
|
2063
|
+
// ──────────────────────────────────────────────────────────────
|
|
2064
|
+
async refreshAuthToken() {
|
|
2065
|
+
if (!this.config?.refreshEndpoint)
|
|
2066
|
+
return null;
|
|
2067
|
+
const refreshToken = this.getRefreshToken();
|
|
2068
|
+
if (!refreshToken)
|
|
2069
|
+
return null;
|
|
2070
|
+
try {
|
|
2071
|
+
const response = await this.apiService.call(this.config.refreshEndpoint, undefined, { refreshToken });
|
|
2072
|
+
if (response?.token) {
|
|
2073
|
+
this.setToken(response.token, response.refreshToken || refreshToken);
|
|
2074
|
+
return response.token;
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
catch (error) {
|
|
2078
|
+
console.error('[AvoraMetaForge] Token refresh failed:', error);
|
|
2079
|
+
await this.logout();
|
|
2080
|
+
}
|
|
2081
|
+
return null;
|
|
2082
|
+
}
|
|
2083
|
+
scheduleTokenRefresh() {
|
|
2084
|
+
if (this.refreshTimer)
|
|
2085
|
+
clearTimeout(this.refreshTimer);
|
|
2086
|
+
const token = this.getToken();
|
|
2087
|
+
if (!token)
|
|
2088
|
+
return;
|
|
2089
|
+
try {
|
|
2090
|
+
const payload = JSON.parse(atob(token.split('.')[1]));
|
|
2091
|
+
if (payload.exp) {
|
|
2092
|
+
const expiresIn = payload.exp * 1000 - Date.now();
|
|
2093
|
+
const refreshIn = Math.max(expiresIn - 60000, 5000);
|
|
2094
|
+
this.refreshTimer = setTimeout(() => this.refreshAuthToken(), refreshIn);
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
catch { }
|
|
2098
|
+
}
|
|
2099
|
+
// ──────────────────────────────────────────────────────────────
|
|
2100
|
+
// Storage Helpers
|
|
2101
|
+
// ──────────────────────────────────────────────────────────────
|
|
2102
|
+
getStorage() {
|
|
2103
|
+
switch (this.config?.tokenStorage) {
|
|
2104
|
+
case 'sessionStorage': return sessionStorage;
|
|
2105
|
+
case 'localStorage':
|
|
2106
|
+
default: return localStorage;
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
getStoredToken() {
|
|
2110
|
+
const tokenKey = this.config?.tokenKey || 'amf_auth_token';
|
|
2111
|
+
return this.getFromStorage(tokenKey);
|
|
2112
|
+
}
|
|
2113
|
+
getFromStorage(key) {
|
|
2114
|
+
const storage = this.getStorage();
|
|
2115
|
+
return storage.getItem(key);
|
|
2116
|
+
}
|
|
2117
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2014
2118
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AuthService, providedIn: 'root' });
|
|
2015
2119
|
}
|
|
2016
2120
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AuthService, decorators: [{
|
|
2017
2121
|
type: Injectable,
|
|
2018
2122
|
args: [{ providedIn: 'root' }]
|
|
2019
|
-
}]
|
|
2123
|
+
}] });
|
|
2020
2124
|
|
|
2021
2125
|
/**
|
|
2022
2126
|
* AvoraMetaForge — Plugin Registry Service
|
|
@@ -2279,7 +2383,7 @@ function getAmfRoutes(meta) {
|
|
|
2279
2383
|
if (pages.includes('login')) {
|
|
2280
2384
|
routes.push({
|
|
2281
2385
|
path: 'login',
|
|
2282
|
-
loadComponent: () => import('./avora-labs-meta-forge-login.page-
|
|
2386
|
+
loadComponent: () => import('./avora-labs-meta-forge-login.page-D72_EUGF.mjs').then(m => m.LoginComponent),
|
|
2283
2387
|
data: { layout: 'empty' },
|
|
2284
2388
|
});
|
|
2285
2389
|
}
|
|
@@ -2507,7 +2611,7 @@ class MetaModalHostComponent {
|
|
|
2507
2611
|
</div>
|
|
2508
2612
|
</div>
|
|
2509
2613
|
}
|
|
2510
|
-
`, isInline: true, styles: [".amf-modal-backdrop{position:fixed;inset:0;background:#0009;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);z-index:9999;display:flex;align-items:center;justify-content:center;padding:20px;animation:fadeIn .2s ease-out}.amf-modal-dialog{background:var(--glass-bg, rgba(20,25,40,.9));border:1px solid var(--app-border, rgba(255,255,255,.1));border-radius:16px;box-shadow:0 25px 50px -12px #00000080;width:100%;max-height:90vh;overflow-y:auto;display:flex;flex-direction:column;animation:slideUp .3s cubic-bezier(.16,1,.3,1)}.size-sm{max-width:400px}.size-md{max-width:600px}.size-lg{max-width:800px}.size-full{max-width:95vw;height:95vh}.amf-modal-header{padding:20px 24px;border-bottom:1px solid var(--app-border, rgba(255,255,255,.1));display:flex;justify-content:space-between;align-items:center}.amf-modal-header h3{font-size:1.25rem;margin:0;color:#fff}.amf-modal-close{background:transparent;border:none;color:#94a3b8;font-size:1.5rem;cursor:pointer;line-height:1;padding:0 4px}.amf-modal-close:hover{color:#fff}.amf-modal-content{padding:24px;flex-grow:1;color:#94a3b8}.amf-modal-footer{padding:16px 24px;border-top:1px solid var(--app-border, rgba(255,255,255,.1));display:flex;justify-content:flex-end;gap:12px}.btn-primary{background:linear-gradient(135deg,var(--app-primary, #6366f1),var(--app-accent, #c084fc));color:#fff;padding:10px 20px;border-radius:8px;border:none;cursor:pointer;font-weight:600}.btn-outline{background:transparent;border:1px solid #475569;color:#e2e8f0;padding:10px 20px;border-radius:8px;cursor:pointer;font-weight:600}.btn-danger{background:#ef4444;color:#fff;padding:10px 20px;border-radius:8px;border:none;cursor:pointer;font-weight:600}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{opacity:0;transform:translateY(20px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1
|
|
2614
|
+
`, isInline: true, styles: [".amf-modal-backdrop{position:fixed;inset:0;background:#0009;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);z-index:9999;display:flex;align-items:center;justify-content:center;padding:20px;animation:fadeIn .2s ease-out}.amf-modal-dialog{background:var(--glass-bg, rgba(20,25,40,.9));border:1px solid var(--app-border, rgba(255,255,255,.1));border-radius:16px;box-shadow:0 25px 50px -12px #00000080;width:100%;max-height:90vh;overflow-y:auto;display:flex;flex-direction:column;animation:slideUp .3s cubic-bezier(.16,1,.3,1)}.size-sm{max-width:400px}.size-md{max-width:600px}.size-lg{max-width:800px}.size-full{max-width:95vw;height:95vh}.amf-modal-header{padding:20px 24px;border-bottom:1px solid var(--app-border, rgba(255,255,255,.1));display:flex;justify-content:space-between;align-items:center}.amf-modal-header h3{font-size:1.25rem;margin:0;color:#fff}.amf-modal-close{background:transparent;border:none;color:#94a3b8;font-size:1.5rem;cursor:pointer;line-height:1;padding:0 4px}.amf-modal-close:hover{color:#fff}.amf-modal-content{padding:24px;flex-grow:1;color:#94a3b8}.amf-modal-footer{padding:16px 24px;border-top:1px solid var(--app-border, rgba(255,255,255,.1));display:flex;justify-content:flex-end;gap:12px}.btn-primary{background:linear-gradient(135deg,var(--app-primary, #6366f1),var(--app-accent, #c084fc));color:#fff;padding:10px 20px;border-radius:8px;border:none;cursor:pointer;font-weight:600}.btn-outline{background:transparent;border:1px solid #475569;color:#e2e8f0;padding:10px 20px;border-radius:8px;cursor:pointer;font-weight:600}.btn-danger{background:#ef4444;color:#fff;padding:10px 20px;border-radius:8px;border:none;cursor:pointer;font-weight:600}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{opacity:0;transform:translateY(20px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MetaRendererComponent, selector: "amf-renderer", inputs: ["section", "context"] }] });
|
|
2511
2615
|
}
|
|
2512
2616
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaModalHostComponent, decorators: [{
|
|
2513
2617
|
type: Component,
|
|
@@ -2674,7 +2778,7 @@ class AmfDialogHostComponent {
|
|
|
2674
2778
|
</div>
|
|
2675
2779
|
</div>
|
|
2676
2780
|
}
|
|
2677
|
-
`, isInline: true, styles: [".amf-dialog-backdrop{position:fixed;inset:0;background:#0a0f1ebf;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);z-index:10000;display:flex;align-items:center;justify-content:center;padding:20px;animation:fadeIn .25s ease-out}.amf-dialog-box{background:var(--glass-bg, rgba(20,25,40,.9));border:1px solid var(--app-border, rgba(255,255,255,.1));border-radius:20px;box-shadow:0 25px 50px -12px #0009,0 0 0 1px #ffffff0d inset;width:100%;max-width:420px;display:flex;flex-direction:column;animation:popIn .3s cubic-bezier(.16,1,.3,1);overflow:hidden}.dialog-header{padding:32px 32px 16px;display:flex;flex-direction:column;align-items:center;text-align:center;gap:16px}.dialog-icon-wrapper{width:64px;height:64px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:32px;color:#fff;box-shadow:0 8px 16px -4px #0000004d}.dialog-icon-wrapper.variant-info{background:linear-gradient(135deg,#3b82f6,#2563eb);box-shadow:0 8px 24px -6px #3b82f680}.dialog-icon-wrapper.variant-success{background:linear-gradient(135deg,#10b981,#059669);box-shadow:0 8px 24px -6px #10b98180}.dialog-icon-wrapper.variant-warning{background:linear-gradient(135deg,#f59e0b,#d97706);box-shadow:0 8px 24px -6px #f59e0b80}.dialog-icon-wrapper.variant-danger{background:linear-gradient(135deg,#ef4444,#dc2626);box-shadow:0 8px 24px -6px #ef444480}.icon-element{width:32px;height:32px;display:block;filter:drop-shadow(0 2px 2px rgba(0,0,0,.2))}.icon-fallback{font-family:monospace;font-weight:700}.dialog-title{margin:0;color:var(--app-text, #ffffff);font-size:1.25rem;font-weight:700;letter-spacing:-.02em}.dialog-content{padding:0 32px 32px;text-align:center}.dialog-message{margin:0;color:var(--app-text-muted, #94a3b8);font-size:.95rem;line-height:1.5}.dialog-actions{display:flex;gap:12px;padding:24px 32px;background:#0003;border-top:1px solid var(--app-border, rgba(255,255,255,.05))}.btn{flex:1;padding:12px 20px;border-radius:12px;font-size:.9rem;font-weight:600;cursor:pointer;transition:all .2s;border:none;display:inline-flex;align-items:center;justify-content:center}.btn-cancel{background:#ffffff0d;color:var(--app-text, #ffffff);border:1px solid rgba(255,255,255,.1)}.btn-cancel:hover{background:#ffffff1a}.btn-confirm{color:#fff;box-shadow:0 4px 12px transparent}.btn-confirm:hover{transform:translateY(-1px)}.btn-variant-info{background:#3b82f6;box-shadow:0 4px 12px #3b82f64d}.btn-variant-info:hover{background:#60a5fa;box-shadow:0 6px 16px #3b82f666}.btn-variant-success{background:#10b981;box-shadow:0 4px 12px #10b9814d}.btn-variant-success:hover{background:#34d399;box-shadow:0 6px 16px #10b98166}.btn-variant-warning{background:#f59e0b;box-shadow:0 4px 12px #f59e0b4d}.btn-variant-warning:hover{background:#fbbf24;box-shadow:0 6px 16px #f59e0b66}.btn-variant-danger{background:#ef4444;box-shadow:0 4px 12px #ef44444d}.btn-variant-danger:hover{background:#f87171;box-shadow:0 6px 16px #ef444466}@keyframes fadeIn{0%{opacity:0;-webkit-backdrop-filter:blur(0px);backdrop-filter:blur(0px)}to{opacity:1;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}}@keyframes popIn{0%{opacity:0;transform:scale(.9) translateY(10px)}to{opacity:1;transform:scale(1) translateY(0)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1
|
|
2781
|
+
`, isInline: true, styles: [".amf-dialog-backdrop{position:fixed;inset:0;background:#0a0f1ebf;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);z-index:10000;display:flex;align-items:center;justify-content:center;padding:20px;animation:fadeIn .25s ease-out}.amf-dialog-box{background:var(--glass-bg, rgba(20,25,40,.9));border:1px solid var(--app-border, rgba(255,255,255,.1));border-radius:20px;box-shadow:0 25px 50px -12px #0009,0 0 0 1px #ffffff0d inset;width:100%;max-width:420px;display:flex;flex-direction:column;animation:popIn .3s cubic-bezier(.16,1,.3,1);overflow:hidden}.dialog-header{padding:32px 32px 16px;display:flex;flex-direction:column;align-items:center;text-align:center;gap:16px}.dialog-icon-wrapper{width:64px;height:64px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:32px;color:#fff;box-shadow:0 8px 16px -4px #0000004d}.dialog-icon-wrapper.variant-info{background:linear-gradient(135deg,#3b82f6,#2563eb);box-shadow:0 8px 24px -6px #3b82f680}.dialog-icon-wrapper.variant-success{background:linear-gradient(135deg,#10b981,#059669);box-shadow:0 8px 24px -6px #10b98180}.dialog-icon-wrapper.variant-warning{background:linear-gradient(135deg,#f59e0b,#d97706);box-shadow:0 8px 24px -6px #f59e0b80}.dialog-icon-wrapper.variant-danger{background:linear-gradient(135deg,#ef4444,#dc2626);box-shadow:0 8px 24px -6px #ef444480}.icon-element{width:32px;height:32px;display:block;filter:drop-shadow(0 2px 2px rgba(0,0,0,.2))}.icon-fallback{font-family:monospace;font-weight:700}.dialog-title{margin:0;color:var(--app-text, #ffffff);font-size:1.25rem;font-weight:700;letter-spacing:-.02em}.dialog-content{padding:0 32px 32px;text-align:center}.dialog-message{margin:0;color:var(--app-text-muted, #94a3b8);font-size:.95rem;line-height:1.5}.dialog-actions{display:flex;gap:12px;padding:24px 32px;background:#0003;border-top:1px solid var(--app-border, rgba(255,255,255,.05))}.btn{flex:1;padding:12px 20px;border-radius:12px;font-size:.9rem;font-weight:600;cursor:pointer;transition:all .2s;border:none;display:inline-flex;align-items:center;justify-content:center}.btn-cancel{background:#ffffff0d;color:var(--app-text, #ffffff);border:1px solid rgba(255,255,255,.1)}.btn-cancel:hover{background:#ffffff1a}.btn-confirm{color:#fff;box-shadow:0 4px 12px transparent}.btn-confirm:hover{transform:translateY(-1px)}.btn-variant-info{background:#3b82f6;box-shadow:0 4px 12px #3b82f64d}.btn-variant-info:hover{background:#60a5fa;box-shadow:0 6px 16px #3b82f666}.btn-variant-success{background:#10b981;box-shadow:0 4px 12px #10b9814d}.btn-variant-success:hover{background:#34d399;box-shadow:0 6px 16px #10b98166}.btn-variant-warning{background:#f59e0b;box-shadow:0 4px 12px #f59e0b4d}.btn-variant-warning:hover{background:#fbbf24;box-shadow:0 6px 16px #f59e0b66}.btn-variant-danger{background:#ef4444;box-shadow:0 4px 12px #ef44444d}.btn-variant-danger:hover{background:#f87171;box-shadow:0 6px 16px #ef444466}@keyframes fadeIn{0%{opacity:0;-webkit-backdrop-filter:blur(0px);backdrop-filter:blur(0px)}to{opacity:1;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}}@keyframes popIn{0%{opacity:0;transform:scale(.9) translateY(10px)}to{opacity:1;transform:scale(1) translateY(0)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
|
|
2678
2782
|
}
|
|
2679
2783
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AmfDialogHostComponent, decorators: [{
|
|
2680
2784
|
type: Component,
|
|
@@ -2823,228 +2927,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
2823
2927
|
`, styles: [".amf-drawer-backdrop{position:fixed;inset:0;background:#0000008c;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1200;animation:fadeIn .25s ease-out}.amf-drawer-panel{position:fixed;top:0;right:0;height:100%;max-width:95vw;background:var(--glass-bg, rgba(15, 20, 40, .97));border-left:1px solid var(--app-border, rgba(255,255,255,.08));box-shadow:-20px 0 60px #00000080;z-index:1201;display:flex;flex-direction:column;transform:translate(100%);transition:transform .35s cubic-bezier(.16,1,.3,1);will-change:transform;overflow:hidden}.amf-drawer-panel.position-left{right:auto;left:0;border-left:none;border-right:1px solid var(--app-border, rgba(255,255,255,.08));transform:translate(-100%)}.amf-drawer-panel.is-open{transform:translate(0)}.amf-drawer-header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid var(--app-border, rgba(255,255,255,.08));flex-shrink:0}.amf-drawer-header h3{margin:0;font-size:1.125rem;font-weight:700;color:var(--app-text, #f1f5f9);letter-spacing:-.01em}.amf-drawer-close{background:#ffffff0f;border:1px solid rgba(255,255,255,.08);color:var(--app-text-muted, #94a3b8);font-size:1.25rem;line-height:1;width:32px;height:32px;border-radius:8px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s;flex-shrink:0}.amf-drawer-close:hover{background:#ffffff1f;color:var(--app-text, #f1f5f9)}.amf-drawer-content{flex:1;overflow-y:auto;padding:24px}.amf-drawer-footer{flex-shrink:0;padding:16px 24px;border-top:1px solid var(--app-border, rgba(255,255,255,.08));display:flex;justify-content:flex-end;gap:12px;background:#00000026}.btn-primary{background:linear-gradient(135deg,var(--app-primary, #6366f1),var(--app-accent, #c084fc));color:#fff;padding:10px 20px;border-radius:8px;border:none;cursor:pointer;font-weight:600;transition:all .2s}.btn-primary:hover{transform:translateY(-1px);box-shadow:0 6px 20px var(--app-glow)}.btn-outline{background:transparent;border:1px solid #475569;color:#e2e8f0;padding:10px 20px;border-radius:8px;cursor:pointer;font-weight:600;transition:all .2s}.btn-outline:hover{background:#ffffff0f}.btn-danger{background:#ef4444;color:#fff;padding:10px 20px;border-radius:8px;border:none;cursor:pointer;font-weight:600}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}\n"] }]
|
|
2824
2928
|
}] });
|
|
2825
2929
|
|
|
2826
|
-
/**
|
|
2827
|
-
* AvoraMetaForge — Meta Auth Service
|
|
2828
|
-
*
|
|
2829
|
-
* Centralized authentication service supporting:
|
|
2830
|
-
* - JWT / OAuth2 / Session / API Key auth strategies
|
|
2831
|
-
* - Token storage (localStorage, sessionStorage, memory)
|
|
2832
|
-
* - Auto token refresh before expiry
|
|
2833
|
-
* - Role and permission resolution
|
|
2834
|
-
* - Login / Logout lifecycle with actions
|
|
2835
|
-
* - Token injection into MetaApiService via MetaStateService
|
|
2836
|
-
*/
|
|
2837
|
-
class MetaAuthService {
|
|
2838
|
-
state = inject(MetaStateService);
|
|
2839
|
-
apiService = inject(MetaApiService);
|
|
2840
|
-
config = null;
|
|
2841
|
-
refreshTimer;
|
|
2842
|
-
// ──────────────────────────────────────────────────────────────
|
|
2843
|
-
// Configuration
|
|
2844
|
-
// ──────────────────────────────────────────────────────────────
|
|
2845
|
-
/** Initialize auth from AppMeta config */
|
|
2846
|
-
configure(authConfig) {
|
|
2847
|
-
this.config = authConfig;
|
|
2848
|
-
// Load persisted token on startup
|
|
2849
|
-
const token = this.getStoredToken();
|
|
2850
|
-
if (token) {
|
|
2851
|
-
this.state.set('auth.token', token);
|
|
2852
|
-
this.state.set('auth.isAuthenticated', true);
|
|
2853
|
-
// Schedule auto-refresh if enabled
|
|
2854
|
-
if (authConfig.autoRefresh) {
|
|
2855
|
-
this.scheduleTokenRefresh();
|
|
2856
|
-
}
|
|
2857
|
-
}
|
|
2858
|
-
// Load persisted user
|
|
2859
|
-
const userRaw = this.getFromStorage(`${authConfig.tokenKey || 'amf_auth'}_user`);
|
|
2860
|
-
if (userRaw) {
|
|
2861
|
-
try {
|
|
2862
|
-
const user = JSON.parse(userRaw);
|
|
2863
|
-
this.state.set('auth.user', user);
|
|
2864
|
-
}
|
|
2865
|
-
catch { /* invalid stored user */ }
|
|
2866
|
-
}
|
|
2867
|
-
}
|
|
2868
|
-
// ──────────────────────────────────────────────────────────────
|
|
2869
|
-
// Token Management
|
|
2870
|
-
// ──────────────────────────────────────────────────────────────
|
|
2871
|
-
/** Store auth token and update state */
|
|
2872
|
-
setToken(token, refreshToken) {
|
|
2873
|
-
const storage = this.getStorage();
|
|
2874
|
-
const tokenKey = this.config?.tokenKey || 'amf_auth_token';
|
|
2875
|
-
storage.setItem(tokenKey, token);
|
|
2876
|
-
this.state.set('auth.token', token);
|
|
2877
|
-
this.state.set('auth.isAuthenticated', true);
|
|
2878
|
-
if (refreshToken) {
|
|
2879
|
-
const refreshKey = this.config?.refreshTokenKey || 'amf_auth_refresh';
|
|
2880
|
-
storage.setItem(refreshKey, refreshToken);
|
|
2881
|
-
this.state.set('auth.refreshToken', refreshToken);
|
|
2882
|
-
}
|
|
2883
|
-
if (this.config?.autoRefresh) {
|
|
2884
|
-
this.scheduleTokenRefresh();
|
|
2885
|
-
}
|
|
2886
|
-
}
|
|
2887
|
-
/** Get current token */
|
|
2888
|
-
getToken() {
|
|
2889
|
-
return this.state.get('auth.token') || this.getStoredToken();
|
|
2890
|
-
}
|
|
2891
|
-
/** Get current refresh token */
|
|
2892
|
-
getRefreshToken() {
|
|
2893
|
-
const refreshKey = this.config?.refreshTokenKey || 'amf_auth_refresh';
|
|
2894
|
-
return this.getFromStorage(refreshKey);
|
|
2895
|
-
}
|
|
2896
|
-
/** Check if user is authenticated */
|
|
2897
|
-
isAuthenticated() {
|
|
2898
|
-
return !!this.getToken();
|
|
2899
|
-
}
|
|
2900
|
-
// ──────────────────────────────────────────────────────────────
|
|
2901
|
-
// User Management
|
|
2902
|
-
// ──────────────────────────────────────────────────────────────
|
|
2903
|
-
/** Set the current user */
|
|
2904
|
-
setUser(user) {
|
|
2905
|
-
this.state.set('auth.user', user);
|
|
2906
|
-
this.state.set('auth.roles', user.roles || []);
|
|
2907
|
-
this.state.set('auth.permissions', user.permissions || []);
|
|
2908
|
-
// Persist user
|
|
2909
|
-
const tokenKey = this.config?.tokenKey || 'amf_auth';
|
|
2910
|
-
const storage = this.getStorage();
|
|
2911
|
-
storage.setItem(`${tokenKey}_user`, JSON.stringify(user));
|
|
2912
|
-
}
|
|
2913
|
-
/** Get current user */
|
|
2914
|
-
getUser() {
|
|
2915
|
-
return this.state.get('auth.user') || null;
|
|
2916
|
-
}
|
|
2917
|
-
/** Check if user has a specific role */
|
|
2918
|
-
hasRole(role) {
|
|
2919
|
-
const roles = this.state.get('auth.roles') || [];
|
|
2920
|
-
return roles.includes(role);
|
|
2921
|
-
}
|
|
2922
|
-
/** Check if user has ANY of the specified roles */
|
|
2923
|
-
hasAnyRole(roles) {
|
|
2924
|
-
const userRoles = this.state.get('auth.roles') || [];
|
|
2925
|
-
return roles.some(r => userRoles.includes(r));
|
|
2926
|
-
}
|
|
2927
|
-
/** Check if user has a specific permission */
|
|
2928
|
-
hasPermission(permission) {
|
|
2929
|
-
const permissions = this.state.get('auth.permissions') || [];
|
|
2930
|
-
return permissions.includes(permission);
|
|
2931
|
-
}
|
|
2932
|
-
/** Check if user has ALL specified permissions */
|
|
2933
|
-
hasAllPermissions(permissions) {
|
|
2934
|
-
const userPerms = this.state.get('auth.permissions') || [];
|
|
2935
|
-
return permissions.every(p => userPerms.includes(p));
|
|
2936
|
-
}
|
|
2937
|
-
// ──────────────────────────────────────────────────────────────
|
|
2938
|
-
// Login / Logout
|
|
2939
|
-
// ──────────────────────────────────────────────────────────────
|
|
2940
|
-
/** Perform login via configured endpoint */
|
|
2941
|
-
async login(credentials) {
|
|
2942
|
-
if (!this.config?.loginEndpoint) {
|
|
2943
|
-
throw new Error('[AvoraMetaForge] No login endpoint configured');
|
|
2944
|
-
}
|
|
2945
|
-
const response = await this.apiService.call(this.config.loginEndpoint, undefined, credentials);
|
|
2946
|
-
// Auto-extract token if response has standard structure
|
|
2947
|
-
if (response?.token) {
|
|
2948
|
-
this.setToken(response.token, response.refreshToken);
|
|
2949
|
-
}
|
|
2950
|
-
if (response?.user) {
|
|
2951
|
-
this.setUser(response.user);
|
|
2952
|
-
}
|
|
2953
|
-
return response;
|
|
2954
|
-
}
|
|
2955
|
-
/** Perform logout */
|
|
2956
|
-
async logout() {
|
|
2957
|
-
// Call logout endpoint if configured
|
|
2958
|
-
if (this.config?.logoutEndpoint) {
|
|
2959
|
-
try {
|
|
2960
|
-
await this.apiService.call(this.config.logoutEndpoint);
|
|
2961
|
-
}
|
|
2962
|
-
catch { /* ignore logout errors */ }
|
|
2963
|
-
}
|
|
2964
|
-
// Clear tokens
|
|
2965
|
-
const storage = this.getStorage();
|
|
2966
|
-
const tokenKey = this.config?.tokenKey || 'amf_auth_token';
|
|
2967
|
-
const refreshKey = this.config?.refreshTokenKey || 'amf_auth_refresh';
|
|
2968
|
-
storage.removeItem(tokenKey);
|
|
2969
|
-
storage.removeItem(refreshKey);
|
|
2970
|
-
storage.removeItem(`${this.config?.tokenKey || 'amf_auth'}_user`);
|
|
2971
|
-
// Clear state
|
|
2972
|
-
this.state.clearNamespace('auth');
|
|
2973
|
-
// Cancel refresh timer
|
|
2974
|
-
if (this.refreshTimer) {
|
|
2975
|
-
clearTimeout(this.refreshTimer);
|
|
2976
|
-
this.refreshTimer = null;
|
|
2977
|
-
}
|
|
2978
|
-
}
|
|
2979
|
-
// ──────────────────────────────────────────────────────────────
|
|
2980
|
-
// Token Refresh
|
|
2981
|
-
// ──────────────────────────────────────────────────────────────
|
|
2982
|
-
/** Refresh the auth token */
|
|
2983
|
-
async refreshAuthToken() {
|
|
2984
|
-
if (!this.config?.refreshEndpoint)
|
|
2985
|
-
return null;
|
|
2986
|
-
const refreshToken = this.getRefreshToken();
|
|
2987
|
-
if (!refreshToken)
|
|
2988
|
-
return null;
|
|
2989
|
-
try {
|
|
2990
|
-
const response = await this.apiService.call(this.config.refreshEndpoint, undefined, { refreshToken });
|
|
2991
|
-
if (response?.token) {
|
|
2992
|
-
this.setToken(response.token, response.refreshToken || refreshToken);
|
|
2993
|
-
return response.token;
|
|
2994
|
-
}
|
|
2995
|
-
}
|
|
2996
|
-
catch (error) {
|
|
2997
|
-
console.error('[AvoraMetaForge] Token refresh failed:', error);
|
|
2998
|
-
await this.logout();
|
|
2999
|
-
}
|
|
3000
|
-
return null;
|
|
3001
|
-
}
|
|
3002
|
-
scheduleTokenRefresh() {
|
|
3003
|
-
if (this.refreshTimer)
|
|
3004
|
-
clearTimeout(this.refreshTimer);
|
|
3005
|
-
const token = this.getToken();
|
|
3006
|
-
if (!token)
|
|
3007
|
-
return;
|
|
3008
|
-
// Try to decode JWT expiry
|
|
3009
|
-
try {
|
|
3010
|
-
const payload = JSON.parse(atob(token.split('.')[1]));
|
|
3011
|
-
if (payload.exp) {
|
|
3012
|
-
const expiresIn = payload.exp * 1000 - Date.now();
|
|
3013
|
-
// Refresh 60 seconds before expiry
|
|
3014
|
-
const refreshIn = Math.max(expiresIn - 60000, 5000);
|
|
3015
|
-
this.refreshTimer = setTimeout(() => this.refreshAuthToken(), refreshIn);
|
|
3016
|
-
}
|
|
3017
|
-
}
|
|
3018
|
-
catch {
|
|
3019
|
-
// Not a JWT or can't decode — skip auto-refresh scheduling
|
|
3020
|
-
}
|
|
3021
|
-
}
|
|
3022
|
-
// ──────────────────────────────────────────────────────────────
|
|
3023
|
-
// Storage Helpers
|
|
3024
|
-
// ──────────────────────────────────────────────────────────────
|
|
3025
|
-
getStorage() {
|
|
3026
|
-
switch (this.config?.tokenStorage) {
|
|
3027
|
-
case 'sessionStorage': return sessionStorage;
|
|
3028
|
-
case 'localStorage':
|
|
3029
|
-
default: return localStorage;
|
|
3030
|
-
}
|
|
3031
|
-
}
|
|
3032
|
-
getStoredToken() {
|
|
3033
|
-
const tokenKey = this.config?.tokenKey || 'amf_auth_token';
|
|
3034
|
-
return this.getFromStorage(tokenKey);
|
|
3035
|
-
}
|
|
3036
|
-
getFromStorage(key) {
|
|
3037
|
-
const storage = this.getStorage();
|
|
3038
|
-
return storage.getItem(key);
|
|
3039
|
-
}
|
|
3040
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaAuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3041
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaAuthService, providedIn: 'root' });
|
|
3042
|
-
}
|
|
3043
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaAuthService, decorators: [{
|
|
3044
|
-
type: Injectable,
|
|
3045
|
-
args: [{ providedIn: 'root' }]
|
|
3046
|
-
}] });
|
|
3047
|
-
|
|
3048
2930
|
/**
|
|
3049
2931
|
* AvoraMetaForge — Validator Factory Service
|
|
3050
2932
|
*/
|
|
@@ -3501,7 +3383,7 @@ class FieldRendererComponent {
|
|
|
3501
3383
|
}
|
|
3502
3384
|
</div>
|
|
3503
3385
|
}
|
|
3504
|
-
`, isInline: true, styles: [".amf-field{display:flex;flex-direction:column;gap:6px}.amf-field.field-disabled{opacity:.5;pointer-events:none}.field-label{font-size:.875rem;font-weight:600;color:var(--app-text)}.required-mark{color:#f43f5e;margin-left:2px}.field-input-wrapper{display:flex;align-items:stretch;position:relative}.field-prefix,.field-suffix{padding:10px 12px;font-size:.875rem;color:var(--app-text-muted);background:var(--glass-bg);border:1px solid var(--app-border);display:flex;align-items:center;justify-content:center;white-space:nowrap;box-sizing:border-box}.field-prefix{border-right:none;border-radius:8px 0 0 8px}.field-suffix{border-left:none;border-radius:0 8px 8px 0}.field-input{flex:1;width:100%;padding:10px 14px;border:1px solid var(--app-border);border-radius:8px;background:var(--glass-bg);color:var(--app-text);font-size:.875rem;font-family:inherit;outline:none;transition:border-color .2s,box-shadow .2s;box-sizing:border-box}.has-prefix .field-input{border-top-left-radius:0;border-bottom-left-radius:0}.has-suffix .field-input{border-top-right-radius:0;border-bottom-right-radius:0}.field-input:focus{border-color:var(--app-primary);box-shadow:0 0 0 3px var(--app-primary-light);z-index:3;position:relative}.field-input::placeholder{color:var(--app-text-muted);opacity:.6}.field-input[readonly]{opacity:.7;cursor:not-allowed}.field-input:disabled{opacity:.5;cursor:not-allowed}.has-error .field-input{border-color:#f43f5e}.has-error .field-input:focus{box-shadow:0 0 0 3px #f43f5e26}.field-select{appearance:none;cursor:pointer;padding-right:36px;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24'%3E%3Cpath fill='%2394a3b8' d='M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6z'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 12px center;color-scheme:dark}.field-select option{background-color:#1e1e2d;color:#fff}:host-context([data-color-scheme=\"light\"]) .field-select{color-scheme:light}:host-context([data-color-scheme=\"light\"]) .field-select option{background-color:#fff;color:#000}.field-textarea{resize:vertical;min-height:80px}.field-checkbox-label,.field-radio-label{display:flex;align-items:center;gap:8px;font-size:.875rem;color:var(--app-text);cursor:pointer}.field-radio-group{display:flex;flex-direction:column;gap:8px}.field-otp-group{display:flex;gap:8px;justify-content:center;width:100%}.otp-digit{width:44px;height:50px;text-align:center;font-size:1.25rem;font-weight:600;padding:0;letter-spacing:0}.field-toggle-label{display:flex;align-items:center;gap:10px;cursor:pointer}.field-toggle-input{display:none}.field-toggle-track{width:44px;height:24px;background:var(--app-border);border-radius:12px;position:relative;transition:background .2s}.field-toggle-input:checked+.field-toggle-track{background:var(--app-primary)}.field-toggle-thumb{position:absolute;top:2px;left:2px;width:20px;height:20px;background:#fff;border-radius:50%;transition:transform .2s}.field-toggle-input:checked+.field-toggle-track .field-toggle-thumb{transform:translate(20px)}.field-toggle-text{font-size:.875rem;color:var(--app-text)}.field-hint{font-size:.75rem;color:var(--app-text-muted)}.field-error{font-size:.75rem;color:#f43f5e;font-weight:500}.field-heading{font-size:1.125rem;margin-top:8px;color:var(--app-text)}.field-divider{border:none;border-top:1px solid var(--app-border);margin:8px 0}.field-button{padding:10px 20px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1);border:none;width:100%}.field-button.btn-primary{background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff}.field-button.btn-primary:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px var(--app-glow)}.field-button.btn-secondary{background:var(--glass-bg);color:var(--app-text);border:1px solid var(--app-border)}.field-button.btn-secondary:hover:not(:disabled){background:var(--glass-bg-hover);border-color:var(--glass-border-light)}.field-button.btn-outline{background:transparent;color:var(--app-text);border:1px solid var(--app-border)}.field-button.btn-outline:hover:not(:disabled){background:var(--glass-bg-hover)}.field-button.btn-success{background:linear-gradient(135deg,#10b981,#34d399);color:#fff}.field-button.btn-success:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px #10b9814d}.field-button.btn-accent{background:linear-gradient(135deg,var(--app-accent),var(--app-primary));color:#fff}.field-button.btn-accent:hover:not(:disabled){transform:translateY(-2px)}.field-button:disabled{opacity:.5;cursor:not-allowed;transform:none}.password-wrapper{position:relative;display:flex;align-items:stretch;width:100%}.password-input{padding-right:44px!important}.pwd-toggle-btn{position:absolute;right:0;top:0;bottom:0;width:42px;display:flex;align-items:center;justify-content:center;background:transparent;border:none;cursor:pointer;color:var(--app-text-muted);border-radius:0 8px 8px 0;transition:color .2s;z-index:2}.pwd-toggle-btn:hover{color:var(--app-primary)}.pwd-toggle-btn svg{width:18px;height:18px}.currency-wrapper{display:flex;align-items:stretch;width:100%}.currency-symbol{padding:10px 12px;font-size:.875rem;font-weight:600;color:var(--app-text-muted);background:var(--glass-bg);border:1px solid var(--app-border);border-right:none;border-radius:8px 0 0 8px;display:flex;align-items:center;white-space:nowrap;box-sizing:border-box}.currency-input{border-top-left-radius:0!important;border-bottom-left-radius:0!important}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$
|
|
3386
|
+
`, isInline: true, styles: [".amf-field{display:flex;flex-direction:column;gap:6px}.amf-field.field-disabled{opacity:.5;pointer-events:none}.field-label{font-size:.875rem;font-weight:600;color:var(--app-text)}.required-mark{color:#f43f5e;margin-left:2px}.field-input-wrapper{display:flex;align-items:stretch;position:relative}.field-prefix,.field-suffix{padding:10px 12px;font-size:.875rem;color:var(--app-text-muted);background:var(--glass-bg);border:1px solid var(--app-border);display:flex;align-items:center;justify-content:center;white-space:nowrap;box-sizing:border-box}.field-prefix{border-right:none;border-radius:8px 0 0 8px}.field-suffix{border-left:none;border-radius:0 8px 8px 0}.field-input{flex:1;width:100%;padding:10px 14px;border:1px solid var(--app-border);border-radius:8px;background:var(--glass-bg);color:var(--app-text);font-size:.875rem;font-family:inherit;outline:none;transition:border-color .2s,box-shadow .2s;box-sizing:border-box}.has-prefix .field-input{border-top-left-radius:0;border-bottom-left-radius:0}.has-suffix .field-input{border-top-right-radius:0;border-bottom-right-radius:0}.field-input:focus{border-color:var(--app-primary);box-shadow:0 0 0 3px var(--app-primary-light);z-index:3;position:relative}.field-input::placeholder{color:var(--app-text-muted);opacity:.6}.field-input[readonly]{opacity:.7;cursor:not-allowed}.field-input:disabled{opacity:.5;cursor:not-allowed}.has-error .field-input{border-color:#f43f5e}.has-error .field-input:focus{box-shadow:0 0 0 3px #f43f5e26}.field-select{appearance:none;cursor:pointer;padding-right:36px;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24'%3E%3Cpath fill='%2394a3b8' d='M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6z'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 12px center;color-scheme:dark}.field-select option{background-color:#1e1e2d;color:#fff}:host-context([data-color-scheme=\"light\"]) .field-select{color-scheme:light}:host-context([data-color-scheme=\"light\"]) .field-select option{background-color:#fff;color:#000}.field-textarea{resize:vertical;min-height:80px}.field-checkbox-label,.field-radio-label{display:flex;align-items:center;gap:8px;font-size:.875rem;color:var(--app-text);cursor:pointer}.field-radio-group{display:flex;flex-direction:column;gap:8px}.field-otp-group{display:flex;gap:8px;justify-content:center;width:100%}.otp-digit{width:44px;height:50px;text-align:center;font-size:1.25rem;font-weight:600;padding:0;letter-spacing:0}.field-toggle-label{display:flex;align-items:center;gap:10px;cursor:pointer}.field-toggle-input{display:none}.field-toggle-track{width:44px;height:24px;background:var(--app-border);border-radius:12px;position:relative;transition:background .2s}.field-toggle-input:checked+.field-toggle-track{background:var(--app-primary)}.field-toggle-thumb{position:absolute;top:2px;left:2px;width:20px;height:20px;background:#fff;border-radius:50%;transition:transform .2s}.field-toggle-input:checked+.field-toggle-track .field-toggle-thumb{transform:translate(20px)}.field-toggle-text{font-size:.875rem;color:var(--app-text)}.field-hint{font-size:.75rem;color:var(--app-text-muted)}.field-error{font-size:.75rem;color:#f43f5e;font-weight:500}.field-heading{font-size:1.125rem;margin-top:8px;color:var(--app-text)}.field-divider{border:none;border-top:1px solid var(--app-border);margin:8px 0}.field-button{padding:10px 20px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1);border:none;width:100%}.field-button.btn-primary{background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff}.field-button.btn-primary:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px var(--app-glow)}.field-button.btn-secondary{background:var(--glass-bg);color:var(--app-text);border:1px solid var(--app-border)}.field-button.btn-secondary:hover:not(:disabled){background:var(--glass-bg-hover);border-color:var(--glass-border-light)}.field-button.btn-outline{background:transparent;color:var(--app-text);border:1px solid var(--app-border)}.field-button.btn-outline:hover:not(:disabled){background:var(--glass-bg-hover)}.field-button.btn-success{background:linear-gradient(135deg,#10b981,#34d399);color:#fff}.field-button.btn-success:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px #10b9814d}.field-button.btn-accent{background:linear-gradient(135deg,var(--app-accent),var(--app-primary));color:#fff}.field-button.btn-accent:hover:not(:disabled){transform:translateY(-2px)}.field-button:disabled{opacity:.5;cursor:not-allowed;transform:none}.password-wrapper{position:relative;display:flex;align-items:stretch;width:100%}.password-input{padding-right:44px!important}.pwd-toggle-btn{position:absolute;right:0;top:0;bottom:0;width:42px;display:flex;align-items:center;justify-content:center;background:transparent;border:none;cursor:pointer;color:var(--app-text-muted);border-radius:0 8px 8px 0;transition:color .2s;z-index:2}.pwd-toggle-btn:hover{color:var(--app-primary)}.pwd-toggle-btn svg{width:18px;height:18px}.currency-wrapper{display:flex;align-items:stretch;width:100%}.currency-symbol{padding:10px 12px;font-size:.875rem;font-weight:600;color:var(--app-text-muted);background:var(--glass-bg);border:1px solid var(--app-border);border-right:none;border-radius:8px 0 0 8px;display:flex;align-items:center;white-space:nowrap;box-sizing:border-box}.currency-input{border-top-left-radius:0!important;border-bottom-left-radius:0!important}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$1.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormArrayDirective, selector: "[formArray]", inputs: ["formArray"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: RepeaterFieldComponent, selector: "amf-repeater-field", inputs: ["field", "formArray", "formDisabled", "actionDispatcher", "context"] }] });
|
|
3505
3387
|
}
|
|
3506
3388
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: FieldRendererComponent, decorators: [{
|
|
3507
3389
|
type: Component,
|
|
@@ -3775,7 +3657,7 @@ class FormRendererComponent {
|
|
|
3775
3657
|
</div>
|
|
3776
3658
|
}
|
|
3777
3659
|
</form>
|
|
3778
|
-
`, isInline: true, styles: [".amf-form{display:flex;flex-direction:column;gap:24px}.amf-form.form-disabled{opacity:.6;pointer-events:none}.amf-form-fields{display:flex;flex-direction:column;gap:20px}.amf-form-fields.layout-grid{display:grid;gap:20px}.amf-form-fields.layout-horizontal{flex-direction:row;flex-wrap:wrap;gap:16px}.amf-form-fields.layout-horizontal>*{flex:1;min-width:200px}.amf-form-fields.layout-inline{flex-direction:row;align-items:flex-end;gap:12px}.amf-form-actions{display:flex;justify-content:flex-end;gap:12px;padding-top:8px;border-top:1px solid var(--app-border)}.btn-primary{background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:var(--app-on-primary, #fff);border:none;padding:10px 24px;border-radius:10px;font-weight:600;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1)}.btn-primary:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px var(--app-glow)}.btn-primary:disabled{opacity:.5;cursor:not-allowed;transform:none}.btn-secondary{background:var(--glass-bg);color:var(--app-text);border:1px solid var(--app-border);padding:10px 24px;border-radius:10px;font-weight:600;cursor:pointer;transition:all .2s}.btn-secondary:hover{background:var(--glass-bg-hover);border-color:var(--glass-border-light)}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$
|
|
3660
|
+
`, isInline: true, styles: [".amf-form{display:flex;flex-direction:column;gap:24px}.amf-form.form-disabled{opacity:.6;pointer-events:none}.amf-form-fields{display:flex;flex-direction:column;gap:20px}.amf-form-fields.layout-grid{display:grid;gap:20px}.amf-form-fields.layout-horizontal{flex-direction:row;flex-wrap:wrap;gap:16px}.amf-form-fields.layout-horizontal>*{flex:1;min-width:200px}.amf-form-fields.layout-inline{flex-direction:row;align-items:flex-end;gap:12px}.amf-form-actions{display:flex;justify-content:flex-end;gap:12px;padding-top:8px;border-top:1px solid var(--app-border)}.btn-primary{background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:var(--app-on-primary, #fff);border:none;padding:10px 24px;border-radius:10px;font-weight:600;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1)}.btn-primary:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px var(--app-glow)}.btn-primary:disabled{opacity:.5;cursor:not-allowed;transform:none}.btn-secondary{background:var(--glass-bg);color:var(--app-text);border:1px solid var(--app-border);padding:10px 24px;border-radius:10px;font-weight:600;cursor:pointer;transition:all .2s}.btn-secondary:hover{background:var(--glass-bg-hover);border-color:var(--glass-border-light)}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FieldRendererComponent, selector: "amf-field-renderer", inputs: ["field", "form", "formDisabled", "actionDispatcher", "context"] }] });
|
|
3779
3661
|
}
|
|
3780
3662
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: FormRendererComponent, decorators: [{
|
|
3781
3663
|
type: Component,
|
|
@@ -4150,7 +4032,7 @@ class StepperFormRendererComponent {
|
|
|
4150
4032
|
</div>
|
|
4151
4033
|
</form>
|
|
4152
4034
|
</div>
|
|
4153
|
-
`, isInline: true, styles: [".amf-stepper{display:flex;flex-direction:column;gap:0}.amf-stepper.stepper-disabled{opacity:.6;pointer-events:none}.stepper-header{display:flex;align-items:flex-start;gap:0;padding:20px 24px 0;overflow-x:auto;scrollbar-width:none}.stepper-header::-webkit-scrollbar{display:none}.step-item{display:flex;align-items:center;flex:1;min-width:0;cursor:default;position:relative}.step-item.navigable{cursor:pointer}.step-item.navigable:hover .step-indicator{border-color:var(--app-primary)}.step-item.navigable:hover .step-title{color:var(--app-text)}.step-indicator{flex-shrink:0;width:36px;height:36px;border-radius:50%;border:2px solid var(--app-border);background:var(--app-surface);display:flex;align-items:center;justify-content:center;transition:all .35s cubic-bezier(.4,0,.2,1);position:relative;z-index:1}.step-item.active .step-indicator{border-color:var(--app-primary);background:var(--app-primary);box-shadow:0 0 0 4px rgba(var(--app-primary-rgb, 99 102 241),.18)}.step-item.completed .step-indicator{border-color:#22c55e;background:#22c55e}.step-item.skipped .step-indicator{border-color:var(--app-text-muted);background:var(--glass-bg)}.step-number{font-size:.8125rem;font-weight:700;color:var(--app-text-muted)}.step-item.active .step-number{color:#fff}.check-icon,.skip-icon{width:18px;height:18px;fill:#fff}.skip-icon{fill:var(--app-text-muted)}.step-label-group{display:flex;flex-direction:column;margin-left:10px;min-width:0;flex-shrink:0}.step-title{font-size:.8125rem;font-weight:600;color:var(--app-text-muted);white-space:nowrap;transition:color .2s}.step-item.active .step-title{color:var(--app-text)}.step-item.completed .step-title{color:var(--app-text-muted)}.step-description{font-size:.6875rem;color:var(--app-text-muted);opacity:.7;white-space:nowrap;margin-top:1px}.step-connector{flex:1;height:2px;background:var(--app-border);margin:0 10px 14px;border-radius:1px;transition:background .4s ease;align-self:center}.step-connector.completed{background:linear-gradient(90deg,#22c55e,var(--app-primary))}.stepper-progress-mobile{display:none;flex-direction:column;gap:8px;padding:16px 24px 0}@media(max-width:640px){.stepper-header{display:none}.stepper-progress-mobile{display:flex}}.progress-label{font-size:.8125rem;font-weight:600;color:var(--app-text)}.progress-bar-track{width:100%;height:6px;background:var(--app-border);border-radius:3px;overflow:hidden}.progress-bar-fill{height:100%;background:linear-gradient(90deg,var(--app-primary),var(--app-accent));border-radius:3px;transition:width .4s cubic-bezier(.4,0,.2,1)}.stepper-form-body{display:flex;flex-direction:column;gap:24px;padding:24px}.step-content{animation:stepFadeIn .3s ease-out}@keyframes stepFadeIn{0%{opacity:0;transform:translate(12px)}to{opacity:1;transform:translate(0)}}.step-fields{display:grid;grid-template-columns:1fr;gap:20px}.step-error-summary{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#f43f5e14;border:1px solid rgba(244,63,94,.25);border-radius:10px;margin-top:8px;animation:stepFadeIn .2s ease-out}.error-summary-icon{width:18px;height:18px;fill:#f43f5e;flex-shrink:0}.step-error-summary span{font-size:.8125rem;color:#f43f5e;font-weight:500}.stepper-actions{display:flex;justify-content:space-between;align-items:center;padding-top:8px;border-top:1px solid var(--app-border)}.stepper-actions-left,.stepper-actions-right{display:flex;gap:10px;align-items:center}.btn-reset{display:flex;align-items:center;gap:6px;background:transparent;color:#ef4444;border:1px solid rgba(239,68,68,.3);padding:10px 20px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .2s}.btn-reset svg{width:16px;height:16px;fill:currentColor}.btn-reset:hover{background:#ef44441a;border-color:#ef444480}.btn-reset:disabled{opacity:.5;cursor:not-allowed}.btn-back{display:flex;align-items:center;gap:6px;background:var(--glass-bg);color:var(--app-text);border:1px solid var(--app-border);padding:10px 20px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .2s}.btn-back svg{width:16px;height:16px;fill:currentColor}.btn-back:hover{background:var(--glass-bg-hover);border-color:var(--glass-border-light)}.btn-back:disabled{opacity:.5;cursor:not-allowed}.btn-skip{background:transparent;color:var(--app-text-muted);border:none;padding:10px 16px;border-radius:10px;font-weight:500;font-size:.8125rem;cursor:pointer;transition:color .2s}.btn-skip:hover{color:var(--app-primary)}.btn-skip:disabled{opacity:.5;cursor:not-allowed}.btn-next{display:flex;align-items:center;gap:6px;background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff;border:none;padding:10px 24px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1)}.btn-next svg{width:16px;height:16px;fill:currentColor}.btn-next:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px var(--app-glow)}.btn-next:disabled{opacity:.5;cursor:not-allowed;transform:none}.btn-submit{display:flex;align-items:center;gap:6px;background:linear-gradient(135deg,#22c55e,#16a34a);color:#fff;border:none;padding:10px 28px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1)}.btn-submit svg{width:16px;height:16px;fill:currentColor}.btn-submit:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px #22c55e59}.btn-submit:disabled{opacity:.5;cursor:not-allowed;transform:none}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$
|
|
4035
|
+
`, isInline: true, styles: [".amf-stepper{display:flex;flex-direction:column;gap:0}.amf-stepper.stepper-disabled{opacity:.6;pointer-events:none}.stepper-header{display:flex;align-items:flex-start;gap:0;padding:20px 24px 0;overflow-x:auto;scrollbar-width:none}.stepper-header::-webkit-scrollbar{display:none}.step-item{display:flex;align-items:center;flex:1;min-width:0;cursor:default;position:relative}.step-item.navigable{cursor:pointer}.step-item.navigable:hover .step-indicator{border-color:var(--app-primary)}.step-item.navigable:hover .step-title{color:var(--app-text)}.step-indicator{flex-shrink:0;width:36px;height:36px;border-radius:50%;border:2px solid var(--app-border);background:var(--app-surface);display:flex;align-items:center;justify-content:center;transition:all .35s cubic-bezier(.4,0,.2,1);position:relative;z-index:1}.step-item.active .step-indicator{border-color:var(--app-primary);background:var(--app-primary);box-shadow:0 0 0 4px rgba(var(--app-primary-rgb, 99 102 241),.18)}.step-item.completed .step-indicator{border-color:#22c55e;background:#22c55e}.step-item.skipped .step-indicator{border-color:var(--app-text-muted);background:var(--glass-bg)}.step-number{font-size:.8125rem;font-weight:700;color:var(--app-text-muted)}.step-item.active .step-number{color:#fff}.check-icon,.skip-icon{width:18px;height:18px;fill:#fff}.skip-icon{fill:var(--app-text-muted)}.step-label-group{display:flex;flex-direction:column;margin-left:10px;min-width:0;flex-shrink:0}.step-title{font-size:.8125rem;font-weight:600;color:var(--app-text-muted);white-space:nowrap;transition:color .2s}.step-item.active .step-title{color:var(--app-text)}.step-item.completed .step-title{color:var(--app-text-muted)}.step-description{font-size:.6875rem;color:var(--app-text-muted);opacity:.7;white-space:nowrap;margin-top:1px}.step-connector{flex:1;height:2px;background:var(--app-border);margin:0 10px 14px;border-radius:1px;transition:background .4s ease;align-self:center}.step-connector.completed{background:linear-gradient(90deg,#22c55e,var(--app-primary))}.stepper-progress-mobile{display:none;flex-direction:column;gap:8px;padding:16px 24px 0}@media(max-width:640px){.stepper-header{display:none}.stepper-progress-mobile{display:flex}}.progress-label{font-size:.8125rem;font-weight:600;color:var(--app-text)}.progress-bar-track{width:100%;height:6px;background:var(--app-border);border-radius:3px;overflow:hidden}.progress-bar-fill{height:100%;background:linear-gradient(90deg,var(--app-primary),var(--app-accent));border-radius:3px;transition:width .4s cubic-bezier(.4,0,.2,1)}.stepper-form-body{display:flex;flex-direction:column;gap:24px;padding:24px}.step-content{animation:stepFadeIn .3s ease-out}@keyframes stepFadeIn{0%{opacity:0;transform:translate(12px)}to{opacity:1;transform:translate(0)}}.step-fields{display:grid;grid-template-columns:1fr;gap:20px}.step-error-summary{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#f43f5e14;border:1px solid rgba(244,63,94,.25);border-radius:10px;margin-top:8px;animation:stepFadeIn .2s ease-out}.error-summary-icon{width:18px;height:18px;fill:#f43f5e;flex-shrink:0}.step-error-summary span{font-size:.8125rem;color:#f43f5e;font-weight:500}.stepper-actions{display:flex;justify-content:space-between;align-items:center;padding-top:8px;border-top:1px solid var(--app-border)}.stepper-actions-left,.stepper-actions-right{display:flex;gap:10px;align-items:center}.btn-reset{display:flex;align-items:center;gap:6px;background:transparent;color:#ef4444;border:1px solid rgba(239,68,68,.3);padding:10px 20px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .2s}.btn-reset svg{width:16px;height:16px;fill:currentColor}.btn-reset:hover{background:#ef44441a;border-color:#ef444480}.btn-reset:disabled{opacity:.5;cursor:not-allowed}.btn-back{display:flex;align-items:center;gap:6px;background:var(--glass-bg);color:var(--app-text);border:1px solid var(--app-border);padding:10px 20px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .2s}.btn-back svg{width:16px;height:16px;fill:currentColor}.btn-back:hover{background:var(--glass-bg-hover);border-color:var(--glass-border-light)}.btn-back:disabled{opacity:.5;cursor:not-allowed}.btn-skip{background:transparent;color:var(--app-text-muted);border:none;padding:10px 16px;border-radius:10px;font-weight:500;font-size:.8125rem;cursor:pointer;transition:color .2s}.btn-skip:hover{color:var(--app-primary)}.btn-skip:disabled{opacity:.5;cursor:not-allowed}.btn-next{display:flex;align-items:center;gap:6px;background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff;border:none;padding:10px 24px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1)}.btn-next svg{width:16px;height:16px;fill:currentColor}.btn-next:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px var(--app-glow)}.btn-next:disabled{opacity:.5;cursor:not-allowed;transform:none}.btn-submit{display:flex;align-items:center;gap:6px;background:linear-gradient(135deg,#22c55e,#16a34a);color:#fff;border:none;padding:10px 28px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1)}.btn-submit svg{width:16px;height:16px;fill:currentColor}.btn-submit:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px #22c55e59}.btn-submit:disabled{opacity:.5;cursor:not-allowed;transform:none}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FieldRendererComponent, selector: "amf-field-renderer", inputs: ["field", "form", "formDisabled", "actionDispatcher", "context"] }] });
|
|
4154
4036
|
}
|
|
4155
4037
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: StepperFormRendererComponent, decorators: [{
|
|
4156
4038
|
type: Component,
|
|
@@ -4313,7 +4195,7 @@ class CellRendererComponent {
|
|
|
4313
4195
|
}
|
|
4314
4196
|
@default { <span>{{ value }}</span> }
|
|
4315
4197
|
}
|
|
4316
|
-
`, isInline: true, styles: [":host{display:contents}.cell-badge{padding:4px 10px;border-radius:6px;font-size:.75rem;font-weight:600;display:inline-block}.cell-badge.success,.cell-badge.active{background:#34d39926;color:#34d399}.cell-badge.danger,.cell-badge.inactive{background:#f43f5e26;color:#fb7185}.cell-badge.warning,.cell-badge.pending{background:#fbbf2426;color:#fbbf24}.cell-badge.info{background:#3b82f626;color:#60a5fa}.cell-badge.muted{background:var(--glass-bg);color:var(--app-text-muted)}.cell-avatar{display:flex;align-items:center;gap:12px}.avatar-circle{width:34px;height:34px;border-radius:50%;background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:.875rem;flex-shrink:0}.avatar-info{display:flex;flex-direction:column}.avatar-name{font-weight:600;color:var(--app-text);font-size:.875rem}.avatar-subtitle{font-size:.75rem;color:var(--app-text-muted)}.cell-boolean{font-weight:700}.cell-boolean.is-true{color:#34d399}.cell-boolean:not(.is-true){color:#fb7185}.cell-number{font-variant-numeric:tabular-nums}.cell-progress{display:flex;align-items:center;gap:8px}.progress-bar{flex:1;height:6px;background:var(--glass-bg);border-radius:3px;overflow:hidden}.progress-fill{height:100%;background:linear-gradient(90deg,var(--app-primary),var(--app-accent));border-radius:3px;transition:width .3s}.progress-text{font-size:.75rem;color:var(--app-text-muted);min-width:36px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1
|
|
4198
|
+
`, isInline: true, styles: [":host{display:contents}.cell-badge{padding:4px 10px;border-radius:6px;font-size:.75rem;font-weight:600;display:inline-block}.cell-badge.success,.cell-badge.active{background:#34d39926;color:#34d399}.cell-badge.danger,.cell-badge.inactive{background:#f43f5e26;color:#fb7185}.cell-badge.warning,.cell-badge.pending{background:#fbbf2426;color:#fbbf24}.cell-badge.info{background:#3b82f626;color:#60a5fa}.cell-badge.muted{background:var(--glass-bg);color:var(--app-text-muted)}.cell-avatar{display:flex;align-items:center;gap:12px}.avatar-circle{width:34px;height:34px;border-radius:50%;background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:.875rem;flex-shrink:0}.avatar-info{display:flex;flex-direction:column}.avatar-name{font-weight:600;color:var(--app-text);font-size:.875rem}.avatar-subtitle{font-size:.75rem;color:var(--app-text-muted)}.cell-boolean{font-weight:700}.cell-boolean.is-true{color:#34d399}.cell-boolean:not(.is-true){color:#fb7185}.cell-number{font-variant-numeric:tabular-nums}.cell-progress{display:flex;align-items:center;gap:8px}.progress-bar{flex:1;height:6px;background:var(--glass-bg);border-radius:3px;overflow:hidden}.progress-fill{height:100%;background:linear-gradient(90deg,var(--app-primary),var(--app-accent));border-radius:3px;transition:width .3s}.progress-text{font-size:.75rem;color:var(--app-text-muted);min-width:36px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.TitleCasePipe, name: "titlecase" }, { kind: "pipe", type: i1.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i1.DatePipe, name: "date" }] });
|
|
4317
4199
|
}
|
|
4318
4200
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: CellRendererComponent, decorators: [{
|
|
4319
4201
|
type: Component,
|
|
@@ -4976,7 +4858,7 @@ class TableRendererComponent {
|
|
|
4976
4858
|
</div>
|
|
4977
4859
|
}
|
|
4978
4860
|
</div>
|
|
4979
|
-
`, isInline: true, styles: [".amf-table-card{background:var(--app-surface);border:1px solid var(--app-border);border-radius:16px;overflow:hidden;box-shadow:0 1px 3px #0000000d}.table-header{padding:16px 20px;display:flex;justify-content:space-between;align-items:center;gap:16px;border-bottom:1px solid var(--app-border);flex-wrap:wrap}.table-header-left,.table-header-right{display:flex;align-items:center;gap:12px}.search-box{position:relative;min-width:240px}.search-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);width:16px;height:16px;fill:var(--app-text-muted)}.search-box input{width:100%;padding:8px 12px 8px 36px;border:1px solid var(--app-border);border-radius:8px;font-size:.8125rem;outline:none;background:var(--glass-bg);color:var(--app-text)}.search-box input:focus{border-color:var(--app-primary)}.filter-select{padding:8px 12px;border:1px solid var(--app-border);border-radius:8px;font-size:.8125rem;outline:none;background:var(--glass-bg);color:var(--app-text);color-scheme:dark}.filter-select option{background-color:#1e1e2d;color:#fff}:host-context([data-color-scheme=\"light\"]) .filter-select{color-scheme:light}:host-context([data-color-scheme=\"light\"]) .filter-select option{background-color:#fff;color:#000}.table-wrapper{width:100%;overflow-x:auto}.data-table{width:100%;border-collapse:collapse;white-space:normal;word-break:break-word}.data-table th{background:var(--app-bg);padding:10px 20px;font-size:.6875rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--app-text-muted);border-bottom:1px solid var(--app-border);-webkit-user-select:none;user-select:none}.data-table th.sortable{cursor:pointer}.data-table th.sortable:hover{color:var(--app-primary)}.sort-indicator{margin-left:4px;font-size:.75rem}.data-table td{padding:14px 20px;border-bottom:1px solid var(--app-border);font-size:.875rem;color:var(--app-text)}.data-table.hoverable tbody tr:hover{background:var(--glass-bg)}.data-table.striped tbody tr:nth-child(2n){background:var(--glass-bg)}.variant-striped .data-table tbody tr:nth-child(2n){background:var(--glass-bg)}.variant-borderless{border:none!important;box-shadow:none!important;background:transparent!important}.variant-borderless .table-header{border-bottom:none;padding:0 0 16px}.variant-borderless .data-table th{background:transparent;border-bottom:2px solid var(--app-border)}.variant-borderless .data-table td{border-bottom:1px dashed var(--app-border)}.variant-borderless .table-footer{border-top:none;background:transparent;padding:16px 0 0}.variant-glass{background:var(--glass-bg);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur));border:1px solid var(--glass-border);box-shadow:var(--glass-shadow-sm)}.variant-glass .table-header,.variant-glass .table-footer,.variant-glass .data-table th{background:transparent;border-color:var(--glass-border)}.variant-glass .data-table td{border-bottom:1px solid var(--glass-border)}.variant-elevated{box-shadow:0 20px 40px var(--glass-shadow);transform:translateY(-2px);transition:all .3s ease}.variant-compact .table-header{padding:12px 16px}.variant-compact .data-table th{padding:8px 16px;font-size:.625rem}.variant-compact .data-table td{padding:8px 16px;font-size:.8125rem}.variant-compact .table-footer{padding:8px 16px}tr.clickable{cursor:pointer}.amf-checkbox{width:16px;height:16px;cursor:pointer;accent-color:var(--app-primary)}.data-table tbody tr.selected{background:#3b82f626!important}.actions-col{text-align:right!important;width:120px}.actions-cell{text-align:right}.action-btns{display:flex;justify-content:flex-end;gap:6px}.action-btn{width:30px;height:30px;border-radius:6px;border:1px solid var(--app-border);background:transparent;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s}.action-btn svg{width:14px;height:14px;fill:var(--app-text-muted)}.action-btn:hover{border-color:var(--app-primary)}.action-btn:hover svg{fill:var(--app-primary)}.action-btn.danger:hover{border-color:#f43f5e}.action-btn.danger:hover svg{fill:#f43f5e}.btn-primary{background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff;border:none;padding:8px 16px;border-radius:8px;font-weight:600;font-size:.8125rem;cursor:pointer;display:flex;align-items:center;gap:6px;transition:all .2s}.btn-primary:hover{transform:translateY(-1px);box-shadow:0 4px 12px var(--app-glow)}.btn-icon{width:16px;height:16px;fill:currentColor}.btn-sm{padding:6px 12px;font-size:.75rem;border-radius:6px}.btn-ghost{background:transparent;border:1px solid var(--app-border);color:var(--app-text);padding:8px 16px;border-radius:8px;font-weight:600;font-size:.8125rem;display:flex;align-items:center;gap:6px;cursor:pointer;transition:all .2s}.btn-ghost:hover{background:var(--glass-bg-hover);color:var(--app-primary)}.export-container{position:relative}.export-menu{position:absolute;top:calc(100% + 8px);right:0;background:var(--app-surface);border:1px solid var(--app-border);border-radius:12px;box-shadow:0 10px 40px #00000080;min-width:160px;z-index:100;overflow:hidden;animation:slideInDown .2s ease-out backwards}.export-menu .dropdown-item{padding:10px 16px;font-size:.8125rem;font-weight:500;cursor:pointer;color:var(--app-text);transition:background .2s}.export-menu .dropdown-item:hover{background:var(--glass-bg-hover);color:var(--app-primary)}.empty-state{text-align:center;padding:40px!important;color:var(--app-text-muted)}.table-footer{padding:12px 20px;display:flex;justify-content:space-between;align-items:center;background:var(--app-bg);border-top:1px solid var(--app-border)}.footer-left{display:flex;align-items:center;gap:16px}.results-count{font-size:.75rem;color:var(--app-text-muted)}.page-size-wrap{display:flex;align-items:center;gap:6px}.page-size-label{font-size:.75rem;color:var(--app-text-muted);white-space:nowrap}.page-size-select{padding:4px 8px;border:1px solid var(--app-border);border-radius:6px;font-size:.75rem;background:var(--glass-bg);color:var(--app-text);outline:none;cursor:pointer;color-scheme:dark}.page-size-select option{background-color:#1a1a2e;color:#fff}:host-context([data-color-scheme=\"light\"]) .page-size-select{color-scheme:light}:host-context([data-color-scheme=\"light\"]) .page-size-select option{background-color:#fff;color:#000}.pagination{display:flex;gap:4px}.btn-page,.btn-page-nav{padding:6px 10px;border:1px solid var(--app-border);background:transparent;border-radius:6px;font-size:.75rem;font-weight:500;color:var(--app-text);cursor:pointer}.btn-page.active{background:var(--app-primary);border-color:var(--app-primary);color:#fff}.btn-page-nav:disabled{opacity:.4;cursor:not-allowed}.editable-cell{position:relative}.editable-cell:hover{background:#3b82f614;cursor:text}.inline-edit-wrap{display:flex;flex-direction:column;gap:4px;min-width:0}.inline-edit-row{display:flex;align-items:center;gap:4px}.inline-input{flex:1;min-width:0;padding:5px 8px;border:1.5px solid var(--app-primary);border-radius:6px;background:var(--app-surface);color:var(--app-text);font-size:.875rem;outline:none}.inline-input.input-invalid{border-color:#f43f5e}.inline-edit-error{font-size:.6875rem;color:#f43f5e;font-weight:500;padding:0 2px;animation:fadeIn .15s ease-out}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.inline-edit-actions{display:flex;gap:3px;flex-shrink:0}.ie-btn{width:26px;height:26px;border-radius:5px;border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:opacity .15s}.ie-btn svg{width:14px;height:14px;fill:currentColor}.ie-btn:hover{opacity:.85}.ie-save{background:#22c55e;color:#fff}.ie-cancel{background:var(--app-border);color:var(--app-text-muted)}select.inline-input{color-scheme:dark;cursor:pointer}select.inline-input option{background-color:#1a1a2e;color:#fff}:host-context([data-color-scheme=\"light\"]) select.inline-input{color-scheme:light}:host-context([data-color-scheme=\"light\"]) select.inline-input option{background-color:#fff;color:#000}.expand-cell{width:36px;text-align:center;cursor:pointer}.expand-chevron{display:inline-block;transition:transform .2s;font-size:.625rem;color:var(--app-text-muted)}.expand-chevron.open{transform:rotate(90deg)}.expanded-row td,.expanded-content{padding:0!important}.expand-section{padding:14px 24px;display:flex;flex-wrap:wrap;gap:16px;background:var(--glass-bg);animation:fadeInUp .2s ease-out}.expand-field{display:flex;gap:8px;font-size:.8125rem}.expand-label{color:var(--app-text-muted);font-weight:600}.group-header-row td{background:var(--app-bg)}.group-toggle{display:flex;align-items:center;gap:8px;background:none;border:none;color:var(--app-text);cursor:pointer;font-size:.8125rem;padding:8px 16px}.group-chevron{display:inline-block;font-size:.625rem;transition:transform .2s;color:var(--app-text-muted)}.group-chevron.open{transform:rotate(90deg)}.group-count{color:var(--app-text-muted);font-size:.75rem}.aggregate-row td{background:var(--app-bg);border-top:2px solid var(--app-border)}.aggregate-cell{padding:10px 20px!important}.agg-value{font-size:.8125rem;font-weight:700;color:var(--app-primary)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i2.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i2.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i2.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: CellRendererComponent, selector: "amf-cell-renderer", inputs: ["column", "row", "value"] }, { kind: "pipe", type: i1$1.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }] });
|
|
4861
|
+
`, isInline: true, styles: [".amf-table-card{background:var(--app-surface);border:1px solid var(--app-border);border-radius:16px;overflow:hidden;box-shadow:0 1px 3px #0000000d}.table-header{padding:16px 20px;display:flex;justify-content:space-between;align-items:center;gap:16px;border-bottom:1px solid var(--app-border);flex-wrap:wrap}.table-header-left,.table-header-right{display:flex;align-items:center;gap:12px}.search-box{position:relative;min-width:240px}.search-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);width:16px;height:16px;fill:var(--app-text-muted)}.search-box input{width:100%;padding:8px 12px 8px 36px;border:1px solid var(--app-border);border-radius:8px;font-size:.8125rem;outline:none;background:var(--glass-bg);color:var(--app-text)}.search-box input:focus{border-color:var(--app-primary)}.filter-select{padding:8px 12px;border:1px solid var(--app-border);border-radius:8px;font-size:.8125rem;outline:none;background:var(--glass-bg);color:var(--app-text);color-scheme:dark}.filter-select option{background-color:#1e1e2d;color:#fff}:host-context([data-color-scheme=\"light\"]) .filter-select{color-scheme:light}:host-context([data-color-scheme=\"light\"]) .filter-select option{background-color:#fff;color:#000}.table-wrapper{width:100%;overflow-x:auto}.data-table{width:100%;border-collapse:collapse;white-space:normal;word-break:break-word}.data-table th{background:var(--app-bg);padding:10px 20px;font-size:.6875rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--app-text-muted);border-bottom:1px solid var(--app-border);-webkit-user-select:none;user-select:none}.data-table th.sortable{cursor:pointer}.data-table th.sortable:hover{color:var(--app-primary)}.sort-indicator{margin-left:4px;font-size:.75rem}.data-table td{padding:14px 20px;border-bottom:1px solid var(--app-border);font-size:.875rem;color:var(--app-text)}.data-table.hoverable tbody tr:hover{background:var(--glass-bg)}.data-table.striped tbody tr:nth-child(2n){background:var(--glass-bg)}.variant-striped .data-table tbody tr:nth-child(2n){background:var(--glass-bg)}.variant-borderless{border:none!important;box-shadow:none!important;background:transparent!important}.variant-borderless .table-header{border-bottom:none;padding:0 0 16px}.variant-borderless .data-table th{background:transparent;border-bottom:2px solid var(--app-border)}.variant-borderless .data-table td{border-bottom:1px dashed var(--app-border)}.variant-borderless .table-footer{border-top:none;background:transparent;padding:16px 0 0}.variant-glass{background:var(--glass-bg);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur));border:1px solid var(--glass-border);box-shadow:var(--glass-shadow-sm)}.variant-glass .table-header,.variant-glass .table-footer,.variant-glass .data-table th{background:transparent;border-color:var(--glass-border)}.variant-glass .data-table td{border-bottom:1px solid var(--glass-border)}.variant-elevated{box-shadow:0 20px 40px var(--glass-shadow);transform:translateY(-2px);transition:all .3s ease}.variant-compact .table-header{padding:12px 16px}.variant-compact .data-table th{padding:8px 16px;font-size:.625rem}.variant-compact .data-table td{padding:8px 16px;font-size:.8125rem}.variant-compact .table-footer{padding:8px 16px}tr.clickable{cursor:pointer}.amf-checkbox{width:16px;height:16px;cursor:pointer;accent-color:var(--app-primary)}.data-table tbody tr.selected{background:#3b82f626!important}.actions-col{text-align:right!important;width:120px}.actions-cell{text-align:right}.action-btns{display:flex;justify-content:flex-end;gap:6px}.action-btn{width:30px;height:30px;border-radius:6px;border:1px solid var(--app-border);background:transparent;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s}.action-btn svg{width:14px;height:14px;fill:var(--app-text-muted)}.action-btn:hover{border-color:var(--app-primary)}.action-btn:hover svg{fill:var(--app-primary)}.action-btn.danger:hover{border-color:#f43f5e}.action-btn.danger:hover svg{fill:#f43f5e}.btn-primary{background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff;border:none;padding:8px 16px;border-radius:8px;font-weight:600;font-size:.8125rem;cursor:pointer;display:flex;align-items:center;gap:6px;transition:all .2s}.btn-primary:hover{transform:translateY(-1px);box-shadow:0 4px 12px var(--app-glow)}.btn-icon{width:16px;height:16px;fill:currentColor}.btn-sm{padding:6px 12px;font-size:.75rem;border-radius:6px}.btn-ghost{background:transparent;border:1px solid var(--app-border);color:var(--app-text);padding:8px 16px;border-radius:8px;font-weight:600;font-size:.8125rem;display:flex;align-items:center;gap:6px;cursor:pointer;transition:all .2s}.btn-ghost:hover{background:var(--glass-bg-hover);color:var(--app-primary)}.export-container{position:relative}.export-menu{position:absolute;top:calc(100% + 8px);right:0;background:var(--app-surface);border:1px solid var(--app-border);border-radius:12px;box-shadow:0 10px 40px #00000080;min-width:160px;z-index:100;overflow:hidden;animation:slideInDown .2s ease-out backwards}.export-menu .dropdown-item{padding:10px 16px;font-size:.8125rem;font-weight:500;cursor:pointer;color:var(--app-text);transition:background .2s}.export-menu .dropdown-item:hover{background:var(--glass-bg-hover);color:var(--app-primary)}.empty-state{text-align:center;padding:40px!important;color:var(--app-text-muted)}.table-footer{padding:12px 20px;display:flex;justify-content:space-between;align-items:center;background:var(--app-bg);border-top:1px solid var(--app-border)}.footer-left{display:flex;align-items:center;gap:16px}.results-count{font-size:.75rem;color:var(--app-text-muted)}.page-size-wrap{display:flex;align-items:center;gap:6px}.page-size-label{font-size:.75rem;color:var(--app-text-muted);white-space:nowrap}.page-size-select{padding:4px 8px;border:1px solid var(--app-border);border-radius:6px;font-size:.75rem;background:var(--glass-bg);color:var(--app-text);outline:none;cursor:pointer;color-scheme:dark}.page-size-select option{background-color:#1a1a2e;color:#fff}:host-context([data-color-scheme=\"light\"]) .page-size-select{color-scheme:light}:host-context([data-color-scheme=\"light\"]) .page-size-select option{background-color:#fff;color:#000}.pagination{display:flex;gap:4px}.btn-page,.btn-page-nav{padding:6px 10px;border:1px solid var(--app-border);background:transparent;border-radius:6px;font-size:.75rem;font-weight:500;color:var(--app-text);cursor:pointer}.btn-page.active{background:var(--app-primary);border-color:var(--app-primary);color:#fff}.btn-page-nav:disabled{opacity:.4;cursor:not-allowed}.editable-cell{position:relative}.editable-cell:hover{background:#3b82f614;cursor:text}.inline-edit-wrap{display:flex;flex-direction:column;gap:4px;min-width:0}.inline-edit-row{display:flex;align-items:center;gap:4px}.inline-input{flex:1;min-width:0;padding:5px 8px;border:1.5px solid var(--app-primary);border-radius:6px;background:var(--app-surface);color:var(--app-text);font-size:.875rem;outline:none}.inline-input.input-invalid{border-color:#f43f5e}.inline-edit-error{font-size:.6875rem;color:#f43f5e;font-weight:500;padding:0 2px;animation:fadeIn .15s ease-out}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.inline-edit-actions{display:flex;gap:3px;flex-shrink:0}.ie-btn{width:26px;height:26px;border-radius:5px;border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:opacity .15s}.ie-btn svg{width:14px;height:14px;fill:currentColor}.ie-btn:hover{opacity:.85}.ie-save{background:#22c55e;color:#fff}.ie-cancel{background:var(--app-border);color:var(--app-text-muted)}select.inline-input{color-scheme:dark;cursor:pointer}select.inline-input option{background-color:#1a1a2e;color:#fff}:host-context([data-color-scheme=\"light\"]) select.inline-input{color-scheme:light}:host-context([data-color-scheme=\"light\"]) select.inline-input option{background-color:#fff;color:#000}.expand-cell{width:36px;text-align:center;cursor:pointer}.expand-chevron{display:inline-block;transition:transform .2s;font-size:.625rem;color:var(--app-text-muted)}.expand-chevron.open{transform:rotate(90deg)}.expanded-row td,.expanded-content{padding:0!important}.expand-section{padding:14px 24px;display:flex;flex-wrap:wrap;gap:16px;background:var(--glass-bg);animation:fadeInUp .2s ease-out}.expand-field{display:flex;gap:8px;font-size:.8125rem}.expand-label{color:var(--app-text-muted);font-weight:600}.group-header-row td{background:var(--app-bg)}.group-toggle{display:flex;align-items:center;gap:8px;background:none;border:none;color:var(--app-text);cursor:pointer;font-size:.8125rem;padding:8px 16px}.group-chevron{display:inline-block;font-size:.625rem;transition:transform .2s;color:var(--app-text-muted)}.group-chevron.open{transform:rotate(90deg)}.group-count{color:var(--app-text-muted);font-size:.75rem}.aggregate-row td{background:var(--app-bg);border-top:2px solid var(--app-border)}.aggregate-cell{padding:10px 20px!important}.agg-value{font-size:.8125rem;font-weight:700;color:var(--app-primary)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i2.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i2.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i2.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: CellRendererComponent, selector: "amf-cell-renderer", inputs: ["column", "row", "value"] }, { kind: "pipe", type: i1.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i1.JsonPipe, name: "json" }] });
|
|
4980
4862
|
}
|
|
4981
4863
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TableRendererComponent, decorators: [{
|
|
4982
4864
|
type: Component,
|
|
@@ -5536,13 +5418,13 @@ class AppConfigService {
|
|
|
5536
5418
|
html.setAttribute('data-color-scheme', 'light');
|
|
5537
5419
|
}
|
|
5538
5420
|
}
|
|
5539
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AppConfigService, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5421
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AppConfigService, deps: [{ token: i1$2.Router }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5540
5422
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AppConfigService, providedIn: 'root' });
|
|
5541
5423
|
}
|
|
5542
5424
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AppConfigService, decorators: [{
|
|
5543
5425
|
type: Injectable,
|
|
5544
5426
|
args: [{ providedIn: 'root' }]
|
|
5545
|
-
}], ctorParameters: () => [{ type: i1.Router }] });
|
|
5427
|
+
}], ctorParameters: () => [{ type: i1$2.Router }] });
|
|
5546
5428
|
|
|
5547
5429
|
/**
|
|
5548
5430
|
* AvoraMetaForge — Provider Initialization
|
|
@@ -5585,9 +5467,9 @@ function initializeAvoraMetaForge(registry, routerService, apiService, stateServ
|
|
|
5585
5467
|
if (config.defaultHeaders) {
|
|
5586
5468
|
apiService.setGlobalHeaders(config.defaultHeaders);
|
|
5587
5469
|
}
|
|
5588
|
-
|
|
5589
|
-
if (
|
|
5590
|
-
authService.configure(
|
|
5470
|
+
const authConfig = config.auth;
|
|
5471
|
+
if (authConfig) {
|
|
5472
|
+
authService.configure(authConfig, authConfig.mock || false);
|
|
5591
5473
|
}
|
|
5592
5474
|
// 6. Register plugins
|
|
5593
5475
|
if (config.plugins?.length) {
|
|
@@ -5650,7 +5532,7 @@ function provideAvoraMetaForge(config) {
|
|
|
5650
5532
|
MetaRouterService,
|
|
5651
5533
|
MetaApiService,
|
|
5652
5534
|
MetaStateService,
|
|
5653
|
-
|
|
5535
|
+
AuthService,
|
|
5654
5536
|
ActionDispatcherService,
|
|
5655
5537
|
ConditionEvaluatorService,
|
|
5656
5538
|
PluginRegistryService,
|
|
@@ -5668,24 +5550,6 @@ function provideAvoraMetaForge(config) {
|
|
|
5668
5550
|
* - Checks if a valid (non-expired) token exists via AuthService.
|
|
5669
5551
|
* - Stores the attempted URL for post-login redirect.
|
|
5670
5552
|
* - Redirects unauthenticated users to /login.
|
|
5671
|
-
*
|
|
5672
|
-
* \u2500\u2500 CURRENT (DEMO) BEHAVIOUR \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
5673
|
-
* Delegates to `AuthService` (the demo/mock auth service).
|
|
5674
|
-
* The token it checks is a locally-generated fake JWT \u2014 no server
|
|
5675
|
-
* validation occurs. The guard correctly protects routes in the demo
|
|
5676
|
-
* but will let any fabricated token through.
|
|
5677
|
-
*
|
|
5678
|
-
* \u2500\u2500 PRODUCTION MIGRATION PATH \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
5679
|
-
* Option A \u2014 Use the framework\u2019s built-in MetaGuard:
|
|
5680
|
-
* Set `guard: { requireAuth: true, redirectTo: '/login' }` on any
|
|
5681
|
-
* PageMeta definition. MetaGuard already reads from MetaAuthService
|
|
5682
|
-
* and handles role/permission checks declaratively.
|
|
5683
|
-
*
|
|
5684
|
-
* Option B \u2014 Keep this guard but swap the auth service:
|
|
5685
|
-
* Replace `inject(AuthService)` with `inject(MetaAuthService)` and
|
|
5686
|
-
* call `.isAuthenticated()` on it once real tokens are in flight.
|
|
5687
|
-
*
|
|
5688
|
-
* See FRAMEWORK_GUIDE.md \u00a73 for step-by-step migration instructions.
|
|
5689
5553
|
*/
|
|
5690
5554
|
const authGuard = (route, state) => {
|
|
5691
5555
|
const authService = inject(AuthService);
|
|
@@ -5700,23 +5564,6 @@ const authGuard = (route, state) => {
|
|
|
5700
5564
|
|
|
5701
5565
|
/**
|
|
5702
5566
|
* HTTP Interceptor — Bearer token injection + 401 global logout.
|
|
5703
|
-
*
|
|
5704
|
-
* ── CURRENT (DEMO) BEHAVIOUR ──────────────────────────────────────────────
|
|
5705
|
-
* Reads the Bearer token from `AuthService` (the demo/mock service).
|
|
5706
|
-
* The token is a fake JWT-shaped string generated locally — it will be
|
|
5707
|
-
* rejected by any real API server that validates JWT signatures.
|
|
5708
|
-
*
|
|
5709
|
-
* ── PRODUCTION MIGRATION PATH ────────────────────────────────────────────
|
|
5710
|
-
* Option A — Swap the token source (minimal change):
|
|
5711
|
-
* Replace `authService.getToken()` with a call to `MetaAuthService.getToken()`
|
|
5712
|
-
* once you have a real login endpoint producing real JWTs.
|
|
5713
|
-
*
|
|
5714
|
-
* Option B — Remove this interceptor entirely:
|
|
5715
|
-
* Use AvoraMetaForge’s built-in auth injection via `ApiEndpointMeta.auth`.
|
|
5716
|
-
* Set `auth: { type: 'bearer', token: 'state:auth.token' }` on each endpoint
|
|
5717
|
-
* and MetaApiService will inject it automatically. No interceptor needed.
|
|
5718
|
-
*
|
|
5719
|
-
* See FRAMEWORK_GUIDE.md §3 for step-by-step instructions.
|
|
5720
5567
|
*/
|
|
5721
5568
|
const authInterceptor = (req, next) => {
|
|
5722
5569
|
const authService = inject(AuthService);
|
|
@@ -5864,7 +5711,7 @@ class SidebarComponent {
|
|
|
5864
5711
|
}
|
|
5865
5712
|
</ng-template>
|
|
5866
5713
|
</div>
|
|
5867
|
-
`, isInline: true, styles: [":host{display:block;height:100%}.sidebar-container{width:var(--sidebar-width, 260px);height:100%;background:var(--app-sidebar-bg);backdrop-filter:blur(var(--glass-blur-heavy));-webkit-backdrop-filter:blur(var(--glass-blur-heavy));border-right:1px solid var(--glass-border);display:flex;flex-direction:column;transition:width var(--transition-smooth);overflow:hidden;position:relative}.sidebar-container:after{content:\"\";position:absolute;top:0;right:0;width:1px;height:100%;background:linear-gradient(to bottom,transparent,var(--app-primary-light),transparent);pointer-events:none}.sidebar-container.collapsed{width:80px}.sidebar-header{height:68px;display:flex;align-items:center;padding:0 20px;border-bottom:1px solid var(--glass-border)}.logo{display:flex;align-items:center;gap:12px;font-weight:700;font-size:1.25rem;color:var(--app-text);white-space:nowrap}.logo-glow{width:38px;height:38px;border-radius:10px;background:linear-gradient(135deg,var(--app-primary),var(--app-accent));display:flex;align-items:center;justify-content:center;box-shadow:0 0 20px var(--app-glow);animation:pulseGlow 4s ease-in-out infinite;flex-shrink:0}.logo-icon{width:20px;height:20px;fill:#fff}.sidebar-container.collapsed .logo-text{display:none}.sidebar-nav{flex:1;overflow-y:auto;padding:16px 0}.nav-group{margin-top:28px}.nav-group:first-child{margin-top:0}.group-title{font-size:.6875rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--app-text-muted);padding:0 24px 8px;opacity:.6}.sidebar-container.collapsed .group-title{display:none}ul{list-style:none;padding:0;margin:0}.nav-item-wrapper{margin-bottom:2px;padding:0 10px}.nav-item{display:flex;align-items:center;justify-content:space-between;height:44px;padding:0 14px;border-radius:10px;color:var(--app-sidebar-text);cursor:pointer;transition:all var(--transition-smooth);text-decoration:none;position:relative}.nav-item:hover{background:var(--glass-bg-hover);color:var(--app-text)}.nav-item.active{background:linear-gradient(135deg,var(--app-primary-light),var(--app-accent-light));color:var(--app-primary);box-shadow:0 0 20px var(--app-glow)}.nav-item.active:before{content:\"\";position:absolute;left:0;top:50%;transform:translateY(-50%);width:3px;height:20px;border-radius:0 3px 3px 0;background:linear-gradient(to bottom,var(--app-primary),var(--app-accent))}.nav-item.active .nav-icon{filter:drop-shadow(0 0 6px var(--app-glow))}.nav-link-content{display:flex;align-items:center;gap:12px}.nav-icon{width:20px;height:20px;fill:currentColor;flex-shrink:0;transition:all var(--transition-fast)}.sidebar-container.collapsed .nav-label,.sidebar-container.collapsed .chevron,.sidebar-container.collapsed .badge{display:none}.chevron{width:16px;height:16px;fill:currentColor;transition:transform var(--transition-smooth);opacity:.5}.chevron.rotated{transform:rotate(90deg)}.badge{font-size:10px;padding:2px 8px;border-radius:10px;color:#fff;font-weight:600;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.sub-menu{padding-left:24px;margin-top:4px;animation:fadeInUp .2s ease-out}.sidebar-container.collapsed .sub-menu{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1
|
|
5714
|
+
`, isInline: true, styles: [":host{display:block;height:100%}.sidebar-container{width:var(--sidebar-width, 260px);height:100%;background:var(--app-sidebar-bg);backdrop-filter:blur(var(--glass-blur-heavy));-webkit-backdrop-filter:blur(var(--glass-blur-heavy));border-right:1px solid var(--glass-border);display:flex;flex-direction:column;transition:width var(--transition-smooth);overflow:hidden;position:relative}.sidebar-container:after{content:\"\";position:absolute;top:0;right:0;width:1px;height:100%;background:linear-gradient(to bottom,transparent,var(--app-primary-light),transparent);pointer-events:none}.sidebar-container.collapsed{width:80px}.sidebar-header{height:68px;display:flex;align-items:center;padding:0 20px;border-bottom:1px solid var(--glass-border)}.logo{display:flex;align-items:center;gap:12px;font-weight:700;font-size:1.25rem;color:var(--app-text);white-space:nowrap}.logo-glow{width:38px;height:38px;border-radius:10px;background:linear-gradient(135deg,var(--app-primary),var(--app-accent));display:flex;align-items:center;justify-content:center;box-shadow:0 0 20px var(--app-glow);animation:pulseGlow 4s ease-in-out infinite;flex-shrink:0}.logo-icon{width:20px;height:20px;fill:#fff}.sidebar-container.collapsed .logo-text{display:none}.sidebar-nav{flex:1;overflow-y:auto;padding:16px 0}.nav-group{margin-top:28px}.nav-group:first-child{margin-top:0}.group-title{font-size:.6875rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--app-text-muted);padding:0 24px 8px;opacity:.6}.sidebar-container.collapsed .group-title{display:none}ul{list-style:none;padding:0;margin:0}.nav-item-wrapper{margin-bottom:2px;padding:0 10px}.nav-item{display:flex;align-items:center;justify-content:space-between;height:44px;padding:0 14px;border-radius:10px;color:var(--app-sidebar-text);cursor:pointer;transition:all var(--transition-smooth);text-decoration:none;position:relative}.nav-item:hover{background:var(--glass-bg-hover);color:var(--app-text)}.nav-item.active{background:linear-gradient(135deg,var(--app-primary-light),var(--app-accent-light));color:var(--app-primary);box-shadow:0 0 20px var(--app-glow)}.nav-item.active:before{content:\"\";position:absolute;left:0;top:50%;transform:translateY(-50%);width:3px;height:20px;border-radius:0 3px 3px 0;background:linear-gradient(to bottom,var(--app-primary),var(--app-accent))}.nav-item.active .nav-icon{filter:drop-shadow(0 0 6px var(--app-glow))}.nav-link-content{display:flex;align-items:center;gap:12px}.nav-icon{width:20px;height:20px;fill:currentColor;flex-shrink:0;transition:all var(--transition-fast)}.sidebar-container.collapsed .nav-label,.sidebar-container.collapsed .chevron,.sidebar-container.collapsed .badge{display:none}.chevron{width:16px;height:16px;fill:currentColor;transition:transform var(--transition-smooth);opacity:.5}.chevron.rotated{transform:rotate(90deg)}.badge{font-size:10px;padding:2px 8px;border-radius:10px;color:#fff;font-weight:600;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.sub-menu{padding-left:24px;margin-top:4px;animation:fadeInUp .2s ease-out}.sidebar-container.collapsed .sub-menu{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] });
|
|
5868
5715
|
}
|
|
5869
5716
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SidebarComponent, decorators: [{
|
|
5870
5717
|
type: Component,
|
|
@@ -6545,5 +6392,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
6545
6392
|
* Generated bundle index. Do not edit.
|
|
6546
6393
|
*/
|
|
6547
6394
|
|
|
6548
|
-
export { APP_META_CONFIG_TOKEN, AccordionSectionComponent, ActionDispatcherService, AmfDialogHostComponent, AmfDrawerHostComponent, AppConfigService, AuthService, CardSectionComponent, ComponentRegistryService, ConditionEvaluatorService, FormRendererComponent, LayoutComponent, LayoutType, META_SECTION_CONFIG, META_SECTION_CONTEXT, MetaApiService,
|
|
6395
|
+
export { APP_META_CONFIG_TOKEN, AccordionSectionComponent, ActionDispatcherService, AmfDialogHostComponent, AmfDrawerHostComponent, AppConfigService, AuthService, CardSectionComponent, ComponentRegistryService, ConditionEvaluatorService, FormRendererComponent, LayoutComponent, LayoutType, META_SECTION_CONFIG, META_SECTION_CONTEXT, MetaApiService, MetaModalHostComponent, MetaPageComponent, MetaRendererComponent, MetaRouterService, MetaStateService, NotificationService, PageHeaderSectionComponent, PluginRegistryService, RepeaterFieldComponent, StatsGridSectionComponent, StepperFormRendererComponent, TableRendererComponent, ThemeService, authGuard, authInterceptor, getAmfRoutes, initializeAvoraMetaForge, metaCanDeactivateGuard, metaGuard, provideAvoraMetaForge };
|
|
6549
6396
|
//# sourceMappingURL=avora-labs-meta-forge.mjs.map
|