Skip to content

Commit

Permalink
Implemented Roles & Personnel (#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
mlhaufe authored Jun 12, 2024
1 parent 1dfaf58 commit 5eba936
Show file tree
Hide file tree
Showing 17 changed files with 431 additions and 29 deletions.
20 changes: 0 additions & 20 deletions domain/Project.ts

This file was deleted.

25 changes: 25 additions & 0 deletions modules/project/application/CreatePersonUseCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type Repository from "~/application/Repository"
import UseCase from "~/application/UseCase"
import Person from "../domain/Person"
import { emptyUuid, type Uuid } from "~/domain/Uuid"

type In = Pick<Person, 'projectId' | 'email' | 'roleId' | 'name'>

export default class CreatePersonUseCase extends UseCase<In, Uuid> {
constructor(readonly repository: Repository<Person>) {
super()
}

async execute({ name, projectId, email, roleId }: In): Promise<Uuid> {
return await this.repository.add(new Person({
id: crypto.randomUUID(),
projectId,
email,
roleId,
name,
parentId: emptyUuid,
property: '',
statement: ''
}))
}
}
19 changes: 19 additions & 0 deletions modules/project/application/CreateProjectUseCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type Repository from "~/application/Repository";
import UseCase from "~/application/UseCase";
import type { Uuid } from "~/domain/Uuid";
import Project from "../domain/Project";

export default class CreateProjectUseCase extends UseCase<Uuid, Uuid> {
constructor(readonly repository: Repository<Project>) {
super()
}

async execute(solutionId: Uuid): Promise<Uuid> {
return await this.repository.add(new Project({
id: crypto.randomUUID(),
solutionId,
componentIds: [],
limitationIds: []
}))
}
}
14 changes: 14 additions & 0 deletions modules/project/application/DeletePersonUseCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import UseCase from "~/application/UseCase"
import type { Uuid } from "~/domain/Uuid"
import type Person from "../domain/Person"
import type Repository from "~/application/Repository"

export default class DeletePersonUseCase extends UseCase<Uuid, void> {
constructor(readonly repository: Repository<Person>) {
super()
}

async execute(id: Uuid): Promise<void> {
return await this.repository.delete(id)
}
}
14 changes: 14 additions & 0 deletions modules/project/application/GetPersonnelUseCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import UseCase from "~/application/UseCase";
import type Person from "../domain/Person";
import type { Uuid } from "~/domain/Uuid";
import type Repository from "~/application/Repository";

export default class GetPersonnelUseCase extends UseCase<Uuid, Person[] | undefined> {
constructor(readonly repository: Repository<Person>) {
super()
}

async execute(projectId: Uuid): Promise<Person[] | undefined> {
return this.repository.getAll(p => p.projectId === projectId)
}
}
16 changes: 16 additions & 0 deletions modules/project/application/GetProjectBySolutionIdUseCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import UseCase from "~/application/UseCase";
import type Repository from "~/application/Repository";
import type Project from "../domain/Project";
import type { Uuid } from "~/domain/Uuid";

export default class GetProjectBySolutionIdUseCase extends UseCase<Uuid, Project | undefined> {
constructor(readonly repository: Repository<Project>) {
super()
}

async execute(solutionId: Uuid): Promise<Project | undefined> {
const projects = await this.repository.getAll(g => g.solutionId === solutionId)

return projects[0]
}
}
25 changes: 25 additions & 0 deletions modules/project/application/UpdatePersonUseCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import UseCase from "~/application/UseCase";
import Person from "../domain/Person";
import type Repository from "~/application/Repository";
import { emptyUuid } from "~/domain/Uuid";

type In = Pick<Person, 'id' | 'projectId' | 'email' | 'roleId' | 'name'>

export default class UpdatePersonUseCase extends UseCase<In, void> {
constructor(readonly repository: Repository<Person>) {
super()
}

async execute({ id, name, projectId, email, roleId }: In): Promise<void> {
return await this.repository.update(new Person({
id,
projectId,
email,
roleId,
name,
parentId: emptyUuid,
property: '',
statement: ''
}))
}
}
16 changes: 16 additions & 0 deletions modules/project/data/PersonRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Properties } from "~/domain/Properties";
import StorageRepository from "~/data/StorageRepository.js";
import type Person from "../domain/Person";
import PersonToJsonMapper from "../mappers/PersonToJsonMapper";

const { serializationVersion } = useAppConfig()

export default class PersonRepository extends StorageRepository<Person> {
constructor(properties: Properties<Omit<PersonRepository, 'storageKey' | 'mapper'>> = {}) {
super({
...properties,
storageKey: 'person',
mapper: new PersonToJsonMapper(serializationVersion)
})
}
}
16 changes: 16 additions & 0 deletions modules/project/data/ProjectRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type Project from "../domain/Project";
import type { Properties } from "~/domain/Properties";
import StorageRepository from "~/data/StorageRepository.js";
import ProjectToJsonMapper from "../mappers/ProjectToJsonMapper";

const { serializationVersion } = useAppConfig()

export default class ProjectRepository extends StorageRepository<Project> {
constructor(properties: Properties<Omit<ProjectRepository, 'storageKey' | 'mapper'>> = {}) {
super({
...properties,
storageKey: 'project',
mapper: new ProjectToJsonMapper(serializationVersion)
})
}
}
15 changes: 15 additions & 0 deletions modules/project/domain/Person.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Actor from "~/domain/Actor";
import type { Properties } from "~/domain/Properties";
import type { Uuid } from "~/domain/Uuid";

export default class Person extends Actor {
constructor({ email, roleId, projectId, ...rest }: Properties<Person>) {
super(rest);

Object.assign(this, { email, roleId, projectId });
}

email!: string;
roleId!: Uuid;
projectId!: Uuid;
}
7 changes: 7 additions & 0 deletions modules/project/domain/Project.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import PEGS from "../../../domain/PEGS";

/**
* The set of human processes involved in the plannimg, construction,
* revision, and operation of a system
*/
export default class Project extends PEGS { }
6 changes: 5 additions & 1 deletion modules/project/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ export default defineNuxtModule({
pages.push({
name: 'Project',
path: '/solution/:solutionSlug/project',
file: resolve('./ui/pages/ProjectIndex.vue')
file: resolve('./ui/pages/Index.vue')
}, {
name: 'Roles & Personnel',
path: '/solution/:solutionSlug/project/roles-personnel',
file: resolve('./ui/pages/RolesPersonnel.vue')
})
})
}
Expand Down
31 changes: 31 additions & 0 deletions modules/project/mappers/PersonToJsonMapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import RequirementToJsonMapper, { type RequirementJson } from "~/mappers/RequirementToJsonMapper";
import Person from "../domain/Person";
import type { Uuid } from "~/domain/Uuid";

export interface PersonJson extends RequirementJson {
email: string;
roleId: Uuid;
projectId: Uuid;
}

export default class PersonToJsonMapper extends RequirementToJsonMapper {
override mapFrom(target: PersonJson): Person {
return new Person({
...super.mapFrom(target),
email: target.email,
roleId: target.roleId,
projectId: target.projectId
})
}

override mapTo(source: Person): PersonJson {
const requirement = super.mapTo(source)

return {
...requirement,
email: source.email,
roleId: source.roleId,
projectId: source.projectId
}
}
}
23 changes: 23 additions & 0 deletions modules/project/mappers/ProjectToJsonMapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import PEGSToJsonMapper, { type PEGSJson } from "~/mappers/PEGSToJsonMapper";
import Project from "../domain/Project";

export interface ProjectJson extends PEGSJson { }

export default class ProjectToJsonMapper extends PEGSToJsonMapper {
override mapFrom(target: ProjectJson): Project {
const pegs = super.mapFrom(target)

return new Project({
id: pegs.id,
limitationIds: pegs.limitationIds,
solutionId: pegs.solutionId,
componentIds: pegs.componentIds
});
}

override mapTo(source: Project): ProjectJson {
return {
...super.mapTo(source as any)
};
}
}
61 changes: 61 additions & 0 deletions modules/project/ui/pages/Index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<script lang="ts" setup>
import GetSolutionBySlugUseCase from '~/modules/solution/application/GetSolutionBySlugUseCase';
import UpdateSolutionUseCase from '~/modules/solution/application/UpdateSolutionUseCase';
import SolutionRepository from '~/modules/solution/data/SolutionRepository';
import ProjectRepository from '../../data/ProjectRepository';
import GetProjectBySolutionIdUseCase from '../../application/GetProjectBySolutionIdUseCase';
import CreateProjectUseCase from '../../application/CreateProjectUseCase';
useHead({
title: 'Project'
})
const router = useRouter(),
route = useRoute(),
slug = route.params.solutionSlug as string,
solutionRepository = new SolutionRepository(),
projectRepository = new ProjectRepository(),
getProjectBySolutionIdUseCase = new GetProjectBySolutionIdUseCase(projectRepository),
getSolutionBySlugUseCase = new GetSolutionBySlugUseCase(solutionRepository),
createProjectUseCase = new CreateProjectUseCase(projectRepository),
updateSolutionUseCase = new UpdateSolutionUseCase(solutionRepository),
solution = await getSolutionBySlugUseCase.execute(slug)
if (!solution) {
router.push({ name: 'Solutions' });
} else {
const project = await getProjectBySolutionIdUseCase.execute(solution.id);
if (!project) {
const newId = await createProjectUseCase.execute(solution.id);
await updateSolutionUseCase.execute({
id: solution.id,
name: solution.name,
description: solution.description,
environmentId: solution.environmentId,
goalsId: solution.goalsId,
projectId: newId,
systemId: solution.systemId
});
}
}
const links = [
{ name: 'Roles & Personnel', icon: 'pi-users', label: 'Roles & Personnel' }
]
</script>
<template>
<p>
A Project is the set of human processes involved in the plannimg, construction,
revision, and operation of a system
</p>

<div class="grid">
<NuxtLink v-for="link in links" :key="link.name" :to="{ name: link.name, params: { solutionSlug: slug } }"
class="col-fixed w-2 mr-4">
<Button :label="link.label" class="w-full h-5rem text-1xl" :icon="`pi ${link.icon} text-3xl`" iconPos="top"
severity="secondary" />
</NuxtLink>
</div>
</template>
8 changes: 0 additions & 8 deletions modules/project/ui/pages/ProjectIndex.vue

This file was deleted.

Loading

0 comments on commit 5eba936

Please sign in to comment.