Add Splatfest info for NA

This commit is contained in:
Matt Isenhower
2017-08-05 16:21:19 -07:00
parent c4c68c3240
commit 2404ba73d5
14 changed files with 299 additions and 10 deletions

View File

@@ -32,6 +32,7 @@
"purifycss-webpack": "^0.7.0",
"sass-loader": "^6.0.6",
"style-loader": "^0.18.2",
"v-click-outside": "^0.0.8",
"vue": "^2.4.2",
"vue-loader": "^13.0.2",
"vue-template-compiler": "^2.4.2",

View File

@@ -6,6 +6,7 @@ $bg-spots: url(../img/bg-spots.png);
$bg-mask-product: url(../img/bg-mask-product.png);
$bg-mask-title-squid: url(../img/bg-mask-title-squid.png);
$bg-mask-hook: url(../img/bg-mask-hook.png);
$bg-mask-banner: url(../img/bg-mask-banner.png);
// Colors
$bg-battle-regular: #19d719;
@@ -64,3 +65,14 @@ $bg-battle-league: #f02d7d;
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
}
.bg-mask-banner {
-webkit-mask-image: $bg-mask-banner;
mask-image: $bg-mask-banner;
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
-webkit-mask-position: center;
mask-position: center;
}

View File

@@ -38,7 +38,7 @@
}
}
.button.is-clear {
.button.is-translucent {
@extend .text-shadow;
background: rgba($white-ter, 0.4);
@@ -52,12 +52,57 @@
}
}
.button.is-clear {
@extend .text-shadow;
background: transparent;
border: rgba($white-ter, 0.9);
color: $grey-lighter;
&:hover {
background: rgba($white, 0.2);
border: rgba($white, 1.0);
color: $white;
}
}
.button.is-rounded {
border-radius: 100px;
padding-left: 12px;
padding-right: 12px;
}
.chevron::before {
border-style: solid;
border-width: 0.1em 0.1em 0 0;
content: '';
display: inline-block;
height: 0.45em;
left: 0.15em;
position: relative;
top: 0.15em;
transform: rotate(-45deg);
vertical-align: top;
width: 0.45em;
}
.chevron.right:before {
left: 0;
transform: rotate(45deg);
}
.chevron.bottom:before {
// top: 0;
top: 0.45em;
left: 0;
transform: rotate(135deg);
}
.chevron.left:before {
left: 0.1em;
transform: rotate(-135deg);
}
.hand {
cursor: pointer;
}

View File

@@ -1,5 +1,8 @@
@import '~bulma/sass/utilities/initial-variables';
$background: $black-ter;
$body-background-color: #191919;
$text: $grey-lighter;
$text-strong: $white-ter;
$title-color: $white-ter;
@@ -9,3 +12,8 @@ $purple: #460fc8;
// Temp: This can be removed after Bulma 0.5.1
$sizes: $size-1 $size-2 $size-3 $size-4 $size-5 $size-6 $size-7;
$dropdown-content-background-color: rgba($grey-dark, 0.9);
$dropdown-item-color: $grey-lighter;
$dropdown-item-hover-color: $white;
$dropdown-item-active-background-color: $orange;

View File

@@ -7,7 +7,6 @@
html {
@extend .bg-squids;
background-color: #191919;
}
.fa {
@@ -46,6 +45,13 @@ html {
padding: 35px 10px 10px 10px;
margin: auto;
&.splatfest-schedule-box {
// Provide a little more room for the third Splatfest stage
max-width: 720px;
-webkit-mask-size: 730px 1168px;
mask-size: 730px 1168px;
}
&.regular {
background-color: $bg-battle-regular;
}
@@ -123,6 +129,56 @@ html {
}
}
.splatfest {
@extend .text-shadow;
max-width: 500px;
margin: auto;
.hook-box, .hook-box:before {
background-color: #888;
@extend .bg-stripes;
padding-left: 0;
padding-right: 0;
padding-bottom: 0;
}
.splatfest-header, .splatfest-content {
padding: 5px 15px 10px;
}
.panel-container {
position: relative;
.alpha, .bravo {
@extend .font-splatoon1;
@extend .title-color;
@extend .is-size-5;
position: absolute;
bottom: 0.25rem;
}
.alpha {
left: 0.25rem;
}
.bravo {
right: 0.25rem;
}
}
.festival-period-container {
margin-bottom: 10px;
}
.festival-period {
@extend .bg-mask-banner;
@extend .bg-stripes;
background-size: 53px 53px;
padding: 4px 20px;
}
}
.main-schedule {
background: rgba(0,0,0,0.7);
padding: 5px 10px 10px;

BIN
src/img/bg-mask-banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 567 B

View File

@@ -2,7 +2,7 @@
<div class="hero is-fullheight">
<div class="hero-head">
<div class="container is-fluid">
<div class="level">
<div class="level is-marginless">
<div class="level-left">
<div class="level-item">
<h1 class="title is-1 font-splatoon1 is-inline">Splatoon 2</h1>
@@ -14,6 +14,15 @@
</div>
</div>
</div>
<div class="level">
<div class="level-left"></div>
<div class="level-right">
<div class="level-item">
<Dropdown :options="regions" v-model="selectedRegionKey" style="margin: 0 -12px"></Dropdown>
</div>
</div>
</div>
</div>
</div>
@@ -24,8 +33,21 @@
<span class="fa fa-spin squid-refresh"></span>
</span>
</div>
<div v-else>
<div class="columns is-desktop">
<div v-if="isFestivalActive" class="columns is-desktop" style="max-width: 1392px; margin: auto">
<div class="column">
<div class="splatfest tilt-left">
<div class="hook-box">
<SplatfestBox :festival="festival" :now="now"></SplatfestBox>
</div>
</div>
</div>
<div class="column">
<ScheduleBox class="main-schedule-box splatfest-schedule-box tilt-right" cssClass="regular" :schedules="regular" :festival="festival" :now="now"></ScheduleBox>
</div>
</div>
<div v-else class="columns is-desktop">
<div class="column">
<ScheduleBox class="main-schedule-box tilt-left" cssClass="regular" :schedules="regular" :now="now"></ScheduleBox>
</div>
@@ -59,17 +81,27 @@
<script>
import axios from 'axios';
import Dropdown from './Dropdown.vue';
import ScheduleBox from './ScheduleBox.vue';
import SalmonRunBox from './SalmonRunBox.vue';
import SplatfestBox from './SplatfestBox.vue';
export default {
components: { ScheduleBox, SalmonRunBox },
components: { Dropdown, ScheduleBox, SalmonRunBox, SplatfestBox },
data() {
return {
regions: [
{ key: null, name: 'Global' },
{ key: 'na', name: 'North America' },
],
selectedRegionKey: null,
now: null,
splatnet: {
schedules: null,
timeline: null,
festivals: {
na: null,
},
},
};
},
@@ -78,6 +110,16 @@ export default {
regular() { return !this.loading && this.splatnet.schedules.regular.filter(this.filterSchedule) },
ranked() { return !this.loading && this.splatnet.schedules.gachi.filter(this.filterSchedule) },
league() { return !this.loading && this.splatnet.schedules.league.filter(this.filterSchedule) },
festival() {
if (this.loading || !this.selectedRegionKey)
return;
let festivals = this.splatnet.festivals[this.selectedRegionKey];
return festivals && festivals.festivals && festivals.festivals[0];
},
isFestivalActive() {
return this.festival && this.festival.times.start <= this.now && this.festival.times.end > this.now;
},
coop() {
if (!this.loading && this.splatnet.timeline.coop && this.splatnet.timeline.coop.schedule.end_time >= this.now)
return this.splatnet.timeline.coop;
@@ -97,6 +139,7 @@ export default {
updateData() {
axios.get('/data/schedules.json').then(response => this.splatnet.schedules = response.data);
axios.get('/data/timeline.json').then(response => this.splatnet.timeline = response.data);
axios.get('/data/festivals-na.json').then(response => this.splatnet.festivals.na = response.data);
},
updateNow() {
this.now = Math.trunc((new Date).getTime() / 1000);

View File

@@ -0,0 +1,41 @@
<template>
<div class="dropdown is-right font-splatoon2" :class="{ 'is-active': isOpen }">
<div class="dropdown-trigger">
<button class="button is-clear font-splatoon2" @click="isOpen = !isOpen" v-click-outside="hide">
<span v-if="selectedOption">{{ selectedOption.name }}</span>
<span class="icon is-small">
<span class="chevron bottom"></span>
</span>
</button>
</div>
<div class="dropdown-menu" role="menu">
<div class="dropdown-content">
<a href="#" class="dropdown-item" v-for="option in options" :class="{ 'is-active': option.key == value }" @click="$emit('input', option.key)">
{{ option.name }}
</a>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['options', 'value'],
data() {
return {
isOpen: false,
};
},
computed: {
selectedOption() {
if (this.options)
return this.options.find(option => option.key == this.value);
},
},
methods: {
hide() {
this.isOpen = false;
},
},
}
</script>

View File

@@ -10,7 +10,8 @@
</div>
<div class="level-item">
<h2 class="title is-3 is-size-2-fullhd is-size-4-mobile font-splatoon1">
{{ gameMode.name }}
<template v-if="isFestival">Splatfest Battle</template>
<template v-else>{{ gameMode.name }}</template>
</h2>
</div>
</div>
@@ -19,6 +20,11 @@
<script>
export default {
props: ['gameMode'],
props: ['gameMode', 'festival', 'now'],
computed: {
isFestival() {
return this.festival && this.festival.times.start <= this.now && this.festival.times.end > this.now;
},
},
}
</script>

View File

@@ -1,6 +1,6 @@
<template>
<div class="font-splatoon2" :class="cssClass" v-if="gameMode">
<GameModeHeader :gameMode="gameMode"></GameModeHeader>
<GameModeHeader :gameMode="gameMode" :festival="festival" :now="now"></GameModeHeader>
<div class="main-schedule" v-if="currentSchedule">
<div class="level is-mobile top-bar">
@@ -18,13 +18,16 @@
<div class="columns is-mobile is-slim">
<div class="column"><Stage :stage="currentSchedule.stage_a"></Stage></div>
<div class="column"><Stage :stage="currentSchedule.stage_b"></Stage></div>
<template v-if="festival">
<div class="column"><Stage :stage="festival.special_stage"></Stage></div>
</template>
</div>
</div>
<ScheduleList :schedules="upcomingSchedules" :now="now" :onlyFirst="true"></ScheduleList>
<p class="has-text-centered" style="margin-top: 10px">
<button class="button is-clear is-rounded" @click="isOpen=true">
<button class="button is-translucent is-rounded" @click="isOpen=true">
<span class="icon squid-icon-tilt">
<span class="fa squid-squid"></span>
</span>
@@ -55,7 +58,7 @@ import ScheduleList from './ScheduleList.vue';
export default {
components: { GameModeHeader, Stage, ScheduleList },
props: ['schedules', 'cssClass', 'now'],
props: ['schedules', 'cssClass', 'festival', 'now'],
data() {
return {
isOpen: false,

View File

@@ -0,0 +1,54 @@
<template>
<div class="font-splatoon2">
<div class="splatfest-header">
<h2 class="title is-3 is-size-2-fullhd font-splatoon1">
Splatfest
</h2>
</div>
<div class="panel-container">
<div class="image">
<img :src="image" />
</div>
<div class="alpha">
{{ festival.names.alpha_short }}
</div>
<div class="bravo">
{{ festival.names.bravo_short }}
</div>
</div>
<div class="has-text-centered is-size-5 title-color festival-period-container">
<span class="festival-period" :style="{ 'background-color': festival.colors.middle.css_rgb }">
{{ festival.times.start | date }}
{{ festival.times.start | time }}
&ndash;
{{ festival.times.end | date }}
{{ festival.times.end | time }}
</span>
</div>
<div class="splatfest-content has-text-centered">
<template v-if="festival.times.start <= now">
{{ festival.times.end - now | duration }}
remaining
</template>
<template v-else>
in
{{ festival.times.start - now | duration }}
</template>
</div>
</div>
</template>
<script>
export default {
props: ['festival', 'now'],
computed: {
image() {
if (this.festival)
return `https://app.splatoon2.nintendo.net${this.festival.images.panel}`;
}
}
}
</script>

View File

@@ -1,5 +1,8 @@
import Vue from 'vue';
import App from './components/App.vue';
import vClickOutside from 'v-click-outside';
Vue.use(vClickOutside);
Vue.directive('portal', {
inserted(el) {

View File

@@ -42,7 +42,20 @@ const updateTimeline = function() {
});
}
const updateFestivals = function() {
console.info('Updating festivals...');
api.get('festivals/active').then(response => {
// Make sure the data path exists
mkdirp(dataPath);
fs.writeFile(`${dataPath}/festivals-na.json`, JSON.stringify(response.data));
console.info('Updated festivals.');
});
}
module.exports.update = function() {
updateSchedules();
updateTimeline();
updateFestivals();
}

View File

@@ -5366,6 +5366,10 @@ uuid@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"
v-click-outside@^0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/v-click-outside/-/v-click-outside-0.0.8.tgz#1f3033b8c4ace431c3233a4080127fc088d52093"
validate-npm-package-license@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"