Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move modal state controls to a shared mixin #131

Merged
merged 4 commits into from
Apr 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 5 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ If you spot anything out of date or incorrect, please [open an issue](https://gi
- [Dependencies](#dependencies)
- [npm Dependencies](#npm-dependencies)
- [Development](#development)
- [Project Overview](#project-overview)
- [TypeScript Guidelines](#typescript-guidelines)
- [Vue Guidelines](#vue-guidelines)
- [Documentation](#documentation)
Expand Down Expand Up @@ -64,14 +65,17 @@ When declaring dependencies in `package.json`, always use the [`~` operator](htt

## Development

[Visual Studio Code](https://code.visualstudio.com/) with extensions like [Veter](https://marketplace.visualstudio.com/items?itemName=octref.vetur) and [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) is recommended.
[Visual Studio Code](https://code.visualstudio.com/) with extensions like [Vetur](https://marketplace.visualstudio.com/items?itemName=octref.vetur) and [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) is recommended.

### Project Overview

This codebase is largely contained in [`src`](/src), where you will find the following directories:

* [`src/assets`](./src/assets): assets (images, etc.) that get bundled in the application - see [Handling Assets](#handling-assets) for more details
* [`src/components`](./src/components): Vue components that are shared throughout the website
* [`src/sections`](./src/sections): the website is mostly designed around horizontal sections that you scroll through - each section is defined as a Vue component here
* [`src/lib`](./src/lib): library of utility functions for Vue components
* [`src/mixins`](./src/mixins): Vue components can share logic through [Mixins](https://vuejs.org/v2/guide/mixins.html) - Mixins in use in this project are included here
* [`src/data`](./src/data): data type definitions for configuration used in the website - see [Configuration](#configuration) for more details
* [`src/styles`](./src/styles): global styles are declared here and imported throughout the application

Expand Down
17 changes: 2 additions & 15 deletions src/lib/util.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { Team } from '@/data/types';

/**
* Turns a single array into an array of arrays, each one representing a column.
*
Expand Down Expand Up @@ -118,9 +116,9 @@ export function getURLParams(location: Location): URLSearchParams {
}

/**
* Describes the state of a modal
* Describes the state of a TeamProjectModal
*/
export interface ModalState {
export interface TeamProjectModalState {
/**
* if the modal is open or closed
*/
Expand All @@ -130,14 +128,3 @@ export interface ModalState {
*/
activeTeamName: string;
}

/**
* Simple find function for teams
*
* @param teams set of teams to query
* @param name name of project to find
*/
export function getTeamByName(teams: Team[], name: string): Team | undefined {
return teams.find((team: Team) =>
team.project.name.toLowerCase() === name.toLowerCase());
}
49 changes: 49 additions & 0 deletions src/mixins/teamProjectModalController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Vue from 'vue';
import { Team } from '@/data/types';
import { TeamProjectModalState, getURLParams } from '@/lib/util';

/**
* This mixin provides a controller for handling TeamProjectModalState.
*
* See Projects.vue, Teams.vue for examples.
*/
export default Vue.extend({
props: {
teams: {
type: Array as () => Team[],
},
},
data: () => ({ isActive: false, activeTeamName: '0' }),
methods: {
getTeamByName(name: string): Team | undefined {
return this.teams.find((team: Team) =>
team.project.name.toLowerCase() === name.toLowerCase());
},
setModalState(state: TeamProjectModalState) {
this.isActive = state.isActive;
this.activeTeamName = state.activeTeamName;
},
closeModal() {
this.isActive = false;
},
},
computed: {
activeTeam(): Team | undefined {
return this.getTeamByName(this.activeTeamName);
},
},
created() {
// jump to linked project if one is provided, AND if the project exists
const linkedProject = getURLParams(window.location).get('project');
if (linkedProject && this.getTeamByName(linkedProject)) {
this.$gtag.event('direct-project-link', {
event_category: this.$options.name,
event_label: linkedProject,
});
this.setModalState({
isActive: true,
activeTeamName: linkedProject,
});
}
},
});
35 changes: 9 additions & 26 deletions src/sections/Projects.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
:section="$options.name"
:team="activeTeam"
:isActive="isActive"
@modalClosed="handleModalClose" />
@modalClosed="closeModal" />

<div class="description">
<h2>Past Projects</h2>
Expand Down Expand Up @@ -40,7 +40,9 @@
<script lang="ts">
import Vue from 'vue';
import { Team } from '@/data/types';
import { generateColumns, updateClassesIfInView, getURLParams, ModalState, getTeamByName } from '@/lib/util';
import { generateColumns, updateClassesIfInView } from '@/lib/util';

import teamProjectModalController from '@/mixins/teamProjectModalController';
import TeamProjectCard from '@/components/TeamProjectCard.vue';
import TeamProjectModal from '@/components/TeamProjectModal.vue';

Expand All @@ -49,19 +51,20 @@ import TeamProjectModal from '@/components/TeamProjectModal.vue';
*/
export default Vue.extend({
name: 'Projects',
mixins: [teamProjectModalController],
props: {
github: String,
teams: {
type: Array as () => Team[],
},
/**
* Link to UBC Launch Pad GitHub account
*/
github: String,
},
computed: {
columns(): Team[][] {
return generateColumns<Team>(this.teams, 2);
},
activeTeam(): Team | undefined {
return getTeamByName(this.teams, this.activeTeamName);
},
},
data: () => ({isActive: false, activeTeamName: '0'}),
methods: {
Expand All @@ -71,29 +74,9 @@ export default Vue.extend({
removeClasses: 'hidden',
});
},
setModalState(state: ModalState) {
this.isActive = state.isActive;
this.activeTeamName = state.activeTeamName;
},
handleModalClose() {
this.isActive = false;
},
},
created() {
window.addEventListener('scroll', this.handleScroll);

// jump to linked project if one is provided
const linkedProject = getURLParams(window.location).get('project');
if (linkedProject && getTeamByName(this.teams, linkedProject)) {
this.$gtag.event('direct-project-link', {
event_category: this.$options.name,
event_label: linkedProject,
});
this.setModalState({
isActive: true,
activeTeamName: linkedProject,
});
}
},
components: {
TeamProjectCard,
Expand Down
29 changes: 4 additions & 25 deletions src/sections/Teams.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
:section="$options.name"
:team="activeTeam"
:isActive="isActive"
@modalClosed="handleModalClose" />
@modalClosed="closeModal" />

<div class="columns is-vcentered is-desktop">
<div class="column is-two-fifths-desktop has-text-centered">
Expand Down Expand Up @@ -56,8 +56,9 @@
<script lang="ts">
import Vue from 'vue';
import { Team } from '@/data/types';
import { generateColumns, updateClassesIfInView, getURLParams, ModalState, getTeamByName } from '@/lib/util';
import { generateColumns, updateClassesIfInView } from '@/lib/util';

import teamProjectModalController from '@/mixins/teamProjectModalController';
import TeamProjectCard from '@/components/TeamProjectCard.vue';
import TeamProjectModal from '@/components/TeamProjectModal.vue';

Expand Down Expand Up @@ -86,6 +87,7 @@ const stats: TeamStats[] = [
*/
export default Vue.extend({
name: 'Teams',
mixins: [teamProjectModalController],
props: {
teams: {
type: Array as () => Team[],
Expand All @@ -99,9 +101,6 @@ export default Vue.extend({
const perColumn = Math.ceil(this.teams.length / perRow);
return generateColumns<Team>(this.teams, perColumn);
},
activeTeam(): Team | undefined {
return getTeamByName(this.teams, this.activeTeamName);
},
},
methods: {
handleScroll() {
Expand All @@ -110,29 +109,9 @@ export default Vue.extend({
removeClasses: 'hidden',
});
},
setModalState(state: ModalState) {
this.isActive = state.isActive;
this.activeTeamName = state.activeTeamName;
},
handleModalClose() {
this.isActive = false;
},
},
created() {
window.addEventListener('scroll', this.handleScroll);

// jump to linked project if one is provided
const linkedProject = getURLParams(window.location).get('project');
if (linkedProject && getTeamByName(this.teams, linkedProject)) {
this.$gtag.event('direct-project-link', {
event_category: this.$options.name,
event_label: linkedProject,
});
this.setModalState({
isActive: true,
activeTeamName: linkedProject,
});
}
},
components: {
TeamProjectCard,
Expand Down