Add falling animation
This commit is contained in:
parent
938f3def1f
commit
db6a31dd85
20 changed files with 211 additions and 152 deletions
|
|
@ -35,7 +35,7 @@
|
||||||
"with": "src/environments/environment.prod.ts"
|
"with": "src/environments/environment.prod.ts"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"optimization": false,
|
"optimization": true,
|
||||||
"outputHashing": "all",
|
"outputHashing": "all",
|
||||||
"sourceMap": false,
|
"sourceMap": false,
|
||||||
"extractCss": true,
|
"extractCss": true,
|
||||||
|
|
@ -47,8 +47,8 @@
|
||||||
"budgets": [
|
"budgets": [
|
||||||
{
|
{
|
||||||
"type": "initial",
|
"type": "initial",
|
||||||
"maximumWarning": "2mb",
|
"maximumWarning": "20mb",
|
||||||
"maximumError": "5mb"
|
"maximumError": "50mb"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,7 @@
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
You are trying to remove
|
You are trying to remove
|
||||||
<span [ngStyle]="{ color: modalService.active.input.baseColor | color }">{{
|
<span [ngStyle]="{ color: tower.baseColor | color }">{{ tower.name ? tower.name : 'an unnamed tower' }}</span
|
||||||
modalService.active.input.name ? modalService.active.input.name : 'an unnamed tower'
|
|
||||||
}}</span
|
|
||||||
>.
|
>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { ModalService } from '../../../../services/modal.service';
|
import { ModalService } from '../../../../services/modal.service';
|
||||||
|
import { Tower } from '../../../../model/tower';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-remove-tower',
|
selector: 'app-remove-tower',
|
||||||
|
|
@ -8,4 +9,6 @@ import { ModalService } from '../../../../services/modal.service';
|
||||||
})
|
})
|
||||||
export class RemoveTowerComponent {
|
export class RemoveTowerComponent {
|
||||||
constructor(public modalService: ModalService) {}
|
constructor(public modalService: ModalService) {}
|
||||||
|
|
||||||
|
tower: Tower = this.modalService.active.input;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,11 @@
|
||||||
[beforeText]="'Hide create tower button'"
|
[beforeText]="'Hide create tower button'"
|
||||||
[afterText]="'Show create tower button'"
|
[afterText]="'Show create tower button'"
|
||||||
[default]="!page.userData.hideCreateTowerButton"
|
[default]="!page.userData.hideCreateTowerButton"
|
||||||
(value)="page?.setHideCreateTowerButton(!$event)"
|
(value)="page.setHideCreateTowerButton(!$event)"
|
||||||
></app-toggle>
|
></app-toggle>
|
||||||
</div>
|
</div>
|
||||||
<!-- wrapper for easier styling -->
|
<!-- wrapper for easier styling -->
|
||||||
|
|
||||||
<p *ngIf="page.towers?.length == 5">There can be a maximum of <strong>5</strong> towers on each page.</p>
|
<p *ngIf="page.towers.length == 5">There can be a maximum of <strong>5</strong> towers on each page.</p>
|
||||||
|
|
||||||
<button (click)="deletePage()">Delete current page</button>
|
<button (click)="deletePage()">Delete current page</button>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Component } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ModalService } from '../../../../services/modal.service';
|
import { ModalService } from '../../../../services/modal.service';
|
||||||
import { DataService } from '../../../../services/data.service';
|
import { DataService } from '../../../../services/data.service';
|
||||||
import { Page } from '../../../../model/page';
|
import { Page } from '../../../../model/page';
|
||||||
|
|
@ -8,8 +8,10 @@ import { Page } from '../../../../model/page';
|
||||||
templateUrl: './settings.component.html',
|
templateUrl: './settings.component.html',
|
||||||
styleUrls: ['./settings.component.scss']
|
styleUrls: ['./settings.component.scss']
|
||||||
})
|
})
|
||||||
export class SettingsComponent {
|
export class SettingsComponent implements OnInit {
|
||||||
constructor(public modalService: ModalService, public dataService: DataService) {
|
constructor(public modalService: ModalService, public dataService: DataService) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
this.modalService.active.input.subscribe(p => (this.page = p));
|
this.modalService.active.input.subscribe(p => (this.page = p));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
<button *ngIf="page && page.towers.length < 5 && !page.userData?.hideCreateTowerButton" (click)="page.addTower()">
|
|
||||||
Create tower
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<section class="towers" cdkDropList cdkDropListOrientation="horizontal" (cdkDropListDropped)="dropDrag($event)">
|
<section class="towers" cdkDropList cdkDropListOrientation="horizontal" (cdkDropListDropped)="dropDrag($event)">
|
||||||
<app-tower
|
<app-tower
|
||||||
*ngFor="let tower of page?.towers"
|
*ngFor="let tower of towers"
|
||||||
[tower]="tower"
|
[tower$]="tower.asObservable()"
|
||||||
[dateRange]="dateRange"
|
[dateRange$]="dateRange"
|
||||||
cdkDrag
|
cdkDrag
|
||||||
(cdkDragStarted)="startDrag(page.towers.indexOf(tower))"
|
(cdkDragStarted)="startDrag(towers.indexOf(tower))"
|
||||||
></app-tower>
|
></app-tower>
|
||||||
|
<div *ngIf="(page$ | async)?.towers.length < 5 && !(page$ | async)?.userData?.hideCreateTowerButton">
|
||||||
|
<img src="assets/plus-sign.svg" alt="add tower" class="add-tower" (click)="page.addTower()" />
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<img
|
<img
|
||||||
[ngClass]="isDragging ? 'active' : ''"
|
[ngClass]="isDragging ? 'active' : ''"
|
||||||
src="assets/trash.svg"
|
src="assets/trash.svg"
|
||||||
alt="trashcan"
|
alt="trashcan"
|
||||||
|
class="trash"
|
||||||
(pointerenter)="trashEnter()"
|
(pointerenter)="trashEnter()"
|
||||||
(pointerleave)="trashExit()"
|
(pointerleave)="trashExit()"
|
||||||
(pointerup)="removeTower()"
|
(pointerup)="removeTower()"
|
||||||
|
|
@ -26,7 +26,6 @@
|
||||||
*ngIf="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"
|
(range)="dateRange.next($event)"
|
||||||
(upperBound)="endDate = $event"
|
|
||||||
></app-double-slider>
|
></app-double-slider>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -24,13 +24,31 @@
|
||||||
|
|
||||||
transition: box-shadow $short-animation-time;
|
transition: box-shadow $short-animation-time;
|
||||||
|
|
||||||
|
max-width: 800px;
|
||||||
|
|
||||||
&.cdk-drop-list-dragging {
|
&.cdk-drop-list-dragging {
|
||||||
*:not(.cdk-drag-placeholder) {
|
*:not(.cdk-drag-placeholder) {
|
||||||
transition: transform $long-animation-time cubic-bezier(0, 0, 0.2, 1);
|
transition: transform $long-animation-time cubic-bezier(0, 0, 0.2, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
max-width: 800px;
|
div {
|
||||||
|
@include center-child();
|
||||||
|
img.add-tower {
|
||||||
|
height: 48px;
|
||||||
|
@media (max-width: $mobile-width) {
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
opacity: 0.33;
|
||||||
|
transition: opacity $long-animation-time;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
& > * {
|
& > * {
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
|
|
@ -65,7 +83,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img.trash {
|
||||||
@include square(48px);
|
@include square(48px);
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,58 +1,62 @@
|
||||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
import { Component, EventEmitter, Input, OnInit, 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';
|
||||||
|
import { Observable } from 'rxjs/internal/Observable';
|
||||||
|
import { Range } from '../../../interfaces/range';
|
||||||
|
import { Subject } from 'rxjs/internal/Subject';
|
||||||
|
import { Tower } from '../../../model/tower';
|
||||||
|
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-page',
|
selector: 'app-page',
|
||||||
templateUrl: './page.component.html',
|
templateUrl: './page.component.html',
|
||||||
styleUrls: ['./page.component.scss']
|
styleUrls: ['./page.component.scss']
|
||||||
})
|
})
|
||||||
export class PageComponent {
|
export class PageComponent implements OnInit {
|
||||||
private _page: Page;
|
@Input() page$: Observable<Page>;
|
||||||
@Input() set page(value: Page) {
|
private page: Page;
|
||||||
if (!value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._page = value;
|
towers: Array<BehaviorSubject<Tower>> = [];
|
||||||
this.updateDates();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Output() isDragHappening: EventEmitter<boolean> = new EventEmitter();
|
@Output() isDragHappening: EventEmitter<boolean> = new EventEmitter();
|
||||||
|
|
||||||
get page(): Page {
|
readonly MIN_BLOCK_COUNT_BEFORE_SHOWING_SLIDER = 6;
|
||||||
return this._page;
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly MIN_BLOCK_COUNT_BEFORE_SHOWING_SLIDER = 3;
|
|
||||||
|
|
||||||
isDragging = false;
|
isDragging = false;
|
||||||
draggedTowerIndex: number;
|
draggedTowerIndex: number;
|
||||||
nearTrashcan = false;
|
nearTrashcan = false;
|
||||||
|
|
||||||
dates: Date[] = [];
|
dates: Date[] = [];
|
||||||
startDate: Date;
|
dateRange: Subject<Range<Date>> = new Subject<Range<Date>>();
|
||||||
endDate: Date;
|
|
||||||
|
|
||||||
get dateLabels(): string[] {
|
get dateLabels(): string[] {
|
||||||
return this.dates.map(d => d.toLocaleDateString());
|
return this.dates.map(d => d.toLocaleDateString());
|
||||||
}
|
}
|
||||||
|
|
||||||
get dateRange(): { from: Date; to: Date } {
|
|
||||||
return this.dates.length >= this.MIN_BLOCK_COUNT_BEFORE_SHOWING_SLIDER
|
|
||||||
? {
|
|
||||||
from: this.startDate,
|
|
||||||
to: this.endDate
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
from: new Date(0, 0),
|
|
||||||
to: new Date(10000, 0)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(private modalService: ModalService, public dataService: DataService) {}
|
constructor(private modalService: ModalService, public dataService: DataService) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.page$.subscribe(value => {
|
||||||
|
if (value) {
|
||||||
|
this.towers = value.towers.map((t, index) => {
|
||||||
|
if (index < this.towers.length) {
|
||||||
|
if (this.towers[index].getValue() !== t) {
|
||||||
|
this.towers[index].next(t);
|
||||||
|
}
|
||||||
|
return this.towers[index];
|
||||||
|
}
|
||||||
|
return new BehaviorSubject(t);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.page = value;
|
||||||
|
this.dates = value.towers
|
||||||
|
.reduce((all, t) => [...t.blocks.map(b => b.created), ...all], [])
|
||||||
|
.sort((d1, d2) => d1.getTime() - d2.getTime());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
dropDrag(event: any) {
|
dropDrag(event: any) {
|
||||||
this.page.moveTower(event);
|
this.page.moveTower(event);
|
||||||
this.isDragging = false;
|
this.isDragging = false;
|
||||||
|
|
@ -88,10 +92,4 @@ export class PageComponent {
|
||||||
// pass
|
// pass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateDates() {
|
|
||||||
this.dates = this.page.towers
|
|
||||||
.reduce((all, t) => [...t.blocks.map(b => b.created), ...all], [])
|
|
||||||
.sort((d1, d2) => d1.getTime() - d2.getTime());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="container {{ tasks.length > 0 ? 'show-hover' : '' }}">
|
<div *ngIf="tasks" class="container {{ tasks.length > 0 ? 'show-hover' : '' }}">
|
||||||
<p class="header" (click)="isOpen = !isOpen">
|
<p class="header" (click)="isOpen = !isOpen">
|
||||||
<strong>
|
<strong>
|
||||||
{{ tasks.length == 0 ? '' : tasks.length }}
|
{{ tasks.length == 0 ? '' : tasks.length }}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,20 @@
|
||||||
<div class="tower">
|
<div class="tower" *ngIf="tower$ | async">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="tasks-container">
|
<div class="tasks-container">
|
||||||
<app-tasks [tasks]="tasks" [tower]="tower"></app-tasks>
|
<app-tasks [tasks]="tasks" [tower]="tower$ | async"></app-tasks>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<img src="assets/plus-sign.svg" alt="add item" (click)="addBlock()" />
|
<img src="assets/plus-sign.svg" alt="add item" (click)="addBlock()" />
|
||||||
|
|
||||||
<div class="block-container-container">
|
<div class="block-container-container">
|
||||||
<div class="block-container falling">
|
<div class="block-container" *ngIf="blocks.length > 0">
|
||||||
<app-block *ngFor="let block of drawableBlocks" [block]="block" [tower]="tower"></app-block>
|
<app-block
|
||||||
|
[ngClass]="block.cssClass"
|
||||||
|
[ngStyle]="block.style"
|
||||||
|
*ngFor="let block of drawableBlocks"
|
||||||
|
[block]="block"
|
||||||
|
[tower]="tower$ | async"
|
||||||
|
></app-block>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -19,6 +25,6 @@
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="name…"
|
placeholder="name…"
|
||||||
[(ngModel)]="towerName"
|
[(ngModel)]="towerName"
|
||||||
[ngStyle]="{ color: tower?.baseColor | color }"
|
[ngStyle]="{ color: (tower$ | async)?.baseColor | color }"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -121,23 +121,17 @@
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
transform: scaleY(-1);
|
transform: scaleY(-1);
|
||||||
&.falling > *:last-child {
|
|
||||||
animation: falling 1.5s cubic-bezier(0.5, 0, 1, 0) forwards;
|
|
||||||
|
|
||||||
@keyframes falling {
|
* {
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(500%);
|
transform: translateY(500%);
|
||||||
}
|
}
|
||||||
|
|
||||||
50% {
|
.descend {
|
||||||
opacity: 1;
|
transition: transform 1.5s cubic-bezier(0.5, 0, 1, 0), opacity 500ms cubic-bezier(0.5, 0, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
.ascend {
|
||||||
transform: translateY(0);
|
transition: transform 1.5s cubic-bezier(0.5, 0, 1, 0), opacity 500ms cubic-bezier(0.5, 0, 1, 0) 1s;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,51 +1,97 @@
|
||||||
import { Component, Input } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { ColoredBlock, Tower } from '../../../../model/tower';
|
import { ColoredBlock, Tower } from '../../../../model/tower';
|
||||||
import { ModalService } from '../../../../services/modal.service';
|
import { ModalService } from '../../../../services/modal.service';
|
||||||
|
import { Observable } from 'rxjs/internal/Observable';
|
||||||
|
import { Range } from '../../../../interfaces/range';
|
||||||
|
import { top } from '../../../../utils/top';
|
||||||
|
|
||||||
|
type StyledBlock = ColoredBlock & { style: { [p: string]: string }; shouldDraw: boolean; cssClass: string };
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-tower',
|
selector: 'app-tower',
|
||||||
templateUrl: './tower.component.html',
|
templateUrl: './tower.component.html',
|
||||||
styleUrls: ['./tower.component.scss']
|
styleUrls: ['./tower.component.scss']
|
||||||
})
|
})
|
||||||
export class TowerComponent {
|
export class TowerComponent implements OnInit {
|
||||||
|
@Input() dateRange$: Observable<Range<Date>>;
|
||||||
|
private dateRange: Range<Date>;
|
||||||
|
|
||||||
|
@Input() tower$: Observable<Tower>;
|
||||||
|
private tower: Tower;
|
||||||
|
|
||||||
get towerName(): string {
|
get towerName(): string {
|
||||||
return this.tower.name;
|
return this.tower ? this.tower.name : 'Loading…';
|
||||||
}
|
}
|
||||||
|
|
||||||
set towerName(value: string) {
|
set towerName(value: string) {
|
||||||
this.tower.changeName(value);
|
this.tower.changeName(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Input() set dateRange(value: { from: Date; to: Date }) {
|
tasks: Array<ColoredBlock>;
|
||||||
if (this.dateRange !== undefined && this.dateRange.from === value.from && this.dateRange.to === value.to) {
|
blocks: Array<StyledBlock> = [];
|
||||||
return;
|
get drawableBlocks(): Array<StyledBlock> {
|
||||||
}
|
return this.blocks.filter(b => b.shouldDraw);
|
||||||
this._dateRange = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
get dateRange(): { from: Date; to: Date } {
|
|
||||||
return this._dateRange;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public constructor(private modalService: ModalService) {}
|
public constructor(private modalService: ModalService) {}
|
||||||
|
|
||||||
get drawableBlocks(): Array<ColoredBlock> {
|
ngOnInit() {
|
||||||
return this.tower.coloredBlocks.filter(
|
this.tower$.subscribe(value => {
|
||||||
block => this.dateRange.from <= block.created && block.created <= this.dateRange.to && block.isDone
|
if (value) {
|
||||||
);
|
this.blocks = value.coloredBlocks
|
||||||
|
.filter(b => b.isDone)
|
||||||
|
.map(b => {
|
||||||
|
let classedBlock = b as StyledBlock;
|
||||||
|
classedBlock.shouldDraw = true;
|
||||||
|
classedBlock.style = { transform: 'translateY(0)', opacity: '1' };
|
||||||
|
classedBlock.cssClass = '';
|
||||||
|
return classedBlock;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.tower) {
|
||||||
|
let difference = this.tower.blocks.map((b, index) => {
|
||||||
|
return b === value.blocks[index];
|
||||||
|
});
|
||||||
|
|
||||||
|
if (
|
||||||
|
(difference.every(i => i) && this.tower.blocks.length < value.blocks.length) ||
|
||||||
|
this.tower.blocks.filter(b => b.isDone).length + 1 === value.blocks.filter(b => b.isDone).length
|
||||||
|
) {
|
||||||
|
const lastBlock = top(this.blocks);
|
||||||
|
if (lastBlock) {
|
||||||
|
lastBlock.style = { opacity: '0' };
|
||||||
|
lastBlock.cssClass = 'descend';
|
||||||
|
setTimeout(() => (lastBlock.style = { transform: 'translateY(0)', opacity: '1' }), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get tasks(): Array<ColoredBlock> {
|
this.tasks = value.coloredBlocks.filter(block => !block.isDone);
|
||||||
return this.tower.coloredBlocks.filter(
|
|
||||||
block => this.dateRange.from <= block.created && block.created <= this.dateRange.to && !block.isDone
|
this.tower = value;
|
||||||
);
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.dateRange$.subscribe(dateRange => {
|
||||||
|
this.initData(dateRange);
|
||||||
|
this.dateRange = dateRange;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Input() tower: Tower;
|
initData(newDateRange: Range<Date>) {
|
||||||
|
for (const block of this.blocks) {
|
||||||
|
block.shouldDraw = newDateRange.from <= block.created;
|
||||||
|
|
||||||
_dateRange: { from: Date; to: Date };
|
if ((block.cssClass === '' || block.cssClass === 'descend') && newDateRange.to < block.created) {
|
||||||
|
block.cssClass = 'ascend';
|
||||||
isFalling = true;
|
block.style = { transform: 'translateY(500%)', opacity: '0' };
|
||||||
|
}
|
||||||
|
if (block.shouldDraw && block.cssClass === 'ascend' && block.created < newDateRange.to) {
|
||||||
|
block.cssClass = 'descend';
|
||||||
|
block.style = { transform: 'translateY(0)', opacity: '1' };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async addBlock() {
|
public async addBlock() {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
<!-- wrapper for easier styling -->
|
<!-- wrapper for easier styling -->
|
||||||
<app-select-add
|
<app-select-add
|
||||||
[options]="pageNames"
|
[options]="pageNames"
|
||||||
[default]="selectedPageName"
|
[default]="(selectedPage$ | async).name"
|
||||||
(value)="selectPage($event)"
|
(value)="selectedPageName = $event"
|
||||||
[placeholder]="'Add a new page…'"
|
[placeholder]="'Add a new page…'"
|
||||||
></app-select-add>
|
></app-select-add>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
<div class="page-container">
|
<div class="page-container">
|
||||||
<!-- wrapper for easier styling -->
|
<!-- wrapper for easier styling -->
|
||||||
<app-page *ngIf="selectedPage" [page]="selectedPage" (isDragHappening)="isDragHappening = $event"></app-page>
|
<app-page [page$]="selectedPage$" (isDragHappening)="isDragHappening = $event"></app-page>
|
||||||
</div>
|
</div>
|
||||||
<!-- wrapper for easier styling -->
|
<!-- wrapper for easier styling -->
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,19 +27,6 @@ export class PagesComponent {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
get selectedPage(): Page {
|
|
||||||
try {
|
|
||||||
return this.pages[this.pageNames.indexOf(this.selectedPageName)];
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _selectedPageName: string;
|
|
||||||
get selectedPageName(): string {
|
|
||||||
return this._selectedPageName;
|
|
||||||
}
|
|
||||||
|
|
||||||
set selectedPageName(value: string) {
|
set selectedPageName(value: string) {
|
||||||
window.localStorage.setItem(
|
window.localStorage.setItem(
|
||||||
USER_DATA_KEY,
|
USER_DATA_KEY,
|
||||||
|
|
@ -47,7 +34,8 @@ export class PagesComponent {
|
||||||
selectedPage: value
|
selectedPage: value
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
this._selectedPageName = value;
|
const index = this.pageNames.indexOf(value);
|
||||||
|
this._selectedPage.next(index >= 0 ? this.pages[0] : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly _selectedPage: BehaviorSubject<Page> = new BehaviorSubject(null);
|
private readonly _selectedPage: BehaviorSubject<Page> = new BehaviorSubject(null);
|
||||||
|
|
@ -56,28 +44,22 @@ export class PagesComponent {
|
||||||
constructor(public dataService: DataService, private modalService: ModalService) {
|
constructor(public dataService: DataService, private modalService: ModalService) {
|
||||||
const userData = JSON.parse(window.localStorage.getItem(USER_DATA_KEY));
|
const userData = JSON.parse(window.localStorage.getItem(USER_DATA_KEY));
|
||||||
if (userData !== null && userData.selectedPage !== undefined) {
|
if (userData !== null && userData.selectedPage !== undefined) {
|
||||||
this._selectedPageName = userData.selectedPage;
|
this.selectedPageName = userData.selectedPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.dataService.safeChildren$.subscribe(pages => {
|
this.dataService.children$.subscribe(pages => {
|
||||||
if (pages) {
|
if (pages) {
|
||||||
this.pages = pages;
|
this.pages = pages;
|
||||||
if (!this.selectedPage) {
|
if (!this._selectedPage.getValue() && this.pages.length > 0) {
|
||||||
this.selectedPageName = this.pages.length > 0 ? this.pages[0].name : null;
|
this.selectedPageName = this.pages[0].name;
|
||||||
|
} else if (this._selectedPage.getValue()) {
|
||||||
|
// To trigger update on new page.
|
||||||
|
this.selectedPageName = this._selectedPage.getValue().name;
|
||||||
}
|
}
|
||||||
this._selectedPage.next(this.selectedPage);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async selectPage(selected: string) {
|
|
||||||
if (!this.pageNames.includes(selected)) {
|
|
||||||
this.dataService.addPage(selected);
|
|
||||||
}
|
|
||||||
this.selectedPageName = selected;
|
|
||||||
this._selectedPage.next(this.selectedPage);
|
|
||||||
}
|
|
||||||
|
|
||||||
async openSettings() {
|
async openSettings() {
|
||||||
try {
|
try {
|
||||||
await this.modalService.showSettings(this.selectedPage$);
|
await this.modalService.showSettings(this.selectedPage$);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
import { range } from '../../../utils/range';
|
import { range } from '../../../utils/range';
|
||||||
|
import { Range } from '../../../interfaces/range';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-double-slider',
|
selector: 'app-double-slider',
|
||||||
|
|
@ -49,8 +50,7 @@ export class DoubleSliderComponent {
|
||||||
|
|
||||||
private _values: any[];
|
private _values: any[];
|
||||||
|
|
||||||
@Output() lowerBound: EventEmitter<any> = new EventEmitter();
|
@Output() range: EventEmitter<Range<any>> = new EventEmitter();
|
||||||
@Output() upperBound: EventEmitter<any> = new EventEmitter();
|
|
||||||
|
|
||||||
drawnLabels: string[];
|
drawnLabels: string[];
|
||||||
|
|
||||||
|
|
@ -93,12 +93,16 @@ export class DoubleSliderComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
private emitValue() {
|
private emitValue() {
|
||||||
if (this.oneValue < this.otherValue) {
|
const range = {
|
||||||
this.lowerBound.emit(this.values[this.indexFromValue(this.oneValue)]);
|
from:
|
||||||
this.upperBound.emit(this.values[this.indexFromValue(this.otherValue)]);
|
this.oneValue < this.otherValue
|
||||||
} else {
|
? this.values[this.indexFromValue(this.oneValue)]
|
||||||
this.lowerBound.emit(this.values[this.indexFromValue(this.otherValue)]);
|
: this.values[this.indexFromValue(this.otherValue)],
|
||||||
this.upperBound.emit(this.values[this.indexFromValue(this.oneValue)]);
|
to:
|
||||||
}
|
this.oneValue < this.otherValue
|
||||||
|
? this.values[this.indexFromValue(this.otherValue)]
|
||||||
|
: this.values[this.indexFromValue(this.oneValue)]
|
||||||
|
};
|
||||||
|
this.range.emit(range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,12 +59,12 @@ export class SelectAddComponent {
|
||||||
this.select(this.newOption);
|
this.select(this.newOption);
|
||||||
this.newOption = '';
|
this.newOption = '';
|
||||||
}
|
}
|
||||||
|
this.toggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
select(option: string) {
|
select(option: string) {
|
||||||
this.selected = option;
|
this.selected = option;
|
||||||
this.value.emit(this.selected);
|
this.value.emit(this.selected);
|
||||||
this.toggle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle() {
|
toggle() {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { ITower } from './tower';
|
import { ITower } from './tower';
|
||||||
|
import { Range } from '../range';
|
||||||
|
|
||||||
export interface IPage {
|
export interface IPage {
|
||||||
name: string;
|
name: string;
|
||||||
|
|
@ -6,9 +7,6 @@ export interface IPage {
|
||||||
|
|
||||||
userData: {
|
userData: {
|
||||||
hideCreateTowerButton?: boolean;
|
hideCreateTowerButton?: boolean;
|
||||||
defaultDateRange?: {
|
defaultDateRange?: Range<Date>;
|
||||||
from: Date;
|
|
||||||
to: Date;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
src/app/interfaces/range.ts
Normal file
4
src/app/interfaces/range.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
export interface Range<T> {
|
||||||
|
from: T;
|
||||||
|
to: T;
|
||||||
|
}
|
||||||
|
|
@ -41,11 +41,17 @@ export class DataService extends Root<Page> {
|
||||||
childrenConstructor: null
|
childrenConstructor: null
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let page of pages) {
|
for (let page of pages) {
|
||||||
new Page(this, page);
|
new Page(this, page);
|
||||||
}
|
}
|
||||||
|
setTimeout(() => {
|
||||||
this.children$.subscribe(value => {
|
this.children$.subscribe(value => {
|
||||||
this.log();
|
this.log();
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
this.children$.subscribe(value => {
|
||||||
this._safeChildren.next(value);
|
this._safeChildren.next(value);
|
||||||
this.save(0);
|
this.save(0);
|
||||||
});
|
});
|
||||||
|
|
@ -60,11 +66,12 @@ export class DataService extends Root<Page> {
|
||||||
}
|
}
|
||||||
|
|
||||||
addPage(name: string) {
|
addPage(name: string) {
|
||||||
new Page(this, {
|
const page = new Page(this, {
|
||||||
name,
|
name,
|
||||||
userData: {},
|
userData: {},
|
||||||
towers: []
|
towers: []
|
||||||
});
|
});
|
||||||
|
page.addTower();
|
||||||
}
|
}
|
||||||
|
|
||||||
removePage(page: Page) {
|
removePage(page: Page) {
|
||||||
|
|
|
||||||
|
|
@ -49,13 +49,13 @@ export class StoreService<T> {
|
||||||
isDone: false
|
isDone: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
created: new Date(2020, 2, 15),
|
created: new Date(2019, 3, 15),
|
||||||
tag: 'go to school',
|
tag: 'go to school',
|
||||||
description: 'done it',
|
description: 'done it',
|
||||||
isDone: true
|
isDone: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
created: new Date(2021, 2, 15),
|
created: new Date(2019, 3, 15, 19),
|
||||||
tag: 'go to school',
|
tag: 'go to school',
|
||||||
isDone: false
|
isDone: false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue