Kaynağa Gözat

delete image / tasks home / translations

master
Florian Eisenmenger 1 yıl önce
ebeveyn
işleme
b06c2b6fe7
16 değiştirilmiş dosya ile 419 ekleme ve 65 silme
  1. +1
    -1
      matsen-tool/openapi.json
  2. +192
    -6
      matsen-tool/openapi.yaml
  3. +1
    -0
      matsen-tool/src/app/contacts/new-contact/new-contact.component.html
  4. +1
    -1
      matsen-tool/src/app/contacts/new-contact/new-contact.component.ts
  5. +55
    -35
      matsen-tool/src/app/home/home.component.html
  6. +141
    -5
      matsen-tool/src/app/home/home.component.ts
  7. +1
    -0
      matsen-tool/src/app/partners/new-partner/new-partner.component.html
  8. +1
    -1
      matsen-tool/src/app/partners/new-partner/new-partner.component.ts
  9. +1
    -0
      matsen-tool/src/app/products/new-product/new-product.component.html
  10. +1
    -1
      matsen-tool/src/app/products/new-product/new-product.component.ts
  11. +0
    -7
      matsen-tool/src/app/tasks/new-task/new-task.component.ts
  12. +1
    -2
      matsen-tool/src/app/tasks/tasks.component.ts
  13. +4
    -2
      matsen-tool/src/assets/i18n/de.json
  14. +17
    -4
      matsen-tool/src/assets/scss/_form.scss
  15. +1
    -0
      matsen-tool/src/assets/scss/_variables.scss
  16. +1
    -0
      matsen-tool/src/styles.scss

+ 1
- 1
matsen-tool/openapi.json
Dosya farkı çok büyük olduğundan ihmal edildi
Dosyayı Görüntüle


+ 192
- 6
matsen-tool/openapi.yaml Dosyayı Görüntüle

@@ -659,6 +659,12 @@ paths:
schema:
type: object
properties:
name:
type: string
required: true
description:
type: text
required: true
file:
type: string
format: binary
@@ -738,9 +744,9 @@ paths:
allowReserved: false
deprecated: false
parameters: []
/api/medias:
/api/media:
get:
operationId: api_medias_get_collection
operationId: api_media_get_collection
tags:
- Media
responses:
@@ -811,7 +817,7 @@ paths:
allowReserved: false
deprecated: false
post:
operationId: api_medias_post
operationId: api_media_post
tags:
- Media
responses:
@@ -851,9 +857,9 @@ paths:
required: false
deprecated: false
parameters: []
'/api/medias/{id}':
'/api/media/{id}':
get:
operationId: api_medias_id_get
operationId: api_media_id_get
tags:
- Media
responses:
@@ -891,7 +897,7 @@ paths:
allowReserved: false
deprecated: false
delete:
operationId: api_medias_id_delete
operationId: api_media_id_delete
tags:
- Media
responses:
@@ -3523,12 +3529,36 @@ components:
externalDocs:
url: 'https://schema.org/MediaObject'
properties:
createdBy:
$ref: '#/components/schemas/User-document_object.read'
name:
type: string
description:
type:
- string
- 'null'
partner:
anyOf:
-
$ref: '#/components/schemas/Partner-document_object.read'
-
type: 'null'
product:
anyOf:
-
$ref: '#/components/schemas/Product-document_object.read'
-
type: 'null'
contentUrl:
externalDocs:
url: 'https://schema.org/contentUrl'
type:
- string
- 'null'
createdAt:
readOnly: true
type: string
format: date-time
Document.jsonhal-document_object.read:
type: object
description: ''
@@ -3545,12 +3575,36 @@ components:
href:
type: string
format: iri-reference
createdBy:
$ref: '#/components/schemas/User.jsonhal-document_object.read'
name:
type: string
description:
type:
- string
- 'null'
partner:
anyOf:
-
$ref: '#/components/schemas/Partner.jsonhal-document_object.read'
-
type: 'null'
product:
anyOf:
-
$ref: '#/components/schemas/Product.jsonhal-document_object.read'
-
type: 'null'
contentUrl:
externalDocs:
url: 'https://schema.org/contentUrl'
type:
- string
- 'null'
createdAt:
readOnly: true
type: string
format: date-time
Document.jsonld-document_object.read:
type: object
description: ''
@@ -3581,12 +3635,36 @@ components:
'@type':
readOnly: true
type: string
createdBy:
$ref: '#/components/schemas/User.jsonld-document_object.read'
name:
type: string
description:
type:
- string
- 'null'
partner:
anyOf:
-
$ref: '#/components/schemas/Partner.jsonld-document_object.read'
-
type: 'null'
product:
anyOf:
-
$ref: '#/components/schemas/Product.jsonld-document_object.read'
-
type: 'null'
contentUrl:
externalDocs:
url: 'https://schema.org/contentUrl'
type:
- string
- 'null'
createdAt:
readOnly: true
type: string
format: date-time
Media-media_object.read:
type: object
description: ''
@@ -3729,6 +3807,10 @@ components:
type: string
format: iri-reference
example: 'https://example.com/'
Partner-document_object.read:
type: object
description: ''
deprecated: false
Partner.jsonhal:
type: object
description: ''
@@ -3809,6 +3891,10 @@ components:
type: string
format: iri-reference
example: 'https://example.com/'
Partner.jsonhal-document_object.read:
type: object
description: ''
deprecated: false
Partner.jsonld:
type: object
description: ''
@@ -3903,6 +3989,34 @@ components:
type: string
format: iri-reference
example: 'https://example.com/'
Partner.jsonld-document_object.read:
type: object
description: ''
deprecated: false
properties:
'@context':
readOnly: true
oneOf:
-
type: string
-
type: object
properties:
'@vocab':
type: string
hydra:
type: string
enum: ['http://www.w3.org/ns/hydra/core#']
required:
- '@vocab'
- hydra
additionalProperties: true
'@id':
readOnly: true
type: string
'@type':
readOnly: true
type: string
PartnerFollow:
type: object
description: ''
@@ -4433,6 +4547,10 @@ components:
- string
- 'null'
format: date-time
Product-document_object.read:
type: object
description: ''
deprecated: false
Product.jsonhal:
type: object
description: ''
@@ -4472,6 +4590,10 @@ components:
- string
- 'null'
format: date-time
Product.jsonhal-document_object.read:
type: object
description: ''
deprecated: false
Product.jsonld:
type: object
description: ''
@@ -4525,6 +4647,34 @@ components:
- string
- 'null'
format: date-time
Product.jsonld-document_object.read:
type: object
description: ''
deprecated: false
properties:
'@context':
readOnly: true
oneOf:
-
type: string
-
type: object
properties:
'@vocab':
type: string
hydra:
type: string
enum: ['http://www.w3.org/ns/hydra/core#']
required:
- '@vocab'
- hydra
additionalProperties: true
'@id':
readOnly: true
type: string
'@type':
readOnly: true
type: string
Sale:
type: object
description: ''
@@ -5356,6 +5506,10 @@ components:
- string
- 'null'
format: date-time
User-document_object.read:
type: object
description: ''
deprecated: false
User.jsonhal:
type: object
description: ''
@@ -5410,6 +5564,10 @@ components:
- string
- 'null'
format: date-time
User.jsonhal-document_object.read:
type: object
description: ''
deprecated: false
User.jsonld:
type: object
description: ''
@@ -5478,6 +5636,34 @@ components:
- string
- 'null'
format: date-time
User.jsonld-document_object.read:
type: object
description: ''
deprecated: false
properties:
'@context':
readOnly: true
oneOf:
-
type: string
-
type: object
properties:
'@vocab':
type: string
hydra:
type: string
enum: ['http://www.w3.org/ns/hydra/core#']
required:
- '@vocab'
- hydra
additionalProperties: true
'@id':
readOnly: true
type: string
'@type':
readOnly: true
type: string
responses: { }
parameters: { }
examples: { }


+ 1
- 0
matsen-tool/src/app/contacts/new-contact/new-contact.component.html Dosyayı Görüntüle

@@ -49,6 +49,7 @@
<div class="mb-3">
<div class="delete-image" (click)="onDeleteImage()">
<img *ngIf="contact.imageUrl !== null" src="{{contact.imageUrl}}" width="40" height="40" />
<p class="mb-0 ms-3">{{'system.delete-image' | translate}}</p>
</div>
</div>



+ 1
- 1
matsen-tool/src/app/contacts/new-contact/new-contact.component.ts Dosyayı Görüntüle

@@ -94,7 +94,7 @@ export class NewContactComponent implements OnInit {

onDeleteImage() {
let confirmMessage = "";
this.translateService.get('system.delete-image').subscribe((translation: string) => {
this.translateService.get('system.confirm-delete-image').subscribe((translation: string) => {
confirmMessage = translation;
});
const userConfirmed = window.confirm(confirmMessage);


+ 55
- 35
matsen-tool/src/app/home/home.component.html Dosyayı Görüntüle

@@ -32,7 +32,7 @@
</div>
</div>

<div class="container">
<div class="container mb-5">
<div class="row pt-4 pb-4 d-flex">
<div class="col d-flex">
<a class="card" routerLink="/products" routerLinkActive="active">
@@ -58,46 +58,66 @@
</div>
</div>

<div class="container spt-accordion">

<h2>Meine Aufgaben</h2>

<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>
</span>
<h2 class="m-0">Wichtige Info: Unbedingt melden!</h2>
<div class="container spt-container">
<div class="spt-accordion">
<div class="d-flex justify-content-between align-items-start">
<h2>{{'user.my' | translate}} {{'basic.tasks' | translate}}</h2>
<button class="btn btn-primary" (click)="openModalNewTask()">{{'basic.new-task' | translate}}</button>
</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>
<div class="tasks mb-3" *ngFor="let task of tasks">
<div class="card 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.partnerName}}</h3>
<span class="info d-flex position-absolute">
<span class="due-date">{{ task.dueAt | date:'dd.MM.YYYY HH:mm':'GMT+0000' }}</span>
<span class="importance" [attr.data-importance]="task.prio"></span>
</span>
<h2 class="m-0">{{task.headline}}</h2>
</div>
<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.assignedToName}}</p>
<span *ngIf="task.createdBy === user?.id" class="position-absolute bi bi-pencil p-2"
data-type="user-tool" data-action="edit" (click)="openModalEditTask(task)"></span>
</div>
</div>
</div>
<div *ngIf="task.id && taskNotesVisibility.get(task.id)">
<div class="card ms-5" *ngFor="let taskNote of task.taskNotes">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<p>{{ taskNote.createdAt | date:'dd.MM.YYYY HH:mm' }}</p>
<p>{{ taskNote.ownerName }}</p>
</div>
<div>
<p>{{ taskNote.message }}</p>
</div>
<span *ngIf="taskNote.owner === user?.id" class="position-absolute bi bi-pencil p-2"
data-type="user-tool" data-action="edit" (click)="openModalEditTaskNote(taskNote)"></span>
</div>
</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>
<div class="d-flex justify-content-end mt-1">
<span *ngIf="task.taskNotes?.length !== 0" role="button" class="badge bg-secondary p-2 me-2"
(click)="showTaskNotes(task)">
<ng-container *ngIf="task.id && taskNotesVisibility.get(task.id)">{{ 'basic.hide-comments' | translate }}</ng-container>
<ng-container *ngIf="task.id && !taskNotesVisibility.get(task.id)">{{ 'basic.show-comments' | translate }}</ng-container>
</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>
<span role="button" class="badge bg-secondary p-2" (click)="openModalNewTaskNote(task)">{{'basic.comment-it' | translate}}</span>
</div>
</div>
<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>

+ 141
- 5
matsen-tool/src/app/home/home.component.ts Dosyayı Görüntüle

@@ -1,15 +1,32 @@
import {Component, OnInit} from '@angular/core';
import {AfterViewInit, ChangeDetectorRef, Component, OnInit, ViewChild} from '@angular/core';

import {User} from '@app/_models';
import {AccountService} from '@app/_services';
import {Subscription} from "rxjs";
import {PostJsonld, PostService, UserJsonld, UserService} from "@app/core/api/v1";
import {
PostJsonld,
PostService,
TaskJsonld,
TaskNoteJsonld,
TaskService,
UserJsonld,
UserService
} from "@app/core/api/v1";
import {MatPaginator, MatPaginatorIntl, PageEvent} from "@angular/material/paginator";
import {NgbModal, NgbModalOptions} from "@ng-bootstrap/ng-bootstrap";
import {MatTableDataSource} from "@angular/material/table";
import {NewTaskComponent} from "@app/tasks/new-task/new-task.component";
import {ModalStatus} from "@app/_helpers/modal.states";
import {NewTaskNoteComponent} from "@app/tasks/new-task-note/new-task-note.component";
import {ApiConverter} from "@app/_helpers/api.converter";

@Component({
templateUrl: 'home.component.html',
styleUrl: 'home.component.scss'
})
export class HomeComponent implements OnInit {
export class HomeComponent implements OnInit, AfterViewInit {
@ViewChild(MatPaginator) tasksPaginator: MatPaginator;

protected user: User | null;
protected postSub: Subscription;
protected posts: Array<PostJsonld>;
@@ -19,10 +36,28 @@ export class HomeComponent implements OnInit {

protected userIsAdmin: boolean;

protected readonly ApiConverter = ApiConverter;

protected tasksSub: Subscription;
protected tasks: Array<TaskJsonld>;
protected tasksDataSource;
protected tasksLength: number;
protected tasksPageEvent: PageEvent;
protected tasksPageSize: number;
protected tasksPageIndex: number;

protected taskNotesVisibility: Map<string, boolean>;

protected modalOptions: NgbModalOptions = {
centered: true
};

constructor(
private modalService: NgbModal,
private accountService: AccountService,
private postService: PostService,
private userService: UserService
private userService: UserService,
private taskService: TaskService
) {
this.user = this.accountService.userValue;
// this.accountService.user.subscribe(x => this.user = x);
@@ -33,10 +68,19 @@ export class HomeComponent implements OnInit {
this.users = [];

this.userIsAdmin = false;

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.taskNotesVisibility = new Map<string, boolean>();
}

ngOnInit(): void {
console.log(this.user);
if (this.user) {
this.userIsAdmin = this.user.roles ? this.user.roles.includes('ROLE_ADMIN') : false;
}
@@ -51,5 +95,97 @@ export class HomeComponent implements OnInit {
this.users = data["hydra:member"];
}
);
this.getTasksData();
}

ngAfterViewInit() {
this.tasksDataSource.paginator = this.tasksPaginator;
}

getTasksData() {
console.log(this.user?.id);
this.tasksSub = this.taskService.tasksGetCollection(
this.tasksPageIndex + 1,
this.tasksPageSize,
"",
[],
this.user?.id
).subscribe(
data => {
this.tasks = data["hydra:member"];
this.tasksLength = Number(data["hydra:totalItems"]);
this.tasks.forEach(task => {
if (task.id) {
this.taskNotesVisibility.set(task.id, false);
}
});
console.log(this.tasks);
}
);
}

tasksHandlePageEvent(e: PageEvent) {
this.tasksPageEvent = e;
this.tasksLength = e.length;
this.tasksPageIndex = e.pageIndex.valueOf();
this.tasksPageSize = e.pageSize.valueOf();
this.getTasksData();
}

openModalNewTask() {
const modalRefTask = this.modalService.open(NewTaskComponent, this.modalOptions);
let task: TaskJsonld = {} as TaskJsonld;
task.partner = null;
task.completed = false;
modalRefTask.componentInstance.task = task;
modalRefTask.componentInstance.submit.subscribe((modalStatus: ModalStatus) => {
if (modalStatus === ModalStatus.Submitted) {
modalRefTask.dismiss();
this.getTasksData();
}
});
}

openModalNewTaskNote(task: TaskJsonld) {
const modalRefTaskNote = this.modalService.open(NewTaskNoteComponent, this.modalOptions);
let taskNote: TaskNoteJsonld = {} as TaskNoteJsonld;
taskNote.task = task.id ?? null;
modalRefTaskNote.componentInstance.taskNote = taskNote;
modalRefTaskNote.componentInstance.submit.subscribe((modalStatus: ModalStatus) => {
if (modalStatus === ModalStatus.Submitted) {
modalRefTaskNote.dismiss();
this.getTasksData();
}
});
}

openModalEditTask(task: TaskJsonld) {
const modalRefTaskEdit = this.modalService.open(NewTaskComponent, this.modalOptions);
modalRefTaskEdit.componentInstance.task = task;
modalRefTaskEdit.componentInstance.dueAtValue = ApiConverter.convertDate(task.dueAt);
modalRefTaskEdit.componentInstance.submit.subscribe((modalStatus: ModalStatus) => {
if (modalStatus === ModalStatus.Submitted) {
modalRefTaskEdit.dismiss();
this.getTasksData();
}
});
}

openModalEditTaskNote(taskNote: TaskNoteJsonld) {
const modalRefTaskNote = this.modalService.open(NewTaskNoteComponent, this.modalOptions);
modalRefTaskNote.componentInstance.taskNote = taskNote;
modalRefTaskNote.componentInstance.submit.subscribe((modalStatus: ModalStatus) => {
if (modalStatus === ModalStatus.Submitted) {
modalRefTaskNote.dismiss();
this.getTasksData();
}
});
}

showTaskNotes(task: TaskJsonld) {
if (task.id) {
const currentVisibility = this.taskNotesVisibility.get(task.id);
this.taskNotesVisibility.set(task.id, !currentVisibility);
}
}
}

+ 1
- 0
matsen-tool/src/app/partners/new-partner/new-partner.component.html Dosyayı Görüntüle

@@ -48,6 +48,7 @@
<div class="mb-3">
<div class="delete-image" (click)="onDeleteImage()">
<img *ngIf="partner.logoUrl !== null" src="{{partner.logoUrl}}" width="40" height="40" />
<p class="mb-0 ms-3">{{'system.delete-image' | translate}}</p>
</div>
</div>



+ 1
- 1
matsen-tool/src/app/partners/new-partner/new-partner.component.ts Dosyayı Görüntüle

@@ -99,7 +99,7 @@ export class NewPartnerComponent implements OnInit {

onDeleteImage() {
let confirmMessage = "";
this.translateService.get('system.delete-image').subscribe((translation: string) => {
this.translateService.get('system.confirm-delete-image').subscribe((translation: string) => {
confirmMessage = translation;
});
const userConfirmed = window.confirm(confirmMessage);


+ 1
- 0
matsen-tool/src/app/products/new-product/new-product.component.html Dosyayı Görüntüle

@@ -26,6 +26,7 @@
<div class="mb-3">
<div class="delete-image" (click)="onDeleteImage()">
<img *ngIf="product.imageUrl !== null" src="{{product.imageUrl}}" width="40" height="40" />
<p class="mb-0 ms-3">{{'system.delete-image' | translate}}</p>
</div>
</div>



+ 1
- 1
matsen-tool/src/app/products/new-product/new-product.component.ts Dosyayı Görüntüle

@@ -90,7 +90,7 @@ export class NewProductComponent implements OnInit {

onDeleteImage() {
let confirmMessage = "";
this.translateService.get('system.delete-image').subscribe((translation: string) => {
this.translateService.get('system.confirm-delete-image').subscribe((translation: string) => {
confirmMessage = translation;
});
const userConfirmed = window.confirm(confirmMessage);


+ 0
- 7
matsen-tool/src/app/tasks/new-task/new-task.component.ts Dosyayı Görüntüle

@@ -21,13 +21,6 @@ export class NewTaskComponent implements OnInit {
protected taskSub: Subscription;
protected dueAtValue: string;

protected users = [
{ id: '/api/users/63', name: 'Daniel Knudsen' },
{ id: '/api/users/64', name: 'Florian Eisenmenger' },
{ id: '/api/users/65', name: 'Francis Donielly' },
{ id: '/api/users/66', name: 'Jaylen Schmiett' },
];

constructor(
private taskService: TaskService,
private userService: UserService


+ 1
- 2
matsen-tool/src/app/tasks/tasks.component.ts Dosyayı Görüntüle

@@ -66,8 +66,7 @@ export class TasksComponent implements OnInit, AfterViewInit {
getTasksData() {
this.tasksSub = this.taskService.tasksGetCollection(
this.tasksPageIndex + 1,
this.tasksPageSize,
// TODO: User-ID muss übergeben werden können, damit man nur die Tasks bekommt, die einem User zugewiesen sind
this.tasksPageSize
).subscribe(
data => {
this.tasks = data["hydra:member"];


+ 4
- 2
matsen-tool/src/assets/i18n/de.json Dosyayı Görüntüle

@@ -1,7 +1,8 @@
{
"system":
{
"delete-image": "Möchten Sie das Bild wirklich löschen?"
"delete-image": "Bild löschen",
"confirm-delete-image": "Möchten Sie das Bild wirklich löschen?"
},
"basic":
{
@@ -44,7 +45,8 @@
},
"user":
{
"hello": "Hi"
"hello": "Hi",
"my": "Meine "
},
"overview":
{


+ 17
- 4
matsen-tool/src/assets/scss/_form.scss Dosyayı Görüntüle

@@ -1,10 +1,23 @@
.spt-form {
.delete-image {
width: 40px;
height: 40px;
display: flex;
justify-content: flex-start;
align-items: center;
cursor: pointer;
padding: 2px 0;
border-radius: 5px;
@include transition();
&:hover {
background: $color-matsen;
color: #fff;
}
img {
width: 100%;
height: auto;
width: 40px;
height: 40px;
object-fit: cover;
}
p {
margin: 0;
}
}
}

+ 1
- 0
matsen-tool/src/assets/scss/_variables.scss Dosyayı Görüntüle

@@ -0,0 +1 @@
$color-matsen: rgba(229,38,30,1);

+ 1
- 0
matsen-tool/src/styles.scss Dosyayı Görüntüle

@@ -1,5 +1,6 @@
/* You can add global styles to this file, and also importApi other style files */

@import "assets/scss/variables";
@import "assets/scss/mixins";
@import "assets/scss/basics";
@import "assets/scss/modal";


Yükleniyor…
İptal
Kaydet