src/app/core/setup/system-init-assistant/system-init-assistant.component.ts

Description

UI for initial system setup and use case selection, used within the AssistantDialog.

Implements

OnInit

Example

Metadata

Relationships

Index

Properties
Methods

Methods

Async initializeSystem
initializeSystem()
Returns : any
onUseCaseSelected
onUseCaseSelected(selected: BaseConfig)
Parameters :
Name Type Optional
selected BaseConfig No
Returns : void
startExploring
startExploring()
Returns : void

Properties

availableLocales
Type : unknown
Default value : signal<ConfigurableEnumValue[]>([])
availableUseCases
Type : unknown
Default value : signal<BaseConfig[]>([])
demoInitialized
Type : unknown
Default value : signal<boolean>(false)
generateDemoData
Type : unknown
Default value : signal<boolean>(environment.demo_mode)
generatingData
Type : unknown
Default value : signal<boolean>(false)
selectedUseCase
Type : unknown
Default value : signal<BaseConfig | null>(null)
import {
  ChangeDetectionStrategy,
  Component,
  inject,
  OnInit,
  signal,
} from "@angular/core";
import { SetupService } from "../setup.service";
import { BaseConfig } from "../base-config";
import { MatButtonModule } from "@angular/material/button";
import { ChooseUseCaseComponent } from "./choose-use-case/choose-use-case.component";
import { Logging } from "../../logging/logging.service";
import { ActivatedRoute } from "@angular/router";
import { DemoDataInitializerService } from "../../demo-data/demo-data-initializer.service";
import { LanguageSelectComponent } from "app/core/language/language-select/language-select.component";
import { availableLocales } from "app/core/language/languages";
import { ConfigurableEnumValue } from "app/core/basic-datatypes/configurable-enum/configurable-enum.types";
import { MatDialogRef } from "@angular/material/dialog";
import { MatCheckbox } from "@angular/material/checkbox";
import { FormsModule } from "@angular/forms";
import { environment } from "#src/environments/environment";
import { AssistantService } from "#src/app/core/setup/assistant.service";

/**
 * UI for initial system setup and use case selection,
 * used within the AssistantDialog.
 */
@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: "app-system-init-assistant",
  imports: [
    MatButtonModule,
    ChooseUseCaseComponent,
    LanguageSelectComponent,
    MatCheckbox,
    FormsModule,
  ],
  templateUrl: "./system-init-assistant.component.html",
  styleUrl: "./system-init-assistant.component.scss",
})
export class SystemInitAssistantComponent implements OnInit {
  private dialogRef =
    inject<MatDialogRef<SystemInitAssistantComponent>>(MatDialogRef);
  private route = inject(ActivatedRoute);

  private readonly demoDataInitializer = inject(DemoDataInitializerService);
  private readonly setupService = inject(SetupService);

  availableUseCases = signal<BaseConfig[]>([]);
  selectedUseCase = signal<BaseConfig | null>(null);
  generateDemoData = signal<boolean>(environment.demo_mode);

  demoInitialized = signal<boolean>(false);
  generatingData = signal<boolean>(false);
  availableLocales = signal<ConfigurableEnumValue[]>([]);

  async ngOnInit(): Promise<void> {
    this.adjustAssistantDialogPanel();

    this.availableUseCases.set(
      await this.setupService.getAvailableBaseConfig(),
    );
    this.availableLocales.set(this.getAvailableLocalesForUseCases());

    await this.initFromQueryParamAutomatically();
  }

  private adjustAssistantDialogPanel() {
    this.dialogRef.updateSize(
      "calc(100% - 100px)",
      AssistantService.ASSISTANT_DIALOG_HEIGHT,
    );
    this.dialogRef.disableClose = true;
  }

  private getAvailableLocalesForUseCases() {
    const availableDemoLocale = new Set(
      this.availableUseCases()
        .map((useCase) => useCase.locale)
        .filter(Boolean),
    );

    return availableLocales.values.filter((locale) =>
      availableDemoLocale.has(locale.id),
    );
  }

  /**
   * The system can be opened with a pre-selected use case: ?useCase=useCaseId
   * @private
   */
  private async initFromQueryParamAutomatically() {
    const preSelectedUseCase = this.route.snapshot.queryParamMap.get("useCase");
    if (!preSelectedUseCase) {
      return;
    }

    const useCase =
      this.availableUseCases().find(
        (config) =>
          // Using lowercase comparison to avoid mismatches due to URL parameter casing or caching issues
          config.id.toLowerCase() === preSelectedUseCase.toLowerCase(),
      ) || null;

    this.selectedUseCase.set(useCase);

    await this.initializeSystem();
  }

  async initializeSystem() {
    if (!this.selectedUseCase()) {
      return;
    }

    this.generatingData.set(true);

    try {
      await this.setupService.initSystemWithBaseConfig(this.selectedUseCase()!);

      if (this.generateDemoData()) {
        await this.demoDataInitializer.generateDemoData();
      }

      this.demoInitialized.set(true);
    } catch (error) {
      Logging.error("Error initializing demo data:", error);
    } finally {
      this.generatingData.set(false);
    }
  }

  onUseCaseSelected(selected: BaseConfig) {
    this.selectedUseCase.set(selected);
  }

  startExploring() {
    this.dialogRef.close();
  }
}
<div class="flex-column gap-regular">
  @if (!demoInitialized() && !generatingData()) {
    <app-language-select
      [availableLocales]="availableLocales()"
    ></app-language-select>
  }

  <h1 i18n>Welcome to Aam Digital!</h1>

  @if (!demoInitialized() && !generatingData()) {
    <p i18n>
      We have built this platform to help you digitize information and case
      files of your project, make it easy to collaborate with your team, track
      individual progress of participants, and be alerted about critical
      developments. With Aam Digital, you can access your data across all
      devices, even when offline.
    </p>

    <app-choose-use-case
      [useCases]="availableUseCases()"
      (selectionChanged)="onUseCaseSelected($event)"
      class="margin-top-large margin-bottom-large"
    >
    </app-choose-use-case>

    <mat-checkbox
      [checked]="generateDemoData()"
      (change)="generateDemoData.set($event.checked)"
      i18n
      >Generate demo data</mat-checkbox
    >

    <p class="footer-note" i18n>
      Aam Digital is very flexible and can be quickly adapted to your needs and
      data structures. It is not limited to the scenarios above. After
      initializing your system, you can further customize it to track, measure,
      and manage your project.
    </p>

    <div class="demo-actions">
      <button
        mat-raised-button
        class="full-width"
        color="accent"
        (click)="initializeSystem()"
        [disabled]="!selectedUseCase()"
        i18n
      >
        Create System
      </button>
    </div>
  } @else if (generatingData()) {
    <p i18n>Generating sample data for this demo ...</p>
  } @else {
    <p i18n>
      We have loaded some sample data into this demo system. Explore and play
      around – you can’t break anything!<br />
      Changes you make in this demo will <em>not</em> be saved anywhere. The
      system is reset after you close or reload the page.
    </p>

    <p i18n>
      You can get assistance by clicking the "Assistant" button on the top right
      of the toolbar. From there you can also switch to other demo scenarios.
    </p>

    <div class="demo-actions">
      <button
        mat-raised-button
        class="full-width"
        color="accent"
        (click)="startExploring()"
        [disabled]="generatingData()"
        i18n
      >
        Start Exploring
      </button>
    </div>
  }
</div>

./system-init-assistant.component.scss

Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""