src/app/core/dashboard/dashboard-widget/dashboard-widget.component.ts

Metadata

Relationships

Depends on

Index

Inputs

Inputs

explanation
Type : string

optional tooltip to explain detailed meaning of this widget / statistic

headline
Type : string
icon
Type : IconName
loading
Type : boolean
Default value : false

Show a loading indicator until data is ready to be shown

subtitle
Type : string
theme
Type : DashboardTheme
title
Type : string | number
import { ChangeDetectionStrategy, Component, input } from "@angular/core";
import { IconName } from "@fortawesome/fontawesome-svg-core";
import { MatProgressSpinnerModule } from "@angular/material/progress-spinner";
import { FaDynamicIconComponent } from "../../common-components/fa-dynamic-icon/fa-dynamic-icon.component";
import { MatTooltipModule } from "@angular/material/tooltip";

export type DashboardTheme =
  "general" | "child" | "attendance" | "note" | "class" | "school";

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: "app-dashboard-widget",
  templateUrl: "./dashboard-widget.component.html",
  styleUrls: ["./dashboard-widget.component.scss"],
  imports: [MatProgressSpinnerModule, FaDynamicIconComponent, MatTooltipModule],
})
export class DashboardWidgetComponent {
  subtitle = input<string>();
  icon = input<IconName>();
  theme = input<DashboardTheme>();

  title = input<string | number>();

  /** optional tooltip to explain detailed meaning of this widget / statistic */
  explanation = input<string>();
  headline = input<string>();

  /** Show a loading indicator until data is ready to be shown */
  loading = input(false);
}
<!-- Header -->
<div class="widget-header theme-background-{{ theme() }}">
  @if (headline()) {
    <div class="widget-headline">{{ headline() }}</div>
  } @else {
    <div class="widget-title">
      @if (loading()) {
        <mat-spinner diameter="40"></mat-spinner>
      } @else {
        {{ title() }}
      }
    </div>
    <div class="widget-subheadline" [matTooltip]="explanation()">
      {{ subtitle() }}
    </div>
  }

  <app-fa-dynamic-icon
    class="widget-icon"
    [icon]="icon()"
  ></app-fa-dynamic-icon>
</div>

<!-- Content -->
<div class="widget-content">
  @if (loading()) {
    <h2 class="headline" i18n>Loading...</h2>
  } @else {
    <ng-content select="app-widget-content"></ng-content>
  }
</div>

./dashboard-widget.component.scss

@use "@angular/material/core/style/elevation" as mat-elevation;

$widget-header-height: 64px;
$widget-content-height: 320px;

$font-size-headline: 40pt;

$padding-header: 24px;

$border-radius-card: 4px;

.widget-header {
  /* Defines a grid that roughly looks like this:
   * |-------|--------------------------------------|
   * |       |                                      |
   * |       |                                      |
   * |-------|--------------------------------------|
   * |       |                                      |
   * |-------|--------------------------------------|
   *
   * The right-upper side is where the headline will be placed.
   * On the lower right side, the subhead-line is placed
   * On the two left sides, the icon will be placed in a
   * centered way
   */
  display: grid;
  grid-template: 2fr 1fr / 40pt 1fr;
  grid-template-areas:
    "icon headline"
    "subheadline subheadline";
  padding: $padding-header;
  height: $widget-header-height;
}

.widget-icon {
  grid-area: icon;
  color: white;
  align-self: center;
  font-size: $font-size-headline;
  /* fixes the correct centering of this item */
  display: table;
}

.widget-headline {
  grid-area: headline;
  text-align: end;
  place-self: end;

  font-size: 28pt;
  color: white;
}

.widget-title {
  grid-area: headline;
  text-align: end;
  place-self: center end;

  font-size: 40pt;
  color: white;
}

.widget-subheadline {
  grid-area: subheadline;
  text-align: end;
  place-self: end;
  margin-top: 8px;

  font-size: 14px;
  color: white;
}

.widget-content {
  height: $widget-content-height;
  overflow: hidden;
  display: flex;
  background-color: white;
}

.headline {
  height: 100%;
  width: 100%;
  display: flex;
  place-content: center;
  place-items: center;
}

/* Map containing the colors that belong to a certain theme */
$themes: (
  general: #555555,
  child: #1565c0,
  attendance: #00838f,
  note: #008f53,
  class: #2e7d32,
  school: #9e9d24,
);

@each $ident, $color in $themes {
  .theme-background-#{$ident} {
    background-color: $color;
  }
}

:host {
  display: block;
  border-radius: $border-radius-card;
  /* necessary for the border-radius to apply */
  overflow: auto;
  @include mat-elevation.elevation(3);
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""