diff --git a/src/app/folder/controllers/FolderController.php b/src/app/folder/controllers/FolderController.php index a7b42214ec4a7b8ad1743386cea8b6114861128e..4acc518cd91d2b74e2aabe51d9841e299e1e09c7 100755 --- a/src/app/folder/controllers/FolderController.php +++ b/src/app/folder/controllers/FolderController.php @@ -27,6 +27,7 @@ use Resource\controllers\ResController; use Resource\controllers\ResourceListController; use Resource\models\ResModel; use Resource\models\ResourceListModel; +use Resource\models\UserFollowedResourceModel; use Respect\Validation\Validator; use Slim\Http\Request; use Slim\Http\Response; @@ -337,7 +338,8 @@ class FolderController return $response->withStatus(204); } - public function folderSharing($args = []) { + public function folderSharing($args = []) + { $folder = FolderController::getScopeFolders(['login' => $GLOBALS['userId'], 'folderId' => $args['folderId'], 'edition' => true]); if (empty($folder[0])) { return false; @@ -462,7 +464,8 @@ class FolderController return true; } - public static function areChildrenInPerimeter(array $aArgs = []) { + public static function areChildrenInPerimeter(array $aArgs = []) + { $folder = FolderController::getScopeFolders(['login' => $GLOBALS['userId'], 'folderId' => $aArgs['folderId'], 'edition' => true]); if (empty($folder[0])) { return false; @@ -524,9 +527,7 @@ class FolderController $resIds = ResourceListController::getIdsWithOffsetAndLimit(['resources' => $rawResources, 'offset' => $queryParams['offset'], 'limit' => $queryParams['limit']]); - foreach ($rawResources as $resource) { - $allResources[] = $resource['res_id']; - } + $allResources = array_column($rawResources, 'res_id'); $formattedResources = []; if (!empty($resIds)) { @@ -564,11 +565,15 @@ class FolderController 'orderBy' => [$order] ]); + $followedResources = UserFollowedResourceModel::get(['select' => ['res_id'], 'where' => ['user_id = ?'], 'data' => [$GLOBALS['id']]]); + $followedResources = array_column($followedResources, 'res_id'); + $formattedResources = ResourceListController::getFormattedResources([ 'resources' => $resources, 'userId' => $GLOBALS['id'], 'attachments' => $attachments, - 'checkLocked' => false + 'checkLocked' => false, + 'trackedMails' => $followedResources, ]); } diff --git a/src/app/resource/controllers/UserFollowedResourceController.php b/src/app/resource/controllers/UserFollowedResourceController.php index 9d3388718c0b117522766beb741f84fd162b1846..0b0c805964e17b4e10f8ed1bdd0cdcc90f8a6ee9 100644 --- a/src/app/resource/controllers/UserFollowedResourceController.php +++ b/src/app/resource/controllers/UserFollowedResourceController.php @@ -14,7 +14,6 @@ namespace Resource\controllers; - use Attachment\models\AttachmentModel; use Basket\models\BasketModel; use Group\controllers\PrivilegeController; @@ -32,7 +31,7 @@ class UserFollowedResourceController { $body = $request->getParsedBody(); - if (!ResController::hasRightByResId(['resId' => $body['resources'], 'userId' => $GLOBALS['id']])){ + if (!ResController::hasRightByResId(['resId' => $body['resources'], 'userId' => $GLOBALS['id']])) { return $response->withStatus(403)->withJson(['errors' => 'Document out of perimeter']); } @@ -59,7 +58,7 @@ class UserFollowedResourceController { $body = $request->getParsedBody(); - if (!ResController::hasRightByResId(['resId' => $body['resources'], 'userId' => $GLOBALS['id']])){ + if (!ResController::hasRightByResId(['resId' => $body['resources'], 'userId' => $GLOBALS['id']])) { return $response->withStatus(403)->withJson(['errors' => 'Document out of perimeter']); } @@ -112,9 +111,7 @@ class UserFollowedResourceController $resIds = ResourceListController::getIdsWithOffsetAndLimit(['resources' => $rawResources, 'offset' => $queryParams['offset'], 'limit' => $queryParams['limit']]); - foreach ($rawResources as $resource) { - $allResources[] = $resource['res_id']; - } + $allResources = array_column($rawResources, 'res_id'); $formattedResources = []; if (!empty($resIds)) { diff --git a/src/frontend/app/folder/document-list/folder-document-list.component.html b/src/frontend/app/folder/document-list/folder-document-list.component.html index 46a7de5b9061704279adb6d38f5005aef3f5b37d..5e36f7cefe4b20ab3e8d53035857102077922912 100644 --- a/src/frontend/app/folder/document-list/folder-document-list.component.html +++ b/src/frontend/app/folder/document-list/folder-document-list.component.html @@ -3,7 +3,7 @@ [fixedInViewport]="appService.getViewMode()" [opened]="appService.getViewMode() ? false : true" autoFocus="false" style="overflow-x:hidden;" [ngStyle]="{'width': appService.getViewMode() ? '80%' : '350px'}"> <header-panel [snavLeft]="snav"></header-panel> - <menu-shortcut></menu-shortcut> + <menu-shortcut #menuShortcut></menu-shortcut> <menu-nav></menu-nav> <basket-home #basketHome [snavL]="snav"></basket-home> <mat-divider></mat-divider> @@ -101,6 +101,10 @@ (change)="toggleRes($event,row)" (click)="$event.stopPropagation();"> </mat-checkbox> </span> + <button mat-icon-button (click)="$event.stopPropagation();toggleMailTracking(row)" style="margin-left: -25px; color: #F99830" + [title]="row.mailTracking === true ? lang.untrackThisMail : lang.trackThisMail"> + <mat-icon [ngClass]="[row.mailTracking === true ? 'fas fa-star' : 'far fa-star']" style="margin-bottom: 5px;"></mat-icon> + </button> <span *ngIf="!appService.getViewMode()" style="cursor:pointer;" class="main-info-status"> <mat-icon *ngIf="row.isLocked !== true" title="{{row.statusLabel}}" diff --git a/src/frontend/app/folder/document-list/folder-document-list.component.ts b/src/frontend/app/folder/document-list/folder-document-list.component.ts index 1bc647a51be1a9bcee85dc4d54c6d1db661ad2f2..6e9dcfa7f4361a07d2d21c8cc5209e01c35712a5 100644 --- a/src/frontend/app/folder/document-list/folder-document-list.component.ts +++ b/src/frontend/app/folder/document-list/folder-document-list.component.ts @@ -23,6 +23,7 @@ import { FolderActionListComponent } from '../folder-action-list/folder-action-l import { FiltersListService } from '../../../service/filtersList.service'; import { trigger, transition, style, animate } from '@angular/animations'; import { FoldersService } from '../folders.service'; +import { MenuShortcutComponent } from '../../menu/menu-shortcut.component'; declare function $j(selector: any): any; @@ -98,6 +99,7 @@ export class FolderDocumentListComponent implements OnInit { @ViewChild('actionsListContext', { static: true }) actionsList: FolderActionListComponent; @ViewChild('appPanelList', { static: true }) appPanelList: PanelListComponent; + @ViewChild('menuShortcut', { static: true }) menuShortcut: MenuShortcutComponent; currentSelectedChrono: string = ''; @@ -306,7 +308,7 @@ export class FolderDocumentListComponent implements OnInit { Object.keys(element).forEach((key) => { if (key == 'statusImage' && element[key] == null) { element[key] = 'fa-question undefined'; - } else if ((element[key] == null || element[key] == '') && ['closingDate', 'countAttachments', 'countNotes', 'display'].indexOf(key) === -1) { + } else if ((element[key] == null || element[key] == '') && ['closingDate', 'countAttachments', 'countNotes', 'display', 'mailTracking'].indexOf(key) === -1) { element[key] = this.lang.undefined; } }); @@ -370,6 +372,27 @@ export class FolderDocumentListComponent implements OnInit { listTodrag() { return this.foldersService.getDragIds(); } + + toggleMailTracking(row: any) { + if (!row.mailTracking) { + this.http.post('../../rest/resources/follow', {resources: [row.resId]}).pipe( + tap(() => this.menuShortcut.nbResourcesFollowed++), + catchError((err: any) => { + this.notify.handleErrors(err); + return of(false); + }) + ).subscribe(); + } else { + this.http.request('DELETE', '../../rest/resources/unfollow', { body: { resources: [row.resId] } }).pipe( + tap(() => this.menuShortcut.nbResourcesFollowed--), + catchError((err: any) => { + this.notify.handleErrors(err); + return of(false); + }) + ).subscribe(); + } + row.mailTracking = !row.mailTracking; + } } export interface BasketList { folder: any; diff --git a/src/frontend/app/home/followed-list/followed-document-list.component.html b/src/frontend/app/home/followed-list/followed-document-list.component.html index da4fef07be0be9d1d5498be17ada4c618d6caee2..93a507ece2598898b32b29971769afdede6c868a 100644 --- a/src/frontend/app/home/followed-list/followed-document-list.component.html +++ b/src/frontend/app/home/followed-list/followed-document-list.component.html @@ -28,7 +28,7 @@ [listProperties]="this.listProperties" [snavR]="snav2" [totalRes]="allResInBasket.length" [selectedRes]="selectedRes" [routeDatas]="'/rest/followedResources/filters'" (toggleAllRes)="toggleAllRes($event)" (refreshEventAfterAction)="refreshDaoAfterAction()" - (refreshEvent)="refreshDao()" [title]="lang.searchMailInFolder"> + (refreshEvent)="refreshDao()" [title]="lang.searchTrackedMail"> </app-filters-tool> </div> </div> @@ -76,6 +76,10 @@ (change)="toggleRes($event,row)" (click)="$event.stopPropagation();"> </mat-checkbox> </span> + <button mat-icon-button (click)="$event.stopPropagation();unfollowMail(row)" style="margin-left: -25px; color: #F99830" + title="{{lang.untrackThisMail}}"> + <mat-icon class="fas fa-star" style="margin-bottom: 5px;"></mat-icon> + </button> <span *ngIf="!appService.getViewMode()" style="cursor:pointer;" class="main-info-status"> <mat-icon *ngIf="row.isLocked !== true" title="{{row.statusLabel}}" diff --git a/src/frontend/app/home/followed-list/followed-document-list.component.ts b/src/frontend/app/home/followed-list/followed-document-list.component.ts index be77d3d8255fd30c93f6a4afb3d75002c004c4a3..d854f6e8a1887b003e8b4697290b8bc0e5d104f2 100644 --- a/src/frontend/app/home/followed-list/followed-document-list.component.ts +++ b/src/frontend/app/home/followed-list/followed-document-list.component.ts @@ -22,6 +22,7 @@ import { FollowedActionListComponent } from '../followed-action-list/followed-ac import { FiltersListService } from '../../../service/filtersList.service'; import { trigger, transition, style, animate } from '@angular/animations'; import {MenuShortcutComponent} from "../../menu/menu-shortcut.component"; +import { FoldersService } from '../../folder/folders.service'; declare function $j(selector: any): any; @@ -115,7 +116,8 @@ export class FollowedDocumentListComponent implements OnInit { private notify: NotificationService, public overlay: Overlay, public viewContainerRef: ViewContainerRef, - public appService: AppService) { + public appService: AppService, + private foldersService: FoldersService) { $j("link[href='merged_css.php']").remove(); } @@ -265,7 +267,7 @@ export class FollowedDocumentListComponent implements OnInit { Object.keys(element).forEach((key) => { if (key == 'statusImage' && element[key] == null) { element[key] = 'fa-question undefined'; - } else if ((element[key] == null || element[key] == '') && ['closingDate', 'countAttachments', 'countNotes', 'display'].indexOf(key) === -1) { + } else if ((element[key] == null || element[key] == '') && ['closingDate', 'countAttachments', 'countNotes', 'display', 'mailTracking'].indexOf(key) === -1) { element[key] = this.lang.undefined; } }); @@ -326,7 +328,23 @@ export class FollowedDocumentListComponent implements OnInit { } listTodrag() { - // return this.foldersService.getDragIds(); + return this.foldersService.getDragIds(); + } + + unfollowMail(row: any) { + this.http.request('DELETE', '../../rest/resources/unfollow', { body: { resources: [row.resId] } }).pipe( + tap(() => { + this.menuShortcut.nbResourcesFollowed--; + this.initResultList(); + }), + catchError((err: any) => { + this.notify.handleErrors(err); + return of(false); + }) + ).subscribe(); + + row.mailTracking = !row.mailTracking; + } } export interface BasketList { diff --git a/src/frontend/lang/lang-en.ts b/src/frontend/lang/lang-en.ts index 76ff93e0bc46f9496979dac240be640bf16ca493..222ba0ea8812ff3d4fb362d04c842c6522ba0370 100755 --- a/src/frontend/lang/lang-en.ts +++ b/src/frontend/lang/lang-en.ts @@ -1374,5 +1374,6 @@ export const LANG_EN = { "notSavedBecauseInvalid": "Configuration not updated because some data are invalid", "deleteAll": "Delete all", "followedMail": "Followed mail(s)", - "stopFollowingAlert": "Do you want to stop following these mails ?" + "stopFollowingAlert": "Do you want to stop following these mails ?", + "searchTrackedMail": "Search in tracked mails" }; diff --git a/src/frontend/lang/lang-fr.ts b/src/frontend/lang/lang-fr.ts index 1448234504c7b3aeada1d32e79e5ea951e85cf00..962791204632d3ff7a219da30d055fe19f3d3be3 100755 --- a/src/frontend/lang/lang-fr.ts +++ b/src/frontend/lang/lang-fr.ts @@ -1414,5 +1414,6 @@ export const LANG_FR = { "notSavedBecauseInvalid": "La configuration n'a pas été mise à jour car des données sont invalides", "deleteAll": "Tout supprimer", "followedMail": "Courrier(s) suivi(s)", - "stopFollowingAlert": "Voulez-vous arrêter de suivre ce(s) courrier(s) ?" + "stopFollowingAlert": "Voulez-vous arrêter de suivre ce(s) courrier(s) ?", + "searchTrackedMail": "Rechercher dans les courriers suivis" }; diff --git a/src/frontend/lang/lang-nl.ts b/src/frontend/lang/lang-nl.ts index cb3b4c525cffa13dfce1b2614ffd1ceeba58eafd..5773a2c6f239f3da2b054ab1ee4c410357c695c6 100755 --- a/src/frontend/lang/lang-nl.ts +++ b/src/frontend/lang/lang-nl.ts @@ -1400,4 +1400,5 @@ export const LANG_NL = { "deleteAll": "Delete all", //_TO_TRANSLATE "followedMail": "Followed mail(s)", //_TO_TRANSLATE "stopFollowingAlert": "Do you want to stop following these mails ?", //_TO_TRANSLATE + "searchTrackedMail": "Search in tracked mails", //_TO_TRANSLATE };