Skip to content

Commit

Permalink
feat: GEO-1068 admin app - move page title into header (#682)
Browse files Browse the repository at this point in the history
  • Loading branch information
banders authored Aug 23, 2024
1 parent fa408c2 commit c3fcefc
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 39 deletions.
18 changes: 5 additions & 13 deletions admin-frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,11 @@
class="d-flex flex-column align-start"
:class="{ 'ptap-panel': areHeaderAndSidebarVisible }"
>
<div v-if="isTitleVisible || isBreadcrumbTrailVisible" class="mb-3">
<h2 class="page-title" v-if="isTitleVisible">
{{ activeRoute.meta.pageTitle }}
</h2>
<BreadcrumbTrail
class="pt-0 pb-0"
v-if="isBreadcrumbTrailVisible"
></BreadcrumbTrail>
</div>
<BreadcrumbTrail
class="pt-0 pb-0 mb-3"
v-if="isBreadcrumbTrailVisible"
></BreadcrumbTrail>

<router-view />
</v-main>
</div>
Expand Down Expand Up @@ -49,9 +45,7 @@ export default {
data() {
return {
areHeaderAndSidebarVisible: false,
isTitleVisible: false,
isBreadcrumbTrailVisible: false,
activeRoute: null,
};
},
computed: {
Expand All @@ -73,13 +67,11 @@ export default {
appStore,
...mapActions(authStore, ['doesUserHaveRole']),
onRouteChanged(to, from) {
this.activeRoute = to;
if (to.fullPath != '/error') {
//Reset error page message back to the default
NotificationService.setErrorPageMessage();
}
this.areHeaderAndSidebarVisible = to.meta.requiresAuth;
this.isTitleVisible = to?.meta?.isTitleVisible && to?.meta?.pageTitle;
this.isBreadcrumbTrailVisible =
to?.meta?.breadcrumbs?.length && this.doesUserHaveRole(USER_ROLE_NAME);
},
Expand Down
3 changes: 1 addition & 2 deletions admin-frontend/src/__tests__/App.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createTestingPinia } from '@pinia/testing';
import { waitFor } from '@testing-library/vue';
import { flushPromises, mount } from '@vue/test-utils';
import { getActivePinia, setActivePinia } from 'pinia';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
Expand All @@ -9,7 +10,6 @@ import * as directives from 'vuetify/directives';
import App from '../App.vue';
import router from '../router';
import { authStore } from '../store/modules/auth';
import { waitFor } from '@testing-library/vue';

// Mock the ResizeObserver
const ResizeObserverMock = vi.fn(() => ({
Expand Down Expand Up @@ -144,7 +144,6 @@ describe('App', () => {
};
mockDoesUserHaveRole.mockReturnValueOnce(false);
componentEnv.app.vm.onRouteChanged(to, null);
expect(componentEnv.app.vm.activeRoute).toStrictEqual(to);
expect(componentEnv.app.vm.areHeaderAndSidebarVisible).toBe(
to.meta.requiresAuth,
);
Expand Down
22 changes: 13 additions & 9 deletions admin-frontend/src/components/BreadcrumbTrail.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<template>
<v-breadcrumbs
:items="breadcrumbItems"
divider=">"
class="px-0"
></v-breadcrumbs>
<v-breadcrumbs :items="breadcrumbItems" class="px-0">
<template v-slot:divider>
<v-icon icon="mdi-chevron-right" size="x-small" class="px-0"></v-icon>
</template>
</v-breadcrumbs>
</template>

<script>
Expand Down Expand Up @@ -38,8 +38,11 @@ function routeToBreadcrumbItem(route, isEnabled = true) {
function updateBreadcrumbItems(route) {
const items = [];
if (route?.meta?.breadcrumbs?.length) {
items.push(...route.meta.breadcrumbs.map((b) => routeToBreadcrumbItem(router.getRoutes().find((r) => r.name == b))));
items.push(
...route.meta.breadcrumbs.map((b) =>
routeToBreadcrumbItem(router.getRoutes().find((r) => r.name == b)),
),
);
if (route?.name != dashboardRoute.name) {
items.push(routeToBreadcrumbItem(route, false));
Expand All @@ -60,14 +63,15 @@ watch(
<style>
.v-breadcrumbs-item {
padding-left: 0px !important;
padding-right: 0px !important;
font-size: 0.8em;
}
.v-breadcrumbs-item--link {
color: revert !important;
}
.v-breadcrumbs-divider {
padding-left: 2px !important;
padding-right: 2px !important;
padding-left: 0px !important;
padding-right: 0px !important;
}
.v-breadcrumbs-item--disabled {
opacity: 1 !important;
Expand Down
1 change: 0 additions & 1 deletion admin-frontend/src/components/ErrorPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,3 @@ export default {
height: 100%;
}
</style>
../services/notificationService
29 changes: 27 additions & 2 deletions admin-frontend/src/components/Header.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
<template>
<v-app-bar absolute style="z-index: 1002" class="d-flex justify-center">
<v-app-bar
absolute
style="z-index: 1002"
class="d-flex justify-center ps-6 pe-6"
>
<h2 v-if="isTitleVisible">
{{
activeRoute.meta.sectionTitle
? activeRoute.meta.sectionTitle
: activeRoute.meta.pageTitle
}}
</h2>
<v-spacer />
<div v-if="isAuthenticated" data-testid="account-info">
<v-icon icon="mdi-account" size="small" />
{{ userInfo?.displayName }}
</div>

<v-btn
class="btn-link"
class="btn-link ms-2"
v-if="isAuthenticated"
@click="redirectToLogout()"
data-testid="logout-btn"
Expand All @@ -34,8 +45,18 @@ export default {
message: false,
hints: true,
authRoutesLogout: sanitizeUrl(AuthRoutes.LOGOUT),
isTitleVisible: false,
activeRoute: null,
};
},
watch: {
$route: {
handler(to, from) {
this.onRouteChanged(to, from);
},
immediate: true,
},
},
computed: {
...mapState(authStore, ['isAuthenticated']),
...mapState(authStore, ['userInfo']),
Expand All @@ -44,6 +65,10 @@ export default {
redirectToLogout() {
window.location.href = this.authRoutesLogout;
},
onRouteChanged(to, from) {
this.activeRoute = to;
this.isTitleVisible = to?.meta?.isTitleVisible && to?.meta?.pageTitle;
},
},
};
</script>
Expand Down
37 changes: 36 additions & 1 deletion admin-frontend/src/components/__tests__/Header.spec.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
import { createTestingPinia } from '@pinia/testing';
import { render, screen } from '@testing-library/vue';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { nextTick } from 'vue';
import { createRouter, createWebHistory } from 'vue-router';
import { createVuetify } from 'vuetify';
import router from '../../router';
import { authStore } from '../../store/modules/auth';
import Header from '../Header.vue';

const pinia = createTestingPinia();
const vuetify = createVuetify();

const routes = router.getRoutes();
const mockRouter = createRouter({
history: createWebHistory(),
routes: routes,
});

const wrappedRender = async () => {
return render(Header, {
global: {
plugins: [pinia, vuetify],
plugins: [pinia, vuetify, mockRouter],
},
});
};
Expand Down Expand Up @@ -41,4 +51,29 @@ describe('Header', () => {
expect(screen.getByTestId('logout-btn')).toHaveTextContent('Logout');
});
});

describe('when route has a pageTitle but not sectionTitle', () => {
it('route pageTitle is shown', async () => {
const { getByText } = await wrappedRender();
const route = routes.find((r) => r.name == 'announcements'); //this route doesn't have a section title
await mockRouter.push({ name: route.name });
await nextTick();
const expectedTitle = route.meta.sectionTitle
? route.meta.sectionTitle
: route.meta.pageTitle;
expect(getByText(expectedTitle)).toBeInTheDocument();
});
});
describe('when route has a sectionTitle', () => {
it('route sectionTitle is shown (not pageTitle)', async () => {
const { getByText } = await wrappedRender();
const route = routes.find((r) => r.name == 'add-announcement'); //this route has a section title
await mockRouter.push({ name: route.name });
await nextTick();
const expectedTitle = route.meta.sectionTitle
? route.meta.sectionTitle
: route.meta.pageTitle;
expect(getByText(expectedTitle)).toBeInTheDocument();
});
});
});
34 changes: 23 additions & 11 deletions admin-frontend/src/components/announcements/AnnouncementForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
<div class="toolbar">
<h1>{{ title }}</h1>
<span class="fill-remaining-space"></span>
<v-btn v-if="!isConfirmDialogVisible" variant="outlined" color="primary" class="mr-2" @click="handleCancel"
<v-btn
v-if="!isConfirmDialogVisible"
variant="outlined"
color="primary"
class="mr-2"
@click="handleCancel"
>Cancel</v-btn
>

Expand Down Expand Up @@ -34,8 +39,8 @@
</div>
</div>

<v-row class="extend-to-right-edge border-t">
<v-col sm="6" md="7" lg="7" xl="8">
<v-row dense class="extend-to-right-edge border-t">
<v-col sm="6" md="7" lg="7" xl="8" class="px-0">
<div class="content">
<v-row dense class="mt-2 form-wrapper">
<v-col cols="12" md="12" sm="12">
Expand Down Expand Up @@ -180,9 +185,7 @@
variant="outlined"
>
<template #prepend-inner>
<v-btn
color="primary"
>Choose File</v-btn>
<v-btn color="primary">Choose File</v-btn>
</template>
</v-file-input>
</v-col>
Expand Down Expand Up @@ -303,7 +306,6 @@ const isPreviewVisible = computed(() => announcementsToPreview.value?.length);
const isConfirmDialogVisible = ref(false);
const attachment = ref<File | null>(null);
console.log(announcement)
const { handleSubmit, setErrors, errors, meta, values } = useForm({
initialValues: {
title: announcement?.title || '',
Expand Down Expand Up @@ -542,8 +544,16 @@ const handleSave = handleSubmit(async (values) => {
await emits('save', {
...values,
published_on: values.published_on ? convert(LocalDate.from(nativeJs(values.published_on))).toDate().toISOString() : undefined,
expires_on: values.expires_on ? convert(LocalDate.from(nativeJs(values.expires_on))).toDate().toISOString() : undefined,
published_on: values.published_on
? convert(LocalDate.from(nativeJs(values.published_on)))
.toDate()
.toISOString()
: undefined,
expires_on: values.expires_on
? convert(LocalDate.from(nativeJs(values.expires_on)))
.toDate()
.toISOString()
: undefined,
linkDisplayName: isEmpty(values.linkDisplayName)
? undefined
: values.linkDisplayName,
Expand All @@ -554,7 +564,7 @@ const handleSave = handleSubmit(async (values) => {
});
</script>

<style lang="scss">
<style scoped lang="scss">
.toolbar {
display: flex;
margin-bottom: 1rem;
Expand All @@ -564,7 +574,9 @@ const handleSave = handleSubmit(async (values) => {
flex: 1 1 auto;
}
}
.v-row {
margin-left: 0px !important;
}
.content {
width: 100%;
max-width: 800px;
Expand Down
2 changes: 2 additions & 0 deletions admin-frontend/src/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ const router = createRouter({
name: 'add-announcement',
component: AddAnnouncementPage,
meta: {
sectionTitle: PAGE_TITLES.ANNOUNCEMENTS,
pageTitle: PAGE_TITLES.ADD_ANNOUNCEMENT,
requiresAuth: true,
requiresRole: USER_ROLE_NAME,
Expand All @@ -88,6 +89,7 @@ const router = createRouter({
name: 'edit-announcement',
component: EditAnnouncementPage,
meta: {
sectionTitle: PAGE_TITLES.ANNOUNCEMENTS,
pageTitle: PAGE_TITLES.EDIT_ANNOUNCEMENT,
requiresAuth: true,
requiresRole: USER_ROLE_NAME,
Expand Down

0 comments on commit c3fcefc

Please sign in to comment.