Compare commits

...
Sign in to create a new pull request.

1 commit

Author SHA1 Message Date
d881463411 notification support 2024-10-13 01:49:19 +02:00
11 changed files with 170 additions and 62 deletions

43
package-lock.json generated
View file

@ -1,16 +1,17 @@
{ {
"name": "syng-weg", "name": "syng-web",
"version": "2.0.0", "version": "2.0.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "syng-weg", "name": "syng-web",
"version": "2.0.0", "version": "2.0.0",
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-free": "^6.2.1", "@fortawesome/fontawesome-free": "^6.2.1",
"@fortawesome/fontawesome-svg-core": "^6.2.1", "@fortawesome/fontawesome-svg-core": "^6.2.1",
"@fortawesome/free-brands-svg-icons": "^6.2.1", "@fortawesome/free-brands-svg-icons": "^6.2.1",
"@fortawesome/free-regular-svg-icons": "^6.2.1",
"@fortawesome/free-solid-svg-icons": "^6.2.1", "@fortawesome/free-solid-svg-icons": "^6.2.1",
"@fortawesome/vue-fontawesome": "^3.0.2", "@fortawesome/vue-fontawesome": "^3.0.2",
"foundation-sites": "^6.7.5", "foundation-sites": "^6.7.5",
@ -108,6 +109,29 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/@fortawesome/free-regular-svg-icons": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.5.2.tgz",
"integrity": "sha512-iabw/f5f8Uy2nTRtJ13XZTS1O5+t+anvlamJ3zJGLEVE2pKsAWhPv2lq01uQlfgCX7VaveT3EVs515cCN9jRbw==",
"hasInstallScript": true,
"license": "(CC-BY-4.0 AND MIT)",
"dependencies": {
"@fortawesome/fontawesome-common-types": "6.5.2"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@fortawesome/free-regular-svg-icons/node_modules/@fortawesome/fontawesome-common-types": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz",
"integrity": "sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw==",
"hasInstallScript": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/@fortawesome/free-solid-svg-icons": { "node_modules/@fortawesome/free-solid-svg-icons": {
"version": "6.4.0", "version": "6.4.0",
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz", "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz",
@ -1041,6 +1065,21 @@
"@fortawesome/fontawesome-common-types": "6.4.0" "@fortawesome/fontawesome-common-types": "6.4.0"
} }
}, },
"@fortawesome/free-regular-svg-icons": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.5.2.tgz",
"integrity": "sha512-iabw/f5f8Uy2nTRtJ13XZTS1O5+t+anvlamJ3zJGLEVE2pKsAWhPv2lq01uQlfgCX7VaveT3EVs515cCN9jRbw==",
"requires": {
"@fortawesome/fontawesome-common-types": "6.5.2"
},
"dependencies": {
"@fortawesome/fontawesome-common-types": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz",
"integrity": "sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw=="
}
}
},
"@fortawesome/free-solid-svg-icons": { "@fortawesome/free-solid-svg-icons": {
"version": "6.4.0", "version": "6.4.0",
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz", "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz",

View file

@ -11,6 +11,7 @@
"@fortawesome/fontawesome-svg-core": "^6.2.1", "@fortawesome/fontawesome-svg-core": "^6.2.1",
"@fortawesome/free-brands-svg-icons": "^6.2.1", "@fortawesome/free-brands-svg-icons": "^6.2.1",
"@fortawesome/free-solid-svg-icons": "^6.2.1", "@fortawesome/free-solid-svg-icons": "^6.2.1",
"@fortawesome/free-regular-svg-icons": "^6.2.1",
"@fortawesome/vue-fontawesome": "^3.0.2", "@fortawesome/vue-fontawesome": "^3.0.2",
"foundation-sites": "^6.7.5", "foundation-sites": "^6.7.5",
"socket.io-client": "^4.5.3", "socket.io-client": "^4.5.3",

View file

@ -28,16 +28,31 @@ const state = ref({
'secret': null, 'secret': null,
'current_entry': null, 'current_entry': null,
'current_name': null, 'current_name': null,
'last_notification_uuid': null,
'searching': false, 'searching': false,
'last_msg': "", 'last_msg': "",
'join_msg': null, 'join_msg': null,
'uid': null, 'uid': null,
'double_entry': {'artist': null, 'title': null, 'reason': null}, 'double_entry': {'artist': null, 'title': null, 'reason': null},
'waiting_room_policy': null, 'waiting_room_policy': null,
'notify_me': [],
'config': {} 'config': {}
}) })
onMounted(() => { onMounted(() => {
if (!window.Notification) {
console.log('Browser does not support notifications.');
} else {
if (Notification.permission !== 'granted') {
Notification.requestPermission().then(
p => {
if (p !== 'granted') {
console.log('User blocked notifications.');
}
}
).catch(err => console.error(err))
}
}
window.addEventListener("resize", (e) => { state.value.is_small = (e.target.innerWidth < 768) }); window.addEventListener("resize", (e) => { state.value.is_small = (e.target.innerWidth < 768) });
$(document).foundation(); $(document).foundation();
if(localStorage.name && localStorage.name != "null"){ state.value.name = localStorage.name } if(localStorage.name && localStorage.name != "null"){ state.value.name = localStorage.name }
@ -47,6 +62,7 @@ onMounted(() => {
} }
if(localStorage.secret){ state.value.secret = localStorage.secret } if(localStorage.secret){ state.value.secret = localStorage.secret }
if(localStorage.uid){ state.value.uid = localStorage.uid } if(localStorage.uid){ state.value.uid = localStorage.uid }
if(localStorage.notify_me) { state.value.notify_me = JSON.parse(localStorage.notify_me); }
if(state.value.server && state.value.room && state.value.name) { if(state.value.server && state.value.room && state.value.name) {
connect() connect()
} }
@ -58,7 +74,7 @@ function emptyLocalStorageAndLogout() {
localStorage.removeItem('name') localStorage.removeItem('name')
localStorage.removeItem('room') localStorage.removeItem('room')
localStorage.removeItem('uid') localStorage.removeItem('uid')
state.socket.disconnect() state.value.socket.disconnect()
state.value.joined = false state.value.joined = false
} }
@ -70,7 +86,7 @@ function updateName(evt) { evt.target.textContent = state.value.name;}
function setServer(server) { state.value.server = server } function setServer(server) { state.value.server = server }
function setSearchTerm(searchTerm) { state.value.search.searchTerm = searchTerm } function setSearchTerm(searchTerm) { state.value.search.searchTerm = searchTerm }
function update_config(config) { function update_config(config) {
state.socket.emit("update_config", {"config": config}) state.value.socket.emit("update_config", {"config": config})
close_config() close_config()
} }
@ -80,18 +96,14 @@ function search() {
append({"ident": state.value.search.searchTerm, "source": "youtube"}) append({"ident": state.value.search.searchTerm, "source": "youtube"})
} else { } else {
state.value.searching = true state.value.searching = true
state.socket.emit("search", {"query": state.value.search.searchTerm }) state.value.socket.emit("search", {"query": state.value.search.searchTerm })
} }
} }
function show_config() { function show_config() {
state.socket.emit("show_config"); state.value.socket.emit("show_config");
} }
function waitingRoomToQueue(uuid) {
state.socket.emit("waiting-room-to-queue", {"uuid": uuid})
}
function append(entry) { function append(entry) {
checked_append_with_name(entry, state.value.name) checked_append_with_name(entry, state.value.name)
} }
@ -113,7 +125,7 @@ function append_anyway(ident, name, source, uid) {
state.value.current_name = null; state.value.current_name = null;
state.value.current_entry = null; state.value.current_entry = null;
state.value.double_entry = {'artist': null, 'title': null, 'reason': null}; state.value.double_entry = {'artist': null, 'title': null, 'reason': null};
state.socket.emit("append-anyway", {"ident": ident, "performer": name, "source": source, "uid": uid }); state.value.socket.emit("append-anyway", {"ident": ident, "performer": name, "source": source, "uid": uid });
$("#queue-tab-title").click(); $("#queue-tab-title").click();
} }
@ -124,7 +136,7 @@ function raw_append(ident, name, source, uid) {
state.value.current_name = null; state.value.current_name = null;
state.value.current_entry = null; state.value.current_entry = null;
state.value.double_entry = {'artist': null, 'title': null, 'reason': null}; state.value.double_entry = {'artist': null, 'title': null, 'reason': null};
state.socket.emit("append", {"ident": ident, "performer": name, "source": source, "uid": uid }); state.value.socket.emit("append", {"ident": ident, "performer": name, "source": source, "uid": uid });
$("#queue-tab-title").click(); $("#queue-tab-title").click();
} }
@ -134,7 +146,7 @@ function wait_append(ident, name, source, uid) {
state.value.current_name = null; state.value.current_name = null;
state.value.current_entry = null; state.value.current_entry = null;
state.socket.emit("waiting-room-append", {"ident": ident, "performer": name, "source": source, "uid": uid }); state.value.socket.emit("waiting-room-append", {"ident": ident, "performer": name, "source": source, "uid": uid });
$("#queue-tab-title").click(); $("#queue-tab-title").click();
} }
@ -162,62 +174,89 @@ function connect() {
state.value.uid = Math.random(); state.value.uid = Math.random();
} }
} }
registerSocketEvents(state.socket) registerSocketEvents(state.value.socket)
} }
function skipCurrent() { function notify_disable(uuid) {
state.socket.emit("skip-current") let notify_me = JSON.parse(localStorage.notify_me)
let idx = notify_me.indexOf(uuid);
notify_me.splice(idx, 1);
localStorage.setItem("notify_me", JSON.stringify(notify_me))
state.value.notify_me = notify_me
} }
function moveUp(uuid) { function notify_enable(uuid) {
state.socket.emit("move-up", {"uuid": uuid}) let notify_me = JSON.parse(localStorage.notify_me)
} notify_me.push(uuid)
localStorage.setItem("notify_me", JSON.stringify(notify_me))
function skip(uuid) { state.value.notify_me = notify_me
state.socket.emit("skip", {"uuid": uuid})
} }
function registerSocketEvents() { function registerSocketEvents() {
state.socket = io(state.value.server) state.value.socket = io(state.value.server)
state.socket.on("search-results", (results) => { state.value.socket.on("search-results", (results) => {
state.value.searching = false state.value.searching = false
state.value.search.searchResults = results.results state.value.search.searchResults = results.results
}) })
state.socket.on("connect", () => { joinRoom() }) state.value.socket.on("connect", () => { joinRoom() })
state.socket.io.on("reconnect", () => { joinRoom() }) state.value.socket.io.on("reconnect", () => { joinRoom() })
state.socket.on("state", (val) => { state.value.socket.on("state", (val) => {
if(!localStorage.notify_me) {
localStorage.setItem("notify_me", "[]");
state.value.notify_me = []
}
var new_notify = [] // Somehow Array.filter does not work
state.value.notify_me.forEach((uuid) => {
for(const entry of val.queue) {
if(entry.uuid === uuid) {
new_notify.push(uuid)
};
};
});
state.value.notify_me = new_notify;
localStorage.setItem("notify_me", JSON.stringify(state.value.notify_me))
if (val.queue.length > 1 &&
val.queue[1].uuid != state.value.last_notification_uuid &&
state.value.notify_me.indexOf(val.queue[1].uuid) !== -1 &&
Notification.permission === 'granted') {
state.value.last_notification_uuid = val.queue[1].uuid;
new Notification("Next Up for " + val.queue[1].performer + ":", {body: val.queue[1].artist + " - " + val.queue[1].title})
}
state.value.queue=val.queue state.value.queue=val.queue
state.value.recent=val.recent state.value.recent=val.recent
state.value.waiting_room = val.waiting_room state.value.waiting_room = val.waiting_room
state.value.waiting_room_policy = val.config.waiting_room_policy state.value.waiting_room_policy = val.config.waiting_room_policy
}) })
state.socket.on("config", (response) => { state.value.socket.on("config", (response) => {
state.value.config=response state.value.config=response
$("#config").foundation("open") $("#config").foundation("open")
}) })
state.socket.on("update_config", (response) => { state.value.socket.on("update_config", (response) => {
console.log(response) console.log(response)
state.value.waiting_room_policy = response["waiting_room_policy"] state.value.waiting_room_policy = response["waiting_room_policy"]
console.log(state) console.log(state)
}) })
state.socket.on("msg", (response) => { state.value.socket.on("msg", (response) => {
state.value.last_msg = response.msg state.value.last_msg = response.msg
$("#msg").foundation("open") $("#msg").foundation("open")
}) })
state.socket.on("ask_for_waitingroom", (response) => { state.value.socket.on("ask_for_waitingroom", (response) => {
state.value.double_entry = response.old_entry; state.value.double_entry = response.old_entry;
state.value.current_entry = response.current_entry; state.value.current_entry = response.current_entry;
$("#alreadyqueued").foundation("open"); $("#alreadyqueued").foundation("open");
}) })
state.socket.on("err", (response) => { state.value.socket.on("err", (response) => {
console.log(response) console.log(response)
switch(response.type) { switch(response.type) {
case "QUEUE_FULL": case "QUEUE_FULL":
@ -247,7 +286,7 @@ function registerSocketEvents() {
function joinRoom() { function joinRoom() {
console.log("Joining room " + state.value.room) console.log("Joining room " + state.value.room)
state.socket.emit("register-web", {"room": state.value.room}, (response) => { state.value.socket.emit("register-web", {"room": state.value.room}, (response) => {
if(response === true) { if(response === true) {
localStorage.name = state.value.name localStorage.name = state.value.name
localStorage.server = state.value.server localStorage.server = state.value.server
@ -257,7 +296,7 @@ function joinRoom() {
state.value.joined = true state.value.joined = true
router.push({name: "room", params: {room: state.value.room}}) router.push({name: "room", params: {room: state.value.room}})
if (state.value.secret) { if (state.value.secret) {
state.socket.emit("register-admin", {"secret": state.value.secret}, (response) => { state.value.socket.emit("register-admin", {"secret": state.value.secret}, (response) => {
state.value.admin = response state.value.admin = response
}) })
} }
@ -269,7 +308,7 @@ function joinRoom() {
"target='_blank'>Syng</a> and run it with <pre>syng-client " + "target='_blank'>Syng</a> and run it with <pre>syng-client " +
state.value.server + "</pre>" state.value.server + "</pre>"
if(state.value.joined) { if(state.value.joined) {
state.socket.disconnect() state.value.socket.disconnect()
setTimeout(() => connect(), 2000) setTimeout(() => connect(), 2000)
} }
} }
@ -286,10 +325,8 @@ function joinRoom() {
@update:searchTerm="setSearchTerm" @update:searchTerm="setSearchTerm"
@search="search" @search="search"
@append="append" @append="append"
@skip="skip" @notify_disable="notify_disable"
@skipCurrent="skipCurrent" @notify_enable="notify_enable"
@moveUp="moveUp"
@waitingRoomToQueue="waitingRoomToQueue"
/> />
<DesktopLayout <DesktopLayout
v-show="!state.is_small" v-show="!state.is_small"
@ -297,10 +334,8 @@ function joinRoom() {
@update:searchTerm="setSearchTerm" @update:searchTerm="setSearchTerm"
@search="search" @search="search"
@append="append" @append="append"
@skip="skip" @notify_disable="notify_disable"
@skipCurrent="skipCurrent" @notify_enable="notify_enable"
@moveUp="moveUp"
@waitingRoomToQueue="waitingRoomToQueue"
/> />
<WelcomeReveal <WelcomeReveal
v-if="!state.joined" v-if="!state.joined"

View file

@ -4,18 +4,22 @@ import QueueDesktop from './QueueDesktop.vue'
import RecentDesktop from './RecentDesktop.vue' import RecentDesktop from './RecentDesktop.vue'
const props = defineProps(['state']); const props = defineProps(['state']);
const emit = defineEmits(['update:searchTerm', 'search', 'append', 'skip', 'skipCurrent', 'moveUp', 'waitingRoomToQueue']) const emit = defineEmits(['update:searchTerm', 'search', 'append', 'skip', 'skipCurrent', 'moveUp', 'waitingRoomToQueue', 'notify_disable', 'notify_enable'])
</script> </script>
<template> <template>
<div class="splitter"> <div class="splitter">
<SearchDesktop :search="state.search" :searching="state.searching" @update:searchTerm="(val) => $emit('update:searchTerm', val)" @search="$emit('search')" @append="(entry) => $emit('append', entry)" /> <SearchDesktop :socket="state.socket" :search="state.search" :searching="state.searching" @update:searchTerm="(val) => $emit('update:searchTerm', val)" @search="$emit('search')" @append="(entry) => $emit('append', entry)" />
<QueueDesktop <QueueDesktop
:socket="state.socket"
:queue="state.queue" :queue="state.queue"
:waiting_room="state.waiting_room" :waiting_room="state.waiting_room"
:waiting_room_policy="state.waiting_room_policy" :waiting_room_policy="state.waiting_room_policy"
:admin="state.admin" :admin="state.admin"
:notify_me="state.notify_me"
@notify_enable="(uuid) => $emit('notify_enable', uuid)"
@notify_disable="(uuid) => $emit('notify_disable', uuid)"
@skip="(uuid) => $emit('skip', uuid)" @skip="(uuid) => $emit('skip', uuid)"
@moveUp="(uuid) => $emit('moveUp', uuid)" @moveUp="(uuid) => $emit('moveUp', uuid)"
@skipCurrent="$emit('skipCurrent')" @skipCurrent="$emit('skipCurrent')"

View file

@ -1,13 +1,13 @@
<script setup> <script setup>
import { computed } from 'vue' import { computed } from 'vue'
const props = defineProps(['admin', 'entry', 'current', 'firstStartedAt', 'offset', 'currentTime', 'waitingRoom']) const props = defineProps(['socket', 'admin', 'entry', 'current', 'firstStartedAt', 'offset', 'currentTime', 'waitingRoom', 'isQueue', 'notify_me'])
const emits = defineEmits(['skip', 'skipCurrent', 'moveUp', 'waitingRoomToQueue']) const emits = defineEmits(['moveUp', 'waitingRoomToQueue', 'notify_enable', 'notify_disable'])
function skip() { function skip() {
if(props.current) { if(props.current) {
emits("skipCurrent") props.socket.emit("skip-current")
} else { } else {
emits("skip", props.entry.uuid) props.socket.emit("skip", {"uuid": props.entry.uuid})
} }
} }
@ -32,6 +32,10 @@ const eta = computed(() =>{
<div class="cell" :class="{'small-9': admin}"> <div class="cell" :class="{'small-9': admin}">
<span class="artist">{{ entry.artist }}</span> <span class="artist">{{ entry.artist }}</span>
<span class="title">{{ entry.title }}</span><br /> <span class="title">{{ entry.title }}</span><br />
<span v-if="!current && !waitingRoom && isQueue" class="notify">
<font-awesome-icon :icon="['far', 'bell']" v-if="notify_me.indexOf(entry.uuid) === -1" @click="$emit('notify_enable', entry.uuid)"/>
<font-awesome-icon :icon="['fas', 'bell']" v-if="notify_me.indexOf(entry.uuid) !== -1" @click="$emit('notify_disable', entry.uuid)"/>
</span>
<span class="performer">{{ entry.performer }}</span> <span class="performer">{{ entry.performer }}</span>
<span v-if="!current && !waitingRoom" class="eta">{{ eta }}</span> <span v-if="!current && !waitingRoom" class="eta">{{ eta }}</span>
</div> </div>
@ -42,13 +46,13 @@ const eta = computed(() =>{
<button <button
class="button success fright" class="button success fright"
v-if="waitingRoom" v-if="waitingRoom"
@click="$emit('waitingRoomToQueue', entry.uuid)" > @click="socket.emit('waiting-room-to-queue', {'uuid': entry.uuid})" >
<font-awesome-icon icon="fa-solid fa-arrows-up-to-line" /> <font-awesome-icon icon="fa-solid fa-arrows-up-to-line" />
</button> </button>
<button <button
class="button warning fright" class="button warning fright"
v-if="!current && !waitingRoom" v-if="!current && !waitingRoom"
@click="$emit('moveUp', entry.uuid)" > @click="socket.emit('move-up', {'uuid': entry.uuid})" >
<font-awesome-icon icon="fa-solid fa-arrow-up" /> <font-awesome-icon icon="fa-solid fa-arrow-up" />
</button> </button>
</div> </div>
@ -62,6 +66,11 @@ const eta = computed(() =>{
background-color: #008000 !important; background-color: #008000 !important;
} }
.notify {
display: inline;
margin-right: 10px;
}
.current::before, #large-current::before{ .current::before, #large-current::before{
content: "Now Playing"; content: "Now Playing";
text-align: center; text-align: center;

View file

@ -5,7 +5,7 @@ import RecentTab from './RecentTab.vue'
import TabHeader from './TabHeader.vue' import TabHeader from './TabHeader.vue'
const props = defineProps(['state']); const props = defineProps(['state']);
const emit = defineEmits(['update:searchTerm', 'search', 'append', 'skip', 'skipCurrent', 'moveUp', 'waitingRoomToQueue']) const emit = defineEmits(['update:searchTerm', 'search', 'append', 'skip', 'skipCurrent', 'moveUp', 'waitingRoomToQueue', 'notify_enable', 'notify_disable'])
</script> </script>
@ -18,12 +18,16 @@ const emit = defineEmits(['update:searchTerm', 'search', 'append', 'skip', 'skip
<TabHeader link="#recent-list" icon="fa-history" /> <TabHeader link="#recent-list" icon="fa-history" />
</div> </div>
<div class="tabs-container" data-tabs-content="main-tab"> <div class="tabs-container" data-tabs-content="main-tab">
<SearchTab :search="state.search" :searching="state.searching" @update:searchTerm="(val) => $emit('update:searchTerm', val)" @search="$emit('search')" @append="(entry) => $emit('append', entry)"/> <SearchTab :socket="state.socket" :search="state.search" :searching="state.searching" @update:searchTerm="(val) => $emit('update:searchTerm', val)" @search="$emit('search')" @append="(entry) => $emit('append', entry)"/>
<QueueTab <QueueTab
:socket="state.socket"
:queue="state.queue" :queue="state.queue"
:admin="state.admin" :admin="state.admin"
:waiting_room="state.waiting_room" :waiting_room="state.waiting_room"
:waiting_room_enabled="state.waiting_room_enabled" :waiting_room_enabled="state.waiting_room_enabled"
:notify_me="state.notify_me"
@notify_disable="(uuid) => $emit('notify_disable', uuid)"
@notify_enable="(uuid) => $emit('notify_enable', uuid)"
@skip="(uuid) => $emit('skip', uuid)" @skip="(uuid) => $emit('skip', uuid)"
@moveUp="(uuid) => $emit('moveUp', uuid)" @moveUp="(uuid) => $emit('moveUp', uuid)"
@skipCurrent="$emit('skipCurrent')" @skipCurrent="$emit('skipCurrent')"

View file

@ -1,18 +1,22 @@
<script setup> <script setup>
import QueueInner from './QueueInner.vue' import QueueInner from './QueueInner.vue'
const props = defineProps(['queue', 'waiting_room', 'admin', 'waiting_room_policy']); const props = defineProps(['socket','queue', 'waiting_room', 'admin', 'waiting_room_policy', 'notify_me']);
const emits = defineEmits(['skip', 'skipCurrent', 'moveUp', 'waitingRoomToQueue']) const emits = defineEmits(['skip', 'skipCurrent', 'moveUp', 'waitingRoomToQueue', 'notify_disable', 'notify_enable'])
</script> </script>
<template> <template>
<div class="comp-column"> <div class="comp-column">
<div class="header">Queue</div> <div class="header">Queue</div>
<QueueInner <QueueInner
:socket="socket"
:queue="queue" :queue="queue"
:admin="admin" :admin="admin"
:waiting_room="waiting_room" :waiting_room="waiting_room"
:waiting_room_policy="waiting_room_policy" :waiting_room_policy="waiting_room_policy"
:notify_me="notify_me"
@notify_enable="(uuid) => $emit('notify_enable', uuid)"
@notify_disable="(uuid) => $emit('notify_disable', uuid)"
@skip="(uuid) => $emit('skip', uuid)" @skip="(uuid) => $emit('skip', uuid)"
@moveUp="(uuid) => $emit('moveUp', uuid)" @moveUp="(uuid) => $emit('moveUp', uuid)"
@skipCurrent="$emit('skipCurrent')" @skipCurrent="$emit('skipCurrent')"

View file

@ -2,8 +2,8 @@
import { onMounted, reactive } from 'vue' import { onMounted, reactive } from 'vue'
import Entry from './Entry.vue' import Entry from './Entry.vue'
const props = defineProps(['queue', 'waiting_room', 'admin', 'waiting_room_policy']); const props = defineProps(['socket', 'queue', 'waiting_room', 'admin', 'waiting_room_policy', 'notify_me']);
const emits = defineEmits(['skip', 'skipCurrent', 'moveUp', 'waitingRoomToQueue']) const emits = defineEmits(['skip', 'skipCurrent', 'moveUp', 'waitingRoomToQueue', 'notify_disable', 'notify_enable'])
let currentTime = reactive({time: Date.now()}) let currentTime = reactive({time: Date.now()})
@ -31,12 +31,17 @@ function offset(index) {
<ul id="queue" class="vertical menu"> <ul id="queue" class="vertical menu">
<Entry <Entry
v-for="(entry, index) in queue" v-for="(entry, index) in queue"
:socket="socket"
:entry="entry" :entry="entry"
:current="index == 0" :current="index == 0"
:isQueue="true"
:admin="admin" :admin="admin"
:notify_me="notify_me"
:firstStartedAt="queue[0].started_at" :firstStartedAt="queue[0].started_at"
:currentTime="currentTime.time" :currentTime="currentTime.time"
:offset="offset(index)" :offset="offset(index)"
@notify_enable="(uuid) => $emit('notify_enable', uuid)"
@notify_disable="(uuid) => $emit('notify_disable', uuid)"
@skip="(uuid) => $emit('skip', uuid)" @skip="(uuid) => $emit('skip', uuid)"
@skipCurrent="$emit('skipCurrent')" @skipCurrent="$emit('skipCurrent')"
@moveUp="(uuid) => $emit('moveUp', uuid)" @moveUp="(uuid) => $emit('moveUp', uuid)"

View file

@ -1,17 +1,21 @@
<script setup> <script setup>
import QueueInner from './QueueInner.vue' import QueueInner from './QueueInner.vue'
const props = defineProps(['queue', 'waiting_room', 'admin', 'waiting_room_policy']); const props = defineProps(['socket','queue', 'waiting_room', 'admin', 'waiting_room_policy', 'notify_me']);
const emits = defineEmits(['skip', 'skipCurrent', 'moveUp', 'waitingRoomToQueue']) const emits = defineEmits(['skip', 'skipCurrent', 'moveUp', 'waitingRoomToQueue', 'notify_enable', 'notify_disable'])
</script> </script>
<template> <template>
<div class="tabs-panel" id="queue-list"> <div class="tabs-panel" id="queue-list">
<QueueInner <QueueInner
:socket="socket"
:queue="queue" :queue="queue"
:admin="admin" :admin="admin"
:waiting_room="waiting_room" :waiting_room="waiting_room"
:waiting_room_policy="waiting_room_policy" :waiting_room_policy="waiting_room_policy"
:notify_me="notify_me"
@notify_disable="(uuid) => $emit('notify_disable', uuid)"
@notify_enable="(uuid) => $emit('notify_enable', uuid)"
@skip="(uuid) => $emit('skip', uuid)" @skip="(uuid) => $emit('skip', uuid)"
@moveUp="(uuid) => $emit('moveUp', uuid)" @moveUp="(uuid) => $emit('moveUp', uuid)"
@skipCurrent="$emit('skipCurrent')" @skipCurrent="$emit('skipCurrent')"

View file

@ -2,14 +2,14 @@
import SearchBar from './SearchBar.vue' import SearchBar from './SearchBar.vue'
import SearchResults from './SearchResults.vue' import SearchResults from './SearchResults.vue'
const props = defineProps(['search', 'searching']); const props = defineProps(['search', 'searching', 'socket']);
const emit = defineEmits(['update:searchTerm', 'search', 'append']) const emit = defineEmits(['update:searchTerm', 'search', 'append'])
</script> </script>
<template> <template>
<div class="tabs-panel is-active" id="simplesearch"> <div class="tabs-panel is-active" id="simplesearch">
<div class="vsplit"> <div class="vsplit">
<SearchBar :searchTerm="search.searchTerm" @update:searchTerm="(val) => $emit('update:searchTerm', val)" @search="$emit('search')" @append="(entry) => $emit('append', entry)" /> <SearchBar :socket="socket" :searchTerm="search.searchTerm" @update:searchTerm="(val) => $emit('update:searchTerm', val)" @search="$emit('search')" @append="(entry) => $emit('append', entry)" />
<SearchResults :searchResults="search.searchResults" :searching="searching" @append="(entry) => $emit('append', entry)" /> <SearchResults :searchResults="search.searchResults" :searching="searching" @append="(entry) => $emit('append', entry)" />
</div> </div>
</div> </div>

View file

@ -6,7 +6,8 @@ import App from './App.vue'
import Main from './Main.vue' import Main from './Main.vue'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { faMagnifyingGlass, faList, faChair, faArrowUp, faHistory, faPlus, faStepForward, faTimes, faArrowsUpToLine } from '@fortawesome/free-solid-svg-icons' import { faMagnifyingGlass, faList, faChair, faArrowUp, faHistory, faPlus, faStepForward, faTimes, faArrowsUpToLine, faBell } from '@fortawesome/free-solid-svg-icons'
import { faBell as farBell } from '@fortawesome/free-regular-svg-icons'
import { faYoutube } from '@fortawesome/free-brands-svg-icons' import { faYoutube } from '@fortawesome/free-brands-svg-icons'
import 'foundation-sites/dist/css/foundation.min.css' import 'foundation-sites/dist/css/foundation.min.css'
@ -21,6 +22,8 @@ library.add(faTimes)
library.add(faArrowUp) library.add(faArrowUp)
library.add(faChair) library.add(faChair)
library.add(faArrowsUpToLine) library.add(faArrowsUpToLine)
library.add(faBell)
library.add(farBell)
window.jQuery = jquery; window.jQuery = jquery;
window.$ = jquery; window.$ = jquery;