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"
|
||||
}
|
||||
],
|
||||
"optimization": false,
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"extractCss": true,
|
||||
|
|
@ -47,8 +47,8 @@
|
|||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
"maximumWarning": "20mb",
|
||||
"maximumError": "50mb"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,7 @@
|
|||
|
||||
<p>
|
||||
You are trying to remove
|
||||
<span [ngStyle]="{ color: modalService.active.input.baseColor | color }">{{
|
||||
modalService.active.input.name ? modalService.active.input.name : 'an unnamed tower'
|
||||
}}</span
|
||||
<span [ngStyle]="{ color: tower.baseColor | color }">{{ tower.name ? tower.name : 'an unnamed tower' }}</span
|
||||
>.
|
||||
</p>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { ModalService } from '../../../../services/modal.service';
|
||||
import { Tower } from '../../../../model/tower';
|
||||
|
||||
@Component({
|
||||
selector: 'app-remove-tower',
|
||||
|
|
@ -8,4 +9,6 @@ import { ModalService } from '../../../../services/modal.service';
|
|||
})
|
||||
export class RemoveTowerComponent {
|
||||
constructor(public modalService: ModalService) {}
|
||||
|
||||
tower: Tower = this.modalService.active.input;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@
|
|||
[beforeText]="'Hide create tower button'"
|
||||
[afterText]="'Show create tower button'"
|
||||
[default]="!page.userData.hideCreateTowerButton"
|
||||
(value)="page?.setHideCreateTowerButton(!$event)"
|
||||
(value)="page.setHideCreateTowerButton(!$event)"
|
||||
></app-toggle>
|
||||
</div>
|
||||
<!-- 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>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ModalService } from '../../../../services/modal.service';
|
||||
import { DataService } from '../../../../services/data.service';
|
||||
import { Page } from '../../../../model/page';
|
||||
|
|
@ -8,8 +8,10 @@ import { Page } from '../../../../model/page';
|
|||
templateUrl: './settings.component.html',
|
||||
styleUrls: ['./settings.component.scss']
|
||||
})
|
||||
export class SettingsComponent {
|
||||
constructor(public modalService: ModalService, public dataService: DataService) {
|
||||
export class SettingsComponent implements OnInit {
|
||||
constructor(public modalService: ModalService, public dataService: DataService) {}
|
||||
|
||||
ngOnInit() {
|
||||
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)">
|
||||
<app-tower
|
||||
*ngFor="let tower of page?.towers"
|
||||
[tower]="tower"
|
||||
[dateRange]="dateRange"
|
||||
*ngFor="let tower of towers"
|
||||
[tower$]="tower.asObservable()"
|
||||
[dateRange$]="dateRange"
|
||||
cdkDrag
|
||||
(cdkDragStarted)="startDrag(page.towers.indexOf(tower))"
|
||||
(cdkDragStarted)="startDrag(towers.indexOf(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>
|
||||
|
||||
<img
|
||||
[ngClass]="isDragging ? 'active' : ''"
|
||||
src="assets/trash.svg"
|
||||
alt="trashcan"
|
||||
class="trash"
|
||||
(pointerenter)="trashEnter()"
|
||||
(pointerleave)="trashExit()"
|
||||
(pointerup)="removeTower()"
|
||||
|
|
@ -26,7 +26,6 @@
|
|||
*ngIf="dates.length >= MIN_BLOCK_COUNT_BEFORE_SHOWING_SLIDER"
|
||||
[values]="dates"
|
||||
[labels]="dateLabels"
|
||||
(lowerBound)="startDate = $event"
|
||||
(upperBound)="endDate = $event"
|
||||
(range)="dateRange.next($event)"
|
||||
></app-double-slider>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -24,13 +24,31 @@
|
|||
|
||||
transition: box-shadow $short-animation-time;
|
||||
|
||||
max-width: 800px;
|
||||
|
||||
&.cdk-drop-list-dragging {
|
||||
*:not(.cdk-drag-placeholder) {
|
||||
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;
|
||||
|
|
@ -65,7 +83,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
img {
|
||||
img.trash {
|
||||
@include square(48px);
|
||||
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 { ModalService } from '../../../services/modal.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({
|
||||
selector: 'app-page',
|
||||
templateUrl: './page.component.html',
|
||||
styleUrls: ['./page.component.scss']
|
||||
})
|
||||
export class PageComponent {
|
||||
private _page: Page;
|
||||
@Input() set page(value: Page) {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
export class PageComponent implements OnInit {
|
||||
@Input() page$: Observable<Page>;
|
||||
private page: Page;
|
||||
|
||||
this._page = value;
|
||||
this.updateDates();
|
||||
}
|
||||
towers: Array<BehaviorSubject<Tower>> = [];
|
||||
|
||||
@Output() isDragHappening: EventEmitter<boolean> = new EventEmitter();
|
||||
|
||||
get page(): Page {
|
||||
return this._page;
|
||||
}
|
||||
|
||||
readonly MIN_BLOCK_COUNT_BEFORE_SHOWING_SLIDER = 3;
|
||||
readonly MIN_BLOCK_COUNT_BEFORE_SHOWING_SLIDER = 6;
|
||||
|
||||
isDragging = false;
|
||||
draggedTowerIndex: number;
|
||||
nearTrashcan = false;
|
||||
|
||||
dates: Date[] = [];
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
dateRange: Subject<Range<Date>> = new Subject<Range<Date>>();
|
||||
|
||||
get dateLabels(): string[] {
|
||||
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) {}
|
||||
|
||||
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) {
|
||||
this.page.moveTower(event);
|
||||
this.isDragging = false;
|
||||
|
|
@ -88,10 +92,4 @@ export class PageComponent {
|
|||
// 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">
|
||||
<strong>
|
||||
{{ tasks.length == 0 ? '' : tasks.length }}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,20 @@
|
|||
<div class="tower">
|
||||
<div class="tower" *ngIf="tower$ | async">
|
||||
<div class="container">
|
||||
<div class="tasks-container">
|
||||
<app-tasks [tasks]="tasks" [tower]="tower"></app-tasks>
|
||||
<app-tasks [tasks]="tasks" [tower]="tower$ | async"></app-tasks>
|
||||
</div>
|
||||
|
||||
<img src="assets/plus-sign.svg" alt="add item" (click)="addBlock()" />
|
||||
|
||||
<div class="block-container-container">
|
||||
<div class="block-container falling">
|
||||
<app-block *ngFor="let block of drawableBlocks" [block]="block" [tower]="tower"></app-block>
|
||||
<div class="block-container" *ngIf="blocks.length > 0">
|
||||
<app-block
|
||||
[ngClass]="block.cssClass"
|
||||
[ngStyle]="block.style"
|
||||
*ngFor="let block of drawableBlocks"
|
||||
[block]="block"
|
||||
[tower]="tower$ | async"
|
||||
></app-block>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -19,6 +25,6 @@
|
|||
type="text"
|
||||
placeholder="name…"
|
||||
[(ngModel)]="towerName"
|
||||
[ngStyle]="{ color: tower?.baseColor | color }"
|
||||
[ngStyle]="{ color: (tower$ | async)?.baseColor | color }"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -121,23 +121,17 @@
|
|||
bottom: 0;
|
||||
width: 100%;
|
||||
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%);
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 1;
|
||||
.descend {
|
||||
transition: transform 1.5s cubic-bezier(0.5, 0, 1, 0), opacity 500ms cubic-bezier(0.5, 0, 1, 0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
.ascend {
|
||||
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 { 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({
|
||||
selector: 'app-tower',
|
||||
templateUrl: './tower.component.html',
|
||||
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 {
|
||||
return this.tower.name;
|
||||
return this.tower ? this.tower.name : 'Loading…';
|
||||
}
|
||||
|
||||
set towerName(value: string) {
|
||||
this.tower.changeName(value);
|
||||
}
|
||||
|
||||
@Input() set dateRange(value: { from: Date; to: Date }) {
|
||||
if (this.dateRange !== undefined && this.dateRange.from === value.from && this.dateRange.to === value.to) {
|
||||
return;
|
||||
}
|
||||
this._dateRange = value;
|
||||
}
|
||||
|
||||
get dateRange(): { from: Date; to: Date } {
|
||||
return this._dateRange;
|
||||
tasks: Array<ColoredBlock>;
|
||||
blocks: Array<StyledBlock> = [];
|
||||
get drawableBlocks(): Array<StyledBlock> {
|
||||
return this.blocks.filter(b => b.shouldDraw);
|
||||
}
|
||||
|
||||
public constructor(private modalService: ModalService) {}
|
||||
|
||||
get drawableBlocks(): Array<ColoredBlock> {
|
||||
return this.tower.coloredBlocks.filter(
|
||||
block => this.dateRange.from <= block.created && block.created <= this.dateRange.to && block.isDone
|
||||
);
|
||||
ngOnInit() {
|
||||
this.tower$.subscribe(value => {
|
||||
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> {
|
||||
return this.tower.coloredBlocks.filter(
|
||||
block => this.dateRange.from <= block.created && block.created <= this.dateRange.to && !block.isDone
|
||||
);
|
||||
this.tasks = value.coloredBlocks.filter(block => !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 };
|
||||
|
||||
isFalling = true;
|
||||
if ((block.cssClass === '' || block.cssClass === 'descend') && newDateRange.to < block.created) {
|
||||
block.cssClass = 'ascend';
|
||||
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() {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
<!-- wrapper for easier styling -->
|
||||
<app-select-add
|
||||
[options]="pageNames"
|
||||
[default]="selectedPageName"
|
||||
(value)="selectPage($event)"
|
||||
[default]="(selectedPage$ | async).name"
|
||||
(value)="selectedPageName = $event"
|
||||
[placeholder]="'Add a new page…'"
|
||||
></app-select-add>
|
||||
</div>
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
<div class="page-container">
|
||||
<!-- 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>
|
||||
<!-- wrapper for easier styling -->
|
||||
|
||||
|
|
|
|||
|
|
@ -27,19 +27,6 @@ export class PagesComponent {
|
|||
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) {
|
||||
window.localStorage.setItem(
|
||||
USER_DATA_KEY,
|
||||
|
|
@ -47,7 +34,8 @@ export class PagesComponent {
|
|||
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);
|
||||
|
|
@ -56,28 +44,22 @@ export class PagesComponent {
|
|||
constructor(public dataService: DataService, private modalService: ModalService) {
|
||||
const userData = JSON.parse(window.localStorage.getItem(USER_DATA_KEY));
|
||||
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) {
|
||||
this.pages = pages;
|
||||
if (!this.selectedPage) {
|
||||
this.selectedPageName = this.pages.length > 0 ? this.pages[0].name : null;
|
||||
if (!this._selectedPage.getValue() && this.pages.length > 0) {
|
||||
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() {
|
||||
try {
|
||||
await this.modalService.showSettings(this.selectedPage$);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { range } from '../../../utils/range';
|
||||
import { Range } from '../../../interfaces/range';
|
||||
|
||||
@Component({
|
||||
selector: 'app-double-slider',
|
||||
|
|
@ -49,8 +50,7 @@ export class DoubleSliderComponent {
|
|||
|
||||
private _values: any[];
|
||||
|
||||
@Output() lowerBound: EventEmitter<any> = new EventEmitter();
|
||||
@Output() upperBound: EventEmitter<any> = new EventEmitter();
|
||||
@Output() range: EventEmitter<Range<any>> = new EventEmitter();
|
||||
|
||||
drawnLabels: string[];
|
||||
|
||||
|
|
@ -93,12 +93,16 @@ export class DoubleSliderComponent {
|
|||
}
|
||||
|
||||
private emitValue() {
|
||||
if (this.oneValue < this.otherValue) {
|
||||
this.lowerBound.emit(this.values[this.indexFromValue(this.oneValue)]);
|
||||
this.upperBound.emit(this.values[this.indexFromValue(this.otherValue)]);
|
||||
} else {
|
||||
this.lowerBound.emit(this.values[this.indexFromValue(this.otherValue)]);
|
||||
this.upperBound.emit(this.values[this.indexFromValue(this.oneValue)]);
|
||||
}
|
||||
const range = {
|
||||
from:
|
||||
this.oneValue < this.otherValue
|
||||
? this.values[this.indexFromValue(this.oneValue)]
|
||||
: this.values[this.indexFromValue(this.otherValue)],
|
||||
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.newOption = '';
|
||||
}
|
||||
this.toggle();
|
||||
}
|
||||
|
||||
select(option: string) {
|
||||
this.selected = option;
|
||||
this.value.emit(this.selected);
|
||||
this.toggle();
|
||||
}
|
||||
|
||||
toggle() {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { ITower } from './tower';
|
||||
import { Range } from '../range';
|
||||
|
||||
export interface IPage {
|
||||
name: string;
|
||||
|
|
@ -6,9 +7,6 @@ export interface IPage {
|
|||
|
||||
userData: {
|
||||
hideCreateTowerButton?: boolean;
|
||||
defaultDateRange?: {
|
||||
from: Date;
|
||||
to: Date;
|
||||
};
|
||||
defaultDateRange?: Range<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
|
||||
}
|
||||
};
|
||||
|
||||
for (let page of pages) {
|
||||
new Page(this, page);
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.children$.subscribe(value => {
|
||||
this.log();
|
||||
});
|
||||
}, 0);
|
||||
|
||||
this.children$.subscribe(value => {
|
||||
this._safeChildren.next(value);
|
||||
this.save(0);
|
||||
});
|
||||
|
|
@ -60,11 +66,12 @@ export class DataService extends Root<Page> {
|
|||
}
|
||||
|
||||
addPage(name: string) {
|
||||
new Page(this, {
|
||||
const page = new Page(this, {
|
||||
name,
|
||||
userData: {},
|
||||
towers: []
|
||||
});
|
||||
page.addTower();
|
||||
}
|
||||
|
||||
removePage(page: Page) {
|
||||
|
|
|
|||
|
|
@ -49,13 +49,13 @@ export class StoreService<T> {
|
|||
isDone: false
|
||||
},
|
||||
{
|
||||
created: new Date(2020, 2, 15),
|
||||
created: new Date(2019, 3, 15),
|
||||
tag: 'go to school',
|
||||
description: 'done it',
|
||||
isDone: true
|
||||
},
|
||||
{
|
||||
created: new Date(2021, 2, 15),
|
||||
created: new Date(2019, 3, 15, 19),
|
||||
tag: 'go to school',
|
||||
isDone: false
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue