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

Task module #1578

Merged
merged 80 commits into from
Jan 10, 2023
Merged
Show file tree
Hide file tree
Changes from 63 commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
79a5320
feat: new task management module
sleidig Dec 6, 2022
8239329
refactor: extract entity-select components into module
sleidig Dec 7, 2022
b8e0443
feat: allow multiple entity types in the same entity-select field
sleidig Dec 7, 2022
15b6ca0
test: fix storybook stories for entity-select
sleidig Dec 7, 2022
7ea3d04
Merge branch 'master' into multi-entity-select
sleidig Dec 7, 2022
1b8537c
Merge branch 'multi-entity-select' into task-module
sleidig Dec 7, 2022
9c8b0b6
fix icon label alignment in new button
sleidig Dec 7, 2022
9d98c12
add multi-type related entities
sleidig Dec 7, 2022
c478d27
Merge remote-tracking branch 'origin/master' into task-module
sleidig Dec 8, 2022
2aa011f
fix(ui): make all entity blocks the same height
sleidig Dec 8, 2022
0cde0d0
improve config for tasks
sleidig Dec 8, 2022
b1409f8
Merge branch 'master' into task-module
sleidig Dec 11, 2022
51eec24
basic task views
sleidig Dec 11, 2022
43dd2b5
Update src/app/features/tasks/model/todo.ts
sleidig Dec 12, 2022
2294a46
added recurring time interval editing
sleidig Dec 12, 2022
dbd314e
added recurring time interval viewing
sleidig Dec 12, 2022
cba1944
make interval units translatable
sleidig Dec 12, 2022
1441557
Update src/app/features/tasks/recurring-interval/time-interval.ts
sleidig Dec 12, 2022
aaeb98e
WIP: task completion flow
sleidig Dec 13, 2022
fd718d0
add current user to tasks
sleidig Dec 13, 2022
6b2e2cb
reuse time unit array
sleidig Dec 13, 2022
aa9ed9d
improve custom interval popup
sleidig Dec 13, 2022
f15e38a
Merge remote-tracking branch 'origin/master' into task-module
sleidig Dec 13, 2022
5228325
make it easier to stick with the current details view on demo reload
sleidig Dec 13, 2022
f1c79c0
rename everything consistently from task to todo
sleidig Dec 13, 2022
c096045
better typing of entity classes
sleidig Dec 13, 2022
64bdd97
open todos in popup (at least for TodosRelatedToEntity)
sleidig Dec 13, 2022
dd3aa24
Merge remote-tracking branch 'origin/master' into task-module
sleidig Dec 13, 2022
4faf568
fix(core): properly handle changes to filters and columns of entity-s…
sleidig Dec 13, 2022
26c535a
basic working prototype of task completion and repetition
sleidig Dec 13, 2022
78bd3bf
translations
sleidig Dec 13, 2022
29bf17f
clean up and improve TodosRelatedTo component
sleidig Dec 14, 2022
d544fcb
Merge branch 'master' into task-module
TheSlimvReal Dec 14, 2022
6773d7d
clean up and improve TodosRelatedTo component
sleidig Dec 14, 2022
4c5a6d1
Update src/app/core/demo-data/demo-data.service.ts
sleidig Dec 16, 2022
91f0d24
rename storybook default params for entity form stories
sleidig Dec 16, 2022
5e1acdf
refactor typing and parameter names
sleidig Dec 16, 2022
b1a8c53
Merge remote-tracking branch 'origin/master' into task-module
sleidig Dec 16, 2022
e9ddd61
Update src/app/features/todos/todos-related-to-entity/todos-related-t…
sleidig Dec 16, 2022
27fa666
Merge branch 'master' into task-module
sleidig Dec 16, 2022
7b4752a
refactor: entity.isNew for easier recognition of create mode
sleidig Dec 20, 2022
386e100
hide "complete" button when creating new task
sleidig Dec 20, 2022
66a1cf1
alert for created repetition task + test fixes
sleidig Dec 20, 2022
6b7e26b
cloneDeep for entities
sleidig Dec 20, 2022
11fc896
fix problems with custom intervals
sleidig Dec 21, 2022
074c503
Merge branch 'master' into task-module
sleidig Dec 21, 2022
9bcfd01
fix completion on unsaved todo
sleidig Dec 21, 2022
50e2d7a
nicer completion display
sleidig Dec 21, 2022
b5152ec
more sophisticate applying of remote changes in entity-form
sleidig Dec 22, 2022
eea3702
undo of todo completion
sleidig Dec 22, 2022
03dc5e0
tests
sleidig Dec 22, 2022
9498072
Merge branch 'master' into task-module
sleidig Jan 3, 2023
f465bf6
finalize todo details
sleidig Jan 3, 2023
70773e0
fix tests
sleidig Jan 3, 2023
e4c7e8d
generalize the index generation
sleidig Jan 3, 2023
d815018
show details in popup - part 1
sleidig Jan 3, 2023
a66ed3f
refactor: add generic dashboard-list-widget.component
sleidig Jan 3, 2023
727352a
add todo dashboard widget
sleidig Jan 4, 2023
8f0b57c
add some custom todo filters
sleidig Jan 4, 2023
e21bc0b
refactor(core): remove obsolete recordChange output from entity-subre…
sleidig Jan 5, 2023
5217502
refactor(core): make initial sort order of entity-subrecord configurable
sleidig Jan 5, 2023
270e0e4
refactor(test): speed up and simplify tests for search component
sleidig Jan 5, 2023
d86281a
correctly sort in list and show fields in popups
sleidig Jan 5, 2023
70410fc
Merge remote-tracking branch 'origin/master' into task-module
TheSlimvReal Jan 6, 2023
6705d6a
improved typing of index creation and inferring whether it is an arra…
TheSlimvReal Jan 6, 2023
89639f6
Merge branch 'master' into task-module
TheSlimvReal Jan 6, 2023
5b25002
fixed component type
TheSlimvReal Jan 6, 2023
223d66c
remove unnecessary padding and width of entity select component
TheSlimvReal Jan 6, 2023
130696c
Merge remote-tracking branch 'origin/task-module' into task-module
TheSlimvReal Jan 6, 2023
53793ee
removed unused class
TheSlimvReal Jan 6, 2023
442ef16
Update src/app/core/config/config-fix.ts
sleidig Jan 6, 2023
06e9752
Update src/app/features/todos/recurring-interval/custom-interval/cust…
sleidig Jan 6, 2023
be19472
Update src/app/features/todos/todo-completion/todo-completion/todo-co…
sleidig Jan 6, 2023
8d28454
fix json and remove confirmation on completing todo
sleidig Jan 6, 2023
e23c6a0
Merge branch 'master' into task-module
sleidig Jan 9, 2023
297f3ca
lazy
sleidig Jan 9, 2023
1b0b0b9
Merge branch 'master' into task-module
sleidig Jan 9, 2023
9061bfc
tests
sleidig Jan 10, 2023
b8752be
translations
sleidig Jan 10, 2023
a167342
code cleanups
sleidig Jan 10, 2023
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
14 changes: 9 additions & 5 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,17 @@ import {
DEFAULT_LANGUAGE,
LANGUAGE_LOCAL_STORAGE_KEY,
} from "./core/language/language-statics";
import { DateAdapter, MAT_DATE_FORMATS } from "@angular/material/core";
import {DateAdapter, MAT_DATE_FORMATS} from "@angular/material/core";
import {
DATE_FORMATS,
DateAdapterWithFormatting,
} from "./core/language/date-adapter-with-formatting";
import { FileModule } from "./features/file/file.module";
import { ConfigSetupModule } from "./core/config-setup/config-setup.module";
import { LocationModule } from "./features/location/location.module";
import { MatchingEntitiesModule } from "./features/matching-entities/matching-entities.module";
import {FileModule} from "./features/file/file.module";
import {ConfigSetupModule} from "./core/config-setup/config-setup.module";
import {LocationModule} from "./features/location/location.module";
import {MatchingEntitiesModule} from "./features/matching-entities/matching-entities.module";
import {TodosModule} from "./features/todos/todos.module";
import {DemoTodoGeneratorService} from "./features/todos/model/demo-todo-generator.service";

/**
* Main entry point of the application.
Expand Down Expand Up @@ -162,6 +164,7 @@ import { MatchingEntitiesModule } from "./features/matching-entities/matching-en
maxCountAttributes: 5,
}),
...DemoPermissionGeneratorService.provider(),
...DemoTodoGeneratorService.provider(),
]),
AttendanceModule,
DashboardShortcutWidgetModule,
Expand All @@ -170,6 +173,7 @@ import { MatchingEntitiesModule } from "./features/matching-entities/matching-en
DatabaseModule,
LocationModule,
MatchingEntitiesModule,
TodosModule,
],
providers: [
{ provide: ErrorHandler, useClass: LoggingErrorHandler },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
@use "src/styles/variables/sizes";

.child-pic {
width: 28px;
height: 28px;
width: sizes.$icon-block;
height: sizes.$icon-block;
border-radius: 50%;
object-fit: cover;
margin-right: 4px;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,60 +1,35 @@
<app-dashboard-widget
<app-dashboard-list-widget
icon="exclamation-triangle"
[title]="notesDataSource.data.length"
subtitle="Notes needing follow-up"
i18n-subtitle="subtitle|dashboard showing notes that require action"
theme="note"
[loading]="loading"
entityType="Note"
[dataMapper]="dataMapper"
>
<app-widget-content>
<div *ngIf="notesDataSource.data.length > 0">
<table
mat-table
[dataSource]="notesDataSource"
aria-label="Notes needing follow-up"
>
<!-- Table header only for assistive technologies like screen readers -->
<tr hidden="true">
<th scope="col">Date</th>
<th scope="col">Title</th>
</tr>
<ng-container matColumnDef="date">
<td *matCellDef="let note" class="date-cell">
{{ note.date | date }}
</td>
</ng-container>
<table mat-table aria-label="Notes needing follow-up">
<!-- Table header only for assistive technologies like screen readers -->
<tr hidden="true">
<th scope="col">Date</th>
<th scope="col">Title</th>
</tr>
<ng-container matColumnDef="date">
<td *matCellDef="let note" class="date-cell row-indicator">
{{ note.date | date }}
</td>
</ng-container>

<ng-container
matColumnDef="title"
>
<td *matCellDef="let note" class="subject-cell">
{{ note.subject }}
</td>
</ng-container>
<ng-container matColumnDef="title">
<td *matCellDef="let note" class="subject-cell">
{{ note.subject }}
</td>
</ng-container>

<tr
mat-row
*matRowDef="let row; columns: ['date', 'title'];"
class="dashboard-table-row row-view"
(click)="openNote(row)"
[ngStyle]="{'--important-notes-bg-color': row.getColor?.()}"
></tr>
</table>
</div>
<div
*ngIf="notesDataSource.data.length === 0"
class="headline"
>
<span i18n="Description when there are no notes that need a follow-up">
no notes that need immediate attention
</span>
</div>
<mat-paginator
#paginator
[style.display]="paginator.getNumberOfPages() === 0 ? 'none' : ''"
[pageSizeOptions]="[5]"
[hidePageSize]="true"
>
</mat-paginator>
</app-widget-content>
</app-dashboard-widget>
<tr
mat-row
*matRowDef="let row; columns: ['date', 'title']"
class="dashboard-table-row row-view"
(click)="openNote(row)"
[ngStyle]="{'--row-indicator-color': row.getColor?.()}"
></tr>
</table>
</app-dashboard-list-widget>
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,6 @@
text-align: right;
}

.date-cell {
position: relative;

&::before {
left: 0;
top: 0;
content: '';
display: block;
width: sizes.$small;
height: 100%;
position: absolute;
background-color: var(--important-notes-bg-color);
}
}

.row-view {
cursor: pointer;
position: relative;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import { ComponentFixture, fakeAsync, TestBed } from "@angular/core/testing";
import {
ComponentFixture,
fakeAsync,
TestBed,
tick,
} from "@angular/core/testing";

import { ImportantNotesDashboardComponent } from "./important-notes-dashboard.component";
import { MockedTestingModule } from "../../../../utils/mocked-testing.module";
import { LoginState } from "../../../../core/session/session-states/login-state.enum";
import { Note } from "../../model/note";
import { FormDialogService } from "../../../../core/form-dialog/form-dialog.service";
import { MatPaginatorModule } from "@angular/material/paginator";
import { warningLevels } from "../../../warning-levels";
import { DashboardModule } from "../../../../core/dashboard/dashboard.module";
import { MatTableModule } from "@angular/material/table";
import { of } from "rxjs";
import { map } from "rxjs/operators";

describe("ImportantNotesDashboardComponent", () => {
let component: ImportantNotesDashboardComponent;
Expand All @@ -23,8 +30,8 @@ describe("ImportantNotesDashboardComponent", () => {
await TestBed.configureTestingModule({
imports: [
MockedTestingModule.withState(LoginState.LOGGED_IN, mockNotes),
MatPaginatorModule,
DashboardModule,
MatTableModule,
],
declarations: [ImportantNotesDashboardComponent],
providers: [
Expand Down Expand Up @@ -56,6 +63,12 @@ describe("ImportantNotesDashboardComponent", () => {
const expectedNotes = mockNotes
.filter((note) => ["WARNING", "URGENT"].includes(note.warningLevel.id))
.reverse();
expect(component.notesDataSource.data).toEqual(expectedNotes);

let actualNotes;
of(mockNotes)
.pipe(map((d) => component.dataMapper(d)))
.subscribe((data) => (actualNotes = data));
tick();
expect(actualNotes).toEqual(expectedNotes);
}));
});
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
import { AfterViewInit, Component, OnInit, ViewChild } from "@angular/core";
import { Component } from "@angular/core";
import { Note } from "../../model/note";
import { EntityMapperService } from "../../../../core/entity/entity-mapper.service";
import { DynamicComponent } from "../../../../core/view/dynamic-components/dynamic-component.decorator";
import { OnInitDynamicComponent } from "../../../../core/view/dynamic-components/on-init-dynamic-component.interface";
import { MatTableDataSource } from "@angular/material/table";
import { MatPaginator } from "@angular/material/paginator";
import { FormDialogService } from "../../../../core/form-dialog/form-dialog.service";
import { NoteDetailsComponent } from "../../note-details/note-details.component";
import { applyUpdate } from "../../../../core/entity/model/entity-update";
import { concat, Observable } from "rxjs";
import { first, map } from "rxjs/operators";
import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
import { OperatorFunction } from "rxjs";
import { map } from "rxjs/operators";
import { UntilDestroy } from "@ngneat/until-destroy";

@DynamicComponent("ImportantNotesDashboard")
@DynamicComponent("ImportantNotesComponent") // TODO remove after all existing instances are updated
Expand All @@ -21,47 +17,20 @@ import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
styleUrls: ["./important-notes-dashboard.component.scss"],
})
export class ImportantNotesDashboardComponent
implements OnInit, OnInitDynamicComponent, AfterViewInit
implements OnInitDynamicComponent
{
private relevantWarningLevels: string[] = [];
dataMapper: (data: Note[]) => Note[] = (data) =>
data
.filter((note) => note.warningLevel && this.noteIsRelevant(note))
.sort((a, b) => b.warningLevel._ordinal - a.warningLevel._ordinal);

private notes: Observable<Note[]>;
public loading: boolean = true;

public notesDataSource = new MatTableDataSource<Note>();

@ViewChild("paginator") private paginator: MatPaginator;

constructor(
private entityMapperService: EntityMapperService,
private formDialog: FormDialogService
) {}

ngOnInit(): void {
// This feed always contains the latest notes plus the initial notes
this.notes = concat(
this.entityMapperService.loadType(Note),
this.entityMapperService
.receiveUpdates(Note)
.pipe(map((next) => applyUpdate(this.notesDataSource.data, next)))
);
// set loading to `false` when the first chunk of notes (the initial notes) have arrived
this.notes.pipe(first()).subscribe(() => (this.loading = false));
this.notes.pipe(untilDestroyed(this)).subscribe((next) => {
this.notesDataSource.data = next
.filter((note) => note.warningLevel && this.noteIsRelevant(note))
.sort((a, b) => b.warningLevel._ordinal - a.warningLevel._ordinal);
});
}
constructor(private formDialog: FormDialogService) {}

onInitFromDynamicConfig(config: any) {
this.relevantWarningLevels = config.warningLevels;
}

ngAfterViewInit() {
this.notesDataSource.paginator = this.paginator;
}

private noteIsRelevant(note: Note): boolean {
return this.relevantWarningLevels.includes(note.warningLevel.id);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<app-entity-subrecord
[(records)]="records"
[records]="records"
[columns]="columns"
[getBackgroundColor]="null"
[newRecordFactory]="generateNewRecordFactory()"
Expand Down
69 changes: 68 additions & 1 deletion src/app/core/config/config-fix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ export const defaultJsonConfig = {
"icon": "file-alt",
"link": "/note"
},
{
"name": $localize`:Menu item:Tasks`,
"icon": "tasks",
"link": "/todo"
},
{
"name": $localize`:Menu item:Admin`,
"icon": "wrench",
Expand Down Expand Up @@ -176,6 +181,10 @@ export const defaultJsonConfig = {
"warningLevels": ["WARNING", "URGENT"],
}
},
{
"component": "TodosDashboard",
"config": {}
},
{
"component": "NotesDashboard",
"config": {
Expand Down Expand Up @@ -688,11 +697,15 @@ export const defaultJsonConfig = {
]
},
{
"title": $localize`:Panel title:Notes & Reports`,
"title": $localize`:Panel title:Notes & Tasks`,
"components": [
{
"title": "",
"component": "NotesRelatedToEntity"
},
{
"title": "Tasks",
"component": "TodosRelatedToEntity"
}
]
},
Expand Down Expand Up @@ -1131,5 +1144,59 @@ export const defaultJsonConfig = {
"newEntityMatchPropertyRight": "schoolId",
"columnsToReview": ["start", "end", "result", "childId", "schoolId"]
}
},

"entity:Todo": {
"attributes": []
},
"view:todo": {
"component": "TodoList",
"config": {
"entity": "Todo",
"columns": ["deadline", "subject", "assignedTo", "startDate", "relatedEntities"],
"filters": [
{ "id": "assignedTo" },

{
"id": "due-status",
"type": "prebuilt"
},
{ "id": "deadline" },
{ "id": "deadline" },
{ "id": "startDate" }
]
}
},
"view:todo/:id": {
"component": "EntityDetails",
"config": {
"entity": "Todo",
"panels": [
{
"title": $localize`:Panel title:Overview`,
"components": [
{
"title": "",
"component": "Form",
"config": {
"cols": [
[
"subject",
"description",
"relatedEntities"
],
[
"assignedTo",
"deadline",
"startDate",
"repetitionInterval"
]
]
}
}
]
}
],
}
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ export class ConfirmationDialogService {
},
})
.afterClosed()
.pipe(map((choice) => !!choice))
);
}
}
Loading