Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replaced Components screens with TreeView component #107

Merged
merged 4 commits into from
Feb 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 58 additions & 28 deletions src/application/EnvironmentInteractor.mts
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import Environment from '~/domain/Environment.mjs';
import type { Properties } from '~/types/Properties.mjs';
import { Assumption, Component, Constraint, ConstraintCategory, Effect, Environment, GlossaryTerm, Invariant, type Uuid } from '~/domain/index.mjs';
import Interactor from './Interactor.mjs';
import type Presenter from './Presenter.mjs';
import type Repository from './Repository.mjs';
import type { Uuid } from '~/domain/Uuid.mjs';
import Assumption from '~/domain/Assumption.mjs';
import type { Properties } from '~/types/Properties.mjs';
import Component from '~/domain/Component.mjs';
import Constraint, { ConstraintCategory } from '~/domain/Constraint.mjs';
import Effect from '~/domain/Effect.mjs';
import GlossaryTerm from '~/domain/GlossaryTerm.mjs';
import Invariant from '~/domain/Invariant.mjs';
import treeFind from '~/lib/treeFind.mjs';

export default class EnvironmentInteractor extends Interactor<Environment> {
constructor({ presenter, repository }: {
Expand Down Expand Up @@ -38,26 +32,35 @@ export default class EnvironmentInteractor extends Interactor<Environment> {
}

async createComponent(
{ environmentId, name, description, interfaceDefinition }: {
{ environmentId, parentId, label }: {
environmentId: Uuid;
name: string;
description: string;
interfaceDefinition: string;
parentId?: Uuid;
label: string;
}
) {
): Promise<Component> {
const environment = await this.repository.get(environmentId);

if (!environment)
throw new Error(`Environment ${environmentId} not found`);

environment.components.push(new Component({
id: crypto.randomUUID(),
name,
description,
statement: interfaceDefinition
}));
const parent = !parentId ? environment :
environment.components.map(c => treeFind(parentId, c))
.find(x => x) ?? environment,
component = new Component({
id: crypto.randomUUID(),
name: label,
statement: '',
children: []
});

if (parent instanceof Environment)
environment.components.push(component);
else
parent.children.push(component);

await this.repository.update(environment);

return component;
}

async createConstraint(
Expand Down Expand Up @@ -147,14 +150,22 @@ export default class EnvironmentInteractor extends Interactor<Environment> {
}

async deleteComponent(
{ environmentId, id }: { environmentId: Uuid; id: Uuid }
{ environmentId, id, parentId }: { environmentId: Uuid; id: Uuid; parentId?: Uuid }
) {
const environment = await this.repository.get(environmentId);

if (!environment)
throw new Error(`Environment ${environmentId} not found`);

environment.components = environment.components.filter(x => x.id !== id);
const parent = !parentId ? environment :
environment.components.map(c => treeFind(parentId, c))
.find(x => x) ?? environment;

if (parent instanceof Environment)
environment.components = environment.components.filter(x => x.id !== id);
else
parent.children = parent.children.filter(x => x.id !== id);

await this.repository.update(environment);
}

Expand Down Expand Up @@ -223,17 +234,36 @@ export default class EnvironmentInteractor extends Interactor<Environment> {
}

async updateComponent(
{ environmentId, component }: { environmentId: Uuid; component: Properties<Component> }
{ environmentId, id, parentId, label }:
{ environmentId: Uuid; id: Uuid; parentId?: Uuid; label: string }
) {
const environment = await this.repository.get(environmentId),
newComponent = new Component(component);
const environment = await this.repository.get(environmentId);

if (!environment)
throw new Error(`Environment ${environmentId} not found`);

environment.components = environment.components.map(x =>
x.id === component.id ? newComponent : x
);
const parent = !parentId ? environment :
environment.components.map(c => treeFind(parentId, c))
.find(x => x) ?? environment;

if (parent instanceof Environment)
parent.components = environment.components.map(c =>
c.id === id ? new Component({
id,
name: label,
statement: '',
children: c.children
}) : c
);
else
parent.children = parent.children.map(c =>
c.id === id ? new Component({
id,
name: label,
statement: '',
children: c.children
}) : c
);

await this.repository.update(environment);
}
Expand Down
7 changes: 1 addition & 6 deletions src/application/GoalsInteractor.mts
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import Goals from '~/domain/Goals.mjs';
import { Behavior, Goals, Limit, Stakeholder, UseCase, type Uuid } from '~/domain/index.mjs';
import Interactor from './Interactor.mjs';
import type Presenter from './Presenter.mjs';
import type Repository from './Repository.mjs';
import type { Uuid } from '~/domain/Uuid.mjs';
import Behavior from '~/domain/Behavior.mjs';
import type { Properties } from '~/types/Properties.mjs';
import Limit from '~/domain/Limit.mjs';
import Stakeholder from '~/domain/Stakeholder.mjs';
import UseCase from '~/domain/UseCase.mjs';

export default class GoalsInteractor extends Interactor<Goals> {
constructor({ presenter, repository }: {
Expand Down
3 changes: 1 addition & 2 deletions src/application/Interactor.mts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import type Entity from '~/domain/Entity.mjs';
import { type Entity, type Uuid } from '~/domain/index.mjs';
import type Repository from './Repository.mjs';
import type Presenter from './Presenter.mjs';
import type { Properties } from '~/types/Properties.mjs';
import type { Uuid } from '~/domain/Uuid.mjs';

export default abstract class Interactor<E extends Entity> {
#presenter; #repository; #Entity;
Expand Down
2 changes: 1 addition & 1 deletion src/application/Presenter.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type Entity from '~/domain/Entity.mjs';
import { type Entity } from '~/domain/index.mjs';

export default interface Presenter<E extends Entity> {
presentItem(entity: E): void;
Expand Down
2 changes: 1 addition & 1 deletion src/application/ProjectInteractor.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Project from '~/domain/Project.mjs';
import { Project } from '~/domain/index.mjs';
import Interactor from './Interactor.mjs';
import type Presenter from './Presenter.mjs';
import type Repository from './Repository.mjs';
Expand Down
2 changes: 1 addition & 1 deletion src/application/Repository.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type Entity from '~/domain/Entity.mjs';
import { type Entity } from '~/domain/index.mjs';
import type Mapper from './Mapper.mjs';

export default abstract class Repository<E extends Entity> extends EventTarget {
Expand Down
2 changes: 1 addition & 1 deletion src/application/SolutionInteractor.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Solution from '~/domain/Solution.mjs';
import { Solution } from '~/domain/index.mjs';
import Interactor from './Interactor.mjs';
import type Presenter from './Presenter.mjs';
import type Repository from './Repository.mjs';
Expand Down
80 changes: 57 additions & 23 deletions src/application/SystemInteractor.mts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import System from '~/domain/System.mjs';
import { Component, System, type Uuid } from '~/domain/index.mjs';
import Interactor from './Interactor.mjs';
import type Presenter from './Presenter.mjs';
import type Repository from './Repository.mjs';
import type { Uuid } from '~/domain/Uuid.mjs';
import Component from '~/domain/Component.mjs';
import type { Properties } from '~/types/Properties.mjs';
import treeFind from '~/lib/treeFind.mjs';

export default class SystemInteractor extends Interactor<System> {
constructor({ presenter, repository }: {
Expand All @@ -15,52 +13,88 @@ export default class SystemInteractor extends Interactor<System> {
}

async createComponent(
{ systemId, name, description, interfaceDefinition }: {
{ systemId, parentId, label }: {
systemId: Uuid;
name: string;
description: string;
interfaceDefinition: string;
parentId?: Uuid;
label: string;
}
) {
): Promise<Component> {
const system = await this.repository.get(systemId);

if (!system)
throw new Error(`System ${systemId} not found`);

system.components.push(new Component({
id: crypto.randomUUID(),
name,
description,
statement: interfaceDefinition
}));
const parent = !parentId ? system :
system.components.map(c => treeFind(parentId, c))
.find(x => x) ?? system,
component = new Component({
id: crypto.randomUUID(),
name: label,
statement: '',
children: []
});

if (parent instanceof System)
system.components.push(component);
else
parent.children.push(component);

await this.repository.update(system);

return component;
}

async deleteComponent(
{ systemId, id }: { systemId: Uuid; id: Uuid }
{ systemId, id, parentId }: { systemId: Uuid; id: Uuid; parentId?: Uuid }
) {
const system = await this.repository.get(systemId);

if (!system)
throw new Error(`System ${systemId} not found`);

system.components = system.components.filter(x => x.id !== id);
const parent = !parentId ? system :
system.components.map(c => treeFind(parentId, c))
.find(x => x) ?? system;

if (parent instanceof System)
system.components = system.components.filter(x => x.id !== id);
else
parent.children = parent.children.filter(x => x.id !== id);

await this.repository.update(system);
}

async updateComponent(
{ systemId, component }: { systemId: Uuid; component: Properties<Component> }
{ systemId, id, parentId, label }:
{ systemId: Uuid; id: Uuid; parentId?: Uuid; label: string }
) {
const system = await this.repository.get(systemId),
newComponent = new Component(component);
const system = await this.repository.get(systemId);

if (!system)
throw new Error(`System ${systemId} not found`);

system.components = system.components.map(x =>
x.id === component.id ? newComponent : x
);
const parent = !parentId ? system :
system.components.map(c => treeFind(parentId, c))
.find(x => x) ?? system;

if (parent instanceof System)
parent.components = system.components.map(c =>
c.id === id ? new Component({
id,
name: label,
statement: '',
children: c.children
}) : c
);
else
parent.children = parent.children.map(c =>
c.id === id ? new Component({
id,
name: label,
statement: '',
children: c.children
}) : c
);

await this.repository.update(system);
}
Expand Down
2 changes: 1 addition & 1 deletion src/data/BehaviorRepository.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Behavior from '~/domain/Behavior.mjs';
import { Behavior } from '~/domain/index.mjs';
import StorageRepository from './StorageRepository.mjs';
import BehaviorToJsonMapper from '~/mappers/BehaviorToJsonMapper.mjs';
import pkg from '~/../package.json' with { type: 'json' };
Expand Down
2 changes: 1 addition & 1 deletion src/data/EnvironmentRepository.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Environment from '~/domain/Environment.mjs';
import { Environment } from '~/domain/index.mjs';
import StorageRepository from './StorageRepository.mjs';
import EnvironmentToJsonMapper from '~/mappers/EnvironmentToJsonMapper.mjs';
import pkg from '~/../package.json' with { type: 'json' };
Expand Down
2 changes: 1 addition & 1 deletion src/data/GoalsRepository.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Goals from '~/domain/Goals.mjs';
import { Goals } from '~/domain/index.mjs';
import StorageRepository from './StorageRepository.mjs';
import GoalsToJsonMapper from '~/mappers/GoalsToJsonMapper.mjs';
import pkg from '~/../package.json' with { type: 'json' };
Expand Down
2 changes: 1 addition & 1 deletion src/data/ProjectRepository.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Project from '~/domain/Project.mjs';
import { Project } from '~/domain/index.mjs';
import StorageRepository from './StorageRepository.mjs';
import ProjectToJsonMapper from '~/mappers/ProjectToJsonMapper.mjs';
import pkg from '~/../package.json' with { type: 'json' };
Expand Down
2 changes: 1 addition & 1 deletion src/data/SlugRepository.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type SlugEntity from '~/domain/SlugEntity.mjs';
import { type SlugEntity } from '~/domain/index.mjs';
import StorageRepository from './StorageRepository.mjs';
import type Mapper from '~/application/Mapper.mjs';
import type { EntityJson } from '~/mappers/EntityToJsonMapper.mjs';
Expand Down
2 changes: 1 addition & 1 deletion src/data/SolutionRepository.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type Solution from '~/domain/Solution.mjs';
import { type Solution } from '~/domain/index.mjs';
import SolutionToJsonMapper from '~/mappers/SolutionToJsonMapper.mjs';
import pkg from '~/../package.json' with { type: 'json' };
import type { SemVerString } from '~/lib/SemVer.mjs';
Expand Down
2 changes: 1 addition & 1 deletion src/data/StorageRepository.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type Entity from '~/domain/Entity.mjs';
import { type Entity } from '~/domain/index.mjs';
import type { EntityJson } from '~/mappers/EntityToJsonMapper.mjs';
import type Mapper from '~/application/Mapper.mjs';
import Repository from '~/application/Repository.mjs';
Expand Down
2 changes: 1 addition & 1 deletion src/data/StorageRepository.test.mts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Behavior } from '~/domain/index.mjs';
import { describe, test } from 'node:test';
import assert from 'node:assert/strict';
import StorageRepository from './StorageRepository.mjs';
import Behavior from '~/domain/Behavior.mjs';
// @ts-expect-error: No typings available
import DomStorage from 'dom-storage';
import BehaviorToJsonMapper from '~/mappers/BehaviorToJsonMapper.mjs';
Expand Down
2 changes: 1 addition & 1 deletion src/data/SystemRepository.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type System from '~/domain/System.mjs';
import { type System } from '~/domain/index.mjs';
import type { SemVerString } from '~/lib/SemVer.mjs';
import StorageRepository from './StorageRepository.mjs';
import pkg from '~/../package.json' with { type: 'json' };
Expand Down
4 changes: 2 additions & 2 deletions src/domain/Assumption.mts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { Properties } from '~/types/Properties.mjs';
import Requirement from './Requirement.mjs';
import { Requirement } from './index.mjs';

/**
* An assumption is a property of the environment that is assumed to be true.
* Assumptions are used to simplify the problem and to make it more tractable.
* An example of an assumption would be: "Screen resolutions will not change during the execution of the program."
*/
export default class Assumption extends Requirement {
export class Assumption extends Requirement {
constructor(properties: Properties<Assumption>) {
super(properties);
}
Expand Down
4 changes: 2 additions & 2 deletions src/domain/Behavior.mts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { Properties } from '~/types/Properties.mjs';
import Requirement from './Requirement.mjs';
import { Requirement } from './index.mjs';

/**
* A Behavior is a specification of how a system produces an outcome or effect.
*/
export default class Behavior extends Requirement {
export class Behavior extends Requirement {
constructor(options: Properties<Behavior>) {
super(options);
}
Expand Down
Loading
Loading