From 7ab0b907c5905da721b9a367df709cebf0e6c091 Mon Sep 17 00:00:00 2001 From: Peter Deltchev Date: Sun, 14 Feb 2016 01:29:02 -0800 Subject: [PATCH] Fixed the release date picker. - upgraded ui-date to the newest version - made adjustments to keep this date in UTC - fixed the picker's broken images --- app/Commands/EditTrackCommand.php | 7 +- app/Models/Track.php | 2 +- .../styles/base/images/animated-overlay.gif | Bin .../styles/base/images/border.png | Bin .../styles/base/images/loading_background.png | Bin .../styles/base/images/overlay.png | Bin .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin .../images/ui-bg_flat_75_ffffff_40x100.png | Bin .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin .../images/ui-bg_glass_65_ffffff_1x400.png | Bin .../images/ui-bg_glass_75_dadada_1x400.png | Bin .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin .../base/images/ui-icons_222222_256x240.png | Bin .../base/images/ui-icons_2e83ff_256x240.png | Bin .../base/images/ui-icons_454545_256x240.png | Bin .../base/images/ui-icons_888888_256x240.png | Bin .../base/images/ui-icons_cd0a0a_256x240.png | Bin public/templates/directives/track-editor.html | 9 +- .../app/directives/track-editor.coffee | 14 +- .../assets/scripts/base/angular-ui-date.js | 386 +++++++++++++----- .../assets/styles/base/images/controls.png | Bin 1633 -> 0 bytes .../assets/styles/base/images/loading.gif | Bin 9427 -> 0 bytes 24 files changed, 301 insertions(+), 117 deletions(-) rename {resources/assets => public}/styles/base/images/animated-overlay.gif (100%) rename {resources/assets => public}/styles/base/images/border.png (100%) rename {resources/assets => public}/styles/base/images/loading_background.png (100%) rename {resources/assets => public}/styles/base/images/overlay.png (100%) rename {resources/assets => public}/styles/base/images/ui-bg_flat_0_aaaaaa_40x100.png (100%) rename {resources/assets => public}/styles/base/images/ui-bg_flat_75_ffffff_40x100.png (100%) rename {resources/assets => public}/styles/base/images/ui-bg_glass_55_fbf9ee_1x400.png (100%) rename {resources/assets => public}/styles/base/images/ui-bg_glass_65_ffffff_1x400.png (100%) rename {resources/assets => public}/styles/base/images/ui-bg_glass_75_dadada_1x400.png (100%) rename {resources/assets => public}/styles/base/images/ui-bg_glass_75_e6e6e6_1x400.png (100%) rename {resources/assets => public}/styles/base/images/ui-bg_glass_95_fef1ec_1x400.png (100%) rename {resources/assets => public}/styles/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png (100%) rename {resources/assets => public}/styles/base/images/ui-icons_222222_256x240.png (100%) rename {resources/assets => public}/styles/base/images/ui-icons_2e83ff_256x240.png (100%) rename {resources/assets => public}/styles/base/images/ui-icons_454545_256x240.png (100%) rename {resources/assets => public}/styles/base/images/ui-icons_888888_256x240.png (100%) rename {resources/assets => public}/styles/base/images/ui-icons_cd0a0a_256x240.png (100%) delete mode 100644 resources/assets/styles/base/images/controls.png delete mode 100644 resources/assets/styles/base/images/loading.gif diff --git a/app/Commands/EditTrackCommand.php b/app/Commands/EditTrackCommand.php index 10f42a04..b7329ef0 100644 --- a/app/Commands/EditTrackCommand.php +++ b/app/Commands/EditTrackCommand.php @@ -61,8 +61,11 @@ class EditTrackCommand extends CommandBase $rules = [ 'title' => 'required|min:3|max:80', - 'released_at' => 'before:' . (date('Y-m-d', - time() + (86400 * 2))) . (isset($this->_input['released_at']) && $this->_input['released_at'] != "" ? '|date' : ''), + 'released_at' => 'before:' . + (date('Y-m-d', time() + (86400 * 2))) . ( + isset($this->_input['released_at']) && $this->_input['released_at'] != "" + ? '|date' + : ''), 'license_id' => 'required|exists:licenses,id', 'genre_id' => 'required|exists:genres,id', 'cover' => 'image|mimes:png,jpeg|min_width:350|min_height:350', diff --git a/app/Models/Track.php b/app/Models/Track.php index f4cf435b..3dafea24 100644 --- a/app/Models/Track.php +++ b/app/Models/Track.php @@ -441,7 +441,7 @@ class Track extends Model implements Searchable $returnValue['show_songs'] = $showSongs; $returnValue['real_cover_url'] = $track->getCoverUrl(Image::NORMAL); $returnValue['cover_url'] = $track->hasCover() ? $track->getCoverUrl(Image::NORMAL) : null; - $returnValue['released_at'] = $track->released_at; + $returnValue['released_at'] = $track->released_at ? $track->released_at->toDateString() : null; $returnValue['lyrics'] = $track->lyrics; $returnValue['description'] = $track->description; $returnValue['is_downloadable'] = !$track->isPublished() ? true : (bool) $track->is_downloadable; diff --git a/resources/assets/styles/base/images/animated-overlay.gif b/public/styles/base/images/animated-overlay.gif similarity index 100% rename from resources/assets/styles/base/images/animated-overlay.gif rename to public/styles/base/images/animated-overlay.gif diff --git a/resources/assets/styles/base/images/border.png b/public/styles/base/images/border.png similarity index 100% rename from resources/assets/styles/base/images/border.png rename to public/styles/base/images/border.png diff --git a/resources/assets/styles/base/images/loading_background.png b/public/styles/base/images/loading_background.png similarity index 100% rename from resources/assets/styles/base/images/loading_background.png rename to public/styles/base/images/loading_background.png diff --git a/resources/assets/styles/base/images/overlay.png b/public/styles/base/images/overlay.png similarity index 100% rename from resources/assets/styles/base/images/overlay.png rename to public/styles/base/images/overlay.png diff --git a/resources/assets/styles/base/images/ui-bg_flat_0_aaaaaa_40x100.png b/public/styles/base/images/ui-bg_flat_0_aaaaaa_40x100.png similarity index 100% rename from resources/assets/styles/base/images/ui-bg_flat_0_aaaaaa_40x100.png rename to public/styles/base/images/ui-bg_flat_0_aaaaaa_40x100.png diff --git a/resources/assets/styles/base/images/ui-bg_flat_75_ffffff_40x100.png b/public/styles/base/images/ui-bg_flat_75_ffffff_40x100.png similarity index 100% rename from resources/assets/styles/base/images/ui-bg_flat_75_ffffff_40x100.png rename to public/styles/base/images/ui-bg_flat_75_ffffff_40x100.png diff --git a/resources/assets/styles/base/images/ui-bg_glass_55_fbf9ee_1x400.png b/public/styles/base/images/ui-bg_glass_55_fbf9ee_1x400.png similarity index 100% rename from resources/assets/styles/base/images/ui-bg_glass_55_fbf9ee_1x400.png rename to public/styles/base/images/ui-bg_glass_55_fbf9ee_1x400.png diff --git a/resources/assets/styles/base/images/ui-bg_glass_65_ffffff_1x400.png b/public/styles/base/images/ui-bg_glass_65_ffffff_1x400.png similarity index 100% rename from resources/assets/styles/base/images/ui-bg_glass_65_ffffff_1x400.png rename to public/styles/base/images/ui-bg_glass_65_ffffff_1x400.png diff --git a/resources/assets/styles/base/images/ui-bg_glass_75_dadada_1x400.png b/public/styles/base/images/ui-bg_glass_75_dadada_1x400.png similarity index 100% rename from resources/assets/styles/base/images/ui-bg_glass_75_dadada_1x400.png rename to public/styles/base/images/ui-bg_glass_75_dadada_1x400.png diff --git a/resources/assets/styles/base/images/ui-bg_glass_75_e6e6e6_1x400.png b/public/styles/base/images/ui-bg_glass_75_e6e6e6_1x400.png similarity index 100% rename from resources/assets/styles/base/images/ui-bg_glass_75_e6e6e6_1x400.png rename to public/styles/base/images/ui-bg_glass_75_e6e6e6_1x400.png diff --git a/resources/assets/styles/base/images/ui-bg_glass_95_fef1ec_1x400.png b/public/styles/base/images/ui-bg_glass_95_fef1ec_1x400.png similarity index 100% rename from resources/assets/styles/base/images/ui-bg_glass_95_fef1ec_1x400.png rename to public/styles/base/images/ui-bg_glass_95_fef1ec_1x400.png diff --git a/resources/assets/styles/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/public/styles/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png similarity index 100% rename from resources/assets/styles/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png rename to public/styles/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png diff --git a/resources/assets/styles/base/images/ui-icons_222222_256x240.png b/public/styles/base/images/ui-icons_222222_256x240.png similarity index 100% rename from resources/assets/styles/base/images/ui-icons_222222_256x240.png rename to public/styles/base/images/ui-icons_222222_256x240.png diff --git a/resources/assets/styles/base/images/ui-icons_2e83ff_256x240.png b/public/styles/base/images/ui-icons_2e83ff_256x240.png similarity index 100% rename from resources/assets/styles/base/images/ui-icons_2e83ff_256x240.png rename to public/styles/base/images/ui-icons_2e83ff_256x240.png diff --git a/resources/assets/styles/base/images/ui-icons_454545_256x240.png b/public/styles/base/images/ui-icons_454545_256x240.png similarity index 100% rename from resources/assets/styles/base/images/ui-icons_454545_256x240.png rename to public/styles/base/images/ui-icons_454545_256x240.png diff --git a/resources/assets/styles/base/images/ui-icons_888888_256x240.png b/public/styles/base/images/ui-icons_888888_256x240.png similarity index 100% rename from resources/assets/styles/base/images/ui-icons_888888_256x240.png rename to public/styles/base/images/ui-icons_888888_256x240.png diff --git a/resources/assets/styles/base/images/ui-icons_cd0a0a_256x240.png b/public/styles/base/images/ui-icons_cd0a0a_256x240.png similarity index 100% rename from resources/assets/styles/base/images/ui-icons_cd0a0a_256x240.png rename to public/styles/base/images/ui-icons_cd0a0a_256x240.png diff --git a/public/templates/directives/track-editor.html b/public/templates/directives/track-editor.html index 2dcf68e4..f2bf656e 100644 --- a/public/templates/directives/track-editor.html +++ b/public/templates/directives/track-editor.html @@ -86,7 +86,14 @@
- +
{{errors.released_at}}
diff --git a/resources/assets/scripts/app/directives/track-editor.coffee b/resources/assets/scripts/app/directives/track-editor.coffee index 1dc4355f..d7b00e07 100644 --- a/resources/assets/scripts/app/directives/track-editor.coffee +++ b/resources/assets/scripts/app/directives/track-editor.coffee @@ -99,6 +99,10 @@ angular.module('ponyfm').directive 'pfmTrackEditor', () -> return if value == null if typeof(value) == 'object' formData.append name, value, value.name + + if name == 'released_at' and value != null + formData.append name, value.toISOString() + else if value != null formData.append name, value @@ -136,6 +140,14 @@ angular.module('ponyfm').directive 'pfmTrackEditor', () -> $scope.albums.push album # Update track data + + # The release date is in UTC - make sure we treat it as such. + if track.released_at + local_date = new Date(track.released_at) + utc_release_timestamp = local_date.getTime() + (local_date.getTimezoneOffset() * 60000); + utc_release_date = new Date(utc_release_timestamp) + else utc_release_date = '' + $scope.track = id: track.id title: track.title @@ -147,7 +159,7 @@ angular.module('ponyfm').directive 'pfmTrackEditor', () -> license_id: track.license_id genre_id: track.genre_id track_type_id: track.track_type_id - released_at: if track.released_at then track.released_at.date else '' + released_at: utc_release_date remove_cover: false cover: track.cover_url album_id: track.album_id diff --git a/resources/assets/scripts/base/angular-ui-date.js b/resources/assets/scripts/base/angular-ui-date.js index f405d5a7..4d583f70 100644 --- a/resources/assets/scripts/base/angular-ui-date.js +++ b/resources/assets/scripts/base/angular-ui-date.js @@ -1,121 +1,283 @@ -/*global angular */ -/* - jQuery UI Datepicker plugin wrapper +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("jquery"), require("angular"), require("jquery-ui/datepicker")); + else if(typeof define === 'function' && define.amd) + define(["jquery", "angular", "jquery-ui/datepicker"], factory); + else if(typeof exports === 'object') + exports["angularUiDate"] = factory(require("jquery"), require("angular"), require("jquery-ui/datepicker")); + else + root["angularUiDate"] = factory(root["jQuery"], root["angular"], root["jquery-ui/datepicker"]); +})(this, function(__WEBPACK_EXTERNAL_MODULE_1__, __WEBPACK_EXTERNAL_MODULE_2__, __WEBPACK_EXTERNAL_MODULE_3__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; - @note If ≤ IE8 make sure you have a polyfill for Date.toISOString() - @param [ui-date] {object} Options to pass to $.fn.datepicker() merged onto uiDateConfig - */ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { -angular.module('ui.date', []) +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; -.constant('uiDateConfig', {}) +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; -.directive('uiDate', ['uiDateConfig', '$timeout', function (uiDateConfig, $timeout) { - 'use strict'; - var options; - options = {}; - angular.extend(options, uiDateConfig); - return { - require:'?ngModel', - link:function (scope, element, attrs, controller) { - var getOptions = function () { - return angular.extend({}, uiDateConfig, scope.$eval(attrs.uiDate)); - }; - var initDateWidget = function () { - var showing = false; - var opts = getOptions(); +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); - // If we have a controller (i.e. ngModelController) then wire it up - if (controller) { +/******/ // Flag the module as loaded +/******/ module.loaded = true; - // Set the view value in a $apply block when users selects - // (calling directive user's function too if provided) - var _onSelect = opts.onSelect || angular.noop; - opts.onSelect = function (value, picker) { - scope.$apply(function() { - showing = true; - controller.$setViewValue(element.datepicker("getDate")); - _onSelect(value, picker); - element.blur(); - }); - }; - opts.beforeShow = function() { - showing = true; - }; - opts.onClose = function(value, picker) { - showing = false; - }; - element.on('blur', function() { - if ( !showing ) { - scope.$apply(function() { - element.datepicker("setDate", element.datepicker("getDate")); - controller.$setViewValue(element.datepicker("getDate")); - }); - } - }); +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } - // Update the date picker when the model changes - controller.$render = function () { - var date = controller.$viewValue; - if ( angular.isDefined(date) && date !== null && !angular.isDate(date) ) { - throw new Error('ng-Model value must be a Date object - currently it is a ' + typeof date + ' - use ui-date-format to convert it from a string'); - } - element.datepicker("setDate", date); - }; - } - // If we don't destroy the old one it doesn't update properly when the config changes - element.datepicker('destroy'); - // Create the new datepicker widget - element.datepicker(opts); - if ( controller ) { - // Force a render to override whatever is in the input text box - controller.$render(); - } - }; - // Watch for changes to the directives options - scope.$watch(getOptions, initDateWidget, true); - } - }; -} -]) -.constant('uiDateFormatConfig', '') +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; -.directive('uiDateFormat', ['uiDateFormatConfig', function(uiDateFormatConfig) { - var directive = { - require:'ngModel', - link: function(scope, element, attrs, modelCtrl) { - var dateFormat = attrs.uiDateFormat || uiDateFormatConfig; - if ( dateFormat ) { - // Use the datepicker with the attribute value as the dateFormat string to convert to and from a string - modelCtrl.$formatters.push(function(value) { - if (angular.isString(value) ) { - return jQuery.datepicker.parseDate(dateFormat, value); - } - return null; - }); - modelCtrl.$parsers.push(function(value){ - if (value) { - return jQuery.datepicker.formatDate(dateFormat, value); - } - return null; - }); - } else { - // Default to ISO formatting - modelCtrl.$formatters.push(function(value) { - if (angular.isString(value) ) { - return new Date(value); - } - return null; - }); - modelCtrl.$parsers.push(function(value){ - if (value) { - return value.toISOString(); - } - return null; - }); - } - } - }; - return directive; -}]); +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = "assets"; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + var _jquery = __webpack_require__(1); + + var _jquery2 = _interopRequireDefault(_jquery); + + var _angular = __webpack_require__(2); + + var _angular2 = _interopRequireDefault(_angular); + + var _datepicker = __webpack_require__(3); + + var _datepicker2 = _interopRequireDefault(_datepicker); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + // sets up jQuery with the datepicker plugin + + exports.default = _angular2.default.module('ui.date', []).constant('uiDateConfig', {}).constant('uiDateFormatConfig', '').factory('uiDateConverter', ['uiDateFormatConfig', function (uiDateFormatConfig) { + return { + stringToDate: stringToDate, + dateToString: dateToString + }; + + function dateToString(dateFormat, value) { + dateFormat = dateFormat || uiDateFormatConfig; + if (value) { + if (dateFormat) { + try { + return _jquery2.default.datepicker.formatDate(dateFormat, value); + } catch (formatException) { + return undefined; + } + } + + if (value.toISOString) { + return value.toISOString(); + } + } + return null; + } + + function stringToDate(dateFormat, valueToParse) { + dateFormat = dateFormat || uiDateFormatConfig; + + if (_angular2.default.isDate(valueToParse) && !isNaN(valueToParse)) { + return valueToParse; + } + + if (_angular2.default.isString(valueToParse)) { + if (dateFormat) { + return _jquery2.default.datepicker.parseDate(dateFormat, valueToParse); + } + + var isoDate = new Date(valueToParse); + return isNaN(isoDate.getTime()) ? null : isoDate; + } + + if (_angular2.default.isNumber(valueToParse)) { + // presumably timestamp to date object + return new Date(valueToParse); + } + + return null; + } + }]).directive('uiDate', ['uiDateConfig', 'uiDateConverter', function uiDateDirective(uiDateConfig, uiDateConverter) { + + return { + require: '?ngModel', + link: function link(scope, element, attrs, controller) { + + var $element = (0, _jquery2.default)(element); + + var getOptions = function getOptions() { + return _angular2.default.extend({}, uiDateConfig, scope.$eval(attrs.uiDate)); + }; + var initDateWidget = function initDateWidget() { + var showing = false; + var opts = getOptions(); + + function setVal() { + var keys = ['Hours', 'Minutes', 'Seconds', 'Milliseconds']; + var isDate = _angular2.default.isDate(controller.$modelValue); + var preserve = {}; + + if (isDate && controller.$modelValue.toDateString() === $element.datepicker('getDate').toDateString()) { + return; + } + + if (isDate) { + _angular2.default.forEach(keys, function (key) { + preserve[key] = controller.$modelValue['get' + key](); + }); + } + + var newViewValue = $element.datepicker('getDate'); + + if (isDate) { + _angular2.default.forEach(keys, function (key) { + newViewValue['set' + key](preserve[key]); + }); + } + + controller.$setViewValue(newViewValue); + } + + // If we have a controller (i.e. ngModelController) then wire it up + if (controller) { + // Set the view value in a $apply block when users selects + // (calling directive user's function too if provided) + var _onSelect = opts.onSelect || _angular2.default.noop; + opts.onSelect = function (value, picker) { + scope.$apply(function () { + showing = true; + setVal(); + _onSelect(value, picker); + $element.blur(); + }); + }; + + var _beforeShow = opts.beforeShow || _angular2.default.noop; + opts.beforeShow = function (input, picker) { + showing = true; + _beforeShow(input, picker); + }; + + var _onClose = opts.onClose || _angular2.default.noop; + opts.onClose = function (value, picker) { + showing = false; + _onClose(value, picker); + }; + + $element.off('blur.datepicker').on('blur.datepicker', function () { + if (!showing) { + scope.$apply(function () { + $element.datepicker('setDate', $element.datepicker('getDate')); + setVal(); + }); + } + }); + + controller.$validators.uiDateValidator = function uiDateValidator(modelValue, viewValue) { + return _angular2.default.isDate(uiDateConverter.stringToDate(attrs.uiDateFormat, viewValue)); + }; + + controller.$parsers.push(function uiDateParser(valueToParse) { + return uiDateConverter.stringToDate(attrs.uiDateFormat, valueToParse); + }); + + // Update the date picker when the model changes + controller.$render = function () { + $element.datepicker('setDate', controller.$modelValue); + }; + } + // Check if the $element already has a datepicker. + // + + if ($element.data('datepicker')) { + // Updates the datepicker options + $element.datepicker('option', opts); + $element.datepicker('refresh'); + } else { + // Creates the new datepicker widget + $element.datepicker(opts); + + // Cleanup on destroy, prevent memory leaking + $element.on('$destroy', function () { + $element.datepicker('hide'); + $element.datepicker('destroy'); + }); + } + + if (controller) { + // Force a render to override whatever is in the input text box + controller.$render(); + } + }; + + // Watch for changes to the directives options + scope.$watch(getOptions, initDateWidget, true); + } + }; + }]).directive('uiDateFormat', ['uiDateConverter', function (uiDateConverter) { + return { + require: 'ngModel', + link: function link(scope, element, attrs, modelCtrl) { + var dateFormat = attrs.uiDateFormat; + + // Use the datepicker with the attribute value as the dateFormat string to convert to and from a string + modelCtrl.$formatters.unshift(function (value) { + return uiDateConverter.stringToDate(dateFormat, value); + }); + + modelCtrl.$parsers.push(function (value) { + return uiDateConverter.dateToString(dateFormat, value); + }); + } + }; + }]); + +/***/ }, +/* 1 */ +/***/ function(module, exports) { + + module.exports = __WEBPACK_EXTERNAL_MODULE_1__; + +/***/ }, +/* 2 */ +/***/ function(module, exports) { + + module.exports = __WEBPACK_EXTERNAL_MODULE_2__; + +/***/ }, +/* 3 */ +/***/ function(module, exports) { + + module.exports = __WEBPACK_EXTERNAL_MODULE_3__; + +/***/ } +/******/ ]) +}); +; +//# sourceMappingURL=date.js.map diff --git a/resources/assets/styles/base/images/controls.png b/resources/assets/styles/base/images/controls.png deleted file mode 100644 index e1e97982a6b4038f0aae1f9e2e7fa4d89df68841..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1633 zcmV-n2A=teP)gwz2>+9y`=TcHq z-rnCuMn^(ILOMD+EiEn~AtAlJz0c6nGcz;A#m3Up)UB_vr>Lo=rKXvgnU9c?i;Iim z;R<0n*sHVxX1Wu=dDmb5@ zoduu*GO7Y3gN)R3LlCkA83ANu{udpGM*u$>gP0`<1_F8BNfnW-jvET2ri(~grcgs6 zfuNc}C`52O?KU>*_xBwlz$`(9h!7a5Xz`@Dfk^XqtL=`O&7MbyN*s{1cohspL^?w` zCJbt{9v>V2SM#J8C>P7Se={P=10MX=2jpbh>VWAOZ`4loT=P^~`R! z;id=$u@Od+m^K=9-@%NRBn(CZNpZq6&5@6g(`ZoI9)5wt!^aKD^z=@#Am195`0Y`!+$%p9c^CoEQgtOp5 zEEcDUb#KOlSex@S5iLQS2y^-+;ZIF|1UAxyZ{Y_TYaYbh#94ll@a=j?n6ogKmGGQ7 zu5N~n{5auRbxdHR(d%}*Gge|&-)9oTqXZGC!A?v^)WCU^aP1K#u)#ixQOY2MYgwb1 zQGiGo4k29I#st9$vMx?gBP7Mh{wQkmjt!+NK5(D1jEohRaI0HZk_dBDoB@dwAf&fhv$fjCdZNhQ<5A@t3*Uq1SKU_ z388}$(?g;PO09|sv0Oq#KnEqK1Ep+20b1FF28^-^1E7+Jp&@{vRHh(7OdzO~Cn)f+ zMpa5ed{x3CKtw zIjm=9~S z64&923<&Y#NBx+n|9Tn!B*WlGV1p8mZ+|0G)5x3`z^_<4m%OOPtq+R zx=*X^VHnsL6e7Z@h#Ade;$UE8&}ApcOhraO2-I4UVPIpA^otN=7>BSx2vohCaMdIv@Ur#r=q^%~zIp~i|2G5+~_YKx?`GWihq zr|&?z77t?7{=eO->2l8W0;7=B8p=plgrXCrz;i%N;_+EX@Qfhv`MBi>a0xK~6byma z5miB?_OlZTfAvRngQFlJ$A8OE=PEDPSfI@teg&4n|@EB5r09gnqfi%%sK5sU5ng9~KoTyQO6214=+ud?G zp#(K*ml1}pP=FHVpWU6m`1Afgr36jUjnjmoig`A?7XREdef;NUcb{vwNmPwbLd&~Y z&szSTYWsQj{WLKWiHb4C6Z00000NkvXXu0mjf#Rc%Z diff --git a/resources/assets/styles/base/images/loading.gif b/resources/assets/styles/base/images/loading.gif deleted file mode 100644 index 19c67bbd0403f3f00d71bfb21a59cb6c55d482ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9427 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