Skip to content

Commit

Permalink
feat(Admin UI): configurable columns and filters for list views (#2177)
Browse files Browse the repository at this point in the history
closes #2067

---------
This functionality has been developed for the project “codo”.
codo is developed under the projects “Landungsbrücken – Patenschaften in Hamburg stärken” and “openTransfer Patenschaften”. It is funded through the program “Menschen stärken Menschen” by the German Federal Ministry of Family Affairs, Senior Citizens, Women and Youth.
More information at https://github.com/codo-mentoring

“Landungsbrücken – Patenschaften in Hamburg stärken” is a project of BürgerStiftung Hamburg in cooperation with the Mentor.Ring Hamburg. With a mix of networking opportunities, capacity building and financial support the project strengthens Hamburg’s scene of mentoring projects since its founding in 2016.

The “Stiftung Bürgermut” foundation since 2007 supports the digital and real exchange of experiences and connections of active citizens. Within the federal program “Menschen stärken Menschen” the foundation as part of its program “openTransfer Patenschaften” offers support services for connecting, spreading and upskilling mentoring organisations across Germany.

Diese Funktion wurde entwickelt für das Projekt codo.
codo wird entwickelt im Rahmen der Projekte Landungsbrücken – Patenschaften in Hamburg stärken und openTransfer Patenschaften. Er ist gefördert durch das Bundesprogramm Menschen stärken Menschen des Bundesministeriums für Familie, Senioren, Frauen und Jugend.
Mehr Informationen unter https://github.com/codo-mentoring

“Landungsbrücken – Patenschaften in Hamburg stärken” ist ein Projekt der BürgerStiftung Hamburg in Kooperation mit dem Mentor.Ring Hamburg. Mit einer Mischung aus Vernetzungsangeboten, Qualifizierungsmaßnahmen und finanzieller Förderung stärkt das Projekt die Hamburger Szene der Patenschaftsprojekte seit der Gründung im Jahr 2016.

Die Stiftung Bürgermut fördert seit 2007 den digitalen und realen Erfahrungsaustausch und die Vernetzung von engagierten Bürger:innen. Innerhalb des Bundesprogramms „Menschen stärken Menschen” bietet die Stiftung im Rahmen ihres Programms openTransfer Patenschaften Unterstützungsleistungen zur Vernetzung, Verbreitung und Qualifizierung von Patenschafts- und Mentoringorganisationen bundesweit.

Co-authored-by: codo-mentoring <[email protected]>
  • Loading branch information
sleidig and codo-mentoring authored Mar 13, 2024
1 parent 9bfeb71 commit 4a870ec
Show file tree
Hide file tree
Showing 44 changed files with 2,021 additions and 796 deletions.
28 changes: 26 additions & 2 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,37 @@
*/

import { Component } from "@angular/core";
import { NavigationEnd, Router } from "@angular/router";
import { filter } from "rxjs/operators";

/**
* Component as the main entry point for the app.
* Actual logic and UI structure is defined in other modules.
*/
@Component({
selector: "app-root",
template: "<app-ui></app-ui>",
template: `@if (configFullscreen) {
<router-outlet></router-outlet>
} @else {
<app-ui></app-ui>
}`,
})
export class AppComponent {}
export class AppComponent {
configFullscreen: boolean = false;

constructor(private router: Router) {
this.detectConfigMode();
router.events
.pipe(filter((e) => e instanceof NavigationEnd))
.subscribe(() => this.detectConfigMode());
}

/**
* Switch the layout for certain admin routes to display those fullscreen without app menu and toolbar.
* @private
*/
private detectConfigMode() {
const currentUrl = this.router.url;
this.configFullscreen = currentUrl.startsWith("/admin/entity");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<app-view-title [disableBackButton]="true">
&lt;Name of displayed {{ this.entityConstructor?.label }}&gt;
</app-view-title>

<app-admin-tabs [tabs]="config?.panels" [newTabFactory]="newPanelFactory">
<ng-template [appAdminTabTemplate]="config?.panels" let-item>
<div class="flex-column gap-large padding-top-large">
<div
*ngFor="let componentConfig of item.components; let j = index"
class="section-wrapper"
>
<app-admin-section-header
[(title)]="componentConfig.title"
(remove)="item.components.splice(j, 1)"
></app-admin-section-header>

<app-admin-entity-form
*ngIf="componentConfig.component === 'Form'; else otherComponent"
[config]="componentConfig.config"
[entityType]="entityConstructor"
>
</app-admin-entity-form>

<ng-template #otherComponent>
<app-admin-entity-panel-component
[config]="componentConfig"
[entityType]="entityConstructor"
></app-admin-entity-panel-component>
</ng-template>
</div>

<button
mat-stroked-button
color="accent"
class="section-add-button"
(click)="addComponent(item)"
i18n
>
<fa-icon
aria-label="add element"
icon="plus-circle"
class="standard-icon-with-text"
></fa-icon>
Add Section
</button>
</div>
</ng-template>
</app-admin-tabs>
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,3 @@
padding: sizes.$large;
margin: sizes.$small;
}

:host ::ng-deep .mat-mdc-tab {
// adjust tab header height to properly display mat-form-field for editing tab label
height: 60px !important;
}
app-admin-section-header {
margin-bottom: -1em;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { ComponentFixture, TestBed } from "@angular/core/testing";

import { AdminEntityDetailsComponent } from "./admin-entity-details.component";
import { EntityDetailsConfig } from "../../../entity-details/EntityDetailsConfig";
import { Entity } from "../../../entity/model/entity";
import { MatTabsModule } from "@angular/material/tabs";
import { NoopAnimationsModule } from "@angular/platform-browser/animations";
import { DatabaseEntity } from "../../../entity/database-entity.decorator";
import { DatabaseField } from "../../../entity/database-field.decorator";
import { FontAwesomeTestingModule } from "@fortawesome/angular-fontawesome/testing";

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

let viewConfig: EntityDetailsConfig;
let viewConfigId, entityConfigId;

@DatabaseEntity("AdminDetailsTest")
class AdminDetailsTestEntity extends Entity {
static readonly ENTITY_TYPE = "AdminDetailsTest";

@DatabaseField({ label: "Name" }) name: string;
}

beforeEach(() => {
viewConfigId = `view:${AdminDetailsTestEntity.route.substring(1)}/:id`;
entityConfigId = `entity:${AdminDetailsTestEntity.ENTITY_TYPE}`;
viewConfig = {
entity: AdminDetailsTestEntity.ENTITY_TYPE,
panels: [{ title: "Tab 1", components: [] }],
};

TestBed.configureTestingModule({
imports: [
AdminEntityDetailsComponent,
MatTabsModule,
NoopAnimationsModule,
FontAwesomeTestingModule,
],
});
fixture = TestBed.createComponent(AdminEntityDetailsComponent);
component = fixture.componentInstance;

component.entityConstructor = AdminDetailsTestEntity;
component.config = JSON.parse(JSON.stringify(viewConfig));

fixture.detectChanges();
});

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

it("should add new section (component in panel) to config", () => {
component.addComponent(component.config.panels[0]);

expect(component.config.panels[0].components.length).toBe(1);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Component, Input } from "@angular/core";
import {
EntityDetailsConfig,
Panel,
} from "../../../entity-details/EntityDetailsConfig";
import { EntityConstructor } from "../../../entity/model/entity";
import { DynamicComponent } from "../../../config/dynamic-components/dynamic-component.decorator";
import { NgForOf, NgIf } from "@angular/common";
import { MatTabsModule } from "@angular/material/tabs";
import { FaIconComponent } from "@fortawesome/angular-fontawesome";
import { MatButtonModule } from "@angular/material/button";
import { EntityTypeLabelPipe } from "../../../common-components/entity-type-label/entity-type-label.pipe";
import { ViewTitleComponent } from "../../../common-components/view-title/view-title.component";
import { AdminSectionHeaderComponent } from "../../building-blocks/admin-section-header/admin-section-header.component";
import { AdminEntityFormComponent } from "../admin-entity-form/admin-entity-form.component";
import { AdminEntityPanelComponentComponent } from "../admin-entity-panel-component/admin-entity-panel-component.component";
import { MatTooltipModule } from "@angular/material/tooltip";
import { AdminTabsComponent } from "../../building-blocks/admin-tabs/admin-tabs.component";
import { AdminTabTemplateDirective } from "../../building-blocks/admin-tabs/admin-tab-template.directive";

@DynamicComponent("AdminEntityDetails")
@Component({
selector: "app-admin-entity-details",
templateUrl: "./admin-entity-details.component.html",
styleUrls: ["./admin-entity-details.component.scss"],
standalone: true,
imports: [
MatTabsModule,
FaIconComponent,
MatButtonModule,
EntityTypeLabelPipe,
ViewTitleComponent,
AdminSectionHeaderComponent,
AdminEntityFormComponent,
AdminEntityPanelComponentComponent,
MatTooltipModule,
NgForOf,
NgIf,
AdminTabsComponent,
AdminTabTemplateDirective,
],
})
export class AdminEntityDetailsComponent {
@Input() entityConstructor: EntityConstructor;
@Input() config: EntityDetailsConfig;

newPanelFactory(): Panel {
return { title: "New Tab", components: [] };
}

addComponent(panel: Panel) {
panel.components.push({
title: $localize`:Default title:New Section`,
component: "Form", // TODO: make this configurable
config: { fieldGroups: [] },
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { MatTooltipModule } from "@angular/material/tooltip";
import { MatCardModule } from "@angular/material/card";
import { EntityFieldLabelComponent } from "../../../common-components/entity-field-label/entity-field-label.component";
import { EntityFieldEditComponent } from "../../../common-components/entity-field-edit/entity-field-edit.component";
import { AdminSectionHeaderComponent } from "../admin-section-header/admin-section-header.component";
import { AdminSectionHeaderComponent } from "../../building-blocks/admin-section-header/admin-section-header.component";
import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
import { FormConfig } from "../../../entity-details/form/form.component";

Expand All @@ -34,7 +34,7 @@ import { FormConfig } from "../../../entity-details/form/form.component";
templateUrl: "./admin-entity-form.component.html",
styleUrls: [
"./admin-entity-form.component.scss",
"../admin-section-header/admin-section-header.component.scss",
"../../building-blocks/admin-section-header/admin-section-header.component.scss",
"../../../common-components/entity-form/entity-form/entity-form.component.scss",
],
standalone: true,
Expand Down

This file was deleted.

Loading

0 comments on commit 4a870ec

Please sign in to comment.