Skip to content

Commit

Permalink
Implemented initial constraints page (#76)
Browse files Browse the repository at this point in the history
  • Loading branch information
mlhaufe authored Jan 12, 2024
1 parent 22a8989 commit bfc9b11
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 6 deletions.
3 changes: 0 additions & 3 deletions _old/domain/entities/Constraint.mts

This file was deleted.

11 changes: 11 additions & 0 deletions src/data/ConstraintRepository.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Constraint from '~/domain/Constraint.mjs';
import StorageRepository from './StorageRepository.mjs';
import ConstraintToJsonMapper from '~/mappers/ConstraintToJsonMapper.mjs';
import pkg from '~/../package.json' with { type: 'json' };
import type { SemVerString } from '~/lib/SemVer.mjs';

export default class ConstraintRepository extends StorageRepository<Constraint> {
constructor(storage: Storage) {
super('constraints', storage, new ConstraintToJsonMapper(pkg.version as SemVerString));
}
}
18 changes: 18 additions & 0 deletions src/domain/Constraint.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { Properties } from '~/types/Properties.mjs';
import Requirement from './Requirement.mjs';

export enum ConstraintCategory {
BusinessRule = 'Business Rule',
PhysicalLaw = 'Physical Law',
EngineeringDecision = 'Engineering Decision'
}

export default class Constraint extends Requirement {
constructor(options: Properties<Constraint>) {
super(options);

this.category = options.category;
}

category: ConstraintCategory;
}
2 changes: 2 additions & 0 deletions src/domain/Environment.mts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ import type { Properties } from '~/types/Properties.mjs';
*/
export default class Environment extends Entity {
glossaryIds: Uuid[];
constraintIds: Uuid[];

constructor(options: Properties<Environment>) {
super(options);
this.glossaryIds = options.glossaryIds;
this.constraintIds = options.constraintIds;
}
}
25 changes: 25 additions & 0 deletions src/mappers/ConstraintToJsonMapper.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Constraint, { ConstraintCategory } from '~/domain/Constraint.mjs';
import RequirementToJsonMapper, { type RequirementJson } from './RequirementToJsonMapper.mjs';
import SemVer from '~/lib/SemVer.mjs';

export interface ConstraintJson extends RequirementJson {
category: ConstraintCategory;
}

export default class ConstraintToJsonMapper extends RequirementToJsonMapper {
override mapFrom(target: ConstraintJson): Constraint {
const version = new SemVer(target.serializationVersion);

if (version.gte('0.4.0'))
return new Constraint(target);

throw new Error(`Unsupported serialization version: ${version}`);
}

override mapTo(source: Constraint): ConstraintJson {
return {
...super.mapTo(source),
category: source.category
};
}
}
9 changes: 7 additions & 2 deletions src/mappers/EnvironmentToJsonMapper.mts
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,27 @@ import SemVer from '~/lib/SemVer.mjs';

export interface EnvironmentJson extends EntityJson {
glossaryIds: Uuid[];
constraintIds: Uuid[];
}

export default class EnvironmentToJsonMapper extends EntityToJsonMapper {
override mapFrom(target: EnvironmentJson): Environment {
const version = new SemVer(target.serializationVersion);

if (version.gte('0.3.0'))
return new Environment(target);
return new Environment({
...target,
constraintIds: target.constraintIds ?? []
});

throw new Error(`Unsupported serialization version: ${version}`);
}

override mapTo(source: Environment): EnvironmentJson {
return {
...super.mapTo(source),
glossaryIds: source.glossaryIds
glossaryIds: source.glossaryIds,
constraintIds: source.constraintIds
};
}
}
1 change: 1 addition & 0 deletions src/presentation/Application.mts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export default class Application extends Container {
(await import('./pages/solution/project/ProjectsIndexPage.mjs')).default,
(await import('./pages/solution/environment/EnvironmentsIndexPage.mjs')).default,
(await import('./pages/solution/environment/GlossaryPage.mjs')).default,
(await import('./pages/solution/environment/ConstraintsPage.mjs')).default,
(await import('./pages/solution/goals/GoalsIndexPage.mjs')).default,
(await import('./pages/solution/goals/RationalePage.mjs')).default,
(await import('./pages/solution/goals/FunctionalityPage.mjs')).default,
Expand Down
3 changes: 2 additions & 1 deletion src/presentation/pages/solution/NewSolutionPage.mts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ export default class NewSolutionPage extends Page {
}),
environment = new Environment({
id: solution.environmentId,
glossaryIds: []
glossaryIds: [],
constraintIds: []
}),
goals = new Goals({
id: solution.goalsId,
Expand Down
1 change: 1 addition & 0 deletions src/presentation/pages/solution/SolutionIndexPage.mts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default class SolutionIndexPage extends Page {
static {
customElements.define('x-page-solution-index', this);
}

constructor() {
super({ title: 'Solutions' }, [
new PegsCards({
Expand Down
82 changes: 82 additions & 0 deletions src/presentation/pages/solution/environment/ConstraintsPage.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import type { Uuid } from '~/types/Uuid.mjs';
import type Environment from '~/domain/Environment.mjs';
import Constraint, { ConstraintCategory } from '~/domain/Constraint.mjs';
import SolutionRepository from '~/data/SolutionRepository.mjs';
import EnvironmentRepository from '~/data/EnvironmentRepository.mjs';
import ConstraintRepository from '~/data/ConstraintRepository.mjs';
import Page from '~/presentation/pages/Page.mjs';
import { DataTable } from '~/presentation/components/DataTable.mjs';
import html from '~/presentation/lib/html.mjs';

const { p } = html;

export default class ConstraintsPage extends Page {
static override route = '/:solution/environment/constraints';
static {
customElements.define('x-page-constraints', this);
}

#solutionRepository = new SolutionRepository(localStorage);
#environmentRepository = new EnvironmentRepository(localStorage);
#constraintRepository = new ConstraintRepository(localStorage);
#environment?: Environment;

constructor() {
super({ title: 'Constraints' }, []);

const dataTable = new DataTable<Constraint>({
columns: {
id: { headerText: 'ID', readonly: true, formType: 'hidden', unique: true },
statement: { headerText: 'Statement', required: true, formType: 'text', unique: true },
category: {
headerText: 'Category', formType: 'select',
options: Object.values(ConstraintCategory).map(x => ({ value: x, text: x }))
}
},
select: async () => {
if (!this.#environment)
return [];

return await this.#constraintRepository.getAll(t => this.#environment!.constraintIds.includes(t.id));
},
onCreate: async item => {
const constraint = new Constraint({ ...item, id: self.crypto.randomUUID() });
this.#environment!.constraintIds.push(constraint.id);
await Promise.all([
this.#constraintRepository.add(constraint),
this.#environmentRepository.update(this.#environment!)
]);
},
onUpdate: async item => {
await this.#constraintRepository.update(new Constraint({
...item
}));
},
onDelete: async id => {
this.#environment!.constraintIds = this.#environment!.constraintIds.filter(x => x !== id);
await Promise.all([
this.#constraintRepository.delete(id),
this.#environmentRepository.update(this.#environment!)
]);
}
});

this.append(
p(`
Environmental constraints are the limitations and obligations that
the environment imposes on the project and system.
`),
dataTable
);

this.#environmentRepository.addEventListener('update', () => dataTable.renderData());
this.#constraintRepository.addEventListener('update', () => dataTable.renderData());
const solutionId = this.urlParams['solution'] as Uuid;
this.#solutionRepository.getBySlug(solutionId).then(solution => {
this.#environmentRepository.get(solution!.environmentId).then(environment => {
this.#environment = environment;
dataTable.renderData();
});
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ export default class EnvironmentsIndexPage extends Page {
icon: 'list',
href: `${location.pathname}/glossary`
}),
new MiniCard({
title: 'Constraints',
icon: 'anchor',
href: `${location.pathname}/constraints`
})
])
);
}
Expand Down

0 comments on commit bfc9b11

Please sign in to comment.