diff --git a/package.json b/package.json index 5a6f482..420e0cd 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "marked": "^4.0.16", "ovenplayer": "~0.10.25", "pretty-ms": "^8.0.0", + "tus-js-client": "^3.1.0", "vue": "^2.6.11", "vue-chat-scroll": "^1.4.0", "vue-masonry-css": "^1.0.3", diff --git a/src/components/AdminDrawer.vue b/src/components/AdminDrawer.vue index 9fbb7e5..a910f77 100644 --- a/src/components/AdminDrawer.vue +++ b/src/components/AdminDrawer.vue @@ -8,10 +8,17 @@ > - - - {{ channel.title.slice(0, 2) }} - + + + + {{ channel.title.slice(0, 2) }} + @@ -25,7 +32,7 @@ @@ -68,7 +75,7 @@ :to="{ name: 'AdminChannel', params: { channelid: channel.id } }" > - + {{ channel.title.slice(0, 2) }} @@ -93,7 +100,10 @@ v-for="item in channelMenu" :key="item.name" link - :to="{ name: item.name, params: { channelid: selectionAdminChannel } }" + :to="{ + name: item.name, + params: { channel: channel }, + }" > {{ item.icon }} diff --git a/src/components/Poster.vue b/src/components/Poster.vue index ba521d2..d309439 100644 --- a/src/components/Poster.vue +++ b/src/components/Poster.vue @@ -19,7 +19,7 @@ + + + Upload + + + + + + + + + + + + + + Cancel + Upload + + + + + + diff --git a/src/components/VideoPlayer.vue b/src/components/VideoPlayer.vue index 78619ca..dcc7409 100644 --- a/src/components/VideoPlayer.vue +++ b/src/components/VideoPlayer.vue @@ -18,7 +18,7 @@ export default { // Disabled as source is now passed as a prop from parent component // source: this.source, options: { - image: this.poster, + image: this.poster.url, autoStart: this.autostart, sources: this.sources, hlsConfig: { diff --git a/src/router/index.js b/src/router/index.js index 413487a..8ef8b6d 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -8,11 +8,13 @@ import Stats from "@/views/Admin/Stats.vue" import Server from "@/views/Admin/Server.vue" import About from "@/views/Admin/About.vue" import GlobalStreamSchedule from "@/views/Admin/GlobalStreamSchedule.vue" + // for channel import ChannelDistribution from "@/views/Admin/ChannelDistribution.vue" import StreamSchedule from "@/views/Admin/StreamSchedule.vue" import AdminChannelLive from "@/views/Admin/ChannelLive.vue" -import ChannelEdit from "@/views/Admin/ChannelEdit.vue" +// import ChannelEdit from "@/views/Admin/ChannelEdit.vue" +import ChannelProfile from "@/views/Admin/ChannelProfile.vue" import StreamEdit from "@/views/Admin/StreamEdit.vue" import ChannelRecordings from "@/views/Admin/ChannelRecordings.vue" import RecordingEdit from "@/views/Admin/RecordingEdit.vue" @@ -94,7 +96,7 @@ const routes = [ { path: "add", name: "ChannelAdd", - component: ChannelEdit, + component: ChannelProfile, }, { path: "stats", @@ -129,10 +131,10 @@ const routes = [ component: AdminChannelLive, props: true, }, - { - path: "edit", - name: "ChannelEdit", - component: ChannelEdit, + { + path: "profile", + name: "ChannelProfile", + component: ChannelProfile, props: true, }, { diff --git a/src/services/api.js b/src/services/api.js index dfa7fb6..d61505e 100644 --- a/src/services/api.js +++ b/src/services/api.js @@ -1,4 +1,5 @@ import axios from 'axios'; +import * as tus from 'tus-js-client'; import { config } from "../../config.js"; import { store } from "./store.js"; @@ -22,6 +23,36 @@ function delay(resp) { return new Promise(resolve => setTimeout(() => resolve(resp), 300)); } +function tusUploader(file, endpoint, onSuccess, onProgress, onError) { + const upload = new tus.Upload(file, { + endpoint: endpoint, + // retryDelays: [0, 3000, 5000, 10000, 20000], + retryDelays: [0], + metadata: { + filename: file.name, + filetype: file.type + }, + onError: onError, + onProgress: function (bytesUploaded, bytesTotal) { + var percentage = (bytesUploaded / bytesTotal * 100).toFixed(2) + onProgress(percentage, bytesUploaded, bytesTotal), + console.log(bytesUploaded, bytesTotal, percentage + "%") + }, + onSuccess: onSuccess, + }) + + // Check if there are any previous uploads to continue. + upload.findPreviousUploads().then(function (previousUploads) { + // Found previous uploads so we select the first one. + if (previousUploads.length) { + upload.resumeFromPreviousUpload(previousUploads[0]) + } + + // Start the upload + upload.start() + }) + return upload +} export const api = { Or(f, params, flat = true) { @@ -52,6 +83,9 @@ export const api = { Save(channelID, channel) { return axios.put(new URL(config.apiURL + "/channel/" + channelID), channel) }, + LogoUploader(channelID, file, onSuccess, onProgress, onError) { + return tusUploader(file, new URL(config.apiURL + "/channel/" + channelID + "/logo"), onSuccess, onProgress, onError) + }, Delete(channelID) { return axios.delete(new URL(config.apiURL + "/channel/" + channelID)) }, diff --git a/src/views/Admin/ChannelEvents.vue b/src/views/Admin/ChannelEvents.vue index 83e06ba..d21d4ec 100644 --- a/src/views/Admin/ChannelEvents.vue +++ b/src/views/Admin/ChannelEvents.vue @@ -48,7 +48,7 @@ - + {{ item.name }} diff --git a/src/views/Admin/ChannelLive.vue b/src/views/Admin/ChannelLive.vue index e55a601..b3ccc7f 100644 --- a/src/views/Admin/ChannelLive.vue +++ b/src/views/Admin/ChannelLive.vue @@ -171,7 +171,7 @@ export default { api.Channels.GetStream(this.channelid).then( (resp) => { this.video = resp.data; - if (this.video.poster == "") { + if (this.video.poster) { this.video.poster = resp.data.channel.logo; } }, diff --git a/src/views/Admin/ChannelProfile.vue b/src/views/Admin/ChannelProfile.vue index d634162..d400684 100644 --- a/src/views/Admin/ChannelProfile.vue +++ b/src/views/Admin/ChannelProfile.vue @@ -1,80 +1,108 @@ @@ -130,19 +168,23 @@ import { mapGetters } from "vuex"; import { api } from "@/services/api.js"; -import { config } from "../../../config.js"; // ingressURLs +import UploadDialog from "@/components/UploadDialog.vue"; export default { name: "ChannelProfile", + components: { + UploadDialog, + }, props: ["channelid"], data() { return { - ingressRTMP: config.ingressURL.rtmp, - ingressWS: config.ingressURL.ws, + ingressRTMP: "", + ingressWS: "", channel: {}, channelFormDefault: {}, enableSave: false, confirmRemove: false, + showUploadDialog: false, }; }, computed: { @@ -184,10 +226,31 @@ export default { this.channel = Object.assign({}, this.channelFormDefault); return; } - api.Channels.Get(this.channelid).then( - (response) => (this.channel = response.data) - ); + api.Channels.Get(this.channelid).then((response) => { + this.channel = response.data.data; + this.ingressRTMP = response.data.ingress.rtmp; + this.ingressWS = response.data.ingress.webrtc; + }); + }, + closeUploadDialog(v) { + this.showUploadDialog = v; }, }, }; + + \ No newline at end of file diff --git a/src/views/Admin/ChannelRecordings.vue b/src/views/Admin/ChannelRecordings.vue index 17ddc97..80d9831 100644 --- a/src/views/Admin/ChannelRecordings.vue +++ b/src/views/Admin/ChannelRecordings.vue @@ -69,7 +69,7 @@ >