UNCLASSIFIED

Commit 419f0100 authored by hunter.congress's avatar hunter.congress
Browse files

Merge branch 'Bull-1182a' of...

Merge branch 'Bull-1182a' of https://repo1.dso.mil/platform-one/party-bus/launchboard/launchboard-fe into BULL-1182a
parents ae4863dc fa1e0935
# launchboard
Launchboard Frontend for:
Production: https://launchboard.apps.dso.mil
Staging: https://launchboard.staging.dso.mil
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
## Testing
### Unit Tests
```
npm run test:unit
```
### End-to-End Tests
Platform One is still working on a solution to run `npm run test:e2e-ci` against a deployed app instance outside of Keycloak/Authservice.
We can run e2e tests on the Launchboard Front End by mocking api requests in Cypress (see `tests/e2e/fixtures/users/`).
```bash
# run e2e tests locally with the cypress ui
npm run test:e2e
# run e2e tests locally headless (no cypress ui)
npm run test:e2e -- --headless
```
......@@ -278,6 +278,12 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz",
"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": {
"version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
......@@ -4151,6 +4157,12 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"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": {
"version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
......@@ -4982,6 +4994,12 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz",
"integrity": "sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A==",
"dev": true
},
"colorette": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz",
"integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==",
"dev": true
}
}
},
......@@ -6052,6 +6070,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": {
"version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
......@@ -7112,6 +7136,12 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz",
"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": {
"version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
......@@ -15126,6 +15156,12 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001244.tgz",
"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": {
"version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
......@@ -15565,6 +15601,12 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz",
"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": {
"version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
......@@ -15728,6 +15770,12 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz",
"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": {
"version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
......@@ -16207,6 +16255,12 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz",
"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": {
"version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
......@@ -16408,6 +16462,12 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz",
"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": {
"version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
......@@ -18935,6 +18995,12 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001223.tgz",
"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": {
"version": "1.3.811",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.811.tgz",
......
......@@ -26,8 +26,7 @@ export default {
syncDarkMode() {
// make sure vuetify matches the current preference
if (this.$store && this.$store.state.userPreferences.userPreference) {
this.$vuetify.theme.dark =
this.$store.state.userPreferences.userPreference.darkMode;
this.$vuetify.theme.dark = this.$store.state.userPreferences.userPreference.darkMode;
}
},
},
......
<template>
<div>
This is a test
<UserSelect
:force-error="areNoAvailableSeats"
:force-error-message="
......
......@@ -95,8 +95,9 @@ export default {
if (!this.$refs.editingElementWrapper) {
return null;
}
const editInputs =
this.$refs.editingElementWrapper.getElementsByTagName("input");
const editInputs = this.$refs.editingElementWrapper.getElementsByTagName(
"input"
);
if (!editInputs || editInputs.length === 0) {
return null;
}
......
......@@ -84,8 +84,7 @@ export default {
mounted() {
this.user = this.$store.state.user.user;
this.darkMode = this.$store.state.userPreferences.userPreference.darkMode;
this.welcomeMenu =
this.$store.state.userPreferences.userPreference.welcomeMessage;
this.welcomeMenu = this.$store.state.userPreferences.userPreference.welcomeMessage;
this.changeLoadingColor();
},
methods: {
......
......@@ -13,12 +13,7 @@
>
<div class="d-flex banner-row subhead section-header">
<div
class="
d-flex
align-items-center
flex-wrap flex-sm-nowrap
name-container
"
class="d-flex align-items-center flex-wrap flex-sm-nowrap name-container"
>
<v-avatar class="mr-2 mr-md-4">
<img v-if="avatar" :src="avatar" :alt="name" />
......@@ -28,23 +23,13 @@
</div>
<div
v-if="$vuetify.breakpoint.mdAndUp"
class="
d-flex
align-items-center
justify-content-center
company-container
"
class="d-flex align-items-center justify-content-center company-container"
>
{{ company }}
</div>
<div
v-if="$vuetify.breakpoint.mdAndUp"
class="
d-flex
align-items-center
justify-content-center
position-container
"
class="d-flex align-items-center justify-content-center position-container"
>
{{ position }}
</div>
......@@ -59,22 +44,12 @@
>
<div class="d-flex banner-row subhead section-content">
<div
class="
d-flex
align-items-center
justify-content-center
company-container
"
class="d-flex align-items-center justify-content-center company-container"
>
{{ company }}
</div>
<div
class="
d-flex
align-items-center
justify-content-center
position-container
"
class="d-flex align-items-center justify-content-center position-container"
>
{{ position }}
</div>
......
<template>
<div v-if="!showMissionAppForm">
<GenerateMissionAppBanner
@show-mission-app-form="toggleMissionAppForm"
v-if="canGenerateMissionApp"
/>
<div>
<v-container fluid class="px-2 px-md-4 px-lg-8 px-xl-16 pb-0">
<v-row>
<v-col cols="12" class="d-flex flex-column pb-0 pb-lg-3">
......@@ -60,32 +56,19 @@
</v-row>
</v-container>
</div>
<div v-else>
<GenerateMissionAppHeader />
<GenerateMissionApplication @show-mission-app-form="toggleMissionAppForm" />
</div>
</template>
<script>
import ProjectsSummary from "@/components/ProjectsSummary";
import Section from "@/components/Section";
import GenerateMissionAppBanner from "@/components/GenerateMissionAppBanner";
import GenerateMissionAppHeader from "@/components/GenerateMissionAppHeader";
import GenerateMissionApplication from "@/components/GenerateMissionApplication";
import Permission from "@/config/user-permissions";
export default {
name: "projects",
components: {
Section,
ProjectsSummary,
GenerateMissionAppBanner,
GenerateMissionApplication,
GenerateMissionAppHeader,
},
data() {
return {
loadingProjectData: false,
showMissionAppForm: false,
};
},
methods: {
......@@ -101,16 +84,6 @@ export default {
setProjectLoading(loading) {
this.loadingProjectData = loading;
},
toggleMissionAppForm(show) {
this.showMissionAppForm = show;
},
},
computed: {
canGenerateMissionApp() {
return [Permission.ADMIN, Permission.SUPER_ADMIN].includes(
this.$store.state.user.user.permission
);
},
},
};
</script>
......@@ -36,16 +36,7 @@
/>
<div
id="team-table-header"
class="
d-flex
flex-column
justify-center
align-top
flex-sm-row
mb-6
mt-4
pl-2
"
class="d-flex flex-column justify-center align-top flex-sm-row mb-6 mt-4 pl-2"
v-if="permission"
>
<div>
......@@ -115,12 +106,7 @@
:multi-sort="false"
:mobile-breakpoint="mobileBreakpoint"
expand-icon="mdi-chevron-right"
class="
lb-mobile-enabled
background-transparent
position-relative
v-table-header
"
class="lb-mobile-enabled background-transparent position-relative v-table-header"
>
<template v-slot:top>
<!--
......
......@@ -549,11 +549,10 @@ export default {
},
async fetchStudentData() {
try {
const studentResponse =
await TrainingService.getCourseRegistrationsById(
this.$route.params.trainingId,
{ ...this.params, attendance: true }
);
const studentResponse = await TrainingService.getCourseRegistrationsById(
this.$route.params.trainingId,
{ ...this.params, attendance: true }
);
this.listItems =
studentResponse.registrations?.map((item) => {
item.completed = { value: item.completed, loading: false };
......
......@@ -9,7 +9,6 @@
"members": [
{
"id": 1,
"keycloakId": "aaaaaaaa-da97-4f57-a322-5e2685be6591",
"picture": null,
"name": "Test User",
"personnelType": null,
......@@ -33,7 +32,6 @@
},
{
"id": 2,
"keycloakId": "bbbbbbbb-da97-4f57-a322-5e2685be6591",
"picture": null,
"name": "Test Admin",
"personnelType": null,
......
......@@ -9,7 +9,6 @@
"users": [
{
"id": 2,
"keycloakId": "aaaaaaaa-56ff-4ddb-803a-8a1f4b73014e",
"picture": null,
"name": "Test Admin",
"personnelType": "P1 Personnel",
......
{
"result": {
"id": 1,
"keycloakId": "aaaaaaaa-da97-4f57-b322-5e2685be6591",
"picture": null,
"name": "Test Admin",
"personnelType": null,
......
{
"result": {
"id": 1,
"keycloakId": "aaaaaaaa-da97-4f57-c322-5e2685be6591",
"picture": null,
"name": "Test Super Admin",
"personnelType": null,
......
{
"result": {
"id": 1,
"keycloakId": "aaaaaaaa-da97-4f57-a322-5e2685be6591",
"picture": null,
"name": "Test User",
"personnelType": null,
......
......@@ -112,8 +112,8 @@ describe("ProjectsSummary", () => {
localVue,
vuetify,
});
const failedProjectJobs =
wrapper.vm.retrieveFailedProjectJobsFromFailedPipeline({
const failedProjectJobs = wrapper.vm.retrieveFailedProjectJobsFromFailedPipeline(
{
id: "1",
links: {},
latestPipeline: {
......@@ -127,7 +127,8 @@ describe("ProjectsSummary", () => {
],
},
favorite: true,
});
}
);
expect(failedProjectJobs.length === 1).toBeTruthy();
});
it("should filter by favorited projects", () => {
......
......@@ -12,7 +12,6 @@ const fakeWait = (ms, val) => {
describe("main", () => {
const mockUser = { name: "mockUser", roles: [] };
const mockUserPreference = {
keycloakId: "mock-keycloak-id",
darkMode: true,
};
......
import Vuex from "vuex";
import { shallowMount, createLocalVue } from "@vue/test-utils";
import Projects from "@/views/Projects.vue";
import Vuex from "vuex";
import Permission from "@/config/user-permissions";
import { shallowMount, createLocalVue } from "@vue/test-utils";
import GenerateMissionAppBanner from "@/components/GenerateMissionAppBanner";
const localVue = createLocalVue();
localVue.use(Vuex);
......@@ -49,11 +48,4 @@ describe("Projects", () => {
wrapper.vm.setProjectLoading("test");
expect(wrapper.vm.loadingProjectData).toEqual("test");
});
it("Should not show the generate mission app banner with a non-admin user", () => {
const wrapper = shallowMount(Projects, { store, localVue });
expect(
wrapper.findComponent(GenerateMissionAppBanner).exists()
).toBeFalsy();
});
});
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment