Skip to content
This repository was archived by the owner on May 30, 2026. It is now read-only.

Commit c26c66f

Browse files
committed
Improve UX of project creation modal
* Replaces the separate "General" and "Identity" tabs with a non-tabbed view. "Identity" is now a collapsible section that is explicitly marked as optional. * Makes the modal a proper form, such that it supports confirmation by pressing enter etc. * Adds proper input validation to prevent invalid configurations from being submitted, e.g. missing classifier, collection project enabled but no collection logic selected, etc. * Prevents the modal from closing when project creation fails. Lets users refine their inputs and retry. * Waits for the creation request to complete before closing the modal. * Redirects directly to the created project instead of back to the project list. Signed-off-by: nscuro <nscuro@protonmail.com>
1 parent 06c5994 commit c26c66f

18 files changed

Lines changed: 446 additions & 300 deletions

File tree

src/App.vue

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,17 +101,25 @@ export default {
101101
}
102102
103103
this.axios.interceptors.response.use(null, (error) => {
104+
if (!error.response) {
105+
this.$toastr.e(
106+
this.$t('condition.unsuccessful_action'),
107+
this.$t('condition.http_request_error'),
108+
);
109+
return Promise.reject(error);
110+
}
111+
const contentType =
112+
(error.response.headers && error.response.headers['content-type']) ||
113+
'';
104114
// On error status codes (4xx - 5xx), display a toast with either:
105115
// * The problem title and detail in case of an RFC 9457 response
106116
// * the HTTP status code and text
107117
if (error.response.status >= 400 && error.response.status < 500) {
108-
if (
109-
error.response.headers['content-type'] === 'application/problem+json'
110-
) {
118+
if (contentType.includes('application/problem+json')) {
111119
this.$toastr.w(error.response.data.detail, error.response.data.title);
112120
} else if (
113121
error.response.status === 400 &&
114-
error.response.headers['content-type'] === 'application/json' &&
122+
contentType.includes('application/json') &&
115123
error.response.data &&
116124
Array.isArray(error.response.data) &&
117125
error.response.data[0].hasOwnProperty('invalidValue')
@@ -130,9 +138,7 @@ export default {
130138
);
131139
}
132140
} else {
133-
if (
134-
error.response.headers['content-type'] === 'application/problem+json'
135-
) {
141+
if (contentType.includes('application/problem+json')) {
136142
this.$toastr.w(error.response.data.detail, error.response.data.title);
137143
} else {
138144
this.$toastr.e(

src/i18n/locales/de.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@
628628
"identifier": "Kennung",
629629
"identifier_type": "Kennungstyp",
630630
"identity": "Identität",
631+
"identity_fields_set": null,
631632
"in_triage": "In Triage",
632633
"inactive": "Inaktiv",
633634
"inactive_active_children": "Das Projekt kann nicht auf inaktiv gesetzt werden, wenn es aktive untergeordnete Projekte hat",
@@ -647,6 +648,7 @@
647648
"internal_status": null,
648649
"inventory": "Inventar",
649650
"inventory_with_vulnerabilities": "Inventarisierung mit Schwachstellen",
651+
"is_latest_tooltip": null,
650652
"item": "Element",
651653
"justification": "Begründung",
652654
"justification_tooltip": "Die Begründung, warum der Auswirkungsanalysestatus „Nicht betroffen“ lautete",
@@ -716,6 +718,7 @@
716718
"operational_risk": "Betriebsrisiko",
717719
"operator": "Operator",
718720
"operator_help": null,
721+
"optional": null,
719722
"osi_approved": "OSI-Zulassung",
720723
"outdated_only": "Nur veraltet",
721724
"overview": "Überblick",
@@ -964,6 +967,8 @@
964967
"relative_seconds_ago": null,
965968
"remove_component": "Komponente entfernen",
966969
"reported_by": "Berichtet von",
970+
"required_classifier": null,
971+
"required_collection_logic": null,
967972
"required_component_identifier": "Eine Komponentenkennung ist erforderlich",
968973
"required_component_name": "Der Komponentenname ist erforderlich",
969974
"required_component_version": "Die Komponentenversion ist erforderlich",

src/i18n/locales/en.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@
628628
"identifier": "Identifier",
629629
"identifier_type": "Identifier Type",
630630
"identity": "Identity",
631+
"identity_fields_set": "{count} field(s) set",
631632
"in_triage": "In Triage",
632633
"inactive": "Inactive",
633634
"inactive_active_children": "The project cannot be set to inactive if it has active children",
@@ -647,6 +648,7 @@
647648
"internal_status": "Component classified as internal",
648649
"inventory": "Inventory",
649650
"inventory_with_vulnerabilities": "Inventory with Vulnerabilities",
651+
"is_latest_tooltip": "Marks this version as the latest release of the project",
650652
"item": "Item",
651653
"justification": "Justification",
652654
"justification_tooltip": "The rationale of why the impact analysis state was asserted to be \"Not Affected\"",
@@ -716,6 +718,7 @@
716718
"operational_risk": "Operational Risk",
717719
"operator": "Operator",
718720
"operator_help": "ANY = any condition matches; ALL = every condition must match",
721+
"optional": "optional",
719722
"osi_approved": "OSI Approved",
720723
"outdated_only": "Outdated only",
721724
"overview": "Overview",
@@ -964,6 +967,8 @@
964967
"relative_seconds_ago": "{n}s ago",
965968
"remove_component": "Remove Component",
966969
"reported_by": "Reported By",
970+
"required_classifier": "A classifier is required",
971+
"required_collection_logic": "A collection logic is required",
967972
"required_component_identifier": "A component identifier is required",
968973
"required_component_name": "The component name is required",
969974
"required_component_version": "The component version is required",

src/i18n/locales/es.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@
628628
"identifier": "Identificador",
629629
"identifier_type": "Tipo de identificador",
630630
"identity": "Identidad",
631+
"identity_fields_set": null,
631632
"in_triage": "En triaje",
632633
"inactive": "Inactivo",
633634
"inactive_active_children": "El proyecto no se puede configurar como inactivo si tiene hijos activos",
@@ -647,6 +648,7 @@
647648
"internal_status": null,
648649
"inventory": "Inventario",
649650
"inventory_with_vulnerabilities": "Inventario con vulnerabilidades",
651+
"is_latest_tooltip": null,
650652
"item": "Elemento",
651653
"justification": "Justificación",
652654
"justification_tooltip": "El motivo por el que se afirmó que el estado del análisis de impacto era \"No afectado\"",
@@ -716,6 +718,7 @@
716718
"operational_risk": "Riesgo operacional",
717719
"operator": "Operador",
718720
"operator_help": null,
721+
"optional": null,
719722
"osi_approved": "Aprobado por OSI",
720723
"outdated_only": "Sólo anticuado",
721724
"overview": "Descripción general",
@@ -964,6 +967,8 @@
964967
"relative_seconds_ago": null,
965968
"remove_component": "Quitar componente",
966969
"reported_by": "Reportado por",
970+
"required_classifier": null,
971+
"required_collection_logic": null,
967972
"required_component_identifier": "Se requiere un identificador de componente",
968973
"required_component_name": "El nombre del componente es obligatorio.",
969974
"required_component_version": "La versión del componente es obligatoria.",

src/i18n/locales/fr.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@
628628
"identifier": "Identifiant",
629629
"identifier_type": "Type d'identifiant",
630630
"identity": "Identité",
631+
"identity_fields_set": null,
631632
"in_triage": "Au tri",
632633
"inactive": "Inactif",
633634
"inactive_active_children": "Le projet ne peut pas être défini comme inactif s'il a des enfants actifs",
@@ -647,6 +648,7 @@
647648
"internal_status": null,
648649
"inventory": "Inventaire",
649650
"inventory_with_vulnerabilities": "Inventaire avec vulnérabilités",
651+
"is_latest_tooltip": null,
650652
"item": "Élément",
651653
"justification": "Justification",
652654
"justification_tooltip": "La raison pour laquelle l'état de l'analyse d'impact a été déclaré « Non affecté »",
@@ -716,6 +718,7 @@
716718
"operational_risk": "Risque opérationnel",
717719
"operator": "Opérateur",
718720
"operator_help": null,
721+
"optional": null,
719722
"osi_approved": "Approuvée par l'OSI",
720723
"outdated_only": "Obsolète seulement",
721724
"overview": "Aperçu",
@@ -964,6 +967,8 @@
964967
"relative_seconds_ago": null,
965968
"remove_component": "Supprimer un composant",
966969
"reported_by": "Rapporté par",
970+
"required_classifier": null,
971+
"required_collection_logic": null,
967972
"required_component_identifier": "Un identifiant de composant est requis",
968973
"required_component_name": "Le nom du composant est obligatoire",
969974
"required_component_version": "La version du composant est requise",

src/i18n/locales/hi.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@
628628
"identifier": "पहचानकर्ता",
629629
"identifier_type": "पहचानकर्ता प्रकार",
630630
"identity": "पहचान",
631+
"identity_fields_set": null,
631632
"in_triage": "ट्राइएज में",
632633
"inactive": "निष्क्रिय",
633634
"inactive_active_children": "यदि प्रोजेक्ट में सक्रिय बच्चे हैं तो उसे निष्क्रिय नहीं किया जा सकता",
@@ -647,6 +648,7 @@
647648
"internal_status": null,
648649
"inventory": "भंडार",
649650
"inventory_with_vulnerabilities": "कमज़ोरियों वाली सूची",
651+
"is_latest_tooltip": null,
650652
"item": "वस्तु",
651653
"justification": "औचित्य",
652654
"justification_tooltip": "प्रभाव विश्लेषण स्थिति को \"प्रभावित नहीं\" क्यों कहा गया, इसका औचित्य",
@@ -716,6 +718,7 @@
716718
"operational_risk": "परिचालनात्मक जोखिम",
717719
"operator": "ऑपरेटर",
718720
"operator_help": null,
721+
"optional": null,
719722
"osi_approved": "ओएसआई स्वीकृत",
720723
"outdated_only": "केवल पुराना",
721724
"overview": "अवलोकन",
@@ -964,6 +967,8 @@
964967
"relative_seconds_ago": null,
965968
"remove_component": "घटक हटाएँ",
966969
"reported_by": "के द्वारा रिपोर्ट किया गया",
970+
"required_classifier": null,
971+
"required_collection_logic": null,
967972
"required_component_identifier": "घटक पहचानकर्ता आवश्यक है",
968973
"required_component_name": "घटक का नाम आवश्यक है",
969974
"required_component_version": "घटक संस्करण आवश्यक है",

src/i18n/locales/it.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@
628628
"identifier": "Identificatore",
629629
"identifier_type": "Tipo di identificatore",
630630
"identity": "Identità",
631+
"identity_fields_set": null,
631632
"in_triage": "Nel triage",
632633
"inactive": "Inattivo",
633634
"inactive_active_children": "Il progetto non può essere impostato su inattivo se ha figli attivi",
@@ -647,6 +648,7 @@
647648
"internal_status": null,
648649
"inventory": "Inventario",
649650
"inventory_with_vulnerabilities": "Inventario con vulnerabilità",
651+
"is_latest_tooltip": null,
650652
"item": "Elemento",
651653
"justification": "Giustificazione",
652654
"justification_tooltip": "La motivazione per cui lo stato dell'analisi d'impatto è stato dichiarato \"Non interessato\"",
@@ -716,6 +718,7 @@
716718
"operational_risk": "Rischio operativo",
717719
"operator": "Operatore",
718720
"operator_help": null,
721+
"optional": null,
719722
"osi_approved": "Approvato dall'OSI",
720723
"outdated_only": "Solo obsoleto",
721724
"overview": "Panoramica",
@@ -964,6 +967,8 @@
964967
"relative_seconds_ago": null,
965968
"remove_component": "Rimuovi componente",
966969
"reported_by": "Segnalato da",
970+
"required_classifier": null,
971+
"required_collection_logic": null,
967972
"required_component_identifier": "È obbligatorio un identificatore del componente",
968973
"required_component_name": "Il nome del componente è obbligatorio",
969974
"required_component_version": "La versione del componente è obbligatoria",

src/i18n/locales/ja.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@
628628
"identifier": "識別子",
629629
"identifier_type": "識別子の種類",
630630
"identity": "身元",
631+
"identity_fields_set": null,
631632
"in_triage": "トリアージ中",
632633
"inactive": "非活性",
633634
"inactive_active_children": "アクティブな子プロジェクトがある場合、プロジェクトを非アクティブに設定することはできません。",
@@ -647,6 +648,7 @@
647648
"internal_status": null,
648649
"inventory": "インベントリ",
649650
"inventory_with_vulnerabilities": "脆弱性のあるインベントリ",
651+
"is_latest_tooltip": null,
650652
"item": "アイテム",
651653
"justification": "正当化",
652654
"justification_tooltip": "影響分析の状態が「影響を受けない」と主張された理由",
@@ -716,6 +718,7 @@
716718
"operational_risk": "運用リスク",
717719
"operator": "オペレーター",
718720
"operator_help": null,
721+
"optional": null,
719722
"osi_approved": "OSI承認",
720723
"outdated_only": "古いもののみ",
721724
"overview": "概要",
@@ -964,6 +967,8 @@
964967
"relative_seconds_ago": null,
965968
"remove_component": "コンポーネントを削除",
966969
"reported_by": "報告者",
970+
"required_classifier": null,
971+
"required_collection_logic": null,
967972
"required_component_identifier": "コンポーネント識別子が必要です",
968973
"required_component_name": "コンポーネント名は必須です",
969974
"required_component_version": "コンポーネントのバージョンが必要です",

src/i18n/locales/pl.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@
628628
"identifier": "Identyfikator",
629629
"identifier_type": "Typ identyfikatora",
630630
"identity": "Tożsamość",
631+
"identity_fields_set": null,
631632
"in_triage": "W segregacji",
632633
"inactive": "Nieaktywny",
633634
"inactive_active_children": "Projektu nie można ustawić jako nieaktywnego, jeśli ma aktywne elementy podrzędne",
@@ -647,6 +648,7 @@
647648
"internal_status": null,
648649
"inventory": "Spis",
649650
"inventory_with_vulnerabilities": "Inwentarz z lukami w zabezpieczeniach",
651+
"is_latest_tooltip": null,
650652
"item": "Pozycja",
651653
"justification": "Uzasadnienie",
652654
"justification_tooltip": "Uzasadnienie, dla którego stwierdzono, że stan analizy wpływu to „Nie ma wpływu”",
@@ -716,6 +718,7 @@
716718
"operational_risk": "Ryzyko operacyjne",
717719
"operator": "Operator",
718720
"operator_help": null,
721+
"optional": null,
719722
"osi_approved": "Zatwierdzone przez OSI",
720723
"outdated_only": "Tylko nieaktualne",
721724
"overview": "Przegląd",
@@ -964,6 +967,8 @@
964967
"relative_seconds_ago": null,
965968
"remove_component": "Usuń komponent",
966969
"reported_by": "Zgłoszone przez",
970+
"required_classifier": null,
971+
"required_collection_logic": null,
967972
"required_component_identifier": "Wymagany jest identyfikator komponentu",
968973
"required_component_name": "Nazwa komponentu jest wymagana",
969974
"required_component_version": "Wymagana jest wersja komponentu",

src/i18n/locales/pt-BR.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@
628628
"identifier": "Identificador",
629629
"identifier_type": "Tipo de identificador",
630630
"identity": "Identidade",
631+
"identity_fields_set": null,
631632
"in_triage": "Em triagem",
632633
"inactive": "Inativo",
633634
"inactive_active_children": "O projeto não pode ser definido como inativo se tiver filhos ativos",
@@ -647,6 +648,7 @@
647648
"internal_status": null,
648649
"inventory": "Inventário",
649650
"inventory_with_vulnerabilities": "Inventário com vulnerabilidades",
651+
"is_latest_tooltip": null,
650652
"item": "Item",
651653
"justification": "Justificação",
652654
"justification_tooltip": "A justificativa pela qual o estado da análise de impacto foi declarado como \"Não afetado\"",
@@ -716,6 +718,7 @@
716718
"operational_risk": "Risco operacional",
717719
"operator": "Operador",
718720
"operator_help": null,
721+
"optional": null,
719722
"osi_approved": "Aprovado pelo OSI",
720723
"outdated_only": "Apenas desatualizado",
721724
"overview": "Visão geral",
@@ -964,6 +967,8 @@
964967
"relative_seconds_ago": null,
965968
"remove_component": "Remover componente",
966969
"reported_by": "Reportado por",
970+
"required_classifier": null,
971+
"required_collection_logic": null,
967972
"required_component_identifier": "Um identificador de componente é obrigatório",
968973
"required_component_name": "O nome do componente é obrigatório",
969974
"required_component_version": "A versão do componente é obrigatória",

0 commit comments

Comments
 (0)