Skip to content

Commit bfa8e6b

Browse files
committed
Merge pull request #6 from rpitv/fix-api-issue-3
Add Authentication and Authorization: Fix API issue #3
1 parent 6458679 commit bfa8e6b

13 files changed

+412
-29
lines changed

apps/glimpse-ui/.eslintrc.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ module.exports = {
2020
"jest-dom/prefer-required": "error",
2121
"jest-dom/prefer-enabled-disabled": "error",
2222
"jest-dom/prefer-checked": "error",
23-
"jest-dom/prefer-to-have-attribute": "error"
23+
"jest-dom/prefer-to-have-attribute": "error",
24+
"no-console": "off"
2425
}
2526
}

apps/glimpse-ui/components/RecentProductionsList.vue

+113-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<div class="past-prod-list">
2+
<simplebar ref="pastProdList" class="past-prod-list">
33
<VCard
44
:href="'/productions/' + prod.id"
55
v-for="prod in productions"
@@ -9,8 +9,14 @@
99
boilerplate
1010
>
1111
<VImg :src="prod.thumbnail.link" :title="prod.thumbnail.name" height="200px" />
12-
<VCardTitle>{{ prod.name }}</VCardTitle>
13-
<VCardSubtitle>{{ prod.description }}</VCardSubtitle>
12+
<div class="prod-card-text-wrapper">
13+
<VCardTitle>
14+
{{ prod.name }}
15+
</VCardTitle>
16+
<VCardSubtitle>
17+
{{ prod.description }}
18+
</VCardSubtitle>
19+
</div>
1420
<VRow>
1521
<VCol>
1622
<VCardText class="v-card__subtitle">
@@ -26,23 +32,71 @@
2632
</VCol>
2733
</VRow>
2834
</VCard>
29-
</div>
35+
36+
<VBtn
37+
v-if="showScrollButton"
38+
@click="pushLeft"
39+
fab
40+
dark
41+
x-large
42+
color="primary"
43+
class="scroll-btn"
44+
title="Click to scroll left"
45+
aria-label="Click to scroll left"
46+
>
47+
<font-awesome-icon :icon="['fal','chevron-right']" size="lg" />
48+
</VBtn>
49+
</simplebar>
3050
</template>
3151

3252
<script>
3353
import gql from 'graphql-tag'
3454
import moment from 'moment'
55+
import simplebar from 'simplebar-vue'
56+
import 'simplebar/dist/simplebar.min.css'
3557
3658
export default {
3759
name: 'RecentProductionsList',
60+
components: {
61+
simplebar
62+
},
3863
data () {
3964
return {
40-
productions: []
65+
productions: [],
66+
showScrollButton: true
4167
}
4268
},
69+
mounted () {
70+
this.$refs.pastProdList.SimpleBar.getScrollElement().addEventListener('scroll', this.handleScroll)
71+
},
72+
destroyed () {
73+
this.$refs.pastProdList.SimpleBar.getScrollElement().removeEventListener('scroll', this.handleScroll)
74+
},
4375
methods: {
4476
getFormattedDate (production) {
4577
return moment(production.startTime).format('MMM Do YYYY')
78+
},
79+
handleScroll (evt) {
80+
this.showScrollButton = (evt.target.scrollLeft === 0)
81+
},
82+
/**
83+
* Push this list left (or right, depending on how you think about it) one full width.
84+
* This exists for the right-chevron button, to demonstrate that this list is scrollable.
85+
* It scrolls in an ease-out manner one full width, or until the end of the list is hit.
86+
*/
87+
pushLeft () {
88+
let pxToPush = this.$refs.pastProdList.SimpleBar.getScrollElement().offsetWidth // Scroll the width of the element
89+
// Runs every 5ms
90+
const interval = setInterval(() => {
91+
const pushAmount = pxToPush / 35 // Scroll by 1/35th of the remaining amount - Creates ease-out effect
92+
this.$refs.pastProdList.SimpleBar.getScrollElement().scrollLeft += pushAmount
93+
94+
pxToPush -= pushAmount
95+
96+
if (pxToPush <= 1) { // Stop when 1 px left, with 0 it breaks as you infinitely approach 0
97+
clearInterval(interval)
98+
}
99+
}, 5)
46100
}
47101
},
48102
apollo: {
@@ -61,22 +115,69 @@ export default {
61115
</script>
62116

63117
<style lang="scss" scoped>
64-
/* Fix word wrapping in cards - See vuetifyjs/vuetify/issues/9130 */
65-
.v-card__text, .v-card__title {
66-
word-break: normal;
67-
}
118+
@use "sass:map";
119+
@import "~vuetify/src/styles/styles.sass";
68120
69121
.past-prod-list {
70-
white-space: nowrap;
71-
overflow-x: scroll;
122+
position: relative;
123+
@media(min-device-width: 500px) {
124+
white-space: nowrap;
125+
overflow-x: scroll;
126+
127+
-ms-overflow-style: none;
128+
&::-webkit-scrollbar {
129+
display: none;
130+
}
131+
132+
.past-prod-card {
133+
margin-right: 20px;
134+
}
135+
}
136+
137+
@media (max-device-width: 500px) {
138+
text-align: center;
139+
.past-prod-card {
140+
text-align: initial;
141+
margin-bottom: 20px;
142+
}
143+
.scroll-btn {
144+
display: none;
145+
}
146+
}
72147
.past-prod-card {
73148
display: inline-block;
74149
width: 300px;
75-
margin-right: 20px;
150+
margin-bottom: 20px;
76151
}
77152
78153
.prod-actions {
79154
float: right;
80155
}
81156
}
157+
.prod-card-text-wrapper {
158+
height: 150px;
159+
overflow: hidden;
160+
text-overflow: ellipsis;
161+
162+
&:before {
163+
content:'';
164+
width:100%;
165+
height: 12%;
166+
position:absolute;
167+
left:0;
168+
bottom: 78px;
169+
background:linear-gradient(transparent, map.get($grey, "darken-3"));
170+
}
171+
}
172+
.scroll-btn {
173+
opacity: 0.7;
174+
&:hover {
175+
opacity: 1;
176+
}
177+
position: absolute;
178+
z-index: 100;
179+
right: 20px;
180+
top: 50%;
181+
transform: translateY(-50%);
182+
}
82183
</style>

apps/glimpse-ui/components/TheHeader.vue

+13-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<VListItemSubtitle class="drawer-social">
1212
<a
1313
v-for="item in socials"
14+
v-if="!item.shouldDisplay || item.shouldDisplay()"
1415
:key="item.title"
1516
:href="item.path"
1617
:aria-label="item.title"
@@ -24,6 +25,7 @@
2425
<!-- Left menu items -->
2526
<VListItem
2627
v-for="item in leftMenuItems"
28+
v-if="!item.shouldDisplay || item.shouldDisplay()"
2729
:key="item.title"
2830
:to="item.path"
2931
class="drawer-item"
@@ -42,6 +44,7 @@
4244
<!-- Right menu items -->
4345
<VListItem
4446
v-for="item in rightMenuItems"
47+
v-if="!item.shouldDisplay || item.shouldDisplay()"
4548
:key="item.title"
4649
:to="item.path"
4750
class="drawer-item"
@@ -76,6 +79,7 @@
7679
<VToolbarItems class="hidden-xs-only">
7780
<VBtn
7881
v-for="item in leftMenuItems"
82+
v-if="!item.shouldDisplay || item.shouldDisplay()"
7983
:key="item.title"
8084
:to="item.path"
8185
:nuxt="true"
@@ -98,6 +102,7 @@
98102
<VList>
99103
<VListItem
100104
v-for="item in rightMenuItems"
105+
v-if="!item.shouldDisplay || item.shouldDisplay()"
101106
:key="item.title"
102107
@click=""
103108
:to="item.path"
@@ -113,6 +118,7 @@
113118
<VToolbarItems class="hidden-sm-and-down app-nav-right-items">
114119
<VBtn
115120
v-for="item in rightMenuItems"
121+
v-if="!item.shouldDisplay || item.shouldDisplay()"
116122
:key="item.title"
117123
:to="item.path"
118124
:nuxt="true"
@@ -147,8 +153,13 @@ export default {
147153
],
148154
rightMenuItems: [
149155
{ title: 'Join The Club', path: '/join', icon: 'hands-helping' },
150-
{ title: 'Donate', path: '/donate', icon: 'donate' },
151-
{ title: 'Login', path: '/login', icon: 'sign-in' }
156+
{ title: this.$store.state.rcs_id + '@rpi.edu',
157+
path: '#',
158+
icon: 'user-circle',
159+
shouldDisplay: () => this.$store.getters.isAuthenticated },
160+
{ title: 'Donate', path: '/donate', icon: 'donate', shouldDisplay: () => !this.$store.getters.isAuthenticated },
161+
{ title: 'Login', path: '/login', icon: 'sign-in', shouldDisplay: () => !this.$store.getters.isAuthenticated },
162+
{ title: 'Logout', path: '/logout', icon: 'sign-out', shouldDisplay: () => this.$store.getters.isAuthenticated }
152163
]
153164
}
154165
},

apps/glimpse-ui/components/VideoCard.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export default {
2424
query: gql`
2525
query getVideo($id: Int!) {
2626
video:getVideo(id: $id) {
27-
data
27+
# data
2828
id
2929
name
3030
videoType

apps/glimpse-ui/layouts/default.vue

+13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<template>
22
<VApp class="default-layout-app">
3+
<VSnackbar v-model="showFailedAuth" :timeout="5000" :bottom="true" color="error">
4+
Authentication failed! Try refreshing.
5+
</VSnackbar>
36
<div class="default-layout-custom-bg" />
47
<div>
58
<TheHeader />
@@ -21,6 +24,11 @@ export default {
2124
components: {
2225
TheHeader,
2326
TheFooter
27+
},
28+
computed: {
29+
showFailedAuth () {
30+
return this.$store.state.showFailedAuth
31+
}
2432
}
2533
}
2634
</script>
@@ -58,4 +66,9 @@ html {
5866
top: 0;
5967
left: 0;
6068
}
69+
70+
/* Fix word wrapping in cards - See vuetifyjs/vuetify/issues/9130 */
71+
.v-card__text, .v-card__title {
72+
word-break: normal;
73+
}
6174
</style>

apps/glimpse-ui/layouts/with-shape.vue

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<template>
22
<VApp class="default-layout-app">
3+
<VSnackbar v-model="showFailedAuth" :timeout="5000" :bottom="true" color="error">
4+
Authentication failed! Try refreshing.
5+
</VSnackbar>
36
<div class="default-layout-custom-bg" />
47
<div>
58
<Header transparent-at-top />
@@ -24,6 +27,11 @@ export default {
2427
BackgroundShape,
2528
Header,
2629
Footer
30+
},
31+
computed: {
32+
showFailedAuth () {
33+
return this.$store.state.showFailedAuth
34+
}
2735
}
2836
}
2937
</script>

apps/glimpse-ui/middleware/login.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default function ({ query, redirect }) {
2+
if (!query.ticket) {
3+
return redirect('https://cas-auth.rpi.edu/cas/login?service=' + encodeURIComponent(process.env.CAS_SERVICE_URL))
4+
}
5+
}

apps/glimpse-ui/nuxt.config.js

+11-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,17 @@ export default {
3131
]
3232
},
3333
serverMiddleware: [
34-
// Proxy static assets
35-
{ path: '/static', handler: createProxyMiddleware({ target: 'http://localhost:4000/' }) }
34+
// Proxy (non-graphql) API requests
35+
{ path: '/api',
36+
handler: createProxyMiddleware({
37+
target: 'http://localhost:4000/',
38+
pathRewrite: {
39+
'^/api': '/'
40+
}
41+
}) },
42+
// Proxy static assets w/o "/api" prefix
43+
{ path: '/static',
44+
handler: createProxyMiddleware({ target: 'http://localhost:4000/' }) }
3645
],
3746
/*
3847
** Customize the progress-bar color

0 commit comments

Comments
 (0)