Add UI input & textarea
Signed-off-by: Bryan Frimin <bryan@getprobo.com> Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
committed by
Sacha Al Himdani
parent
a86181c83d
commit
15cf471454
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
bin/
|
||||
node_modules/
|
||||
.turbo
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"relay": "npx relay-compiler",
|
||||
"build": "tsc -b && vite build",
|
||||
"lint": "eslint .",
|
||||
"check": "tsc --noEmit -p tsconfig.app.json",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -15,6 +16,8 @@
|
||||
"@probo/i18n": "1.0.0",
|
||||
"@probo/ui": "1.0.0",
|
||||
"@radix-ui/react-dialog": "^1.1.14",
|
||||
"@radix-ui/react-select": "^2.2.5",
|
||||
"@tanstack/react-query": "^5.76.1",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"react-error-boundary": "^6.0.0",
|
||||
|
||||
498
apps/console2/public/data/frameworks/ISO27001-2022.json
Normal file
498
apps/console2/public/data/frameworks/ISO27001-2022.json
Normal file
@@ -0,0 +1,498 @@
|
||||
{
|
||||
"id": "ISO/IEC 27001:2022",
|
||||
"name": "ISO 27001 (2022)",
|
||||
"controls": [
|
||||
{
|
||||
"id": "4.1",
|
||||
"name": "Context of the organization - Understanding the organization and its context"
|
||||
},
|
||||
{
|
||||
"id": "4.2",
|
||||
"name": "Context of the organization - Understanding the needs of interested parties"
|
||||
},
|
||||
{
|
||||
"id": "4.3",
|
||||
"name": "Context of the organization - Determining the scope of the information security management system"
|
||||
},
|
||||
{
|
||||
"id": "4.4",
|
||||
"name": "Context of the organization - Information security management system"
|
||||
},
|
||||
{
|
||||
"id": "5.1",
|
||||
"name": "Leadership - Leadership and commitment"
|
||||
},
|
||||
{
|
||||
"id": "5.2",
|
||||
"name": "Leadership - Policy"
|
||||
},
|
||||
{
|
||||
"id": "5.3",
|
||||
"name": "Leadership - Organizational roles, responsibilities and authorities"
|
||||
},
|
||||
{
|
||||
"id": "6.1.1",
|
||||
"name": "Planning - General actions to address risks and opportunities"
|
||||
},
|
||||
{
|
||||
"id": "6.1.2",
|
||||
"name": "Planning - Information security risk assessment"
|
||||
},
|
||||
{
|
||||
"id": "6.1.3",
|
||||
"name": "Planning - Information security risk treatment"
|
||||
},
|
||||
{
|
||||
"id": "6.2",
|
||||
"name": "Planning - Information security objective and planning to achieve them"
|
||||
},
|
||||
{
|
||||
"id": "6.3",
|
||||
"name": "Planning - Planning of Changes"
|
||||
},
|
||||
{
|
||||
"id": "7.1",
|
||||
"name": "Support - Resources"
|
||||
},
|
||||
{
|
||||
"id": "7.2",
|
||||
"name": "Support - Competence"
|
||||
},
|
||||
{
|
||||
"id": "7.3",
|
||||
"name": "Support - Awareness"
|
||||
},
|
||||
{
|
||||
"id": "7.4",
|
||||
"name": "Support - Communication"
|
||||
},
|
||||
{
|
||||
"id": "7.5.1",
|
||||
"name": "Support - Documented information"
|
||||
},
|
||||
{
|
||||
"id": "7.5.2",
|
||||
"name": "Support - Creating and Updating"
|
||||
},
|
||||
{
|
||||
"id": "7.5.3",
|
||||
"name": "Support - Control of documented information"
|
||||
},
|
||||
{
|
||||
"id": "8.1",
|
||||
"name": "Operation - Operation planning and control"
|
||||
},
|
||||
{
|
||||
"id": "8.2",
|
||||
"name": "Operation - Information security risk assessment"
|
||||
},
|
||||
{
|
||||
"id": "8.3",
|
||||
"name": "Operation - Information security risk treatment"
|
||||
},
|
||||
{
|
||||
"id": "9.1",
|
||||
"name": "Performance evaluation - Monitoring, measurement, analysis, and evaluation"
|
||||
},
|
||||
{
|
||||
"id": "9.2.1",
|
||||
"name": "Performance evaluation - Internal Audit - General"
|
||||
},
|
||||
{
|
||||
"id": "9.2.2",
|
||||
"name": "Performance evaluation - Internal Audit Program"
|
||||
},
|
||||
{
|
||||
"id": "9.3.1",
|
||||
"name": "Performance evaluation - Management review - General"
|
||||
},
|
||||
{
|
||||
"id": "9.3.2",
|
||||
"name": "Performance evaluation - Management review inputs"
|
||||
},
|
||||
{
|
||||
"id": "9.3.3",
|
||||
"name": "Performance evaluation - Management review results"
|
||||
},
|
||||
{
|
||||
"id": "10.1",
|
||||
"name": "Improvement - Continual Improvement"
|
||||
},
|
||||
{
|
||||
"id": "10.2",
|
||||
"name": "Improvement - Nonconformity and corrective action"
|
||||
},
|
||||
{
|
||||
"id": "A.5.1",
|
||||
"name": "Organizational - Policies for information security"
|
||||
},
|
||||
{
|
||||
"id": "A.5.2",
|
||||
"name": "Organizational - Information security roles and responsibilities"
|
||||
},
|
||||
{
|
||||
"id": "A.5.3",
|
||||
"name": "Organizational - Segregation of duties"
|
||||
},
|
||||
{
|
||||
"id": "A.5.4",
|
||||
"name": "Organizational - Management responsibilities"
|
||||
},
|
||||
{
|
||||
"id": "A.5.5",
|
||||
"name": "Organizational - Contact with authorities"
|
||||
},
|
||||
{
|
||||
"id": "A.5.6",
|
||||
"name": "Organizational - Contact with special interest groups"
|
||||
},
|
||||
{
|
||||
"id": "A.5.7",
|
||||
"name": "Organizational - Threat Intelligence"
|
||||
},
|
||||
{
|
||||
"id": "A.5.8",
|
||||
"name": "Organizational - Information security in project management"
|
||||
},
|
||||
{
|
||||
"id": "A.5.9",
|
||||
"name": "Organizational - Inventory of information and other associated assets"
|
||||
},
|
||||
{
|
||||
"id": "A.5.10",
|
||||
"name": "Organizational - Acceptable use of information and other associated assets"
|
||||
},
|
||||
{
|
||||
"id": "A.5.11",
|
||||
"name": "Organizational - Return of assets"
|
||||
},
|
||||
{
|
||||
"id": "A.5.12",
|
||||
"name": "Organizational - Classification of information"
|
||||
},
|
||||
{
|
||||
"id": "A.5.13",
|
||||
"name": "Organizational - Labelling of information"
|
||||
},
|
||||
{
|
||||
"id": "A.5.14",
|
||||
"name": "Organizational - Information transfer"
|
||||
},
|
||||
{
|
||||
"id": "A.5.15",
|
||||
"name": "Organizational - Access control"
|
||||
},
|
||||
{
|
||||
"id": "A.5.16",
|
||||
"name": "Organizational - Identity management"
|
||||
},
|
||||
{
|
||||
"id": "A.5.17",
|
||||
"name": "Organizational - Authentication information"
|
||||
},
|
||||
{
|
||||
"id": "A.5.18",
|
||||
"name": "Organizational - Access rights"
|
||||
},
|
||||
{
|
||||
"id": "A.5.19",
|
||||
"name": "Organizational - Information security in supplier relationships"
|
||||
},
|
||||
{
|
||||
"id": "A.5.20",
|
||||
"name": "Organizational - Addressing information security within supplier agreements"
|
||||
},
|
||||
{
|
||||
"id": "A.5.21",
|
||||
"name": "Organizational - Managing information security in the ICT supply chain"
|
||||
},
|
||||
{
|
||||
"id": "A.5.22",
|
||||
"name": "Organizational - Monitoring, review and change management of supplier services"
|
||||
},
|
||||
{
|
||||
"id": "A.5.23",
|
||||
"name": "Organizational - Information security for use of cloud services"
|
||||
},
|
||||
{
|
||||
"id": "A.5.24",
|
||||
"name": "Organizational - Information security incident management planning and preparation"
|
||||
},
|
||||
{
|
||||
"id": "A.5.25",
|
||||
"name": "Organizational - Assessment and decision on information security events"
|
||||
},
|
||||
{
|
||||
"id": "A.5.26",
|
||||
"name": "Organizational - Response to information security incidents"
|
||||
},
|
||||
{
|
||||
"id": "A.5.27",
|
||||
"name": "Organizational - Learning from information security incidents"
|
||||
},
|
||||
{
|
||||
"id": "A.5.28",
|
||||
"name": "Organizational - Collection of evidence"
|
||||
},
|
||||
{
|
||||
"id": "A.5.29",
|
||||
"name": "Organizational - Information security during disruption"
|
||||
},
|
||||
{
|
||||
"id": "A.5.30",
|
||||
"name": "Organizational - ICT readiness for business continuity"
|
||||
},
|
||||
{
|
||||
"id": "A.5.31",
|
||||
"name": "Organizational - Legal, statutory, regulatory and contractual requirements"
|
||||
},
|
||||
{
|
||||
"id": "A.5.32",
|
||||
"name": "Organizational - Intellectual property rights"
|
||||
},
|
||||
{
|
||||
"id": "A.5.33",
|
||||
"name": "Organizational - Protection of records"
|
||||
},
|
||||
{
|
||||
"id": "A.5.34",
|
||||
"name": "Organizational - Privacy and protection of PII"
|
||||
},
|
||||
{
|
||||
"id": "A.5.35",
|
||||
"name": "Organizational - Independent review of information security"
|
||||
},
|
||||
{
|
||||
"id": "A.5.36",
|
||||
"name": "Organizational - Compliance with policies, rules and standards for information security"
|
||||
},
|
||||
{
|
||||
"id": "A.5.37",
|
||||
"name": "Organizational - Documented operating procedures"
|
||||
},
|
||||
{
|
||||
"id": "A.6.1",
|
||||
"name": "People - Screening"
|
||||
},
|
||||
{
|
||||
"id": "A.6.2",
|
||||
"name": "People - Terms and conditions of employment"
|
||||
},
|
||||
{
|
||||
"id": "A.6.3",
|
||||
"name": "People - Information security awareness, education and training"
|
||||
},
|
||||
{
|
||||
"id": "A.6.4",
|
||||
"name": "People - Disciplinary process"
|
||||
},
|
||||
{
|
||||
"id": "A.6.5",
|
||||
"name": "People - Responsibilities after termination or change of employment"
|
||||
},
|
||||
{
|
||||
"id": "A.6.6",
|
||||
"name": "People - Confidentiality or non-disclosure agreements"
|
||||
},
|
||||
{
|
||||
"id": "A.6.7",
|
||||
"name": "People - Remote working"
|
||||
},
|
||||
{
|
||||
"id": "A.6.8",
|
||||
"name": "People - Information security event reporting"
|
||||
},
|
||||
{
|
||||
"id": "A.7.1",
|
||||
"name": "Physical - Physical security perimeters"
|
||||
},
|
||||
{
|
||||
"id": "A.7.2",
|
||||
"name": "Physical - Physical entry"
|
||||
},
|
||||
{
|
||||
"id": "A.7.3",
|
||||
"name": "Physical - Securing offices, rooms and facilities"
|
||||
},
|
||||
{
|
||||
"id": "A.7.4",
|
||||
"name": "Physical - Physical security monitoring"
|
||||
},
|
||||
{
|
||||
"id": "A.7.5",
|
||||
"name": "Physical - Protecting against physical and environmental threats"
|
||||
},
|
||||
{
|
||||
"id": "A.7.6",
|
||||
"name": "Physical - Working in secure areas"
|
||||
},
|
||||
{
|
||||
"id": "A.7.7",
|
||||
"name": "Physical - Clear desk and clear screen"
|
||||
},
|
||||
{
|
||||
"id": "A.7.8",
|
||||
"name": "Physical - Equipment siting and protection"
|
||||
},
|
||||
{
|
||||
"id": "A.7.9",
|
||||
"name": "Physical - Security of assets off-premises"
|
||||
},
|
||||
{
|
||||
"id": "A.7.10",
|
||||
"name": "Physical - Storage media"
|
||||
},
|
||||
{
|
||||
"id": "A.7.11",
|
||||
"name": "Physical - Supporting utilities"
|
||||
},
|
||||
{
|
||||
"id": "A.7.12",
|
||||
"name": "Physical - Cabling security"
|
||||
},
|
||||
{
|
||||
"id": "A.7.13",
|
||||
"name": "Physical - Equipment maintenance"
|
||||
},
|
||||
{
|
||||
"id": "A.7.14",
|
||||
"name": "Physical - Secure disposal or re-use of equipment"
|
||||
},
|
||||
{
|
||||
"id": "A.8.1",
|
||||
"name": "Technological - User endpoint devices"
|
||||
},
|
||||
{
|
||||
"id": "A.8.2",
|
||||
"name": "Technological - Privileged access rights"
|
||||
},
|
||||
{
|
||||
"id": "A.8.3",
|
||||
"name": "Technological - Information access restriction"
|
||||
},
|
||||
{
|
||||
"id": "A.8.4",
|
||||
"name": "Technological - Access to source code"
|
||||
},
|
||||
{
|
||||
"id": "A.8.5",
|
||||
"name": "Technological - Secure authentication"
|
||||
},
|
||||
{
|
||||
"id": "A.8.6",
|
||||
"name": "Technological - Capacity management"
|
||||
},
|
||||
{
|
||||
"id": "A.8.7",
|
||||
"name": "Technological - Protection against malware"
|
||||
},
|
||||
{
|
||||
"id": "A.8.8",
|
||||
"name": "Technological - Management of technical vulnerabilities"
|
||||
},
|
||||
{
|
||||
"id": "A.8.9",
|
||||
"name": "Technological - Configuration management"
|
||||
},
|
||||
{
|
||||
"id": "A.8.10",
|
||||
"name": "Technological - Information deletion"
|
||||
},
|
||||
{
|
||||
"id": "A.8.11",
|
||||
"name": "Technological - Data masking"
|
||||
},
|
||||
{
|
||||
"id": "A.8.12",
|
||||
"name": "Technological - Data leakage prevention"
|
||||
},
|
||||
{
|
||||
"id": "A.8.13",
|
||||
"name": "Technological - Information backup"
|
||||
},
|
||||
{
|
||||
"id": "A.8.14",
|
||||
"name": "Technological - Redundancy of information processing facilities"
|
||||
},
|
||||
{
|
||||
"id": "A.8.15",
|
||||
"name": "Technological - Logging"
|
||||
},
|
||||
{
|
||||
"id": "A.8.16",
|
||||
"name": "Technological - Monitoring activities"
|
||||
},
|
||||
{
|
||||
"id": "A.8.17",
|
||||
"name": "Technological - Clock synchronization"
|
||||
},
|
||||
{
|
||||
"id": "A.8.18",
|
||||
"name": "Technological - Use of privileged utility programs"
|
||||
},
|
||||
{
|
||||
"id": "A.8.19",
|
||||
"name": "Technological - Installation of software on operational systems"
|
||||
},
|
||||
{
|
||||
"id": "A.8.20",
|
||||
"name": "Technological - Networks security"
|
||||
},
|
||||
{
|
||||
"id": "A.8.21",
|
||||
"name": "Technological - Security of network services"
|
||||
},
|
||||
{
|
||||
"id": "A.8.22",
|
||||
"name": "Technological - Segregation of networks"
|
||||
},
|
||||
{
|
||||
"id": "A.8.23",
|
||||
"name": "Technological - Web filtering"
|
||||
},
|
||||
{
|
||||
"id": "A.8.24",
|
||||
"name": "Technological - Use of cryptography"
|
||||
},
|
||||
{
|
||||
"id": "A.8.25",
|
||||
"name": "Technological - Secure development life cycle"
|
||||
},
|
||||
{
|
||||
"id": "A.8.26",
|
||||
"name": "Technological - Application security requirements"
|
||||
},
|
||||
{
|
||||
"id": "A.8.27",
|
||||
"name": "Technological - Secure system architecture and engineering principles"
|
||||
},
|
||||
{
|
||||
"id": "A.8.28",
|
||||
"name": "Technological - Secure coding"
|
||||
},
|
||||
{
|
||||
"id": "A.8.29",
|
||||
"name": "Technological - Security testing in development and acceptance"
|
||||
},
|
||||
{
|
||||
"id": "A.8.30",
|
||||
"name": "Technological - Outsourced development"
|
||||
},
|
||||
{
|
||||
"id": "A.8.31",
|
||||
"name": "Technological - Separation of development, test and production environments"
|
||||
},
|
||||
{
|
||||
"id": "A.8.32",
|
||||
"name": "Technological - Change management"
|
||||
},
|
||||
{
|
||||
"id": "A.8.33",
|
||||
"name": "Technological - Test information"
|
||||
},
|
||||
{
|
||||
"id": "A.8.34",
|
||||
"name": "Technological - Protection of information systems during audit testing"
|
||||
}
|
||||
]
|
||||
}
|
||||
250
apps/console2/public/data/frameworks/SOC2.json
Normal file
250
apps/console2/public/data/frameworks/SOC2.json
Normal file
@@ -0,0 +1,250 @@
|
||||
{
|
||||
"name": "SOC 2",
|
||||
"id": "SOC2",
|
||||
"controls": [
|
||||
{
|
||||
"id": "CC1.1",
|
||||
"name": "COSO Principle 1: The entity demonstrates a commitment to integrity and ethical values."
|
||||
},
|
||||
{
|
||||
"id": "CC1.2",
|
||||
"name": "COSO Principle 2: The board of directors demonstrates independence from management and exercises oversight of the development and performance of internal control."
|
||||
},
|
||||
{
|
||||
"id": "CC1.3",
|
||||
"name": "COSO Principle 3: Management establishes, with board oversight, structures, reporting lines, and appropriate authorities and responsibilities in the pursuit of objectives."
|
||||
},
|
||||
{
|
||||
"id": "CC1.4",
|
||||
"name": "COSO Principle 4: The entity demonstrates a individuals in alignment with objectives."
|
||||
},
|
||||
{
|
||||
"id": "CC1.5",
|
||||
"name": "COSO Principle 5: The entity holds individuals in the pursuit of objectives."
|
||||
},
|
||||
{
|
||||
"id": "CC2.1",
|
||||
"name": "COSO Principle 13: The entity obtains or generates functioning of internal control."
|
||||
},
|
||||
{
|
||||
"id": "CC2.2",
|
||||
"name": "COSO Principle 14: The entity internally communicates information, including objectives and responsibilities for internal control, necessary to support the functioning of internal control."
|
||||
},
|
||||
{
|
||||
"id": "CC2.3",
|
||||
"name": "COSO Principle 15: The entity communicates with functioning of internal control."
|
||||
},
|
||||
{
|
||||
"id": "CC3.1",
|
||||
"name": "COSO Principle 6: The entity specifies objectives with assessment of risks relating to objectives."
|
||||
},
|
||||
{
|
||||
"id": "CC3.2",
|
||||
"name": "COSO Principle 7: The entity identifies risks to the achievement of its objectives across the entity and analyzes risks as a basis for determining how the risks should be managed."
|
||||
},
|
||||
{
|
||||
"id": "CC3.3",
|
||||
"name": "COSO Principle 8: The entity considers the potential objectives."
|
||||
},
|
||||
{
|
||||
"id": "CC3.4",
|
||||
"name": "COSO Principle 9: The entity identifies and assesses internal control."
|
||||
},
|
||||
{
|
||||
"id": "CC4.1",
|
||||
"name": "COSO Principle 16: The entity selects, develops, and performs ongoing and/or separate evaluations to ascertain whether the components of internal control are present and functioning."
|
||||
},
|
||||
{
|
||||
"id": "CC4.2",
|
||||
"name": "COSO Principle 17: The entity evaluates and communicates internal control deficiencies in a timely corrective action, including senior management and the board of directors, as appropriate."
|
||||
},
|
||||
{
|
||||
"id": "CC5.1",
|
||||
"name": "COSO Principle 10: The entity selects and develops control activities that contribute to the mitigation of risks to the achievement of objectives to acceptable levels."
|
||||
},
|
||||
{
|
||||
"id": "CC5.2",
|
||||
"name": "COSO Principle 11: The entity also selects and support the achievement of objectives."
|
||||
},
|
||||
{
|
||||
"id": "CC5.3",
|
||||
"name": "COSO Principle 12: The entity deploys control activities through policies that establish what is expected and in procedures that put policies into action."
|
||||
},
|
||||
{
|
||||
"id": "CC6.1",
|
||||
"name": "The entity implements logical access security software, infrastructure, and architectures over protected information assets to protect them from security events to meet the entity’s objectives."
|
||||
},
|
||||
{
|
||||
"id": "CC6.2",
|
||||
"name": "Prior to issuing system credentials and granting system access, the entity registers and authorizes new internal and external users whose access is administered by the entity. For those users whose access is administered by the entity, user system credentials are removed when user access is no longer authorized."
|
||||
},
|
||||
{
|
||||
"id": "CC6.3",
|
||||
"name": "The entity authorizes, modifies, or removes access to data, software, functions, and other protected information assets based on roles, responsibilities, or the system design and changes, giving consideration to the concepts of least privilege and segregation of duties, to meet the entity’s objectives."
|
||||
},
|
||||
{
|
||||
"id": "CC6.4",
|
||||
"name": "The entity restricts physical access to facilities and protected information assets (for example, data center locations) to authorized personnel to meet the entity’s objectives."
|
||||
},
|
||||
{
|
||||
"id": "CC6.5",
|
||||
"name": "The entity discontinues logical and physical protections over physical assets only after the ability to read or diminished and is no longer required to meet the entity’s objectives."
|
||||
},
|
||||
{
|
||||
"id": "CC6.6",
|
||||
"name": "The entity implements logical access security measures system boundaries."
|
||||
},
|
||||
{
|
||||
"id": "CC6.7",
|
||||
"name": "The entity restricts the transmission, movement, and removal of information to authorized internal and transmission, movement, or removal to meet the entity’s objectives."
|
||||
},
|
||||
{
|
||||
"id": "CC6.8",
|
||||
"name": "The entity implements controls to prevent or detect and software to meet the entity’s objectives."
|
||||
},
|
||||
{
|
||||
"id": "CC7.1",
|
||||
"name": "To meet its objectives, the entity uses detection and monitoring procedures to identify (1) changes to vulnerabilities, and (2) susceptibilities to newly discovered vulnerabilities."
|
||||
},
|
||||
{
|
||||
"id": "CC7.2",
|
||||
"name": "The entity monitors system components and the operation of those components for anomalies that are indicative of malicious acts, natural disasters, and errors affecting the entity’s ability to meet its objectives; anomalies are analyzed to determine whether they represent security events."
|
||||
},
|
||||
{
|
||||
"id": "CC7.3",
|
||||
"name": "The entity evaluates security events to determine whether they could or have resulted in a failure of the entity to meet its objectives (security incidents) and, if so, takes actions to prevent or address such failures."
|
||||
},
|
||||
{
|
||||
"id": "CC7.4",
|
||||
"name": "The entity responds to identified security incidents by executing a defined incident response program to understand, contain, remediate, and communicate security incidents, as appropriate."
|
||||
},
|
||||
{
|
||||
"id": "CC7.5",
|
||||
"name": "The entity identifies, develops, and implements activities to recover from identified security incidents."
|
||||
},
|
||||
{
|
||||
"id": "CC8.1",
|
||||
"name": "The entity authorizes, designs, develops or acquires, configures, documents, tests, approves, and implements changes to infrastructure, data, software, and procedures to meet its objectives."
|
||||
},
|
||||
{
|
||||
"id": "CC9.1",
|
||||
"name": "The entity identifies, selects, and develops risk business disruptions."
|
||||
},
|
||||
{
|
||||
"id": "CC9.2",
|
||||
"name": "The entity assesses and manages risks associated with vendors and business partners."
|
||||
},
|
||||
{
|
||||
"id": "A1.1",
|
||||
"name": "The entity maintains, monitors, and evaluates current processing capacity and use of system components capacity demand and to enable the implementation of additional capacity to help meet its objectives."
|
||||
},
|
||||
{
|
||||
"id": "A1.2",
|
||||
"name": "The entity authorizes, designs, develops or acquires, implements, operates, approves, maintains, and back-up processes, and recovery infrastructure to meet its objectives."
|
||||
},
|
||||
{
|
||||
"id": "A1.3",
|
||||
"name": "The entity tests recovery plan procedures supporting system recovery to meet its objectives."
|
||||
},
|
||||
{
|
||||
"id": "C1.1",
|
||||
"name": "The entity identifies and maintains confidential confidentiality."
|
||||
},
|
||||
{
|
||||
"id": "C1.2",
|
||||
"name": "The entity disposes of confidential information to meet the entity’s objectives related to confidentiality."
|
||||
},
|
||||
{
|
||||
"id": "PI1.1",
|
||||
"name": "The entity obtains or generates, uses, and communicates relevant, quality information regarding the objectives processed and product and service specifications, to support the use of products and services."
|
||||
},
|
||||
{
|
||||
"id": "PI1.2",
|
||||
"name": "The entity implements policies and procedures over system inputs, including controls over completeness and accuracy, to result in products, services, and reporting to meet the entity’s objectives."
|
||||
},
|
||||
{
|
||||
"id": "PI1.3",
|
||||
"name": "The entity implements policies and procedures over reporting to meet the entity’s objectives."
|
||||
},
|
||||
{
|
||||
"id": "PI1.4",
|
||||
"name": "The entity implements policies and procedures to make available or deliver output completely, accurately, and timely in accordance with specifications to meet the entity’s objectives."
|
||||
},
|
||||
{
|
||||
"id": "PI1.5",
|
||||
"name": "The entity implements policies and procedures to store inputs, items in processing, and outputs completely, accurately, and timely in accordance with system specifications to meet the entity’s objectives."
|
||||
},
|
||||
{
|
||||
"id": "P1.1",
|
||||
"name": "The entity provides notice to data subjects about its privacy practices to meet the entity’s objectives related to privacy. The notice is updated and communicated to entity’s privacy practices, including changes in the use of personal information, to meet the entity’s objectives related to privacy."
|
||||
},
|
||||
{
|
||||
"id": "P2.1",
|
||||
"name": "The entity communicates choices available regarding the collection, use, retention, disclosure, and disposal of personal information to the data subjects and the consequences, if any, of each choice. Explicit consent for the collection, use, retention, disclosure, and disposal of personal information is obtained from data subjects or other authorized persons, if required. Such consent is obtained only for the intended purpose of the information to meet the entity’s objectives related to privacy. The entity’s basis for determining implicit consent for the collection, use, retention, disclosure, and disposal of personal information is documented."
|
||||
},
|
||||
{
|
||||
"id": "P3.1",
|
||||
"name": "Personal information is collected consistent with the entity’s objectives related to privacy."
|
||||
},
|
||||
{
|
||||
"id": "P3.2",
|
||||
"name": "For information requiring explicit consent, the entity communicates the need for such consent, as well as the consequences of a failure to provide consent for the request for personal information, and obtains the consent prior to the collection of the information to meet the entity’s objectives related to privacy."
|
||||
},
|
||||
{
|
||||
"id": "P4.1",
|
||||
"name": "The entity limits the use of personal information to the privacy."
|
||||
},
|
||||
{
|
||||
"id": "P4.2",
|
||||
"name": "The entity retains personal information consistent with the entity’s objectives related to privacy."
|
||||
},
|
||||
{
|
||||
"id": "P4.3",
|
||||
"name": "The entity securely disposes of personal information to meet the entity’s objectives related to privacy."
|
||||
},
|
||||
{
|
||||
"id": "P5.1",
|
||||
"name": "The entity grants identified and authenticated data subjects the ability to access their stored personal information for review and, upon request, provides physical or electronic copies of that information to data subjects to meet the entity’s objectives related to privacy. If access is denied, data subjects are informed of the denial and reason for such denial, as required, to meet the entity’s objectives related to privacy."
|
||||
},
|
||||
{
|
||||
"id": "P5.2",
|
||||
"name": "The entity corrects, amends, or appends personal information based on information provided by data subjects and communicates such information to third parties, as committed or required, to meet the entity’s objectives related to privacy. If a request for correction is denied, data subjects are informed of the denial and reason for such denial to meet the entity’s objectives related to privacy."
|
||||
},
|
||||
{
|
||||
"id": "P6.1",
|
||||
"name": "The entity discloses personal information to third parties with the explicit consent of data subjects, and such consent is obtained prior to disclosure to meet the entity’s objectives related to privacy."
|
||||
},
|
||||
{
|
||||
"id": "P6.2",
|
||||
"name": "The entity creates and retains a complete, accurate, and timely record of authorized disclosures of personal information to meet the entity’s objectives related to privacy."
|
||||
},
|
||||
{
|
||||
"id": "P6.3",
|
||||
"name": "The entity creates and retains a complete, accurate, and timely record of detected or reported unauthorized information to meet the entity’s objectives related to privacy."
|
||||
},
|
||||
{
|
||||
"id": "P6.4",
|
||||
"name": "The entity obtains privacy commitments from vendors and other third parties who have access to personal information to meet the entity’s objectives related to privacy. The entity assesses those parties’ compliance on a periodic and as-needed basis and takes corrective action, if necessary."
|
||||
},
|
||||
{
|
||||
"id": "P6.5",
|
||||
"name": "The entity obtains commitments from vendors and other third parties with access to personal information to notify the entity in the event of actual or suspected unauthorized disclosures of personal information. Such notifications are reported to appropriate personnel and acted on in accordance with established incident response procedures to meet the entity’s objectives related to privacy."
|
||||
},
|
||||
{
|
||||
"id": "P6.6",
|
||||
"name": "The entity provides notification of breaches and others to meet the entity’s objectives related to privacy."
|
||||
},
|
||||
{
|
||||
"id": "P6.7",
|
||||
"name": "The entity provides data subjects with an accounting of the personal information held and disclosure of the subjects’ request, to meet the entity’s objectives related to privacy."
|
||||
},
|
||||
{
|
||||
"id": "P7.1",
|
||||
"name": "The entity collects and maintains accurate, up-to-date, the entity’s objectives related to privacy."
|
||||
},
|
||||
{
|
||||
"id": "P8.1",
|
||||
"name": "The entity implements a process for receiving, addressing, resolving, and communicating the resolution of inquiries, complaints, and disputes from data subjects and others and periodically monitors compliance to meet the entity’s objectives related to privacy. Corrections and other necessary actions related to identified deficiencies are made or taken in a timely manner."
|
||||
}
|
||||
]
|
||||
}
|
||||
24
apps/console2/public/data/risks/LICENSE.md
Normal file
24
apps/console2/public/data/risks/LICENSE.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Risks Data
|
||||
|
||||
The [risks.json](risks.json) file contains data about various vendors and their security certifications. This data is licensed under the Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.
|
||||
|
||||
## License Requirements
|
||||
|
||||
When using this data, you must:
|
||||
|
||||
1. **Give appropriate credit** - Provide attribution to Probo Inc. and include a link to this license
|
||||
2. **Indicate if changes were made** - If you modify the data, you must indicate that changes were made
|
||||
3. **Share under the same license** - If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original
|
||||
|
||||
## Attribution Example
|
||||
|
||||
When using this data, please include the following attribution:
|
||||
|
||||
```
|
||||
Data sourced from Probo Inc. (https://www.getprobo.com) under CC BY-SA 4.0 license
|
||||
```
|
||||
|
||||
## More Information
|
||||
|
||||
For more information about the CC BY-SA 4.0 license, please visit:
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
362
apps/console2/public/data/risks/risks.json
Normal file
362
apps/console2/public/data/risks/risks.json
Normal file
@@ -0,0 +1,362 @@
|
||||
[
|
||||
{
|
||||
"category": "Compliance & Legal",
|
||||
"name": "Regulatory penalty with GDPR non-compliance",
|
||||
"description": "Failure to comply with data privacy laws such as GDPR leads to fines and reputational harm."
|
||||
},
|
||||
{
|
||||
"category": "Compliance & Legal",
|
||||
"name": "Intellectual property infringement",
|
||||
"description": "Using or integrating third-party content or software without proper licensing results in lawsuits or product takedowns."
|
||||
},
|
||||
{
|
||||
"category": "Compliance & Legal",
|
||||
"name": "Legal Exposure via employment law violations",
|
||||
"description": "Improper classification of employees or non-compliance with labor laws can lead to penalties or legal disputes."
|
||||
},
|
||||
{
|
||||
"category": "Compliance & Legal",
|
||||
"name": "Business suspension due to missing licenses or permits",
|
||||
"description": "Operating without required business authorizations results in fines or forced operational halt."
|
||||
},
|
||||
{
|
||||
"category": "Compliance & Legal",
|
||||
"name": "Contractual risk due to poorly drafted agreements",
|
||||
"description": "Weak contracts leads to disputes, missed deliverables, or revenue leakage"
|
||||
},
|
||||
{
|
||||
"category": "Compliance & Legal",
|
||||
"name": "Cross-border operations creates jurisdictional risk",
|
||||
"description": "Operating in multiple countries without understanding local laws exposes the company to fines or bans"
|
||||
},
|
||||
{
|
||||
"category": "Compliance & Legal",
|
||||
"name": "Data sovereignty issue with cloud storage",
|
||||
"description": "Storing user data in the wrong jurisdiction violates local data sovereignty laws"
|
||||
},
|
||||
{
|
||||
"category": "Compliance & Legal",
|
||||
"name": "IP infringement due to generative AI misuse",
|
||||
"description": "Use of generative AI without proper content controls can create outputs that violate copyright or trademark protections"
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Data Breach via phishing",
|
||||
"description": "Phishing attacks targeting employees can lead to unauthorized access to sensitive data, such as credentials, which can result in a data breach."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Ransomware locking critical systems",
|
||||
"description": "Attackers can encrypt critical business data and systems, demanding ransom to restore access. This disrupts operations and can result in financial loss."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Malicious or negligent employee",
|
||||
"description": "An employee could leak sensitive data or compromise systems, leading to data loss or operational damage."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Theft of intellectual property (IP)",
|
||||
"description": "Attackers, including competitors, could steal intellectual property, including designs, algorithms, or trade secrets, harming competitive advantage."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Exploitation of unpatched vulnerabilities",
|
||||
"description": "Failure to apply security patches on time leaves systems vulnerable to known exploits, allowing attackers to compromise or control critical systems."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Distributed denial-of-service (DDoS) attack",
|
||||
"description": "A DDoS attack overwhelms your online services with fake traffic, making them unavailable to customers, causing operational downtime and reputational damage."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Third-party vendor breach compromising startup data",
|
||||
"description": "If a third-party vendor with access to your systems is breached, your sensitive data may be exposed due to poor security on the vendor's side."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Loss of data due to poor or nonexistent backup strategy",
|
||||
"description": "Inadequate or nonexistent backups can lead to permanent data loss, potentially halting operations for extended periods."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Account compromise via weak authentication",
|
||||
"description": "Weak passwords or lack of multi-factor authentication (MFA) can lead to unauthorized access to accounts and critical business systems."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Reputational damage from customer data leak",
|
||||
"description": "A breach that exposes sensitive customer data can cause significant reputational damage, reducing trust and potentially leading to lost revenue."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Regulatory non-compliance leading to penalties",
|
||||
"description": "Failure to meet legal standards for data protection (e.g., GDPR) can result in fines and legal action following a breach or violation."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Fraud via social engineering (impersonation or BEC)",
|
||||
"description": "Social engineering tactics such as impersonating executives or vendors can trick employees into making fraudulent payments, causing financial loss."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Device theft leading to data exposure",
|
||||
"description": "Loss or theft of employee devices without proper encryption or remote wipe capabilities can result in exposure of sensitive company data."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Cloud misconfiguration causing data exposure",
|
||||
"description": "Misconfigured cloud environments can accidentally expose sensitive data (e.g., public-facing storage buckets), leading to data leaks."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "API exploits leading to data breaches",
|
||||
"description": "Poorly secured or vulnerable APIs can be exploited, allowing attackers to access, manipulate, or steal sensitive data from the backend."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Employee mishandling of data leading to privacy violations",
|
||||
"description": "Untrained or negligent employees could mishandle sensitive data, resulting in accidental exposure or privacy law violations."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Account hijacking of social media platforms",
|
||||
"description": "If attackers hijack your startup's social media accounts, they could post harmful content or engage in fraudulent activities, damaging the brand."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Weak encryption causing data exposure",
|
||||
"description": "Insufficient encryption of sensitive data can lead to exposure in the event of interception or theft, making the data easily accessible to attackers."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Ineffective change management process",
|
||||
"description": "Without proper control over changes to software systems, unauthorized or untested changes could introduce vulnerabilities."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Insufficient incident response plan",
|
||||
"description": "A poorly defined or tested response plan can lead to a slow or inadequate response from the team in reaction to a security breach."
|
||||
},
|
||||
{
|
||||
"category": "Cybersecurity",
|
||||
"name": "Inadequate logging & monitoring",
|
||||
"description": "Without proper logging and monitoring, suspicious activities or security incidents may go unnoticed"
|
||||
},
|
||||
{
|
||||
"category": "Finance",
|
||||
"name": "Cash flow shortage",
|
||||
"description": "Running out of funds due to high burn rate or delayed revenue forces premature closure of the startup."
|
||||
},
|
||||
{
|
||||
"category": "Finance",
|
||||
"name": "Growth stagnation due to delayed fundraising",
|
||||
"description": "Delays in securing investment halts product development, hiring, or expansion plans."
|
||||
},
|
||||
{
|
||||
"category": "Finance",
|
||||
"name": "Misalignment with investors",
|
||||
"description": "Differences in strategic vision or milestones between founders and investors causes conflicts or withdrawals."
|
||||
},
|
||||
{
|
||||
"category": "Finance",
|
||||
"name": "Revenue loss due to pricing strategy",
|
||||
"description": "Setting product prices too high or low either repels customers or leads to unsustainable margins."
|
||||
},
|
||||
{
|
||||
"category": "Finance",
|
||||
"name": "Revenue concentration on few clients",
|
||||
"description": "Overreliance on one or two large customers makes cash flow vulnerable if they leave"
|
||||
},
|
||||
{
|
||||
"category": "Finance",
|
||||
"name": "Forecasting errors due to inaccurate assumptions",
|
||||
"description": "Poor financial planning based on optimistic projections leads to undercapitalization"
|
||||
},
|
||||
{
|
||||
"category": "Finance",
|
||||
"name": "Non-paying clients lead to debt accumulation",
|
||||
"description": "Providing services before payment without proper vetting leads to bad debt accumulation"
|
||||
},
|
||||
{
|
||||
"category": "Human capital",
|
||||
"name": "Inability to attract talent leads to hiring delay",
|
||||
"description": "Lack of brand visibility, resources, or appeal prevents the startup from hiring the skilled talent it needs."
|
||||
},
|
||||
{
|
||||
"category": "Human capital",
|
||||
"name": "Poor hiring fit leads to culture break",
|
||||
"description": "Recruiting individuals who do not align with the startup's values or pace cause conflict and reduce cohesion."
|
||||
},
|
||||
{
|
||||
"category": "Human capital",
|
||||
"name": "Leadership breakdown due to co-founder conflict",
|
||||
"description": "Disputes among founders over equity, vision, or roles fracture leadership and jeopardize the company."
|
||||
},
|
||||
{
|
||||
"category": "Human capital",
|
||||
"name": "Unsustainable pace leads to team burnout",
|
||||
"description": "Intense work environments without balance leads to high turnover and decreased productivity"
|
||||
},
|
||||
{
|
||||
"category": "Human capital",
|
||||
"name": "Leadership gaps due to delayed hiring",
|
||||
"description": "Postponing key leadership hires limits decision-making quality and organizational growth"
|
||||
},
|
||||
{
|
||||
"category": "Human capital",
|
||||
"name": "Homogenous culture limit diversity, equity and inclusion",
|
||||
"description": "Lack of diversity affects innovation, morale, and stakeholder perception"
|
||||
},
|
||||
{
|
||||
"category": "Operations",
|
||||
"name": "Fragile infrastructure prevent scaling",
|
||||
"description": "Systems or processes not built to scale breaks down under rapid growth"
|
||||
},
|
||||
{
|
||||
"category": "Operations",
|
||||
"name": "Operational blackout due to dependency on single tool",
|
||||
"description": "Relying on one saas tool for operations creates vulnerability if access is lost or the vendor fails"
|
||||
},
|
||||
{
|
||||
"category": "Operations",
|
||||
"name": "Lack of documented process impact customer service",
|
||||
"description": "Inconsistent execution due to absence of documented procedures affects customer experience"
|
||||
},
|
||||
{
|
||||
"category": "Operations",
|
||||
"name": "Execution delays due to inefficient internal processes",
|
||||
"description": "Inefficient or manual workflows slows execution, reduces quality, and increases costs across core operations."
|
||||
},
|
||||
{
|
||||
"category": "Operations",
|
||||
"name": "Supply disruption via vendor dependency",
|
||||
"description": "Over-reliance on single suppliers or service providers causes operational halts if disruptions occur."
|
||||
},
|
||||
{
|
||||
"category": "Operations",
|
||||
"name": "Knowledge loss with departure of key people",
|
||||
"description": "Loss of a critical employee without backup plans disrupts core activities and strategic continuity."
|
||||
},
|
||||
{
|
||||
"category": "Operations",
|
||||
"name": "Customer churn due to product/service failure",
|
||||
"description": "Bugs, outages, or poor product performance drives away users and damages long-term brand trust."
|
||||
},
|
||||
{
|
||||
"category": "Reputational",
|
||||
"name": "Brand damage with negative public reviews",
|
||||
"description": "Poor customer experience or public backlash quickly damage reputation, especially on digital platforms."
|
||||
},
|
||||
{
|
||||
"category": "Reputational",
|
||||
"name": "Reputational loss via unethical conduct",
|
||||
"description": "Engagement in or association with unethical behavior leads to public criticism and loss of trust."
|
||||
},
|
||||
{
|
||||
"category": "Reputational",
|
||||
"name": "Trust erosion due to lack of transparency",
|
||||
"description": "Hiding problems or failing to communicate openly with stakeholders undermines credibility and confidence."
|
||||
},
|
||||
{
|
||||
"category": "Reputational",
|
||||
"name": "Reputation loss due to poor crisis management",
|
||||
"description": "Mishandling incidents such as downtime or breaches escalate to public backlash"
|
||||
},
|
||||
{
|
||||
"category": "Reputational",
|
||||
"name": "Misinformation spreads with social media",
|
||||
"description": "Missteps or false information on social platforms spreads rapidly, harming the brand"
|
||||
},
|
||||
{
|
||||
"category": "Reputational",
|
||||
"name": "Overpromising impacts credibility",
|
||||
"description": "Making bold claims that go unfulfilled damages trust with customers and investors"
|
||||
},
|
||||
{
|
||||
"category": "Reputational",
|
||||
"name": "Customer backlash via lack of AI transparency",
|
||||
"description": "Using AI in ways not disclosed to users breach trust or data protection regulations, leading to complaints or sanctions"
|
||||
},
|
||||
{
|
||||
"category": "Strategic",
|
||||
"name": "Market failure due to misalignment with customer needs",
|
||||
"description": "Failure to understand or respond to actual market demand leads to product rejection and poor sales performance."
|
||||
},
|
||||
{
|
||||
"category": "Strategic",
|
||||
"name": "Inability to pivot",
|
||||
"description": "Sticking to an ineffective business model despite market feedback results in lost opportunities and startup failure."
|
||||
},
|
||||
{
|
||||
"category": "Strategic",
|
||||
"name": "Competitive loss due to market disruption",
|
||||
"description": "New or existing competitors offering better or cheaper solutions rapidly erodes market share and customer base."
|
||||
},
|
||||
{
|
||||
"category": "Strategic",
|
||||
"name": "Operational instability due to partnership",
|
||||
"description": "Unreliable or misaligned partners may cause delivery delays, service breakdowns, or reputational damage."
|
||||
},
|
||||
{
|
||||
"category": "Strategic",
|
||||
"name": "Unfocused expansion dilutes brand",
|
||||
"description": "Expanding too quickly into unrelated markets dilutes the brand and confuse customers"
|
||||
},
|
||||
{
|
||||
"category": "Strategic",
|
||||
"name": "Poor differentiation limits traction",
|
||||
"description": "Lack of clear value proposition makes it difficult to stand out, leading to weak market traction"
|
||||
},
|
||||
{
|
||||
"category": "Strategic",
|
||||
"name": "Founder vision misalignment",
|
||||
"description": "Differences in long-term vision between founders leads to disjointed strategies and stalled progress"
|
||||
},
|
||||
{
|
||||
"category": "Technology",
|
||||
"name": "Development bottlenecks with accumulated technical debt",
|
||||
"description": "Short-term coding shortcuts limits scalability and requires costly refactoring, delaying future development."
|
||||
},
|
||||
{
|
||||
"category": "Technology",
|
||||
"name": "Resource waste with overengineering",
|
||||
"description": "Overbuilding features with little customer value leads to unnecessary complexity and resource exhaustion."
|
||||
},
|
||||
{
|
||||
"category": "Technology",
|
||||
"name": "Technology dependency due to platform lock-In",
|
||||
"description": "Relying on a third-party platform that changes terms or shuts down disrupts operations and force migration."
|
||||
},
|
||||
{
|
||||
"category": "Technology",
|
||||
"name": "Shadow IT introduces security vulnerability",
|
||||
"description": "Employees using unapproved tools introduces security gaps and compliance risks"
|
||||
},
|
||||
{
|
||||
"category": "Technology",
|
||||
"name": "Outdated stack limits performance",
|
||||
"description": "Failure to update tech stack reduces performance and increase integration challenges"
|
||||
},
|
||||
{
|
||||
"category": "Technology",
|
||||
"name": "Poor test coverage led to system failures",
|
||||
"description": "Inadequate testing before release lead to bugs, crashes, and poor user experience"
|
||||
},
|
||||
{
|
||||
"category": "Technology",
|
||||
"name": "Unbalanced training data leads to bias",
|
||||
"description": "AI systems trained on incomplete or biased datasets produce discriminatory or inaccurate results, risking compliance and fairness"
|
||||
},
|
||||
{
|
||||
"category": "Technology",
|
||||
"name": "Overreliance on AI models leads to decision failure",
|
||||
"description": "Automated systems making critical decisions without human oversight cause strategic or operational errors"
|
||||
},
|
||||
{
|
||||
"category": "Technology",
|
||||
"name": "Security exposure due to AI-generated code vulnerabilities",
|
||||
"description": "AI-generated code that lacks proper validation introduces security flaws or backdoors into production systems"
|
||||
}
|
||||
]
|
||||
15
apps/console2/src/hooks/useFetchQuery.ts
Normal file
15
apps/console2/src/hooks/useFetchQuery.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { useQuery, type UseQueryOptions } from "@tanstack/react-query";
|
||||
|
||||
/**
|
||||
* Wrapper around useQuery to fetch data from an API endpoint
|
||||
*/
|
||||
export function useFetchQuery<T>(
|
||||
url: string,
|
||||
options?: Omit<UseQueryOptions<T>, "queryKey" | "queryFn">
|
||||
) {
|
||||
return useQuery<T>({
|
||||
...options,
|
||||
queryKey: [url],
|
||||
queryFn: () => fetch(url).then((res) => res.json()),
|
||||
});
|
||||
}
|
||||
@@ -1,16 +1,27 @@
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import "./index.css";
|
||||
import { App } from "./App.tsx";
|
||||
import { RelayProvider } from "./providers/RelayProviders.tsx";
|
||||
import { TranslatorProvider } from "./providers/TranslatorProvider.tsx";
|
||||
import { App } from "./App";
|
||||
import { RelayProvider } from "./providers/RelayProviders";
|
||||
import { TranslatorProvider } from "./providers/TranslatorProvider";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
refetchOnWindowFocus: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<RelayProvider>
|
||||
<TranslatorProvider>
|
||||
<App />
|
||||
</TranslatorProvider>
|
||||
</RelayProvider>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<RelayProvider>
|
||||
<TranslatorProvider>
|
||||
<App />
|
||||
</TranslatorProvider>
|
||||
</RelayProvider>
|
||||
</QueryClientProvider>
|
||||
</StrictMode>
|
||||
);
|
||||
|
||||
@@ -5,28 +5,58 @@ import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
Label,
|
||||
Select,
|
||||
Option,
|
||||
Field,
|
||||
} from "@probo/ui";
|
||||
import type { ReactNode } from "react";
|
||||
import { useMemo, useState, type ReactNode } from "react";
|
||||
import { useFetchQuery } from "../../../hooks/useFetchQuery";
|
||||
|
||||
type Props = {
|
||||
trigger: ReactNode;
|
||||
};
|
||||
|
||||
type Risk = {
|
||||
category: string;
|
||||
name: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
export default function NewRiskDialog({ trigger }: Props) {
|
||||
const { __ } = useTranslate();
|
||||
|
||||
const onTemplateChange = (risk: Risk) => {
|
||||
console.log(risk);
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open
|
||||
onClose={() => {}}
|
||||
trigger={trigger}
|
||||
title={<Breadcrumb items={[__("Risks"), __("New Risk")]}></Breadcrumb>}
|
||||
>
|
||||
<form>
|
||||
<DialogContent>
|
||||
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Velit harum
|
||||
maiores dolor hic nisi repudiandae autem quod rem eveniet iure
|
||||
quibusdam sint iste numquam, suscipit ad delectus aspernatur. Quo,
|
||||
amet.
|
||||
<DialogContent className="grid grid-cols-[1fr_420px]">
|
||||
{/* Main form */}
|
||||
<div className="py-8 px-12 space-y-6">
|
||||
<TemplateSelector onChange={onTemplateChange} />
|
||||
<Field
|
||||
label={__("Risk name")}
|
||||
name="name"
|
||||
placeholder={__("Service Outage")}
|
||||
/>
|
||||
<Field
|
||||
label={__("Description")}
|
||||
name="description"
|
||||
placeholder={__("Type your description here")}
|
||||
type="textarea"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Properties form */}
|
||||
<div className="py-5 px-6 bg-subtle"></div>
|
||||
</DialogContent>
|
||||
<DialogFooter>
|
||||
<Button type="submit">{__("Create risk")}</Button>
|
||||
@@ -35,3 +65,58 @@ export default function NewRiskDialog({ trigger }: Props) {
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
function TemplateSelector({ onChange }: { onChange: (risk: Risk) => void }) {
|
||||
const { __ } = useTranslate();
|
||||
const { data: risks } = useFetchQuery<Risk[]>("/data/risks/risks.json", {
|
||||
staleTime: 100_000,
|
||||
});
|
||||
|
||||
const categories = useMemo(
|
||||
() => Array.from(new Set(risks?.map((t) => t.category))),
|
||||
[risks]
|
||||
);
|
||||
|
||||
const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
|
||||
|
||||
const templates = useMemo(
|
||||
() => risks?.filter((r) => r.category === selectedCategory) ?? [],
|
||||
[risks, selectedCategory]
|
||||
);
|
||||
|
||||
const onTemplateChange = (template: string) => {
|
||||
const risk = risks?.find((r) => r.name === template);
|
||||
if (!risk) {
|
||||
throw new Error("Risk not found");
|
||||
}
|
||||
onChange(risk);
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<Label>{__("Risk category")}</Label>
|
||||
<div className="grid grid-cols-2 gap-2 mt-[6px]">
|
||||
<Select
|
||||
placeholder={__("Select a category")}
|
||||
onChange={setSelectedCategory}
|
||||
>
|
||||
{categories.map((category) => (
|
||||
<Option key={category} value={category}>
|
||||
{category}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
<Select
|
||||
empty={templates?.length === 0}
|
||||
placeholder={__("Select template")}
|
||||
onChange={onTemplateChange}
|
||||
>
|
||||
{templates?.map((template) => (
|
||||
<Option key={template.name} value={template.name}>
|
||||
{template.name}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
14738
package-lock.json
generated
14738
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
@@ -1,21 +1,25 @@
|
||||
{
|
||||
"name": "probo",
|
||||
"description": "Probo monorepo containing applications and shared packages",
|
||||
"packageManager": "npm@11.1.0",
|
||||
"engines": {
|
||||
"node": "22.x"
|
||||
},
|
||||
"workspaces": [
|
||||
"apps/*",
|
||||
"apps/console2",
|
||||
"packages/*"
|
||||
],
|
||||
"scripts": {
|
||||
"dev": "npm run dev --workspaces --if-present",
|
||||
"build": "npm run build --workspaces --if-present",
|
||||
"test": "npm run test --workspaces --if-present",
|
||||
"lint": "npm run lint --workspaces --if-present"
|
||||
"build": "turbo run build",
|
||||
"dev": "turbo run dev",
|
||||
"lint": "turbo run lint",
|
||||
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
|
||||
"check": "turbo run check"
|
||||
},
|
||||
"devDependencies": {
|
||||
"turbo": "^2.5.3"
|
||||
},
|
||||
"license": "MIT",
|
||||
"packageManager": "bun@1.2.4",
|
||||
"volta": {
|
||||
"node": "22.15.1"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* A type safe version of Object.keys
|
||||
*/
|
||||
export function objectKeys<T>(object: T) {
|
||||
export function objectKeys<T extends Record<string, unknown>>(object: T) {
|
||||
return Object.keys(object) as (keyof T)[];
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import {
|
||||
createContext,
|
||||
PropsWithChildren,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useState,
|
||||
createContext,
|
||||
type PropsWithChildren,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useState,
|
||||
} from "react";
|
||||
|
||||
const defaultValue = {
|
||||
lang: "en" as "en" | "fr",
|
||||
translations: {} as Record<string, string>,
|
||||
translate: (s: string) => s,
|
||||
lang: "en" as "en" | "fr",
|
||||
translations: {} as Record<string, string>,
|
||||
translate: (s: string) => s,
|
||||
};
|
||||
|
||||
type Context = typeof defaultValue;
|
||||
@@ -18,43 +18,40 @@ type Context = typeof defaultValue;
|
||||
const TranslatorContext = createContext(defaultValue);
|
||||
|
||||
type Props = {
|
||||
lang: "en" | "fr";
|
||||
loader: (lang: string) => Promise<Record<string, string>>;
|
||||
lang: "en" | "fr";
|
||||
loader: (lang: string) => Promise<Record<string, string>>;
|
||||
};
|
||||
|
||||
export function TranslatorProvider({
|
||||
lang,
|
||||
loader,
|
||||
children,
|
||||
lang,
|
||||
loader,
|
||||
children,
|
||||
}: PropsWithChildren<Props>) {
|
||||
const [translations, setTranslations] = useState(
|
||||
{} as Record<string, string>,
|
||||
);
|
||||
const translate = useCallback<Context["translate"]>(
|
||||
(s) => {
|
||||
return translations[s] ? translations[s] : s;
|
||||
},
|
||||
[translations],
|
||||
);
|
||||
const [translations, setTranslations] = useState(
|
||||
{} as Record<string, string>
|
||||
);
|
||||
const translate = useCallback<Context["translate"]>(
|
||||
(s) => {
|
||||
return translations[s] ? translations[s] : s;
|
||||
},
|
||||
[translations]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
loader(lang).then(setTranslations);
|
||||
}, [lang]);
|
||||
useEffect(() => {
|
||||
loader(lang).then(setTranslations);
|
||||
}, [lang]);
|
||||
|
||||
return (
|
||||
<TranslatorContext.Provider
|
||||
value={{ lang, translations, translate }}
|
||||
>
|
||||
{children}
|
||||
</TranslatorContext.Provider>
|
||||
);
|
||||
return (
|
||||
<TranslatorContext.Provider value={{ lang, translations, translate }}>
|
||||
{children}
|
||||
</TranslatorContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useTranslate() {
|
||||
const { translate, lang } =
|
||||
useContext(TranslatorContext);
|
||||
return {
|
||||
lang,
|
||||
__: translate,
|
||||
};
|
||||
const { translate, lang } = useContext(TranslatorContext);
|
||||
return {
|
||||
lang,
|
||||
__: translate,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,28 +1,24 @@
|
||||
import type { StorybookConfig } from '@storybook/react-vite';
|
||||
import type { StorybookConfig } from "@storybook/react-vite";
|
||||
|
||||
import { join, dirname } from "path"
|
||||
import { join, dirname } from "path";
|
||||
|
||||
/**
|
||||
* This function is used to resolve the absolute path of a package.
|
||||
* It is needed in projects that use Yarn PnP or are set up within a monorepo.
|
||||
*/
|
||||
* This function is used to resolve the absolute path of a package.
|
||||
* It is needed in projects that use Yarn PnP or are set up within a monorepo.
|
||||
*/
|
||||
function getAbsolutePath(value: string): any {
|
||||
return dirname(require.resolve(join(value, 'package.json')))
|
||||
return dirname(require.resolve(join(value, "package.json")));
|
||||
}
|
||||
const config: StorybookConfig = {
|
||||
"stories": [
|
||||
"../src/**/*.mdx",
|
||||
"../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"
|
||||
],
|
||||
"addons": [
|
||||
getAbsolutePath('@storybook/addon-essentials'),
|
||||
getAbsolutePath('@storybook/addon-onboarding'),
|
||||
getAbsolutePath('@chromatic-com/storybook'),
|
||||
getAbsolutePath("@storybook/experimental-addon-test")
|
||||
],
|
||||
"framework": {
|
||||
"name": getAbsolutePath('@storybook/react-vite'),
|
||||
"options": {}
|
||||
}
|
||||
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
|
||||
addons: [
|
||||
getAbsolutePath("@storybook/addon-essentials"),
|
||||
getAbsolutePath("@chromatic-com/storybook"),
|
||||
getAbsolutePath("@storybook/experimental-addon-test"),
|
||||
],
|
||||
framework: {
|
||||
name: getAbsolutePath("@storybook/react-vite"),
|
||||
options: {},
|
||||
},
|
||||
};
|
||||
export default config;
|
||||
export default config;
|
||||
|
||||
@@ -6,14 +6,16 @@
|
||||
"main": "src/index.ts",
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"dev": "storybook dev -p 6006",
|
||||
"build": "storybook build"
|
||||
"dev": "storybook dev -p 6006 --no-open",
|
||||
"build": "storybook build",
|
||||
"check": "tsc --noEmit -p tsconfig.app.json"
|
||||
},
|
||||
"prettier": "@probo/prettier",
|
||||
"dependencies": {
|
||||
"@probo/helpers": "1.0.0",
|
||||
"@probo/i18n": "1.0.0",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.14",
|
||||
"@radix-ui/react-scroll-area": "^1.2.9",
|
||||
"@tailwindcss/vite": "^4.1.7",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
@@ -30,7 +32,6 @@
|
||||
"@eslint/js": "^9.25.0",
|
||||
"@probo/prettier": "1.0.0",
|
||||
"@storybook/addon-essentials": "^8.6.13",
|
||||
"@storybook/addon-onboarding": "^8.6.13",
|
||||
"@storybook/blocks": "^8.6.13",
|
||||
"@storybook/experimental-addon-test": "^8.6.13",
|
||||
"@storybook/react": "^8.6.13",
|
||||
|
||||
@@ -11,6 +11,6 @@ type Story = StoryObj<typeof Avatar>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
fullName: "John Doe",
|
||||
name: "John Doe",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import clsx from "clsx";
|
||||
import { Link } from "react-router";
|
||||
import { IconChevronRight } from "../Icons";
|
||||
import { Fragment } from "react/jsx-runtime";
|
||||
|
||||
type Props = {
|
||||
items: (ItemProps | string)[];
|
||||
@@ -15,15 +16,14 @@ type ItemProps = {
|
||||
export function Breadcrumb({ items }: Props) {
|
||||
return (
|
||||
<div className="flex items-center gap-[6px] text-txt-tertiary">
|
||||
{items.map((item, index) => (
|
||||
<>
|
||||
{index > 0 && <IconChevronRight size={12} />}
|
||||
{items.map((item, k) => (
|
||||
<Fragment key={k}>
|
||||
{k > 0 && <IconChevronRight size={12} />}
|
||||
<BreadcrumbItem
|
||||
key={index}
|
||||
{...(typeof item === "string" ? { label: item } : item)}
|
||||
active={index === items.length - 1}
|
||||
active={k === items.length - 1}
|
||||
/>
|
||||
</>
|
||||
</Fragment>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -4,7 +4,6 @@ import type {
|
||||
FC,
|
||||
PropsWithChildren,
|
||||
} from "react";
|
||||
import { forwardRef } from "react";
|
||||
import { Link } from "react-router";
|
||||
import { tv, type VariantProps } from "tailwind-variants";
|
||||
|
||||
@@ -56,28 +55,25 @@ type Props = PropsWithChildren<
|
||||
| AnchorHTMLAttributes<HTMLAnchorElement>
|
||||
);
|
||||
|
||||
export const Button = forwardRef<HTMLButtonElement | HTMLAnchorElement, Props>(
|
||||
(props, ref) => {
|
||||
const Component = props.to ? Link : "button";
|
||||
const {
|
||||
icon: IconComponent,
|
||||
iconAfter: IconAfterComponent,
|
||||
children,
|
||||
onClick,
|
||||
...componentProps
|
||||
} = props;
|
||||
return (
|
||||
<Component
|
||||
{...componentProps}
|
||||
onClick={onClick}
|
||||
// @ts-expect-error Component is too dynamic
|
||||
ref={ref}
|
||||
className={button({ ...props, empty: !children })}
|
||||
>
|
||||
{IconComponent && <IconComponent size={16} />}
|
||||
{children}
|
||||
{IconAfterComponent && <IconAfterComponent size={16} />}
|
||||
</Component>
|
||||
);
|
||||
},
|
||||
);
|
||||
export const Button = (props: Props) => {
|
||||
const Component = props.to ? Link : "button";
|
||||
const {
|
||||
icon: IconComponent,
|
||||
iconAfter: IconAfterComponent,
|
||||
children,
|
||||
onClick,
|
||||
...componentProps
|
||||
} = props;
|
||||
return (
|
||||
// @ts-expect-error Component is too dynamic
|
||||
<Component
|
||||
{...componentProps}
|
||||
onClick={onClick}
|
||||
className={button({ ...props, empty: !children })}
|
||||
>
|
||||
{IconComponent && <IconComponent size={16} />}
|
||||
{children}
|
||||
{IconAfterComponent && <IconAfterComponent size={16} />}
|
||||
</Component>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -9,10 +9,4 @@ export default {
|
||||
|
||||
type Story = StoryObj<typeof Input>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
label: "Label",
|
||||
name: "id",
|
||||
help: "e.g. This is a hint",
|
||||
},
|
||||
};
|
||||
export const Default: Story = {};
|
||||
|
||||
@@ -1,54 +1,12 @@
|
||||
import type { InputHTMLAttributes } from "react";
|
||||
import { tv } from "tailwind-variants";
|
||||
|
||||
type Props = {
|
||||
label?: string;
|
||||
help?: string;
|
||||
name?: string;
|
||||
placeholder?: string;
|
||||
type?: string;
|
||||
required?: boolean;
|
||||
};
|
||||
type Props = InputHTMLAttributes<HTMLInputElement>;
|
||||
|
||||
const input = tv({
|
||||
slots: {
|
||||
base: "flex flex-col",
|
||||
label: "text-sm font-medium text-txt-primary mb-[6px]",
|
||||
input: "py-[6px] bg-secondary border border-border-mid rounded-[10px] hover:border-border-strong focus:shadow-focus text-sm px-3",
|
||||
help: "text-xs font-semibold text-txt-tertiary mt-1",
|
||||
},
|
||||
export const input = tv({
|
||||
base: "py-[6px] bg-secondary border border-border-mid rounded-[10px] hover:border-border-strong focus:shadow-focus text-sm px-3",
|
||||
});
|
||||
|
||||
const {
|
||||
base: baseClass,
|
||||
label: labelClass,
|
||||
input: inputClass,
|
||||
help: helpClass,
|
||||
} = input();
|
||||
|
||||
export function Input({
|
||||
label,
|
||||
help,
|
||||
name,
|
||||
placeholder,
|
||||
type,
|
||||
required,
|
||||
}: Props) {
|
||||
return (
|
||||
<div className={baseClass()}>
|
||||
{label && (
|
||||
<label htmlFor={name} className={labelClass()}>
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
<input
|
||||
name={name}
|
||||
id={name}
|
||||
className={inputClass()}
|
||||
placeholder={placeholder}
|
||||
type={type}
|
||||
required={required}
|
||||
/>
|
||||
{help && <span className={helpClass()}>{help}</span>}
|
||||
</div>
|
||||
);
|
||||
export function Input(props: Props) {
|
||||
return <input className={input(props)} {...props} />;
|
||||
}
|
||||
|
||||
12
packages/ui/src/Atoms/Label/Label.stories.tsx
Normal file
12
packages/ui/src/Atoms/Label/Label.stories.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Label } from "./Label";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
|
||||
export default {
|
||||
title: "Atoms/Form/Label",
|
||||
component: Label,
|
||||
argTypes: {},
|
||||
} satisfies Meta<typeof Label>;
|
||||
|
||||
type Story = StoryObj<typeof Label>;
|
||||
|
||||
export const Default: Story = {};
|
||||
14
packages/ui/src/Atoms/Label/Label.tsx
Normal file
14
packages/ui/src/Atoms/Label/Label.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import type { HTMLAttributes } from "react";
|
||||
import { tv } from "tailwind-variants";
|
||||
|
||||
type Props = HTMLAttributes<HTMLLabelElement> & {
|
||||
htmlFor?: string;
|
||||
};
|
||||
|
||||
const label = tv({
|
||||
base: "text-sm font-medium text-txt-primary",
|
||||
});
|
||||
|
||||
export function Label({ ...props }: Props) {
|
||||
return <label {...props} className={label(props)} />;
|
||||
}
|
||||
31
packages/ui/src/Atoms/Select/Select.stories.tsx
Normal file
31
packages/ui/src/Atoms/Select/Select.stories.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import { Select, Option } from "./Select";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
|
||||
export default {
|
||||
title: "Atoms/Form/Select",
|
||||
component: Select,
|
||||
argTypes: {},
|
||||
} satisfies Meta<typeof Select>;
|
||||
|
||||
type Story = StoryObj<typeof Select>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
placeholder: "Select an option",
|
||||
children: (
|
||||
<>
|
||||
<Option value="apple">Apple</Option>
|
||||
<Option value="banana">Banana</Option>
|
||||
<Option value="blueberry">Blueberry</Option>
|
||||
<Option value="grapes">Grapes</Option>
|
||||
<Option value="pineapple">Pineapple</Option>
|
||||
</>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export const NoChildren: Story = {
|
||||
args: {
|
||||
placeholder: "Select an option",
|
||||
},
|
||||
};
|
||||
94
packages/ui/src/Atoms/Select/Select.tsx
Normal file
94
packages/ui/src/Atoms/Select/Select.tsx
Normal file
@@ -0,0 +1,94 @@
|
||||
import {
|
||||
Root,
|
||||
Trigger,
|
||||
Value,
|
||||
Icon,
|
||||
Portal,
|
||||
Content,
|
||||
Viewport,
|
||||
Item,
|
||||
ItemText,
|
||||
} from "@radix-ui/react-select";
|
||||
import * as ScrollArea from "@radix-ui/react-scroll-area";
|
||||
import { input } from "../Input/Input.tsx";
|
||||
import { IconChevronGrabberVertical } from "../Icons/IconChevronGrabberVertical.tsx";
|
||||
import { tv } from "tailwind-variants";
|
||||
import type { ComponentProps, PropsWithChildren } from "react";
|
||||
|
||||
type Props = PropsWithChildren<
|
||||
{
|
||||
placeholder?: string;
|
||||
onChange?: (s: string) => void;
|
||||
empty?: boolean;
|
||||
} & Omit<ComponentProps<typeof Trigger>, "onChange">
|
||||
>;
|
||||
|
||||
const select = tv({
|
||||
slots: {
|
||||
trigger: input({
|
||||
className:
|
||||
"flex justify-between items-center gap-4 data-placeholder:text-txt-tertiary w-full whitespace-nowrap",
|
||||
}),
|
||||
content:
|
||||
"z-100 shadow-mid rounded-[10px] bg-level-1 p-1 animate-in fade-in slide-in-from-top-2 overflow-y-auto overflow-y-auto",
|
||||
option: "flex items-center gap-2 h-8 text-sm font-medium text-txt-primary hover:bg-tertiary-hover active:bg-tertiary-pressed cursor-pointer px-[10px]",
|
||||
},
|
||||
variants: {
|
||||
empty: {
|
||||
true: {
|
||||
trigger: "border-dashed pointer-events-none",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const { trigger, option, content } = select();
|
||||
|
||||
export function Select({
|
||||
placeholder,
|
||||
children,
|
||||
onChange,
|
||||
empty,
|
||||
...props
|
||||
}: Props) {
|
||||
return (
|
||||
<Root onValueChange={onChange}>
|
||||
<Trigger className={trigger({ ...props, empty })}>
|
||||
<div className="text-ellipsis overflow-hidden">
|
||||
<Value placeholder={placeholder} />
|
||||
</div>
|
||||
<Icon className="SelectIcon">
|
||||
<IconChevronGrabberVertical size={16} />
|
||||
</Icon>
|
||||
</Trigger>
|
||||
<Portal>
|
||||
<Content
|
||||
className={content()}
|
||||
position="popper"
|
||||
sideOffset={5}
|
||||
style={{
|
||||
minWidth: "var(--radix-select-trigger-width)",
|
||||
maxHeight:
|
||||
"var(--radix-select-content-available-height)",
|
||||
}}
|
||||
>
|
||||
<ScrollArea.Root className="ScrollAreaRoot" type="auto">
|
||||
<Viewport asChild>
|
||||
<ScrollArea.Viewport className="ScrollAreaViewport">
|
||||
{children}
|
||||
</ScrollArea.Viewport>
|
||||
</Viewport>
|
||||
</ScrollArea.Root>
|
||||
</Content>
|
||||
</Portal>
|
||||
</Root>
|
||||
);
|
||||
}
|
||||
|
||||
export function Option({ children, ...props }: ComponentProps<typeof Item>) {
|
||||
return (
|
||||
<Item {...props} className={option(props)}>
|
||||
<ItemText>{children}</ItemText>
|
||||
</Item>
|
||||
);
|
||||
}
|
||||
12
packages/ui/src/Atoms/Textarea/Textarea.stories.tsx
Normal file
12
packages/ui/src/Atoms/Textarea/Textarea.stories.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Textarea } from "./Textarea";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
|
||||
export default {
|
||||
title: "Atoms/Form/Textarea",
|
||||
component: Textarea,
|
||||
argTypes: {},
|
||||
} satisfies Meta<typeof Textarea>;
|
||||
|
||||
type Story = StoryObj<typeof Textarea>;
|
||||
|
||||
export const Default: Story = {};
|
||||
15
packages/ui/src/Atoms/Textarea/Textarea.tsx
Normal file
15
packages/ui/src/Atoms/Textarea/Textarea.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import type { InputHTMLAttributes } from "react";
|
||||
import { tv } from "tailwind-variants";
|
||||
import { input } from "../Input/Input";
|
||||
|
||||
type Props = InputHTMLAttributes<HTMLTextAreaElement>;
|
||||
|
||||
export const textarea = tv({
|
||||
base: input({ class: "min-h-20" }),
|
||||
});
|
||||
|
||||
console.log(input({ class: "min-h-20" }));
|
||||
|
||||
export function Textarea(props: Props) {
|
||||
return <textarea className={textarea(props)} {...props} />;
|
||||
}
|
||||
@@ -6,27 +6,39 @@ import {
|
||||
Content,
|
||||
Title,
|
||||
Close,
|
||||
Description,
|
||||
} from "@radix-ui/react-dialog";
|
||||
import { IconCrossLargeX } from "../../Atoms/Icons";
|
||||
import type { ReactNode } from "react";
|
||||
import type { HTMLAttributes, ReactNode } from "react";
|
||||
import { Button } from "../../Atoms/Button/Button";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import clsx from "clsx";
|
||||
|
||||
type Props = {
|
||||
onClose: () => void;
|
||||
trigger: ReactNode;
|
||||
title: ReactNode;
|
||||
children?: ReactNode;
|
||||
open?: boolean;
|
||||
};
|
||||
|
||||
export function Dialog({ onClose, trigger, title, children }: Props) {
|
||||
export function Dialog({ onClose, trigger, title, children, open }: Props) {
|
||||
const onOpenChange = (open: boolean) => {
|
||||
if (!open) {
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Root>
|
||||
<Root open={open} onOpenChange={onOpenChange}>
|
||||
<Trigger asChild>{trigger}</Trigger>
|
||||
<Portal>
|
||||
<Overlay className="fixed inset-0 z-50 bg-dialog/40 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0" />
|
||||
<div className="fixed grid place-items-center inset-0 z-50">
|
||||
<Content className="bg-level-2 rounded-2xl max-w-5xl w-[95%]">
|
||||
<Content
|
||||
aria-describedby={undefined}
|
||||
className="bg-level-2 rounded-2xl max-w-5xl w-[95%]"
|
||||
>
|
||||
<div className="flex justify-between items-center p-3 border-b border-b-border-low">
|
||||
<Title className="text-sm font-medium">
|
||||
{title}
|
||||
@@ -58,15 +70,14 @@ export function DialogFooter({ children }: { children?: ReactNode }) {
|
||||
);
|
||||
}
|
||||
|
||||
export function DialogContent({ children }: { children: ReactNode }) {
|
||||
export function DialogContent(props: HTMLAttributes<HTMLDivElement>) {
|
||||
return (
|
||||
<div
|
||||
className="overflow-y-auto"
|
||||
{...props}
|
||||
className={clsx("overflow-y-auto", props.className)}
|
||||
style={{
|
||||
maxHeight: "min(640px, calc(100vh - 140px))",
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
18
packages/ui/src/Molecules/Field/Field.stories.tsx
Normal file
18
packages/ui/src/Molecules/Field/Field.stories.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Field } from "./Field.tsx";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
|
||||
export default {
|
||||
title: "Molecules/Field",
|
||||
component: Field,
|
||||
argTypes: {},
|
||||
} satisfies Meta<typeof Field>;
|
||||
|
||||
type Story = StoryObj<typeof Field>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
label: "Label",
|
||||
name: "id",
|
||||
help: "e.g. This is a hint",
|
||||
},
|
||||
};
|
||||
51
packages/ui/src/Molecules/Field/Field.tsx
Normal file
51
packages/ui/src/Molecules/Field/Field.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import { tv } from "tailwind-variants";
|
||||
import { Label } from "../../Atoms/Label/Label";
|
||||
import { Input } from "../../Atoms/Input/Input";
|
||||
import { Textarea } from "../../Atoms/Textarea/Textarea";
|
||||
|
||||
type Props = {
|
||||
label?: string;
|
||||
help?: string;
|
||||
name?: string;
|
||||
placeholder?: string;
|
||||
type?: string;
|
||||
required?: boolean;
|
||||
};
|
||||
|
||||
const field = tv({
|
||||
slots: {
|
||||
base: "flex flex-col",
|
||||
label: "mb-[6px]",
|
||||
help: "text-xs font-semibold text-txt-tertiary mt-1",
|
||||
},
|
||||
});
|
||||
|
||||
const { base: baseClass, label: labelClass, help: helpClass } = field();
|
||||
|
||||
export function Field({
|
||||
label,
|
||||
help,
|
||||
name,
|
||||
placeholder,
|
||||
type,
|
||||
required,
|
||||
}: Props) {
|
||||
const Comp = type === "textarea" ? Textarea : Input;
|
||||
return (
|
||||
<div className={baseClass()}>
|
||||
{label && (
|
||||
<Label htmlFor={name} className={labelClass()}>
|
||||
{label}
|
||||
</Label>
|
||||
)}
|
||||
<Comp
|
||||
name={name}
|
||||
id={name}
|
||||
placeholder={placeholder}
|
||||
type={type}
|
||||
required={required}
|
||||
/>
|
||||
{help && <span className={helpClass()}>{help}</span>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -18,14 +18,14 @@ export function UserDropdown({ fullName, children, email }: Props) {
|
||||
className="w-60"
|
||||
toggle={
|
||||
<Button variant="tertiary">
|
||||
<Avatar fullName={fullName} />
|
||||
<Avatar name={fullName} />
|
||||
<span>{fullName}</span>
|
||||
<IconChevronDown size={16} />
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<div className="flex gap-2 items-center">
|
||||
<Avatar fullName={fullName} size="l" />
|
||||
<Avatar name={fullName} size="l" />
|
||||
<div>
|
||||
<p className="text-sm font-medium text-txt-primary">
|
||||
{fullName}
|
||||
|
||||
@@ -20,7 +20,10 @@ export {
|
||||
DropdownItem,
|
||||
} from "./Atoms/Dropdown/Dropdown";
|
||||
export { Avatar } from "./Atoms/Avatar/Avatar";
|
||||
export { Input } from "./Atoms/Input/Input";
|
||||
export { Field } from "./Molecules/Field/Field.tsx";
|
||||
export { Input } from "./Atoms/Input/Input.tsx";
|
||||
export { Select, Option } from "./Atoms/Select/Select.tsx";
|
||||
export { Label } from "./Atoms/Label/Label";
|
||||
|
||||
// Molecules
|
||||
export {
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import "./theme.css";
|
||||
import App from "./App.tsx";
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>,
|
||||
);
|
||||
@@ -23,5 +23,6 @@
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["src"]
|
||||
"include": ["src"],
|
||||
"exclude": ["src/Atoms/Icons/generator.ts"]
|
||||
}
|
||||
|
||||
21
turbo.json
Normal file
21
turbo.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "https://turborepo.com/schema.json",
|
||||
"ui": "tui",
|
||||
"tasks": {
|
||||
"build": {
|
||||
"dependsOn": ["^build"],
|
||||
"inputs": ["$TURBO_DEFAULT$", ".env*"],
|
||||
"outputs": [".next/**", "!.next/cache/**"]
|
||||
},
|
||||
"lint": {
|
||||
"dependsOn": ["^lint"]
|
||||
},
|
||||
"check": {
|
||||
"dependsOn": ["^check"]
|
||||
},
|
||||
"dev": {
|
||||
"cache": false,
|
||||
"persistent": true
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user