Linting some ui components.

This commit is contained in:
2021-02-18 21:53:56 +01:00
parent 8bd41cc691
commit 6968ccf389
9 changed files with 122 additions and 158 deletions

View File

@@ -5,14 +5,14 @@
<img src="/public/assets/images/knowit.svg" alt="knowit logo" />
</router-link>
<a class="menu-toggle-container" aria-label="show-menu" @click="toggleMenu" :class="isOpen ? 'open' : 'collapsed'" >
<a class="menu-toggle-container" aria-label="show-menu" @click="toggleMenu" :class="isOpen ? 'open' : 'collapsed'">
<span class="menu-toggle"></span>
<span class="menu-toggle"></span>
<span class="menu-toggle"></span>
</a>
<nav class="menu" :class="isOpen ? 'open' : 'collapsed'" >
<router-link v-for="(route, index) in routes" :key="index" :to="route.route" class="menu-item-link" >
<nav class="menu" :class="isOpen ? 'open' : 'collapsed'">
<router-link v-for="(route, index) in routes" :key="index" :to="route.route" class="menu-item-link">
<a @click="toggleMenu" class="single-route" :class="isOpen ? 'open' : 'collapsed'">{{ route.name }}</a>
<i class="icon icon--arrow-right"></i>
</router-link>
@@ -21,8 +21,9 @@
<div class="clock">
<h2 v-if="!fiveMinutesLeft || !tenMinutesOver">
<span v-if="days > 0">{{ pad(days) }}:</span>
<span>{{ pad(hours) }}</span>:
<span>{{ pad(minutes) }}</span>:
<span>{{ pad(hours) }}</span
>: <span>{{ pad(minutes) }}</span
>:
<span>{{ pad(seconds) }}</span>
</h2>
<h2 v-if="twoMinutesLeft || tenMinutesOver">Lotteriet er i gang!</h2>
@@ -41,7 +42,7 @@ export default {
minutes: 0,
seconds: 0,
distance: 0,
interval: null,
interval: null
};
},
props: {
@@ -68,7 +69,7 @@ export default {
}
},
methods: {
toggleMenu(){
toggleMenu() {
this.isOpen = this.isOpen ? false : true;
},
pad: function(num) {
@@ -91,10 +92,7 @@ export default {
let nowDate = new Date();
let now = nowDate.getTime();
if (nextDayOfLottery.getTimezoneOffset() != nowDate.getTimezoneOffset()) {
let _diff =
(nextDayOfLottery.getTimezoneOffset() - nowDate.getTimezoneOffset()) *
60 *
-1;
let _diff = (nextDayOfLottery.getTimezoneOffset() - nowDate.getTimezoneOffset()) * 60 * -1;
nextDayOfLottery.setSeconds(nextDayOfLottery.getSeconds() + _diff);
}
this.nextLottery = nextDayOfLottery;
@@ -110,12 +108,8 @@ export default {
// Time calculations for days, hours, minutes and seconds
this.days = Math.floor(this.distance / (1000 * 60 * 60 * 24));
this.hours = Math.floor(
(this.distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
);
this.minutes = Math.floor(
(this.distance % (1000 * 60 * 60)) / (1000 * 60)
);
this.hours = Math.floor((this.distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
this.minutes = Math.floor((this.distance % (1000 * 60 * 60)) / (1000 * 60));
this.seconds = Math.floor((this.distance % (1000 * 60)) / 1000);
if (this.days == 7) {
this.days = 0;
@@ -124,7 +118,7 @@ export default {
this.initialize();
}
this.interval = setTimeout(this.countdown, 500);
},
}
}
};
</script>

View File

@@ -1,6 +1,9 @@
<template>
<div class="chat-container">
<span class="logged-in-username" v-if="username">Logget inn som: <span class="username">{{ username }}</span> <button @click="removeUsername">Logg ut</button></span>
<span class="logged-in-username" v-if="username"
>Logget inn som: <span class="username">{{ username }}</span>
<button @click="removeUsername">Logg ut</button></span
>
<div class="history" ref="history" v-if="chatHistory.length > 0">
<div class="opaque-skirt"></div>
@@ -8,7 +11,8 @@
<button @click="loadMoreHistory">Hent eldre meldinger</button>
</div>
<div class="history-message"
<div
class="history-message"
v-for="(history, index) in chatHistory"
:key="`${history.username}-${history.timestamp}-${index}`"
>
@@ -61,12 +65,11 @@ export default {
};
},
created() {
getChatHistory(1, this.pageSize)
.then(resp => {
this.chatHistory = resp.messages;
this.hasMorePages = resp.total != resp.messages.length;
});
const username = window.localStorage.getItem('username');
getChatHistory(1, this.pageSize).then(resp => {
this.chatHistory = resp.messages;
this.hasMorePages = resp.total != resp.messages.length;
});
const username = window.localStorage.getItem("username");
if (username) {
this.username = username;
this.emitUsernameOnConnect = true;
@@ -77,8 +80,7 @@ export default {
handler: function(newVal, oldVal) {
if (oldVal.length == 0) {
this.scrollToBottomOfHistory();
}
else if (newVal && newVal.length == oldVal.length) {
} else if (newVal && newVal.length == oldVal.length) {
if (this.isScrollPositionAtBottom()) {
this.scrollToBottomOfHistory();
}
@@ -105,10 +107,7 @@ export default {
});
this.socket.on("connect", msg => {
if (
this.emitUsernameOnConnect ||
(this.wasDisconnected && this.username != null)
) {
if (this.emitUsernameOnConnect || (this.wasDisconnected && this.username != null)) {
this.setUsername(this.username);
}
});
@@ -133,12 +132,11 @@ export default {
let { page, pageSize } = this;
page = page + 1;
getChatHistory(page, pageSize)
.then(resp => {
this.chatHistory = resp.messages.concat(this.chatHistory);
this.page = page;
this.hasMorePages = resp.total != this.chatHistory.length;
});
getChatHistory(page, pageSize).then(resp => {
this.chatHistory = resp.messages.concat(this.chatHistory);
this.page = page;
this.hasMorePages = resp.total != this.chatHistory.length;
});
},
pad(num) {
if (num > 9) return num;
@@ -146,9 +144,7 @@ export default {
},
getTime(timestamp) {
let date = new Date(timestamp);
const timeString = `${this.pad(date.getHours())}:${this.pad(
date.getMinutes()
)}:${this.pad(date.getSeconds())}`;
const timeString = `${this.pad(date.getHours())}:${this.pad(date.getMinutes())}:${this.pad(date.getSeconds())}`;
if (date.getDate() == new Date().getDate()) {
return timeString;
@@ -158,10 +154,10 @@ export default {
sendMessage() {
const message = { message: this.message };
this.socket.emit("chat", message);
this.message = '';
this.message = "";
this.scrollToBottomOfHistory();
},
setUsername(username=undefined) {
setUsername(username = undefined) {
if (this.temporaryUsername) {
username = this.temporaryUsername;
}
@@ -178,7 +174,7 @@ export default {
if (history) {
return history.offsetHeight + history.scrollTop >= history.scrollHeight;
}
return false
return false;
},
scrollToBottomOfHistory() {
setTimeout(() => {
@@ -189,15 +185,15 @@ export default {
scrollToMessageElement(message) {
const elemTimestamp = this.getTime(message.timestamp);
const self = this;
const getTimeStamp = (elem) => elem.getElementsByClassName('timestamp')[0].innerText;
const prevOldestMessageInNewList = (elem) => getTimeStamp(elem) == elemTimestamp;
const getTimeStamp = elem => elem.getElementsByClassName("timestamp")[0].innerText;
const prevOldestMessageInNewList = elem => getTimeStamp(elem) == elemTimestamp;
setTimeout(() => {
const { history } = self.$refs;
const childrenElements = Array.from(history.getElementsByClassName('history-message'));
const childrenElements = Array.from(history.getElementsByClassName("history-message"));
const elemInNewList = childrenElements.find(prevOldestMessageInNewList);
history.scrollTop = elemInNewList.offsetTop - 70
history.scrollTop = elemInNewList.offsetTop - 70;
}, 1);
}
}
@@ -210,7 +206,7 @@ export default {
.chat-container {
position: relative;
transform: translate3d(0,0,0);
transform: translate3d(0, 0, 0);
}
input {
@@ -241,7 +237,6 @@ input {
display: flex;
}
.history {
height: 75%;
overflow-y: scroll;
@@ -276,11 +271,7 @@ input {
position: fixed;
height: 2rem;
z-index: 1;
background: linear-gradient(
to bottom,
white,
rgba(255, 255, 255, 0)
);
background: linear-gradient(to bottom, white, rgba(255, 255, 255, 0));
}
& .fetch-older-history {
@@ -310,7 +301,7 @@ input {
border-radius: 4px;
&::before {
content: '';
content: "";
position: absolute;
top: 2.1rem;
left: 2rem;

View File

@@ -4,7 +4,7 @@
<div class="flex justify-end">
<div class="requested-count cursor-pointer" @click="request">
<span>{{ requestedElement.count }}</span>
<i class="icon icon--heart" :class="{ 'active': locallyRequested }" />
<i class="icon icon--heart" :class="{ active: locallyRequested }" />
</div>
</div>
</template>
@@ -17,10 +17,9 @@
<template v-slot:bottom>
<div class="float-left request">
<i class="icon icon--heart request-icon" :class="{ 'active': locallyRequested }"></i>
<a aria-role="button" tabindex="0" class="link" @click="request"
:class="{ 'active': locallyRequested }">
{{ locallyRequested ? 'Anbefalt' : 'Anbefal' }}
<i class="icon icon--heart request-icon" :class="{ active: locallyRequested }"></i>
<a aria-role="button" tabindex="0" class="link" @click="request" :class="{ active: locallyRequested }">
{{ locallyRequested ? "Anbefalt" : "Anbefal" }}
</a>
</div>
</template>
@@ -35,14 +34,14 @@ export default {
components: {
Wine
},
data(){
data() {
return {
wine: this.requestedElement.wine,
locallyRequested: false
}
};
},
props: {
requestedElement: {
requestedElement: {
required: true,
type: Object
},
@@ -53,27 +52,26 @@ export default {
}
},
methods: {
request(){
if (this.locallyRequested)
return
console.log("requesting", this.wine)
this.locallyRequested = true
this.requestedElement.count = this.requestedElement.count +1
requestNewWine(this.wine)
request() {
if (this.locallyRequested) return;
this.locallyRequested = true;
this.requestedElement.count = this.requestedElement.count + 1;
requestNewWine(this.wine);
},
async deleteWine() {
const wine = this.wine
const wine = this.wine;
if (window.confirm("Er du sikker på at du vil slette vinen?")) {
let response = await deleteRequestedWine(wine);
if (response['success'] == true) {
this.$emit('wineDeleted', wine);
if (response["success"] == true) {
this.$emit("wineDeleted", wine);
} else {
alert("Klarte ikke slette vinen");
}
}
},
},
}
}
}
};
</script>
<style lang="scss" scoped>
@@ -83,7 +81,7 @@ export default {
display: flex;
align-items: center;
margin-top: -0.5rem;
background-color: rgb(244,244,244);
background-color: rgb(244, 244, 244);
border-radius: 1.1rem;
padding: 0.25rem 1rem;
font-size: 1.25em;
@@ -93,14 +91,14 @@ export default {
line-height: 1.25em;
}
.icon--heart{
.icon--heart {
color: grey;
}
}
.active {
&.link {
border-color: $link-color
border-color: $link-color;
}
&.icon--heart {
@@ -121,4 +119,4 @@ export default {
margin-left: 0.5rem;
}
}
</style>
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div>
<div id="camera-stream">
<h2 v-if="errorMessage">{{ errorMessage }}</h2>
<video playsinline autoplay class="hidden"></video>
</div>
@@ -47,13 +47,8 @@ export default {
this.searchVideoForBarcode(this.video);
},
handleError(error) {
console.log(
"navigator.MediaDevices.getUserMedia error: ",
error.message,
error.name
);
this.errorMessage =
"Feil ved oppstart av kamera! Feilmelding: " + error.message;
console.log("navigator.MediaDevices.getUserMedia error: ", error.message, error.name);
this.errorMessage = "Feil ved oppstart av kamera! Feilmelding: " + error.message;
},
searchVideoForBarcode(video) {
const codeReader = new BrowserBarcodeReader();
@@ -84,10 +79,7 @@ export default {
this.errorMessage = "Feil! " + error.message || error;
},
scrollIntoView() {
window.scrollTo(
0,
document.getElementById("addwine-title").offsetTop - 10
);
window.scrollTo(0, document.getElementById("camera-stream").offsetTop - 10);
}
}
};
@@ -112,4 +104,4 @@ h2 {
text-align: center;
color: $red;
}
</style>
</style>

View File

@@ -2,10 +2,7 @@
<div class="wine">
<slot name="top"></slot>
<div class="wine-image">
<img
v-if="wine.image && loadImage"
:src="wine.image"
/>
<img v-if="wine.image && loadImage" :src="wine.image" />
<img v-else class="wine-placeholder" alt="Wine image" />
</div>
@@ -38,7 +35,7 @@ export default {
data() {
return {
loadImage: false
}
};
},
methods: {
setImage(entries) {
@@ -53,7 +50,7 @@ export default {
this.observer = new IntersectionObserver(this.setImage, {
root: this.$el,
threshold: 0
})
});
},
mounted() {
this.observer.observe(this.$el);
@@ -66,16 +63,17 @@ export default {
@import "@/styles/variables";
.wine {
align-self: flex-start;
padding: 1rem;
box-sizing: border-box;
position: relative;
-webkit-box-shadow: 0px 0px 10px 1px rgba(0, 0, 0, 0.15);
-moz-box-shadow: 0px 0px 10px 1px rgba(0, 0, 0, 0.15);
box-shadow: 0px 0px 10px 1px rgba(0, 0, 0, 0.15);
width: 100%;
@include tablet {
width: 250px;
height: 100%;
max-width: 280px;
}
}
@@ -85,19 +83,18 @@ export default {
margin-top: 10px;
img {
height: 250px;
height: 280px;
@include mobile {
object-fit: cover;
max-width: 90px;
}
}
.wine-placeholder {
height: 250px;
height: 280px;
width: 70px;
}
}
.wine-details {
display: flex;
flex-direction: column;
@@ -107,7 +104,7 @@ export default {
}
}
.wine-name{
.wine-name {
font-size: 20px;
margin: 1em 0;
}
@@ -120,6 +117,7 @@ export default {
.bottom-section {
width: 100%;
margin-top: 1rem;
align-self: flex-end;
.link {
color: $matte-text-color;
@@ -135,4 +133,4 @@ export default {
}
}
}
</style>
</style>

View File

@@ -85,9 +85,7 @@ export default {
this.startConfetti(this.currentName);
return;
}
this.currentName = this.attendees[
this.nameRounds % this.attendees.length
].name;
this.currentName = this.attendees[this.nameRounds % this.attendees.length].name;
this.nameRounds += 1;
clearTimeout(this.nameTimeout);
this.nameTimeout = setTimeout(() => {
@@ -136,8 +134,8 @@ export default {
//duration is computed as x * 1000 miliseconds, in this case 7*1000 = 7000 miliseconds ==> 7 seconds.
var duration = 7 * 1000;
var animationEnd = Date.now() + duration;
var defaults = { startVelocity: 50, spread: 160, ticks: 50, zIndex: 0, particleCount: 20};
var uberDefaults = { startVelocity: 65, spread: 75, zIndex: 0, particleCount: 35}
var defaults = { startVelocity: 50, spread: 160, ticks: 50, zIndex: 0, particleCount: 20 };
var uberDefaults = { startVelocity: 65, spread: 75, zIndex: 0, particleCount: 35 };
function randomInRange(min, max) {
return Math.random() * (max - min) + min;
@@ -148,27 +146,27 @@ export default {
var timeLeft = animationEnd - Date.now();
if (timeLeft <= 0) {
self.drawing = false;
console.time("drawing finished")
console.time("drawing finished");
return clearInterval(interval);
}
if (currentName == "Amund Brandsrud") {
runCannon(uberDefaults, {x: 1, y: 1 }, {angle: 135});
runCannon(uberDefaults, {x: 0, y: 1 }, {angle: 45});
runCannon(uberDefaults, {y: 1 }, {angle: 90});
runCannon(uberDefaults, {x: 0 }, {angle: 45});
runCannon(uberDefaults, {x: 1 }, {angle: 135});
runCannon(uberDefaults, { x: 1, y: 1 }, { angle: 135 });
runCannon(uberDefaults, { x: 0, y: 1 }, { angle: 45 });
runCannon(uberDefaults, { y: 1 }, { angle: 90 });
runCannon(uberDefaults, { x: 0 }, { angle: 45 });
runCannon(uberDefaults, { x: 1 }, { angle: 135 });
} else {
runCannon(defaults, {x: 0 }, {angle: 45});
runCannon(defaults, {x: 1 }, {angle: 135});
runCannon(defaults, {y: 1 }, {angle: 90});
runCannon(defaults, { x: 0 }, { angle: 45 });
runCannon(defaults, { x: 1 }, { angle: 135 });
runCannon(defaults, { y: 1 }, { angle: 90 });
}
}, 250);
function runCannon(confettiDefaultValues, originPoint, launchAngle){
confetti(Object.assign({}, confettiDefaultValues, {origin: originPoint }, launchAngle))
function runCannon(confettiDefaultValues, originPoint, launchAngle) {
confetti(Object.assign({}, confettiDefaultValues, { origin: originPoint }, launchAngle));
}
},
ordinalNumber(number=this.currentWinnerLocal.winnerCount) {
ordinalNumber(number = this.currentWinnerLocal.winnerCount) {
const dictonary = {
1: "første",
2: "andre",
@@ -187,7 +185,6 @@ export default {
}
}
};
</script>
<style lang="scss" scoped>

View File

@@ -1,9 +1,9 @@
<template>
<section>
<h2>{{ title ? title : 'Vinnere' }}</h2>
<h2>{{ title ? title : "Vinnere" }}</h2>
<div class="winning-raffles" v-if="winners.length > 0">
<div v-for="(winner, index) in winners" :key="index">
<router-link :to="`/highscore/${ encodeURIComponent(winner.name) }`">
<router-link :to="`/highscore/${winner.name}`">
<div :class="winner.color + '-raffle'" class="raffle-element">{{ winner.name }}</div>
</router-link>
</div>
@@ -26,7 +26,7 @@ export default {
type: Array
},
drawing: {
type: Boolean,
type: Boolean
},
title: {
type: String,

View File

@@ -1,17 +1,16 @@
const dateString = (date) => {
if (typeof(date) == "string") {
const dateString = date => {
if (typeof date == "string") {
date = new Date(date);
}
const ye = new Intl.DateTimeFormat('en', { year: 'numeric' }).format(date)
const mo = new Intl.DateTimeFormat('en', { month: '2-digit' }).format(date)
const da = new Intl.DateTimeFormat('en', { day: '2-digit' }).format(date)
const ye = new Intl.DateTimeFormat("en", { year: "numeric" }).format(date);
const mo = new Intl.DateTimeFormat("en", { month: "2-digit" }).format(date);
const da = new Intl.DateTimeFormat("en", { day: "2-digit" }).format(date);
return `${ye}-${mo}-${da}`
}
return `${ye}-${mo}-${da}`;
};
function humanReadableDate(date) {
const options = { year: 'numeric', month: 'long', day: 'numeric' };
const options = { year: "numeric", month: "long", day: "numeric" };
return new Date(date).toLocaleDateString(undefined, options);
}
@@ -20,8 +19,4 @@ function daysAgo(date) {
return Math.round(Math.abs((new Date() - new Date(date)) / day));
}
export {
dateString,
humanReadableDate,
daysAgo
}
export { dateString, humanReadableDate, daysAgo };

View File

@@ -12,34 +12,33 @@ const ENV = window.location.href.includes("localhost") ? "development" : "produc
if (ENV !== "development") {
Sentry.init({
dsn: "https://7debc951f0074fb68d7a76a1e3ace6fa@o364834.ingest.sentry.io/4905091",
integrations: [
new VueIntegration({ Vue })
],
integrations: [new VueIntegration({ Vue })],
beforeSend: event => {
console.error(event);
return event;
}
})
});
}
// Add global GA variables
window.ga = window.ga || function(){
window.ga.q = window.ga.q || [];
window.ga.q.push(arguments);
};
window.ga =
window.ga ||
function() {
window.ga.q = window.ga.q || [];
window.ga.q.push(arguments);
};
ga.l = 1 * new Date();
// Initiate
ga('create', __GA_TRACKINGID__, {
'allowAnchor': false,
'cookieExpires': __GA_COOKIELIFETIME__, // Time in seconds
'cookieFlags': 'SameSite=Strict; Secure'
ga("create", __GA_TRACKINGID__, {
allowAnchor: false,
cookieExpires: __GA_COOKIELIFETIME__, // Time in seconds
cookieFlags: "SameSite=Strict; Secure"
});
ga('set', 'anonymizeIp', true); // Enable IP Anonymization/IP masking
ga('send', 'pageview');
ga("set", "anonymizeIp", true); // Enable IP Anonymization/IP masking
ga("send", "pageview");
if (ENV == 'development')
window[`ga-disable-${__GA_TRACKINGID__}`] = true;
if (ENV == "development") window[`ga-disable-${__GA_TRACKINGID__}`] = true;
const router = new VueRouter({
routes: routes