Skip to content
This repository has been archived by the owner on Oct 23, 2023. It is now read-only.

Commit

Permalink
fix(store): page elements have stable IDs now, fixing UI lists
Browse files Browse the repository at this point in the history
  • Loading branch information
TheReincarnator committed Mar 16, 2018
1 parent 0903f24 commit 55053d3
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 88 deletions.
10 changes: 3 additions & 7 deletions src/component/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -221,13 +221,9 @@ MobX.autorun(() => {

MobX.autorun(() => {
const selectedElement = store.getSelectedElement();

if (!selectedElement) {
return;
}

const message: JsonObject = { selectedElementId: selectedElement.getId() };

const message: JsonObject = {
selectedElementId: selectedElement ? selectedElement.getId() : undefined
};
sendWebViewMessage(message, 'selectedElement-change');
});

Expand Down
12 changes: 10 additions & 2 deletions src/component/container/element-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,11 @@ export class ElementList extends React.Component<ElementListProps> {
return;
}

pageElement = new PageElement(styleguide.getPattern(patternId), true);
pageElement = new PageElement({
pattern: styleguide.getPattern(patternId),
page: this.props.store.getCurrentPage() as Page,
setDefaults: true
});
}

if (!parentElement || !pageElement || pageElement.isAncestorOf(parentElement)) {
Expand All @@ -144,7 +148,11 @@ export class ElementList extends React.Component<ElementListProps> {
return;
}

pageElement = new PageElement(styleguide.getPattern(patternId), true);
pageElement = new PageElement({
pattern: styleguide.getPattern(patternId),
page: this.props.store.getCurrentPage() as Page,
setDefaults: true
});
}

if (!pageElement || pageElement.isAncestorOf(element)) {
Expand Down
7 changes: 6 additions & 1 deletion src/component/container/pattern-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Input from '../../lsg/patterns/input/';
import { PatternFolder } from '../../store/styleguide/folder';
import { action } from 'mobx';
import { observer } from 'mobx-react';
import { Page } from '../../store/page/page';
import { PageElement } from '../../store/page/page-element';
import { Pattern } from '../../store/styleguide/pattern';
import PatternList, {
Expand Down Expand Up @@ -152,7 +153,11 @@ export class PatternListContainer extends React.Component<PatternListContainerPr
protected handlePatternClick(pattern: Pattern): void {
const selectedElement: PageElement | undefined = this.props.store.getSelectedElement();
if (selectedElement) {
const newPageElement = new PageElement(pattern, true);
const newPageElement = new PageElement({
pattern,
page: this.props.store.getCurrentPage() as Page,
setDefaults: true
});
selectedElement.addSibling(newPageElement);
this.props.store.setSelectedElement(newPageElement);
}
Expand Down
7 changes: 2 additions & 5 deletions src/component/presentation/react/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export interface PreviewAppState {

interface PreviewProps {
page?: Page;
selectedElementId?: number[];
selectedElementId?: string;
highlightElement: HighlightElementFunction;
}

Expand Down Expand Up @@ -189,10 +189,7 @@ class Preview extends React.Component<PreviewProps> {
const reactComponent = React.createElement(patternFactory, componentProps);

// Finally, build the component
if (
pageElement.getId().toString() ===
(this.props.selectedElementId && this.props.selectedElementId.toString())
) {
if (pageElement.getId() === this.props.selectedElementId) {
return (
<PatternWrapper
key={key}
Expand Down
4 changes: 3 additions & 1 deletion src/component/preview.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ipcRenderer } from 'electron';
import { JsonObject } from '../store/json';
import { Page } from '../store/page/page';
import * as SmoothscrollPolyfill from 'smoothscroll-polyfill';
import { Store } from '../store/store';

Expand All @@ -24,7 +25,8 @@ ipcRenderer.on('open-styleguide', (event: {}, message: JsonObject) => {
});

ipcRenderer.on('selectedElement-change', (event: {}, message: JsonObject) => {
store.setSelectedElementById(message.selectedElementId as number[]);
const page = store.getCurrentPage() as Page;
store.setSelectedElement(page.getElementById(message.selectedElementId as string));
});

const highlightElement: HighlightElementFunction = (element, currentHighlightArea, callback) => {
Expand Down
80 changes: 54 additions & 26 deletions src/store/page/page-element.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import { JsonArray, JsonObject, JsonValue } from '../json';
import * as MobX from 'mobx';
import { Page } from './page';
import { Pattern } from '../styleguide/pattern';
import { Property } from '../styleguide/property/property';
import { PropertyValue } from './property-value';
import { Store } from '../store';
import { Styleguide } from '../styleguide/styleguide';
import * as Uuid from 'uuid';

export interface PageElementProperties {
page: Page;
pattern?: Pattern;
id?: string;
setDefaults?: boolean;
parent?: PageElement;
}

/**
* A page element provides the properties data of a pattern.
Expand All @@ -17,6 +27,16 @@ export class PageElement {
*/
@MobX.observable private children: PageElement[] = [];

/**
* The technical (internal) ID of the page element.
*/
@MobX.observable private id: string;

/**
* The page this element belongs to.
*/
private page: Page;

/**
* The parent page element if this is not the root element.
*/
Expand All @@ -43,10 +63,12 @@ export class PageElement {
* @param parent The (optional) parent for this element. When set, the element is
* automatically added to this parent (and thus maybe to the entire page).
*/
public constructor(pattern?: Pattern, setDefaults?: boolean, parent?: PageElement) {
this.pattern = pattern;
public constructor(properties: PageElementProperties) {
this.id = properties.id ? properties.id : Uuid.v4();
this.page = properties.page;
this.pattern = properties.pattern;

if (setDefaults && this.pattern) {
if (properties.setDefaults && this.pattern) {
this.pattern.getProperties().forEach(property => {
this.setPropertyValue(property.getId(), property.getDefaultValue());
console.log(
Expand All @@ -57,7 +79,7 @@ export class PageElement {
});
}

this.setParent(parent);
this.setParent(properties.parent);
}

/**
Expand All @@ -68,6 +90,7 @@ export class PageElement {
public static fromJsonObject(
json: JsonObject,
store: Store,
page: Page,
parent?: PageElement
): PageElement | undefined {
if (!json) {
Expand All @@ -89,10 +112,10 @@ export class PageElement {

if (!pattern) {
console.warn(`Ignoring unknown pattern "${patternId}"`);
return new PageElement(undefined, false, parent);
return new PageElement({ page, parent });
}

const element = new PageElement(pattern, false, parent);
const element = new PageElement({ id: json.uuid as string, page, pattern, parent });

if (json.properties) {
Object.keys(json.properties as JsonObject).forEach((propertyId: string) => {
Expand Down Expand Up @@ -138,7 +161,7 @@ export class PageElement {
* @return The new clone.
*/
public clone(): PageElement {
const clone = new PageElement(this.pattern);
const clone = new PageElement({ page: this.page, pattern: this.pattern });
this.children.forEach(child => {
clone.addChild(child.clone());
});
Expand All @@ -156,15 +179,17 @@ export class PageElement {
*/
protected createChildElement(json: JsonValue, store: Store): PageElement | PropertyValue {
if (json && (json as JsonObject)['_type'] === 'pattern') {
return PageElement.fromJsonObject(json as JsonObject, store, this);
return PageElement.fromJsonObject(json as JsonObject, store, this.page, this);
} else {
const styleguide = store.getStyleguide() as Styleguide;

const element: PageElement = new PageElement(
styleguide.getPattern('synthetic/text'),
false,
this
);
const element: PageElement = new PageElement({
id: 'synthetic/text',
page: this.page,
pattern: styleguide.getPattern('synthetic/text'),
setDefaults: false,
parent: this
});
element.setPropertyValue('text', String(json));
return element;
}
Expand All @@ -178,7 +203,7 @@ export class PageElement {
*/
protected createPropertyValue(json: JsonValue, store: Store): PageElement | PropertyValue {
if (json && (json as JsonObject)['_type'] === 'pattern') {
return PageElement.fromJsonObject(json as JsonObject, store, this);
return PageElement.fromJsonObject(json as JsonObject, store, this.page, this);
} else {
return json as PropertyValue;
}
Expand All @@ -204,20 +229,19 @@ export class PageElement {
}

/**
* Returns the unique ID of this element
* @return an array of numbers which represents the unique ID
* Returns the technical (internal) ID of the page.
* @return The technical (internal) ID of the page.
*/
public getId(): number[] {
if (!this.parent) {
return [0];
}

if (!this.parent.parent) {
return [0, this.getIndex()];
}
public getId(): string {
return this.id;
}

const parentID = this.parent.getId();
return [...parentID, this.getIndex()];
/**
* Returns the page this element belongs to.
* @return The page this element belongs to.
*/
public getPage(): Page {
return this.page;
}

/**
Expand Down Expand Up @@ -337,6 +361,7 @@ export class PageElement {

if (this.parent) {
(this.parent.children as MobX.IObservableArray<PageElement>).remove(this);
this.parent.getPage().unregisterElementAndChildren(this);
}

this.parent = parent;
Expand All @@ -347,6 +372,8 @@ export class PageElement {
} else {
parent.children.splice(index < 0 ? 0 : index, 0, this);
}

parent.getPage().registerElementAndChildren(this);
}
}

Expand Down Expand Up @@ -376,6 +403,7 @@ export class PageElement {
public toJsonObject(): JsonObject {
const json: JsonObject = {
_type: 'pattern',
uuid: this.id,
pattern: this.pattern && this.pattern.getId()
};

Expand Down
33 changes: 32 additions & 1 deletion src/store/page/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ import { Store } from '../store';
* @see PageRef
*/
export class Page {
/**
* A lookup of all page elements by their ID.
*/
@MobX.observable private elementsById: Map<string, PageElement> = new Map();

/**
* The page reference, containing the technical ID and the human-friendly name of this page.
*/
Expand Down Expand Up @@ -42,11 +47,19 @@ export class Page {
}

const page = new Page(store.getPageRefById(id) as PageRef);
page.root = PageElement.fromJsonObject(json.root as JsonObject, store);
page.root = PageElement.fromJsonObject(json.root as JsonObject, store, page);

return page;
}

/**
* Returns the page element for a given Id or undefined, if no such ID exists.
* @return The page element or undefined.
*/
public getElementById(id: string): PageElement | undefined {
return this.elementsById.get(id);
}

/**
* Returns the technical (internal) ID of the page.
* @return The technical (internal) ID of the page.
Expand Down Expand Up @@ -89,6 +102,15 @@ export class Page {
return this.root;
}

/**
* Adds a given element and all its descendents to the lookup of elements by ID.
* @param element The element to start with.
*/
public registerElementAndChildren(element: PageElement): void {
this.elementsById.set(element.getId(), element);
element.getChildren().forEach(child => this.registerElementAndChildren(child));
}

/**
* Sets the human-friendly name of the page.
* In the frontend, to be displayed instead of the ID.
Expand All @@ -105,4 +127,13 @@ export class Page {
public toJsonObject(): JsonObject {
return { root: this.root ? this.root.toJsonObject() : undefined };
}

/**
* Removes a given element and all its descendents from the lookup of elements by ID.
* @param element The element to start with.
*/
public unregisterElementAndChildren(element: PageElement): void {
this.elementsById.delete(element.getId());
element.getChildren().forEach(child => this.unregisterElementAndChildren(child));
}
}
Loading

0 comments on commit 55053d3

Please sign in to comment.