Skip to content

Commit

Permalink
More Frontend Infrastructure
Browse files Browse the repository at this point in the history
  • Loading branch information
gbdubs committed Sep 11, 2023
1 parent 1807ff1 commit e590748
Show file tree
Hide file tree
Showing 13 changed files with 248 additions and 82 deletions.
70 changes: 23 additions & 47 deletions frontend/components/modal/Error.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
<script setup lang="ts">
import { dialogBreakpoints } from '@/lib/breakpoints'
const { error: { errorModalVisible, error } } = useModal()
const fullError = computed(() => {
Expand All @@ -15,49 +13,27 @@ const fullError = computed(() => {
</script>

<template>
<div>
<PVDialog
v-model:visible="errorModalVisible"
:closable="true"
:modal="true"
:close-on-escape="true"
:dismissable-mask="true"
:draggable="false"
:breakpoints="dialogBreakpoints"
>
<template #header>
<div class="flex justify-content-between align-items-center w-full">
<div>
<div class="font-bold text-xl mb-2">
An error ocurred
</div>
<div class="text-sm">
Sorry about that, our team take bug reports seriously, and will try to make it right!
</div>
</div>
</div>
</template>
<div class="flex gap-3 flex-column">
<StandardDebug
label="Error Trace"
:value="fullError"
always
/>
</div>
<template #footer>
<div class="text-left text-sm">
Some common troubleshooting steps that might be helpful:
<ul>
<li><b>Refresh this page</b> - most of our pages save your progress as you go, so it's almost always fine to reload the page.</li>
<li><b>Check your internet connection</b> - this site requires connection to the internet for most functionality.</li>
<li><b>Visit this site on a desktop computer</b> - this site works best on desktop web browsers.</li>
</ul>
If this issue persists, please report this issue by <a
href="https://github.com/RMI-pacta/app/issues/new"
target="_blank"
>filing a bug in the PACTA repository</a>.
</div>
</template>
</PVDialog>
</div>
<StandardModal
v-model:visible="errorModalVisible"
header="An error ocurred"
sub-header="Sorry about that, our team take bug reports seriously, and will try to make it right!"
>
<StandardDebug
label="Error Trace"
:value="fullError"
always
/>
<div class="text-left text-sm">
Some common troubleshooting steps that might be helpful:
<ul>
<li><b>Refresh this page</b> - most of our pages save your progress as you go, so it's almost always fine to reload the page.</li>
<li><b>Check your internet connection</b> - this site requires connection to the internet for most functionality.</li>
<li><b>Visit this site on a desktop computer</b> - this site works best on desktop web browsers.</li>
</ul>
If this issue persists, please report this issue by <a
href="https://github.com/RMI-pacta/app/issues/new"
target="_blank"
>filing a bug in the PACTA repository</a>.
</div>
</StandardModal>
</template>
1 change: 1 addition & 0 deletions frontend/components/modal/Group.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
<div>
<ModalError />
<ModalLoading />
<ModalPermissionDenied />
</div>
</template>
13 changes: 7 additions & 6 deletions frontend/components/modal/Loading.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,14 @@ watch(() => loading.value, refreshZIndex)
ref="loadingModalEl"
data-anchor-id="loadingModal"
class="loading-modal"
@click="toggleDebug"
>
<!-- TODO(#8) Swap out this reference -->
<img
src="@/assets/img/logo_loading_animation_v1.gif"
class="gif shadow-3"
>
<div @click="() => { toggleDebug() } ">
<!-- TODO(#8) Swap out this reference -->
<img
src="@/assets/img/logo_loading_animation_v1.gif"
class="gif shadow-3"
>
</div>
<ul
v-if="debug"
class="demo-mode border-1 pr-3 py-2"
Expand Down
37 changes: 37 additions & 0 deletions frontend/components/modal/PermissionDenied.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<script setup lang="ts">
const { permissionDenied: { permissionDeniedVisible, permissionDeniedError }, error: { error } } = useModal()

Check failure on line 2 in frontend/components/modal/PermissionDenied.vue

View workflow job for this annotation

GitHub Actions / frontend-build-lint-test

'error' is assigned a value but never used
const router = useRouter()
const navigateBack = () => {
// If the user didn't land here directly, go back to the previous page.
if (window.history.length > 1) {
router.back()
return
}
// Otherwise, just take them home.
return router.push('/')
}
</script>

<template>
<StandardModal
v-model:visible="permissionDeniedVisible"
header="Permission Denied"
sub-header="You aren't authorized to view this page"
@closed="navigateBack"
>
<p>
It is likely that you have gotten here either by entering in an invalid
URL, or by clicking on a link or button that is not set up correctly.
</p>
<p>
If you think this is a bug (something that you should have access
to), or if you want to let us know how you got here, please file a bug.
</p>
<StandardDebug
label="Technical Error"
:value="permissionDeniedError"
always
/>
</StandardModal>
</template>
3 changes: 3 additions & 0 deletions frontend/components/standard/Content.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,8 @@
& > .p-button {
margin: 0.5rem 0;
}
min-height: calc(100vh - 9rem - 4px);
justify-content: center;
}
</style>
67 changes: 67 additions & 0 deletions frontend/components/standard/Modal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<script setup lang="ts">
import { dialogBreakpoints, smallDialogBreakpoints } from '@/lib/breakpoints'
const props = withDefaults(defineProps<{
small?: boolean
visible: boolean
header: string
subHeader?: string
}>(), {
small: false,
subHeader: ''
})
const emit = defineEmits<{
(e: 'update:visible', value: boolean): void
(e: 'closed'): void
}>()
const visible = computed<boolean>({
get: () => props.visible,
set: (value) => { emit('update:visible', value) }
})
const breakpoints = computed(() => props.small ? smallDialogBreakpoints : dialogBreakpoints)
const onHide = () => { emit('closed') }
</script>

<template>
<PVDialog
v-model:visible="visible"
:closable="true"
:modal="true"
:close-on-escape="true"
:dismissable-mask="true"
:draggable="false"
:breakpoints="breakpoints"
@hide="onHide"
>
<template #header>
<div class="flex justify-content-between align-items-center w-full">
<div>
<div class="font-bold text-xl mb-2">
{{ props.header }}
</div>
<div
v-if="props.subHeader"
class="text-md"
>
{{ props.subHeader }}}
</div>
</div>
</div>
</template>

<div class="flex flex-column gap-3 reset-child-margin">
<slot />
</div>
</PVDialog>
</template>

<style lang="scss">
.reset-child-margin {
& > * {
margin: 0;
}
}
</style>
13 changes: 13 additions & 0 deletions frontend/composables/newModal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ export const useModal = () => {
})
}

// permissionDenied
const permissionDeniedVisible = newModalVisibilityState('permissionDeniedVisibile')
const permissionDeniedError = useState<Error | null>(`${prefix}.permissionDeniedError`, () => null)
const setPermissionDenied = (e: Error) => {
permissionDeniedError.value = e
permissionDeniedVisible.value = true
}

const anyBlockingModalOpen = computed(() => anyModalVisible.value || loading.value)

const handleOAPIError = async <T>(t: OPAIError | T): Promise<T> => {
Expand Down Expand Up @@ -95,6 +103,11 @@ export const useModal = () => {
errorModalVisible,
withLoadingAndErrorHandling,
handleOAPIError
},
permissionDenied: {
permissionDeniedVisible,
permissionDeniedError,
setPermissionDenied
}
}
}
9 changes: 9 additions & 0 deletions frontend/middleware/admin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export default defineNuxtRouteMiddleware(async () => {
/* TODO(grady) add Authorization here
const { getMe } = useMSAL()
const { isAdmin } = await getMe()
if (!isAdmin.value) {
return await navigateTo('/denied')
}
*/
})
11 changes: 11 additions & 0 deletions frontend/pages/admin.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script setup lang="ts">
definePageMeta({
middleware: 'admin'
})
</script>

<template>
<div>
<NuxtPage />
</div>
</template>
59 changes: 59 additions & 0 deletions frontend/pages/admin/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<script setup lang="ts">
interface AdminItem {
title: string
icon: string
desc: string
href: string
}
const adminItems: AdminItem[] = [
{
title: 'PACTA Versions',
icon: 'pi pi-check-square',
desc: 'Create, update + manage versions of the PACTA algorithm + docker image',
href: '/admin/pacta-version'
}
]
</script>

<template>
<StandardContent>
<TitleBar title="Admin Console" />
<p>
This is the home for administrators of the PACTA platform.
</p>
<div class="grid align-items-stretch pb-3">
<div
v-for="item in adminItems"
:key="item.title"
class="col-12 md:col-6"
>
<PVCard class="h-full">
<template #title>
<div class="flex align-items-center">
<i
:class="item.icon"
class="text-2xl mr-3"
/>
<span>{{ item.title }}</span>
</div>
</template>
<template #content>
{{ item.desc }}
</template>
<template #footer>
<div class="flex justify-content-end w-full">
<LinkButton
class="p-button-sm"
:to="item.href"
icon="pi pi-arrow-right"
icon-pos="right"
label="Go"
/>
</div>
</template>
</PVCard>
</div>
</div>
</standardcontent>
</template>
9 changes: 9 additions & 0 deletions frontend/pages/denied.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<template>
<div />
</template>

<script setup lang="ts">
const { permissionDenied: { setPermissionDenied } } = useModal()
setPermissionDenied(new Error('permission denied'))
</script>
36 changes: 7 additions & 29 deletions frontend/pages/index.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,5 @@
<script setup lang="ts">
import { type PactaVersion } from 'openapi/generated/pacta'
const { isAuthenticated, signIn, signOut } = await useMSAL()
const { pactaClient } = useAPI()
const pactaVersions = useState<PactaVersion[]>('index.pactaVersions', () => [])
const testAPI = async (): Promise<void> => {
const resp = await pactaClient.listPactaVersions()
if ('message' in resp) {
console.error('error response from server', resp)
return
}
pactaVersions.value = resp
}
</script>

<template>
Expand All @@ -32,19 +17,12 @@ const testAPI = async (): Promise<void> => {
label="Sign In"
@click="signIn"
/>
<div v-else>
<PVButton
class="inline-block"
label="Test the API"
@click="testAPI"
/>

<PVButton
class="inline-block m-2"
label="Sign Out"
icon="pi pi-sign-out"
@click="signOut"
/>
</div>
<PVButton
v-else
class="inline-block"
label="Sign Out"
icon="pi pi-sign-out"
@click="signOut"
/>
</StandardContent>
</template>
Loading

0 comments on commit e590748

Please sign in to comment.