Skip to content

Commit

Permalink
refactor: give simple task summary its own component
Browse files Browse the repository at this point in the history
  • Loading branch information
johannesjo committed Jan 13, 2019
1 parent 200defa commit 6e0c455
Show file tree
Hide file tree
Showing 9 changed files with 402 additions and 318 deletions.
Original file line number Diff line number Diff line change
@@ -1,161 +1,6 @@
<h2 mat-dialog-title="">Task List Export</h2>


<div class="dialog-content"
mat-dialog-content="">

<textarea [(ngModel)]="tasksTxt"
tabindex="-1"
name="tasksTxt"
rows="10"
id="task-textarea"
class="simple-textarea mat-elevation-z2"></textarea>


<section class="options">
<div class="row">
<div class="col">
<div class="md-caption"
style="margin: 10px 0;">Options
</div>
<div>
<mat-slide-toggle [(ngModel)]="options.isUseNewLine"
(change)="onOptionsChange()"
name="isUseNewLine"
aria-label="Add new line">
Add new line after task
</mat-slide-toggle>
</div>
<div>
<mat-slide-toggle [(ngModel)]="options.isListSubTasks"
(change)="onOptionsChange()"
name="isListSubTasks"
aria-label="List sub tasks">
List sub tasks
</mat-slide-toggle>
</div>
<div *ngIf="!isWorklogExport">
<mat-slide-toggle [(ngModel)]="options.isWorkedOnTodayOnly"
(change)="onOptionsChange()"
name="isWorkedOnTodayOnly"
aria-label="List worked on today tasks only">
List worked on today tasks only
</mat-slide-toggle>
</div>
<div *ngIf="!isWorklogExport">
<mat-slide-toggle [(ngModel)]="options.isListDoneOnly"
(change)="onOptionsChange()"
name="isListDoneOnly"
aria-label="List done tasks only">
List done tasks only
</mat-slide-toggle>
</div>
<mat-form-field class="md-block">
<label>Separate tasks by</label>
<input type="text"
matInput=""
(change)="onOptionsChange()"
name="separateBy"
[(ngModel)]="options.separateBy">
</mat-form-field>
</div>

<div class="col">
<div class="md-caption"
style="margin: 10px 0;">Fields to display
</div>
<div>
<mat-slide-toggle (change)="onOptionsChange()"
name="showTitle"
[(ngModel)]="options.isShowTitle"
aria-label="Title">
Title
</mat-slide-toggle>
</div>
<div>
<mat-slide-toggle (change)="onOptionsChange()"
name="showDate"
[(ngModel)]="options.isShowDate"
aria-label="Date">
Date
</mat-slide-toggle>
</div>
<div>
<mat-slide-toggle [(ngModel)]="options.isShowTimeSpent"
(change)="onOptionsChange()"
name="showTimeSpent"
aria-label="Time Spent">
Time Spent
</mat-slide-toggle>
</div>
<div>
<mat-slide-toggle [(ngModel)]="options.isShowTimeEstimate"
(change)="onOptionsChange()"
name="showTimeSpent"
aria-label="Time Estimate">
Time Estimate
</mat-slide-toggle>
</div>
<div>
<mat-slide-toggle [(ngModel)]="options.isTimesAsMilliseconds"
(change)="onOptionsChange()"
name="isTimeSpentAsMilliseconds"
[disabled]="!options.isShowTimeSpent"
aria-label="Show time as milliseconds">
Time as milliseconds
</mat-slide-toggle>
</div>
<mat-form-field class="md-block">
<label>Separate fields by</label>
<input type="text"
matInput=""
(change)="onOptionsChange()"
name="separateFieldsBy"
[(ngModel)]="options.separateFieldsBy">
</mat-form-field>
</div>
</div>

<div class="row">
<mat-form-field style="width: 100%">
<label>Regular Expression to remove</label>
<input type="text"
matInput=""
(change)="onOptionsChange()"
name="regExToRemove"
[(ngModel)]="options.regExToRemove">
<div class="validation-messages">
<div *ngIf="isInvalidRegEx"
class="error">Invalid Regular Expression
</div>
</div>
</mat-form-field>
</div>
</section>
</div>


<div mat-dialog-actions=""
align="end">
<button mat-raised-button=""
color="primary"
id="clipboard-btn"
data-clipboard-action="copy"
data-clipboard-target="#task-textarea">
<mat-icon>content_paste</mat-icon>
Copy to clipboard
</button>
<a mat-raised-button=""
color="primary"
[simpleDownload]="'tasks.txt'"
[simpleDownloadData]="tasksTxt">
<mat-icon>file_download</mat-icon>
Save to file
</a>
<button mat-raised-button=""
(click)="close()"
type="button">
<mat-icon>close</mat-icon>
Close
</button>
</div>
<simple-task-summary [isWorklogExport]="data.isWorklogExport"
[isShowClose]="true"
[tasks]="data.tasks"
(cancel)="close()"></simple-task-summary>
Original file line number Diff line number Diff line change
@@ -1,172 +1,24 @@
import { ChangeDetectionStrategy, Component, Inject, OnDestroy, OnInit } from '@angular/core';
import { msToString } from '../../../ui/duration/ms-to-string.pipe';
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
import { TaskWithSubTasks } from '../../tasks/task.model';
import { ProjectService } from '../../project/project.service';
import { Subscription } from 'rxjs';
import { SimpleSummarySettingsCopy } from '../../project/project.model';
import { SIMPLE_SUMMARY_DEFAULTS } from '../../project/project.const';
import Clipboard from 'clipboard';
import { SnackService } from '../../../core/snack/snack.service';
import { getWorklogStr } from '../../../util/get-work-log-str';

const CSV_EXPORT_SETTINGS = {
separateBy: '',
separateFieldsBy: ';',
isUseNewLine: true,
isListSubTasks: true,
isListDoneOnly: false,
isWorkedOnTodayOnly: true,
showTitle: true,
showTimeSpent: true,
isTimeSpentAsMilliseconds: true,
showDate: false
};

@Component({
selector: 'dialog-simple-task-summary',
templateUrl: './dialog-simple-task-summary.component.html',
styleUrls: ['./dialog-simple-task-summary.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DialogSimpleTaskSummaryComponent implements OnInit, OnDestroy {
export class DialogSimpleTaskSummaryComponent {
options: SimpleSummarySettingsCopy = SIMPLE_SUMMARY_DEFAULTS;
isInvalidRegEx: boolean;
tasksTxt: string;
isWorklogExport = this.data.isWorklogExport;

private _subs: Subscription = new Subscription();

constructor(
private _matDialogRef: MatDialogRef<DialogSimpleTaskSummaryComponent>,
@Inject(MAT_DIALOG_DATA) public data: any,
private _projectService: ProjectService,
private _snackService: SnackService,
) {
}

ngOnInit() {
this._subs.add(this._projectService.advancedCfg$.subscribe((val) => {
this.options = val.simpleSummarySettings;
this.tasksTxt = this._createTasksText(this.data.tasks);
}));

// dirty but good enough for now
const clipboard = new Clipboard('#clipboard-btn');
clipboard.on('success', (e: any) => {
this._snackService.open({
message: 'Copied to clipboard',
type: 'SUCCESS'
});
e.clearSelection();
});
}

ngOnDestroy() {
this._subs.unsubscribe();
}

close() {
this._matDialogRef.close();
}

onOptionsChange() {
this._projectService.updateSimpleSummarySettings(this._projectService.currentId, this.options);
}

private _formatTask(task) {
let taskTxt = '';
if (this.options.isShowDate) {
taskTxt += task.dateStr || getWorklogStr();
}

if (this.options.isShowTitle) {
taskTxt = this._addSeparator(taskTxt);
taskTxt += task.title;
}

if (this.options.isShowTimeSpent) {
taskTxt = this._addSeparator(taskTxt);

taskTxt += this.options.isTimesAsMilliseconds
? task.timeSpent
: msToString(task.timeSpent, false, true);
}

if (this.options.isShowTimeEstimate) {
taskTxt = this._addSeparator(taskTxt);

taskTxt += this.options.isTimesAsMilliseconds
? task.timeEstimate
: msToString(task.timeEstimate, false, true);
}

taskTxt += this.options.separateBy;
return taskTxt;
}

private _addSeparator(taskTxt) {
if (taskTxt.length > 0) {
taskTxt += this.options.separateFieldsBy;
}
return taskTxt;
}

private _createTasksText(tasks: TaskWithSubTasks[]) {
let tasksTxt = '';
const newLineSeparator = '\n';

if (tasks) {
for (let i = 0; i < tasks.length; i++) {
const task = tasks[i];
if (
(this.isWorklogExport)
|| (!this.options.isListDoneOnly || task.isDone)
&& (!this.options.isWorkedOnTodayOnly || this._checkIsWorkedOnToday(task))
) {
tasksTxt += this._formatTask(task);
if (this.options.isUseNewLine) {
tasksTxt += newLineSeparator;
}
}

if (this.options.isListSubTasks && task.subTasks && task.subTasks.length > 0) {
for (let j = 0; j < task.subTasks.length; j++) {
const subTask = task.subTasks[j];
if (
(!this.options.isListDoneOnly || subTask.isDone)
&& (!this.options.isWorkedOnTodayOnly || this._checkIsWorkedOnToday(subTask))) {
tasksTxt += this._formatTask(subTask);
if (this.options.isUseNewLine) {
tasksTxt += newLineSeparator;
}
}
}
}
}
}

// cut off last separator
tasksTxt = tasksTxt.substring(0, tasksTxt.length - this.options.separateBy.length);
if (this.options.isUseNewLine) {
tasksTxt = tasksTxt.substring(0, tasksTxt.length - newLineSeparator.length);
}

if (this.options.regExToRemove) {
this.isInvalidRegEx = false;
try {
const regEx = new RegExp(this.options.regExToRemove, 'g');
tasksTxt = tasksTxt.replace(regEx, '');
} catch (e) {
this.isInvalidRegEx = true;
}
}

return tasksTxt;
}

private _checkIsWorkedOnToday(task) {
const dateStr = getWorklogStr();
return !!task.timeSpentOnDay[dateStr];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { DialogSimpleTaskSummaryComponent } from './dialog-simple-task-summary/d
import { UiModule } from '../../ui/ui.module';
import { FormsModule } from '@angular/forms';
import { SnackModule } from '../../core/snack/snack.module';
import { SimpleTaskSummaryComponent } from './simple-task-summary/simple-task-summary.component';

@NgModule({
imports: [
Expand All @@ -12,8 +13,9 @@ import { SnackModule } from '../../core/snack/snack.module';
FormsModule,
SnackModule,
],
declarations: [DialogSimpleTaskSummaryComponent],
entryComponents: [DialogSimpleTaskSummaryComponent]
declarations: [DialogSimpleTaskSummaryComponent, SimpleTaskSummaryComponent],
entryComponents: [DialogSimpleTaskSummaryComponent],
exports: [SimpleTaskSummaryComponent],
})
export class SimpleTaskSummaryModule {
}

0 comments on commit 6e0c455

Please sign in to comment.