diff --git a/aircox/admin/sound.py b/aircox/admin/sound.py index 5b2b830..15df74f 100644 --- a/aircox/admin/sound.py +++ b/aircox/admin/sound.py @@ -70,6 +70,20 @@ class SoundAdmin(SortableAdminBase, admin.ModelAdmin): if obj.type != Sound.TYPE_REMOVED else '' audio.short_description = _('Audio') + def add_view(self, request, object_id, form_url='', context=None): + context = context or {} + context['init_app'] = True + context['init_el'] = '#inline-tracks' + context['track_timestamp'] = True + return super().change_view(request, object_id, form_url, context) + + def change_view(self, request, object_id, form_url='', context=None): + context = context or {} + context['init_app'] = True + context['init_el'] = '#inline-tracks' + context['track_timestamp'] = True + return super().change_view(request, object_id, form_url, context) + @admin.register(Track) class TrackAdmin(admin.ModelAdmin): diff --git a/aircox/serializers/admin.py b/aircox/serializers/admin.py index 0818685..34658cb 100644 --- a/aircox/serializers/admin.py +++ b/aircox/serializers/admin.py @@ -13,7 +13,7 @@ class TrackSerializer(TaggitSerializer, serializers.ModelSerializer): class Meta: model = Track fields = ('pk', 'artist', 'title', 'album', 'year', 'position', - 'info', 'tags', 'episode', 'sound') + 'info', 'tags', 'episode', 'sound', 'timestamp') class UserSettingsSerializer(serializers.ModelSerializer): diff --git a/aircox/static/aircox/js/chunk-common.js b/aircox/static/aircox/js/chunk-common.js index 7952a3f..393dcb8 100644 --- a/aircox/static/aircox/js/chunk-common.js +++ b/aircox/static/aircox/js/chunk-common.js @@ -85,7 +85,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _ALi \*************************************************************************************************************************************************************************************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"Page\": function() { return /* binding */ Page; }\n/* harmony export */ });\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.push.js */ \"./node_modules/core-js/modules/es.array.push.js\");\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var lodash__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\");\n/* harmony import */ var lodash__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(lodash__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _model__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../model */ \"./src/model.js\");\n/* harmony import */ var _track__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../track */ \"./src/track.js\");\n/* harmony import */ var _AActionButton__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./AActionButton */ \"./src/components/AActionButton.vue\");\n/* harmony import */ var _ARow_vue__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./ARow.vue */ \"./src/components/ARow.vue\");\n/* harmony import */ var _ARows_vue__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./ARows.vue */ \"./src/components/ARows.vue\");\n\n\n\n\n\n\n\n\n/// Page display\nconst Page = {\n Text: 0,\n List: 1,\n Settings: 2\n};\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n components: {\n AActionButton: _AActionButton__WEBPACK_IMPORTED_MODULE_4__[\"default\"],\n ARow: _ARow_vue__WEBPACK_IMPORTED_MODULE_5__[\"default\"],\n ARows: _ARows_vue__WEBPACK_IMPORTED_MODULE_6__[\"default\"]\n },\n props: {\n initData: Object,\n dataPrefix: String,\n labels: Object,\n settingsUrl: String,\n defaultColumns: {\n type: Array,\n default: () => ['artist', 'title', 'tags', 'album', 'year']\n }\n },\n data() {\n const settings = {\n playlist_editor_columns: this.defaultColumns,\n playlist_editor_sep: ' -- '\n };\n return {\n Page: Page,\n page: Page.Text,\n set: new _model__WEBPACK_IMPORTED_MODULE_2__.Set(_track__WEBPACK_IMPORTED_MODULE_3__[\"default\"]),\n extraData: {},\n settings,\n savedSettings: (0,lodash__WEBPACK_IMPORTED_MODULE_1__.cloneDeep)(settings)\n };\n },\n computed: {\n settingsChanged() {\n var k = Object.keys(this.savedSettings).findIndex(k => !(0,lodash__WEBPACK_IMPORTED_MODULE_1__.isEqual)(this.settings[k], this.savedSettings[k]));\n return k != -1;\n },\n separator: {\n set(value) {\n this.settings.playlist_editor_sep = value;\n if (this.page == Page.List) this.updateInput();\n },\n get() {\n return this.settings.playlist_editor_sep;\n }\n },\n columns: {\n set(value) {\n var cols = value.filter(x => x in this.defaultColumns);\n var left = this.defaultColumns.filter(x => !(x in cols));\n value = cols.concat(left);\n this.settings.playlist_editor_columns = value;\n },\n get() {\n return this.settings.playlist_editor_columns;\n }\n },\n items() {\n return this.set.items;\n },\n rowsSlots() {\n return Object.keys(this.$slots).filter(x => x.startsWith('row-') || x.startsWith('rows-')).map(x => [x, x.startsWith('rows-') ? x.slice(5) : x]);\n }\n },\n methods: {\n onCellEvent(event) {\n switch (event.name) {\n case 'change':\n this.updateInput();\n break;\n }\n },\n formatMove({\n from,\n to\n }) {\n const value = this.columns[from];\n this.columns.splice(from, 1);\n this.columns.splice(to, 0, value);\n if (this.page == Page.Text) this.updateList();else this.updateText();\n },\n columnMove({\n from,\n to\n }) {\n const value = this.columns[from];\n this.columns.splice(from, 1);\n this.columns.splice(to, 0, value);\n this.updateInput();\n },\n listItemMove({\n from,\n to,\n set\n }) {\n set.move(from, to);\n this.updateInput();\n },\n updateList() {\n const items = this.toList(this.$refs.textarea.value);\n this.set.reset(items);\n },\n updateInput() {\n const input = this.toText(this.items);\n this.$refs.textarea.value = input;\n },\n /**\n * From input and separator, return list of items.\n */\n toList(input) {\n var lines = input.split('\\n');\n var items = [];\n for (let line of lines) {\n line = line.trimLeft();\n if (!line) continue;\n var lineBits = line.split(this.separator);\n var item = {};\n for (var col in this.columns) {\n if (col >= lineBits.length) break;\n const attr = this.columns[col];\n item[attr] = lineBits[col].trim();\n }\n item && items.push(item);\n }\n return items;\n },\n /**\n * From items and separator return a string\n */\n toText(items) {\n const sep = ` ${this.separator.trim()} `;\n const lines = [];\n for (let item of items) {\n if (!item) continue;\n var line = [];\n for (var col of this.columns) line.push(item.data[col] || '');\n line = (0,lodash__WEBPACK_IMPORTED_MODULE_1__.dropRightWhile)(line, x => !x || !('' + x).trim());\n line = line.join(sep).trimRight();\n lines.push(line);\n }\n return lines.join('\\n');\n },\n _data_key(key) {\n key = key.slice(this.dataPrefix.length);\n try {\n var [index, attr] = key.split('-', 1);\n return [Number(index), attr];\n } catch (err) {\n return [null, key];\n }\n },\n //! Update saved settings from this.settings\n settingsSaved(settings = null) {\n if (settings !== null) this.settings = settings;\n this.savedSettings = (0,lodash__WEBPACK_IMPORTED_MODULE_1__.cloneDeep)(this.settings);\n },\n /**\n * Load initial data\n */\n loadData({\n items = [],\n settings = null\n }, reset = false) {\n if (reset) {\n this.set.items = [];\n }\n for (var index in items) this.set.push((0,lodash__WEBPACK_IMPORTED_MODULE_1__.cloneDeep)(items[index]));\n if (settings) this.settingsSaved(settings);\n this.updateInput();\n }\n },\n watch: {\n initData(val) {\n this.loadData(val);\n }\n },\n mounted() {\n this.initData && this.loadData(this.initData);\n this.page = this.items ? Page.List : Page.Text;\n }\n});\n\n//# sourceURL=webpack://aircox-assets/./src/components/APlaylistEditor.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"Page\": function() { return /* binding */ Page; }\n/* harmony export */ });\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.push.js */ \"./node_modules/core-js/modules/es.array.push.js\");\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var lodash__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\");\n/* harmony import */ var lodash__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(lodash__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _model__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../model */ \"./src/model.js\");\n/* harmony import */ var _track__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../track */ \"./src/track.js\");\n/* harmony import */ var _AActionButton__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./AActionButton */ \"./src/components/AActionButton.vue\");\n/* harmony import */ var _ARow_vue__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./ARow.vue */ \"./src/components/ARow.vue\");\n/* harmony import */ var _ARows_vue__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./ARows.vue */ \"./src/components/ARows.vue\");\n\n\n\n\n\n\n\n\n/// Page display\nconst Page = {\n Text: 0,\n List: 1,\n Settings: 2\n};\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n components: {\n AActionButton: _AActionButton__WEBPACK_IMPORTED_MODULE_4__[\"default\"],\n ARow: _ARow_vue__WEBPACK_IMPORTED_MODULE_5__[\"default\"],\n ARows: _ARows_vue__WEBPACK_IMPORTED_MODULE_6__[\"default\"]\n },\n props: {\n initData: Object,\n dataPrefix: String,\n labels: Object,\n settingsUrl: String,\n defaultColumns: {\n type: Array,\n default: () => ['artist', 'title', 'tags', 'album', 'year', 'timestamp']\n }\n },\n data() {\n const settings = {\n playlist_editor_columns: this.defaultColumns,\n playlist_editor_sep: ' -- '\n };\n return {\n Page: Page,\n page: Page.Text,\n set: new _model__WEBPACK_IMPORTED_MODULE_2__.Set(_track__WEBPACK_IMPORTED_MODULE_3__[\"default\"]),\n extraData: {},\n settings,\n savedSettings: (0,lodash__WEBPACK_IMPORTED_MODULE_1__.cloneDeep)(settings)\n };\n },\n computed: {\n settingsChanged() {\n var k = Object.keys(this.savedSettings).findIndex(k => !(0,lodash__WEBPACK_IMPORTED_MODULE_1__.isEqual)(this.settings[k], this.savedSettings[k]));\n return k != -1;\n },\n separator: {\n set(value) {\n this.settings.playlist_editor_sep = value;\n if (this.page == Page.List) this.updateInput();\n },\n get() {\n return this.settings.playlist_editor_sep;\n }\n },\n columns: {\n set(value) {\n var cols = value.filter(x => x in this.defaultColumns);\n var left = this.defaultColumns.filter(x => !(x in cols));\n value = cols.concat(left);\n this.settings.playlist_editor_columns = value;\n },\n get() {\n return this.settings.playlist_editor_columns;\n }\n },\n items() {\n return this.set.items;\n },\n rowsSlots() {\n return Object.keys(this.$slots).filter(x => x.startsWith('row-') || x.startsWith('rows-')).map(x => [x, x.startsWith('rows-') ? x.slice(5) : x]);\n }\n },\n methods: {\n onCellEvent(event) {\n switch (event.name) {\n case 'change':\n this.updateInput();\n break;\n }\n },\n formatMove({\n from,\n to\n }) {\n const value = this.columns[from];\n this.columns.splice(from, 1);\n this.columns.splice(to, 0, value);\n if (this.page == Page.Text) this.updateList();else this.updateText();\n },\n columnMove({\n from,\n to\n }) {\n const value = this.columns[from];\n this.columns.splice(from, 1);\n this.columns.splice(to, 0, value);\n this.updateInput();\n },\n listItemMove({\n from,\n to,\n set\n }) {\n set.move(from, to);\n this.updateInput();\n },\n updateList() {\n const items = this.toList(this.$refs.textarea.value);\n this.set.reset(items);\n },\n updateInput() {\n const input = this.toText(this.items);\n this.$refs.textarea.value = input;\n },\n /**\n * From input and separator, return list of items.\n */\n toList(input) {\n var lines = input.split('\\n');\n var items = [];\n for (let line of lines) {\n line = line.trimLeft();\n if (!line) continue;\n var lineBits = line.split(this.separator);\n var item = {};\n for (var col in this.columns) {\n if (col >= lineBits.length) break;\n const attr = this.columns[col];\n item[attr] = lineBits[col].trim();\n }\n item && items.push(item);\n }\n return items;\n },\n /**\n * From items and separator return a string\n */\n toText(items) {\n const sep = ` ${this.separator.trim()} `;\n const lines = [];\n for (let item of items) {\n if (!item) continue;\n var line = [];\n for (var col of this.columns) line.push(item.data[col] || '');\n line = (0,lodash__WEBPACK_IMPORTED_MODULE_1__.dropRightWhile)(line, x => !x || !('' + x).trim());\n line = line.join(sep).trimRight();\n lines.push(line);\n }\n return lines.join('\\n');\n },\n _data_key(key) {\n key = key.slice(this.dataPrefix.length);\n try {\n var [index, attr] = key.split('-', 1);\n return [Number(index), attr];\n } catch (err) {\n return [null, key];\n }\n },\n //! Update saved settings from this.settings\n settingsSaved(settings = null) {\n if (settings !== null) this.settings = settings;\n this.savedSettings = (0,lodash__WEBPACK_IMPORTED_MODULE_1__.cloneDeep)(this.settings);\n },\n /**\n * Load initial data\n */\n loadData({\n items = [],\n settings = null\n }, reset = false) {\n if (reset) {\n this.set.items = [];\n }\n for (var index in items) this.set.push((0,lodash__WEBPACK_IMPORTED_MODULE_1__.cloneDeep)(items[index]));\n if (settings) this.settingsSaved(settings);\n this.updateInput();\n }\n },\n watch: {\n initData(val) {\n this.loadData(val);\n }\n },\n mounted() {\n this.initData && this.loadData(this.initData);\n this.page = this.items ? Page.List : Page.Text;\n }\n});\n\n//# sourceURL=webpack://aircox-assets/./src/components/APlaylistEditor.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D"); /***/ }), @@ -115,7 +115,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core \***************************************************************************************************************************************************************************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.push.js */ \"./node_modules/core-js/modules/es.array.push.js\");\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _AList_vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./AList.vue */ \"./src/components/AList.vue\");\n/* harmony import */ var _ARow_vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ARow.vue */ \"./src/components/ARow.vue\");\n\n\n\nconst Component = {\n extends: _AList_vue__WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n components: {\n ARow: _ARow_vue__WEBPACK_IMPORTED_MODULE_2__[\"default\"]\n },\n emit: ['cell', 'colmove'],\n props: {\n ..._AList_vue__WEBPACK_IMPORTED_MODULE_1__[\"default\"].props,\n columns: Array,\n labels: Object,\n allowCreate: Boolean\n },\n data() {\n return {\n ...super.data,\n extraItem: new this.set.model()\n };\n },\n computed: {\n rowCells() {\n const cells = [];\n for (var row in this.items) cells.push({\n row\n });\n },\n rows() {\n return [...this.$el.querySelectorAll('tr')].filter(x => x.__row).map(x => x.__row);\n },\n rowSlots() {\n return Object.keys(this.$slots).filter(x => x.startsWith('row-')).map(x => [x, x.slice(4)]);\n }\n },\n methods: {\n validateExtraCell() {\n if (!this.allowCreate) return;\n this.set.push(this.extraItem);\n this.extraItem = new this.set.model();\n },\n onControlKey(event, cell) {\n switch (event.key) {\n case \"ArrowUp\":\n this.focus(-1, 0, cell);\n event.stopPropagation();\n event.preventDefault();\n break;\n case \"ArrowDown\":\n this.focus(1, 0, cell);\n event.stopPropagation();\n event.preventDefault();\n break;\n case \"ArrowLeft\":\n this.focus(0, -1, cell);\n event.stopPropagation();\n event.preventDefault();\n break;\n case \"ArrowRight\":\n this.focus(0, 1, cell);\n event.stopPropagation();\n event.preventDefault();\n break;\n }\n },\n /**\n * React on 'cell' event, re-emitting it with additional values:\n * - `set`: data set\n * - `row`: row index\n *\n * @param {Number} row: row index\n * @param {} data: cell's event data\n */\n onCellEvent(row, event) {\n if (event.name == 'focus') this.cellFocus(event.data, event.cell);\n this.$emit('cell', {\n ...event,\n row,\n set: this.set\n });\n },\n getCellNode(row, col) {\n const el = this.$refs[row];\n return el && el.cellEls(col);\n },\n /**\n * Focus on a cell\n */\n focus(row, col, from = null) {\n if (from) row += from.row;\n row = this.rows[row];\n row && row.focus(col, from);\n }\n }\n};\nComponent.props.itemTag.default = 'tr';\nComponent.props.listTag.default = 'tbody';\n/* harmony default export */ __webpack_exports__[\"default\"] = (Component);\n\n//# sourceURL=webpack://aircox-assets/./src/components/ARows.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.push.js */ \"./node_modules/core-js/modules/es.array.push.js\");\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _AList_vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./AList.vue */ \"./src/components/AList.vue\");\n/* harmony import */ var _ARow_vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ARow.vue */ \"./src/components/ARow.vue\");\n\n\n\nconst Component = {\n extends: _AList_vue__WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n components: {\n ARow: _ARow_vue__WEBPACK_IMPORTED_MODULE_2__[\"default\"]\n },\n emit: ['cell', 'colmove'],\n props: {\n ..._AList_vue__WEBPACK_IMPORTED_MODULE_1__[\"default\"].props,\n columns: Array,\n labels: Object,\n allowCreate: Boolean\n },\n data() {\n return {\n ...super.data,\n extraItem: new this.set.model()\n };\n },\n computed: {\n rowCells() {\n const cells = [];\n for (var row in this.items) cells.push({\n row\n });\n },\n rows() {\n return [...this.$el.querySelectorAll('tr')].filter(x => x.__row).map(x => x.__row);\n },\n rowSlots() {\n return Object.keys(this.$slots).filter(x => x.startsWith('row-')).map(x => [x, x.slice(4)]);\n }\n },\n methods: {\n onControlKey(event, cell) {\n switch (event.key) {\n case \"ArrowUp\":\n this.focus(-1, 0, cell);\n event.stopPropagation();\n event.preventDefault();\n break;\n case \"ArrowDown\":\n this.focus(1, 0, cell);\n event.stopPropagation();\n event.preventDefault();\n break;\n case \"ArrowLeft\":\n this.focus(0, -1, cell);\n event.stopPropagation();\n event.preventDefault();\n break;\n case \"ArrowRight\":\n this.focus(0, 1, cell);\n event.stopPropagation();\n event.preventDefault();\n break;\n }\n },\n /**\n * React on 'cell' event, re-emitting it with additional values:\n * - `set`: data set\n * - `row`: row index\n *\n * @param {Number} row: row index\n * @param {} data: cell's event data\n */\n onCellEvent(row, event) {\n if (event.name == 'focus') this.cellFocus(event.data, event.cell);\n this.$emit('cell', {\n ...event,\n row,\n set: this.set\n });\n },\n getCellNode(row, col) {\n const el = this.$refs[row];\n return el && el.cellEls(col);\n },\n /**\n * Focus on a cell\n */\n focus(row, col, from = null) {\n if (from) row += from.row;\n row = this.rows[row];\n row && row.focus(col, from);\n }\n }\n};\nComponent.props.itemTag.default = 'tr';\nComponent.props.listTag.default = 'tbody';\n/* harmony default export */ __webpack_exports__[\"default\"] = (Component);\n\n//# sourceURL=webpack://aircox-assets/./src/components/ARows.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D"); /***/ }), @@ -225,7 +225,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac \*****************************************************************************************************************************************************************************************************************************************************************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"render\": function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm-bundler.js\");\n\nconst _hoisted_1 = {\n class: \"playlist-editor\"\n};\nconst _hoisted_2 = {\n class: \"columns\"\n};\nconst _hoisted_3 = {\n class: \"column\"\n};\nconst _hoisted_4 = {\n class: \"column has-text-right\"\n};\nconst _hoisted_5 = {\n class: \"float-right field has-addons\"\n};\nconst _hoisted_6 = {\n class: \"control\"\n};\nconst _hoisted_7 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"icon is-small\"\n}, [/*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"i\", {\n class: \"fa fa-pencil\"\n})], -1 /* HOISTED */);\nconst _hoisted_8 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"Texte\", -1 /* HOISTED */);\nconst _hoisted_9 = [_hoisted_7, _hoisted_8];\nconst _hoisted_10 = {\n class: \"control\"\n};\nconst _hoisted_11 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"icon is-small\"\n}, [/*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"i\", {\n class: \"fa fa-list\"\n})], -1 /* HOISTED */);\nconst _hoisted_12 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"Liste\", -1 /* HOISTED */);\nconst _hoisted_13 = [_hoisted_11, _hoisted_12];\nconst _hoisted_14 = {\n class: \"page\"\n};\nconst _hoisted_15 = {\n class: \"page\"\n};\nconst _hoisted_16 = {\n class: \"mt-2\"\n};\nconst _hoisted_17 = {\n class: \"field is-inline-block is-vcentered mr-3\"\n};\nconst _hoisted_18 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", {\n class: \"label is-inline mr-2\",\n style: {\n \"vertical-align\": \"middle\"\n }\n}, \" Séparateur\", -1 /* HOISTED */);\nconst _hoisted_19 = {\n class: \"control is-inline-block\",\n style: {\n \"vertical-align\": \"middle\"\n }\n};\nconst _hoisted_20 = {\n class: \"field is-inline-block is-vcentered mr-5\"\n};\nconst _hoisted_21 = {\n class: \"label is-inline mr-2\",\n style: {\n \"vertical-align\": \"middle\"\n }\n};\nconst _hoisted_22 = {\n class: \"table is-bordered is-inline-block\",\n style: {\n \"vertical-align\": \"middle\"\n }\n};\nconst _hoisted_23 = {\n key: 0,\n style: {\n \"cursor\": \"pointer\"\n }\n};\nconst _hoisted_24 = [\"onClick\"];\nconst _hoisted_25 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"i\", {\n class: \"fa fa-left-right\"\n}, null, -1 /* HOISTED */);\nconst _hoisted_26 = [_hoisted_25];\nconst _hoisted_27 = {\n key: 0,\n class: \"field is-vcentered is-inline-block\"\n};\nconst _hoisted_28 = {\n class: \"float-right\"\n};\nconst _hoisted_29 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"icon\"\n}, [/*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"i\", {\n class: \"fa fa-rotate\"\n})], -1 /* HOISTED */);\n\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n const _component_a_rows = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)(\"a-rows\");\n const _component_a_row = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)(\"a-row\");\n const _component_a_action_button = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)(\"a-action-button\");\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"title\")]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_4, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_5, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", _hoisted_6, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"a\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['button', 'p-2', $data.page == $data.Page.Text ? 'is-primary' : 'is-light']),\n onClick: _cache[0] || (_cache[0] = $event => $data.page = $data.Page.Text)\n }, _hoisted_9, 2 /* CLASS */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", _hoisted_10, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"a\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['button', 'p-2', $data.page == $data.Page.List ? 'is-primary' : 'is-light']),\n onClick: _cache[1] || (_cache[1] = $event => $data.page = $data.Page.List)\n }, _hoisted_13, 2 /* CLASS */)])])])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"top\", {\n set: $data.set,\n columns: $options.columns,\n items: $options.items\n }), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"section\", _hoisted_14, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"textarea\", {\n ref: \"textarea\",\n class: \"is-fullwidth is-size-6\",\n rows: \"20\",\n onChange: _cache[2] || (_cache[2] = (...args) => $options.updateList && $options.updateList(...args))\n }, null, 544 /* HYDRATE_EVENTS, NEED_PATCH */)], 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vShow, $data.page == $data.Page.Text]]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"section\", _hoisted_15, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_a_rows, {\n set: $data.set,\n columns: $options.columns,\n labels: $props.labels,\n \"allow-create\": true,\n orderable: true,\n onMove: $options.listItemMove,\n onColmove: $options.columnMove,\n onCell: $options.onCellEvent\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.createSlots)({\n _: 2 /* DYNAMIC */\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($options.rowsSlots, ([name, slot]) => {\n return {\n name: slot,\n fn: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(data => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, name, (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeProps)((0,vue__WEBPACK_IMPORTED_MODULE_0__.guardReactiveProps)(data)))])\n };\n })]), 1032 /* PROPS, DYNAMIC_SLOTS */, [\"set\", \"columns\", \"labels\", \"onMove\", \"onColmove\", \"onCell\"])], 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vShow, $data.page == $data.Page.List]]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_16, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_17, [_hoisted_18, (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_19, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n type: \"text\",\n ref: \"sep\",\n class: \"input is-inline is-text-centered is-small\",\n style: {\n \"max-width\": \"5em\"\n },\n \"onUpdate:modelValue\": _cache[3] || (_cache[3] = $event => $options.separator = $event),\n onChange: _cache[4] || (_cache[4] = $event => $options.updateList())\n }, null, 544 /* HYDRATE_EVENTS, NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $options.separator]])])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_20, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", _hoisted_21, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.labels.columns), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"table\", _hoisted_22, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"tr\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_a_row, {\n columns: $options.columns,\n item: $props.labels,\n onMove: $options.formatMove,\n orderable: true\n }, {\n \"cell-after\": (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(({\n cell\n }) => [cell.col < $options.columns.length - 1 ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"td\", _hoisted_23, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"icon\",\n onClick: $event => $options.formatMove({\n from: cell.col,\n to: cell.col + 1\n })\n }, _hoisted_26, 8 /* PROPS */, _hoisted_24)])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)]),\n _: 1 /* STABLE */\n }, 8 /* PROPS */, [\"columns\", \"item\", \"onMove\"])])])]), $options.settingsChanged ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_27, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_a_action_button, {\n icon: \"fa fa-floppy-disk\",\n class: \"button control p-3 is-info\",\n \"run-class\": \"blink\",\n url: $props.settingsUrl,\n method: \"POST\",\n data: $data.settings,\n \"aria-label\": $props.labels.save_settings,\n onDone: _cache[5] || (_cache[5] = $event => $options.settingsSaved())\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)((0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.labels.save_settings), 1 /* TEXT */)]),\n\n _: 1 /* STABLE */\n }, 8 /* PROPS */, [\"url\", \"data\", \"aria-label\"])])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_28, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"a\", {\n class: \"button is-warning p-2 ml-2\",\n onClick: _cache[6] || (_cache[6] = $event => $options.loadData({\n items: this.initData.items\n }, true))\n }, [_hoisted_29, (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.labels.discard_changes), 1 /* TEXT */)])])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"bottom\", {\n set: $data.set,\n columns: $options.columns,\n items: $options.items\n })]);\n}\n\n//# sourceURL=webpack://aircox-assets/./src/components/APlaylistEditor.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"render\": function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.push.js */ \"./node_modules/core-js/modules/es.array.push.js\");\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm-bundler.js\");\n\n\nconst _hoisted_1 = {\n class: \"playlist-editor\"\n};\nconst _hoisted_2 = {\n class: \"columns\"\n};\nconst _hoisted_3 = {\n class: \"column\"\n};\nconst _hoisted_4 = {\n class: \"column has-text-right\"\n};\nconst _hoisted_5 = {\n class: \"float-right field has-addons\"\n};\nconst _hoisted_6 = {\n class: \"control\"\n};\nconst _hoisted_7 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", {\n class: \"icon is-small\"\n}, [/*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"i\", {\n class: \"fa fa-pencil\"\n})], -1 /* HOISTED */);\nconst _hoisted_8 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, \"Texte\", -1 /* HOISTED */);\nconst _hoisted_9 = [_hoisted_7, _hoisted_8];\nconst _hoisted_10 = {\n class: \"control\"\n};\nconst _hoisted_11 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", {\n class: \"icon is-small\"\n}, [/*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"i\", {\n class: \"fa fa-list\"\n})], -1 /* HOISTED */);\nconst _hoisted_12 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, \"Liste\", -1 /* HOISTED */);\nconst _hoisted_13 = [_hoisted_11, _hoisted_12];\nconst _hoisted_14 = {\n class: \"page\"\n};\nconst _hoisted_15 = {\n class: \"page\"\n};\nconst _hoisted_16 = [\"onClick\", \"title\", \"aria-label\"];\nconst _hoisted_17 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", {\n class: \"icon\"\n}, [/*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"i\", {\n class: \"fa fa-trash\"\n})], -1 /* HOISTED */);\nconst _hoisted_18 = [_hoisted_17];\nconst _hoisted_19 = {\n class: \"mt-2\"\n};\nconst _hoisted_20 = {\n class: \"field is-inline-block is-vcentered mr-3\"\n};\nconst _hoisted_21 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"label\", {\n class: \"label is-inline mr-2\",\n style: {\n \"vertical-align\": \"middle\"\n }\n}, \" Séparateur\", -1 /* HOISTED */);\nconst _hoisted_22 = {\n class: \"control is-inline-block\",\n style: {\n \"vertical-align\": \"middle\"\n }\n};\nconst _hoisted_23 = {\n class: \"field is-inline-block is-vcentered mr-3\"\n};\nconst _hoisted_24 = {\n class: \"label is-inline mr-2\",\n style: {\n \"vertical-align\": \"middle\"\n }\n};\nconst _hoisted_25 = {\n class: \"table is-bordered is-inline-block\",\n style: {\n \"vertical-align\": \"middle\"\n }\n};\nconst _hoisted_26 = {\n key: 0,\n style: {\n \"cursor\": \"pointer\"\n }\n};\nconst _hoisted_27 = [\"onClick\"];\nconst _hoisted_28 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"i\", {\n class: \"fa fa-left-right\"\n}, null, -1 /* HOISTED */);\nconst _hoisted_29 = [_hoisted_28];\nconst _hoisted_30 = {\n key: 0,\n class: \"field is-vcentered is-inline-block\"\n};\nconst _hoisted_31 = {\n class: \"float-right\"\n};\nconst _hoisted_32 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", {\n class: \"icon\"\n}, [/*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"i\", {\n class: \"fa fa-rotate\"\n})], -1 /* HOISTED */);\nconst _hoisted_33 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", {\n class: \"icon\"\n}, [/*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"i\", {\n class: \"fa fa-plus\"\n})], -1 /* HOISTED */);\n\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n const _component_a_rows = (0,vue__WEBPACK_IMPORTED_MODULE_1__.resolveComponent)(\"a-rows\");\n const _component_a_row = (0,vue__WEBPACK_IMPORTED_MODULE_1__.resolveComponent)(\"a-row\");\n const _component_a_action_button = (0,vue__WEBPACK_IMPORTED_MODULE_1__.resolveComponent)(\"a-action-button\");\n return (0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.renderSlot)(_ctx.$slots, \"title\")]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", _hoisted_4, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", _hoisted_5, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"p\", _hoisted_6, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"a\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_1__.normalizeClass)(['button', 'p-2', $data.page == $data.Page.Text ? 'is-primary' : 'is-light']),\n onClick: _cache[0] || (_cache[0] = $event => $data.page = $data.Page.Text)\n }, _hoisted_9, 2 /* CLASS */)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"p\", _hoisted_10, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"a\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_1__.normalizeClass)(['button', 'p-2', $data.page == $data.Page.List ? 'is-primary' : 'is-light']),\n onClick: _cache[1] || (_cache[1] = $event => $data.page = $data.Page.List)\n }, _hoisted_13, 2 /* CLASS */)])])])]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.renderSlot)(_ctx.$slots, \"top\", {\n set: $data.set,\n columns: $options.columns,\n items: $options.items\n }), (0,vue__WEBPACK_IMPORTED_MODULE_1__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"section\", _hoisted_14, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"textarea\", {\n ref: \"textarea\",\n class: \"is-fullwidth is-size-6\",\n rows: \"20\",\n onChange: _cache[2] || (_cache[2] = (...args) => $options.updateList && $options.updateList(...args))\n }, null, 544 /* HYDRATE_EVENTS, NEED_PATCH */)], 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_1__.vShow, $data.page == $data.Page.Text]]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"section\", _hoisted_15, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createVNode)(_component_a_rows, {\n set: $data.set,\n columns: $options.columns,\n labels: $props.labels,\n \"allow-create\": true,\n orderable: true,\n onMove: $options.listItemMove,\n onColmove: $options.columnMove,\n onCell: $options.onCellEvent\n }, (0,vue__WEBPACK_IMPORTED_MODULE_1__.createSlots)({\n \"row-tail\": (0,vue__WEBPACK_IMPORTED_MODULE_1__.withCtx)(data => [_ctx.$slots['row-tail'] ? (0,vue__WEBPACK_IMPORTED_MODULE_1__.renderSlot)(_ctx.$slots, _ctx.row - _ctx.tail, (0,vue__WEBPACK_IMPORTED_MODULE_1__.normalizeProps)((0,vue__WEBPACK_IMPORTED_MODULE_1__.mergeProps)({\n key: 0\n }, data))) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"td\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"a\", {\n class: \"button is-danger is-outlined p-3 is-size-6\",\n onClick: $event => $options.items.splice(data.row, 1),\n title: $props.labels.remove_track,\n \"aria-label\": $props.labels.remove_track\n }, _hoisted_18, 8 /* PROPS */, _hoisted_16)])]),\n _: 2 /* DYNAMIC */\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.renderList)($options.rowsSlots, ([name, slot]) => {\n return {\n name: slot,\n fn: (0,vue__WEBPACK_IMPORTED_MODULE_1__.withCtx)(data => [name != 'row-tail' ? (0,vue__WEBPACK_IMPORTED_MODULE_1__.renderSlot)(_ctx.$slots, name, (0,vue__WEBPACK_IMPORTED_MODULE_1__.normalizeProps)((0,vue__WEBPACK_IMPORTED_MODULE_1__.mergeProps)({\n key: 0\n }, data))) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true)])\n };\n })]), 1032 /* PROPS, DYNAMIC_SLOTS */, [\"set\", \"columns\", \"labels\", \"onMove\", \"onColmove\", \"onCell\"])], 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_1__.vShow, $data.page == $data.Page.List]]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", _hoisted_19, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", _hoisted_20, [_hoisted_21, (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", _hoisted_22, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"input\", {\n type: \"text\",\n ref: \"sep\",\n class: \"input is-inline is-text-centered is-small\",\n style: {\n \"max-width\": \"5em\"\n },\n \"onUpdate:modelValue\": _cache[3] || (_cache[3] = $event => $options.separator = $event),\n onChange: _cache[4] || (_cache[4] = $event => $options.updateList())\n }, null, 544 /* HYDRATE_EVENTS, NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_1__.vModelText, $options.separator]])])]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", _hoisted_23, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"label\", _hoisted_24, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($props.labels.columns), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"table\", _hoisted_25, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"tr\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createVNode)(_component_a_row, {\n columns: $options.columns,\n item: $props.labels,\n onMove: $options.formatMove,\n orderable: true\n }, {\n \"cell-after\": (0,vue__WEBPACK_IMPORTED_MODULE_1__.withCtx)(({\n cell\n }) => [cell.col < $options.columns.length - 1 ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"td\", _hoisted_26, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", {\n class: \"icon\",\n onClick: $event => $options.formatMove({\n from: cell.col,\n to: cell.col + 1\n })\n }, _hoisted_29, 8 /* PROPS */, _hoisted_27)])) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true)]),\n _: 1 /* STABLE */\n }, 8 /* PROPS */, [\"columns\", \"item\", \"onMove\"])])])]), $options.settingsChanged ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_30, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createVNode)(_component_a_action_button, {\n icon: \"fa fa-floppy-disk\",\n class: \"button control p-3 is-info\",\n \"run-class\": \"blink\",\n url: $props.settingsUrl,\n method: \"POST\",\n data: $data.settings,\n \"aria-label\": $props.labels.save_settings,\n onDone: _cache[5] || (_cache[5] = $event => $options.settingsSaved())\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_1__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createTextVNode)((0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($props.labels.save_settings), 1 /* TEXT */)]),\n\n _: 1 /* STABLE */\n }, 8 /* PROPS */, [\"url\", \"data\", \"aria-label\"])])) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", _hoisted_31, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"a\", {\n class: \"button is-warning p-2 ml-2\",\n onClick: _cache[6] || (_cache[6] = $event => $options.loadData({\n items: this.initData.items\n }, true))\n }, [_hoisted_32, (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($props.labels.discard_changes), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"a\", {\n class: \"button is-primary p-2 ml-2\",\n \"t-if\": \"page == page.List\",\n onClick: _cache[7] || (_cache[7] = $event => this.set.push(new this.set.model()))\n }, [_hoisted_33, (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($props.labels.add_track), 1 /* TEXT */)])])]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.renderSlot)(_ctx.$slots, \"bottom\", {\n set: $data.set,\n columns: $options.columns,\n items: $options.items\n })]);\n}\n\n//# sourceURL=webpack://aircox-assets/./src/components/APlaylistEditor.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D"); /***/ }), @@ -245,7 +245,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac \******************************************************************************************************************************************************************************************************************************************************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"render\": function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm-bundler.js\");\n\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"tr\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"head\", {\n item: $props.item,\n row: $options.row\n }), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($props.columns, (attr, col) => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n key: col\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"cell-before\", {\n item: $props.item,\n cell: $options.cells[col],\n attr: attr\n }), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)((0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveDynamicComponent)($props.cellTag), {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['cell', 'cell-' + attr]),\n \"data-col\": col,\n draggable: $props.orderable,\n onDragstart: $options.onDragStart,\n onDragover: $options.onDragOver,\n onDrop: $options.onDrop\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, attr, {\n item: $props.item,\n cell: $options.cells[col],\n data: $options.itemData,\n attr: attr,\n emit: $options.cellEmit,\n value: $options.itemData && $options.itemData[attr]\n }, () => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)((0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($options.itemData && $options.itemData[attr]), 1 /* TEXT */)])]),\n\n _: 2 /* DYNAMIC */\n }, 1064 /* PROPS, HYDRATE_EVENTS, DYNAMIC_SLOTS */, [\"class\", \"data-col\", \"draggable\", \"onDragstart\", \"onDragover\", \"onDrop\"])), (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"cell-after\", {\n item: $props.item,\n col: col,\n cell: $options.cells[col],\n attr: attr\n })], 64 /* STABLE_FRAGMENT */);\n }), 128 /* KEYED_FRAGMENT */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"tail\", {\n item: $props.item,\n row: $options.row\n })]);\n}\n\n//# sourceURL=webpack://aircox-assets/./src/components/ARow.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"render\": function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm-bundler.js\");\n\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"tr\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"head\", {\n item: $props.item,\n row: $options.row\n }), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($props.columns, (attr, col) => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n key: col\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"cell-before\", {\n item: $props.item,\n cell: $options.cells[col],\n attr: attr\n }), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)((0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveDynamicComponent)($props.cellTag), {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['cell', 'cell-' + attr]),\n \"data-col\": col,\n draggable: $props.orderable,\n onDragstart: $options.onDragStart,\n onDragover: $options.onDragOver,\n onDrop: $options.onDrop\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, attr, {\n item: $props.item,\n cell: $options.cells[col],\n data: $options.itemData,\n attr: attr,\n emit: $options.cellEmit,\n value: $options.itemData && $options.itemData[attr]\n }, () => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)((0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($options.itemData && $options.itemData[attr]), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"cell\", {\n item: $props.item,\n cell: $options.cells[col],\n data: $options.itemData,\n attr: attr,\n emit: $options.cellEmit,\n value: $options.itemData && $options.itemData[attr]\n })]),\n _: 2 /* DYNAMIC */\n }, 1064 /* PROPS, HYDRATE_EVENTS, DYNAMIC_SLOTS */, [\"class\", \"data-col\", \"draggable\", \"onDragstart\", \"onDragover\", \"onDrop\"])), (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"cell-after\", {\n item: $props.item,\n col: col,\n cell: $options.cells[col],\n attr: attr\n })], 64 /* STABLE_FRAGMENT */);\n }), 128 /* KEYED_FRAGMENT */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"tail\", {\n item: $props.item,\n row: $options.row\n })]);\n}\n\n//# sourceURL=webpack://aircox-assets/./src/components/ARow.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D"); /***/ }), @@ -255,7 +255,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac \*******************************************************************************************************************************************************************************************************************************************************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"render\": function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm-bundler.js\");\n\nconst _hoisted_1 = {\n class: \"table is-stripped is-fullwidth\"\n};\nconst _hoisted_2 = [\"onKeydown\"];\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n const _component_a_row = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)(\"a-row\");\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"table\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"thead\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_a_row, {\n item: _ctx.labels,\n columns: _ctx.columns,\n orderable: _ctx.orderable,\n onMove: _cache[0] || (_cache[0] = $event => _ctx.$emit('colmove', $event))\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.createSlots)({\n _: 2 /* DYNAMIC */\n }, [_ctx.$slots['header-head'] ? {\n name: \"head\",\n fn: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(data => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"header-head\", (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeProps)((0,vue__WEBPACK_IMPORTED_MODULE_0__.guardReactiveProps)(data)))]),\n key: \"0\"\n } : undefined, _ctx.$slots['header-tail'] ? {\n name: \"tail\",\n fn: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(data => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"header-tail\", (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeProps)((0,vue__WEBPACK_IMPORTED_MODULE_0__.guardReactiveProps)(data)))]),\n key: \"1\"\n } : undefined]), 1032 /* PROPS, DYNAMIC_SLOTS */, [\"item\", \"columns\", \"orderable\"])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"tbody\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"head\"), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)(_ctx.items, (item, row) => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n key: row\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" data-index comes from AList component drag & drop \"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_a_row, {\n item: item,\n cell: {\n row\n },\n columns: _ctx.columns,\n \"data-index\": row,\n draggable: _ctx.orderable,\n onDragstart: _ctx.onDragStart,\n onDragover: _ctx.onDragOver,\n onDrop: _ctx.onDrop,\n onCell: $event => _ctx.onCellEvent(row, $event)\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.createSlots)({\n _: 2 /* DYNAMIC */\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)(_ctx.rowSlots, ([name, slot]) => {\n return {\n name: slot,\n fn: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(data => [slot == 'head' || slot == 'tail' ? (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, name, (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeProps)((0,vue__WEBPACK_IMPORTED_MODULE_0__.mergeProps)({\n key: 0\n }, data))) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 1,\n onKeydown: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($event => _ctx.onControlKey($event, data.cell), [\"ctrl\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, name, (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeProps)((0,vue__WEBPACK_IMPORTED_MODULE_0__.guardReactiveProps)(data)))], 40 /* PROPS, HYDRATE_EVENTS */, _hoisted_2))])\n };\n })]), 1032 /* PROPS, DYNAMIC_SLOTS */, [\"item\", \"cell\", \"columns\", \"data-index\", \"draggable\", \"onDragstart\", \"onDragover\", \"onDrop\", \"onCell\"])], 64 /* STABLE_FRAGMENT */);\n }), 128 /* KEYED_FRAGMENT */)), _ctx.allowCreate ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)(_component_a_row, {\n key: 0,\n item: _ctx.extraItem,\n cell: {\n row: _ctx.items.length,\n columns: _ctx.columns\n },\n onKeypress: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withKeys)((0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)(_ctx.validateExtraCell, [\"stop\", \"prevent\"]), [\"enter\"])\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.createSlots)({\n _: 2 /* DYNAMIC */\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)(_ctx.rowSlots, ([name, slot]) => {\n return {\n name: slot,\n fn: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(data => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, name, (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeProps)((0,vue__WEBPACK_IMPORTED_MODULE_0__.guardReactiveProps)(data)))])\n };\n })]), 1032 /* PROPS, DYNAMIC_SLOTS */, [\"item\", \"cell\", \"onKeypress\"])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"tail\")])]);\n}\n\n//# sourceURL=webpack://aircox-assets/./src/components/ARows.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"render\": function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm-bundler.js\");\n\nconst _hoisted_1 = {\n class: \"table is-stripped is-fullwidth\"\n};\nconst _hoisted_2 = [\"onKeydown\"];\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n const _component_a_row = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)(\"a-row\");\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"table\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"thead\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_a_row, {\n item: _ctx.labels,\n columns: _ctx.columns,\n orderable: _ctx.orderable,\n onMove: _cache[0] || (_cache[0] = $event => _ctx.$emit('colmove', $event))\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.createSlots)({\n _: 2 /* DYNAMIC */\n }, [_ctx.$slots['header-head'] ? {\n name: \"head\",\n fn: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(data => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"header-head\", (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeProps)((0,vue__WEBPACK_IMPORTED_MODULE_0__.guardReactiveProps)(data)))]),\n key: \"0\"\n } : undefined, _ctx.$slots['header-tail'] ? {\n name: \"tail\",\n fn: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(data => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"header-tail\", (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeProps)((0,vue__WEBPACK_IMPORTED_MODULE_0__.guardReactiveProps)(data)))]),\n key: \"1\"\n } : undefined]), 1032 /* PROPS, DYNAMIC_SLOTS */, [\"item\", \"columns\", \"orderable\"])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"tbody\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"head\"), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)(_ctx.items, (item, row) => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n key: row\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" data-index comes from AList component drag & drop \"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_a_row, {\n item: item,\n cell: {\n row\n },\n columns: _ctx.columns,\n \"data-index\": row,\n draggable: _ctx.orderable,\n onDragstart: _ctx.onDragStart,\n onDragover: _ctx.onDragOver,\n onDrop: _ctx.onDrop,\n onCell: $event => _ctx.onCellEvent(row, $event)\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.createSlots)({\n _: 2 /* DYNAMIC */\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)(_ctx.rowSlots, ([name, slot]) => {\n return {\n name: slot,\n fn: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(data => [slot == 'head' || slot == 'tail' ? (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, name, (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeProps)((0,vue__WEBPACK_IMPORTED_MODULE_0__.mergeProps)({\n key: 0\n }, data))) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 1,\n onKeydown: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($event => _ctx.onControlKey($event, data.cell), [\"ctrl\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, name, (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeProps)((0,vue__WEBPACK_IMPORTED_MODULE_0__.guardReactiveProps)(data)))], 40 /* PROPS, HYDRATE_EVENTS */, _hoisted_2))])\n };\n })]), 1032 /* PROPS, DYNAMIC_SLOTS */, [\"item\", \"cell\", \"columns\", \"data-index\", \"draggable\", \"onDragstart\", \"onDragover\", \"onDrop\", \"onCell\"])], 64 /* STABLE_FRAGMENT */);\n }), 128 /* KEYED_FRAGMENT */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderSlot)(_ctx.$slots, \"tail\")])]);\n}\n\n//# sourceURL=webpack://aircox-assets/./src/components/ARows.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D"); /***/ }), @@ -345,7 +345,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac \**********************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"Set\": function() { return /* binding */ Set; },\n/* harmony export */ \"default\": function() { return /* binding */ Model; },\n/* harmony export */ \"getCsrf\": function() { return /* binding */ getCsrf; }\n/* harmony export */ });\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.push.js */ \"./node_modules/core-js/modules/es.array.push.js\");\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__);\n\n/**\n * Return cookie with provided key\n */\nfunction getCookie(key) {\n if (document.cookie && document.cookie !== '') {\n const cookie = document.cookie.split(';').find(c => c.trim().startsWith(key + '='));\n return cookie ? decodeURIComponent(cookie.split('=')[1]) : null;\n }\n return null;\n}\n\n/**\n * CSRF token provided by Django\n */\nvar csrfToken = null;\n\n/**\n * Get CSRF token\n */\nfunction getCsrf() {\n if (csrfToken === null) csrfToken = getCookie('csrftoken');\n return csrfToken;\n}\n\n// TODO: prevent duplicate simple fetch\n/**\n * Provide interface used to fetch and manipulate objects.\n */\nclass Model {\n /**\n * Instanciate model with provided data and options.\n * By default `url` is taken from `data.url_`.\n */\n constructor(data = {}, {\n url = null,\n ...options\n } = {}) {\n this.url = url || data.url_;\n this.options = options;\n this.commit(data);\n }\n get errors() {\n return this.data.__errors__;\n }\n\n /**\n * Get instance id from its data\n */\n static getId(data) {\n return 'id' in data ? data.id : data.pk;\n }\n\n /**\n * Return fetch options\n */\n static getOptions(options) {\n return {\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n 'X-CSRFToken': getCsrf()\n },\n ...options\n };\n }\n\n /**\n * Return model instances for the provided list of model data.\n * @param {Array} items: array of data\n * @param {Object} options: options passed down to all model instances\n */\n static fromList(items, options = {}) {\n return items ? items.map(d => new this(d, options)) : [];\n }\n\n /**\n * Fetch item from server\n */\n static fetch(url, {\n many = false,\n ...options\n } = {}, args = {}) {\n options = this.getOptions(options);\n const request = fetch(url, options).then(response => response.json());\n if (many) return request.then(data => {\n if (!(data instanceof Array)) data = data.results;\n return this.fromList(data, args);\n });else return request.then(data => new this(data, {\n url: url,\n ...args\n }));\n }\n\n /**\n * Fetch data from server.\n */\n fetch(options) {\n options = this.constructor.getOptions(options);\n return fetch(this.url, options).then(response => response.json()).then(data => this.commit(data));\n }\n\n /**\n * Call API action on object.\n */\n action(path, options, commit = false) {\n options = this.constructor.getOptions(options);\n const promise = fetch(this.url + path, options);\n return commit ? promise.then(data => data.json()).then(data => {\n this.commit(data);\n this.data;\n }) : promise;\n }\n\n /**\n * Update instance's data with provided data. Return None\n */\n commit(data) {\n this.data = data;\n this.id = this.constructor.getId(this.data);\n }\n\n /**\n * Update model data, without reset previous value\n */\n update(data) {\n this.data = {\n ...this.data,\n ...data\n };\n this.id = this.constructor.getId(this.data);\n }\n\n /**\n * Save instance into localStorage.\n */\n store(key) {\n window.localStorage.setItem(key, JSON.stringify(this.data));\n }\n\n /**\n * Load model instance from localStorage.\n */\n static storeLoad(key) {\n let item = window.localStorage.getItem(key);\n return item === null ? item : new this(JSON.parse(item));\n }\n\n /**\n * Return error for a specific attribute name if any \n */\n error(attr = null) {\n return attr === null ? this.errors : this.errors && this.errors[attr];\n }\n}\n\n/**\n * List of models\n */\nclass Set {\n constructor(model, {\n items = [],\n url = null,\n args = {},\n unique = null,\n max = null,\n storeKey = null\n } = {}) {\n this.items = [];\n this.model = model;\n this.url = url;\n this.unique = unique;\n this.max = max;\n this.storeKey = storeKey;\n for (var item of items) this.push(item, {\n args: args,\n save: false\n });\n }\n get length() {\n return this.items.length;\n }\n\n /**\n * Fetch multiple items from server\n */\n static fetch(model, url, options = null, args = null) {\n options = model.getOptions(options);\n return fetch(url, options).then(response => response.json()).then(data => (data instanceof Array ? data : data.results).map(d => new model(d, {\n url: url,\n ...args\n })));\n }\n\n /**\n * Load list from localStorage\n */\n static storeLoad(model, key, args = {}) {\n let items = window.localStorage.getItem(key);\n return new this(model, {\n ...args,\n storeKey: key,\n items: items ? JSON.parse(items) : []\n });\n }\n\n /**\n * Store list into localStorage\n */\n store() {\n this.storeKey && window.localStorage.setItem(this.storeKey, JSON.stringify(this.items.map(i => i.data)));\n }\n\n /**\n * Save item\n */\n save() {\n this.storeKey && this.store();\n }\n\n /**\n * Get item at index\n */\n get(index) {\n return this.items[index];\n }\n\n /**\n * Find an item by id or using a predicate function\n */\n find(pred) {\n return pred instanceof Function ? this.items.find(pred) : this.items.find(x => x.id == pred.id);\n }\n\n /**\n * Find item index by id or using a predicate function\n */\n findIndex(pred) {\n return pred instanceof Function ? this.items.findIndex(pred) : this.items.findIndex(x => x.id == pred.id);\n }\n\n /**\n * Add item to set, return index.\n */\n push(item, {\n args = {},\n save = true\n } = {}) {\n item = item instanceof this.model ? item : new this.model(item, args);\n if (this.unique) {\n let index = this.findIndex(item);\n if (index > -1) return index;\n }\n if (this.max && this.items.length >= this.max) this.items.splice(0, this.items.length - this.max);\n this.items.push(item);\n save && this.save();\n return this.items.length - 1;\n }\n\n /**\n * Remove item from set by index\n */\n remove(index, {\n save = true\n } = {}) {\n this.items.splice(index, 1);\n save && this.save();\n }\n\n /**\n * Clear items, assign new ones\n */\n reset(items = []) {\n // TODO: check reactivity\n this.items = [];\n for (var item of items) this.push(item);\n }\n move(from, to) {\n if (from >= this.length || to > this.length) throw \"source or target index is not in range\";\n const value = this.items[from];\n this.items.splice(from, 1);\n this.items.splice(to, 0, value);\n }\n}\nSet[Symbol.iterator] = function () {\n return this.items[Symbol.iterator]();\n};\n\n//# sourceURL=webpack://aircox-assets/./src/model.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"Set\": function() { return /* binding */ Set; },\n/* harmony export */ \"default\": function() { return /* binding */ Model; },\n/* harmony export */ \"getCsrf\": function() { return /* binding */ getCsrf; }\n/* harmony export */ });\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.push.js */ \"./node_modules/core-js/modules/es.array.push.js\");\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__);\n\n/**\n * Return cookie with provided key\n */\nfunction getCookie(key) {\n if (document.cookie && document.cookie !== '') {\n const cookie = document.cookie.split(';').find(c => c.trim().startsWith(key + '='));\n return cookie ? decodeURIComponent(cookie.split('=')[1]) : null;\n }\n return null;\n}\n\n/**\n * CSRF token provided by Django\n */\nvar csrfToken = null;\n\n/**\n * Get CSRF token\n */\nfunction getCsrf() {\n if (csrfToken === null) csrfToken = getCookie('csrftoken');\n return csrfToken;\n}\n\n// TODO: prevent duplicate simple fetch\n/**\n * Provide interface used to fetch and manipulate objects.\n */\nclass Model {\n /**\n * Instanciate model with provided data and options.\n * By default `url` is taken from `data.url_`.\n */\n constructor(data = {}, {\n url = null,\n ...options\n } = {}) {\n this.url = url || data.url_;\n this.options = options;\n this.commit(data);\n }\n get errors() {\n return this.data && this.data.__errors__;\n }\n\n /**\n * Get instance id from its data\n */\n static getId(data) {\n return 'id' in data ? data.id : data.pk;\n }\n\n /**\n * Return fetch options\n */\n static getOptions(options) {\n return {\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n 'X-CSRFToken': getCsrf()\n },\n ...options\n };\n }\n\n /**\n * Return model instances for the provided list of model data.\n * @param {Array} items: array of data\n * @param {Object} options: options passed down to all model instances\n */\n static fromList(items, options = {}) {\n return items ? items.map(d => new this(d, options)) : [];\n }\n\n /**\n * Fetch item from server\n */\n static fetch(url, {\n many = false,\n ...options\n } = {}, args = {}) {\n options = this.getOptions(options);\n const request = fetch(url, options).then(response => response.json());\n if (many) return request.then(data => {\n if (!(data instanceof Array)) data = data.results;\n return this.fromList(data, args);\n });else return request.then(data => new this(data, {\n url: url,\n ...args\n }));\n }\n\n /**\n * Fetch data from server.\n */\n fetch(options) {\n options = this.constructor.getOptions(options);\n return fetch(this.url, options).then(response => response.json()).then(data => this.commit(data));\n }\n\n /**\n * Call API action on object.\n */\n action(path, options, commit = false) {\n options = this.constructor.getOptions(options);\n const promise = fetch(this.url + path, options);\n return commit ? promise.then(data => data.json()).then(data => {\n this.commit(data);\n this.data;\n }) : promise;\n }\n\n /**\n * Update instance's data with provided data. Return None\n */\n commit(data) {\n this.data = data;\n this.id = this.constructor.getId(this.data);\n }\n\n /**\n * Update model data, without reset previous value\n */\n update(data) {\n this.data = {\n ...this.data,\n ...data\n };\n this.id = this.constructor.getId(this.data);\n }\n\n /**\n * Save instance into localStorage.\n */\n store(key) {\n window.localStorage.setItem(key, JSON.stringify(this.data));\n }\n\n /**\n * Load model instance from localStorage.\n */\n static storeLoad(key) {\n let item = window.localStorage.getItem(key);\n return item === null ? item : new this(JSON.parse(item));\n }\n\n /**\n * Return true if model instance has no data\n */\n get isEmpty() {\n return !this.data || Object.keys(this.data).findIndex(k => !!this.data[k] && this.data[k] !== 0) == -1;\n }\n\n /**\n * Return error for a specific attribute name if any \n */\n error(attr = null) {\n return attr === null ? this.errors : this.errors && this.errors[attr];\n }\n}\n\n/**\n * List of models\n */\nclass Set {\n constructor(model, {\n items = [],\n url = null,\n args = {},\n unique = null,\n max = null,\n storeKey = null\n } = {}) {\n this.items = [];\n this.model = model;\n this.url = url;\n this.unique = unique;\n this.max = max;\n this.storeKey = storeKey;\n for (var item of items) this.push(item, {\n args: args,\n save: false\n });\n }\n get length() {\n return this.items.length;\n }\n\n /**\n * Fetch multiple items from server\n */\n static fetch(model, url, options = null, args = null) {\n options = model.getOptions(options);\n return fetch(url, options).then(response => response.json()).then(data => (data instanceof Array ? data : data.results).map(d => new model(d, {\n url: url,\n ...args\n })));\n }\n\n /**\n * Load list from localStorage\n */\n static storeLoad(model, key, args = {}) {\n let items = window.localStorage.getItem(key);\n return new this(model, {\n ...args,\n storeKey: key,\n items: items ? JSON.parse(items) : []\n });\n }\n\n /**\n * Store list into localStorage\n */\n store() {\n this.storeKey && window.localStorage.setItem(this.storeKey, JSON.stringify(this.items.map(i => i.data)));\n }\n\n /**\n * Save item\n */\n save() {\n this.storeKey && this.store();\n }\n\n /**\n * Get item at index\n */\n get(index) {\n return this.items[index];\n }\n\n /**\n * Find an item by id or using a predicate function\n */\n find(pred) {\n return pred instanceof Function ? this.items.find(pred) : this.items.find(x => x.id == pred.id);\n }\n\n /**\n * Find item index by id or using a predicate function\n */\n findIndex(pred) {\n return pred instanceof Function ? this.items.findIndex(pred) : this.items.findIndex(x => x.id == pred.id);\n }\n\n /**\n * Add item to set, return index.\n */\n push(item, {\n args = {},\n save = true\n } = {}) {\n item = item instanceof this.model ? item : new this.model(item, args);\n if (this.unique) {\n let index = this.findIndex(item);\n if (index > -1) return index;\n }\n if (this.max && this.items.length >= this.max) this.items.splice(0, this.items.length - this.max);\n this.items.push(item);\n save && this.save();\n return this.items.length - 1;\n }\n\n /**\n * Remove item from set by index\n */\n remove(index, {\n save = true\n } = {}) {\n this.items.splice(index, 1);\n save && this.save();\n }\n\n /**\n * Clear items, assign new ones\n */\n reset(items = []) {\n // TODO: check reactivity\n this.items = [];\n for (var item of items) this.push(item);\n }\n move(from, to) {\n if (from >= this.length || to > this.length) throw \"source or target index is not in range\";\n const value = this.items[from];\n this.items.splice(from, 1);\n this.items.splice(to, 0, value);\n }\n}\nSet[Symbol.iterator] = function () {\n return this.items[Symbol.iterator]();\n};\n\n//# sourceURL=webpack://aircox-assets/./src/model.js?"); /***/ }), diff --git a/aircox/templates/admin/aircox/playlist_inline.html b/aircox/templates/admin/aircox/playlist_inline.html index 5d1312e..45e371a 100644 --- a/aircox/templates/admin/aircox/playlist_inline.html +++ b/aircox/templates/admin/aircox/playlist_inline.html @@ -10,6 +10,9 @@ {% for field in admin_formset.fields %} {% if not field.widget.is_hidden and not field.is_readonly %} - - @@ -85,13 +77,6 @@ const Component = { }, methods: { - validateExtraCell() { - if(!this.allowCreate) - return - this.set.push(this.extraItem) - this.extraItem = new this.set.model() - }, - onControlKey(event, cell) { switch(event.key) { case "ArrowUp": this.focus(-1, 0, cell) diff --git a/assets/src/model.js b/assets/src/model.js index 55266da..1277c54 100644 --- a/assets/src/model.js +++ b/assets/src/model.js @@ -42,7 +42,7 @@ export default class Model { } get errors() { - return this.data.__errors__ + return this.data && this.data.__errors__ } /** @@ -143,6 +143,13 @@ export default class Model { return item === null ? item : new this(JSON.parse(item)); } + /** + * Return true if model instance has no data + */ + get isEmpty() { + return !this.data || Object.keys(this.data).findIndex(k => !!this.data[k] && this.data[k] !== 0) == -1 + } + /** * Return error for a specific attribute name if any */