| @@ -213,6 +213,46 @@ export const productJsonldForm = new FormGroup({ | |||||
| createdAt: new FormControl(null, []) | createdAt: new FormControl(null, []) | ||||
| }); | }); | ||||
| export const taskForm = new FormGroup({ | |||||
| headline: new FormControl(null, [Validators.required]), | |||||
| description: new FormControl(null, [Validators.required]), | |||||
| createdBy: new FormControl(null, []), | |||||
| assignedTo: new FormControl(null, [Validators.required]), | |||||
| dueAt: new FormControl(null, [Validators.required]), | |||||
| partner: new FormControl(null, []), | |||||
| contact: new FormControl(null, []), | |||||
| prio: new FormControl(null, [Validators.required]), | |||||
| completed: new FormControl(null, []), | |||||
| createdAt: new FormControl(null, []) | |||||
| }); | |||||
| export const taskJsonhalForm = new FormGroup({ | |||||
| _links: new FormControl(null, []), | |||||
| headline: new FormControl(null, [Validators.required]), | |||||
| description: new FormControl(null, [Validators.required]), | |||||
| createdBy: new FormControl(null, []), | |||||
| assignedTo: new FormControl(null, [Validators.required]), | |||||
| dueAt: new FormControl(null, [Validators.required]), | |||||
| partner: new FormControl(null, []), | |||||
| contact: new FormControl(null, []), | |||||
| prio: new FormControl(null, [Validators.required]), | |||||
| completed: new FormControl(null, []), | |||||
| createdAt: new FormControl(null, []) | |||||
| }); | |||||
| export const taskJsonldForm = new FormGroup({ | |||||
| headline: new FormControl(null, [Validators.required]), | |||||
| description: new FormControl(null, [Validators.required]), | |||||
| createdBy: new FormControl(null, []), | |||||
| assignedTo: new FormControl(null, [Validators.required]), | |||||
| dueAt: new FormControl(null, [Validators.required]), | |||||
| partner: new FormControl(null, []), | |||||
| contact: new FormControl(null, []), | |||||
| prio: new FormControl(null, [Validators.required]), | |||||
| completed: new FormControl(null, []), | |||||
| createdAt: new FormControl(null, []) | |||||
| }); | |||||
| export const userForm = new FormGroup({ | export const userForm = new FormGroup({ | ||||
| email: new FormControl(null, [Validators.required, Validators.email]), | email: new FormControl(null, [Validators.required, Validators.email]), | ||||
| firstName: new FormControl(null, [Validators.required]), | firstName: new FormControl(null, [Validators.required]), | ||||
| @@ -43,7 +43,7 @@ export class NewContactComponent implements OnInit { | |||||
| // On submit form: Check if image is set | // On submit form: Check if image is set | ||||
| onSubmit() { | onSubmit() { | ||||
| if (this.selectedImage !== null) { | if (this.selectedImage !== null) { | ||||
| this.mediaSub = this.mediaService.mediasPost( | |||||
| this.mediaSub = this.mediaService.mediaPost( | |||||
| this.selectedImage | this.selectedImage | ||||
| ).subscribe( | ).subscribe( | ||||
| data => { | data => { | ||||
| @@ -48,7 +48,7 @@ export class NewPartnerComponent implements OnInit { | |||||
| // On submit form: Check if image is set | // On submit form: Check if image is set | ||||
| onSubmit() { | onSubmit() { | ||||
| if (this.selectedImage !== null) { | if (this.selectedImage !== null) { | ||||
| this.mediaSub = this.mediaService.mediasPost( | |||||
| this.mediaSub = this.mediaService.mediaPost( | |||||
| this.selectedImage | this.selectedImage | ||||
| ).subscribe( | ).subscribe( | ||||
| data => { | data => { | ||||
| @@ -104,51 +104,35 @@ | |||||
| <h2>{{'basic.tasks' | translate}}</h2> | <h2>{{'basic.tasks' | translate}}</h2> | ||||
| <button class="btn btn-primary" (click)="openModalNewTask()">{{'basic.new-task' | translate}}</button> | <button class="btn btn-primary" (click)="openModalNewTask()">{{'basic.new-task' | translate}}</button> | ||||
| </div> | </div> | ||||
| <div class="card mb-3 p-3"> | |||||
| <div class="position-relative" data-bs-toggle="collapse" data-bs-target="#collapseExample" | |||||
| aria-expanded="false" | |||||
| aria-controls="collapseExample"> | |||||
| <h3 class="m-0">Matsen AG</h3> | |||||
| <span class="info d-flex position-absolute"> | |||||
| <span class="due-date">01.10.2023</span> | |||||
| <span class="importance" data-importance="1"></span> | |||||
| <div class="tasks" *ngFor="let task of tasks"> | |||||
| <div class="card mb-3 p-3"> | |||||
| <div class="position-relative" data-bs-toggle="collapse" [attr.data-bs-target]="'#collapse-' + ApiConverter.extractId(task.id)" | |||||
| aria-expanded="false" | |||||
| aria-controls="collapseExample"> | |||||
| <h3 class="m-0">{{task.partner}}</h3> | |||||
| <span class="info d-flex position-absolute"> | |||||
| <span class="due-date">{{ task.dueAt | date:'dd.MM.YYYY HH:mm' }}</span> | |||||
| <span class="importance" [attr.data-importance]="task.prio"></span> | |||||
| </span> | </span> | ||||
| <h2 class="m-0">Wichtige Info: Unbedingt melden!</h2> | |||||
| </div> | |||||
| <div class="collapse" id="collapseExample"> | |||||
| <div class="pt-3 pe-5 position-relative"> | |||||
| <p class="m-0">Some placeholder content for the collapse component. This panel is hidden by default | |||||
| but | |||||
| revealed when the user activates the relevant trigger.</p> | |||||
| <span class="position-absolute bi bi-pencil p-2" data-type="user-tool" data-action="edit"></span> | |||||
| <h2 class="m-0">{{task.headline}}</h2> | |||||
| </div> | </div> | ||||
| </div> | |||||
| </div> | |||||
| <div class="card mb-3 p-3"> | |||||
| <div class="position-relative" data-bs-toggle="collapse" data-bs-target="#collapseExample2" | |||||
| aria-expanded="false" aria-controls="collapseExample2"> | |||||
| <h3 class="m-0">Matsen AG</h3> | |||||
| <span class="info d-flex position-absolute"> | |||||
| <span class="due-date">01.10.2023</span> | |||||
| <span class="importance" data-importance="1"></span> | |||||
| </span> | |||||
| <h2 class="m-0">Wichtige Info: Unbedingt melden!</h2> | |||||
| </div> | |||||
| <div class="collapse" id="collapseExample2"> | |||||
| <div class="pt-3 pe-5 position-relative"> | |||||
| <p class="m-0">Some placeholder content for the collapse component. This panel is hidden by default | |||||
| but | |||||
| revealed when the user activates the relevant trigger.</p> | |||||
| <span class="position-absolute bi bi-pencil p-2" data-type="user-tool" data-action="edit"></span> | |||||
| <div class="collapse" id="collapse-{{ApiConverter.extractId(task.id)}}"> | |||||
| <div class="pt-3 pe-5 position-relative"> | |||||
| <p class="m-0">{{task.description}}</p> | |||||
| <p>Zugewiesen an: {{task.assignedTo}}</p> | |||||
| <span class="position-absolute bi bi-pencil p-2" data-type="user-tool" data-action="edit"></span> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <!-- <mat-paginator class="mb-4" [length]="tasksLength"--> | |||||
| <!-- (page)="tasksHandlePageEvent($event)"--> | |||||
| <!-- [pageSize]="tasksPageSize"--> | |||||
| <!-- [pageIndex]="tasksPageIndex"--> | |||||
| <!-- showFirstLastButtons>--> | |||||
| <!-- </mat-paginator>--> | |||||
| <mat-paginator *ngIf="tasks.length > 0" class="rounded-1" | |||||
| [pageSizeOptions]="[10,20,30]" | |||||
| [length]="tasksLength" | |||||
| (page)="tasksHandlePageEvent($event)" | |||||
| [pageSize]="tasksPageSize" | |||||
| [pageIndex]="tasksPageIndex" | |||||
| showFirstLastButtons> | |||||
| </mat-paginator> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="spt-container"> | <div class="spt-container"> | ||||
| @@ -10,7 +10,7 @@ import { | |||||
| PartnerJsonld, | PartnerJsonld, | ||||
| PartnerService, | PartnerService, | ||||
| PostJsonld, | PostJsonld, | ||||
| PostService | |||||
| PostService, TaskJsonld, TaskService | |||||
| } from "@app/core/api/v1"; | } from "@app/core/api/v1"; | ||||
| import {Subscription} from "rxjs"; | import {Subscription} from "rxjs"; | ||||
| import {environment} from "@environments/environment"; | import {environment} from "@environments/environment"; | ||||
| @@ -32,10 +32,11 @@ import {NewPartnerComponent} from "@app/partners/new-partner/new-partner.compone | |||||
| }) | }) | ||||
| export class PartnersDetailComponent implements OnInit, AfterViewInit { | export class PartnersDetailComponent implements OnInit, AfterViewInit { | ||||
| @ViewChild(MatPaginator) contactsPaginator: MatPaginator; | @ViewChild(MatPaginator) contactsPaginator: MatPaginator; | ||||
| // @ViewChild(MatPaginator) tasksPaginator: MatPaginator; | |||||
| @ViewChild(MatPaginator) tasksPaginator: MatPaginator; | |||||
| @ViewChild(MatPaginator) postsPaginator: MatPaginator; | @ViewChild(MatPaginator) postsPaginator: MatPaginator; | ||||
| protected user: User | null; | protected user: User | null; | ||||
| protected readonly ApiConverter = ApiConverter; | |||||
| protected readonly environment = environment; | protected readonly environment = environment; | ||||
| protected id: string; | protected id: string; | ||||
| @@ -51,11 +52,13 @@ export class PartnersDetailComponent implements OnInit, AfterViewInit { | |||||
| protected contactsPageSize: number; | protected contactsPageSize: number; | ||||
| protected contactsPageIndex: number; | protected contactsPageIndex: number; | ||||
| // protected tasksDataSource; | |||||
| // protected tasksLength: number; | |||||
| // protected tasksPageEvent: PageEvent; | |||||
| // protected tasksPageSize: number; | |||||
| // protected tasksPageIndex: number; | |||||
| protected tasksSub: Subscription; | |||||
| protected tasks: Array<TaskJsonld>; | |||||
| protected tasksDataSource; | |||||
| protected tasksLength: number; | |||||
| protected tasksPageEvent: PageEvent; | |||||
| protected tasksPageSize: number; | |||||
| protected tasksPageIndex: number; | |||||
| protected postsSub: Subscription; | protected postsSub: Subscription; | ||||
| protected posts: Array<PostJsonld>; | protected posts: Array<PostJsonld>; | ||||
| @@ -78,7 +81,8 @@ export class PartnersDetailComponent implements OnInit, AfterViewInit { | |||||
| private route: ActivatedRoute, | private route: ActivatedRoute, | ||||
| private partnerService: PartnerService, | private partnerService: PartnerService, | ||||
| private contactService: ContactService, | private contactService: ContactService, | ||||
| private postService: PostService | |||||
| private postService: PostService, | |||||
| private taskService: TaskService | |||||
| ) { | ) { | ||||
| this.id = ""; | this.id = ""; | ||||
| this.partnerDetailSub = new Subscription(); | this.partnerDetailSub = new Subscription(); | ||||
| @@ -95,13 +99,14 @@ export class PartnersDetailComponent implements OnInit, AfterViewInit { | |||||
| this.contactsPageSize = 6; | this.contactsPageSize = 6; | ||||
| this.contactsPageIndex = 0; | this.contactsPageIndex = 0; | ||||
| // TODO: Change Jsonld | |||||
| // this.tasksPaginator = new MatPaginator(new MatPaginatorIntl(), ChangeDetectorRef.prototype); | |||||
| // this.tasksDataSource = new MatTableDataSource<ContactJsonld>(this.contacts); | |||||
| // this.tasksLength = 0; | |||||
| // this.tasksPageEvent = new PageEvent(); | |||||
| // this.tasksPageSize = 10; | |||||
| // this.tasksPageIndex = 0; | |||||
| this.tasksSub = new Subscription(); | |||||
| this.tasks = []; | |||||
| this.tasksPaginator = new MatPaginator(new MatPaginatorIntl(), ChangeDetectorRef.prototype); | |||||
| this.tasksDataSource = new MatTableDataSource<TaskJsonld>(this.tasks); | |||||
| this.tasksLength = 0; | |||||
| this.tasksPageEvent = new PageEvent(); | |||||
| this.tasksPageSize = 10; | |||||
| this.tasksPageIndex = 0; | |||||
| this.postsSub = new Subscription(); | this.postsSub = new Subscription(); | ||||
| this.posts = []; | this.posts = []; | ||||
| @@ -120,11 +125,12 @@ export class PartnersDetailComponent implements OnInit, AfterViewInit { | |||||
| this.getPartnerData(); | this.getPartnerData(); | ||||
| this.getContactsData(); | this.getContactsData(); | ||||
| this.getPostsData(); | this.getPostsData(); | ||||
| this.getTasksData(); | |||||
| } | } | ||||
| ngAfterViewInit() { | ngAfterViewInit() { | ||||
| this.contactsDataSource.paginator = this.contactsPaginator; | this.contactsDataSource.paginator = this.contactsPaginator; | ||||
| // this.tasksDataSource.paginator = this.tasksPaginator; | |||||
| this.tasksDataSource.paginator = this.tasksPaginator; | |||||
| this.postsDataSource.paginator = this.postsPaginator; | this.postsDataSource.paginator = this.postsPaginator; | ||||
| } | } | ||||
| @@ -167,6 +173,21 @@ export class PartnersDetailComponent implements OnInit, AfterViewInit { | |||||
| ); | ); | ||||
| } | } | ||||
| getTasksData() { | |||||
| this.tasksSub = this.taskService.tasksGetCollection( | |||||
| this.tasksPageIndex + 1, | |||||
| this.tasksPageSize, | |||||
| // TODO: Partner ID muss übergeben werden können, damit man nur die Partner-Tasks bekommt | |||||
| // TODO: User-ID muss übergeben werden können, damit man nur die Tasks bekommt, die einem User zugewiesen sind | |||||
| // this.id | |||||
| ).subscribe( | |||||
| data => { | |||||
| this.tasks = data["hydra:member"]; | |||||
| this.tasksLength = Number(data["hydra:totalItems"]); | |||||
| } | |||||
| ); | |||||
| } | |||||
| contactsHandlePageEvent(e: PageEvent) { | contactsHandlePageEvent(e: PageEvent) { | ||||
| this.contactsPageEvent = e; | this.contactsPageEvent = e; | ||||
| this.contactsLength = e.length; | this.contactsLength = e.length; | ||||
| @@ -176,11 +197,11 @@ export class PartnersDetailComponent implements OnInit, AfterViewInit { | |||||
| } | } | ||||
| tasksHandlePageEvent(e: PageEvent) { | tasksHandlePageEvent(e: PageEvent) { | ||||
| // this.tasksPageEvent = e; | |||||
| // this.tasksLength = e.length; | |||||
| // this.tasksPageIndex = e.pageIndex.valueOf(); | |||||
| // this.tasksPageSize = e.pageSize.valueOf(); | |||||
| // this.getData(); | |||||
| this.tasksPageEvent = e; | |||||
| this.tasksLength = e.length; | |||||
| this.tasksPageIndex = e.pageIndex.valueOf(); | |||||
| this.tasksPageSize = e.pageSize.valueOf(); | |||||
| this.getTasksData(); | |||||
| } | } | ||||
| postsHandlePageEvent(e: PageEvent) { | postsHandlePageEvent(e: PageEvent) { | ||||
| @@ -209,6 +230,19 @@ export class PartnersDetailComponent implements OnInit, AfterViewInit { | |||||
| }); | }); | ||||
| } | } | ||||
| openModalNewTask() { | |||||
| const modalRefTask = this.modalService.open(NewTaskComponent, this.modalOptions); | |||||
| let task: TaskJsonld = {} as TaskJsonld; | |||||
| task.partner = this.partner.id ?? null; | |||||
| modalRefTask.componentInstance.posting = task; | |||||
| modalRefTask.componentInstance.submit.subscribe((modalStatus: ModalStatus) => { | |||||
| if (modalStatus === ModalStatus.Submitted) { | |||||
| modalRefTask.dismiss(); | |||||
| this.getTasksData(); | |||||
| } | |||||
| }); | |||||
| } | |||||
| openModalNewPosting() { | openModalNewPosting() { | ||||
| const modalRefPosting = this.modalService.open(NewPostingComponent, this.modalOptions); | const modalRefPosting = this.modalService.open(NewPostingComponent, this.modalOptions); | ||||
| let posting: PostJsonld = {} as PostJsonld; | let posting: PostJsonld = {} as PostJsonld; | ||||
| @@ -257,12 +291,6 @@ export class PartnersDetailComponent implements OnInit, AfterViewInit { | |||||
| }); | }); | ||||
| } | } | ||||
| openModalNewTask() { | |||||
| // TODO | |||||
| const modalRef = this.modalService.open(ModalComponent, this.modalOptions); | |||||
| modalRef.componentInstance.dynamicComponent = NewTaskComponent; | |||||
| } | |||||
| openModalEditPartner() { | openModalEditPartner() { | ||||
| const modalRef = this.modalService.open(NewPartnerComponent, this.modalOptions); | const modalRef = this.modalService.open(NewPartnerComponent, this.modalOptions); | ||||
| modalRef.componentInstance.partner = this.partner; | modalRef.componentInstance.partner = this.partner; | ||||
| @@ -1,6 +1,6 @@ | |||||
| import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; | import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; | ||||
| import {ModalStatus} from "@app/_helpers/modal.states"; | import {ModalStatus} from "@app/_helpers/modal.states"; | ||||
| import {CommentJsonld, CommentService, PostJsonld, PostService} from "@app/core/api/v1"; | |||||
| import {CommentJsonld, CommentService, PostJsonld} from "@app/core/api/v1"; | |||||
| import {Subscription} from "rxjs"; | import {Subscription} from "rxjs"; | ||||
| import {FormGroupInitializer} from "@app/_helpers/formgroup.initializer"; | import {FormGroupInitializer} from "@app/_helpers/formgroup.initializer"; | ||||
| import {FormGroup} from "@angular/forms"; | import {FormGroup} from "@angular/forms"; | ||||
| @@ -41,7 +41,7 @@ export class NewProductComponent implements OnInit { | |||||
| onSubmit() { | onSubmit() { | ||||
| if (this.selectedImage !== null) { | if (this.selectedImage !== null) { | ||||
| this.mediaSub = this.mediaService.mediasPost( | |||||
| this.mediaSub = this.mediaService.mediaPost( | |||||
| this.selectedImage | this.selectedImage | ||||
| ).subscribe( | ).subscribe( | ||||
| data => { | data => { | ||||
| @@ -1 +1,23 @@ | |||||
| <p>new-task works!</p> | |||||
| <h2 *ngIf="!task.id">{{'basic.new-task' | translate}}</h2> | |||||
| <h2 *ngIf="task.id">{{'basic.edit-task' | translate}}</h2> | |||||
| <div class="spt-form"> | |||||
| <form [formGroup]="taskForm" (ngSubmit)="onSubmit()"> | |||||
| <div class="mb-3"> | |||||
| <label for="headline" class="form-label">{{'form.headline' | translate}}:</label> | |||||
| <input type="text" class="form-control" id="headline" formControlName="headline" /> | |||||
| <div class="form-text" *ngIf="taskForm.get('headline')?.invalid && taskForm.get('headline')?.touched"> | |||||
| {{'form.headline' | translate}} {{'form.mandatory' | translate}}. | |||||
| </div> | |||||
| </div> | |||||
| <div class="mb-3"> | |||||
| <label for="description" class="form-label">{{'form.description' | translate}}:</label> | |||||
| <input type="text" class="form-control" id="description" formControlName="description" /> | |||||
| <div class="form-text" *ngIf="taskForm.get('description')?.invalid && taskForm.get('description')?.touched"> | |||||
| {{'form.description' | translate}} {{'form.mandatory' | translate}}. | |||||
| </div> | |||||
| </div> | |||||
| <button type="submit" class="btn btn-primary" [disabled]="taskForm.invalid">{{'form.send' | translate}}</button> | |||||
| </form> | |||||
| </div> | |||||
| @@ -1,10 +1,36 @@ | |||||
| import { Component } from '@angular/core'; | |||||
| import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; | |||||
| import {TaskJsonld} from "@app/core/api/v1"; | |||||
| import {ModalStatus} from "@app/_helpers/modal.states"; | |||||
| import {FormGroupInitializer} from "@app/_helpers/formgroup.initializer"; | |||||
| import {FormGroup} from "@angular/forms"; | |||||
| import {Subscription} from "rxjs"; | |||||
| import {taskForm} from "@app/_forms/apiForms"; | |||||
| @Component({ | @Component({ | ||||
| selector: 'app-new-task', | selector: 'app-new-task', | ||||
| templateUrl: './new-task.component.html', | templateUrl: './new-task.component.html', | ||||
| styleUrl: './new-task.component.scss' | styleUrl: './new-task.component.scss' | ||||
| }) | }) | ||||
| export class NewTaskComponent { | |||||
| export class NewTaskComponent implements OnInit { | |||||
| @Input() public task!: TaskJsonld; | |||||
| @Output() public submit: EventEmitter<ModalStatus> = new EventEmitter<ModalStatus>(); | |||||
| protected taskForm: FormGroup; | |||||
| protected taskSub: Subscription; | |||||
| constructor( | |||||
| ) { | |||||
| this.taskForm = taskForm; | |||||
| this.taskSub = new Subscription(); | |||||
| } | |||||
| ngOnInit(): void { | |||||
| this.taskForm = FormGroupInitializer.initFormGroup(this.taskForm, this.task); | |||||
| } | |||||
| onSubmit() { | |||||
| } | |||||
| } | } | ||||
| @@ -29,3 +29,22 @@ img { | |||||
| .spt-container { | .spt-container { | ||||
| margin-bottom: 3rem; | margin-bottom: 3rem; | ||||
| } | } | ||||
| .importance { | |||||
| display: block; | |||||
| width: 50vw; | |||||
| height: 5px; | |||||
| position: absolute; | |||||
| right: 0; | |||||
| top: -16px; | |||||
| &[data-importance="low"] { | |||||
| background: #77bb33; | |||||
| } | |||||
| &[data-importance="medium"] { | |||||
| background: #ffee55; | |||||
| } | |||||
| &[data-importance="high"] { | |||||
| background: #bb1414; | |||||
| } | |||||
| } | |||||