mirror of
https://github.com/AzuraCast/AzuraCast.git
synced 2024-06-14 05:06:37 +00:00
Vue 3 WIP
This commit is contained in:
parent
37dc95b7d9
commit
a4e1f15e47
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"vueCompilerOptions": {
|
"vueCompilerOptions": {
|
||||||
"target": 2.7
|
"target": 3.2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
873
frontend/npm-shrinkwrap.json
generated
873
frontend/npm-shrinkwrap.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -16,7 +16,9 @@
|
||||||
"@fullcalendar/daygrid": "^5.9.0",
|
"@fullcalendar/daygrid": "^5.9.0",
|
||||||
"@fullcalendar/luxon2": "^5.10.2",
|
"@fullcalendar/luxon2": "^5.10.2",
|
||||||
"@fullcalendar/timegrid": "^5.9.0",
|
"@fullcalendar/timegrid": "^5.9.0",
|
||||||
"@fullcalendar/vue": "^5.9.0",
|
"@fullcalendar/vue3": "^5.11",
|
||||||
|
"@vue-leaflet/vue-leaflet": "*",
|
||||||
|
"@vue/compat": "^3.2.45",
|
||||||
"@vuelidate/core": "^2.0.0",
|
"@vuelidate/core": "^2.0.0",
|
||||||
"@vuelidate/validators": "^2.0.0",
|
"@vuelidate/validators": "^2.0.0",
|
||||||
"axios": "^1",
|
"axios": "^1",
|
||||||
|
@ -61,14 +63,12 @@
|
||||||
"sass-loader": "^13",
|
"sass-loader": "^13",
|
||||||
"store": "^2",
|
"store": "^2",
|
||||||
"sweetalert2": "11.4.8",
|
"sweetalert2": "11.4.8",
|
||||||
"vue": "^2 <3",
|
"vue": "^3.2",
|
||||||
"vue-axios": "^2 <3",
|
"vue-axios": "^3.5",
|
||||||
"vue-clipboard2": "^0.3.3",
|
"vue-clipboard2": "^0.3.3",
|
||||||
"vue-gettext": "^2.1.12",
|
"vue-gettext": "^2.1.12",
|
||||||
"vue-loader": "^15 <16",
|
"vue-loader": "^17",
|
||||||
"vue2-daterange-picker": "^0.6.6",
|
"vue3-daterange-picker": "^1",
|
||||||
"vue2-leaflet": "^2.7.1",
|
|
||||||
"vue2-leaflet-fullscreen": "^1.0.1",
|
|
||||||
"vuedraggable": "^2.24.1",
|
"vuedraggable": "^2.24.1",
|
||||||
"wavesurfer.js": "^6",
|
"wavesurfer.js": "^6",
|
||||||
"webpack": "^5.52.1",
|
"webpack": "^5.52.1",
|
||||||
|
|
469
frontend/scss/vendors/_daterangepicker.scss
vendored
Normal file
469
frontend/scss/vendors/_daterangepicker.scss
vendored
Normal file
|
@ -0,0 +1,469 @@
|
||||||
|
$ranges-hover-bg-color: #eee !default;
|
||||||
|
$ranges-hover-text-color: #000 !default;
|
||||||
|
$ranges-active-bg-color: #08c !default;
|
||||||
|
$ranges-active-text-color: #fff !default;
|
||||||
|
|
||||||
|
//Apply/OK buttons
|
||||||
|
$primary-button-bg: #28a745 !default;
|
||||||
|
$primary-button-color: #fff !default;
|
||||||
|
//Cancel button
|
||||||
|
$secondary-button-bg: #6c757d !default;
|
||||||
|
$secondary-button-color: #fff !default;
|
||||||
|
|
||||||
|
$btn-border-width: 1px;
|
||||||
|
|
||||||
|
.daterangepicker {
|
||||||
|
|
||||||
|
.ranges {
|
||||||
|
text-align: left;
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ranges ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ranges li {
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ranges li:hover {
|
||||||
|
background-color: $ranges-hover-bg-color;
|
||||||
|
color: $ranges-hover-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ranges li.active {
|
||||||
|
background-color: $ranges-active-bg-color;
|
||||||
|
color: $ranges-active-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.monthselect, .yearselect {
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 1px;
|
||||||
|
height: auto;
|
||||||
|
margin: 0;
|
||||||
|
cursor: default;
|
||||||
|
width: calc(50% - 1rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.monthselect {
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-time {
|
||||||
|
text-align: center;
|
||||||
|
margin: 4px auto 0 auto;
|
||||||
|
line-height: 30px;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-time select.disabled {
|
||||||
|
color: #ccc;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
select.hourselect, select.minuteselect, select.secondselect, select.ampmselect {
|
||||||
|
width: 50px;
|
||||||
|
margin: 2px;
|
||||||
|
background: #eee;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
padding: 2px;
|
||||||
|
outline: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@import "variables";
|
||||||
|
|
||||||
|
.drp-buttons .btn {
|
||||||
|
margin-left: 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 4px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
display: inline-block;
|
||||||
|
//font-family: $btn-font-family;
|
||||||
|
//font-weight: $btn-font-weight;
|
||||||
|
//color: $body-color;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
user-select: none;
|
||||||
|
background-color: transparent;
|
||||||
|
border: $btn-border-width solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-success, .btn-primary {
|
||||||
|
background-color: $primary-button-bg;
|
||||||
|
color: $primary-button-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
background-color: $secondary-button-bg;
|
||||||
|
color: $secondary-button-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vue-daterange-picker {
|
||||||
|
*, ::after, ::before {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.drp-calendar .col .left {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker {
|
||||||
|
&.hide-calendars.show-ranges {
|
||||||
|
.ranges {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
ul {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendars-container {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker[readonly] {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
//imported
|
||||||
|
.daterangepicker {
|
||||||
|
position: absolute;
|
||||||
|
color: inherit;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
width: 278px;
|
||||||
|
max-width: none;
|
||||||
|
padding: 0;
|
||||||
|
margin-top: 7px;
|
||||||
|
top: 100px;
|
||||||
|
left: 20px;
|
||||||
|
z-index: 3001;
|
||||||
|
display: none;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker:before, .daterangepicker:after {
|
||||||
|
position: absolute;
|
||||||
|
display: inline-block;
|
||||||
|
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker:before {
|
||||||
|
top: -7px;
|
||||||
|
border-right: 7px solid transparent;
|
||||||
|
border-left: 7px solid transparent;
|
||||||
|
border-bottom: 7px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker:after {
|
||||||
|
top: -6px;
|
||||||
|
border-right: 6px solid transparent;
|
||||||
|
border-bottom: 6px solid #fff;
|
||||||
|
border-left: 6px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker.opensleft:before {
|
||||||
|
right: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker.opensleft:after {
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker.openscenter:before {
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 0;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker.openscenter:after {
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 0;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker.opensright:before {
|
||||||
|
left: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker.opensright:after {
|
||||||
|
left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker.drop-up {
|
||||||
|
margin-top: -7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker.drop-up:before {
|
||||||
|
top: initial;
|
||||||
|
bottom: -7px;
|
||||||
|
border-bottom: initial;
|
||||||
|
border-top: 7px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker.drop-up:after {
|
||||||
|
top: initial;
|
||||||
|
bottom: -6px;
|
||||||
|
border-bottom: initial;
|
||||||
|
border-top: 6px solid #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker.single .drp-selected {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker.show-calendar .drp-calendar {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker.show-calendar .drp-buttons {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker.auto-apply .drp-buttons {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker .drp-calendar {
|
||||||
|
display: none;
|
||||||
|
max-width: 270px;
|
||||||
|
width: 270px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker .drp-calendar.left {
|
||||||
|
padding: 8px 0 8px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker .drp-calendar.right {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker .drp-calendar.single .calendar-table {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker .calendar-table .next span, .daterangepicker .calendar-table .prev span {
|
||||||
|
color: #fff;
|
||||||
|
border: solid black;
|
||||||
|
border-width: 0 2px 2px 0;
|
||||||
|
border-radius: 0;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker .calendar-table .next span {
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
-webkit-transform: rotate(-45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker .calendar-table .prev span {
|
||||||
|
transform: rotate(135deg);
|
||||||
|
-webkit-transform: rotate(135deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker .calendar-table th, .daterangepicker .calendar-table td {
|
||||||
|
white-space: nowrap;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
min-width: 32px;
|
||||||
|
width: 32px;
|
||||||
|
height: 24px;
|
||||||
|
line-height: 24px;
|
||||||
|
font-size: 12px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker .calendar-table {
|
||||||
|
border: 1px solid #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker .calendar-table table {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
border-spacing: 0;
|
||||||
|
border-collapse: collapse;
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker td.available:hover, .daterangepicker th.available:hover {
|
||||||
|
background-color: #eee;
|
||||||
|
border-color: transparent;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker td.week, .daterangepicker th.week {
|
||||||
|
font-size: 80%;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker td.off, .daterangepicker td.off.in-range, .daterangepicker td.off.start-date, .daterangepicker td.off.end-date {
|
||||||
|
background-color: #fff;
|
||||||
|
border-color: transparent;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker td.in-range {
|
||||||
|
background-color: #ebf4f8;
|
||||||
|
border-color: transparent;
|
||||||
|
color: #000;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker td.start-date {
|
||||||
|
border-radius: 4px 0 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker td.end-date {
|
||||||
|
border-radius: 0 4px 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker td.start-date.end-date {
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker td.active, .daterangepicker td.active:hover {
|
||||||
|
background-color: #357ebd;
|
||||||
|
border-color: transparent;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker th.month {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker td.disabled, .daterangepicker option.disabled {
|
||||||
|
color: #999;
|
||||||
|
cursor: not-allowed;
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker select.yearselect {
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker .drp-buttons {
|
||||||
|
clear: both;
|
||||||
|
text-align: right;
|
||||||
|
padding: 8px;
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
display: none;
|
||||||
|
line-height: 12px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker .drp-selected {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 12px;
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.daterangepicker.show-ranges .drp-calendar.left {
|
||||||
|
border-left: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.daterangepicker.show-calendar .ranges {
|
||||||
|
margin-top: 8px;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Larger Screen Styling */
|
||||||
|
@media (min-width: 564px) {
|
||||||
|
.daterangepicker {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
.daterangepicker .ranges ul {
|
||||||
|
width: 140px;
|
||||||
|
}
|
||||||
|
.daterangepicker.single .ranges ul {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.daterangepicker.single .drp-calendar.left {
|
||||||
|
clear: none;
|
||||||
|
}
|
||||||
|
.daterangepicker.ltr {
|
||||||
|
direction: ltr;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.daterangepicker.ltr .drp-calendar.left {
|
||||||
|
clear: left;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
.daterangepicker.ltr .drp-calendar.left .calendar-table {
|
||||||
|
border-right: none;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
.daterangepicker.ltr .drp-calendar.right {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
.daterangepicker.ltr .drp-calendar.right .calendar-table {
|
||||||
|
border-left: none;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
}
|
||||||
|
.daterangepicker.ltr .drp-calendar.left .calendar-table {
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
|
.daterangepicker.rtl {
|
||||||
|
direction: rtl;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.daterangepicker.rtl .drp-calendar.left {
|
||||||
|
clear: right;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
.daterangepicker.rtl .drp-calendar.left .calendar-table {
|
||||||
|
border-left: none;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
}
|
||||||
|
.daterangepicker.rtl .drp-calendar.right {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
.daterangepicker.rtl .drp-calendar.right .calendar-table {
|
||||||
|
border-right: none;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
.daterangepicker.rtl .drp-calendar.left .calendar-table {
|
||||||
|
padding-left: 12px;
|
||||||
|
}
|
||||||
|
.daterangepicker.rtl .ranges, .daterangepicker.rtl .drp-calendar {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 730px) {
|
||||||
|
.daterangepicker .drp-calendar.left {
|
||||||
|
clear: none !important;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,70 +1,65 @@
|
||||||
import Vue from 'vue';
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import VueAxios from 'vue-axios';
|
import VueAxios from 'vue-axios';
|
||||||
import GetTextPlugin from 'vue-gettext';
|
import GetTextPlugin from 'vue-gettext';
|
||||||
import translations from '../../translations/translations.json';
|
import translations from '../../translations/translations.json';
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
export default function (vueApp) {
|
||||||
// Configure localization
|
return function (el, props) {
|
||||||
Vue.use(GetTextPlugin, {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
defaultLanguage: 'en_US',
|
// Configure localization
|
||||||
translations: translations,
|
vueApp.use(GetTextPlugin, {
|
||||||
silent: true
|
defaultLanguage: 'en_US',
|
||||||
});
|
translations: translations,
|
||||||
|
silent: true
|
||||||
|
});
|
||||||
|
|
||||||
if (typeof App.locale !== 'undefined') {
|
if (typeof App.locale !== 'undefined') {
|
||||||
Vue.config.language = App.locale;
|
vueApp.config.language = App.locale;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure auto-CSRF on requests
|
// Configure auto-CSRF on requests
|
||||||
if (typeof App.api_csrf !== 'undefined') {
|
if (typeof App.api_csrf !== 'undefined') {
|
||||||
axios.defaults.headers.common['X-API-CSRF'] = App.api_csrf;
|
axios.defaults.headers.common['X-API-CSRF'] = App.api_csrf;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.use(VueAxios, axios);
|
vueApp.use(VueAxios, axios);
|
||||||
|
|
||||||
Vue.prototype.$eventHub = new Vue();
|
|
||||||
});
|
|
||||||
|
|
||||||
export default function (component) {
|
|
||||||
return function (el, props) {
|
|
||||||
return new Vue({
|
|
||||||
el: el,
|
|
||||||
created () {
|
|
||||||
let handleAxiosError = (error) => {
|
|
||||||
let notifyMessage = this.$gettext('An error occurred and your request could not be completed.');
|
|
||||||
if (error.response) {
|
|
||||||
// Request made and server responded
|
|
||||||
notifyMessage = error.response.data.message;
|
|
||||||
console.error(notifyMessage);
|
|
||||||
} else if (error.request) {
|
|
||||||
// The request was made but no response was received
|
|
||||||
console.error(error.request);
|
|
||||||
} else {
|
|
||||||
// Something happened in setting up the request that triggered an Error
|
|
||||||
console.error('Error', error.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof this.$notifyError === 'function') {
|
|
||||||
this.$notifyError(notifyMessage);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
axios.interceptors.request.use((config) => {
|
|
||||||
return config;
|
|
||||||
}, (error) => {
|
|
||||||
handleAxiosError(error);
|
|
||||||
return Promise.reject(error);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
axios.interceptors.response.use((response) => {
|
vueApp.created(() => {
|
||||||
return response;
|
let handleAxiosError = (error) => {
|
||||||
}, (error) => {
|
let notifyMessage = this.$gettext('An error occurred and your request could not be completed.');
|
||||||
handleAxiosError(error);
|
if (error.response) {
|
||||||
return Promise.reject(error);
|
// Request made and server responded
|
||||||
|
notifyMessage = error.response.data.message;
|
||||||
|
console.error(notifyMessage);
|
||||||
|
} else if (error.request) {
|
||||||
|
// The request was made but no response was received
|
||||||
|
console.error(error.request);
|
||||||
|
} else {
|
||||||
|
// Something happened in setting up the request that triggered an Error
|
||||||
|
console.error('Error', error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof this.$notifyError === 'function') {
|
||||||
|
this.$notifyError(notifyMessage);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
axios.interceptors.request.use((config) => {
|
||||||
|
return config;
|
||||||
|
}, (error) => {
|
||||||
|
handleAxiosError(error);
|
||||||
|
return Promise.reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
axios.interceptors.response.use((response) => {
|
||||||
|
return response;
|
||||||
|
}, (error) => {
|
||||||
|
handleAxiosError(error);
|
||||||
|
return Promise.reject(error);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
|
||||||
render: createElement => createElement(component, { props: props })
|
vueApp.mount(el, {props: props});
|
||||||
});
|
};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<permissions-form-station-row
|
<permissions-form-station-row
|
||||||
v-for="(row, index) in form.permissions.$model.station" :key="index"
|
v-for="(row, index) in form.permissions.$model.station" :key="index"
|
||||||
:stations="stations" :station-permissions="stationPermissions"
|
:stations="stations" :station-permissions="stationPermissions"
|
||||||
:row.sync="row" @remove="remove(index)"
|
v-model:row="form.permissions.$model.station[index]" @remove="remove(index)"
|
||||||
></permissions-form-station-row>
|
></permissions-form-station-row>
|
||||||
|
|
||||||
<b-button-group v-if="hasRemainingStations">
|
<b-button-group v-if="hasRemainingStations">
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
</data-table>
|
</data-table>
|
||||||
</b-card>
|
</b-card>
|
||||||
|
|
||||||
<admin-stations-edit-modal ref="editModal" :create-url="listUrl" v-bind="$props"
|
<admin-stations-edit-modal v-bind="$props" ref="editModal" :create-url="listUrl"
|
||||||
@relist="relist"></admin-stations-edit-modal>
|
@relist="relist"></admin-stations-edit-modal>
|
||||||
|
|
||||||
<admin-stations-clone-modal ref="cloneModal" @relist="relist"></admin-stations-clone-modal>
|
<admin-stations-clone-modal ref="cloneModal" @relist="relist"></admin-stations-clone-modal>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<b-modal size="lg" id="station_edit_modal" ref="modal" :title="langTitle" :busy="loading"
|
<b-modal size="lg" id="station_edit_modal" ref="modal" :title="langTitle" :busy="loading"
|
||||||
@shown="resetForm" @hidden="clearContents">
|
@shown="resetForm" @hidden="clearContents">
|
||||||
<admin-stations-form ref="form" v-bind="$props" is-modal :create-url="createUrl" :edit-url="editUrl"
|
<admin-stations-form v-bind="$props" ref="form" is-modal :create-url="createUrl" :edit-url="editUrl"
|
||||||
:is-edit-mode="isEditMode" @error="close" @submitted="onSubmit"
|
:is-edit-mode="isEditMode" @error="close" @submitted="onSubmit"
|
||||||
@validUpdate="onValidUpdate" @loadingUpdate="onLoadingUpdate">
|
@validUpdate="onValidUpdate" @loadingUpdate="onLoadingUpdate">
|
||||||
<template #submitButton>
|
<template #submitButton>
|
||||||
|
|
|
@ -60,14 +60,14 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="datatable-main">
|
<div class="datatable-main">
|
||||||
<b-table ref="table" show-empty striped hover :selectable="selectable" :api-url="apiUrl" :per-page="perPage"
|
<b-table ref="table" show-empty striped hover :selectable="selectable" :api-url="apiUrl" :per-page="perPage"
|
||||||
:current-page.sync="currentPage" @row-selected="onRowSelected" :items="itemProvider"
|
v-model:current-page="currentPage" @row-selected="onRowSelected" :items="itemProvider"
|
||||||
:fields="visibleFields"
|
:fields="visibleFields"
|
||||||
:empty-text="langNoRecords" :empty-filtered-text="langNoRecords" :responsive="responsive"
|
:empty-text="langNoRecords" :empty-filtered-text="langNoRecords" :responsive="responsive"
|
||||||
:no-provider-paging="handleClientSide" :no-provider-sorting="handleClientSide"
|
:no-provider-paging="handleClientSide" :no-provider-sorting="handleClientSide"
|
||||||
:no-provider-filtering="handleClientSide"
|
:no-provider-filtering="handleClientSide"
|
||||||
tbody-tr-class="align-middle" thead-tr-class="align-middle" selected-variant=""
|
tbody-tr-class="align-middle" thead-tr-class="align-middle" selected-variant=""
|
||||||
:filter="filter" @filtered="onFiltered" @refreshed="onRefreshed"
|
:filter="filter" @filtered="onFiltered" @refreshed="onRefreshed"
|
||||||
:sort-by.sync="sortBy" :sort-desc.sync="sortDesc" @sort-changed="onSortChanged">
|
v-model:sort-by="sortBy" v-model:sort-desc="sortDesc" @sort-changed="onSortChanged">
|
||||||
<template #head(selected)="data">
|
<template #head(selected)="data">
|
||||||
<b-form-checkbox :aria-label="langSelectAll" :checked="allSelected"
|
<b-form-checkbox :aria-label="langSelectAll" :checked="allSelected"
|
||||||
@change="toggleSelected"></b-form-checkbox>
|
@change="toggleSelected"></b-form-checkbox>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<date-range-picker
|
<date-range-picker
|
||||||
ref="picker" controlContainerClass="" opens="left" show-dropdowns
|
v-bind="$props" ref="picker" controlContainerClass="" opens="left" show-dropdowns
|
||||||
v-bind="$props"
|
|
||||||
:time-picker-increment="1" :ranges="ranges" @update="onUpdate">
|
:time-picker-increment="1" :ranges="ranges" @update="onUpdate">
|
||||||
<template #input="datePicker">
|
<template #input="datePicker">
|
||||||
<a class="btn btn-bg dropdown-toggle" id="reportrange" href="#" @click.prevent="">
|
<a class="btn btn-bg dropdown-toggle" id="reportrange" href="#" @click.prevent="">
|
||||||
|
@ -9,19 +8,19 @@
|
||||||
{{ datePicker.rangeText }}
|
{{ datePicker.rangeText }}
|
||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
<slot v-for="(_, name) in $slots" :name="name" :slot="name"/>
|
|
||||||
<template v-for="(_, name) in $scopedSlots" :slot="name" slot-scope="slotData">
|
<template v-for="(_, slot) of $slots" v-slot:[slot]="scope">
|
||||||
<slot :name="name" v-bind="slotData"/>
|
<slot :name="slot" v-bind="scope"></slot>
|
||||||
</template>
|
</template>
|
||||||
</date-range-picker>
|
</date-range-picker>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="css">
|
<style lang="scss">
|
||||||
@import '../../../node_modules/vue2-daterange-picker/dist/vue2-daterange-picker.css';
|
@import '../../../node_modules/vue3-daterange-picker/src/assets/daterangepicker';
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import DateRangePicker from 'vue2-daterange-picker';
|
import DateRangePicker from 'vue3-daterange-picker';
|
||||||
import Icon from "./Icon";
|
import Icon from "./Icon";
|
||||||
import {DateTime} from 'luxon';
|
import {DateTime} from 'luxon';
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flow-upload">
|
<div class="flow-upload">
|
||||||
<div class="upload-progress">
|
<div class="upload-progress">
|
||||||
<div class="uploading-file pt-1" v-for="(file, _) in files" :id="'file_upload_' + file.uniqueIdentifier"
|
<template v-for="(file, _) in files">
|
||||||
v-if="file.is_visible" :class="{ 'text-success': file.is_completed, 'text-danger': file.error }">
|
<div v-if="file.is_visible" class="uploading-file pt-1" :id="'file_upload_' + file.uniqueIdentifier"
|
||||||
<h6 class="fileuploadname m-0">{{ file.name }}</h6>
|
:class="{ 'text-success': file.is_completed, 'text-danger': file.error }">
|
||||||
<b-progress v-if="!file.is_completed" :value="file.progress_percent" :max="100"
|
<h6 class="fileuploadname m-0">{{ file.name }}</h6>
|
||||||
show-progress class="h-15 my-1"></b-progress>
|
<b-progress v-if="!file.is_completed" :value="file.progress_percent" :max="100"
|
||||||
<div class="upload-status" v-if="file.error">
|
show-progress class="h-15 my-1"></b-progress>
|
||||||
{{ file.error }}
|
<div class="upload-status" v-if="file.error">
|
||||||
|
{{ file.error }}
|
||||||
|
</div>
|
||||||
|
<div class="size">{{ formatFileSize(file.size) }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="size">{{ formatFileSize(file.size) }}</div>
|
</template>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="file-drop-target" ref="file_drop_target">
|
<div class="file-drop-target" ref="file_drop_target">
|
||||||
<translate key="lang_upload_target">Drag file(s) here to upload or</translate>
|
<translate key="lang_upload_target">Drag file(s) here to upload or</translate>
|
||||||
|
|
|
@ -27,9 +27,8 @@
|
||||||
</slot>
|
</slot>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<slot v-for="(_, name) in $slots" :name="name" :slot="name"/>
|
<template v-for="(_, slot) of filteredScopedSlots" v-slot:[slot]="scope">
|
||||||
<template v-for="(_, name) in filteredScopedSlots" :slot="name" slot-scope="slotData">
|
<slot :name="slot" v-bind="scope"></slot>
|
||||||
<slot :name="name" v-bind="slotData"/>
|
|
||||||
</template>
|
</template>
|
||||||
</b-modal>
|
</b-modal>
|
||||||
</template>
|
</template>
|
||||||
|
@ -75,7 +74,7 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
filteredScopedSlots() {
|
filteredScopedSlots() {
|
||||||
return _.filter(this.$scopedSlots, (slot, name) => {
|
return _.filter(this.$slots, (slot, name) => {
|
||||||
return !_.includes([
|
return !_.includes([
|
||||||
'default', 'modal-footer'
|
'default', 'modal-footer'
|
||||||
], name);
|
], name);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import '@fullcalendar/core/vdom';
|
import '@fullcalendar/core/vdom';
|
||||||
import FullCalendar from '@fullcalendar/vue';
|
import FullCalendar from '@fullcalendar/vue3';
|
||||||
import allLocales from '@fullcalendar/core/locales-all';
|
import allLocales from '@fullcalendar/core/locales-all';
|
||||||
import luxon2Plugin from '@fullcalendar/luxon2';
|
import luxon2Plugin from '@fullcalendar/luxon2';
|
||||||
import timeGridPlugin from '@fullcalendar/timegrid';
|
import timeGridPlugin from '@fullcalendar/timegrid';
|
||||||
|
|
|
@ -3,7 +3,7 @@ export default {
|
||||||
name: 'BFormFieldset',
|
name: 'BFormFieldset',
|
||||||
methods: {
|
methods: {
|
||||||
getSlot(name, scope = {}) {
|
getSlot(name, scope = {}) {
|
||||||
let slot = this.$scopedSlots[name] || this.$slots[name]
|
let slot = this.$slots[name]
|
||||||
return typeof slot === 'function' ? slot(scope) : slot
|
return typeof slot === 'function' ? slot(scope) : slot
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -13,9 +13,8 @@
|
||||||
<slot name="description" v-bind="slotProps"></slot>
|
<slot name="description" v-bind="slotProps"></slot>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<slot v-for="(_, name) in $slots" :name="name" :slot="name"/>
|
<template v-for="(_, slot) of filteredScopedSlots" v-slot:[slot]="scope">
|
||||||
<template v-for="(_, name) in filteredScopedSlots" :slot="name" slot-scope="slotData">
|
<slot :name="slot" v-bind="scope"></slot>
|
||||||
<slot :name="name" v-bind="slotData"/>
|
|
||||||
</template>
|
</template>
|
||||||
</b-form-group>
|
</b-form-group>
|
||||||
</template>
|
</template>
|
||||||
|
@ -33,7 +32,7 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
filteredScopedSlots() {
|
filteredScopedSlots() {
|
||||||
return _.filter(this.$scopedSlots, (slot, name) => {
|
return _.filter(this.$slots, (slot, name) => {
|
||||||
return !_.includes([
|
return !_.includes([
|
||||||
'default', 'label', 'description'
|
'default', 'label', 'description'
|
||||||
], name);
|
], name);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<b-form-group v-bind="$attrs" :label-for="id" :state="fieldState">
|
<b-form-group v-bind="$attrs" :label-for="id" :state="fieldState">
|
||||||
<template #default>
|
<template #default>
|
||||||
<slot name="default" v-bind="{ id, field, state: fieldState }">
|
<slot name="default" v-bind="{ id, field, state: fieldState }">
|
||||||
<b-form-checkbox :id="id" :name="name" v-model="field.$model" v-bind="inputAttrs">
|
<b-form-checkbox v-bind="inputAttrs" v-model="field.$model" :id="id" :name="name">
|
||||||
<slot name="label" :lang="'lang_'+id">
|
<slot name="label" :lang="'lang_'+id">
|
||||||
|
|
||||||
</slot>
|
</slot>
|
||||||
|
@ -25,9 +25,8 @@
|
||||||
<slot name="description" v-bind="slotProps" :lang="'lang_'+id+'_desc'"></slot>
|
<slot name="description" v-bind="slotProps" :lang="'lang_'+id+'_desc'"></slot>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<slot v-for="(_, name) in $slots" :name="name" :slot="name"/>
|
<template v-for="(_, slot) of filteredScopedSlots" v-slot:[slot]="scope">
|
||||||
<template v-for="(_, name) in filteredScopedSlots" :slot="name" slot-scope="slotData">
|
<slot :name="slot" v-bind="scope"></slot>
|
||||||
<slot :name="name" v-bind="slotData"/>
|
|
||||||
</template>
|
</template>
|
||||||
</b-form-group>
|
</b-form-group>
|
||||||
</template>
|
</template>
|
||||||
|
@ -64,7 +63,7 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
filteredScopedSlots() {
|
filteredScopedSlots() {
|
||||||
return _.filter(this.$scopedSlots, (slot, name) => {
|
return _.filter(this.$slots, (slot, name) => {
|
||||||
return !_.includes([
|
return !_.includes([
|
||||||
'default', 'description'
|
'default', 'description'
|
||||||
], name);
|
], name);
|
||||||
|
|
|
@ -2,13 +2,12 @@
|
||||||
<b-form-group v-bind="$attrs" :label-for="id" :state="fieldState">
|
<b-form-group v-bind="$attrs" :label-for="id" :state="fieldState">
|
||||||
<template #default>
|
<template #default>
|
||||||
<slot name="default" v-bind="{ id, field, state: fieldState }">
|
<slot name="default" v-bind="{ id, field, state: fieldState }">
|
||||||
<b-form-textarea v-if="inputType === 'textarea'" ref="input" :id="id" :name="name"
|
<b-form-textarea v-bind="inputAttrs" v-if="inputType === 'textarea'" ref="input" :id="id" :name="name"
|
||||||
v-model="modelValue"
|
v-model="modelValue" :required="isRequired" :number="isNumeric" :trim="inputTrim"
|
||||||
:required="isRequired" :number="isNumeric" :trim="inputTrim" v-bind="inputAttrs"
|
|
||||||
:autofocus="autofocus" :state="fieldState"></b-form-textarea>
|
:autofocus="autofocus" :state="fieldState"></b-form-textarea>
|
||||||
<b-form-input v-else ref="input" :type="inputType" :id="id" :name="name" v-model="modelValue"
|
<b-form-input v-bind="inputAttrs" v-else ref="input" :type="inputType" :id="id" :name="name"
|
||||||
:required="isRequired" :number="isNumeric" :trim="inputTrim"
|
v-model="modelValue" :required="isRequired" :number="isNumeric" :trim="inputTrim"
|
||||||
:autofocus="autofocus" v-bind="inputAttrs" :state="fieldState"></b-form-input>
|
:autofocus="autofocus" :state="fieldState"></b-form-input>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<b-form-invalid-feedback :state="fieldState">
|
<b-form-invalid-feedback :state="fieldState">
|
||||||
|
@ -17,7 +16,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #label="slotProps">
|
<template #label="slotProps">
|
||||||
<slot name="label" v-bind="slotProps" :lang="'lang_'+id"></slot>
|
<slot v-bind="slotProps" name="label" :lang="'lang_'+id"></slot>
|
||||||
<span v-if="isRequired" class="text-danger">
|
<span v-if="isRequired" class="text-danger">
|
||||||
<span aria-hidden="true">*</span>
|
<span aria-hidden="true">*</span>
|
||||||
<span class="sr-only">Required</span>
|
<span class="sr-only">Required</span>
|
||||||
|
@ -27,12 +26,11 @@
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<template #description="slotProps">
|
<template #description="slotProps">
|
||||||
<slot name="description" v-bind="slotProps" :lang="'lang_'+id+'_desc'"></slot>
|
<slot v-bind="slotProps" name="description" :lang="'lang_'+id+'_desc'"></slot>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<slot v-for="(_, name) in $slots" :name="name" :slot="name"/>
|
<template v-for="(_, slot) of filteredScopedSlots" v-slot:[slot]="scope">
|
||||||
<template v-for="(_, name) in filteredScopedSlots" :slot="name" slot-scope="slotData">
|
<slot :name="slot" v-bind="scope"></slot>
|
||||||
<slot :name="name" v-bind="slotData"/>
|
|
||||||
</template>
|
</template>
|
||||||
</b-form-group>
|
</b-form-group>
|
||||||
</template>
|
</template>
|
||||||
|
@ -101,7 +99,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
filteredScopedSlots() {
|
filteredScopedSlots() {
|
||||||
return _.filter(this.$scopedSlots, (slot, name) => {
|
return _.filter(this.$slots, (slot, name) => {
|
||||||
return !_.includes([
|
return !_.includes([
|
||||||
'default', 'label', 'description'
|
'default', 'label', 'description'
|
||||||
], name);
|
], name);
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="break"></div>
|
<div class="break"></div>
|
||||||
<small class="date-played text-muted">
|
<small class="date-played text-muted">
|
||||||
<span v-html="unixTimestampToDate(row.played_at)">{{ row.played_at }}</span>
|
<span v-html="unixTimestampToDate(row.played_at)"></span>
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
<div class="mt-3" v-if="playing">
|
<div class="mt-3" v-if="playing">
|
||||||
|
|
||||||
<div class="d-flex flex-row mb-2">
|
<div class="d-flex flex-row mb-2">
|
||||||
<div class="flex-shrink-0 pt-1 pr-2">{{ position | prettifyTime }}</div>
|
<div class="flex-shrink-0 pt-1 pr-2">{{ prettifyTime(position) }}</div>
|
||||||
<div class="flex-fill">
|
<div class="flex-fill">
|
||||||
<input type="range" min="0" max="100" step="0.1" class="custom-range slider"
|
<input type="range" min="0" max="100" step="0.1" class="custom-range slider"
|
||||||
v-bind:value="seekingPosition"
|
v-bind:value="seekingPosition"
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
v-on:mousemove="doSeek($event)"
|
v-on:mousemove="doSeek($event)"
|
||||||
v-on:mouseup="isSeeking = false">
|
v-on:mouseup="isSeeking = false">
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-shrink-0 pt-1 pl-2">{{ duration | prettifyTime }}</div>
|
<div class="flex-shrink-0 pt-1 pl-2">{{ prettifyTime(duration) }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="progress mb-1">
|
<div class="progress mb-1">
|
||||||
|
@ -93,7 +93,7 @@
|
||||||
<h5 class="mb-0">{{
|
<h5 class="mb-0">{{
|
||||||
rowFile.metadata.title ? rowFile.metadata.title : lang_unknown_title
|
rowFile.metadata.title ? rowFile.metadata.title : lang_unknown_title
|
||||||
}}</h5>
|
}}</h5>
|
||||||
<small class="pt-1">{{ rowFile.audio.length | prettifyTime }}</small>
|
<small class="pt-1">{{ prettifyTime(rowFile.audio.length) }}</small>
|
||||||
</div>
|
</div>
|
||||||
<p class="mb-0">{{ rowFile.metadata.artist ? rowFile.metadata.artist : lang_unknown_artist }}</p>
|
<p class="mb-0">{{ rowFile.metadata.artist ? rowFile.metadata.artist : lang_unknown_artist }}</p>
|
||||||
</a>
|
</a>
|
||||||
|
@ -155,16 +155,16 @@ export default {
|
||||||
this.$root.$on('new-mixer-value', this.setMixGain);
|
this.$root.$on('new-mixer-value', this.setMixGain);
|
||||||
this.$root.$on('new-cue', this.onNewCue);
|
this.$root.$on('new-cue', this.onNewCue);
|
||||||
},
|
},
|
||||||
filters: {
|
methods: {
|
||||||
prettifyTime (time) {
|
prettifyTime(time) {
|
||||||
if (typeof time === 'undefined') {
|
if (typeof time === 'undefined') {
|
||||||
return 'N/A';
|
return 'N/A';
|
||||||
}
|
}
|
||||||
|
|
||||||
var hours = parseInt(time / 3600);
|
let hours = parseInt(time / 3600);
|
||||||
time %= 3600;
|
time %= 3600;
|
||||||
var minutes = parseInt(time / 60);
|
let minutes = parseInt(time / 60);
|
||||||
var seconds = parseInt(time % 60);
|
let seconds = parseInt(time % 60);
|
||||||
|
|
||||||
if (minutes < 10) {
|
if (minutes < 10) {
|
||||||
minutes = '0' + minutes;
|
minutes = '0' + minutes;
|
||||||
|
@ -178,19 +178,17 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
return minutes + ':' + seconds;
|
return minutes + ':' + seconds;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
cue() {
|
||||||
methods: {
|
|
||||||
cue () {
|
|
||||||
this.resumeStream();
|
this.resumeStream();
|
||||||
this.$root.$emit('new-cue', (this.passThrough) ? 'off' : this.id);
|
this.$root.$emit('new-cue', (this.passThrough) ? 'off' : this.id);
|
||||||
},
|
},
|
||||||
|
|
||||||
onNewCue (new_cue) {
|
onNewCue(new_cue) {
|
||||||
this.passThrough = (new_cue === this.id);
|
this.passThrough = (new_cue === this.id);
|
||||||
},
|
},
|
||||||
|
|
||||||
setMixGain (new_value) {
|
setMixGain(new_value) {
|
||||||
if (this.id === 'playlist_1') {
|
if (this.id === 'playlist_1') {
|
||||||
this.mixGainObj.gain.value = 1.0 - new_value;
|
this.mixGainObj.gain.value = 1.0 - new_value;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<translate key="lang_hdr_info">Continue the setup process by creating your first radio station below. You can edit any of these details later.</translate>
|
<translate key="lang_hdr_info">Continue the setup process by creating your first radio station below. You can edit any of these details later.</translate>
|
||||||
</info-card>
|
</info-card>
|
||||||
|
|
||||||
<admin-stations-form ref="form" v-bind="$props" :is-edit-mode="false" :create-url="createUrl"
|
<admin-stations-form v-bind="$props" ref="form" :is-edit-mode="false" :create-url="createUrl"
|
||||||
@submitted="onSubmitted">
|
@submitted="onSubmitted">
|
||||||
<template #submitButtonText>
|
<template #submitButtonText>
|
||||||
<translate key="lang_btn_create_and_continue">Create and Continue</translate>
|
<translate key="lang_btn_create_and_continue">Create and Continue</translate>
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
<h5 class="m-0">{{ row.item.name }}</h5>
|
<h5 class="m-0">{{ row.item.name }}</h5>
|
||||||
</template>
|
</template>
|
||||||
<template #cell(format)="row">
|
<template #cell(format)="row">
|
||||||
{{ row.item.format|upper }}
|
{{ upper(row.item.format) }}
|
||||||
</template>
|
</template>
|
||||||
<template #cell(bitrate)="row">
|
<template #cell(bitrate)="row">
|
||||||
{{ row.item.bitrate }}kbps
|
{{ row.item.bitrate }}kbps
|
||||||
|
@ -70,16 +70,14 @@ export default {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
filters: {
|
methods: {
|
||||||
upper(data) {
|
upper(data) {
|
||||||
let upper = [];
|
let upper = [];
|
||||||
data.split(' ').forEach((word) => {
|
data.split(' ').forEach((word) => {
|
||||||
upper.push(word.toUpperCase());
|
upper.push(word.toUpperCase());
|
||||||
});
|
});
|
||||||
return upper.join(' ');
|
return upper.join(' ');
|
||||||
}
|
},
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
relist() {
|
relist() {
|
||||||
this.$refs.datatable.refresh();
|
this.$refs.datatable.refresh();
|
||||||
},
|
},
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
<template v-if="row.item.enable_autodj">
|
<template v-if="row.item.enable_autodj">
|
||||||
<translate key="lang_autodj_enabled">Enabled</translate>
|
<translate key="lang_autodj_enabled">Enabled</translate>
|
||||||
-
|
-
|
||||||
{{ row.item.autodj_bitrate }}kbps {{ row.item.autodj_format|upper }}
|
{{ row.item.autodj_bitrate }}kbps {{ upper(row.item.autodj_format) }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<translate key="lang_autodj_disabled">Disabled</translate>
|
<translate key="lang_autodj_disabled">Disabled</translate>
|
||||||
|
@ -86,16 +86,14 @@ export default {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
filters: {
|
methods: {
|
||||||
upper(data) {
|
upper(data) {
|
||||||
let upper = [];
|
let upper = [];
|
||||||
data.split(' ').forEach((word) => {
|
data.split(' ').forEach((word) => {
|
||||||
upper.push(word.toUpperCase());
|
upper.push(word.toUpperCase());
|
||||||
});
|
});
|
||||||
return upper.join(' ');
|
return upper.join(' ');
|
||||||
}
|
},
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
relist() {
|
relist() {
|
||||||
this.$refs.datatable.refresh();
|
this.$refs.datatable.refresh();
|
||||||
},
|
},
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
<playlists-form-schedule-row v-for="(row, index) in scheduleItems" :key="index"
|
<playlists-form-schedule-row v-for="(row, index) in scheduleItems" :key="index"
|
||||||
:station-time-zone="stationTimeZone"
|
:station-time-zone="stationTimeZone"
|
||||||
:index="index" :row.sync="row" @remove="remove(index)">
|
:index="index" v-model:row="scheduleItems[index]" @remove="remove(index)">
|
||||||
</playlists-form-schedule-row>
|
</playlists-form-schedule-row>
|
||||||
|
|
||||||
<b-button-group>
|
<b-button-group>
|
||||||
|
|
|
@ -4,26 +4,26 @@
|
||||||
|
|
||||||
<div class="row" id="profile">
|
<div class="row" id="profile">
|
||||||
<div class="col-lg-7">
|
<div class="col-lg-7">
|
||||||
<profile-now-playing :np="np" v-bind="$props"></profile-now-playing>
|
<profile-now-playing v-bind="$props" :np="np"></profile-now-playing>
|
||||||
|
|
||||||
<profile-schedule :station-time-zone="stationTimeZone" :schedule-items="np.schedule"></profile-schedule>
|
<profile-schedule :station-time-zone="stationTimeZone" :schedule-items="np.schedule"></profile-schedule>
|
||||||
|
|
||||||
<profile-streams :np="np" v-bind="$props"></profile-streams>
|
<profile-streams v-bind="$props" :np="np"></profile-streams>
|
||||||
|
|
||||||
<profile-public-pages v-bind="$props"></profile-public-pages>
|
<profile-public-pages v-bind="$props"></profile-public-pages>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-lg-5">
|
<div class="col-lg-5">
|
||||||
<profile-requests v-if="stationSupportsRequests" v-bind="$props"></profile-requests>
|
<profile-requests v-bind="$props" v-if="stationSupportsRequests"></profile-requests>
|
||||||
|
|
||||||
<profile-streamers v-if="stationSupportsStreamers" v-bind="$props"></profile-streamers>
|
<profile-streamers v-bind="$props" v-if="stationSupportsStreamers"></profile-streamers>
|
||||||
|
|
||||||
<template v-if="hasActiveFrontend">
|
<template v-if="hasActiveFrontend">
|
||||||
<profile-frontend :np="np" v-bind="$props"></profile-frontend>
|
<profile-frontend v-bind="$props" :np="np"></profile-frontend>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="hasActiveBackend">
|
<template v-if="hasActiveBackend">
|
||||||
<profile-backend :np="np" v-bind="$props"></profile-backend>
|
<profile-backend v-bind="$props" :np="np"></profile-backend>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<profile-backend-none></profile-backend-none>
|
<profile-backend-none></profile-backend-none>
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
<translate key="lang_public_pages_disable">Disable</translate>
|
<translate key="lang_public_pages_disable">Disable</translate>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<embed-modal ref="embed_modal" v-bind="$props"></embed-modal>
|
<embed-modal v-bind="$props" ref="embed_modal"></embed-modal>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="card-header bg-primary-dark">
|
<div class="card-header bg-primary-dark">
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<admin-stations-form ref="form" v-bind="$props" :is-edit-mode="true" :edit-url="editUrl"
|
<admin-stations-form v-bind="$props" ref="form" :is-edit-mode="true" :edit-url="editUrl"
|
||||||
@submitted="onSubmitted"></admin-stations-form>
|
@submitted="onSubmitted"></admin-stations-form>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
<template v-if="row.item.enable_autodj">
|
<template v-if="row.item.enable_autodj">
|
||||||
<translate key="lang_autodj_enabled">Enabled</translate>
|
<translate key="lang_autodj_enabled">Enabled</translate>
|
||||||
-
|
-
|
||||||
{{ row.item.autodj_bitrate }}kbps {{ row.item.autodj_format|upper }}
|
{{ row.item.autodj_bitrate }}kbps {{ upper(row.item.autodj_format) }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<translate key="lang_autodj_disabled">Disabled</translate>
|
<translate key="lang_autodj_disabled">Disabled</translate>
|
||||||
|
@ -77,7 +77,7 @@ export default {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
filters: {
|
methods: {
|
||||||
upper(data) {
|
upper(data) {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return '';
|
return '';
|
||||||
|
@ -88,9 +88,7 @@ export default {
|
||||||
upper.push(word.toUpperCase());
|
upper.push(word.toUpperCase());
|
||||||
});
|
});
|
||||||
return upper.join(' ');
|
return upper.join(' ');
|
||||||
}
|
},
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
relist() {
|
relist() {
|
||||||
this.$refs.datatable.refresh();
|
this.$refs.datatable.refresh();
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<l-map v-if="mapPoints.length < 3000" style="height: 300px; z-index: 0;" :zoom="1" :center="[40, 0]">
|
<l-map v-if="mapPoints.length < 3000" style="height: 300px; z-index: 0;" :zoom="1" :center="[40, 0]">
|
||||||
<l-control-fullscreen/>
|
|
||||||
<l-tile-layer :url="tileUrl" :attribution="tileAttribution"></l-tile-layer>
|
<l-tile-layer :url="tileUrl" :attribution="tileAttribution"></l-tile-layer>
|
||||||
<l-marker v-for="l in mapPoints" :key="l.hash"
|
<l-marker v-for="l in mapPoints" :key="l.hash"
|
||||||
:lat-lng="{lat: l.location.lat, lng: l.location.lon}">
|
:lat-lng="{lat: l.location.lat, lng: l.location.lon}">
|
||||||
|
@ -22,8 +21,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import L from 'leaflet';
|
import L from 'leaflet';
|
||||||
import {LMap, LMarker, LTileLayer, LTooltip} from 'vue2-leaflet';
|
import {LMap, LMarker, LTileLayer, LTooltip} from '@vue-leaflet/vue-leaflet';
|
||||||
import LControlFullscreen from 'vue2-leaflet-fullscreen';
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -36,8 +34,7 @@ export default {
|
||||||
LMap,
|
LMap,
|
||||||
LTileLayer,
|
LTileLayer,
|
||||||
LMarker,
|
LMarker,
|
||||||
LTooltip,
|
LTooltip
|
||||||
LControlFullscreen
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
nonsubscription transmissions other than broadcast simulcasts and transmissions of non-music
|
nonsubscription transmissions other than broadcast simulcasts and transmissions of non-music
|
||||||
programming." If your station does not fall within this category, update the transmission
|
programming." If your station does not fall within this category, update the transmission
|
||||||
category field accordingly.
|
category field accordingly.
|
||||||
|
</li>
|
||||||
<li>The data collected by AzuraCast meets the SoundExchange standard for Actual Total
|
<li>The data collected by AzuraCast meets the SoundExchange standard for Actual Total
|
||||||
Performances (ATP) by tracking unique listeners across all song plays. All other information
|
Performances (ATP) by tracking unique listeners across all song plays. All other information
|
||||||
is derived from the metadata of the uploaded songs themselves, and may not be completely
|
is derived from the metadata of the uploaded songs themselves, and may not be completely
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
<streamers-form-schedule-row v-for="(row, index) in scheduleItems" :key="index"
|
<streamers-form-schedule-row v-for="(row, index) in scheduleItems" :key="index"
|
||||||
:station-time-zone="stationTimeZone"
|
:station-time-zone="stationTimeZone"
|
||||||
:index="index" :row.sync="row" @remove="remove(index)">
|
:index="index" v-model:row="scheduleItems[index]" @remove="remove(index)">
|
||||||
</streamers-form-schedule-row>
|
</streamers-form-schedule-row>
|
||||||
|
|
||||||
<b-button-group>
|
<b-button-group>
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
import initBase from '~/base.js';
|
import initBase from '~/base.js';
|
||||||
|
import {createApp} from "vue";
|
||||||
import '~/vendor/bootstrapVue.js';
|
import useSweetAlert from '~/vendor/sweetalert.js';
|
||||||
import '~/vendor/sweetalert.js';
|
import useBootstrapVue from '~/vendor/bootstrapVue.js';
|
||||||
|
|
||||||
import AdminApiKeys from '~/components/Admin/ApiKeys.vue';
|
import AdminApiKeys from '~/components/Admin/ApiKeys.vue';
|
||||||
|
|
||||||
export default initBase(AdminApiKeys);
|
const vueApp = createApp(AdminApiKeys);
|
||||||
|
|
||||||
|
useSweetAlert(vueApp);
|
||||||
|
useBootstrapVue(vueApp);
|
||||||
|
|
||||||
|
export default initBase(vueApp);
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import initBase
|
import initBase from '~/base.js';
|
||||||
from '~/base.js';
|
import {createApp} from "vue";
|
||||||
|
import useBootstrapVue from '~/vendor/bootstrapVue.js';
|
||||||
import '~/vendor/bootstrapVue.js';
|
|
||||||
import '~/vendor/luxon.js';
|
import '~/vendor/luxon.js';
|
||||||
|
|
||||||
import AuditLog
|
import AuditLog from '~/components/Admin/AuditLog.vue';
|
||||||
from '~/components/Admin/AuditLog.vue';
|
|
||||||
|
|
||||||
export default initBase(AuditLog);
|
const vueApp = createApp(AuditLog);
|
||||||
|
|
||||||
|
useBootstrapVue(vueApp);
|
||||||
|
|
||||||
|
export default initBase(vueApp);
|
||||||
|
|
|
@ -6,6 +6,8 @@ Vue.use(PiniaVuePlugin);
|
||||||
const pinia = createPinia();
|
const pinia = createPinia();
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
|
||||||
|
|
||||||
let inlinePlayer = new Vue({
|
let inlinePlayer = new Vue({
|
||||||
el: '#radio-player-controls',
|
el: '#radio-player-controls',
|
||||||
render: createElement => createElement(InlinePlayer),
|
render: createElement => createElement(InlinePlayer),
|
||||||
|
|
159
frontend/vue/vendor/bootstrapVue.js
vendored
159
frontend/vue/vendor/bootstrapVue.js
vendored
|
@ -1,111 +1,106 @@
|
||||||
import Vue from 'vue';
|
|
||||||
import {BootstrapVue} from 'bootstrap-vue';
|
import {BootstrapVue} from 'bootstrap-vue';
|
||||||
|
|
||||||
import 'bootstrap-vue/dist/bootstrap-vue.css';
|
import 'bootstrap-vue/dist/bootstrap-vue.css';
|
||||||
|
|
||||||
Vue.use(BootstrapVue);
|
export default function useBootstrapVue(vueApp) {
|
||||||
|
vueApp.use(BootstrapVue);
|
||||||
|
|
||||||
const BootstrapVueNotifiers = {
|
vueApp.config.globalProperties.$notify = function (message = null, options = {}) {
|
||||||
install(Vue, opts) {
|
if (!!document.hidden) {
|
||||||
Vue.prototype.$notify = function (message = null, options = {}) {
|
return;
|
||||||
if (!!document.hidden) {
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaults = {
|
|
||||||
variant: 'default',
|
|
||||||
toaster: 'b-toaster-top-right',
|
|
||||||
autoHideDelay: 3000,
|
|
||||||
solid: true
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$bvToast.toast(message, {...defaults, ...options});
|
const defaults = {
|
||||||
|
variant: 'default',
|
||||||
|
toaster: 'b-toaster-top-right',
|
||||||
|
autoHideDelay: 3000,
|
||||||
|
solid: true
|
||||||
};
|
};
|
||||||
|
|
||||||
Vue.prototype.$notifyError = function (message = null, options = {}) {
|
this.$bvToast.toast(message, {...defaults, ...options});
|
||||||
if (message === null) {
|
};
|
||||||
message = this.$gettext('An error occurred and your request could not be completed.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaults = {
|
vueApp.config.globalProperties.$notifyError = function (message = null, options = {}) {
|
||||||
variant: 'danger',
|
if (message === null) {
|
||||||
title: this.$gettext('Error')
|
message = this.$gettext('An error occurred and your request could not be completed.');
|
||||||
};
|
}
|
||||||
|
|
||||||
this.$notify(message, {...defaults, ...options});
|
const defaults = {
|
||||||
|
variant: 'danger',
|
||||||
return message;
|
title: this.$gettext('Error')
|
||||||
};
|
};
|
||||||
|
|
||||||
Vue.prototype.$notifySuccess = function (message = null, options = {}) {
|
this.$notify(message, {...defaults, ...options});
|
||||||
if (message === null) {
|
|
||||||
message = this.$gettext('Changes saved.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaults = {
|
return message;
|
||||||
variant: 'success',
|
};
|
||||||
title: this.$gettext('Success')
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$notify(message, {...defaults, ...options});
|
vueApp.config.globalProperties.$notifySuccess = function (message = null, options = {}) {
|
||||||
|
if (message === null) {
|
||||||
|
message = this.$gettext('Changes saved.');
|
||||||
|
}
|
||||||
|
|
||||||
return message;
|
const defaults = {
|
||||||
|
variant: 'success',
|
||||||
|
title: this.$gettext('Success')
|
||||||
};
|
};
|
||||||
|
|
||||||
const LOADING_TOAST_ID = 'toast-loading';
|
this.$notify(message, {...defaults, ...options});
|
||||||
|
|
||||||
Vue.prototype.$showLoading = function (message = null, options = {}) {
|
return message;
|
||||||
if (message === null) {
|
};
|
||||||
message = this.$gettext('Applying changes...');
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaults = {
|
const LOADING_TOAST_ID = 'toast-loading';
|
||||||
id: LOADING_TOAST_ID,
|
|
||||||
variant: 'warning',
|
|
||||||
title: this.$gettext('Please wait...'),
|
|
||||||
autoHideDelay: 10000,
|
|
||||||
isStatus: true
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$notify(message, {...defaults, ...options});
|
vueApp.config.globalProperties.$showLoading = function (message = null, options = {}) {
|
||||||
return message;
|
if (message === null) {
|
||||||
|
message = this.$gettext('Applying changes...');
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaults = {
|
||||||
|
id: LOADING_TOAST_ID,
|
||||||
|
variant: 'warning',
|
||||||
|
title: this.$gettext('Please wait...'),
|
||||||
|
autoHideDelay: 10000,
|
||||||
|
isStatus: true
|
||||||
};
|
};
|
||||||
|
|
||||||
Vue.prototype.$hideLoading = function () {
|
this.$notify(message, {...defaults, ...options});
|
||||||
this.$bvToast.hide(LOADING_TOAST_ID);
|
return message;
|
||||||
};
|
};
|
||||||
|
|
||||||
let $isAxiosLoading = false;
|
vueApp.config.globalProperties.$hideLoading = function () {
|
||||||
let $axiosLoadCount = 0;
|
this.$bvToast.hide(LOADING_TOAST_ID);
|
||||||
|
};
|
||||||
|
|
||||||
Vue.prototype.$setLoading = function (isLoading) {
|
let $isAxiosLoading = false;
|
||||||
let prevIsLoading = $isAxiosLoading;
|
let $axiosLoadCount = 0;
|
||||||
if (isLoading) {
|
|
||||||
$axiosLoadCount++;
|
|
||||||
$isAxiosLoading = true;
|
|
||||||
} else if ($axiosLoadCount > 0) {
|
|
||||||
$axiosLoadCount--;
|
|
||||||
$isAxiosLoading = ($axiosLoadCount > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle state changes
|
vueApp.config.globalProperties.$setLoading = function (isLoading) {
|
||||||
if (!prevIsLoading && $isAxiosLoading) {
|
let prevIsLoading = $isAxiosLoading;
|
||||||
this.$showLoading();
|
if (isLoading) {
|
||||||
} else if (prevIsLoading && !$isAxiosLoading) {
|
$axiosLoadCount++;
|
||||||
this.$hideLoading();
|
$isAxiosLoading = true;
|
||||||
}
|
} else if ($axiosLoadCount > 0) {
|
||||||
};
|
$axiosLoadCount--;
|
||||||
|
$isAxiosLoading = ($axiosLoadCount > 0);
|
||||||
|
}
|
||||||
|
|
||||||
Vue.prototype.$wrapWithLoading = function (promise) {
|
// Handle state changes
|
||||||
this.$setLoading(true);
|
if (!prevIsLoading && $isAxiosLoading) {
|
||||||
|
this.$showLoading();
|
||||||
|
} else if (prevIsLoading && !$isAxiosLoading) {
|
||||||
|
this.$hideLoading();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
promise.finally(() => {
|
vueApp.config.globalProperties.$wrapWithLoading = function (promise) {
|
||||||
this.$setLoading(false);
|
this.$setLoading(true);
|
||||||
});
|
|
||||||
|
|
||||||
return promise;
|
promise.finally(() => {
|
||||||
};
|
this.$setLoading(false);
|
||||||
}
|
});
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
Vue.use(BootstrapVueNotifiers);
|
|
||||||
|
|
9
frontend/vue/vendor/clipboard.js
vendored
9
frontend/vue/vendor/clipboard.js
vendored
|
@ -1,8 +1,7 @@
|
||||||
import Vue
|
import VueClipboard from 'vue-clipboard2';
|
||||||
from 'vue';
|
|
||||||
import VueClipboard
|
|
||||||
from 'vue-clipboard2';
|
|
||||||
|
|
||||||
VueClipboard.config.autoSetContainer = true;
|
VueClipboard.config.autoSetContainer = true;
|
||||||
|
|
||||||
Vue.use(VueClipboard);
|
export default function useVueClipboard(vueApp) {
|
||||||
|
vueApp.use(VueClipboard);
|
||||||
|
};
|
||||||
|
|
3
frontend/vue/vendor/luxon.js
vendored
3
frontend/vue/vendor/luxon.js
vendored
|
@ -1,4 +1,5 @@
|
||||||
import { Settings } from 'luxon';
|
import {Settings} from 'luxon';
|
||||||
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
Settings.defaultLocale = App.locale_with_dashes;
|
Settings.defaultLocale = App.locale_with_dashes;
|
||||||
|
|
34
frontend/vue/vendor/sweetalert.js
vendored
34
frontend/vue/vendor/sweetalert.js
vendored
|
@ -1,25 +1,19 @@
|
||||||
import Swal from 'sweetalert2';
|
import Swal from 'sweetalert2';
|
||||||
|
|
||||||
import Vue from 'vue';
|
export default function useSweetAlert(vueApp) {
|
||||||
|
vueApp.config.globalProperties.$swal = function (options = {}) {
|
||||||
|
return Swal.fire(options);
|
||||||
|
};
|
||||||
|
|
||||||
const ConfirmFunctions = {
|
vueApp.config.globalProperties.$confirmDelete = function (options = {}) {
|
||||||
install(Vue, opts) {
|
const defaults = {
|
||||||
Vue.prototype.$swal = function (options = {}) {
|
title: this.$gettext('Delete Record?'),
|
||||||
return Swal.fire(options);
|
confirmButtonText: this.$gettext('Delete'),
|
||||||
|
confirmButtonColor: '#e64942',
|
||||||
|
showCancelButton: true,
|
||||||
|
focusCancel: true
|
||||||
};
|
};
|
||||||
|
|
||||||
Vue.prototype.$confirmDelete = function (options = {}) {
|
return this.$swal({...defaults, ...options});
|
||||||
const defaults = {
|
};
|
||||||
title: this.$gettext('Delete Record?'),
|
}
|
||||||
confirmButtonText: this.$gettext('Delete'),
|
|
||||||
confirmButtonColor: '#e64942',
|
|
||||||
showCancelButton: true,
|
|
||||||
focusCancel: true
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.$swal({...defaults, ...options});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Vue.use(ConfirmFunctions);
|
|
||||||
|
|
|
@ -60,7 +60,8 @@ module.exports = {
|
||||||
resolve: {
|
resolve: {
|
||||||
enforceExtension: false,
|
enforceExtension: false,
|
||||||
alias: {
|
alias: {
|
||||||
'~': path.resolve(__dirname, './vue')
|
'~': path.resolve(__dirname, './vue'),
|
||||||
|
vue: '@vue/compat'
|
||||||
},
|
},
|
||||||
extensions: ['.js', '.vue', '.json']
|
extensions: ['.js', '.vue', '.json']
|
||||||
},
|
},
|
||||||
|
@ -101,14 +102,18 @@ module.exports = {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.vue$/i,
|
test: /\.vue$/i,
|
||||||
use: [
|
loader: 'vue-loader',
|
||||||
'vue-loader'
|
options: {
|
||||||
]
|
compilerOptions: {
|
||||||
|
compatConfig: {
|
||||||
|
MODE: 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.scss$/i,
|
test: /\.scss$/i,
|
||||||
use: [
|
use: [
|
||||||
'vue-style-loader',
|
|
||||||
'css-loader',
|
'css-loader',
|
||||||
'sass-loader'
|
'sass-loader'
|
||||||
]
|
]
|
||||||
|
@ -116,7 +121,6 @@ module.exports = {
|
||||||
{
|
{
|
||||||
test: /\.css$/i,
|
test: /\.css$/i,
|
||||||
use: [
|
use: [
|
||||||
'vue-style-loader',
|
|
||||||
'css-loader'
|
'css-loader'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue
Block a user