Frontend/backend project structure

+ Base implementation of a differential synchronization based on Neil
  Fraser article/talk

See https://www.youtube.com/watch?v=S2Hp_1jqpY8
This commit is contained in:
2020-04-27 22:43:42 +02:00
parent 40759f59d6
commit d9fb51394c
89 changed files with 2178 additions and 14 deletions

View File

@ -0,0 +1,71 @@
import { TaskCategory, TaskCategoryID } from "./task";
import { Project } from "./project";
export interface TaskCategoriesIndex {
[id: string]: TaskCategory
}
export interface TimeUnit {
label: string
acronym: string
}
export interface Params {
taskCategories: TaskCategoriesIndex
timeUnit: TimeUnit
currency: string
roundUpEstimations: boolean
hideFinancialPreviewOnPrint: boolean
}
export const defaults = {
taskCategories: {
"RQ15CD3iX1Ey2f9kat7tfLGZmUx9GGc15nS6A7fYtZv76SnS4": {
id: "RQ15CD3iX1Ey2f9kat7tfLGZmUx9GGc15nS6A7fYtZv76SnS4",
label: "Développement",
costPerTimeUnit: 500,
},
"QRdGS5Pr5si9SSjU84WAq19cjxQ3rUL71jKh8oHSMZSY4bBH9": {
id: "QRdGS5Pr5si9SSjU84WAq19cjxQ3rUL71jKh8oHSMZSY4bBH9",
label: "Conduite de projet",
costPerTimeUnit: 500,
},
"RPcqFMLdQrgBSomv7Sao7EQSb7on6rtjfDQK5JZNhNSg9DwEo": {
id: "RPcqFMLdQrgBSomv7Sao7EQSb7on6rtjfDQK5JZNhNSg9DwEo",
label: "Recette",
costPerTimeUnit: 500,
},
},
timeUnit: {
label: "jour/homme",
acronym: "j/h",
},
roundUpEstimations: true,
currency: "€ H.T.",
costPerTimeUnit: 500,
hideFinancialPreviewOnPrint: false,
}
export function getTimeUnit(project: Project): TimeUnit {
return project.params.timeUnit ? project.params.timeUnit : defaults.timeUnit;
}
export function getRoundUpEstimations(project: Project): boolean {
return project.params.hasOwnProperty("roundUpEstimations") ? project.params.roundUpEstimations : defaults.roundUpEstimations;
}
export function getCurrency(project: Project): string {
return project.params.currency ? project.params.currency : defaults.currency;
}
export function getTaskCategories(project: Project): TaskCategoriesIndex {
return project.params.taskCategories ? project.params.taskCategories : defaults.taskCategories;
}
export function getTaskCategoryCost(taskCategory: TaskCategory): number {
return taskCategory.hasOwnProperty("costPerTimeUnit") ? taskCategory.costPerTimeUnit : defaults.costPerTimeUnit;
}
export function getHideFinancialPreviewOnPrint(project: Project): boolean {
return project.params.hasOwnProperty("hideFinancialPreviewOnPrint") ? project.params.hideFinancialPreviewOnPrint : defaults.hideFinancialPreviewOnPrint;
}

View File

@ -0,0 +1,29 @@
import { Task, TaskCategory, TaskID } from './task';
import { Params, defaults } from "./params";
import { uuidV4 } from "../util/uuid";
export type ProjectID = string;
export interface Project {
id: ProjectID
label: string
description: string
tasks: Tasks
params: Params
}
export interface Tasks {
[id: string]: Task
}
export function newProject(id?: string): Project {
return {
id: id ? id : uuidV4(),
label: "",
description: "",
tasks: {},
params: {
...defaults
},
};
}

46
client/src/models/task.ts Normal file
View File

@ -0,0 +1,46 @@
import { uuidV4, base58UUID } from "../util/uuid"
import { defaults } from "./params";
export type TaskID = string
export enum EstimationConfidence {
Optimistic = "optimistic",
Likely = "likely",
Pessimistic = "pessimistic"
}
export interface Task {
id: TaskID
label: string
category: TaskCategoryID
estimations: { [confidence in EstimationConfidence]: number }
}
export type TaskCategoryID = string
export interface TaskCategory {
id: TaskCategoryID
label: string
costPerTimeUnit: number
}
export function newTask(label: string, category: TaskCategoryID): Task {
return {
id: base58UUID(),
label,
category,
estimations: {
[EstimationConfidence.Optimistic]: 0,
[EstimationConfidence.Likely]: 0,
[EstimationConfidence.Pessimistic]: 0,
}
};
}
export function createTaskCategory(): TaskCategory {
return {
id: base58UUID(),
costPerTimeUnit: defaults.costPerTimeUnit,
label: ""
};
}