UNCLASSIFIED

Commits (9)
...@@ -320,6 +320,12 @@ ...@@ -320,6 +320,12 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz",
"integrity": "sha512-k/RYs6zc/fjbxTjaWZemeSmOjO0JJV+KguOBA3NwPup8uzxM1cMhR2BD9XmO86GuqaqTCO8CgkgH9Rz//vdDiA==" "integrity": "sha512-k/RYs6zc/fjbxTjaWZemeSmOjO0JJV+KguOBA3NwPup8uzxM1cMhR2BD9XmO86GuqaqTCO8CgkgH9Rz//vdDiA=="
}, },
"colorette": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz",
"integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==",
"dev": true
},
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.3.811", "version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
...@@ -4267,6 +4273,12 @@ ...@@ -4267,6 +4273,12 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true "dev": true
}, },
"colorette": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz",
"integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==",
"dev": true
},
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.3.811", "version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
...@@ -5144,6 +5156,12 @@ ...@@ -5144,6 +5156,12 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz",
"integrity": "sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A==", "integrity": "sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A==",
"dev": true "dev": true
},
"colorette": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz",
"integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==",
"dev": true
} }
} }
}, },
...@@ -6216,6 +6234,12 @@ ...@@ -6216,6 +6234,12 @@
} }
} }
}, },
"colorette": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz",
"integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==",
"dev": true
},
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.3.811", "version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
...@@ -7276,6 +7300,12 @@ ...@@ -7276,6 +7300,12 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz",
"integrity": "sha512-k/RYs6zc/fjbxTjaWZemeSmOjO0JJV+KguOBA3NwPup8uzxM1cMhR2BD9XmO86GuqaqTCO8CgkgH9Rz//vdDiA==" "integrity": "sha512-k/RYs6zc/fjbxTjaWZemeSmOjO0JJV+KguOBA3NwPup8uzxM1cMhR2BD9XmO86GuqaqTCO8CgkgH9Rz//vdDiA=="
}, },
"colorette": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz",
"integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==",
"dev": true
},
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.3.811", "version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
...@@ -12310,9 +12340,9 @@ ...@@ -12310,9 +12340,9 @@
}, },
"dependencies": { "dependencies": {
"ws": { "ws": {
"version": "7.5.3", "version": "7.5.4",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.4.tgz",
"integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==", "integrity": "sha512-zP9z6GXm6zC27YtspwH99T3qTG7bBFv2VIkeHstMLrLlDJuzA7tQ5ls3OJ1hOGGCzTQPniNJoHXIAOS0Jljohg==",
"dev": true "dev": true
} }
} }
...@@ -12346,9 +12376,9 @@ ...@@ -12346,9 +12376,9 @@
} }
}, },
"ws": { "ws": {
"version": "7.5.3", "version": "7.5.4",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.4.tgz",
"integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==" "integrity": "sha512-zP9z6GXm6zC27YtspwH99T3qTG7bBFv2VIkeHstMLrLlDJuzA7tQ5ls3OJ1hOGGCzTQPniNJoHXIAOS0Jljohg=="
} }
} }
}, },
...@@ -12897,9 +12927,9 @@ ...@@ -12897,9 +12927,9 @@
"dev": true "dev": true
}, },
"ws": { "ws": {
"version": "7.5.3", "version": "7.5.4",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.4.tgz",
"integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==", "integrity": "sha512-zP9z6GXm6zC27YtspwH99T3qTG7bBFv2VIkeHstMLrLlDJuzA7tQ5ls3OJ1hOGGCzTQPniNJoHXIAOS0Jljohg==",
"dev": true "dev": true
} }
} }
...@@ -15329,6 +15359,12 @@ ...@@ -15329,6 +15359,12 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001244.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001244.tgz",
"integrity": "sha512-Wb4UFZPkPoJoKKVfELPWytRzpemjP/s0pe22NriANru1NoI+5bGNxzKtk7edYL8rmCWTfQO8eRiF0pn1Dqzx7Q==" "integrity": "sha512-Wb4UFZPkPoJoKKVfELPWytRzpemjP/s0pe22NriANru1NoI+5bGNxzKtk7edYL8rmCWTfQO8eRiF0pn1Dqzx7Q=="
}, },
"colorette": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz",
"integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==",
"dev": true
},
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.3.811", "version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
...@@ -15726,6 +15762,12 @@ ...@@ -15726,6 +15762,12 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz",
"integrity": "sha512-k/RYs6zc/fjbxTjaWZemeSmOjO0JJV+KguOBA3NwPup8uzxM1cMhR2BD9XmO86GuqaqTCO8CgkgH9Rz//vdDiA==" "integrity": "sha512-k/RYs6zc/fjbxTjaWZemeSmOjO0JJV+KguOBA3NwPup8uzxM1cMhR2BD9XmO86GuqaqTCO8CgkgH9Rz//vdDiA=="
}, },
"colorette": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz",
"integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==",
"dev": true
},
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.3.811", "version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
...@@ -15889,6 +15931,12 @@ ...@@ -15889,6 +15931,12 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz",
"integrity": "sha512-k/RYs6zc/fjbxTjaWZemeSmOjO0JJV+KguOBA3NwPup8uzxM1cMhR2BD9XmO86GuqaqTCO8CgkgH9Rz//vdDiA==" "integrity": "sha512-k/RYs6zc/fjbxTjaWZemeSmOjO0JJV+KguOBA3NwPup8uzxM1cMhR2BD9XmO86GuqaqTCO8CgkgH9Rz//vdDiA=="
}, },
"colorette": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz",
"integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==",
"dev": true
},
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.3.811", "version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
...@@ -16368,6 +16416,12 @@ ...@@ -16368,6 +16416,12 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz",
"integrity": "sha512-k/RYs6zc/fjbxTjaWZemeSmOjO0JJV+KguOBA3NwPup8uzxM1cMhR2BD9XmO86GuqaqTCO8CgkgH9Rz//vdDiA==" "integrity": "sha512-k/RYs6zc/fjbxTjaWZemeSmOjO0JJV+KguOBA3NwPup8uzxM1cMhR2BD9XmO86GuqaqTCO8CgkgH9Rz//vdDiA=="
}, },
"colorette": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz",
"integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==",
"dev": true
},
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.3.811", "version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
...@@ -16569,6 +16623,12 @@ ...@@ -16569,6 +16623,12 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz",
"integrity": "sha512-k/RYs6zc/fjbxTjaWZemeSmOjO0JJV+KguOBA3NwPup8uzxM1cMhR2BD9XmO86GuqaqTCO8CgkgH9Rz//vdDiA==" "integrity": "sha512-k/RYs6zc/fjbxTjaWZemeSmOjO0JJV+KguOBA3NwPup8uzxM1cMhR2BD9XmO86GuqaqTCO8CgkgH9Rz//vdDiA=="
}, },
"colorette": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz",
"integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==",
"dev": true
},
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.3.811", "version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
...@@ -19105,6 +19165,12 @@ ...@@ -19105,6 +19165,12 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz",
"integrity": "sha512-k/RYs6zc/fjbxTjaWZemeSmOjO0JJV+KguOBA3NwPup8uzxM1cMhR2BD9XmO86GuqaqTCO8CgkgH9Rz//vdDiA==" "integrity": "sha512-k/RYs6zc/fjbxTjaWZemeSmOjO0JJV+KguOBA3NwPup8uzxM1cMhR2BD9XmO86GuqaqTCO8CgkgH9Rz//vdDiA=="
}, },
"colorette": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz",
"integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==",
"dev": true
},
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.3.811", "version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
...@@ -21437,9 +21503,9 @@ ...@@ -21437,9 +21503,9 @@
"dev": true "dev": true
}, },
"ws": { "ws": {
"version": "7.5.3", "version": "7.5.4",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.4.tgz",
"integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==", "integrity": "sha512-zP9z6GXm6zC27YtspwH99T3qTG7bBFv2VIkeHstMLrLlDJuzA7tQ5ls3OJ1hOGGCzTQPniNJoHXIAOS0Jljohg==",
"dev": true "dev": true
} }
} }
...@@ -21715,9 +21781,9 @@ ...@@ -21715,9 +21781,9 @@
} }
}, },
"ws": { "ws": {
"version": "7.5.3", "version": "7.5.4",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.4.tgz",
"integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==", "integrity": "sha512-zP9z6GXm6zC27YtspwH99T3qTG7bBFv2VIkeHstMLrLlDJuzA7tQ5ls3OJ1hOGGCzTQPniNJoHXIAOS0Jljohg==",
"dev": true "dev": true
} }
} }
......
...@@ -26,8 +26,7 @@ export default { ...@@ -26,8 +26,7 @@ export default {
syncDarkMode() { syncDarkMode() {
// make sure vuetify matches the current preference // make sure vuetify matches the current preference
if (this.$store && this.$store.state.userPreferences.userPreference) { if (this.$store && this.$store.state.userPreferences.userPreference) {
this.$vuetify.theme.dark = this.$vuetify.theme.dark = this.$store.state.userPreferences.userPreference.darkMode;
this.$store.state.userPreferences.userPreference.darkMode;
} }
}, },
}, },
......
...@@ -16,7 +16,7 @@ HTTP.interceptors.response.use( ...@@ -16,7 +16,7 @@ HTTP.interceptors.response.use(
// If err.status does not exist a general networking error occurred. // If err.status does not exist a general networking error occurred.
// We'll assume that their keycloak session has expired, so refresh the // We'll assume that their keycloak session has expired, so refresh the
// page which will redirect them to login // page which will redirect them to login
if (!err.status) { if (!err.status && !err.response?.status) {
location.reload(); location.reload();
} else { } else {
throw err; throw err;
......
...@@ -95,8 +95,9 @@ export default { ...@@ -95,8 +95,9 @@ export default {
if (!this.$refs.editingElementWrapper) { if (!this.$refs.editingElementWrapper) {
return null; return null;
} }
const editInputs = const editInputs = this.$refs.editingElementWrapper.getElementsByTagName(
this.$refs.editingElementWrapper.getElementsByTagName("input"); "input"
);
if (!editInputs || editInputs.length === 0) { if (!editInputs || editInputs.length === 0) {
return null; return null;
} }
......
...@@ -84,8 +84,7 @@ export default { ...@@ -84,8 +84,7 @@ export default {
mounted() { mounted() {
this.user = this.$store.state.user.user; this.user = this.$store.state.user.user;
this.darkMode = this.$store.state.userPreferences.userPreference.darkMode; this.darkMode = this.$store.state.userPreferences.userPreference.darkMode;
this.welcomeMenu = this.welcomeMenu = this.$store.state.userPreferences.userPreference.welcomeMessage;
this.$store.state.userPreferences.userPreference.welcomeMessage;
this.changeLoadingColor(); this.changeLoadingColor();
}, },
methods: { methods: {
......
...@@ -25,7 +25,13 @@ ...@@ -25,7 +25,13 @@
and star the projects that you are interested in.</v-card-text and star the projects that you are interested in.</v-card-text
> >
</v-card> </v-card>
<v-expansion-panels accordion multiple hover flat v-else> <v-expansion-panels
accordion
multiple
hover
flat
v-else-if="this.panelView === true"
>
<v-expansion-panel <v-expansion-panel
v-for="(project, index) in filteredProjects" v-for="(project, index) in filteredProjects"
:key="index" :key="index"
...@@ -231,6 +237,100 @@ ...@@ -231,6 +237,100 @@
</v-expansion-panel-content> </v-expansion-panel-content>
</v-expansion-panel> </v-expansion-panel>
</v-expansion-panels> </v-expansion-panels>
<v-row class="justify-content-center" v-else-if="this.cardView === true">
<v-col
v-for="(project, index) in filteredProjects"
:lg="projectCardColumnLgCount"
:key="index"
:project="project"
:cols="12"
>
<v-card class="card">
<div
v-bind:class="{
'project-card-header-failed':
project.latestPipeline.status === 'failed',
'project-card-header-passed':
project.latestPipeline.status === 'passed',
}"
>
<v-card-title class="justify-content-center project-card-title">
<div>
<p>
{{ project.name }}
</p>
<v-row class="justify-content-center">
<v-tooltip top>
<template v-slot:activator="{ on, attrs }">
<v-btn
icon
:href="project.links.repo"
rel="noopener noreferer"
target="_blank"
v-bind="attrs"
v-on="on"
@click.native.stop
color="primary"
>
<v-icon small>$vuetify.icons.gitlab</v-icon>
</v-btn>
</template>
<span>GitLab repository</span>
</v-tooltip>
</v-row>
</div>
</v-card-title>
</div>
<v-card-actions>
<v-layout row justify-center class="project-card-detail">
<v-card-text v-if="project.latestPipeline">
<div class="project-card-text">
Pipeline: {{ project.latestPipeline.message }}
</div>
</v-card-text>
<v-tooltip bottom>
<template v-slot:activator="{ on, attrs }">
<span v-bind="attrs" v-on="on">
<GitLabIcon
v-if="
project.latestPipeline.status === 'running' ||
project.latestPipeline.status === 'pending'
"
class="status-icon"
:status="'running'"
/>
<GitLabIcon
v-if="project.latestPipeline.status === 'failed'"
class="status-icon"
:status="'failed'"
/> </span
></template>
<span>
Latest Pipeline: {{ project.latestPipeline.status }}
</span>
</v-tooltip>
<router-link
class="project-title"
target="_blank"
v-for="(
job, jIndex
) in retrieveFailedProjectJobsFromFailedPipeline(project)"
:key="jIndex"
:to="job.link"
>
<a
class="project-card-text"
:href="job.link"
rel="noopener noreferer"
target="_blank"
>{{ job.name }};
</a>
</router-link>
</v-layout>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-skeleton-loader> </v-skeleton-loader>
</v-container> </v-container>
</template> </template>
...@@ -248,6 +348,10 @@ export default { ...@@ -248,6 +348,10 @@ export default {
ErrorMessage, ErrorMessage,
}, },
props: { props: {
projectCardColumnLgCount: {
type: Number,
default: 4,
},
detailed: { detailed: {
type: Boolean, type: Boolean,
default: true, default: true,
...@@ -258,6 +362,8 @@ export default { ...@@ -258,6 +362,8 @@ export default {
}, },
data: () => ({ data: () => ({
loading: false, loading: false,
panelView: false,
cardView: true,
emptyString: false, emptyString: false,
error: false, error: false,
errorMessage: "", errorMessage: "",
...@@ -281,11 +387,13 @@ export default { ...@@ -281,11 +387,13 @@ export default {
async refreshProjects() { async refreshProjects() {
if (this.setProjectLoading) { if (this.setProjectLoading) {
this.setProjectLoading(true); this.setProjectLoading(true);
this.loading = true;
} }
this.error = false; this.error = false;
this.emptyString = false; this.emptyString = false;
try { try {
const projects = await ProjectService.getProjectsSummary(); const projects = await ProjectService.getProjectsSummary();
this.failedProjectJobs = this.projects;
if (projects) { if (projects) {
this.setProjects(projects); this.setProjects(projects);
} }
...@@ -299,6 +407,22 @@ export default { ...@@ -299,6 +407,22 @@ export default {
} }
if (this.setProjectLoading) { if (this.setProjectLoading) {
this.setProjectLoading(false); this.setProjectLoading(false);
this.loading = false;
}
},
setCardView() {
this.panelView = false;
this.cardView = true;
},
setPanelView() {
this.panelView = true;
this.cardView = false;
},
retrieveFailedProjectJobsFromFailedPipeline(project) {
if (project.latestPipeline.status === "failed") {
return (project.latestPipeline.jobs || []).filter(
(o) => o.status === "failed"
);
} }
}, },
}, },
...@@ -330,6 +454,35 @@ export default { ...@@ -330,6 +454,35 @@ export default {
.status-icon { .status-icon {
width: 24px; width: 24px;
height: 24px; height: 24px;
margin-right: 10px;
}
.project-card-header-passed {
background-color: map-get($material-light, "background-accent-1");
color: map-get($material-light, "secondary-text-color");
fill: map-get($material-light, "secondary-text-color");
}
.project-card-header-failed {
background-color: #ff3838;
color: map-get($material-light, "secondary-text-color");
fill: map-get($material-light, "secondary-text-color");
}
.project-card-title {
padding-bottom: 20px;
}
.project-card-detail {
padding-top: 30px;
padding-bottom: 45px;
padding-left: 45px;
padding-right: 45px;
}
.project-card-text {
font-size: medium;
}
.card {
min-height: 100%;
min-width: 100%;
max-width: 400px;
margin: auto;
} }
} }
</style> </style>
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
</template> </template>
<span>Refresh</span> <span>Refresh</span>
</v-tooltip> </v-tooltip>
<slot name="header-bar-icons"> </slot>
<v-btn <v-btn
v-if="!hideCollapse && !hideCollapseButton" v-if="!hideCollapse && !hideCollapseButton"
icon icon
......
...@@ -13,12 +13,7 @@ ...@@ -13,12 +13,7 @@
> >
<div class="d-flex banner-row subhead section-header"> <div class="d-flex banner-row subhead section-header">
<div <div
class=" class="d-flex align-items-center flex-wrap flex-sm-nowrap name-container"
d-flex
align-items-center
flex-wrap flex-sm-nowrap
name-container
"
> >
<v-avatar class="mr-2 mr-md-4"> <v-avatar class="mr-2 mr-md-4">
<img v-if="avatar" :src="avatar" :alt="name" /> <img v-if="avatar" :src="avatar" :alt="name" />
...@@ -28,23 +23,13 @@ ...@@ -28,23 +23,13 @@
</div> </div>
<div <div
v-if="$vuetify.breakpoint.mdAndUp" v-if="$vuetify.breakpoint.mdAndUp"
class=" class="d-flex align-items-center justify-content-center company-container"
d-flex
align-items-center
justify-content-center
company-container
"
> >
{{ company }} {{ company }}
</div> </div>
<div <div
v-if="$vuetify.breakpoint.mdAndUp" v-if="$vuetify.breakpoint.mdAndUp"
class=" class="d-flex align-items-center justify-content-center position-container"
d-flex
align-items-center
justify-content-center
position-container
"
> >
{{ position }} {{ position }}
</div> </div>
...@@ -59,22 +44,12 @@ ...@@ -59,22 +44,12 @@
> >
<div class="d-flex banner-row subhead section-content"> <div class="d-flex banner-row subhead section-content">
<div <div
class=" class="d-flex align-items-center justify-content-center company-container"
d-flex
align-items-center
justify-content-center
company-container
"
> >
{{ company }} {{ company }}
</div> </div>
<div <div
class=" class="d-flex align-items-center justify-content-center position-container"
d-flex
align-items-center
justify-content-center
position-container
"
> >
{{ position }} {{ position }}
</div> </div>
......
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
<img v-if="item.avatar" :src="item.avatar" :alt="data.item.name" /> <img v-if="item.avatar" :src="item.avatar" :alt="data.item.name" />
<v-icon x-large v-else>mdi-account-circle</v-icon> <v-icon x-large v-else>mdi-account-circle</v-icon>
</v-list-item-avatar> </v-list-item-avatar>
<v-list-item-content> <v-list-item-content>
<v-list-item-title class="text-left">{{ item.name }}</v-list-item-title> <v-list-item-title class="text-left">{{ item.name }}</v-list-item-title>
<v-list-item-subtitle class="text-left">{{ <v-list-item-subtitle class="text-left">{{
item.email item.email
......
...@@ -15,10 +15,44 @@ ...@@ -15,10 +15,44 @@
:loading="loadingProjectData" :loading="loadingProjectData"
:refreshClick="refreshProjectData" :refreshClick="refreshProjectData"
> >
<div
class="align-items-center d-flex"
slot="header-bar-icons"
:cardViewProjects="cardViewProjects"
:panelViewProjects="panelViewProjects"
>
<v-tooltip top>
<template v-slot:activator="{ on, attrs }">
<v-btn
icon
v-bind="attrs"
v-on="on"
@click="cardViewProjects"
>
<v-icon>mdi-view-grid</v-icon>
</v-btn>
</template>
<span>Card View</span>
</v-tooltip>
<v-tooltip top>
<template v-slot:activator="{ on, attrs }">
<v-btn
icon
v-bind="attrs"
v-on="on"
@click="panelViewProjects"
>
<v-icon>mdi-reorder-horizontal</v-icon>
</v-btn>
</template>
<span>Panel View</span>
</v-tooltip>
</div>
<ProjectsSummary <ProjectsSummary
slot="content" slot="content"
ref="projectSummary" ref="projectSummary"
:setProjectLoading="setProjectLoading" :setProjectLoading="setProjectLoading"
:projectCardColumnLgCount="4"
detailed detailed
/> />
</Section> </Section>
...@@ -58,6 +92,12 @@ export default { ...@@ -58,6 +92,12 @@ export default {
refreshProjectData() { refreshProjectData() {
this.$refs.projectSummary.refreshProjects(); this.$refs.projectSummary.refreshProjects();
}, },
cardViewProjects() {
this.$refs.projectSummary.setCardView();
},
panelViewProjects() {
this.$refs.projectSummary.setPanelView();
},
setProjectLoading(loading) { setProjectLoading(loading) {
this.loadingProjectData = loading; this.loadingProjectData = loading;
}, },
......
<template> <template>
<div> <div>
<v-container class="team"> <div v-if="!Object.entries(team).length">
<NotFoundComponent />
</div>
<v-container class="team" v-else>
<div class="d-flex flex-column justify-center align-top flex-sm-row mb-4"> <div class="d-flex flex-column justify-center align-top flex-sm-row mb-4">
<div> <div>
<h1 <h1
...@@ -304,6 +308,7 @@ import SelectAddStudentsToCourseDialog from "@/components/Dialogs/SelectAddStude ...@@ -304,6 +308,7 @@ import SelectAddStudentsToCourseDialog from "@/components/Dialogs/SelectAddStude
import TeamService from "@/api/services/team"; import TeamService from "@/api/services/team";
import UserSelect from "@/components/UserSelect"; import UserSelect from "@/components/UserSelect";
import AddTeam from "@/components/AddTeam"; import AddTeam from "@/components/AddTeam";
import NotFoundComponent from "@/components/NotFoundComponent";
import { defaultSnackbarTimeout } from "@/config/config"; import { defaultSnackbarTimeout } from "@/config/config";
import inputRules from "@/utils/inputRules"; import inputRules from "@/utils/inputRules";
import Permission from "@/config/user-permissions"; import Permission from "@/config/user-permissions";
...@@ -317,6 +322,7 @@ export default { ...@@ -317,6 +322,7 @@ export default {
SelectAddStudentsToCourseDialog, SelectAddStudentsToCourseDialog,
AddTeam, AddTeam,
BaseDialog, BaseDialog,
NotFoundComponent,
}, },
data: () => ({ data: () => ({
editValid: false, editValid: false,
......
<template> <template>
<div> <div>
<v-container class="course"> <div v-if="!Object.entries(trainingCourse).length">
<NotFoundComponent />
</div>
<v-container class="course" v-else>
<v-skeleton-loader <v-skeleton-loader
:loading="initialLoad" :loading="initialLoad"
type="table-heading,table-thead, table-tbody" type="table-heading,table-thead, table-tbody"
...@@ -384,6 +387,7 @@ ...@@ -384,6 +387,7 @@
import moment from "moment"; import moment from "moment";
import TrainingService from "@/api/services/training"; import TrainingService from "@/api/services/training";
import inputRules from "@/utils/inputRules"; import inputRules from "@/utils/inputRules";
import NotFoundComponent from "@/components/NotFoundComponent";
import TrainingAttendance from "@/components/Training/TrainingAttendance"; import TrainingAttendance from "@/components/Training/TrainingAttendance";
import { SET_ERROR_MESSAGE, SET_ERROR_DIALOG } from "@/store/mutation-types"; import { SET_ERROR_MESSAGE, SET_ERROR_DIALOG } from "@/store/mutation-types";
import UserSelect from "@/components/UserSelect"; import UserSelect from "@/components/UserSelect";
...@@ -391,7 +395,12 @@ import { DEFAULT_PAGINATION_PARAMS } from "@/config/table-constants"; ...@@ -391,7 +395,12 @@ import { DEFAULT_PAGINATION_PARAMS } from "@/config/table-constants";
import AddStudentsToCourseDialog from "@/components/Dialogs/AddStudentsToCourseDialog"; import AddStudentsToCourseDialog from "@/components/Dialogs/AddStudentsToCourseDialog";
export default { export default {
components: { AddStudentsToCourseDialog, TrainingAttendance, UserSelect }, components: {
AddStudentsToCourseDialog,
TrainingAttendance,
UserSelect,
NotFoundComponent,
},
data: () => ({ data: () => ({
selectedInstructors: [], selectedInstructors: [],
loading: false, loading: false,
...@@ -529,11 +538,10 @@ export default { ...@@ -529,11 +538,10 @@ export default {
}, },
async fetchStudentData() { async fetchStudentData() {
try { try {
const studentResponse = const studentResponse = await TrainingService.getCourseRegistrationsById(
await TrainingService.getCourseRegistrationsById( this.$route.params.trainingId,
this.$route.params.trainingId, { ...this.params, attendance: true }
{ ...this.params, attendance: true } );
);
this.listItems = this.listItems =
studentResponse.registrations?.map((item) => { studentResponse.registrations?.map((item) => {
item.completed = { value: item.completed, loading: false }; item.completed = { value: item.completed, loading: false };
......
...@@ -69,7 +69,6 @@ ...@@ -69,7 +69,6 @@
:add-busy="state.isAddingBusy" :add-busy="state.isAddingBusy"
/> />
</template> </template>
<template v-slot:[`item.name`]="{ item }"> <template v-slot:[`item.name`]="{ item }">
<router-link <router-link
:to="{ name: 'TeamDetails', params: { teamId: item.id } }" :to="{ name: 'TeamDetails', params: { teamId: item.id } }"
...@@ -93,6 +92,7 @@ ...@@ -93,6 +92,7 @@
> >
</div> </div>
</template> </template>
<template v-slot:[`item.email`]="{ item }" class="team-leads"> <template v-slot:[`item.email`]="{ item }" class="team-leads">
<div <div
class="d-flex flex-wrap white-space-nowrap" class="d-flex flex-wrap white-space-nowrap"
......
...@@ -59,6 +59,29 @@ ...@@ -59,6 +59,29 @@
:refreshClick="refreshProjectData" :refreshClick="refreshProjectData"
headerTitle="My Project Summary" headerTitle="My Project Summary"
> >
<div
class="align-items-center d-flex"
slot="header-bar-icons"
:cardViewProjects="cardViewProjects"
:panelViewProjects="panelViewProjects"
>
<v-tooltip top>
<template v-slot:activator="{ on, attrs }">
<v-btn icon v-bind="attrs" v-on="on" @click="cardViewProjects">
<v-icon>mdi-view-grid</v-icon>
</v-btn>
</template>
<span>Card View</span>
</v-tooltip>
<v-tooltip top>
<template v-slot:activator="{ on, attrs }">
<v-btn icon v-bind="attrs" v-on="on" @click="panelViewProjects">
<v-icon>mdi-reorder-horizontal</v-icon>
</v-btn>
</template>
<span>Panel View</span>
</v-tooltip>
</div>
<span slot="userinfo"> <span slot="userinfo">
<TutorialTooltip tooltipName="projects"> <TutorialTooltip tooltipName="projects">
<span id="projectsTutorialTooltip"></span> <span id="projectsTutorialTooltip"></span>
...@@ -68,6 +91,7 @@ ...@@ -68,6 +91,7 @@
slot="content" slot="content"
ref="projectSummary" ref="projectSummary"
:setProjectLoading="setProjectLoading" :setProjectLoading="setProjectLoading"
:projectCardColumnLgCount="6"
/> />
</Section> </Section>
...@@ -135,6 +159,12 @@ export default { ...@@ -135,6 +159,12 @@ export default {
refreshProjectData() { refreshProjectData() {
this.$refs.projectSummary.refreshProjects(); this.$refs.projectSummary.refreshProjects();
}, },
cardViewProjects() {
this.$refs.projectSummary.setCardView();
},
panelViewProjects() {
this.$refs.projectSummary.setPanelView();
},
refreshCurriculumSchedule() { refreshCurriculumSchedule() {
this.$refs.curriculumSchedule.refreshCurriculumSchedule(); this.$refs.curriculumSchedule.refreshCurriculumSchedule();
}, },
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
"members": [ "members": [
{ {
"id": 1, "id": 1,
"keycloakId": "aaaaaaaa-da97-4f57-a322-5e2685be6591",
"picture": null, "picture": null,
"name": "Test User", "name": "Test User",
"personnelType": null, "personnelType": null,
...@@ -33,7 +32,6 @@ ...@@ -33,7 +32,6 @@
}, },
{ {
"id": 2, "id": 2,
"keycloakId": "bbbbbbbb-da97-4f57-a322-5e2685be6591",
"picture": null, "picture": null,
"name": "Test Admin", "name": "Test Admin",
"personnelType": null, "personnelType": null,
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
"users": [ "users": [
{ {
"id": 2, "id": 2,
"keycloakId": "aaaaaaaa-56ff-4ddb-803a-8a1f4b73014e",
"picture": null, "picture": null,
"name": "Test Admin", "name": "Test Admin",
"personnelType": "P1 Personnel", "personnelType": "P1 Personnel",
......
{ {
"result": { "result": {
"id": 1, "id": 1,
"keycloakId": "aaaaaaaa-da97-4f57-b322-5e2685be6591",
"picture": null, "picture": null,
"name": "Test Admin", "name": "Test Admin",
"personnelType": null, "personnelType": null,
......
{ {
"result": { "result": {
"id": 1, "id": 1,
"keycloakId": "aaaaaaaa-da97-4f57-c322-5e2685be6591",
"picture": null, "picture": null,
"name": "Test Super Admin", "name": "Test Super Admin",
"personnelType": null, "personnelType": null,
......
{ {
"result": { "result": {
"id": 1, "id": 1,
"keycloakId": "aaaaaaaa-da97-4f57-a322-5e2685be6591",
"picture": null, "picture": null,
"name": "Test User", "name": "Test User",
"personnelType": null, "personnelType": null,
......
...@@ -35,6 +35,102 @@ describe("ProjectsSummary", () => { ...@@ -35,6 +35,102 @@ describe("ProjectsSummary", () => {
expect(wrapper.find(".error").exists()).toBe(false); expect(wrapper.find(".error").exists()).toBe(false);
}); });
it("should set panelView true and cardView false", () => {
ProjectService.getProjectsSummary = jest.fn();
// render the component
const wrapper = shallowMount(ProjectsSummary, {
mocks: {
$store: {
state: {
error: {},
projects: {
list: [],
},
},
commit: jest.fn(),
},
},
data() {
return {
cardView: true,
panelView: false,
};
},
localVue,
vuetify,
});
wrapper.vm.setPanelView();
expect(
wrapper.vm.panelView === true && wrapper.vm.cardView === false
).toBeTruthy();
});
it("should set panelView false and cardView true", () => {
ProjectService.getProjectsSummary = jest.fn();
// render the component
const wrapper = shallowMount(ProjectsSummary, {
mocks: {
$store: {
state: {
error: {},
projects: {
list: [],
},
},
commit: jest.fn(),
},
},
data() {
return {
cardView: true,
panelView: false,
};
},
localVue,
vuetify,
});
wrapper.vm.setCardView();
expect(
wrapper.vm.panelView === false && wrapper.vm.cardView === true
).toBeTruthy();
});
it("should return only failed jobs from a failed pipeline given a project", () => {
ProjectService.getProjectsSummary = jest.fn();
// render the component
const wrapper = shallowMount(ProjectsSummary, {
mocks: {
$store: {
state: {
error: {},
projects: {
list: [],
},
},
commit: jest.fn(),
},
},
localVue,
vuetify,
});
const failedProjectJobs = wrapper.vm.retrieveFailedProjectJobsFromFailedPipeline(
{
id: "1",
links: {},
latestPipeline: {
name: "testPipeline",
status: "failed",
latestPipeline: "",
message: "test",
jobs: [
{ name: "e2e-test", status: "failed", link: "" },
{ name: "e2e-test2", status: "passed", link: "" },
],
},
favorite: true,
}
);
expect(failedProjectJobs.length === 1).toBeTruthy();
});
it("should filter by favorited projects", () => { it("should filter by favorited projects", () => {
ProjectService.getProjectsSummary = jest.fn(); ProjectService.getProjectsSummary = jest.fn();
// render the component // render the component
......