-
Notifications
You must be signed in to change notification settings - Fork 100
Mo 228 sept 24 Part 2 FE class based models #2213
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
Changes from all commits
3a47bc5
8117be1
2214d15
5fd2943
fc9ab7a
e1b56ea
2eaaf00
eace00a
5131e5b
e523515
2a24d27
b151f35
5cb4579
ae53411
14297ca
91b781b
ba1af93
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| export class ProjectFrameworksModel { | ||
| framework_id!: number; | ||
| project_id!: number; | ||
| is_demo?: boolean; | ||
|
|
||
| constructor(data: ProjectFrameworksModel) { | ||
| this.framework_id = data.framework_id; | ||
| this.project_id = data.project_id; | ||
| this.is_demo = data.is_demo; | ||
| } | ||
|
|
||
| static createNewProjectFrameworks( | ||
| data: ProjectFrameworksModel | ||
| ): ProjectFrameworksModel { | ||
| return new ProjectFrameworksModel(data); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| export class ProjectScopeModel { | ||
| id?: number; | ||
| assessmentId!: number; | ||
| describeAiEnvironment!: string; | ||
| isNewAiTechnology!: boolean; | ||
| usesPersonalData!: boolean; | ||
| projectScopeDocuments!: string; | ||
| technologyType!: string; | ||
| hasOngoingMonitoring!: boolean; | ||
| unintendedOutcomes!: string; | ||
| technologyDocumentation!: string; | ||
| is_demo?: boolean; | ||
| created_at?: Date; | ||
|
|
||
| constructor(data: ProjectScopeModel) { | ||
| this.id = data.id; | ||
| this.assessmentId = data.assessmentId; | ||
| this.describeAiEnvironment = data.describeAiEnvironment; | ||
| this.isNewAiTechnology = data.isNewAiTechnology; | ||
| this.usesPersonalData = data.usesPersonalData; | ||
| this.projectScopeDocuments = data.projectScopeDocuments; | ||
| this.technologyType = data.technologyType; | ||
| this.hasOngoingMonitoring = data.hasOngoingMonitoring; | ||
| this.unintendedOutcomes = data.unintendedOutcomes; | ||
| this.technologyDocumentation = data.technologyDocumentation; | ||
| this.is_demo = data.is_demo; | ||
| this.created_at = data.created_at; | ||
| } | ||
|
|
||
| static createNewProjectScope(data: ProjectScopeModel): ProjectScopeModel { | ||
| return new ProjectScopeModel(data); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| export class ProjectsMembersModel { | ||
| user_id!: number; | ||
| project_id!: number; | ||
| is_demo?: boolean; | ||
|
|
||
| constructor(data: ProjectsMembersModel) { | ||
| this.user_id = data.user_id; | ||
| this.project_id = data.project_id; | ||
| this.is_demo = data.is_demo; | ||
| } | ||
|
|
||
| static createNewProjectsMembers( | ||
| data: ProjectsMembersModel | ||
| ): ProjectsMembersModel { | ||
| return new ProjectsMembersModel(data); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| export class QuestionModel { | ||
| id?: number; | ||
| order_no?: number; | ||
| question!: string; | ||
| hint!: string; | ||
| priority_level!: "high priority" | "medium priority" | "low priority"; | ||
| answer_type!: string; | ||
| input_type!: string; | ||
| evidence_required!: boolean; | ||
| is_required!: boolean; | ||
| dropdown_options?: any[]; | ||
| evidence_files?: { | ||
| id: string; | ||
| fileName: string; | ||
| project_id: number; | ||
| uploaded_by: number; | ||
| uploaded_time: Date; | ||
| }[]; | ||
| answer?: string; | ||
| subtopic_id!: number; | ||
| is_demo?: boolean; | ||
| created_at?: Date; | ||
| status?: "Not started" | "In progress" | "Done"; | ||
|
|
||
| constructor(data: QuestionModel) { | ||
| this.id = data.id; | ||
| this.order_no = data.order_no; | ||
| this.question = data.question; | ||
| this.hint = data.hint; | ||
| this.priority_level = data.priority_level; | ||
| this.answer_type = data.answer_type; | ||
| this.input_type = data.input_type; | ||
| this.evidence_required = data.evidence_required; | ||
| this.is_required = data.is_required; | ||
| this.dropdown_options = data.dropdown_options; | ||
| this.evidence_files = data.evidence_files; | ||
| this.answer = data.answer; | ||
| this.subtopic_id = data.subtopic_id; | ||
| this.is_demo = data.is_demo; | ||
| this.created_at = data.created_at; | ||
| this.status = data.status; | ||
| } | ||
|
|
||
| static createNewQuestion(data: QuestionModel): QuestionModel { | ||
| return new QuestionModel(data); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| export class RiskModel { | ||
| id?: number; | ||
| risk_name!: string; | ||
| risk_owner!: number; | ||
| ai_lifecycle_phase!: | ||
| | "Problem definition & planning" | ||
| | "Data collection & processing" | ||
| | "Model development & training" | ||
| | "Model validation & testing" | ||
| | "Deployment & integration" | ||
| | "Monitoring & maintenance" | ||
| | "Decommissioning & retirement"; | ||
| risk_description!: string; | ||
| risk_category!: string[]; | ||
| impact!: string; | ||
| assessment_mapping!: string; | ||
| controls_mapping!: string; | ||
| likelihood!: "Rare" | "Unlikely" | "Possible" | "Likely" | "Almost Certain"; | ||
| severity!: "Negligible" | "Minor" | "Moderate" | "Major" | "Catastrophic"; | ||
| risk_level_autocalculated!: | ||
| | "No risk" | ||
| | "Very low risk" | ||
| | "Low risk" | ||
| | "Medium risk" | ||
| | "High risk" | ||
| | "Very high risk"; | ||
| review_notes!: string; | ||
| mitigation_status!: | ||
| | "Not Started" | ||
| | "In Progress" | ||
| | "Completed" | ||
| | "On Hold" | ||
| | "Deferred" | ||
| | "Canceled" | ||
| | "Requires review"; | ||
| current_risk_level!: | ||
| | "Very Low risk" | ||
| | "Low risk" | ||
| | "Medium risk" | ||
| | "High risk" | ||
| | "Very high risk"; | ||
| deadline!: Date; | ||
| mitigation_plan!: string; | ||
| implementation_strategy!: string; | ||
| mitigation_evidence_document!: string; | ||
| likelihood_mitigation!: | ||
| | "Rare" | ||
| | "Unlikely" | ||
| | "Possible" | ||
| | "Likely" | ||
| | "Almost Certain"; | ||
| risk_severity!: "Negligible" | "Minor" | "Moderate" | "Major" | "Critical"; | ||
| final_risk_level!: string; | ||
| risk_approval!: number; | ||
| approval_status!: string; | ||
| date_of_assessment!: Date; | ||
| is_demo?: boolean; | ||
| created_at?: Date; | ||
|
|
||
| constructor(data: RiskModel) { | ||
| this.id = data.id; | ||
| this.risk_name = data.risk_name; | ||
| this.risk_owner = data.risk_owner; | ||
| this.ai_lifecycle_phase = data.ai_lifecycle_phase; | ||
| this.risk_description = data.risk_description; | ||
| this.risk_category = data.risk_category; | ||
| this.impact = data.impact; | ||
| this.assessment_mapping = data.assessment_mapping; | ||
| this.controls_mapping = data.controls_mapping; | ||
| this.likelihood = data.likelihood; | ||
| this.severity = data.severity; | ||
| this.risk_level_autocalculated = data.risk_level_autocalculated; | ||
| this.review_notes = data.review_notes; | ||
| this.mitigation_status = data.mitigation_status; | ||
| this.current_risk_level = data.current_risk_level; | ||
| this.deadline = data.deadline; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Parse API date strings into Date in the constructor. Backends generally return ISO strings; assigning directly to Date-typed fields risks Invalid Date or runtime issues when using Date APIs. Apply this diff: - this.deadline = data.deadline;
+ this.deadline =
+ typeof data.deadline === "string" || typeof data.deadline === "number"
+ ? new Date(data.deadline)
+ : data.deadline;
- this.date_of_assessment = data.date_of_assessment;
+ this.date_of_assessment =
+ typeof data.date_of_assessment === "string" || typeof data.date_of_assessment === "number"
+ ? new Date(data.date_of_assessment)
+ : data.date_of_assessment;
- this.created_at = data.created_at;
+ this.created_at =
+ data.created_at == null
+ ? undefined
+ : typeof data.created_at === "string" || typeof data.created_at === "number"
+ ? new Date(data.created_at)
+ : data.created_at;Also applies to: 85-85, 87-87 🤖 Prompt for AI Agents |
||
| this.mitigation_plan = data.mitigation_plan; | ||
| this.implementation_strategy = data.implementation_strategy; | ||
| this.mitigation_evidence_document = data.mitigation_evidence_document; | ||
| this.likelihood_mitigation = data.likelihood_mitigation; | ||
| this.risk_severity = data.risk_severity; | ||
| this.final_risk_level = data.final_risk_level; | ||
| this.risk_approval = data.risk_approval; | ||
| this.approval_status = data.approval_status; | ||
| this.date_of_assessment = data.date_of_assessment; | ||
| this.is_demo = data.is_demo; | ||
| this.created_at = data.created_at; | ||
| } | ||
|
|
||
| static createNewRisk(data: RiskModel): RiskModel { | ||
| return new RiskModel(data); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| export class RoleModel { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Constructor should accept a DTO (not RoleModel) and normalize dates. Using -export class RoleModel {
+export interface RoleDTO {
+ id?: number;
+ name: string;
+ description: string;
+ is_demo?: boolean;
+ created_at?: string | Date;
+}
+
+export class RoleModel {
id?: number;
name!: string;
description!: string;
is_demo?: boolean;
created_at?: Date;
- constructor(data: RoleModel) {
+ constructor(data: RoleDTO) {
this.id = data.id;
this.name = data.name;
this.description = data.description;
this.is_demo = data.is_demo;
- this.created_at = data.created_at;
+ this.created_at = data.created_at
+ ? new Date(data.created_at)
+ : undefined;
}
- static createRole(data: RoleModel): RoleModel {
- return new RoleModel(data);
+ static createRole(data: RoleDTO): RoleModel {
+ return new RoleModel(data);
}
}Note: Consider renaming the factory to Also applies to: 6-6, 8-14, 16-18 |
||
| id?: number; | ||
| name!: string; | ||
| description!: string; | ||
| is_demo?: boolean; | ||
| created_at?: Date; | ||
|
|
||
| constructor(data: RoleModel) { | ||
| this.id = data.id; | ||
| this.name = data.name; | ||
| this.description = data.description; | ||
| this.is_demo = data.is_demo; | ||
| this.created_at = data.created_at; | ||
| } | ||
|
|
||
| static createRole(data: RoleModel): RoleModel { | ||
| return new RoleModel(data); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| export class SubControlModel { | ||
| id?: number; | ||
| title!: string; | ||
| description!: string; | ||
| order_no?: number; | ||
| status?: "Waiting" | "In progress" | "Done"; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major 🧩 Analysis chainStatus literal consistency Confirm "In progress" matches other modules (Training Registrar uses "In progress" after fix). 🏁 Script executed: #!/bin/bash
rg -n -C1 -P '"In progress"|"In Progress"' Clients/srcLength of output: 18542 Status literal consistency 🤖 Prompt for AI Agents |
||
| approver?: number; | ||
| risk_review?: "Acceptable risk" | "Residual risk" | "Unacceptable risk"; | ||
| owner?: number; | ||
| reviewer?: number; | ||
| due_date?: Date; | ||
| implementation_details?: string; | ||
| evidence_description?: string; | ||
| feedback_description?: string; | ||
| evidence_files?: { | ||
| id: string; | ||
| fileName: string; | ||
| project_id: number; | ||
| uploaded_by: number; | ||
| uploaded_time: Date; | ||
| }[]; | ||
| feedback_files?: { | ||
| id: string; | ||
| fileName: string; | ||
| project_id: number; | ||
| uploaded_by: number; | ||
| uploaded_time: Date; | ||
| }[]; | ||
| control_id!: number; | ||
| is_demo?: boolean; | ||
| created_at?: Date; | ||
|
|
||
| constructor(data: SubControlModel) { | ||
| this.id = data.id; | ||
| this.title = data.title; | ||
| this.description = data.description; | ||
| this.order_no = data.order_no; | ||
| this.status = data.status; | ||
| this.approver = data.approver; | ||
| this.risk_review = data.risk_review; | ||
| this.owner = data.owner; | ||
| this.reviewer = data.reviewer; | ||
| this.due_date = data.due_date; | ||
| this.implementation_details = data.implementation_details; | ||
| this.evidence_description = data.evidence_description; | ||
| this.feedback_description = data.feedback_description; | ||
| this.evidence_files = data.evidence_files; | ||
| this.feedback_files = data.feedback_files; | ||
| this.control_id = data.control_id; | ||
| this.is_demo = data.is_demo; | ||
| this.created_at = data.created_at; | ||
| } | ||
|
|
||
| static createSubControl(data: SubControlModel): SubControlModel { | ||
| return new SubControlModel(data); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| export class SubscriptionModel { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major 🧩 Analysis chainDefine Current signature requires Please confirm backend status literals (is it "canceled" or "cancelled"?). Script to scan the repo: Proposed changes: -export class SubscriptionModel {
+export type SubscriptionStatus = "active" | "inactive" | "canceled";
+
+export interface SubscriptionDTO {
+ id?: number;
+ organization_id: number;
+ tier_id: number;
+ stripe_sub_id: string;
+ status: SubscriptionStatus;
+ start_date: string | Date;
+ end_date?: string | Date;
+ created_at: string | Date;
+ updated_at: string | Date;
+}
+
+export class SubscriptionModel {
id?: number;
organization_id!: number;
tier_id!: number;
stripe_sub_id!: string;
- status!: "active" | "inactive" | "canceled";
+ status!: SubscriptionStatus;
start_date!: Date;
end_date?: Date;
created_at!: Date;
updated_at!: Date;
- constructor(data: SubscriptionModel) {
+ constructor(data: SubscriptionDTO) {
this.id = data.id;
this.organization_id = data.organization_id;
this.tier_id = data.tier_id;
this.stripe_sub_id = data.stripe_sub_id;
this.status = data.status;
- this.start_date = data.start_date;
- this.end_date = data.end_date;
- this.created_at = data.created_at;
- this.updated_at = data.updated_at;
+ this.start_date = new Date(data.start_date);
+ this.end_date = data.end_date ? new Date(data.end_date) : undefined;
+ this.created_at = new Date(data.created_at);
+ this.updated_at = new Date(data.updated_at);
}
- static createSubscription(data: SubscriptionModel): SubscriptionModel {
+ static createSubscription(data: SubscriptionDTO): SubscriptionModel {
return new SubscriptionModel(data);
}
}Also applies to: 2-10, 12-22, 24-26 🏁 Script executed: #!/bin/bash
# Search for subscription status literals across the repo
rg -nP -C2 '\b(cancelled|canceled|active|inactive)\b' --type-add 'all:*.{ts,tsx,js,py,go,rb,java}'Length of output: 59 🏁 Script executed: #!/bin/bash
# Search for subscription status literals across relevant source files
rg -nP -C2 '\b(cancelled|canceled|active|inactive)\b' -g '*.{ts,tsx,js,py,go,rb,java}'Length of output: 28300 Refactor SubscriptionModel to use SubscriptionDTO and enforce type-safe status
🤖 Prompt for AI Agents |
||
| id?: number; | ||
| organization_id!: number; | ||
| tier_id!: number; | ||
| stripe_sub_id!: string; | ||
| status!: "active" | "inactive" | "canceled"; | ||
| start_date!: Date; | ||
| end_date?: Date; | ||
| created_at!: Date; | ||
| updated_at!: Date; | ||
|
|
||
| constructor(data: SubscriptionModel) { | ||
| this.id = data.id; | ||
| this.organization_id = data.organization_id; | ||
| this.tier_id = data.tier_id; | ||
| this.stripe_sub_id = data.stripe_sub_id; | ||
| this.status = data.status; | ||
| this.start_date = data.start_date; | ||
| this.end_date = data.end_date; | ||
| this.created_at = data.created_at; | ||
| this.updated_at = data.updated_at; | ||
| } | ||
|
|
||
| static createSubscription(data: SubscriptionModel): SubscriptionModel { | ||
| return new SubscriptionModel(data); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| export class SubtopicModel { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Adopt DTO input and normalize Same rationale/pattern as TopicModel. -export class SubtopicModel {
+export interface SubtopicDTO {
+ id?: number;
+ title: string;
+ order_no?: number;
+ topic_id: number;
+ is_demo?: boolean;
+ created_at?: string | Date;
+}
+
+export class SubtopicModel {
id?: number;
title!: string;
order_no?: number;
topic_id!: number;
is_demo?: boolean;
created_at?: Date;
- constructor(data: SubtopicModel) {
+ constructor(data: SubtopicDTO) {
this.id = data.id;
this.title = data.title;
this.order_no = data.order_no;
this.topic_id = data.topic_id;
this.is_demo = data.is_demo;
- this.created_at = data.created_at;
+ this.created_at = data.created_at ? new Date(data.created_at) : undefined;
}
- static createSubtopic(data: SubtopicModel): SubtopicModel {
+ static createSubtopic(data: SubtopicDTO): SubtopicModel {
return new SubtopicModel(data);
}
}Also applies to: 7-7, 9-16, 18-20 🤖 Prompt for AI Agents |
||
| id?: number; | ||
| title!: string; | ||
| order_no?: number; | ||
| topic_id!: number; | ||
| is_demo?: boolean; | ||
| created_at?: Date; | ||
|
|
||
| constructor(data: SubtopicModel) { | ||
| this.id = data.id; | ||
| this.title = data.title; | ||
| this.order_no = data.order_no; | ||
| this.topic_id = data.topic_id; | ||
| this.is_demo = data.is_demo; | ||
| this.created_at = data.created_at; | ||
| } | ||
|
|
||
| static createSubtopic(data: SubtopicModel): SubtopicModel { | ||
| return new SubtopicModel(data); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| import { TaskPriority, TaskStatus } from "../../interfaces/i.task"; | ||
|
|
||
| export class TaskModel { | ||
| id?: number; | ||
| title!: string; | ||
| description?: string; | ||
| creator_id!: number; | ||
| organization_id!: number; | ||
| due_date?: Date; | ||
| priority!: TaskPriority; | ||
| status!: TaskStatus; | ||
| categories?: string[]; | ||
| created_at?: Date; | ||
| updated_at?: Date; | ||
|
|
||
| constructor(data: TaskModel) { | ||
| this.id = data.id; | ||
| this.title = data.title; | ||
| this.description = data.description; | ||
| this.creator_id = data.creator_id; | ||
| this.organization_id = data.organization_id; | ||
| this.due_date = data.due_date; | ||
| this.priority = data.priority; | ||
| this.status = data.status; | ||
| this.categories = data.categories; | ||
| this.created_at = data.created_at; | ||
| this.updated_at = data.updated_at; | ||
| } | ||
|
|
||
| static createTask(data: TaskModel): TaskModel { | ||
| return new TaskModel(data); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| export class TaskAssigneeModel { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Accept DTO and coerce Mirror the DTO+normalization pattern so callers can pass API payloads safely. -export class TaskAssigneeModel {
+export interface TaskAssigneeDTO {
+ task_id: number;
+ user_id: number;
+ assigned_at?: string | Date;
+}
+
+export class TaskAssigneeModel {
task_id!: number;
user_id!: number;
assigned_at?: Date;
- constructor(data: TaskAssigneeModel) {
+ constructor(data: TaskAssigneeDTO) {
this.task_id = data.task_id;
this.user_id = data.user_id;
- this.assigned_at = data.assigned_at;
+ this.assigned_at = data.assigned_at
+ ? new Date(data.assigned_at)
+ : undefined;
}
- static createTaskAssignee(data: TaskAssigneeModel): TaskAssigneeModel {
+ static createTaskAssignee(data: TaskAssigneeDTO): TaskAssigneeModel {
return new TaskAssigneeModel(data);
}
}Also applies to: 4-4, 6-10, 12-14 🤖 Prompt for AI Agents |
||
| task_id!: number; | ||
| user_id!: number; | ||
| assigned_at?: Date; | ||
|
|
||
| constructor(data: TaskAssigneeModel) { | ||
| this.task_id = data.task_id; | ||
| this.user_id = data.user_id; | ||
| this.assigned_at = data.assigned_at; | ||
| } | ||
|
|
||
| static createTaskAssignee(data: TaskAssigneeModel): TaskAssigneeModel { | ||
| return new TaskAssigneeModel(data); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix casing mismatch in risk levels (compile-time inconsistency).
"Very Low risk" vs "Very low risk" will cause type mismatches across the app. Align to a single canonical value.
Apply this diff:
🤖 Prompt for AI Agents