Fix bugs
This commit is contained in:
parent
e96ac49c8e
commit
e992152a75
28 changed files with 289 additions and 79 deletions
|
|
@ -7,8 +7,8 @@
|
||||||
<!-- wrapper for easier styling -->
|
<!-- wrapper for easier styling -->
|
||||||
<app-select-add
|
<app-select-add
|
||||||
class="select"
|
class="select"
|
||||||
[options]="modalService.active.input"
|
[options]="modalService.active.input.options"
|
||||||
[default]="modalService.active.input[0]"
|
[default]="modalService.active.input.options[0]"
|
||||||
[alwaysDropShadow]="true"
|
[alwaysDropShadow]="true"
|
||||||
[onlyShadowBorder]="true"
|
[onlyShadowBorder]="true"
|
||||||
[placeholder]="'Tag this item…'"
|
[placeholder]="'Tag this item…'"
|
||||||
|
|
@ -24,10 +24,10 @@
|
||||||
<app-toggle
|
<app-toggle
|
||||||
[beforeText]="'This task hasn\'t been finished yet'"
|
[beforeText]="'This task hasn\'t been finished yet'"
|
||||||
[afterText]="'Goal already accomplished'"
|
[afterText]="'Goal already accomplished'"
|
||||||
[default]="false"
|
[default]="!modalService.active.input.isTask"
|
||||||
(value)="isDone = $event"
|
(value)="isDone = $event"
|
||||||
></app-toggle>
|
></app-toggle>
|
||||||
</div>
|
</div>
|
||||||
<!-- wrapper for easier styling -->
|
<!-- wrapper for easier styling -->
|
||||||
|
|
||||||
<button (click)="submit()">Create</button>
|
<button (click)="submit()" [disabled]="!selected">Create</button>
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,10 @@ export class CreateBlockComponent {
|
||||||
constructor(public modalService: ModalService) {}
|
constructor(public modalService: ModalService) {}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
|
if (!this.selected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.modalService.submit({
|
this.modalService.submit({
|
||||||
selected: this.selected,
|
selected: this.selected,
|
||||||
description: this.description,
|
description: this.description,
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<img
|
<img
|
||||||
*ngIf="isDragging"
|
[ngClass]="isDragging ? 'active' : ''"
|
||||||
src="assets/trash.svg"
|
src="assets/trash.svg"
|
||||||
alt="trashcan"
|
alt="trashcan"
|
||||||
(pointerenter)="trashEnter()"
|
(pointerenter)="trashEnter()"
|
||||||
|
|
@ -24,9 +24,9 @@
|
||||||
(pointerup)="removeTower()"
|
(pointerup)="removeTower()"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="double-slider-container">
|
<div class="double-slider-container" [ngStyle]="{ opacity: isDragging ? '0' : '1' }">
|
||||||
<app-double-slider
|
<app-double-slider
|
||||||
*ngIf="!isDragging && dates.length >= MIN_BLOCK_COUNT_BEFORE_SHOWING_SLIDER"
|
*ngIf="dates.length >= MIN_BLOCK_COUNT_BEFORE_SHOWING_SLIDER"
|
||||||
[values]="dates"
|
[values]="dates"
|
||||||
[labels]="dateLabels"
|
[labels]="dateLabels"
|
||||||
(lowerBound)="startDate = $event"
|
(lowerBound)="startDate = $event"
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
|
||||||
flex: 1 0 auto;
|
flex: 1 0 auto;
|
||||||
|
|
||||||
|
|
@ -28,7 +30,33 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@include inner-spacing(var(--medium-padding), $horizontal: true);
|
max-width: 800px;
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
max-width: 200px;
|
||||||
|
box-sizing: content-box;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
|
||||||
|
&:not(:nth-last-child(1)) {
|
||||||
|
margin-right: var(--medium-padding);
|
||||||
|
@media (max-width: $mobile-width) {
|
||||||
|
margin-right: var(--small-padding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
@for $i from 1 to 6 {
|
||||||
|
& > *:first-child:nth-last-child(#{$i}),
|
||||||
|
& > *:first-child:nth-last-child(#{$i}) ~ * {
|
||||||
|
width: calc((100% - (#{$i} - 1) * var(--medium-padding)) / #{$i});
|
||||||
|
|
||||||
|
@media (max-width: $mobile-width) {
|
||||||
|
width: calc((100% - (#{$i} - 1) * var(--small-padding)) / #{$i});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.double-slider-container {
|
.double-slider-container {
|
||||||
|
|
@ -38,16 +66,25 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
@include square(47.33333px);
|
@include square(48px);
|
||||||
padding: 47.3333px 0;
|
padding: 16px;
|
||||||
margin: auto;
|
|
||||||
|
|
||||||
position: relative;
|
position: absolute;
|
||||||
z-index: 1500;
|
z-index: 1500;
|
||||||
|
bottom: 8px;
|
||||||
|
left: 50%;
|
||||||
|
margin: 0 !important;
|
||||||
|
|
||||||
|
transform: translateX(-50%) scale(0);
|
||||||
|
|
||||||
transition: transform $long-animation-time;
|
transition: transform $long-animation-time;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
transform: translateX(-50%) scale(1);
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: scale(1.2);
|
transform: translateX(-50%) scale(1.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Component, Input } from '@angular/core';
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
import { Page } from '../../../model/page';
|
import { Page } from '../../../model/page';
|
||||||
import { ModalService } from '../../../services/modal.service';
|
import { ModalService } from '../../../services/modal.service';
|
||||||
import { DataService } from '../../../services/data.service';
|
import { DataService } from '../../../services/data.service';
|
||||||
|
|
@ -20,6 +20,8 @@ export class PageComponent {
|
||||||
this.updateDates();
|
this.updateDates();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Output() isDragHappening: EventEmitter<boolean> = new EventEmitter();
|
||||||
|
|
||||||
get page(): Page {
|
get page(): Page {
|
||||||
return this._page;
|
return this._page;
|
||||||
}
|
}
|
||||||
|
|
@ -59,11 +61,13 @@ export class PageComponent {
|
||||||
dropDrag(event: any) {
|
dropDrag(event: any) {
|
||||||
this.page.moveTower(event);
|
this.page.moveTower(event);
|
||||||
this.isDragging = false;
|
this.isDragging = false;
|
||||||
|
this.isDragHappening.emit(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
startDrag(id: number) {
|
startDrag(id: number) {
|
||||||
this.draggedTowerIndex = id;
|
this.draggedTowerIndex = id;
|
||||||
this.isDragging = true;
|
this.isDragging = true;
|
||||||
|
this.isDragHappening.emit(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
trashEnter() {
|
trashEnter() {
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,14 @@
|
||||||
<div class="container">
|
<div class="container {{ tasks.length > 0 ? 'show-hover' : '' }}">
|
||||||
<p class="header" (click)="isOpen = !isOpen">
|
<p class="header" (click)="isOpen = !isOpen">
|
||||||
{{ tasks.length == 0 ? 'no' : '' }}
|
|
||||||
<strong>
|
<strong>
|
||||||
{{ tasks.length == 0 ? '' : tasks.length }}
|
{{ tasks.length == 0 ? '' : tasks.length }}
|
||||||
</strong>
|
</strong>
|
||||||
{{ tasks.length == 1 ? 'task' : 'tasks' }}
|
{{ tasks.length == 0 ? '​' : tasks.length == 1 ? 'task' : 'tasks' }}
|
||||||
</p>
|
</p>
|
||||||
<div class="all-task" #allTask [ngStyle]="{ height: (isOpen ? allTask?.scrollHeight : 0) + 'px' }">
|
<div class="all-task" #allTask [ngStyle]="{ height: (isOpen ? allTask?.scrollHeight : 0) + 'px' }">
|
||||||
<p
|
<div class="task-container" *ngFor="let task of tasks" [ngStyle]="{ color: task.color.toString() }">
|
||||||
*ngFor="let task of tasks"
|
<div [ngStyle]="{ 'background-color': task.color.toString() }"></div>
|
||||||
(click)="handleClick(task)"
|
<p (click)="handleClick(task)" [innerText]="task.description ? task.description : 'unknown'"></p>
|
||||||
[innerText]="task.description ? task.description : 'unknown'"
|
</div>
|
||||||
></p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,20 @@
|
||||||
:host {
|
:host {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
z-index: 100000;
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
@include card();
|
@include card();
|
||||||
box-shadow: $shadow-border;
|
|
||||||
padding: var(--small-padding);
|
cursor: pointer;
|
||||||
margin: var(--small-padding);
|
transition: box-shadow $long-animation-time;
|
||||||
|
&.show-hover:hover {
|
||||||
|
box-shadow: $shadow-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
padding: calc(var(--small-padding) / 2);
|
||||||
|
margin: calc(var(--small-padding) / 2);
|
||||||
|
|
||||||
max-height: 30vh;
|
max-height: 30vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
@ -18,7 +26,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
width: 100%;
|
|
||||||
font-size: var(--medium-font-size);
|
font-size: var(--medium-font-size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -29,23 +36,43 @@
|
||||||
margin-top: var(--small-padding);
|
margin-top: var(--small-padding);
|
||||||
}
|
}
|
||||||
|
|
||||||
width: 100%;
|
height: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
transition: height $long-animation-time;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
|
|
||||||
height: 0;
|
.task-container {
|
||||||
transition: height $long-animation-time;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
p {
|
|
||||||
max-width: 60px;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow-x: hidden;
|
|
||||||
text-align: left;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
font-weight: bold;
|
p {
|
||||||
|
@media (min-width: $mobile-width) {
|
||||||
|
color: inherit !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
margin: 0 calc(var(--small-padding) / 2) 0 0;
|
||||||
|
@include square(var(--small-padding));
|
||||||
|
@media (max-width: $mobile-width) {
|
||||||
|
@include square(calc(var(--small-padding) / 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow-x: hidden;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
@media (max-width: $mobile-width) {
|
||||||
|
font-size: var(--small-font-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
|
||||||
import { Block } from '../../../../../model/block';
|
import { Block } from '../../../../../model/block';
|
||||||
import { Tower } from '../../../../../model/tower';
|
import { Tower } from '../../../../../model/tower';
|
||||||
import { ModalService } from '../../../../../services/modal.service';
|
import { ModalService } from '../../../../../services/modal.service';
|
||||||
|
import { CancelService } from '../../../../../services/cancel.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-tasks',
|
selector: 'app-tasks',
|
||||||
|
|
@ -12,11 +13,25 @@ export class TasksComponent implements OnInit {
|
||||||
@Input() tasks: Block[];
|
@Input() tasks: Block[];
|
||||||
@Input() tower: Tower;
|
@Input() tower: Tower;
|
||||||
|
|
||||||
@Input() isOpen = false;
|
private _isOpen = false;
|
||||||
|
@Input() set isOpen(value: boolean) {
|
||||||
|
if (value) {
|
||||||
|
this.cancelService.cancelAllExcept(this);
|
||||||
|
}
|
||||||
|
this._isOpen = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isOpen(): boolean {
|
||||||
|
return this._isOpen;
|
||||||
|
}
|
||||||
|
|
||||||
@ViewChild('allTask') allTask: ElementRef;
|
@ViewChild('allTask') allTask: ElementRef;
|
||||||
|
|
||||||
constructor(private modalService: ModalService) {}
|
constructor(private modalService: ModalService, private cancelService: CancelService) {
|
||||||
|
this.cancelService.subscribe(this, () => {
|
||||||
|
this.isOpen = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit() {}
|
ngOnInit() {}
|
||||||
|
|
||||||
|
|
@ -39,4 +54,16 @@ export class TasksComponent implements OnInit {
|
||||||
// pass
|
// pass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async addTask() {
|
||||||
|
try {
|
||||||
|
const { selected: tag, description, isDone } = await this.modalService.showCreateBlock({
|
||||||
|
options: this.tower.tags,
|
||||||
|
isTask: true
|
||||||
|
});
|
||||||
|
this.tower.addBlock({ tag, description, isDone });
|
||||||
|
} catch (e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
<input
|
<input
|
||||||
id="tower-name"
|
id="tower-name"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="…"
|
placeholder="name…"
|
||||||
[(ngModel)]="tower.name"
|
[(ngModel)]="tower.name"
|
||||||
[ngStyle]="{ color: tower.baseColor.toString() }"
|
[ngStyle]="{ color: tower.baseColor.toString() }"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,17 @@
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.cdk-drag-preview,
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@media (min-width: $mobile-width) {
|
||||||
|
div {
|
||||||
|
.container {
|
||||||
|
box-shadow: $shadow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.cdk-drag-preview {
|
||||||
div {
|
div {
|
||||||
.container {
|
.container {
|
||||||
box-shadow: $shadow;
|
box-shadow: $shadow;
|
||||||
|
|
@ -39,7 +48,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%;
|
max-width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
@include inner-spacing(var(--small-padding));
|
@include inner-spacing(var(--small-padding));
|
||||||
|
|
@ -52,7 +61,7 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
@include card();
|
@include card();
|
||||||
|
overflow: hidden;
|
||||||
transition: transform $short-animation-time, box-shadow $long-animation-time;
|
transition: transform $short-animation-time, box-shadow $long-animation-time;
|
||||||
|
|
||||||
@include inner-spacing(var(--medium-padding));
|
@include inner-spacing(var(--medium-padding));
|
||||||
|
|
@ -65,7 +74,7 @@
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 3;
|
z-index: 2;
|
||||||
|
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|
@ -85,9 +94,9 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
|
||||||
height: 56px;
|
height: 48px;
|
||||||
@media (max-width: $mobile-width) {
|
@media (max-width: $mobile-width) {
|
||||||
height: 42px;
|
height: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
opacity: 0.33;
|
opacity: 0.33;
|
||||||
|
|
@ -130,7 +139,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type='text'] {
|
input[type='text'] {
|
||||||
font-size: var(--medium-font-size);
|
font-size: var(--small-font-size);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@media (min-width: $mobile-width) {
|
@media (min-width: $mobile-width) {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Component, ElementRef, Input, ViewChild } from '@angular/core';
|
import { Component, Input } from '@angular/core';
|
||||||
import { Tower } from '../../../../model/tower';
|
import { Tower } from '../../../../model/tower';
|
||||||
import { ModalService } from '../../../../services/modal.service';
|
import { ModalService } from '../../../../services/modal.service';
|
||||||
import { Block } from '../../../../model/block';
|
import { Block } from '../../../../model/block';
|
||||||
|
|
@ -40,7 +40,10 @@ export class TowerComponent {
|
||||||
|
|
||||||
public async addBlock() {
|
public async addBlock() {
|
||||||
try {
|
try {
|
||||||
const { selected: tag, description, isDone } = await this.modalService.showCreateBlock(this.tower.tags);
|
const { selected: tag, description, isDone } = await this.modalService.showCreateBlock({
|
||||||
|
options: this.tower.tags,
|
||||||
|
isTask: false
|
||||||
|
});
|
||||||
this.tower.addBlock({ tag, description, isDone });
|
this.tower.addBlock({ tag, description, isDone });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// pass
|
// pass
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,12 @@
|
||||||
|
|
||||||
<div class="page-container">
|
<div class="page-container">
|
||||||
<!-- wrapper for easier styling -->
|
<!-- wrapper for easier styling -->
|
||||||
<app-page *ngIf="dataService.active !== null" [page]="dataService.active"></app-page>
|
<app-page
|
||||||
|
*ngIf="dataService.active !== null"
|
||||||
|
[page]="dataService.active"
|
||||||
|
(isDragHappening)="isDragHappening = $event"
|
||||||
|
></app-page>
|
||||||
</div>
|
</div>
|
||||||
<!-- wrapper for easier styling -->
|
<!-- wrapper for easier styling -->
|
||||||
|
|
||||||
<button (click)="openSettings()">Settings</button>
|
<button [ngClass]="isDragHappening ? 'transparent' : ''" (click)="openSettings()">Settings</button>
|
||||||
|
|
|
||||||
|
|
@ -18,4 +18,12 @@
|
||||||
.page-container {
|
.page-container {
|
||||||
flex: 1 0 auto;
|
flex: 1 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
transition: opacity $long-animation-time;
|
||||||
|
|
||||||
|
&.transparent {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ export class PagesComponent {
|
||||||
@ViewChild('page') page: ElementRef;
|
@ViewChild('page') page: ElementRef;
|
||||||
@ViewChild('bottom') bottom: ElementRef;
|
@ViewChild('bottom') bottom: ElementRef;
|
||||||
|
|
||||||
|
isDragHappening = false;
|
||||||
|
|
||||||
constructor(public dataService: DataService, private modalService: ModalService) {}
|
constructor(public dataService: DataService, private modalService: ModalService) {}
|
||||||
|
|
||||||
async selectPage(selected: string) {
|
async selectPage(selected: string) {
|
||||||
|
|
|
||||||
|
|
@ -37,11 +37,12 @@ $slider-size: 40px;
|
||||||
|
|
||||||
transition: box-shadow $long-animation-time, transform $long-animation-time;
|
transition: box-shadow $long-animation-time, transform $long-animation-time;
|
||||||
|
|
||||||
&:hover {
|
@media (min-width: $mobile-width) {
|
||||||
box-shadow: $shadow;
|
&:hover {
|
||||||
transform: translateY(-$slider-size / 2 + $line-height / 2) scale(1.1);
|
box-shadow: $shadow;
|
||||||
|
transform: translateY(-$slider-size / 2 + $line-height / 2) scale(1.1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,12 @@ export class DoubleSliderComponent {
|
||||||
|
|
||||||
this._values = values;
|
this._values = values;
|
||||||
this.calculateLabels();
|
this.calculateLabels();
|
||||||
|
if (this._oneValue > this._otherValue) {
|
||||||
|
this._oneValue = this.MAX - 1;
|
||||||
|
} else {
|
||||||
|
this._otherValue = this.MAX - 1;
|
||||||
|
}
|
||||||
|
|
||||||
this.emitValue();
|
this.emitValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -98,8 +98,10 @@ $inner-padding: var(--medium-padding);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.background {
|
@media (min-width: $mobile-width) {
|
||||||
box-shadow: $shadow;
|
.background {
|
||||||
|
box-shadow: $shadow;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { Component, Input, Output, EventEmitter, ViewChild, ElementRef } from '@angular/core';
|
import { Component, Input, Output, EventEmitter, ViewChild, ElementRef } from '@angular/core';
|
||||||
|
import { CancelService } from '../../../services/cancel.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-select-add',
|
selector: 'app-select-add',
|
||||||
|
|
@ -28,6 +29,12 @@ export class SelectAddComponent {
|
||||||
newOption: string;
|
newOption: string;
|
||||||
isOpen = false;
|
isOpen = false;
|
||||||
|
|
||||||
|
constructor(private cancelService: CancelService) {
|
||||||
|
this.cancelService.subscribe(this, () => {
|
||||||
|
this.isOpen = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
get otherOptions(): string[] {
|
get otherOptions(): string[] {
|
||||||
return this.options.filter(a => a !== this.selected);
|
return this.options.filter(a => a !== this.selected);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,11 @@ import { Color } from './color';
|
||||||
|
|
||||||
export class Block extends Base implements IBlock {
|
export class Block extends Base implements IBlock {
|
||||||
constructor(props: IBlock) {
|
constructor(props: IBlock) {
|
||||||
|
// TODO: remove
|
||||||
|
if (props.isDone === undefined) {
|
||||||
|
props.isDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
if (this.created.constructor.name !== 'Date') {
|
if (this.created.constructor.name !== 'Date') {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,11 @@ import { ITower } from '../interfaces/persistance/tower';
|
||||||
|
|
||||||
export class Page extends Base implements IPage {
|
export class Page extends Base implements IPage {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
// TODO: remove
|
||||||
|
if (!props.userData) {
|
||||||
|
props.userData = {};
|
||||||
|
}
|
||||||
|
|
||||||
super(props);
|
super(props);
|
||||||
// @ts-ignore to prevent update message
|
// @ts-ignore to prevent update message
|
||||||
this.__towers = this.towers.map(t => this.createTower(t));
|
this.__towers = this.towers.map(t => this.createTower(t));
|
||||||
|
|
@ -37,7 +42,6 @@ export class Page extends Base implements IPage {
|
||||||
do {
|
do {
|
||||||
hue = Math.random() * 360;
|
hue = Math.random() * 360;
|
||||||
} while (30 <= hue && hue <= 200);
|
} while (30 <= hue && hue <= 200);
|
||||||
console.log(hue);
|
|
||||||
|
|
||||||
this.towers.push(
|
this.towers.push(
|
||||||
this.createTower({
|
this.createTower({
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { Color } from './color';
|
||||||
import { Block } from './block';
|
import { Block } from './block';
|
||||||
import { Base } from './base';
|
import { Base } from './base';
|
||||||
import { IBlock } from '../interfaces/persistance/block';
|
import { IBlock } from '../interfaces/persistance/block';
|
||||||
import { hashCode } from '../utils/hash';
|
import { hash } from '../utils/hash';
|
||||||
|
|
||||||
export class Tower extends Base implements ITower {
|
export class Tower extends Base implements ITower {
|
||||||
constructor(props: ITower) {
|
constructor(props: ITower) {
|
||||||
|
|
@ -46,7 +46,7 @@ export class Tower extends Base implements ITower {
|
||||||
if (!this.tags.includes(block.tag)) {
|
if (!this.tags.includes(block.tag)) {
|
||||||
this.tags.push(block.tag);
|
this.tags.push(block.tag);
|
||||||
}
|
}
|
||||||
block.color = this.baseColor.lighten(hashCode(block.tag) * 50);
|
block.color = this.baseColor.lighten(hash(block.tag) * 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
super.update();
|
super.update();
|
||||||
|
|
|
||||||
30
src/app/services/cancel.service.ts
Normal file
30
src/app/services/cancel.service.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
interface Subscriber {
|
||||||
|
callback: () => void;
|
||||||
|
object: object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class CancelService {
|
||||||
|
private subscribers: Subscriber[] = [];
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
subscribe(object: object, callback: () => void) {
|
||||||
|
this.subscribers.push({
|
||||||
|
object,
|
||||||
|
callback
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelAllExcept(except: object) {
|
||||||
|
this.subscribers.filter(s => s.object !== except).map(s => s.callback());
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelAll() {
|
||||||
|
this.subscribers.map(s => s.callback());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Tower } from '../model/tower';
|
import { Tower } from '../model/tower';
|
||||||
import { top } from '../utils/top';
|
import { top } from '../utils/top';
|
||||||
|
import { CancelService } from './cancel.service';
|
||||||
|
|
||||||
export enum ModalType {
|
export enum ModalType {
|
||||||
createBlock,
|
createBlock,
|
||||||
|
|
@ -25,8 +26,13 @@ interface Modal {
|
||||||
export class ModalService {
|
export class ModalService {
|
||||||
private modalStack: Modal[] = [];
|
private modalStack: Modal[] = [];
|
||||||
|
|
||||||
showCreateBlock(options: string[]): Promise<{ selected: string; description: string; isDone: boolean }> {
|
constructor(private cancelService: CancelService) {}
|
||||||
return this.createPromiseAndPushToStack(options, ModalType.createBlock);
|
|
||||||
|
showCreateBlock(input: {
|
||||||
|
options: string[];
|
||||||
|
isTask: boolean;
|
||||||
|
}): Promise<{ selected: string; description: string; isDone: boolean }> {
|
||||||
|
return this.createPromiseAndPushToStack(input, ModalType.createBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
showEditBlock(data: {
|
showEditBlock(data: {
|
||||||
|
|
@ -65,6 +71,8 @@ export class ModalService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private createPromiseAndPushToStack(input: any, type: ModalType): Promise<any> {
|
private createPromiseAndPushToStack(input: any, type: ModalType): Promise<any> {
|
||||||
|
this.cancelService.cancelAll();
|
||||||
|
|
||||||
const modal = {
|
const modal = {
|
||||||
input,
|
input,
|
||||||
type,
|
type,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Page } from '../model/page';
|
import { Page } from '../model/page';
|
||||||
|
|
||||||
const LOCAL_STORAGE_KEY = 'life-towers.data.v.2.1';
|
const LOCAL_STORAGE_KEY = 'life-towers.data.v.2';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,8 @@
|
||||||
export const hashCode = (text: string) => {
|
export const hash = (text: string): number => {
|
||||||
let hash = 0;
|
// Return number between 0 and 1.
|
||||||
if (text.length == 0) {
|
if (!text) {
|
||||||
return hash;
|
return 0;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < text.length; i++) {
|
const hash = Array.prototype.reduce.call(text, (hash, char) => (hash << 5) - hash + char.charCodeAt(0), 7);
|
||||||
const char = text.charCodeAt(i);
|
return hash / (Math.pow(2, 32) - 1);
|
||||||
hash = (hash << 5) - hash + char;
|
|
||||||
hash = hash & hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
hash /= Math.pow(2, 32) - 1;
|
|
||||||
return hash;
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
$accent-color: #a2666f;
|
$accent-color: #a2666f;
|
||||||
$text-color: #5d576b;
|
$text-color: #5d576bff;
|
||||||
$light-color: #ffffff;
|
$light-color: #ffffff;
|
||||||
|
|
||||||
$background-gradient: linear-gradient(90deg, #fff9e077 0, #ffd6d677 100%);
|
$background-gradient: linear-gradient(90deg, #fff9e077 0, #ffd6d677 100%);
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,35 @@ button {
|
||||||
|
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: 0;
|
border: 0;
|
||||||
text-decoration: underline;
|
|
||||||
|
|
||||||
@include medium-text();
|
@include medium-text();
|
||||||
@include jump();
|
font-size: var(--large-font-size);
|
||||||
|
$height: 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom: solid $height #5d576b55;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
color: #5d576b55;
|
||||||
|
border-bottom: solid $height #5d576b33;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:disabled):hover {
|
||||||
|
&:after {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:after {
|
||||||
|
content: '';
|
||||||
|
width: 0;
|
||||||
|
height: $height;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: calc(-1 * #{$height});
|
||||||
|
background-color: $text-color;
|
||||||
|
transition: width 300ms;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
|
|
|
||||||
|
|
@ -60,3 +60,8 @@ img {
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue