Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Step-wise Setup Wizard #2280

Merged
merged 81 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from 80 commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
1dd2703
first step (mostly working) refactoring of entities-table component
sleidig Dec 21, 2023
2716644
Merge branch 'master' into admin-list
sleidig Dec 21, 2023
a16d52b
move code locations
sleidig Dec 22, 2023
2785f19
extract inline-edit
sleidig Dec 22, 2023
fb2186d
extract create button
sleidig Dec 22, 2023
b8d152a
fix some tests
sleidig Dec 22, 2023
b827d72
fix remaining tests & bugs
sleidig Dec 29, 2023
3737477
Update src/app/core/common-components/entities-table/list-paginator/l…
sleidig Jan 2, 2024
e4b37cb
Update src/app/core/common-components/entities-table/entity-inline-ed…
sleidig Jan 2, 2024
a5b212a
Merge branch 'master' into admin-list
sleidig Jan 2, 2024
2d139ba
remove unneeded code
sleidig Jan 3, 2024
542aca6
Merge remote-tracking branch 'origin/admin-list' into admin-list
sleidig Jan 3, 2024
cb31631
add fields-menu and positioning
sleidig Jan 4, 2024
f033ddd
Merge branch 'master' into admin-list
sleidig Jan 5, 2024
30d8444
remove unnecessary @UntilDestroy from child classes
sleidig Jan 8, 2024
d1c7a52
use base class onInit for ChildSchoolOverview
sleidig Jan 8, 2024
5162288
remove ngIf for table action columns
sleidig Jan 8, 2024
421c983
clarify comment for duplicate column config removal
sleidig Jan 8, 2024
d1c0cb4
remove unnecessary updateSubscription variables
sleidig Jan 8, 2024
73ccb14
simplify updateColumnsToDisplayForScreenSize
sleidig Jan 8, 2024
bc1e2bb
use super.ngOnInit
sleidig Jan 8, 2024
07e46a9
Merge branch 'master' into admin-list
sleidig Jan 8, 2024
d08bb44
fix test
sleidig Jan 8, 2024
9664842
fix ed mat
sleidig Jan 8, 2024
dacfe71
fix inline editing UI + triggering popup
sleidig Jan 8, 2024
c2e4d6e
fix inline editing unsavedChanges
sleidig Jan 8, 2024
6c6f6e9
correctly display relevant fields in popup
sleidig Jan 8, 2024
1213ff6
fix sort issue when setting programmatically from config
sleidig Jan 8, 2024
39a6c6b
use inheritance to identify date types
sleidig Jan 8, 2024
36a687e
fix tests
sleidig Jan 8, 2024
fb246be
Merge branch 'admin-list' into admin-list2
sleidig Jan 9, 2024
c193b49
Update src/app/core/common-components/entities-table/entity-inline-ed…
sleidig Jan 10, 2024
a28498c
fix todo list also navigating in addition to popup
sleidig Jan 10, 2024
a3e51dd
fix notes list not updating on undo delete
sleidig Jan 10, 2024
21c0360
Merge branch 'master' into admin-list
sleidig Jan 10, 2024
a3d2046
remove deprecated, unused code
sleidig Jan 10, 2024
4353bc4
ensure default sort by first column
sleidig Jan 10, 2024
8aefdac
fix switch highlighting of active entries
sleidig Jan 10, 2024
19f07cc
fix allowing to overwrite schema field with custom column config
sleidig Jan 10, 2024
68abce4
fix test
sleidig Jan 10, 2024
3d70d13
fix(core): related-entities can handle records where the mapped field…
sleidig Jan 11, 2024
0f71f77
Merge branch 'master' into admin-list
sleidig Jan 11, 2024
d3fd01d
show inactive on todo-list
sleidig Jan 11, 2024
3657756
disable un-sortable columns sort header automatically
sleidig Jan 11, 2024
aea5bd0
reset unsaved changes on inline cancel
sleidig Jan 12, 2024
1735a06
Merge branch 'fix-related-entities' into admin-list
sleidig Jan 12, 2024
a69abab
Merge branch 'master' into admin-list
sleidig Jan 12, 2024
5445a29
Merge branch 'admin-list' into admin-list2
sleidig Jan 12, 2024
7a78328
Merge branch 'master' into admin-list2
sleidig Jan 22, 2024
aa6d242
Merge branch 'master' into admin-list2
sleidig Feb 6, 2024
334095b
fix ui
sleidig Feb 6, 2024
b21cfd6
Merge branch 'master' into admin-list2
sleidig Mar 5, 2024
2000ffe
add admin-entity-list component
sleidig Mar 5, 2024
66f804f
introduce parent component for all config related to an entity type
sleidig Mar 6, 2024
8e4c56a
drag&drop for table columns
sleidig Mar 6, 2024
352a241
move admin-section-header
sleidig Mar 6, 2024
fc01814
support simplified config without columnGroups
sleidig Mar 6, 2024
cf9981f
fix tests
sleidig Mar 6, 2024
2b1d34a
Merge branch 'master' into admin-list2
sleidig Mar 6, 2024
11e1d6f
code cleanup
sleidig Mar 6, 2024
0d6a1e5
code cleanup
sleidig Mar 6, 2024
52326d6
better indentation with latest prettier
sleidig Mar 7, 2024
848f84c
generalize admin-tabs component
sleidig Mar 7, 2024
9d97dcc
code cleanup
sleidig Mar 7, 2024
22c1a5b
Merge branch 'master' into admin-list2
sleidig Mar 7, 2024
e4a30f1
basic step-wise setup wizard prototype
sleidig Mar 7, 2024
aacf3ec
Merge branch 'admin-list2' into setup-steps
sleidig Mar 7, 2024
b7dc4e4
layout tuning
sleidig Mar 7, 2024
881a144
translations and styling
sleidig Mar 12, 2024
19691c9
Merge branch 'admin-list2' into setup-steps
sleidig Mar 12, 2024
fbb7560
Merge branch 'master' into setup-steps
sleidig Mar 14, 2024
2975396
Merge branch 'master' into setup-steps
sleidig Mar 14, 2024
6066ffc
Merge branch 'master' into setup-steps
sleidig Apr 17, 2024
a62aec4
small ui adaptions
sleidig Apr 17, 2024
19019bd
make configurable and formatted with markdown
sleidig Apr 18, 2024
34274da
save progress and dismissal of setup wizard
sleidig Apr 19, 2024
d784b45
translations
sleidig Apr 19, 2024
2961cf0
Merge branch 'master' into setup-steps
sleidig Apr 19, 2024
35d2f80
handle missing config
sleidig Apr 19, 2024
51a125a
Merge branch 'master' into setup-steps
sleidig Apr 25, 2024
da225f5
add tests
sleidig Apr 25, 2024
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,6 +1,12 @@
<app-view-title [disableBackButton]="true" [displayInPlace]="true">
&lt;Name of displayed {{ this.entityConstructor?.label }}&gt;
</app-view-title>
<p i18n>
You can edit how users will see the details of a single record of this type.
Drag and drop fields and sections in this preview of a profile view and group
them as appropriate. We recommend to keep things simple: Only add fields that
you really need for your work.
</p>

<app-admin-tabs [tabs]="config?.panels" [newTabFactory]="newPanelFactory">
<ng-template [appAdminTabTemplate]="config?.panels" let-item>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ <h2 i18n>General Settings of "{{ entityConstructor.label }}" Records</h2>
</mat-form-field>

<mat-form-field floatLabel="always">
<mat-label i18n>
Label (Plural)
<mat-label>
<span i18n>Label (Plural)</span>
<fa-icon
icon="question-circle"
matTooltip="Optionally you can define how multiple records of this entity should be called, e.g. in lists."
Expand All @@ -31,8 +31,8 @@ <h2 i18n>General Settings of "{{ entityConstructor.label }}" Records</h2>
</mat-form-field>

<mat-form-field floatLabel="always">
<mat-label i18n>
Icon
<mat-label>
<span i18n>Icon</span>
<fa-icon
icon="question-circle"
matTooltip="The icon to represent this entity type, e.g. when displaying records as a small preview block. [see fontawesome.com/icons]"
Expand All @@ -49,8 +49,8 @@ <h2 i18n>General Settings of "{{ entityConstructor.label }}" Records</h2>

<div class="entity-form-cell">
<mat-form-field>
<mat-label i18n>
Generated Title of Record
<mat-label>
<span i18n>Generated Title of Record</span>
<fa-icon
icon="question-circle"
matTooltip="Select the fields that should be used (in that order) to generate a simple name/title for a record. This generated title is used in previews, search and for form fields that allow to select a record of this type. (Only text fields can be used here)"
Expand Down
2 changes: 1 addition & 1 deletion src/app/core/admin/admin-entity/admin-entity.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class AdminEntityComponent implements OnInit {
configDetailsView: EntityDetailsConfig;
configListView: EntityListConfig;
configEntitySettings: EntityConfig;
protected mode: "details" | "list" | "general" = "list";
protected mode: "details" | "list" | "general" = "details";

@ContentChild(TemplateRef) templateRef: TemplateRef<any>;

Expand Down
5 changes: 5 additions & 0 deletions src/app/core/admin/admin.routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ConfigImportComponent } from "../../features/config-setup/config-import
import { ConflictResolutionListComponent } from "../../features/conflict-resolution/conflict-resolution-list/conflict-resolution-list.component";
import { UserRoleGuard } from "../permissions/permission-guard/user-role.guard";
import { EntityPermissionGuard } from "../permissions/permission-guard/entity-permission.guard";
import { SetupWizardComponent } from "./setup-wizard/setup-wizard.component";

export const adminRoutes: Routes = [
{
Expand All @@ -15,6 +16,10 @@ export const adminRoutes: Routes = [
permittedUserRoles: ["admin_app"],
},
},
{
path: "setup-wizard",
component: SetupWizardComponent,
},
{
path: "entity/:entityType",
component: RoutedViewComponent,
Expand Down
4 changes: 4 additions & 0 deletions src/app/core/admin/admin/admin.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ <h2>Shortcuts</h2>
<mat-list-item [routerLink]="['/admin/conflicts']" i18n="admin menu item">
Database Conflicts
</mat-list-item>

<mat-list-item [routerLink]="['/admin/setup-wizard']" i18n="admin menu item">
Setup Wizard
</mat-list-item>
</mat-nav-list>

<hr />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@if (showSetupWizard) {
<button
mat-flat-button
routerLink="/admin/setup-wizard"
class="button"
color="accent"
style="border-radius: 0"
i18n
>
<fa-icon icon="person-digging"></fa-icon>
Setup Wizard
</button>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

.button {
border-top: solid 1px rgba(0, 0, 0, 0.12);
border-radius: 0;
overflow: hidden;
width: 100%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ComponentFixture, TestBed } from "@angular/core/testing";

import { SetupWizardButtonComponent } from "./setup-wizard-button.component";
import { EntityMapperService } from "../../../entity/entity-mapper/entity-mapper.service";
import { mockEntityMapper } from "../../../entity/entity-mapper/mock-entity-mapper-service";

describe("SetupWizardButtonComponent", () => {
let component: SetupWizardButtonComponent;
let fixture: ComponentFixture<SetupWizardButtonComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SetupWizardButtonComponent],
providers: [
{ provide: EntityMapperService, useValue: mockEntityMapper() },
],
}).compileComponents();

fixture = TestBed.createComponent(SetupWizardButtonComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it("should create", () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Component } from "@angular/core";
import { FaIconComponent } from "@fortawesome/angular-fontawesome";
import { MatButton } from "@angular/material/button";
import { RouterLink } from "@angular/router";
import { EntityMapperService } from "../../../entity/entity-mapper/entity-mapper.service";
import { Config } from "../../../config/config";
import {
CONFIG_SETUP_WIZARD_ID,
SetupWizardConfig,
} from "../setup-wizard-config";
import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
import { filter } from "rxjs/operators";
import { LoggingService } from "../../../logging/logging.service";

@UntilDestroy()
@Component({
selector: "app-setup-wizard-button",
standalone: true,
imports: [FaIconComponent, MatButton, RouterLink],
templateUrl: "./setup-wizard-button.component.html",
styleUrls: ["./setup-wizard-button.component.scss"],
})
export class SetupWizardButtonComponent {
showSetupWizard: boolean;

constructor(entityMapper: EntityMapperService, logger: LoggingService) {
entityMapper
.load(Config, CONFIG_SETUP_WIZARD_ID)
.then((r: Config<SetupWizardConfig>) => {
this.updateStatus(r.data);
})
.catch((e) => logger.debug("No Setup Wizard Config found"));

entityMapper
.receiveUpdates<Config<SetupWizardConfig>>(Config)
.pipe(
untilDestroyed(this),
filter(({ entity }) => entity.getId() === CONFIG_SETUP_WIZARD_ID),
)
.subscribe((update) => this.updateStatus(update.entity.data));
}

private updateStatus(config: SetupWizardConfig) {
this.showSetupWizard = !config.finished;
}
}
106 changes: 106 additions & 0 deletions src/app/core/admin/setup-wizard/setup-wizard-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { MenuItem } from "../../ui/navigation/menu-item";

export const CONFIG_SETUP_WIZARD_ID = "Config:SetupWizard";

export interface SetupWizardConfig {
/** index of the current (last visited) step, to be opened when user returns to the wizard **/
currentStep?: number;

/** whether the wizard has been completed overall and should be hidden */
finished?: boolean;

steps: SetupWizardStep[];
}

export interface SetupWizardStep {
title: string;
text: string;
actions?: MenuItem[];

/** whether the user(s) have completed this step yet */
completed?: boolean;
}

export const defaultSetupWizardConfig: SetupWizardConfig = {
steps: [
{
title: $localize`:Setup Wizard Step Title:Welcome`,
text: $localize`:Setup Wizard Step Text:
# Welcome to Aam Digital!
We are here to help you manage your participants' or beneficiaries' details
and your team's interactions with them.

The Aam Digital platform is very flexible and you can customize the structures and views
to exactly fit your project needs.
The following steps guide you through the most important configuration options for this.
And you can start working with your data within a few minutes already.

We also have some short video guides for you: [Aam Digital Video Guides (YouTube)](https://www.youtube.com/channel/UCZSFOX_MBa8zz5Mtfv_qlnA/videos)

Feel free to leave this setup wizard in between to explore the existing system first.
You can always come back to this view through the "Setup Wizard" button at the bottom of the main menu on the left.
To dismiss and hide this wizard, go to the last step of the wizard and "finish" the setup process.`,
},
{
title: $localize`:Setup Wizard Step Title:Profiles & Fields`,
text: $localize`:Setup Wizard Step Text:
The system already holds some basic structures for your case management.
You can adapt the fields and how the details are displayed.

If you have further requirements, don't hesitate to reach out to us at [support@aam-digital.com](mailto:support@aam-digital.com).

_Please note that the setup wizard and form builder is still under active development ("beta" version).
Some advanced configuration options are not available here yet for you to configure yourself and may need assistance from the tech support team.
We are currently extending and optimizing the user interfaces for these steps._
`,
actions: [
{
label: $localize`:Setup Wizard Step Action:Customize Child profile`,
link: "/admin/entity/Child",
},
{
label: $localize`:Setup Wizard Step Action:Customize School profile`,
link: "/admin/entity/School",
},
],
},
{
title: $localize`:Setup Wizard Step Title:User Accounts`,
text: $localize`:Setup Wizard Step Text:
You can collaborate on Aam Digital as a team.
Data is synced and all users have access to the latest information.`,
actions: [
{
label: $localize`:Setup Wizard Step Action:Manage User Accounts`,
link: "/user",
},
],
},
{
title: $localize`:Setup Wizard Step Title:Import Data`,
text: $localize`:Setup Wizard Step Text:
If you have exising data from a previous system, you can easily import it.
Save the data in ".csv" format (e.g. from MS Excel).
You do not need any specific column names in your file to be imported.
The Import Module helps your map your spreadsheet data to the relevant fields in your Aam Digital profiles.`,
actions: [
{
label: $localize`:Setup Wizard Step Action:Import Data`,
link: "/import",
},
],
},
{
title: $localize`:Setup Wizard Step Title:Done!`,
text: $localize`:Setup Wizard Step Text:
That's it. You are ready to explore your system and start work!

You can always adapt your setup further, after you started using it.
We recommend to keep things simple in the beginning,
start using it for some of your tasks
and then add further fields and adjust your setup.

Feel free to reach out to us with your questions or feedback: [support@aam-digital.com](mailto:support@aam-digital.com)`,
},
],
};
45 changes: 45 additions & 0 deletions src/app/core/admin/setup-wizard/setup-wizard.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<mat-stepper [(selectedIndex)]="currentStep">
<!-- overwrite icons to keep simple numbered steps -->
<ng-template matStepperIcon="edit" let-index="index">
{{ index + 1 }}
</ng-template>
<ng-template matStepperIcon="done" let-index="index">
{{ index + 1 }}
</ng-template>

@for (step of config?.steps; track step; let last = $last) {
<mat-step [label]="step.title" [completed]="step.completed">
<markdown>{{ step.text }}</markdown>

<mat-action-list>
@for (action of step.actions; track action.link) {
<button mat-list-item [routerLink]="action.link">
{{ action.label }}
</button>
}
</mat-action-list>

@if (!last) {
<button
mat-stroked-button
matStepperNext
(click)="step.completed = true"
i18n
>
Continue
</button>
} @else {
<button
mat-stroked-button
routerLink=""
(click)="step.completed = true; config.finished = true"
matTooltip="We will hide the setup wizard from the main menu as you finish it here. You can still access it from the admin screen."
i18n-matTooltip
i18n
>
Finish
</button>
}
</mat-step>
}
</mat-stepper>
Empty file.
27 changes: 27 additions & 0 deletions src/app/core/admin/setup-wizard/setup-wizard.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ComponentFixture, TestBed } from "@angular/core/testing";

import { SetupWizardComponent } from "./setup-wizard.component";
import { EntityMapperService } from "../../entity/entity-mapper/entity-mapper.service";
import { mockEntityMapper } from "../../entity/entity-mapper/mock-entity-mapper-service";

describe("SetupWizardComponent", () => {
let component: SetupWizardComponent;
let fixture: ComponentFixture<SetupWizardComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SetupWizardComponent],
providers: [
{ provide: EntityMapperService, useValue: mockEntityMapper() },
],
}).compileComponents();

fixture = TestBed.createComponent(SetupWizardComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it("should create", () => {
expect(component).toBeTruthy();
});
});
Loading
Loading