Add rename page functionality

This commit is contained in:
Andras Schmelczer 2019-09-08 16:10:33 +02:00
parent 3101c973eb
commit 3a1accaae1
18 changed files with 201 additions and 63 deletions

View file

@ -1,2 +1,4 @@
<app-modal></app-modal>
<router-outlet></router-outlet>
<main (click)="cancelService.cancelAll()">
<app-modal></app-modal>
<router-outlet></router-outlet>
</main>

View file

@ -0,0 +1,3 @@
main {
height: 100%;
}

View file

@ -1,24 +1,18 @@
import { Component } from '@angular/core';
import { InnerNode, InnerNodeState } from './store/inner-node';
import { Root } from './store/root';
import { ChangeDetectionStrategy, Component, DoCheck } from '@angular/core';
import { CancelService } from './services/cancel.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
styleUrls: ['./app.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent {
export class AppComponent implements DoCheck {
title = 'life';
constructor() {
/*const rl = new InnerNode();
const rr = new InnerNode();
const l = new InnerNode();
const r = new InnerNode([rl, rr]);
const root = new Root<InnerNode>([l, r]);
root.log();
constructor(public cancelService: CancelService) {}
rr.changeKeys<InnerNodeState>({ dummy: 8 });
root.log();*/
ngDoCheck() {
console.log('app change detection');
}
}

View file

@ -1,9 +1,9 @@
<main class="{{ modalService.active ? 'active' : '' }}" [ngSwitch]="modalService.active?.type">
<app-create-block *ngSwitchCase="ModalType.createBlock"></app-create-block>
<app-edit-block *ngSwitchCase="ModalType.editBlock"></app-edit-block>
<app-remove-block *ngSwitchCase="ModalType.removeBlock"></app-remove-block>
<app-remove-tower *ngSwitchCase="ModalType.removeTower"></app-remove-tower>
<app-settings *ngSwitchCase="ModalType.settings"></app-settings>
<app-get-started *ngSwitchCase="ModalType.getStarted"></app-get-started>
<app-remove-page *ngSwitchCase="ModalType.removePage"></app-remove-page>
</main>
<section class="{{ modalService.active ? 'active' : '' }}" [ngSwitch]="modalService.active?.type">
<app-create-block (click)="$event.stopPropagation()" *ngSwitchCase="ModalType.createBlock"></app-create-block>
<app-edit-block (click)="$event.stopPropagation()" *ngSwitchCase="ModalType.editBlock"></app-edit-block>
<app-remove-block (click)="$event.stopPropagation()" *ngSwitchCase="ModalType.removeBlock"></app-remove-block>
<app-remove-tower (click)="$event.stopPropagation()" *ngSwitchCase="ModalType.removeTower"></app-remove-tower>
<app-settings (click)="$event.stopPropagation()" *ngSwitchCase="ModalType.settings"></app-settings>
<app-get-started (click)="$event.stopPropagation()" *ngSwitchCase="ModalType.getStarted"></app-get-started>
<app-remove-page (click)="$event.stopPropagation()" *ngSwitchCase="ModalType.removePage"></app-remove-page>
</section>

View file

@ -1,13 +1,13 @@
@import '../../../styles';
main {
section {
position: absolute;
top: 0;
left: 0;
z-index: 10000;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
z-index: 10000;
@include center-child();

View file

@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import { ChangeDetectorRef, Component } from '@angular/core';
import { ModalService, ModalType } from '../../services/modal.service';
@Component({
@ -7,14 +7,18 @@ import { ModalService, ModalType } from '../../services/modal.service';
styleUrls: ['./modal.component.scss']
})
export class ModalComponent {
// Needed for accessing the enum from html.
ModalType = ModalType;
constructor(public modalService: ModalService) {
constructor(public modalService: ModalService, private changeDetectionRef: ChangeDetectorRef) {
window.addEventListener('keydown', (event: KeyboardEvent) => {
if (event.key === 'Escape') {
this.modalService.cancel();
}
});
/*window.addEventListener('resize', (_: UIEvent) => {
console.log('resize');
this.changeDetectionRef.markForCheck();
});*/
}
}

View file

@ -2,7 +2,6 @@
:host {
@include card();
box-shadow: $shadow;
width: 66vw;
max-width: 400px;
@ -12,7 +11,9 @@
box-sizing: border-box;
padding: var(--large-padding);
position: relative;
box-shadow: $shadow;
@include inner-spacing(var(--large-padding));

View file

@ -4,7 +4,7 @@
@include card();
width: 66vw;
max-width: 500px;
max-width: 400px;
@media (max-width: $mobile-width) {
width: 300px;
}

View file

@ -4,7 +4,9 @@
[options]="pageNames"
[default]="(selectedPage$ | async)?.name"
(value)="selectPage($event)"
(optionChange)="changeName($event)"
[placeholder]="'Add a new page…'"
[editable]="true"
></app-select-add>
</div>
<!-- wrapper for easier styling -->

View file

@ -51,6 +51,16 @@ export class PagesComponent implements OnInit {
});
}
changeName({ from, to }: { from: string; to: string }) {
const page = this.pages.find(p => p.name === from);
if (page) {
page.changeName(to);
if (from === this.selectedPageName) {
this.selectPage(to);
}
}
}
selectPage(name: string) {
if (!name) {
if (this.pages && this.pages.length > 0) {

View file

@ -1,12 +1,30 @@
<div class="select-add {{ onlyShadowBorder ? 'shadow-border' : '' }}">
<div #top class="top" (click)="toggle()">
<p [innerHTML]="selected ? selected : placeholder"></p>
<img src="assets/arrow.svg" [className]="isOpen ? 'upside-down' : ''" alt="arrow" />
<div class="select-add {{ onlyShadowBorder ? 'shadow-border' : '' }}" (click)="$event.stopPropagation()">
<div #top class="top" (click)="!editMode && toggle()">
<p [innerHTML]="selected ? selected : placeholder" *ngIf="!editMode || !selected; else editableSelected"></p>
<ng-template #editableSelected>
<input type="text" [value]="selected" (change)="changeOption(selected, $event)" />
</ng-template>
<img
src="assets/arrow.svg"
(click)="editMode && (toggle() || $event.stopPropagation())"
[className]="isOpen ? 'upside-down' : ''"
alt="arrow"
/>
</div>
<div class="bottom-container">
<div #bottom class="bottom {{ isOpen ? 'open' : '' }}">
<p *ngFor="let option of otherOptions" [innerHTML]="option" (click)="select(option)"></p>
<ng-container *ngIf="!editMode; else editableOthers">
<p *ngFor="let option of otherOptions" [innerHTML]="option" (click)="select(option)"></p>
</ng-container>
<ng-template #editableOthers>
<input
type="text"
*ngFor="let option of otherOptions"
[value]="option"
(change)="changeOption(option, $event)"
/>
</ng-template>
<input
type="text"
@ -16,7 +34,12 @@
(keyup)="handleKeys($event)"
/>
<button *ngIf="options.length <= maxItemCount" (click)="addNewOption()" [disabled]="!newOption">Add</button>
<div class="buttons">
<button *ngIf="options.length <= maxItemCount" (click)="addNewOption()" [disabled]="!newOption">Add</button>
<div *ngIf="editable" class="edit {{ editMode ? 'active' : '' }}" (click)="editMode = !editMode">
<img src="assets/pen.svg" alt="edit" />
</div>
</div>
</div>
</div>

View file

@ -19,7 +19,8 @@ $inner-padding: var(--medium-padding);
position: relative;
cursor: pointer;
p {
p,
input[type='text'] {
display: inline-block;
@include sub-title-text();
}
@ -36,7 +37,7 @@ $inner-padding: var(--medium-padding);
.bottom-container {
width: 100%;
height: 40vh;
height: 300px;
position: absolute;
overflow-y: hidden;
@ -77,6 +78,75 @@ $inner-padding: var(--medium-padding);
cursor: pointer;
}
.buttons {
height: 32px;
@media (max-width: $mobile-width) {
height: 24px;
}
position: relative;
width: 100%;
button {
margin: 0;
position: absolute;
left: 50%;
top: 50%;
transform: translateY(-50%) translateX(-50%);
}
.edit {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
margin: 0;
opacity: 0.25;
cursor: pointer;
img {
@include square(16px);
}
transition: opacity $short-animation-time;
&:before {
content: '';
display: block;
position: absolute;
bottom: calc(-1 * #{$line-height});
left: 0;
height: $line-height;
background-color: $text-color;
width: 0;
transition: width $long-animation-time;
}
@media (min-width: $mobile-width) {
&:hover {
opacity: 0.5;
}
&:hover {
&:before {
width: 100% !important;
}
}
}
&.active {
&:before {
width: 100% !important;
}
}
&.active {
opacity: 1;
}
}
}
}
.edit {
}
}

View file

@ -12,6 +12,7 @@ export class SelectAddComponent {
@Input() options: string[];
@Input() alwaysDropShadow = false;
@Input() onlyShadowBorder = false;
@Input() editable = false;
@Input() set default(value: string) {
this.selected = value;
@ -20,7 +21,20 @@ export class SelectAddComponent {
}
}
backgroundHeight: string;
private _editMode = false;
set editMode(value: boolean) {
this._editMode = value;
this.backgroundHeight = this.getBackgroundHeight();
}
get editMode(): boolean {
return this._editMode;
}
@Output() value: EventEmitter<string> = new EventEmitter();
@Output() optionChange: EventEmitter<{ from: string; to: string }> = new EventEmitter();
@ViewChild('top') top: ElementRef;
@ViewChild('bottom') bottom: ElementRef;
@ -32,6 +46,15 @@ export class SelectAddComponent {
constructor(private cancelService: CancelService) {
this.cancelService.subscribe(this, () => {
this.isOpen = false;
this.editMode = false;
});
}
changeOption(from: string, event) {
console.log(event);
this.optionChange.emit({
from,
to: event.target.value
});
}
@ -45,15 +68,6 @@ export class SelectAddComponent {
}
}
get backgroundHeight(): string {
if (this.isOpen && this.top && this.bottom) {
const topHeight = this.top.nativeElement.clientHeight;
const bottomHeight = this.bottom.nativeElement.clientHeight;
return `${topHeight + bottomHeight}px`;
}
return `100%`;
}
addNewOption() {
if (this.newOption) {
this.select(this.newOption);
@ -69,5 +83,20 @@ export class SelectAddComponent {
toggle() {
this.isOpen = !this.isOpen;
if (!this.isOpen) {
this.editMode = false;
}
this.backgroundHeight = this.getBackgroundHeight();
console.log('editable', this.editable);
}
private getBackgroundHeight(): string {
if (this.isOpen && this.top && this.bottom) {
const topHeight = this.top.nativeElement.clientHeight;
const bottomHeight = this.bottom.nativeElement.clientHeight;
console.log(topHeight, bottomHeight);
return `${topHeight + bottomHeight}px`;
}
return `100%`;
}
}

View file

@ -58,6 +58,12 @@ export class Page extends Serializable implements IPage, PageState {
});
}
changeName(to: string) {
this.changeProps({
name: to
});
}
addTower(name = '') {
let hue;
do {

View file

@ -11,8 +11,6 @@ interface Subscriber {
export class CancelService {
private subscribers: Subscriber[] = [];
constructor() {}
subscribe(object: object, callback: () => void) {
this.subscribers.push({
object,
@ -21,10 +19,12 @@ export class CancelService {
}
cancelAllExcept(except: object) {
console.log('cancel all except', except);
this.subscribers.filter(s => s.object !== except).map(s => s.callback());
}
cancelAll() {
console.log('cancel all');
this.subscribers.map(s => s.callback());
}
}

View file

@ -1,7 +0,0 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 129 129" enable-background="new 0 0 129 129" width="512px" height="512px"><g><g>
<g>
<path d="m119.2,114.3h-109.4c-2.3,0-4.1,1.9-4.1,4.1s1.9,4.1 4.1,4.1h109.5c2.3,0 4.1-1.9 4.1-4.1s-1.9-4.1-4.2-4.1z" data-original="#000000" class="active-path" data-old_color="#000000" fill="#5D576B"/>
<path d="m5.7,78l-.1,19.5c0,1.1 0.4,2.2 1.2,3 0.8,0.8 1.8,1.2 2.9,1.2l19.4-.1c1.1,0 2.1-0.4 2.9-1.2l67-67c1.6-1.6 1.6-4.2 0-5.9l-19.2-19.4c-1.6-1.6-4.2-1.6-5.9-1.77636e-15l-13.4,13.5-53.6,53.5c-0.7,0.8-1.2,1.8-1.2,2.9zm71.2-61.1l13.5,13.5-7.6,7.6-13.5-13.5 7.6-7.6zm-62.9,62.9l49.4-49.4 13.5,13.5-49.4,49.3-13.6,.1 .1-13.5z" data-original="#000000" class="active-path" data-old_color="#000000" fill="#5D576B"/>
</g>
</g></g> </svg>

Before

Width:  |  Height:  |  Size: 872 B

4
src/assets/pen.svg Normal file
View file

@ -0,0 +1,4 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" width="512px" height="512px" viewBox="0 0 528.899 528.899" style="enable-background:new 0 0 528.899 528.899;" xml:space="preserve"><g><g>
<path d="M328.883,89.125l107.59,107.589l-272.34,272.34L56.604,361.465L328.883,89.125z M518.113,63.177l-47.981-47.981 c-18.543-18.543-48.653-18.543-67.259,0l-45.961,45.961l107.59,107.59l53.611-53.611 C532.495,100.753,532.495,77.559,518.113,63.177z M0.3,512.69c-1.958,8.812,5.998,16.708,14.811,14.565l119.891-29.069 L27.473,390.597L0.3,512.69z" data-original="#000000" class="active-path" data-old_color="#000000" fill="#5D576B"/>
</g></g> </svg>

After

Width:  |  Height:  |  Size: 737 B

View file

@ -29,9 +29,6 @@ html {
body {
height: 100%;
background: $background-gradient-opaque;
}
body {
text-align: center;
padding: var(--large-padding);
box-sizing: border-box;