mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-22 15:37:02 +00:00
434 lines
15 KiB
HTML
434 lines
15 KiB
HTML
<ng-container *ngIf="IS_TOUCH_ONLY">
|
|
<div #blockLeftEl class="block-left bg-400">
|
|
<mat-icon *ngIf="!task?.isDone">check</mat-icon>
|
|
<mat-icon *ngIf="task?.isDone">undo</mat-icon>
|
|
</div>
|
|
|
|
<div #blockRightEl class="block-right bg-400">
|
|
<ng-container *ngIf="(workContextService.isToday$|async)">
|
|
<mat-icon *ngIf="!(task?.repeatCfgId)">alarm</mat-icon>
|
|
<mat-icon *ngIf="(task?.repeatCfgId)" svgIcon="repeat"></mat-icon>
|
|
</ng-container>
|
|
<ng-container *ngIf="!(workContextService.isToday$|async)">
|
|
<mat-icon *ngIf="!task?.tagIds.includes(TODAY_TAG_ID)">wb_sunny</mat-icon>
|
|
<mat-icon
|
|
*ngIf="task?.tagIds.includes(TODAY_TAG_ID) && (task?.projectId || task?.tagIds?.length > 1)"
|
|
svgIcon="remove_today"
|
|
></mat-icon>
|
|
</ng-container>
|
|
</div>
|
|
</ng-container>
|
|
|
|
<div #innerWrapperEl class="inner-wrapper">
|
|
<div
|
|
#contextMenuTriggerEl
|
|
[matMenuTriggerFor]="contextMenu"
|
|
[style.left]="contextMenuPosition.x"
|
|
[style.top]="contextMenuPosition.y"
|
|
style="visibility: hidden; position: fixed"
|
|
></div>
|
|
|
|
<div
|
|
#projectMenuTriggerEl
|
|
[matMenuTriggerFor]="projectMenu"
|
|
style="visibility: hidden"
|
|
></div>
|
|
|
|
<div class="box"></div>
|
|
|
|
<!-- TODO only bind pan etc when touch is available-->
|
|
<div
|
|
(contextmenu)="openContextMenu($event)"
|
|
(panend)="onPanEnd()"
|
|
(panleft)="onPanLeft($event)"
|
|
(panright)="onPanRight($event)"
|
|
(panstart)="onPanStart($event)"
|
|
[class.isPreventPointerEventsWhilePanning]="isPreventPointerEventsWhilePanning"
|
|
class="first-line"
|
|
>
|
|
<button
|
|
(click)="toggleTaskDone()"
|
|
*ngIf="task?.isDone"
|
|
[title]="T.F.TASK.CMP.TOGGLE_DONE|translate"
|
|
class="check-done"
|
|
mat-icon-button
|
|
>
|
|
<mat-icon @swirl class="undo">undo </mat-icon>
|
|
<mat-icon @swirl class="check">check </mat-icon>
|
|
</button>
|
|
|
|
<div class="title-and-left-btns-wrapper">
|
|
<div
|
|
[class.handle-par]="!task?.parentId"
|
|
[class.handle-sub]="task?.parentId"
|
|
class="drag-handle"
|
|
>
|
|
<mat-icon class="drag-handle-ico" svgIcon="drag_handle"></mat-icon>
|
|
<mat-icon *ngIf="isCurrent" class="play-icon-indicator">play_arrow </mat-icon>
|
|
|
|
<div class="type-ico-wrapper">
|
|
<mat-icon
|
|
*ngIf="task?.repeatCfgId"
|
|
[style.transform]="isCurrent ? 'scale(1.4)': ''"
|
|
class="task-type-ico"
|
|
svgIcon="repeat"
|
|
>
|
|
</mat-icon>
|
|
|
|
<div *ngIf="task?.issueId" class="task-type-ico">
|
|
<div *ngIf="task?.issuePoints" class="mini-badge bgc-primary">
|
|
{{task?.issuePoints}}
|
|
</div>
|
|
<mat-icon [svgIcon]="task?.issueType|issueIcon"></mat-icon>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
(click)="IS_TOUCH_ONLY && toggleShowAdditionalInfoOpen()"
|
|
class="title-and-tags-wrapper"
|
|
>
|
|
<div class="parent-title" *ngIf="isShowParentTitle && task.parentId">
|
|
<div
|
|
class="dot"
|
|
*ngIf="(projectColor$|async) as projectColor"
|
|
[style.backgroundColor]="projectColor"
|
|
></div>
|
|
<div class="title">{{parentTitle$|async}}</div>
|
|
</div>
|
|
|
|
<div
|
|
#contentEditableOnClickEl
|
|
(editFinished)="updateTaskTitleIfChanged($event)"
|
|
[isResetAfterEdit]="true"
|
|
[value]="task?.title"
|
|
class="task-title show-only-on-no-touch-only"
|
|
contentEditableOnClick
|
|
contenteditable="true"
|
|
></div>
|
|
|
|
<div class="task-title show-only-on-touch-only">{{task?.title}}</div>
|
|
|
|
<tag-list *ngIf="!task?.parentId || isDev" [task]="task"></tag-list>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="all-controls-wrapper">
|
|
<div
|
|
(click)="estimateTime()"
|
|
[class.hasNoTimeSpentOrEstimate]="!task?.timeSpent && !task?.timeEstimate"
|
|
[class.isEditable]="!task?.subTasks?.length"
|
|
class="time-wrapper"
|
|
>
|
|
<div *ngIf="!task?.subTasks?.length" class="time">
|
|
<div class="time-val">
|
|
<span [innerHTML]="task?.timeSpent|msToString"></span>
|
|
</div>
|
|
<div class="separator">/</div>
|
|
<div [innerHTML]="task?.timeEstimate|msToString" class="time-val"></div>
|
|
</div>
|
|
|
|
<div *ngIf="task?.subTasks?.length" class="time">
|
|
<div class="time-val">
|
|
<span>∑</span>
|
|
<span [innerHTML]="task?.subTasks|subTaskTotalTimeSpent|msToString"></span>
|
|
</div>
|
|
<div class="separator">/</div>
|
|
<div
|
|
[innerHTML]="task?.subTasks|subTaskTotalTimeEstimate|msToString"
|
|
class="time-val"
|
|
></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="controls">
|
|
<div class="hover-controls">
|
|
<button
|
|
(click)="startTask()"
|
|
*ngIf="!task?.isDone && !isCurrent && !task?.subTasks?.length"
|
|
[title]="T.F.TASK.CMP.TRACK_TIME|translate"
|
|
class="ico-btn start-task-btn"
|
|
color=""
|
|
mat-icon-button
|
|
>
|
|
<mat-icon class="play-icon" svgIcon="play"></mat-icon>
|
|
</button>
|
|
|
|
<button
|
|
(click)="pauseTask()"
|
|
*ngIf="!task?.isDone && isCurrent && !task?.subTasks?.length"
|
|
[title]="T.F.TASK.CMP.TRACK_TIME_STOP|translate"
|
|
class="ico-btn"
|
|
color="accent"
|
|
mat-icon-button
|
|
>
|
|
<mat-icon>pause</mat-icon>
|
|
</button>
|
|
|
|
<button
|
|
(click)="addToMyDay()"
|
|
*ngIf="!task?.parentId && !task?.tagIds.includes(TODAY_TAG_ID)"
|
|
[title]="T.F.TASK.CMP.ADD_TO_MY_DAY|translate"
|
|
class="ico-btn"
|
|
color=""
|
|
mat-icon-button
|
|
>
|
|
<mat-icon>wb_sunny</mat-icon>
|
|
</button>
|
|
|
|
<button
|
|
(click)="removeFromMyDay()"
|
|
*ngIf="!task?.parentId && !task?.isDone && task?.tagIds.includes(TODAY_TAG_ID) && (task?.projectId || task?.tagIds?.length > 1)"
|
|
[title]="T.F.TASK.CMP.REMOVE_FROM_MY_DAY|translate"
|
|
class="ico-btn"
|
|
color=""
|
|
mat-icon-button
|
|
>
|
|
<mat-icon svgIcon="remove_today"></mat-icon>
|
|
</button>
|
|
|
|
<button
|
|
(click)="toggleTaskDone()"
|
|
[title]="T.F.TASK.CMP.TOGGLE_DONE|translate"
|
|
class="ico-btn task-done-btn"
|
|
color=""
|
|
mat-icon-button
|
|
>
|
|
<mat-icon *ngIf="task?.isDone">undo</mat-icon>
|
|
<mat-icon *ngIf="!task?.isDone">check</mat-icon>
|
|
</button>
|
|
|
|
<button
|
|
(click)="toggleShowAdditionalInfoOpen()"
|
|
*ngIf="!task?.notes&&!task?.issueId&&!isSelected"
|
|
[title]="T.F.TASK.CMP.TOGGLE_ADDITIONAL|translate"
|
|
class="ico-btn show-additional-info-btn"
|
|
color=""
|
|
mat-icon-button
|
|
>
|
|
<mat-icon *ngIf="!task?.issueWasUpdated">chat_bubble_outline</mat-icon>
|
|
<mat-icon *ngIf="task?.issueWasUpdated" color="accent">update </mat-icon>
|
|
</button>
|
|
</div>
|
|
|
|
<button
|
|
(click)="toggleShowAttachments()"
|
|
*ngIf="task?.attachments?.length || task?.issueAttachmentNr"
|
|
[title]="T.F.TASK.CMP.TOGGLE_ATTACHMENTS|translate"
|
|
class="ico-btn attachment-btn"
|
|
color=""
|
|
mat-icon-button
|
|
>
|
|
<mat-icon>attach_file</mat-icon>
|
|
</button>
|
|
|
|
<button
|
|
(click)="editReminder()"
|
|
*ngIf="task?.reminderId"
|
|
[title]="T.F.TASK.CMP.EDIT_REMINDER|translate"
|
|
class="ico-btn schedule-btn"
|
|
color=""
|
|
mat-icon-button
|
|
>
|
|
<mat-icon>alarm</mat-icon>
|
|
<div class="time-badge">{{task.plannedAt|shortPlannedAt}}</div>
|
|
</button>
|
|
|
|
<div>
|
|
<button
|
|
(click)="toggleShowAdditionalInfoOpen()"
|
|
*ngIf="task?.notes||task?.issueId||isSelected"
|
|
[title]="T.F.TASK.CMP.TOGGLE_ADDITIONAL|translate"
|
|
class="ico-btn show-additional-info-btn"
|
|
color=""
|
|
mat-icon-button
|
|
>
|
|
<mat-icon *ngIf="!task?.issueWasUpdated && !isSelected">chat</mat-icon>
|
|
<mat-icon *ngIf="!task?.issueWasUpdated && isSelected">close</mat-icon>
|
|
<mat-icon *ngIf="task?.issueWasUpdated" class="updated-icon" color="accent"
|
|
>update
|
|
</mat-icon>
|
|
</button>
|
|
</div>
|
|
|
|
<mat-menu #contextMenu="matMenu" (close)="focusSelf()">
|
|
<ng-template matMenuContent>
|
|
<button
|
|
(click)="startTask()"
|
|
*ngIf="IS_TOUCH_ONLY && !task?.isDone && !isCurrent && !task?.subTasks?.length"
|
|
mat-menu-item
|
|
>
|
|
<mat-icon class="play-icon" svgIcon="play"></mat-icon>
|
|
{{T.F.TASK.CMP.TRACK_TIME|translate}}
|
|
</button>
|
|
<button
|
|
(click)="pauseTask()"
|
|
*ngIf="IS_TOUCH_ONLY && !task?.isDone && isCurrent && !task?.subTasks?.length"
|
|
mat-menu-item
|
|
>
|
|
<mat-icon>pause</mat-icon>
|
|
{{T.F.TASK.CMP.TRACK_TIME_STOP|translate}}
|
|
</button>
|
|
|
|
<button
|
|
(click)="removeFromMyDay()"
|
|
*ngIf="IS_TOUCH_ONLY && !task?.parentId && !task?.isDone && task?.tagIds.includes(TODAY_TAG_ID) && (task?.projectId || task?.tagIds?.length > 1)"
|
|
mat-menu-item
|
|
>
|
|
<mat-icon svgIcon="remove_today"></mat-icon>
|
|
{{T.F.TASK.CMP.REMOVE_FROM_MY_DAY|translate}}
|
|
</button>
|
|
|
|
<button
|
|
(click)="estimateTime()"
|
|
*ngIf="!task?.subTasks?.length"
|
|
class="hide-xs"
|
|
mat-menu-item
|
|
>
|
|
<mat-icon>timer</mat-icon>
|
|
{{T.F.TASK.CMP.OPEN_TIME|translate}}
|
|
</button>
|
|
|
|
<button (click)="editReminder()" *ngIf="!task?.repeatCfgId" mat-menu-item>
|
|
<ng-container *ngIf="!task?.reminderId">
|
|
<mat-icon>alarm_add</mat-icon>
|
|
{{T.F.TASK.CMP.SCHEDULE|translate}}
|
|
</ng-container>
|
|
<ng-container *ngIf="task?.reminderId">
|
|
<mat-icon>alarm</mat-icon>
|
|
{{T.F.TASK.CMP.EDIT_REMINDER|translate}}
|
|
</ng-container>
|
|
</button>
|
|
|
|
<button
|
|
(click)="addSubTask();"
|
|
*ngIf="!task?.parentId&&!task?.isDone"
|
|
mat-menu-item
|
|
>
|
|
<mat-icon>playlist_add</mat-icon>
|
|
{{T.F.TASK.CMP.ADD_SUB_TASK|translate}}
|
|
</button>
|
|
|
|
<button (click)="addAttachment();" class="hide-xs" mat-menu-item>
|
|
<mat-icon>attachment</mat-icon>
|
|
{{T.F.TASK.CMP.OPEN_ATTACH|translate}}
|
|
</button>
|
|
|
|
<!--TODO maybe handle dynamically -->
|
|
<a
|
|
*ngIf="task?.issueId"
|
|
[href]="issueUrl$|async"
|
|
mat-menu-item
|
|
style="color: inherit"
|
|
target="_blank"
|
|
>
|
|
<mat-icon [svgIcon]="task?.issueType|issueIcon"></mat-icon>
|
|
{{T.F.TASK.CMP.OPEN_ISSUE|translate}}
|
|
</a>
|
|
|
|
<button (click)="updateIssueData()" *ngIf="task?.issueId" mat-menu-item>
|
|
<mat-icon>cloud_download</mat-icon>
|
|
{{T.F.TASK.CMP.UPDATE_ISSUE_DATA|translate}}
|
|
</button>
|
|
|
|
<button
|
|
(click)="moveToBacklog();"
|
|
*ngIf="!task?.parentId && !isBacklog && task?.projectId"
|
|
mat-menu-item
|
|
>
|
|
<mat-icon>arrow_downward</mat-icon>
|
|
{{T.F.TASK.CMP.MOVE_TO_BACKLOG|translate}}
|
|
</button>
|
|
|
|
<button
|
|
(click)="moveToToday();"
|
|
*ngIf="!task?.parentId && isBacklog && task?.projectId"
|
|
mat-menu-item
|
|
>
|
|
<mat-icon>arrow_upward</mat-icon>
|
|
{{T.F.TASK.CMP.MOVE_TO_TODAY|translate}}
|
|
</button>
|
|
|
|
<button (click)="editTags();" *ngIf="!task?.parentId" mat-menu-item>
|
|
<mat-icon>style</mat-icon>
|
|
{{T.F.TASK.CMP.EDIT_TAGS|translate}}
|
|
</button>
|
|
|
|
<button
|
|
*ngIf="!task?.parentId && !task?.issueId && !task?.repeatCfgId"
|
|
[matMenuTriggerFor]="projectMenu"
|
|
mat-menu-item
|
|
>
|
|
<mat-icon>forward</mat-icon>
|
|
{{(task?.projectId ? T.F.TASK.CMP.MOVE_TO_OTHER_PROJECT :
|
|
T.F.TASK.CMP.ADD_TO_PROJECT)|translate}}
|
|
</button>
|
|
|
|
<button *ngIf="task?.parentId" (click)="convertToMainTask()" mat-menu-item>
|
|
<mat-icon>subdirectory_arrow_left</mat-icon>
|
|
{{(T.F.TASK.CMP.CONVERT_TO_PARENT_TASK)|translate}}
|
|
</button>
|
|
|
|
<button (click)="deleteTask(true)" class="color-warn" mat-menu-item>
|
|
<mat-icon class="color-warn-i">delete_forever</mat-icon>
|
|
{{T.F.TASK.CMP.DELETE|translate}}
|
|
</button>
|
|
</ng-template>
|
|
</mat-menu>
|
|
|
|
<mat-menu #projectMenu="matMenu" (closed)="focusSelf()">
|
|
<ng-template matMenuContent>
|
|
<button
|
|
(click)="moveTaskToProject(project.id)"
|
|
*ngFor="let project of (moveToProjectList$|async); trackBy:trackByProjectId;"
|
|
mat-menu-item
|
|
>
|
|
{{project.title}}
|
|
</button>
|
|
</ng-template>
|
|
</mat-menu>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<progress-bar
|
|
*ngIf="isCurrent"
|
|
[cssClass]="'bg-accent'"
|
|
[progress]="progress"
|
|
></progress-bar>
|
|
|
|
<div *ngIf="task?.subTasks?.length" class="sub-tasks">
|
|
<button
|
|
(click)="toggleSubTaskMode()"
|
|
*ngIf="task?.subTasks?.length"
|
|
[title]="T.F.TASK.CMP.TOGGLE_SUB_TASK_VISIBILITY|translate"
|
|
class="toggle-sub-tasks-btn ico-btn mat-elevation-z2"
|
|
color=""
|
|
mat-mini-fab
|
|
>
|
|
<mat-icon *ngIf="(task?._showSubTasksMode===ShowSubTasksMode.HideAll)"
|
|
>add
|
|
</mat-icon>
|
|
<mat-icon
|
|
*ngIf="(task?._showSubTasksMode!==ShowSubTasksMode.HideAll)"
|
|
[class.isHideDoneTasks]="(task?._showSubTasksMode===ShowSubTasksMode.HideDone)"
|
|
>remove
|
|
</mat-icon>
|
|
</button>
|
|
<task-list
|
|
*ngIf="task?.subTasks?.length"
|
|
[@expand]
|
|
[isHideAll]="(task?._showSubTasksMode!==ShowSubTasksMode.Show)"
|
|
[isHideDone]="(task?._showSubTasksMode===ShowSubTasksMode.HideDone)"
|
|
[listModelId]="task?.id"
|
|
[parentId]="task?.id"
|
|
[tasks]="task?.subTasks"
|
|
listId="SUB"
|
|
></task-list>
|
|
</div>
|
|
|
|
<div *ngIf="isDragOver" class="bgc-accent drag-over-msg">
|
|
<mat-icon>add</mat-icon>
|
|
{{T.F.TASK.CMP.DROP_ATTACHMENT|translate:{title: task?.title} }}
|
|
</div>
|
|
</div>
|