Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<mat-card class="dashboard-card" [class]="'card-' + color">
<mat-card class="dashboard-card"
[class]="'card-' + color"
[class.zero-value]="isZero"
[class.shake-animation]="isZero">
<mat-card-content>
<div class="card-header">
<div class="icon-container" [class]="'icon-' + color">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,53 @@

// Prompt styling
::ng-deep [prompt] {
font-size: 13px;
color: #7f11e0;
font-weight: 500;
font-size: 14px;
color: #d32f2f;
font-weight: 600;
display: flex;
align-items: center;
gap: 4px;
animation: pulse 2s infinite;
gap: 6px;
animation: urgent-pulse 1.5s infinite;
text-shadow: 0 0 8px rgba(211, 47, 47, 0.3);
letter-spacing: 0.5px;

&:before {
content: '👆';
font-size: 16px;
span {
position: relative;

&::after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg,
transparent,
#d32f2f,
transparent
);
animation: underline-slide 2s infinite;
}
}
}

@keyframes urgent-pulse {
0%, 100% {
opacity: 0.9;
transform: scale(1);
}
50% {
opacity: 1;
transform: scale(1.02);
}
}

@keyframes underline-slide {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}

Expand All @@ -139,6 +175,97 @@
}
}

// Zero value styling
.dashboard-card.zero-value {
background: linear-gradient(135deg, #fff5f5 0%, #ffe0e0 100%);
border: 2px solid #ff6b6b;
position: relative;
overflow: hidden;
box-shadow: 0 0 20px rgba(255, 107, 107, 0.2);
animation: glow-pulse 2.5s infinite;

&::before {
content: '';
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
background: linear-gradient(90deg,
transparent,
rgba(255, 107, 107, 0.3),
transparent
);
animation: shimmer 3s infinite;
}

.card-value {
color: #d32f2f !important;
font-weight: 700 !important;
text-shadow: 0 0 3px rgba(211, 47, 47, 0.2);
}

.icon-container {
animation: attention-pulse 2s infinite;
box-shadow: 0 0 15px rgba(255, 107, 107, 0.3);
}

&:hover {
transform: translateY(-2px) scale(1.02);
box-shadow: 0 4px 30px rgba(255, 107, 107, 0.3);
}
}

@keyframes glow-pulse {
0%, 100% {
box-shadow: 0 0 20px rgba(255, 107, 107, 0.2);
}
50% {
box-shadow: 0 0 30px rgba(255, 107, 107, 0.4);
}
}

// Shake animation for zero value cards
.dashboard-card.shake-animation {
animation: subtle-shake 4s infinite;
}

@keyframes subtle-shake {
0%, 90%, 100% {
transform: translateX(0);
}
92% {
transform: translateX(-2px) rotate(-0.5deg);
}
94% {
transform: translateX(2px) rotate(0.5deg);
}
96% {
transform: translateX(-1px) rotate(-0.3deg);
}
98% {
transform: translateX(1px) rotate(0.3deg);
}
}

@keyframes shimmer {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(200%);
}
}

@keyframes attention-pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
}

// Dark theme
:host-context(.dark-theme) {
.dashboard-card {
Expand All @@ -165,9 +292,35 @@
color: #bbb;
}
}

&.zero-value {
background: linear-gradient(135deg, #4a1a1a 0%, #3d1515 100%);
border: 2px solid #ff6b6b;

&::before {
background: linear-gradient(90deg,
transparent,
rgba(255, 107, 107, 0.2),
transparent
);
}

.card-value {
color: #ff8a80 !important;
}
}
}

::ng-deep [prompt] {
color: #bb86fc;
color: #ff8a80;
text-shadow: 0 0 10px rgba(255, 138, 128, 0.5);

span::after {
background: linear-gradient(90deg,
transparent,
#ff8a80,
transparent
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export class DfDashboardCardComponent {
@Input() trendClass?: string;
@Input() footerText?: string;
@Input() showPrompt?: boolean = false;
@Input() isZero?: boolean = false;
@Input() color: 'primary' | 'accent' | 'success' | 'info' | 'warn' =
'primary';
}
11 changes: 11 additions & 0 deletions src/app/adf-home/df-dashboard/df-dashboard.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ <h2 class="dashboard-title">{{ 'home.dashboard.title' | transloco }}</h2>
[value]="stats.services.total"
[subtitle]="'home.dashboard.services.total' | transloco"
[showPrompt]="stats.services.total === 0"
[isZero]="stats.services.total === 0"
color="primary">
<div prompt class="service-prompt" *ngIf="stats.services.total === 0">
<span>{{ 'home.dashboard.services.createPrompt' | transloco }}</span>
Expand All @@ -33,7 +34,12 @@ <h2 class="dashboard-title">{{ 'home.dashboard.title' | transloco }}</h2>
[title]="'home.dashboard.apiKeys.title' | transloco"
[value]="stats.apiKeys.total"
[subtitle]="'home.dashboard.apiKeys.total' | transloco"
[showPrompt]="stats.apiKeys.total === 0"
[isZero]="stats.apiKeys.total === 0"
color="success">
<div prompt class="key-prompt" *ngIf="stats.apiKeys.total === 0">
<span>{{ 'home.dashboard.apiKeys.createPrompt' | transloco }}</span>
</div>
</df-dashboard-card>

<!-- Roles Card -->
Expand All @@ -42,7 +48,12 @@ <h2 class="dashboard-title">{{ 'home.dashboard.title' | transloco }}</h2>
[title]="'home.dashboard.roles.title' | transloco"
[value]="stats.roles.total"
[subtitle]="'home.dashboard.roles.total' | transloco"
[showPrompt]="stats.roles.total === 0"
[isZero]="stats.roles.total === 0"
color="info">
<div prompt class="role-prompt" *ngIf="stats.roles.total === 0">
<span>{{ 'home.dashboard.roles.createPrompt' | transloco }}</span>
</div>
</df-dashboard-card>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ import { catchError, throwError } from 'rxjs';
standalone: true,
imports: DfManageTableModules,
})
export class DfManageServicesTableComponent extends DfManageTableComponent<ServiceRow> implements OnInit {
export class DfManageServicesTableComponent
extends DfManageTableComponent<ServiceRow>
implements OnInit
{
serviceTypes: Array<ServiceType> = [];
system = false;
constructor(
Expand All @@ -41,15 +44,18 @@ export class DfManageServicesTableComponent extends DfManageTableComponent<Servi
) {
super(router, activatedRoute, liveAnnouncer, translateService, dialog);
}

override ngOnInit(): void {
// Call parent's ngOnInit first to set up the data source
super.ngOnInit();

// Then subscribe to route data for additional setup
this._activatedRoute.data.subscribe((routeData) => {
this._activatedRoute.data.subscribe(routeData => {
const { data } = routeData;
this.system = routeData['system'] || this._activatedRoute.snapshot.parent?.data?.['system'] || false;
this.system =
routeData['system'] ||
this._activatedRoute.snapshot.parent?.data?.['system'] ||
false;
this.serviceTypes = data?.serviceTypes;
this.allowCreate = !this.system;
if (this.system) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,9 +384,7 @@ export class DfServiceDetailsComponent implements OnInit {
if (serviceType === 'local_email') {
return false;
}
return (
serviceType && this.configSchema?.length === 0
);
return serviceType && this.configSchema?.length === 0;
}

get scriptMode() {
Expand Down
10 changes: 7 additions & 3 deletions src/app/adf-services/resolvers/services.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ export const servicesResolver =
const serviceTypeService = inject(SERVICE_TYPE_SERVICE_TOKEN);
const servicesService = inject(SERVICES_SERVICE_TOKEN);

const system: boolean = route.data['system'] || route.parent?.data?.['system'] || false;
const groups: Array<string> = route.data['groups'] || route.parent?.data?.['groups'];
const system: boolean =
route.data['system'] || route.parent?.data?.['system'] || false;
const groups: Array<string> =
route.data['groups'] || route.parent?.data?.['groups'];

if (groups) {
const filteredGroups = groups.map(grp =>
Expand All @@ -44,7 +46,9 @@ export const servicesResolver =
limit,
sort: 'name',
filter: `${
system ? '(created_by_id is null) and (name != "api_docs") and ' : ''
system
? '(created_by_id is null) and (name != "api_docs") and '
: ''
}(type in ("${serviceTypes.map(src => src.name).join('","')}"))${
filter ? ` and ${filter}` : ''
}`,
Expand Down
8 changes: 5 additions & 3 deletions src/assets/i18n/home/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,19 +99,21 @@
"services": {
"title": "API Services",
"total": "Your Services",
"createPrompt": "Get started! Create your first API using the cards above"
"createPrompt": "🚀 Get started! Create your first API service above!"
},
"admins": {
"title": "Admins",
"total": "Total Admins"
},
"apiKeys": {
"title": "API Keys",
"total": "Your API Keys"
"total": "Your API Keys",
"createPrompt": "🔑 Secure your APIs! Generate an API key now!"
},
"roles": {
"title": "Roles",
"total": "Your Roles"
"total": "Your Roles",
"createPrompt": "🔒 Control access! Set up your first role!"
}
}
}