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

Commit

Permalink
feat(store): property type system, setter, and coercing
Browse files Browse the repository at this point in the history
  • Loading branch information
TheReincarnator committed Dec 7, 2017
1 parent 61ede8e commit a961ab6
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 89 deletions.
2 changes: 1 addition & 1 deletion src/component/container/element_list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export class ElementList extends React.Component<ElementListProps> {
}

public createItemFromProperty(key: string, value: PropertyValue): ListPropsListItem {
if (Array.isArray(value)) {
if (value instanceof Array) {
const items: ListPropsListItem[] = [];
(value as (string | number)[]).forEach((child, index: number) => {
items.push(this.createItemFromProperty(String(index + 1), child));
Expand Down
2 changes: 1 addition & 1 deletion src/component/presentation/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class Preview extends React.Component<PreviewProps> {
* or an array or object with values converted in the same manner, if an array resp. object is provided.
*/
private createComponent(value: PropertyValue, key?: string): React.Component | PropertyValue {
if (Array.isArray(value)) {
if (value instanceof Array) {
const array: (string | number)[] = value;
// Handle arrays by returning a new array with recursively processed elements.
return array.map((element: PropertyValue, index: number) =>
Expand Down
68 changes: 36 additions & 32 deletions src/store/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PatternFolder } from './pattern/folder';
import * as FileUtils from 'fs';
import { observable } from 'mobx';
import * as MobX from 'mobx';
import { Page } from './page';
import { PageElement } from './page/page_element';
import { PageRef } from './page/page_ref';
Expand All @@ -9,11 +9,11 @@ import { Pattern } from './pattern';
import { Project } from './project';

export class Store {
@observable private currentPage?: Page;
@observable private selectedElement?: PageElement;
private projects: Project[] = [];
@MobX.observable private currentPage?: Page;
@MobX.observable private projects: Project[] = [];
private patternRoot: PatternFolder;
@observable private styleGuidePath: string;
@MobX.observable private selectedElement?: PageElement;
@MobX.observable private styleGuidePath: string;

public getCurrentPage(): Page | undefined {
return this.currentPage;
Expand Down Expand Up @@ -48,39 +48,43 @@ export class Store {
}

public openStyleguide(styleGuidePath: string): void {
if (!PathUtils.isAbsolute(styleGuidePath)) {
// Currently, store is two levels below stacked, so go two up
styleGuidePath = PathUtils.join(__dirname, '..', '..', styleGuidePath);
}
this.styleGuidePath = styleGuidePath;
this.currentPage = undefined;
this.projects = [];
this.patternRoot = new PatternFolder(this, 'patterns');
MobX.transaction(() => {
if (!PathUtils.isAbsolute(styleGuidePath)) {
// Currently, store is two levels below stacked, so go two up
styleGuidePath = PathUtils.join(__dirname, '..', '..', styleGuidePath);
}
this.styleGuidePath = styleGuidePath;
this.currentPage = undefined;
this.projects = [];
this.patternRoot = new PatternFolder(this, 'patterns');

const projects: Project[] = [];
const projects: Project[] = [];

const projectsPath = this.getProjectsPath();
FileUtils.readdirSync(projectsPath)
.map((name: string) => ({ name, path: PathUtils.join(projectsPath, name) }))
.filter(child => FileUtils.lstatSync(child.path).isDirectory())
.forEach(folder => {
const pages: PageRef[] = [];
FileUtils.readdirSync(folder.path)
.filter(child => child.match(/\.json$/))
.forEach(file => {
const pageId: string = file.replace(/\.json$/, '');
const pageName: string = file.replace(/\.json$/, '');
pages.push(new PageRef(pageId, pageName));
});
const projectsPath = this.getProjectsPath();
FileUtils.readdirSync(projectsPath)
.map((name: string) => ({ name, path: PathUtils.join(projectsPath, name) }))
.filter(child => FileUtils.lstatSync(child.path).isDirectory())
.forEach(folder => {
const pages: PageRef[] = [];
FileUtils.readdirSync(folder.path)
.filter(child => child.match(/\.json$/))
.forEach(file => {
const pageId: string = file.replace(/\.json$/, '');
const pageName: string = file.replace(/\.json$/, '');
pages.push(new PageRef(pageId, pageName));
});

projects.push(new Project(folder.name, folder.name, pages));
});
this.projects = projects;
projects.push(new Project(folder.name, folder.name, pages));
});
this.projects = projects;
});
}

public openPage(projectId: string, pageId: string): void {
this.currentPage = new Page(this, projectId, pageId);
this.selectedElement = undefined;
MobX.transaction(() => {
this.currentPage = new Page(this, projectId, pageId);
this.selectedElement = undefined;
});
}

public setSelectedElement(selectedElement: PageElement): void {
Expand Down
11 changes: 7 additions & 4 deletions src/store/page/page_element.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import * as MobX from 'mobx';
import { Pattern } from '../pattern';
import { Property } from '../pattern/property';
import { PropertyValue } from './property_value';
import { Store } from '..';

export class PageElement {
private children: PageElement[] = [];
@MobX.observable private children: PageElement[] = [];
private patternPath: string;
private pattern?: Pattern;
private propertyValues: { [id: string]: PropertyValue } = {};
@MobX.observable private propertyValues: Map<string, PropertyValue> = new Map();

// tslint:disable-next-line:no-any
public constructor(json: any, store: Store) {
Expand Down Expand Up @@ -57,7 +58,9 @@ export class PageElement {
}

public getPropertyValue(id: string): PropertyValue {
return this.propertyValues[id];
const value: PropertyValue = this.propertyValues.get(id);

return value;
}

// tslint:disable-next-line:no-any
Expand All @@ -72,6 +75,6 @@ export class PageElement {
return;
}

this.propertyValues[id] = property.coerceValue(value);
this.propertyValues.set(id, value);
}
}
63 changes: 31 additions & 32 deletions src/store/pattern/folder/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import * as FileUtils from 'fs';
import * as MobX from 'mobx';
import * as PathUtils from 'path';
import { Pattern } from '..';
import { Store } from '../..';

export class PatternFolder {
private children: PatternFolder[];
private childrenByName: { [name: string]: PatternFolder } = {};
@MobX.observable private children: Map<string, PatternFolder> = new Map();
private name: string;
private parent?: PatternFolder;
private patterns: Pattern[];
private patternsByName: { [id: string]: Pattern } = {};
@MobX.observable private patterns: Map<string, Pattern> = new Map();
private store: Store;

public constructor(store: Store, name: string, parent?: PatternFolder) {
Expand All @@ -27,11 +26,11 @@ export class PatternFolder {
public getChild(path: string): PatternFolder | undefined {
const slashPos: number = path.indexOf('/');
if (slashPos < 0) {
return this.childrenByName[path];
return this.children.get(path);
}

const folderName: string = path.substring(0, slashPos);
const folder: PatternFolder | undefined = this.childrenByName[folderName];
const folder: PatternFolder | undefined = this.children.get(folderName);
if (!folder) {
return undefined;
}
Expand All @@ -41,7 +40,7 @@ export class PatternFolder {
}

public getChildren(): PatternFolder[] {
return this.children;
return Array.from(this.children.values());
}

public getName(): string {
Expand All @@ -53,17 +52,17 @@ export class PatternFolder {
}

public getPatterns(): Pattern[] {
return this.patterns;
return Array.from(this.patterns.values());
}

public getPattern(path: string): Pattern | undefined {
const slashPos: number = path.indexOf('/');
if (slashPos < 0) {
return this.patternsByName[path];
return this.patterns.get(path);
}

const folderName: string = path.substring(0, slashPos);
const folder: PatternFolder | undefined = this.childrenByName[folderName];
const folder: PatternFolder | undefined = this.children.get(folderName);
if (!folder) {
return undefined;
}
Expand All @@ -81,30 +80,30 @@ export class PatternFolder {
}

public reload(): void {
this.patterns = [];
this.children = [];

const parentPath: string = this.getAbsolutePath();
FileUtils.readdirSync(parentPath).forEach(childName => {
const childPath = PathUtils.join(parentPath, childName);
if (FileUtils.lstatSync(childPath).isDirectory()) {
if (
FileUtils.existsSync(PathUtils.join(childPath, 'index.d.ts')) &&
FileUtils.existsSync(PathUtils.join(childPath, 'index.js'))
) {
const pattern: Pattern = new Pattern(this, childName);
if (pattern.isValid()) {
this.patterns.push(pattern);
this.patternsByName[childName] = pattern;
}
} else {
const childFolder: PatternFolder = new PatternFolder(this.store, childName, this);
if (childFolder.patterns.length || childFolder.children.length) {
this.children.push(childFolder);
this.childrenByName[childName] = childFolder;
MobX.transaction(() => {
this.patterns.clear();
this.children.clear();

const parentPath: string = this.getAbsolutePath();
FileUtils.readdirSync(parentPath).forEach(childName => {
const childPath = PathUtils.join(parentPath, childName);
if (FileUtils.lstatSync(childPath).isDirectory()) {
if (
FileUtils.existsSync(PathUtils.join(childPath, 'index.d.ts')) &&
FileUtils.existsSync(PathUtils.join(childPath, 'index.js'))
) {
const pattern: Pattern = new Pattern(this, childName);
if (pattern.isValid()) {
this.patterns.set(childName, pattern);
}
} else {
const childFolder: PatternFolder = new PatternFolder(this.store, childName, this);
if (childFolder.patterns.size > 0 || childFolder.children.size > 0) {
this.children.set(childName, childFolder);
}
}
}
}
});
});
}
}
19 changes: 6 additions & 13 deletions src/store/pattern/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,7 @@ export class Pattern {
/**
* The properties this pattern supports.
*/
private properties: Property[];

/**
* The properties this pattern supports.
*/
private propertiesById: { [id: string]: Property } = {};
private properties: Map<string, Property> = new Map();

/**
* This is a valid pattern for Stacked (has been parsed successfully).
Expand All @@ -52,11 +47,11 @@ export class Pattern {
}

public getProperties(): Property[] {
return this.properties;
return Array.from(this.properties.values());
}

public getProperty(id: string): Property | undefined {
return this.propertiesById[id];
return this.properties.get(id);
}

public getRelativePath(): string {
Expand All @@ -73,14 +68,12 @@ export class Pattern {
}

this.valid = false;
this.properties = [];
this.properties.clear();
Pattern.parsers.some(parser => {
const result: Property[] | undefined = parser.parse(this);
if (result) {
this.properties = result;
this.propertiesById = {};
this.properties.forEach(pattern => {
this.propertiesById[pattern.getId()] = pattern;
result.forEach(property => {
this.properties.set(property.getId(), property);
});

this.valid = true;
Expand Down
2 changes: 1 addition & 1 deletion src/store/pattern/property/boolean_property.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export class BooleanProperty extends Property {

// tslint:disable-next-line:no-any
public coerceValue(value: any): any {
return value && (value === true || value === 'true' || value === 1);
return value === true || value === 'true' || value === 1;
}

public getType(): string {
Expand Down
4 changes: 2 additions & 2 deletions src/store/pattern/property/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export abstract class Property {

// tslint:disable-next-line:no-any
protected arraysAndEqual(value1: any, value2: any): boolean {
if (!Array.isArray(value1) || !Array.isArray(value2)) {
if (!(value1 instanceof Array) || !(value2 instanceof Array)) {
return false;
}

Expand All @@ -36,7 +36,7 @@ export abstract class Property {
protected coerceArrayValue(value: any, elementCoercion: (value: any) => any): any {
// tslint:disable-next-line:no-any
let result: any[];
if (Array.isArray(value)) {
if (value instanceof Array) {
result = value;
} else {
result = [value];
Expand Down
7 changes: 4 additions & 3 deletions src/store/project/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import * as MobX from 'mobx';
import { PageRef } from '../page/page_ref';

export class Project {
private id: string;
private name: string;
private pages: PageRef[];
@MobX.observable private id: string;
@MobX.observable private name: string;
@MobX.observable private pages: PageRef[] = [];

public constructor(id: string, name: string, pages: PageRef[]) {
this.id = id;
Expand Down

0 comments on commit a961ab6

Please sign in to comment.