Skip to content
This repository has been archived by the owner on Apr 3, 2024. It is now read-only.

Add Production View #50

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
aae9239
Add start of the individual production view
robere2 Nov 23, 2022
d970006
Add props to ProductionView subcomponents
robere2 Nov 23, 2022
8161e2a
Add styling to ProductionView.vue, fix base font not being used
robere2 Nov 24, 2022
33c7a30
Add 16:9 aspect ratio player
robere2 Nov 24, 2022
66cc72a
Mostly finished tags component
SuperUltraMegaChicken Nov 25, 2022
ca029bd
Start work on video/image carousel
robere2 Nov 30, 2022
e4555a5
Merge branch 'fix-issue-45' of github.com:rpitv/glimpse-ui into fix-i…
robere2 Nov 30, 2022
78222b0
Carousel component fixed
SuperUltraMegaChicken Dec 1, 2022
70aa759
Add basic image/video display with real data to production page
robere2 Dec 22, 2022
48eb4a3
Hide arrows when only one media item is available on productions page…
robere2 Dec 22, 2022
7d4394c
Add error message for unsupported video types (todo)
robere2 Dec 22, 2022
aaa988e
Update carousel buttons to use fontawesome icons
robere2 Dec 22, 2022
7b89d50
remove unused left class
robere2 Dec 22, 2022
a211c08
Add fetching real credit data to Production page
robere2 Dec 22, 2022
714bc02
Add loading spinner when production data is still being fetched
robere2 Dec 22, 2022
bd2c50a
Added check for empty tags, added credits component
SuperUltraMegaChicken Dec 23, 2022
43dbc94
Update credits to be sorted and remove profile picture (for now)
robere2 Dec 31, 2022
7a653f2
Hide tags dropdown when no tags are set on a Production
robere2 Dec 31, 2022
0c7d1c3
Hide credits when no credits are listed. Remove redundant hidden tags…
robere2 Dec 31, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/assets/base.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import url("https://fonts.googleapis.com/css?family=Ubuntu:wght@300;400|Oswald:wght@200;300;400&display=swap");
@import url('https://fonts.googleapis.com/css2?family=Bitter:ital,wght@0,400;0,500;0,700;1,400;1,700;1,500&family=Oswald:wght@300;400&display=swap');

h1,
h2,
Expand All @@ -10,14 +10,17 @@ nav {
font-family: "Oswald", sans-serif;
}

html {
font-family: "Ubuntu", sans-serif;
body {
font-family: "Bitter", serif !important;
font-size: 16px;
word-spacing: 1px;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
}

html {
box-sizing: border-box;
}

Expand Down
110 changes: 110 additions & 0 deletions src/components/production/ProductionCarousel.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<template>
<div v-if="items.length > 0">
<n-carousel ref="carousel" class="aspect-ratio">
<div v-for="item of items" class="carousel-contents extend-height">
<div v-if="item.__typename === 'Image'">
<img :src="item.path" :alt="item.name" />
</div>
<div v-else class="extend-height">
<iframe v-if="item.format === 'EMBED'" class="videoplayer" :src="item.metadata.url" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<div v-else class="unsupported-format">
<p>Sorry, videos in this format currently cannot be played.</p>
<p>Contact us to download a copy of this video.</p>
</div>
</div>
</div>
</n-carousel>
<n-space justify="space-between" v-if="items.length > 1">
<n-button text class="carousel-btns" @click="prev">
<FontAwesomeIcon icon="fas fa-arrow-left" />
</n-button>
<n-button text class="carousel-btns" @click="next">
<FontAwesomeIcon icon="fas fa-arrow-right" />
</n-button>
</n-space>
</div>
<div v-else>
<p class="no-media">No images or videos available.</p>
</div>
</template>

<script setup lang="ts">
import type {Image, Video} from "@/graphql/types";
import type {PropType} from "vue";
import {ref, watchEffect} from "vue";
import {NCarousel, NSpace, NButton} from "naive-ui";
import {FontAwesomeIcon} from "@fortawesome/vue-fontawesome";

const props = defineProps({
items: {
type: Array as PropType<
(
Pick<Video, "__typename" | "name" | "format" | "metadata"> |
Pick<Image, "__typename" | "name" | "description" | "path">
)[]>,
required: true
}
});

watchEffect(() => {
console.log(props.items);
})

const carousel = ref<InstanceType<typeof NCarousel> | null>(null);

// Components don't load in fast enough for refs so we need to use functions instead of just calling their methods
function prev() {
carousel.value?.prev();
}

function next() {
carousel.value?.next();
}
</script>

<style scoped lang="scss">
.aspect-ratio {
position: relative;
aspect-ratio: 16 / 9;
background-color: black;
height: 100%;
width: 100%;
}

img {
aspect-ratio: 16 / 9;
height: 100%;
width: 100%;
}
.videoplayer {
aspect-ratio: 16 / 9;
height: 100%;
width: 100%;
}

.carousel-btns {
margin-top: 5px;
font-size: 28px;
}

.no-media {
text-align: center;
font-style: italic;
}

.unsupported-format {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
text-align: center;
font-style: italic;
}

.extend-height {
position: relative;
height: 100%;
}

</style>
62 changes: 62 additions & 0 deletions src/components/production/ProductionCredits.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<template>
<div v-if="sortedCredits.length > 0">
<h3>Credits</h3>
<n-grid :cols="3">
<n-grid-item v-for="credit in sortedCredits" :key="credit.id" class="col">
<span class="no-display-at-1250">&ensp; </span>
<span class="name">&nbsp;{{ credit.person.name }}</span>
<span class="no-display-at-1250"> - </span>
<span class="title">{{ credit.title }}</span>
</n-grid-item>
</n-grid>
</div>
</template>

<script setup lang="ts">
import type {PropType} from "vue";
import type {Credit} from "@/graphql/types";
import {NGrid, NGridItem} from "naive-ui";
import {computed} from "vue";

const props = defineProps({
credits: {
type: Array as PropType<Pick<Credit, "__typename" | "title" | "priority" | "person" | "id">[]>,
required: true
}
});

const sortedCredits = computed(() => {
return [...props.credits].sort((a, b) => b.priority - a.priority);
});

</script>

<style scoped lang="scss">

.profile-icon {
border-radius: 50%;
display: inline;
vertical-align: middle;
}

.name {
font-weight: bold;
}

.col {
padding: 5px;
}

@media screen and (max-width: 1250px) {
.col {
text-align: center;
}
.name {
display: block;
}
.no-display-at-1250 {
display: none;
}
}

</style>
48 changes: 48 additions & 0 deletions src/components/production/ProductionTags.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<template>
<NButton text @click="show = !show" style="font-size: 16px; font-family: 'Oswald', sans-serif;">
<span :class="{show: show, notShow: !show}" style="font-size: 12px">&#xfe40;</span>&nbsp;Tags
</NButton>
<hr class="divider">
<NCollapseTransition :show="show">
<NSpace>
<NButton v-for="tag in props.tags" :key="tag" color="#426779" style="color: #68b0d4" size="tiny">
{{ tag }}
</NButton>
</NSpace>
</NCollapseTransition>
</template>

<script setup lang="ts">

import type {PropType} from "vue";
import {ref} from "vue";
import {NCollapseTransition, NButton, NSpace} from "naive-ui"

const show = ref<boolean>(false);


const props = defineProps({
tags: {
type: Array as PropType<string[]>,
required: true
}
})
</script>

<style scoped lang="scss">
.divider {
border-top: 2px;
}

.notShow {
font-weight: bold;
transition-duration: 0.25s;
transform: rotate(-90deg);
}

.show {
font-weight: bold;
transition-duration: 0.25s;
transform: rotate(0deg);
}
</style>
36 changes: 36 additions & 0 deletions src/graphql/ReadProduction.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
query ReadProduction($id: ID!) {
ReadProduction: findOneProduction(id: $id) {
name
description
startTime
credits {
id
person {
id
name
}
title
priority
}
category {
name
}
images {
image {
id
description
path
}
}
videos {
video {
name
format
metadata
}
}
tags {
tag
}
}
}
9 changes: 9 additions & 0 deletions src/graphql/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,7 @@ export type Production = {
category?: Maybe<Category>;
closetLocation?: Maybe<Scalars['String']>;
closetTime?: Maybe<Scalars['DateTime']>;
credits?: Maybe<Array<Credit>>;
description?: Maybe<Scalars['String']>;
discordChannel?: Maybe<Scalars['String']>;
discordServer?: Maybe<Scalars['String']>;
Expand Down Expand Up @@ -1717,6 +1718,13 @@ export type PermissionsForQueryVariables = Exact<{

export type PermissionsForQuery = { __typename?: 'Query', permissions: Array<{ __typename?: 'GroupPermission', action: string, subject: Array<string>, fields?: Array<string> | null, conditions?: any | null, inverted: boolean, reason?: string | null } | { __typename?: 'UserPermission', action: string, subject: Array<string>, fields?: Array<string> | null, conditions?: any | null, inverted: boolean, reason?: string | null }> };

export type ReadProductionQueryVariables = Exact<{
id: Scalars['ID'];
}>;


export type ReadProductionQuery = { __typename?: 'Query', ReadProduction?: { __typename?: 'Production', name: string, description?: string | null, startTime?: any | null, credits?: Array<{ __typename?: 'Credit', id: string, title?: string | null, priority: number, person: { __typename?: 'Person', id: string, name: string } }> | null, category?: { __typename?: 'Category', name?: string | null } | null, images?: Array<{ __typename?: 'ProductionImage', image: { __typename?: 'Image', id: string, description?: string | null, path: string } }> | null, videos?: Array<{ __typename?: 'ProductionVideo', video: { __typename?: 'Video', name: string, format: VideoFormat, metadata?: any | null } }> | null, tags?: Array<{ __typename?: 'ProductionTag', tag: string }> | null } | null };

export type SelfIdQueryVariables = Exact<{ [key: string]: never; }>;


Expand Down Expand Up @@ -1750,6 +1758,7 @@ export const FindAllProductionsDocument = {"kind":"Document","definitions":[{"ki
export const ListStreamsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ListStreams"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"streams"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"to"}},{"kind":"Field","name":{"kind":"Name","value":"from"}},{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]} as unknown as DocumentNode<ListStreamsQuery, ListStreamsQueryVariables>;
export const LogoutDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"Logout"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"logoutSuccess"},"name":{"kind":"Name","value":"logout"}}]}}]} as unknown as DocumentNode<LogoutMutation, LogoutMutationVariables>;
export const PermissionsForDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"PermissionsFor"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"user"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"permissions"},"name":{"kind":"Name","value":"permissionsFor"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"user"},"value":{"kind":"Variable","name":{"kind":"Name","value":"user"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"GroupPermission"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"action"}},{"kind":"Field","name":{"kind":"Name","value":"subject"}},{"kind":"Field","name":{"kind":"Name","value":"fields"}},{"kind":"Field","name":{"kind":"Name","value":"conditions"}},{"kind":"Field","name":{"kind":"Name","value":"inverted"}},{"kind":"Field","name":{"kind":"Name","value":"reason"}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"UserPermission"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"action"}},{"kind":"Field","name":{"kind":"Name","value":"subject"}},{"kind":"Field","name":{"kind":"Name","value":"fields"}},{"kind":"Field","name":{"kind":"Name","value":"conditions"}},{"kind":"Field","name":{"kind":"Name","value":"inverted"}},{"kind":"Field","name":{"kind":"Name","value":"reason"}}]}}]}}]}}]} as unknown as DocumentNode<PermissionsForQuery, PermissionsForQueryVariables>;
export const ReadProductionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ReadProduction"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"ReadProduction"},"name":{"kind":"Name","value":"findOneProduction"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"startTime"}},{"kind":"Field","name":{"kind":"Name","value":"credits"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"person"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"priority"}}]}},{"kind":"Field","name":{"kind":"Name","value":"category"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"images"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"image"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"path"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"videos"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"video"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"format"}},{"kind":"Field","name":{"kind":"Name","value":"metadata"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"tags"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"tag"}}]}}]}}]}}]} as unknown as DocumentNode<ReadProductionQuery, ReadProductionQueryVariables>;
export const SelfIdDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"SelfId"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"self"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode<SelfIdQuery, SelfIdQueryVariables>;
export const StartStreamDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"StartStream"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"to"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"from"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"success"},"name":{"kind":"Name","value":"createStream"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"to"},"value":{"kind":"Variable","name":{"kind":"Name","value":"to"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"from"},"value":{"kind":"Variable","name":{"kind":"Name","value":"from"}}}]}}]}]}}]} as unknown as DocumentNode<StartStreamMutation, StartStreamMutationVariables>;
export const StopStreamDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"StopStream"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"success"},"name":{"kind":"Name","value":"deleteStream"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}]}]}}]} as unknown as DocumentNode<StopStreamMutation, StopStreamMutationVariables>;
Expand Down
8 changes: 7 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import { createApolloProvider } from "@vue/apollo-option";
import { DefaultApolloClient } from "@vue/apollo-composable";

import { library } from "@fortawesome/fontawesome-svg-core";
import { faCaretDown } from "@fortawesome/pro-solid-svg-icons";
import {
faCaretDown,
faArrowLeft,
faArrowRight,
} from "@fortawesome/pro-solid-svg-icons";
import {
faCircleInfo,
faHome,
Expand Down Expand Up @@ -50,6 +54,8 @@ import {
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";

library.add(faCaretDown);
library.add(faArrowLeft);
library.add(faArrowRight);

library.add(faHome);
library.add(faCircleInfo);
Expand Down
11 changes: 8 additions & 3 deletions src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { createRouter, createWebHistory } from "vue-router";
import HomeView from "../views/HomeView.vue";
import AboutView from "../views/AboutView.vue";
import ProductionsView from "../views/ProductionsView.vue";
import ProductionView from "../views/ProductionView.vue";
import ContactView from "../views/ContactView.vue";
import LoginView from "../views/LoginView.vue";
import DonateView from "../views/DonateView.vue";
Expand Down Expand Up @@ -124,9 +125,13 @@ const router = createRouter({
},
},
{
path: "/productions",
name: "productions",
component: ProductionsView,
path: "/productions/:id",
name: "production",
component: restrictedComponent(
ProductionView,
AbilityActions.Read,
AbilitySubjects.Production
),
meta: {
layoutCssName: "plain-layout",
},
Expand Down
9 changes: 9 additions & 0 deletions src/util/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export function shouldOpenInNewTab(e: MouseEvent): boolean {
* NavigationHeaderButton, and I am not aware of any way to make Vue templates refer to themselves in their
* script.
* @param child
* @param currentDepth
*/
export function computeNavDropdownChildElement(
child: NavButton,
Expand All @@ -63,3 +64,11 @@ export function computeNavDropdownChildElement(
}

export type FontAwesomeIconWeights = "fas" | "fal" | "fad" | "fab";

export type DeepPartial<T> = {
[P in keyof T]?: T[P] extends (infer U)[]
? DeepPartial<U>[]
: T[P] extends boolean | string | number
? T[P]
: DeepPartial<T[P]>;
};
Loading