mirror of
https://github.com/KevinMidboe/zoff.git
synced 2026-02-11 03:49:42 +00:00
Compare commits
14 Commits
dependabot
...
vue-setup
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0501a7ebbb | ||
|
|
4aa216947a | ||
|
|
53a9b83f6b | ||
|
|
a06f965163 | ||
| f90cf2132b | |||
| 3680d9ba43 | |||
| cb0d3633ac | |||
| 178f21e6c8 | |||
| 6b40947302 | |||
| 6caef24fd8 | |||
| a604e9de8f | |||
| 1e8770a226 | |||
| b32710b4d3 | |||
|
|
ce7ac96a5d |
3
config/env/dev.env.js
vendored
Normal file
3
config/env/dev.env.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
NODE_ENV: "development"
|
||||||
|
};
|
||||||
3
config/env/prod.env.js
vendored
Normal file
3
config/env/prod.env.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
NODE_ENV: "production"
|
||||||
|
};
|
||||||
3
config/env/staging.env.js
vendored
Normal file
3
config/env/staging.env.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
NODE_ENV: "staging"
|
||||||
|
};
|
||||||
15
config/helpers.js
Normal file
15
config/helpers.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
const _root = path.resolve(__dirname, "..");
|
||||||
|
|
||||||
|
exports.root = function(args) {
|
||||||
|
args = Array.prototype.slice.call(arguments, 0);
|
||||||
|
|
||||||
|
return path.join.apply(path, [_root].concat(args));
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.assetsPath = function(_path) {
|
||||||
|
return path.posix.join("static", _path);
|
||||||
|
};
|
||||||
61
config/webpack.config.common.js
Normal file
61
config/webpack.config.common.js
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const VueLoaderPlugin = require("vue-loader/lib/plugin");
|
||||||
|
const MiniCSSExtractPlugin = require("mini-css-extract-plugin");
|
||||||
|
const helpers = require("./helpers");
|
||||||
|
const isDev = process.env.NODE_ENV === "development";
|
||||||
|
|
||||||
|
const webpackConfig = function(isDev) {
|
||||||
|
return {
|
||||||
|
entry: {
|
||||||
|
main: ["@babel/polyfill", helpers.root("frontend", "main")]
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: [".js", ".vue"],
|
||||||
|
alias: {
|
||||||
|
vue$: isDev ? "vue/dist/vue.runtime.js" : "vue/dist/vue.runtime.min.js",
|
||||||
|
"@": helpers.root("frontend")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.vue$/,
|
||||||
|
loader: "vue-loader",
|
||||||
|
include: [helpers.root("frontend")]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.js$/,
|
||||||
|
loader: "babel-loader",
|
||||||
|
include: [helpers.root("frontend")]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
use: [
|
||||||
|
isDev ? "vue-style-loader" : MiniCSSExtractPlugin.loader,
|
||||||
|
{ loader: "css-loader", options: { sourceMap: isDev } }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.scss$/,
|
||||||
|
use: [
|
||||||
|
isDev ? "vue-style-loader" : MiniCSSExtractPlugin.loader,
|
||||||
|
{ loader: "css-loader", options: { sourceMap: isDev } },
|
||||||
|
{ loader: "sass-loader", options: { sourceMap: isDev } }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.sass$/,
|
||||||
|
use: [
|
||||||
|
isDev ? "vue-style-loader" : MiniCSSExtractPlugin.loader,
|
||||||
|
{ loader: "css-loader", options: { sourceMap: isDev } },
|
||||||
|
{ loader: "sass-loader", options: { sourceMap: isDev } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
plugins: [new VueLoaderPlugin()]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = webpackConfig;
|
||||||
44
config/webpack.config.dev.js
Normal file
44
config/webpack.config.dev.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const webpack = require("webpack");
|
||||||
|
const merge = require("webpack-merge");
|
||||||
|
const FriendlyErrorsPlugin = require("friendly-errors-webpack-plugin");
|
||||||
|
const HtmlPlugin = require("html-webpack-plugin");
|
||||||
|
const helpers = require("./helpers");
|
||||||
|
const commonConfig = require("./webpack.config.common");
|
||||||
|
const environment = require("./env/dev.env");
|
||||||
|
|
||||||
|
const webpackConfig = merge(commonConfig(true), {
|
||||||
|
mode: "development",
|
||||||
|
devtool: "cheap-module-eval-source-map",
|
||||||
|
output: {
|
||||||
|
path: helpers.root("dist"),
|
||||||
|
publicPath: "/",
|
||||||
|
filename: "js/[name].bundle.js",
|
||||||
|
chunkFilename: "js/[id].chunk.js"
|
||||||
|
},
|
||||||
|
optimization: {
|
||||||
|
runtimeChunk: "single",
|
||||||
|
splitChunks: {
|
||||||
|
chunks: "all"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new webpack.EnvironmentPlugin(environment),
|
||||||
|
new webpack.HotModuleReplacementPlugin(),
|
||||||
|
new FriendlyErrorsPlugin(),
|
||||||
|
new HtmlPlugin({ template: "frontend/index.html", chunksSortMode: "dependency" })
|
||||||
|
],
|
||||||
|
devServer: {
|
||||||
|
compress: true,
|
||||||
|
historyApiFallback: true,
|
||||||
|
hot: true,
|
||||||
|
overlay: true,
|
||||||
|
port: 8080,
|
||||||
|
stats: {
|
||||||
|
normal: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = webpackConfig;
|
||||||
55
config/webpack.config.prod.js
Normal file
55
config/webpack.config.prod.js
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const webpack = require("webpack");
|
||||||
|
const merge = require("webpack-merge");
|
||||||
|
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
|
||||||
|
const MiniCSSExtractPlugin = require("mini-css-extract-plugin");
|
||||||
|
const UglifyJSPlugin = require("uglifyjs-webpack-plugin");
|
||||||
|
const CompressionPlugin = require("compression-webpack-plugin");
|
||||||
|
const helpers = require("./helpers");
|
||||||
|
const commonConfig = require("./webpack.config.common");
|
||||||
|
const isProd = process.env.NODE_ENV === "production";
|
||||||
|
const environment = isProd
|
||||||
|
? require("./env/prod.env")
|
||||||
|
: require("./env/staging.env");
|
||||||
|
|
||||||
|
const webpackConfig = merge(commonConfig(false), {
|
||||||
|
mode: "production",
|
||||||
|
output: {
|
||||||
|
path: helpers.root("dist"),
|
||||||
|
publicPath: "/",
|
||||||
|
filename: "js/[name].bundle.js"
|
||||||
|
},
|
||||||
|
optimization: {
|
||||||
|
minimizer: [
|
||||||
|
new OptimizeCSSAssetsPlugin({
|
||||||
|
cssProcessorPluginOptions: {
|
||||||
|
preset: ["default", { discardComments: { removeAll: true } }]
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
new UglifyJSPlugin({
|
||||||
|
cache: true,
|
||||||
|
parallel: false,
|
||||||
|
sourceMap: !isProd
|
||||||
|
})
|
||||||
|
]
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new webpack.EnvironmentPlugin(environment),
|
||||||
|
new MiniCSSExtractPlugin({
|
||||||
|
filename: "css/[name].css"
|
||||||
|
})
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!isProd) {
|
||||||
|
webpackConfig.devtool = "source-map";
|
||||||
|
|
||||||
|
if (process.env.npm_config_report) {
|
||||||
|
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
|
||||||
|
.BundleAnalyzerPlugin;
|
||||||
|
webpackConfig.plugins.push(new BundleAnalyzerPlugin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = webpackConfig;
|
||||||
9
frontend/App.vue
Normal file
9
frontend/App.vue
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<router-view />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import './styles/normalize';
|
||||||
|
</style>
|
||||||
93
frontend/components/Player.vue
Normal file
93
frontend/components/Player.vue
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
<template>
|
||||||
|
<div class="conatiner">
|
||||||
|
<h1>Player</h1>
|
||||||
|
<div id="player"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
done: false,
|
||||||
|
player: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeMount() {
|
||||||
|
this.loadYoutubeIframe()
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
done: function(val) {
|
||||||
|
console.log('done changed to:', val)
|
||||||
|
if (val === true) {
|
||||||
|
this.player.playVideo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
loadYoutubeIframe() {
|
||||||
|
// const tag = this.$refs.player;
|
||||||
|
const tag = document.createElement('script');
|
||||||
|
tag.src = 'https://www.youtube.com/iframe_api';
|
||||||
|
const firstScriptTag = document.getElementsByTagName('script')[0]
|
||||||
|
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
|
||||||
|
|
||||||
|
const that = this;
|
||||||
|
// setTimeout(() => that.onYouTubeIframeAPIReady(), 2000);
|
||||||
|
window.onYouTubeIframeAPIReady = this.onYouTubeIframeAPIReady
|
||||||
|
},
|
||||||
|
onYouTubeIframeAPIReady() {
|
||||||
|
console.log('we are loaded and ready to fucking go!')
|
||||||
|
this.player = new YT.Player('player', {
|
||||||
|
videoId: 'SJOgTMP8cs4',
|
||||||
|
playerVars: {
|
||||||
|
rel: "0",
|
||||||
|
autoplay: 1,
|
||||||
|
wmode: "transparent",
|
||||||
|
controls: "0",
|
||||||
|
fs: "0",
|
||||||
|
iv_load_policy: "3",
|
||||||
|
theme: "light",
|
||||||
|
color: "white",
|
||||||
|
showinfo: 0
|
||||||
|
},
|
||||||
|
events: {
|
||||||
|
onReady: this.onPlayerReady,
|
||||||
|
onStateChange: this.onPlayerStateChange,
|
||||||
|
onError: this.errorHandler
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onPlayerReady(event) {
|
||||||
|
console.log('event from onPlayerReady', event)
|
||||||
|
event.target.playVideo();
|
||||||
|
},
|
||||||
|
onPlayerStateChange(event) {
|
||||||
|
console.log('on player changed')
|
||||||
|
if (event.data === YT.PlayerState.PLAYING && !this.done) {
|
||||||
|
this.done = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
errorHandler(error) {
|
||||||
|
console.log('error handling youtube player. Error:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
#player {
|
||||||
|
width: 100vw !important;
|
||||||
|
height: 60vh;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
30
frontend/components/Styleguide.vue
Normal file
30
frontend/components/Styleguide.vue
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1>Styleguide</h1>
|
||||||
|
<div class="row">
|
||||||
|
<h2>Chat</h2>
|
||||||
|
<Chat />
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<h2>Playlist-element</h2>
|
||||||
|
<Playlist />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Playlist from "@/components/playlist/Playlist";
|
||||||
|
import Chat from "@/components/chat/Chat";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Chat,
|
||||||
|
Playlist
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
||||||
149
frontend/components/chat/Chat.vue
Normal file
149
frontend/components/chat/Chat.vue
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
<template>
|
||||||
|
<div class="chat-container">
|
||||||
|
<ul>
|
||||||
|
<li v-for="(message, i) in chat" :key="i">
|
||||||
|
<Name :name="message.name" :icon="message.icon" />
|
||||||
|
<span class="channel-name" v-if="message.channel != null">{{ message.channel }}</span>
|
||||||
|
<span class="channel-message">: {{ message.message }}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="chat-input">
|
||||||
|
<ChatInput @sentMessage="sentMessage" @requestHelp="requestHelp" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Name from "@/components/chat/Name";
|
||||||
|
import ChatInput from "@/components/chat/ChatInput";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Name,
|
||||||
|
ChatInput
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
chat: function(_chat) {
|
||||||
|
if (_chat.length > 30) {
|
||||||
|
this.chat = _chat
|
||||||
|
.reverse()
|
||||||
|
.splice(0, 30)
|
||||||
|
.reverse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
sentMessage: function(message) {
|
||||||
|
this.chat.push({
|
||||||
|
name: "pepega",
|
||||||
|
icon: null,
|
||||||
|
message: message,
|
||||||
|
channel: "avicii"
|
||||||
|
});
|
||||||
|
},
|
||||||
|
requestHelp: function() {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
chat: [
|
||||||
|
{
|
||||||
|
name: "KasperRT",
|
||||||
|
icon: "https://img.youtube.com/vi/fn_amMJehPU/mqdefault.jpg",
|
||||||
|
message: "Hei på deg",
|
||||||
|
channel: "summér"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "KasperRT",
|
||||||
|
icon: "https://img.youtube.com/vi/fn_amMJehPU/mqdefault.jpg",
|
||||||
|
message: "Hei på deg",
|
||||||
|
channel: "summér"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "KasperRT",
|
||||||
|
icon: "https://img.youtube.com/vi/fn_amMJehPU/mqdefault.jpg",
|
||||||
|
message: "Hei på deg",
|
||||||
|
channel: "summér"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "KasperRT",
|
||||||
|
icon: "https://img.youtube.com/vi/fn_amMJehPU/mqdefault.jpg",
|
||||||
|
message: "Hei på deg",
|
||||||
|
channel: "summér"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "KasperRT",
|
||||||
|
icon: "https://img.youtube.com/vi/fn_amMJehPU/mqdefault.jpg",
|
||||||
|
message: "Hei på deg",
|
||||||
|
channel: "summér"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "KasperRT",
|
||||||
|
icon: "https://img.youtube.com/vi/fn_amMJehPU/mqdefault.jpg",
|
||||||
|
message: "Hei på deg",
|
||||||
|
channel: "summér"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "KasperRT",
|
||||||
|
icon: "https://img.youtube.com/vi/fn_amMJehPU/mqdefault.jpg",
|
||||||
|
message: "Hei på deg",
|
||||||
|
channel: "summér"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "KasperRT",
|
||||||
|
icon: "https://img.youtube.com/vi/fn_amMJehPU/mqdefault.jpg",
|
||||||
|
message: "Hei på deg",
|
||||||
|
channel: "summér"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "KasperRT",
|
||||||
|
icon: "https://img.youtube.com/vi/fn_amMJehPU/mqdefault.jpg",
|
||||||
|
message: "Hei på deg",
|
||||||
|
channel: "summér"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "KasperRT",
|
||||||
|
icon: "https://img.youtube.com/vi/fn_amMJehPU/mqdefault.jpg",
|
||||||
|
message: "Hei på deg",
|
||||||
|
channel: "summér"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "KasperRT",
|
||||||
|
icon: "https://img.youtube.com/vi/fn_amMJehPU/mqdefault.jpg",
|
||||||
|
message: "Hei på deg",
|
||||||
|
channel: "summér"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
& li {
|
||||||
|
display: flex;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
& .channel-name {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
color: whitesmoke;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(even) {
|
||||||
|
background: #00000040;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(odd) {
|
||||||
|
background: #00000050;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
33
frontend/components/chat/ChatInput.vue
Normal file
33
frontend/components/chat/ChatInput.vue
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<template>
|
||||||
|
<div class="chat-input">
|
||||||
|
<input v-model="chatInput" type="text" placeholder="Aa.." @keyup.enter="send" />
|
||||||
|
<button @click="send">Send</button>
|
||||||
|
<button @click="requestHelp">Help</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
chatInput: ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
send: function() {
|
||||||
|
if(this.chatInput == "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$emit("sentMessage", this.chatInput);
|
||||||
|
this.chatInput = "";
|
||||||
|
},
|
||||||
|
requestHelp: function() {
|
||||||
|
console.log("emit for help here");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
|
||||||
|
</style>
|
||||||
41
frontend/components/chat/Name.vue
Normal file
41
frontend/components/chat/Name.vue
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<template>
|
||||||
|
<div class="name">
|
||||||
|
<div class="icon-container" v-if="icon != undefined">
|
||||||
|
<img :src="icon" />
|
||||||
|
</div>
|
||||||
|
<div class="name-container">{{ name }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
type: String,
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.name {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 10px;
|
||||||
|
width: 10px;
|
||||||
|
padding: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name-container {
|
||||||
|
padding: 0 5px 0 5px;
|
||||||
|
color: orange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
113
frontend/components/playlist/ContextMenu.vue
Normal file
113
frontend/components/playlist/ContextMenu.vue
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
<template>
|
||||||
|
<div class="context-menu-container" :style="'top:' + mouseY + 'px;left:' + mouseX + 'px;'">
|
||||||
|
<ul>
|
||||||
|
<li @click="copyLink">Copy link</li>
|
||||||
|
<li @click="findSimilar">Find similar</li>
|
||||||
|
<li class="addedBy">Added by {{ addedBy }}</li>
|
||||||
|
<hr />
|
||||||
|
<li @click="deleteSong" :disabled="loggedIn">Delete</li>
|
||||||
|
</ul>
|
||||||
|
<div class="context-menu-background" @mouseout="closeSelf" @click="closeSelf"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
id: {
|
||||||
|
required: true,
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
required: true,
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
addedBy: {
|
||||||
|
required: true,
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
mouseX: {
|
||||||
|
required: true,
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
mouseY: {
|
||||||
|
required: true,
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
loggedIn: function() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
closeSelf: function(e) {
|
||||||
|
if (e.toElement == null || e.toElement.nodeName == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.toElement.nodeName == "UL" || e.toElement.nodeName == "LI") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$emit("closeContextMenu");
|
||||||
|
},
|
||||||
|
copyLink: function() {
|
||||||
|
console.log("copy link of", this.id);
|
||||||
|
},
|
||||||
|
findSimilar: function() {
|
||||||
|
console.log("find similar of", this.id);
|
||||||
|
},
|
||||||
|
deleteSong: function() {
|
||||||
|
console.log("delete song of", this.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.context-menu-background {
|
||||||
|
background: #000000a0;
|
||||||
|
width: 500px;
|
||||||
|
height: 500px;
|
||||||
|
position: absolute;
|
||||||
|
left: -85%;
|
||||||
|
top: -100%;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.context-menu-container {
|
||||||
|
font-family: sans-serif;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
background-color: #2d2d2d;
|
||||||
|
border-radius: 10px;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
& ul {
|
||||||
|
z-index: 2;
|
||||||
|
list-style: none;
|
||||||
|
padding: 10px 0 10px 0;
|
||||||
|
margin: 0;
|
||||||
|
position: relative;
|
||||||
|
background-color: #2d2d2d;
|
||||||
|
border-radius: 10px;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
& li {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px 15px;
|
||||||
|
|
||||||
|
&:hover:not(.addedBy) {
|
||||||
|
background-color: #ffffff15;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.addedBy {
|
||||||
|
cursor: initial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& hr {
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
181
frontend/components/playlist/Playlist.vue
Normal file
181
frontend/components/playlist/Playlist.vue
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
<template>
|
||||||
|
<div class="playlist-conatiner">
|
||||||
|
<div class="playlist-element" v-for="(song, i) in paginatedList" :key="i">
|
||||||
|
<Song
|
||||||
|
class="song"
|
||||||
|
:title="song.title"
|
||||||
|
:thumbnail="song.thumbnail"
|
||||||
|
:votes="song.votes"
|
||||||
|
:addedBy="song.added_by"
|
||||||
|
:id="song.id"
|
||||||
|
:type="song.type"
|
||||||
|
:duration="song.duration"
|
||||||
|
@contextmenu="moreInfo"
|
||||||
|
/>
|
||||||
|
<div class="song-context-button" @click="moreInfo($event, song.id)">. . .</div>
|
||||||
|
</div>
|
||||||
|
<div class="pagination-buttons">
|
||||||
|
<button @click="firstPage" :disabled="disabledPrev" class="first"><</button>
|
||||||
|
<button @click="prevPage" :disabled="disabledPrev">previous</button>
|
||||||
|
<span>{{ page + 1 }} / {{ pages }}</span>
|
||||||
|
<button @click="nextPage" :disabled="disabledNext">next</button>
|
||||||
|
<button @click="lastPage" :disabled="disabledNext" class="last">></button>
|
||||||
|
</div>
|
||||||
|
<ContextMenu
|
||||||
|
v-if="contextMenuOpen"
|
||||||
|
:addedBy="contextOnElement.added_by"
|
||||||
|
:id="contextOnElement.id"
|
||||||
|
:type="contextOnElement.type"
|
||||||
|
:mouseX="mouseX"
|
||||||
|
:mouseY="mouseY"
|
||||||
|
@closeContextMenu="closeContextMenu"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Song from "@/components/playlist/Song";
|
||||||
|
import ContextMenu from "@/components/playlist/ContextMenu";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Song,
|
||||||
|
ContextMenu
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
paginatedList: function() {
|
||||||
|
return this.playlist.slice(
|
||||||
|
this.page * this.perPage,
|
||||||
|
(1 + this.page) * this.perPage
|
||||||
|
);
|
||||||
|
},
|
||||||
|
disabledPrev: function() {
|
||||||
|
return this.page == 0;
|
||||||
|
},
|
||||||
|
disabledNext: function() {
|
||||||
|
return this.playlist.length < (this.page + 1) * this.perPage;
|
||||||
|
},
|
||||||
|
pages: function() {
|
||||||
|
return Math.ceil(this.playlist.length / this.perPage);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async beforeMount() {
|
||||||
|
try {
|
||||||
|
const request = await fetch("https://zoff.me/api/list/summér", {
|
||||||
|
method: "POST"
|
||||||
|
});
|
||||||
|
const playlist = await request.json();
|
||||||
|
if (this.playlist.error == true) {
|
||||||
|
console.error(this.playlist.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.playlist = playlist.results;
|
||||||
|
} catch (e) {
|
||||||
|
alert("TIMEOUT");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
moreInfo: function(e, id) {
|
||||||
|
e.preventDefault();
|
||||||
|
this.contextOnElement = this.playlist.find(song => song.id == id);
|
||||||
|
this.mouseX = e.pageX;
|
||||||
|
this.mouseY = e.pageY;
|
||||||
|
this.contextMenuOpen = true;
|
||||||
|
},
|
||||||
|
closeContextMenu: function() {
|
||||||
|
this.contextMenuOpen = false;
|
||||||
|
this.contextOnElement = null;
|
||||||
|
},
|
||||||
|
firstPage: function() {
|
||||||
|
this.page = 0;
|
||||||
|
},
|
||||||
|
lastPage: function() {
|
||||||
|
this.page = Math.floor(this.playlist.length / this.perPage);
|
||||||
|
},
|
||||||
|
prevPage: function() {
|
||||||
|
if (this.page == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.page -= 1;
|
||||||
|
},
|
||||||
|
nextPage: function() {
|
||||||
|
if (this.playlist.length < (this.page + 1) * this.perPage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.page += 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
contextMenuOpen: false,
|
||||||
|
contextOnElement: {},
|
||||||
|
page: 0,
|
||||||
|
perPage: 10,
|
||||||
|
playlist: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.playlist-conatiner {
|
||||||
|
background-color: #2d2d2d;
|
||||||
|
padding-top: 5px;
|
||||||
|
|
||||||
|
& .playlist-element {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
box-shadow: 0px 0px 2px #000000;
|
||||||
|
border-radius: 5px;
|
||||||
|
background: #2d2d2d;
|
||||||
|
color: white;
|
||||||
|
margin: 5px 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0px 0px 3px #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .song {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
& .song-context-button {
|
||||||
|
width: 10%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-left: 1px solid black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
color: white;
|
||||||
|
padding: 10px 0;
|
||||||
|
|
||||||
|
& span {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
& button {
|
||||||
|
width: 35%;
|
||||||
|
height: 30px;
|
||||||
|
background: transparent;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&.first,
|
||||||
|
&.last {
|
||||||
|
width: 10%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
136
frontend/components/playlist/Song.vue
Normal file
136
frontend/components/playlist/Song.vue
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
<template>
|
||||||
|
<div class="song-container">
|
||||||
|
<div
|
||||||
|
class="song-voteable-container"
|
||||||
|
@click="clickedSong"
|
||||||
|
@contextmenu="$emit('contextmenu', $event, id)"
|
||||||
|
>
|
||||||
|
<div class="song-thumbnail">
|
||||||
|
<img :src="thumbnail" :alt="title" />
|
||||||
|
<span class="song-duration">{{ durationInString }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="song-info">
|
||||||
|
<div class="song-title">{{ title }}</div>
|
||||||
|
<div class="song-votes">{{ votes }} vote{{votes > 1 || votes == 0 ? "s" : null }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ContextMenu from "@/components/playlist/ContextMenu";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
ContextMenu
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
id: {
|
||||||
|
required: true,
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
thumbnail: {
|
||||||
|
required: true,
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
required: true,
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
votes: {
|
||||||
|
required: true,
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
addedBy: {
|
||||||
|
required: true,
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
required: true,
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
duration: {
|
||||||
|
required: true,
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
contextMenuOpen: false,
|
||||||
|
mouseX: 0,
|
||||||
|
mouseY: 0
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
durationInString: function() {
|
||||||
|
let time = this.duration;
|
||||||
|
let minutes = Math.floor(time / 60);
|
||||||
|
time = time - minutes * 60;
|
||||||
|
let minutesString = (minutes + "").padStart(2, "0");
|
||||||
|
let secondString = (time + "").padStart(2, "0");
|
||||||
|
return `${minutesString}:${secondString}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
clickedSong: function() {
|
||||||
|
console.log("Clicked on song with info", this.title, this.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.song-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
.song-voteable-container {
|
||||||
|
width: 75%;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
& .song-votes {
|
||||||
|
color: lightgrey;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .song-thumbnail {
|
||||||
|
width: 25%;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
& img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-top-left-radius: 7.5px;
|
||||||
|
border-bottom-left-radius: 7.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .song-duration {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 5px;
|
||||||
|
left: 0px;
|
||||||
|
border-top-left-radius: 4px;
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
padding: 0 5px;
|
||||||
|
background: #000000A0;
|
||||||
|
color:white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& .song-info {
|
||||||
|
width: 100%;
|
||||||
|
padding-left: 10px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& .song-mutation {
|
||||||
|
width: 25%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
9
frontend/index.html
Normal file
9
frontend/index.html
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Zoff</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
16
frontend/main.js
Normal file
16
frontend/main.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import VueRouter from 'vue-router'
|
||||||
|
import router from './routes'
|
||||||
|
import store from './store'
|
||||||
|
|
||||||
|
import App from './App.vue'
|
||||||
|
|
||||||
|
Vue.use(VueRouter)
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: '#app',
|
||||||
|
router,
|
||||||
|
store,
|
||||||
|
components: { App },
|
||||||
|
render: h => h(App)
|
||||||
|
})
|
||||||
21
frontend/modules/playerModule.js
Normal file
21
frontend/modules/playerModule.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
export default {
|
||||||
|
namespaced: true,
|
||||||
|
state: {
|
||||||
|
player: undefined
|
||||||
|
},
|
||||||
|
getters: {
|
||||||
|
player: (state) => {
|
||||||
|
return state.player;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
SET_PLAYER: (state, player) => {
|
||||||
|
state.player = player;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actios: {
|
||||||
|
setPlayer({ commit }, player) {
|
||||||
|
commit('SET_PLAYER', player)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
frontend/routes.js
Normal file
31
frontend/routes.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import VueRouter from 'vue-router';
|
||||||
|
|
||||||
|
Vue.use(VueRouter)
|
||||||
|
|
||||||
|
let routes = [
|
||||||
|
{
|
||||||
|
name: 'player',
|
||||||
|
path: '/player',
|
||||||
|
component: (resolve) => require(['./components/Player.vue'], resolve)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'styleguide',
|
||||||
|
path: '/styleguide',
|
||||||
|
component: (resolve) => require(['./components/Styleguide.vue'], resolve)
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// name: '404',
|
||||||
|
// path: '/404',
|
||||||
|
// component: (resolve) => require(['./components/404.vue'], resolve)
|
||||||
|
// }
|
||||||
|
];
|
||||||
|
|
||||||
|
const router = new VueRouter({
|
||||||
|
mode: 'hash',
|
||||||
|
base: '/',
|
||||||
|
routes,
|
||||||
|
linkActiveClass: 'is-active'
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
12
frontend/store.js
Normal file
12
frontend/store.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import Vue from 'vue';
|
||||||
|
import Vuex from 'vuex';
|
||||||
|
|
||||||
|
import playerModule from '@/modules/playerModule';
|
||||||
|
|
||||||
|
Vue.use(Vuex);
|
||||||
|
|
||||||
|
const store = new Vuex.Store({
|
||||||
|
modules: {
|
||||||
|
playerModule
|
||||||
|
}
|
||||||
|
})
|
||||||
6
frontend/styles/normalize.scss
vendored
Normal file
6
frontend/styles/normalize.scss
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
7853
package-lock.json
generated
7853
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
39
package.json
39
package.json
@@ -5,6 +5,7 @@
|
|||||||
"main": "server/app.js",
|
"main": "server/app.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "npm install --only=dev && npm install && $(npm bin)/gulp build && node server/app.js",
|
"start": "npm install --only=dev && npm install && $(npm bin)/gulp build && node server/app.js",
|
||||||
|
"vue": "cross-env NODE_ENV=development webpack-dev-server --progress",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -20,12 +21,40 @@
|
|||||||
"url": "https://github.com/zoff-music/zoff/issues"
|
"url": "https://github.com/zoff-music/zoff/issues"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "~5.2",
|
||||||
"gulp": "^4.0.0",
|
"gulp": "^4.0.0",
|
||||||
"gulp-concat": "^2.6.1",
|
"gulp-concat": "^2.6.1",
|
||||||
"gulp-uglify": "^3.0.2"
|
"gulp-uglify": "^3.0.2",
|
||||||
|
"@babel/core": "~7.2",
|
||||||
|
"@babel/plugin-proposal-class-properties": "~7.3",
|
||||||
|
"@babel/plugin-proposal-decorators": "~7.3",
|
||||||
|
"@babel/plugin-proposal-json-strings": "~7.2",
|
||||||
|
"@babel/plugin-syntax-dynamic-import": "~7.2",
|
||||||
|
"@babel/plugin-syntax-import-meta": "~7.2",
|
||||||
|
"@babel/preset-env": "~7.3",
|
||||||
|
"babel-loader": "~8.0",
|
||||||
|
"compression-webpack-plugin": "~2.0",
|
||||||
|
"css-loader": "~0.28",
|
||||||
|
"friendly-errors-webpack-plugin": "~1.7",
|
||||||
|
"html-webpack-plugin": "~3.2",
|
||||||
|
"mini-css-extract-plugin": "~0.5",
|
||||||
|
"node-sass": "~4.11",
|
||||||
|
"optimize-css-assets-webpack-plugin": "~3.2",
|
||||||
|
"sass-loader": "~7.1",
|
||||||
|
"uglifyjs-webpack-plugin": "~1.2",
|
||||||
|
"vue-loader": "~15.6",
|
||||||
|
"vue-style-loader": "~4.1",
|
||||||
|
"vue-template-compiler": "~2.6",
|
||||||
|
"webpack": "~4.29",
|
||||||
|
"webpack-bundle-analyzer": "~3.0",
|
||||||
|
"webpack-cli": "~3.2",
|
||||||
|
"webpack-dev-server": "~3.1",
|
||||||
|
"webpack-hot-middleware": "~2.24",
|
||||||
|
"webpack-merge": "~4.2"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/zoff-music/zoff#readme",
|
"homepage": "https://github.com/zoff-music/zoff#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@babel/polyfill": "~7.2",
|
||||||
"bad-words": "^1.6.5",
|
"bad-words": "^1.6.5",
|
||||||
"bcrypt-nodejs": "0.0.3",
|
"bcrypt-nodejs": "0.0.3",
|
||||||
"body-parser": "^1.18.3",
|
"body-parser": "^1.18.3",
|
||||||
@@ -38,6 +67,7 @@
|
|||||||
"express-handlebars": "^3.0.2",
|
"express-handlebars": "^3.0.2",
|
||||||
"express-recaptcha": "^3.0.1",
|
"express-recaptcha": "^3.0.1",
|
||||||
"express-session": "^1.15.6",
|
"express-session": "^1.15.6",
|
||||||
|
"extract-text-webpack-plugin": "^3.0.2",
|
||||||
"farmhash": "^3.0.0",
|
"farmhash": "^3.0.0",
|
||||||
"feature-policy": "^0.2.0",
|
"feature-policy": "^0.2.0",
|
||||||
"gulp-clean-css": "^4.2.0",
|
"gulp-clean-css": "^4.2.0",
|
||||||
@@ -48,7 +78,7 @@
|
|||||||
"mongodb": "^2.2.36",
|
"mongodb": "^2.2.36",
|
||||||
"mongojs": "^2.6.0",
|
"mongojs": "^2.6.0",
|
||||||
"mongojs-paginate": "^1.2.0",
|
"mongojs-paginate": "^1.2.0",
|
||||||
"mongoose": "^5.7.5",
|
"mongoose": "^5.4.18",
|
||||||
"mpromise": "^0.5.5",
|
"mpromise": "^0.5.5",
|
||||||
"nodemailer": "^4.7.0",
|
"nodemailer": "^4.7.0",
|
||||||
"passport": "^0.4.0",
|
"passport": "^0.4.0",
|
||||||
@@ -59,6 +89,9 @@
|
|||||||
"socket.io": "^2.2.0",
|
"socket.io": "^2.2.0",
|
||||||
"socket.io-redis": "^5.2.0",
|
"socket.io-redis": "^5.2.0",
|
||||||
"sticky-session": "^1.1.2",
|
"sticky-session": "^1.1.2",
|
||||||
"uniqid": "5.0.3"
|
"uniqid": "5.0.3",
|
||||||
|
"vue": "~2.6",
|
||||||
|
"vue-router": "~3.0",
|
||||||
|
"vuex": "^3.1.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,7 +350,12 @@ temp_pass = "";
|
|||||||
|
|
||||||
initializeCastApi = function() {
|
initializeCastApi = function() {
|
||||||
try {
|
try {
|
||||||
if (cast == undefined) return;
|
if (
|
||||||
|
cast == undefined ||
|
||||||
|
chrome.cast == undefined ||
|
||||||
|
chrome.cast.AutoJoinPolicy == undefined
|
||||||
|
)
|
||||||
|
return;
|
||||||
} catch (event) {
|
} catch (event) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
9
webpack.config.js
Normal file
9
webpack.config.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const environment = (process.env.NODE_ENV || "development").trim();
|
||||||
|
|
||||||
|
if (environment === "development") {
|
||||||
|
module.exports = require("./config/webpack.config.dev");
|
||||||
|
} else {
|
||||||
|
module.exports = require("./config/webpack.config.prod");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user