From ff2a85a988ba2387a0fb310f362dd2074c1f9bc8 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 3 Apr 2024 12:27:55 +0100 Subject: [PATCH 01/14] ID-2946 [Feat] Updates UI to match design (#1) * ID-3900 Discard data source entry loading method * Tweaks copy for update type * ID-3904 Updates interface to use config framework * ID-3904 Updates update options to use HTML tags * ID-3899 Improve loading states * Removes unused node attributes * Initialize children widgets * Cleanup * ID-4113 Improves management for loading and D&D states * Fix XSS vulnerability --- .eslintrc | 5 +- build.html | 23 +- css/build.css | 3 + dist/app.js | 310 ++----- js/build.js | 399 +++++---- js/interface.js | 29 + package-lock.json | 1126 +++++++++++++++++++++++++ package.json | 37 +- src/Application.vue | 37 - src/components/DataSourceProvider.vue | 51 -- src/components/LoadSourceOption.vue | 43 - src/components/UpdateType.vue | 49 -- src/main.js | 8 - src/scss/index.scss | 13 - src/state.js | 1 - translation.json | 10 + widget.json | 27 +- 17 files changed, 1486 insertions(+), 685 deletions(-) create mode 100644 css/build.css create mode 100644 js/interface.js create mode 100644 package-lock.json delete mode 100644 src/Application.vue delete mode 100644 src/components/DataSourceProvider.vue delete mode 100644 src/components/LoadSourceOption.vue delete mode 100644 src/components/UpdateType.vue delete mode 100644 src/main.js delete mode 100644 src/scss/index.scss delete mode 100644 src/state.js create mode 100644 translation.json diff --git a/.eslintrc b/.eslintrc index 15f946e..cd768ff 100644 --- a/.eslintrc +++ b/.eslintrc @@ -6,9 +6,10 @@ "plugin:vue/essential" ], "globals": { - "Vue": true + "Vue": true, + "CryptoJS": true }, "rules": { "no-new": 0 } -} \ No newline at end of file +} diff --git a/build.html b/build.html index c17b8c6..e90518a 100644 --- a/build.html +++ b/build.html @@ -1 +1,22 @@ -{{{ content }}} \ No newline at end of file + + + + + + + + + diff --git a/css/build.css b/css/build.css new file mode 100644 index 0000000..b689514 --- /dev/null +++ b/css/build.css @@ -0,0 +1,3 @@ +fl-record-container .record-container-load-error { + text-align: center; +} diff --git a/dist/app.js b/dist/app.js index 4680932..1a07ddb 100644 --- a/dist/app.js +++ b/dist/app.js @@ -105,8 +105,8 @@ new Vue({ "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _Application_vue_vue_type_template_id_44b1e432___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); -/* harmony import */ var _Application_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); +/* harmony import */ var _Application_vue_vue_type_template_id_44b1e432__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var _Application_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); /* empty/unused harmony star reexport *//* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(12); @@ -116,9 +116,9 @@ __webpack_require__.r(__webpack_exports__); /* normalize component */ var component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__["default"])( - _Application_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__["default"], - _Application_vue_vue_type_template_id_44b1e432___WEBPACK_IMPORTED_MODULE_0__["render"], - _Application_vue_vue_type_template_id_44b1e432___WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"], + _Application_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_1__["default"], + _Application_vue_vue_type_template_id_44b1e432__WEBPACK_IMPORTED_MODULE_0__["render"], + _Application_vue_vue_type_template_id_44b1e432__WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"], false, null, null, @@ -137,10 +137,10 @@ component.options.__file = "src/Application.vue" "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_Application_vue_vue_type_template_id_44b1e432___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); -/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "render", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_Application_vue_vue_type_template_id_44b1e432___WEBPACK_IMPORTED_MODULE_0__["render"]; }); +/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_Application_vue_vue_type_template_id_44b1e432__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "render", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_Application_vue_vue_type_template_id_44b1e432__WEBPACK_IMPORTED_MODULE_0__["render"]; }); -/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "staticRenderFns", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_Application_vue_vue_type_template_id_44b1e432___WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"]; }); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "staticRenderFns", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_Application_vue_vue_type_template_id_44b1e432__WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"]; }); @@ -164,8 +164,6 @@ var render = function () { on: { saved: _vm.dataSourceProviderSave }, }), _vm._v(" "), - _c("Load-Source-Option"), - _vm._v(" "), _c("Update-Type"), ], 1 @@ -182,8 +180,8 @@ render._withStripped = true "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _node_modules_babel_loader_lib_index_js_ref_3_0_node_modules_vue_loader_lib_index_js_vue_loader_options_Application_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5); -/* empty/unused harmony star reexport */ /* harmony default export */ __webpack_exports__["default"] = (_node_modules_babel_loader_lib_index_js_ref_3_0_node_modules_vue_loader_lib_index_js_vue_loader_options_Application_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__["default"]); +/* harmony import */ var _node_modules_babel_loader_lib_index_js_ref_3_0_node_modules_vue_loader_lib_index_js_vue_loader_options_Application_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5); +/* empty/unused harmony star reexport */ /* harmony default export */ __webpack_exports__["default"] = (_node_modules_babel_loader_lib_index_js_ref_3_0_node_modules_vue_loader_lib_index_js_vue_loader_options_Application_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_0__["default"]); /***/ }), /* 5 */ @@ -193,9 +191,7 @@ __webpack_require__.r(__webpack_exports__); __webpack_require__.r(__webpack_exports__); /* harmony import */ var _state__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); /* harmony import */ var _components_DataSourceProvider__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7); -/* harmony import */ var _components_LoadSourceOption__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(13); -/* harmony import */ var _components_UpdateType__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(18); -// +/* harmony import */ var _components_UpdateType__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(13); // // // @@ -213,8 +209,7 @@ __webpack_require__.r(__webpack_exports__); }, components: { DataSourceProvider: _components_DataSourceProvider__WEBPACK_IMPORTED_MODULE_1__["default"], - LoadSourceOption: _components_LoadSourceOption__WEBPACK_IMPORTED_MODULE_2__["default"], - UpdateType: _components_UpdateType__WEBPACK_IMPORTED_MODULE_3__["default"] + UpdateType: _components_UpdateType__WEBPACK_IMPORTED_MODULE_2__["default"] }, methods: { dataSourceProviderSave: function dataSourceProviderSave() { @@ -225,7 +220,6 @@ __webpack_require__.r(__webpack_exports__); }, mounted: function mounted() { var _this = this; - Fliplet.Widget.onSaveRequest(function () { _this.$refs.dataSourceProvider.forwardSaveRequest(); }); @@ -246,8 +240,8 @@ __webpack_require__.r(__webpack_exports__); "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _DataSourceProvider_vue_vue_type_template_id_99b22eb4___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8); -/* harmony import */ var _DataSourceProvider_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(10); +/* harmony import */ var _DataSourceProvider_vue_vue_type_template_id_99b22eb4__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8); +/* harmony import */ var _DataSourceProvider_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(10); /* empty/unused harmony star reexport *//* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(12); @@ -257,9 +251,9 @@ __webpack_require__.r(__webpack_exports__); /* normalize component */ var component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__["default"])( - _DataSourceProvider_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__["default"], - _DataSourceProvider_vue_vue_type_template_id_99b22eb4___WEBPACK_IMPORTED_MODULE_0__["render"], - _DataSourceProvider_vue_vue_type_template_id_99b22eb4___WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"], + _DataSourceProvider_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_1__["default"], + _DataSourceProvider_vue_vue_type_template_id_99b22eb4__WEBPACK_IMPORTED_MODULE_0__["render"], + _DataSourceProvider_vue_vue_type_template_id_99b22eb4__WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"], false, null, null, @@ -278,10 +272,10 @@ component.options.__file = "src/components/DataSourceProvider.vue" "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_DataSourceProvider_vue_vue_type_template_id_99b22eb4___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9); -/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "render", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_DataSourceProvider_vue_vue_type_template_id_99b22eb4___WEBPACK_IMPORTED_MODULE_0__["render"]; }); +/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_DataSourceProvider_vue_vue_type_template_id_99b22eb4__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "render", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_DataSourceProvider_vue_vue_type_template_id_99b22eb4__WEBPACK_IMPORTED_MODULE_0__["render"]; }); -/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "staticRenderFns", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_DataSourceProvider_vue_vue_type_template_id_99b22eb4___WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"]; }); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "staticRenderFns", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_DataSourceProvider_vue_vue_type_template_id_99b22eb4__WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"]; }); @@ -310,8 +304,8 @@ render._withStripped = true "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _node_modules_babel_loader_lib_index_js_ref_3_0_node_modules_vue_loader_lib_index_js_vue_loader_options_DataSourceProvider_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(11); -/* empty/unused harmony star reexport */ /* harmony default export */ __webpack_exports__["default"] = (_node_modules_babel_loader_lib_index_js_ref_3_0_node_modules_vue_loader_lib_index_js_vue_loader_options_DataSourceProvider_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__["default"]); +/* harmony import */ var _node_modules_babel_loader_lib_index_js_ref_3_0_node_modules_vue_loader_lib_index_js_vue_loader_options_DataSourceProvider_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(11); +/* empty/unused harmony star reexport */ /* harmony default export */ __webpack_exports__["default"] = (_node_modules_babel_loader_lib_index_js_ref_3_0_node_modules_vue_loader_lib_index_js_vue_loader_options_DataSourceProvider_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_0__["default"]); /***/ }), /* 11 */ @@ -325,6 +319,7 @@ __webpack_require__.r(__webpack_exports__); // // + /* harmony default export */ __webpack_exports__["default"] = ({ data: function data() { return { @@ -349,7 +344,6 @@ __webpack_require__.r(__webpack_exports__); }, mounted: function mounted() { var _this = this; - this.provider = Fliplet.Widget.open('com.fliplet.data-source-provider', { selector: '#data-source-provider', data: this.settings, @@ -362,7 +356,6 @@ __webpack_require__.r(__webpack_exports__); this.provider.then(function (dataSource) { _state_js__WEBPACK_IMPORTED_MODULE_0__["default"].dataSourceId = dataSource.data.id; _this.provider = null; - _this.$emit('saved'); }); } @@ -479,8 +472,8 @@ function normalizeComponent( "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _LoadSourceOption_vue_vue_type_template_id_61802cb4___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(14); -/* harmony import */ var _LoadSourceOption_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(16); +/* harmony import */ var _UpdateType_vue_vue_type_template_id_7e8d7f5a__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(14); +/* harmony import */ var _UpdateType_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(16); /* empty/unused harmony star reexport *//* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(12); @@ -490,9 +483,9 @@ __webpack_require__.r(__webpack_exports__); /* normalize component */ var component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__["default"])( - _LoadSourceOption_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__["default"], - _LoadSourceOption_vue_vue_type_template_id_61802cb4___WEBPACK_IMPORTED_MODULE_0__["render"], - _LoadSourceOption_vue_vue_type_template_id_61802cb4___WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"], + _UpdateType_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_1__["default"], + _UpdateType_vue_vue_type_template_id_7e8d7f5a__WEBPACK_IMPORTED_MODULE_0__["render"], + _UpdateType_vue_vue_type_template_id_7e8d7f5a__WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"], false, null, null, @@ -502,7 +495,7 @@ var component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_ /* hot reload */ if (false) { var api; } -component.options.__file = "src/components/LoadSourceOption.vue" +component.options.__file = "src/components/UpdateType.vue" /* harmony default export */ __webpack_exports__["default"] = (component.exports); /***/ }), @@ -511,10 +504,10 @@ component.options.__file = "src/components/LoadSourceOption.vue" "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_LoadSourceOption_vue_vue_type_template_id_61802cb4___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "render", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_LoadSourceOption_vue_vue_type_template_id_61802cb4___WEBPACK_IMPORTED_MODULE_0__["render"]; }); +/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_UpdateType_vue_vue_type_template_id_7e8d7f5a__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "render", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_UpdateType_vue_vue_type_template_id_7e8d7f5a__WEBPACK_IMPORTED_MODULE_0__["render"]; }); -/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "staticRenderFns", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_LoadSourceOption_vue_vue_type_template_id_61802cb4___WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"]; }); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "staticRenderFns", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_UpdateType_vue_vue_type_template_id_7e8d7f5a__WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"]; }); @@ -522,216 +515,6 @@ __webpack_require__.r(__webpack_exports__); /* 15 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "render", function() { return render; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "staticRenderFns", function() { return staticRenderFns; }); -var render = function () { - var _vm = this - var _h = _vm.$createElement - var _c = _vm._self._c || _h - return _c("div", { staticClass: "form-group clearfix" }, [ - _vm._m(0), - _vm._v(" "), - _c("div", { staticClass: "col-sm-8" }, [ - _c("div", { staticClass: "radio radio-icon" }, [ - _c("input", { - directives: [ - { - name: "model", - rawName: "v-model", - value: _vm.loadSource, - expression: "loadSource", - }, - ], - attrs: { type: "radio", id: "render-query", value: "query" }, - domProps: { checked: _vm._q(_vm.loadSource, "query") }, - on: { - change: function ($event) { - _vm.loadSource = "query" - }, - }, - }), - _vm._v(" "), - _vm._m(1), - ]), - _vm._v(" "), - _c("div", { staticClass: "radio radio-icon" }, [ - _c("input", { - directives: [ - { - name: "model", - rawName: "v-model", - value: _vm.loadSource, - expression: "loadSource", - }, - ], - attrs: { type: "radio", id: "render-custom", value: "custom" }, - domProps: { checked: _vm._q(_vm.loadSource, "custom") }, - on: { - change: function ($event) { - _vm.loadSource = "custom" - }, - }, - }), - _vm._v(" "), - _vm._m(2), - ]), - ]), - ]) -} -var staticRenderFns = [ - function () { - var _vm = this - var _h = _vm.$createElement - var _c = _vm._self._c || _h - return _c("div", { staticClass: "col-sm-4 control-label" }, [ - _c("label", [_vm._v("Choose how the data source entry is loaded")]), - ]) - }, - function () { - var _vm = this - var _h = _vm.$createElement - var _c = _vm._self._c || _h - return _c("label", { attrs: { for: "render-query" } }, [ - _c("span", { staticClass: "check" }, [ - _c("i", { staticClass: "fa fa-circle" }), - ]), - _vm._v(" Automatically from query parameters"), - _c("br"), - _c("p", { staticClass: "small" }, [ - _vm._v("This option will load the data source entry from the "), - _c("code", [_vm._v("dataSourceQueryId")]), - _vm._v(" query parameter, when found."), - ]), - ]) - }, - function () { - var _vm = this - var _h = _vm.$createElement - var _c = _vm._self._c || _h - return _c("label", { attrs: { for: "render-custom" } }, [ - _c("span", { staticClass: "check" }, [ - _c("i", { staticClass: "fa fa-circle" }), - ]), - _vm._v(" Custom implementation"), - _c("br"), - _c("p", { staticClass: "small" }, [ - _vm._v( - "Do not load the data source entry. You can load it manually using the data record " - ), - _c("strong", [_vm._v("JS API")]), - _vm._v("."), - ]), - ]) - }, -] -render._withStripped = true - - - -/***/ }), -/* 16 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var _node_modules_babel_loader_lib_index_js_ref_3_0_node_modules_vue_loader_lib_index_js_vue_loader_options_LoadSourceOption_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(17); -/* empty/unused harmony star reexport */ /* harmony default export */ __webpack_exports__["default"] = (_node_modules_babel_loader_lib_index_js_ref_3_0_node_modules_vue_loader_lib_index_js_vue_loader_options_LoadSourceOption_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__["default"]); - -/***/ }), -/* 17 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var _state_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// - -/* harmony default export */ __webpack_exports__["default"] = ({ - data: function data() { - return { - loadSource: _state_js__WEBPACK_IMPORTED_MODULE_0__["default"].loadSource || 'query' - }; - }, - watch: { - loadSource: function loadSource(val) { - _state_js__WEBPACK_IMPORTED_MODULE_0__["default"].loadSource = val; - } - }, - mounted: function mounted() {} -}); - -/***/ }), -/* 18 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var _UpdateType_vue_vue_type_template_id_7e8d7f5a___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(19); -/* harmony import */ var _UpdateType_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(21); -/* empty/unused harmony star reexport *//* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(12); - - - - - -/* normalize component */ - -var component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__["default"])( - _UpdateType_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__["default"], - _UpdateType_vue_vue_type_template_id_7e8d7f5a___WEBPACK_IMPORTED_MODULE_0__["render"], - _UpdateType_vue_vue_type_template_id_7e8d7f5a___WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"], - false, - null, - null, - null - -) - -/* hot reload */ -if (false) { var api; } -component.options.__file = "src/components/UpdateType.vue" -/* harmony default export */ __webpack_exports__["default"] = (component.exports); - -/***/ }), -/* 19 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_UpdateType_vue_vue_type_template_id_7e8d7f5a___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20); -/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "render", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_UpdateType_vue_vue_type_template_id_7e8d7f5a___WEBPACK_IMPORTED_MODULE_0__["render"]; }); - -/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "staticRenderFns", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_UpdateType_vue_vue_type_template_id_7e8d7f5a___WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"]; }); - - - -/***/ }), -/* 20 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "render", function() { return render; }); @@ -818,11 +601,7 @@ var staticRenderFns = [ var _h = _vm.$createElement var _c = _vm._self._c || _h return _c("div", { staticClass: "col-sm-4 control-label" }, [ - _c("label", [ - _vm._v( - "Choose how the data source entry is updated while the user is on the screen" - ), - ]), + _c("label", [_vm._v("Select data update mode")]), ]) }, function () { @@ -833,11 +612,12 @@ var staticRenderFns = [ _c("span", { staticClass: "check" }, [ _c("i", { staticClass: "fa fa-circle" }), ]), - _vm._v(" Do not update (default)"), + _vm._v(" No update"), _c("br"), + _vm._v(" "), _c("p", { staticClass: "small" }, [ _vm._v( - "The data source entry will not be updated while the user is on the screen." + "Updates are not silently applied and users won't see the changes until they load the list for the next time." ), ]), ]) @@ -852,9 +632,10 @@ var staticRenderFns = [ ]), _vm._v(" Informed update"), _c("br"), + _vm._v(" "), _c("p", { staticClass: "small" }, [ _vm._v( - "The data source entry will be updated while the user is on the screen. The user will be informed of the update." + "Users are informed if an update is available. When the user chooses to apply it, changes are applied in-situ, i.e. without a complete reload." ), ]), ]) @@ -869,9 +650,10 @@ var staticRenderFns = [ ]), _vm._v(" Real-time update"), _c("br"), + _vm._v(" "), _c("p", { staticClass: "small" }, [ _vm._v( - "The data source entry will be updated while the user is on the screen. The user will not be informed of the update. The contents in the screen will be updated automatically." + "Updates are automatically applied when they are available. Detail view can be directly loaded (via query parameter) without loading the list first." ), ]), ]) @@ -882,16 +664,16 @@ render._withStripped = true /***/ }), -/* 21 */ +/* 16 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _node_modules_babel_loader_lib_index_js_ref_3_0_node_modules_vue_loader_lib_index_js_vue_loader_options_UpdateType_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(22); -/* empty/unused harmony star reexport */ /* harmony default export */ __webpack_exports__["default"] = (_node_modules_babel_loader_lib_index_js_ref_3_0_node_modules_vue_loader_lib_index_js_vue_loader_options_UpdateType_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__["default"]); +/* harmony import */ var _node_modules_babel_loader_lib_index_js_ref_3_0_node_modules_vue_loader_lib_index_js_vue_loader_options_UpdateType_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(17); +/* empty/unused harmony star reexport */ /* harmony default export */ __webpack_exports__["default"] = (_node_modules_babel_loader_lib_index_js_ref_3_0_node_modules_vue_loader_lib_index_js_vue_loader_options_UpdateType_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_0__["default"]); /***/ }), -/* 22 */ +/* 17 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -925,6 +707,10 @@ __webpack_require__.r(__webpack_exports__); // // // +// +// +// + /* harmony default export */ __webpack_exports__["default"] = ({ data: function data() { diff --git a/js/build.js b/js/build.js index 3688812..ec3ee82 100644 --- a/js/build.js +++ b/js/build.js @@ -1,218 +1,287 @@ -Fliplet.RecordContainer = Fliplet.RecordContainer || {}; +(function() { + Fliplet.RecordContainer = Fliplet.RecordContainer || {}; -const recordContainerInstances = []; + const recordContainerInstances = {}; + const isInteract = Fliplet.Env.get('interact'); -Fliplet.Widget.instance('record-container', function(data, parent) { - const container = new Promise((resolve) => { - let loadData; - let _dataSourceConnection; + const sampleData = isInteract + ? { id: 1, data: {} } + : undefined; - // Get the current data source entry ID from the URL - let dataSourceEntryId = Fliplet.Navigate.query.dataSourceEntryId; + function getHtmlKeyFromPath(path) { + return `data${CryptoJS.MD5(path).toString().substr(-6)}`; + } - // Find child props - const $props = $(this).findUntil('fl-prop[data-engine]', 'fl-record-container, fl-helper, fl-list-repeater'); + function normalizePath(path) { + return path.startsWith('$') ? path.substr(1) : `entry.data.${path}`; + } - function getConnection() { - if (!_dataSourceConnection) { - _dataSourceConnection = Fliplet.DataSources.connect(data.dataSourceId); + Fliplet.Widget.instance('record-container', function(data, parent) { + const $recordTemplate = $(this).find('template[name="record"]').eq(0); + const $emptyTemplate = $(this).find('template[name="empty"]').eq(0); + const templateViewName = 'content'; + const templateNodeName = 'Content'; + const recordTemplatePaths = []; + const testDataObject = {}; + let compiledRecordTemplate; + + let recordTemplate = $('
').append($($recordTemplate.html() || '').find('fl-prop[data-path]').each(function(i, el) { + const path = normalizePath(el.getAttribute('data-path')); + let pathObject = _.get(testDataObject, path); + + if (!pathObject) { + // Provide a unique alphanumeric key for the path suitable for v-html + pathObject = { path, key: getHtmlKeyFromPath(path) }; + _.set(testDataObject, path, pathObject); + recordTemplatePaths.push(pathObject); } - return _dataSourceConnection; - } + el.setAttribute('v-html', `data.${ pathObject.key }`); + }).end()).html(); + const emptyTemplate = $emptyTemplate.html(); - const vm = new Vue({ - id: data.id, - name: data.name, - data: { - entry: {}, - parent: parent - }, - methods: { - _setData(key, data) { - if (!data) { - return; - } + $recordTemplate.remove(); + $emptyTemplate.remove(); - this[key] = data; + const container = new Promise((resolve) => { + let loadData; - this._updateVisibility(); - this._updatePropTags(); - }, - _updateVisibility() { - // Show/hide empty state containers - }, - _updatePropTags() { - const $vm = this; + function getTemplateForHtml() { + const recordTag = document.createElement('fl-record'); + + recordTag.setAttribute(':data-entry-id', 'entry.id'); + recordTag.setAttribute('v-bind', 'attrs'); + + $(recordTag).html(recordTemplate || (isInteract ? emptyTemplate : '')); - $props.each(function() { - const $el = $(this); - const path = $el.data('path'); + return recordTag.outerHTML; + } - if (!path) { + compiledRecordTemplate = Vue.compile(getTemplateForHtml()); + + // Get the current data source entry ID from the URL + let dataSourceEntryId = Fliplet.Navigate.query.dataSourceEntryId; + + // Record component + const recordComponent = Vue.component(data.content, { + props: ['entry'], + data() { + const result = { + attrs: { + 'data-view': templateViewName, + 'data-node-name': templateNodeName + }, + data: {}, + viewContainer: undefined + }; + + return result; + }, + watch: { + entry() { + this.setData(); + } + }, + methods: { + setData() { + if (isInteract) { return; } - let value = _.get($vm, path); + // Loop through the record template paths and set the data for v-html + recordTemplatePaths.forEach((pathObject) => { + this.$set(this.data, pathObject.key, _.get(this, pathObject.path)); + }); + } + }, + render(createElement) { + return compiledRecordTemplate.render.call(this, createElement); + }, + mounted() { + this.setData(); - if (typeof value === 'object') { - value = JSON.stringify(value); - } + Fliplet.Widget.initializeChildren(this.$el, this); - $el.html(value); + if (!isInteract) { + return; + } + + /* Edit mode only */ + + this.viewContainer = new Fliplet.Interact.ViewContainer(this.$el, { + placeholder: emptyTemplate }); + } + }); + + // Find child props + const vm = new Vue({ + el: this, + id: data.id, + name: data.name, + data: { + isLoading: false, + error: undefined, + entry: undefined, + noDataTemplate: data.noDataContent || T('widgets.recordContainer.noDataContent'), + parent + }, + components: { + record: recordComponent }, - /** - * Schedules an update of the data source entry - * @return {undefined} - */ - _scheduleUpdate() { - switch (data.updateType) { - case 'informed': - case 'live': - // TODO: Update the data source entry in real time - break; - case 'none': - default: - break; + filters: { + parseError(error) { + return Fliplet.parseError(error); } }, - /** - * Loads data from a function and sets it to the specified key - * @param {String} key The key to set the data to - * @param {Function} fn The function to execute - * @returns {Promise} A promise that resolves when the data is set - */ - load(key, fn) { - if (typeof key === 'function') { - fn = key; - key = 'entry'; + methods: { + /** + * Schedules an update of the data source entry + * @return {undefined} + */ + _scheduleUpdate() { + switch (data.updateType) { + case 'informed': + case 'live': + // TODO: Update the data source entry in real time + break; + case 'none': + default: + break; + } } + } + }); - let result = fn(); + if (isInteract) { + loadData = Promise.resolve(sampleData); + } else if (parent && typeof parent.connection === 'function') { + vm.isLoading = true; + vm.error = undefined; + + loadData = parent.connection().then((connection) => { + return Fliplet.Hooks.run('recordContainerBeforeRetrieveData', { + container: this, + connection: connection, + instance: vm, + dataSourceId: connection.id, + dataSourceEntryId + }).then((result) => { + // Merge all results into a single object + result = _.extend.apply(this, [{}].concat(result)); + + // If the result is an object and it has keys, we assume it's a query + if (typeof result === 'object' && Object.keys(result).length) { + return connection.findOne(result); + } - if (!(result instanceof Promise)) { - result = Promise.resolve(result); - } + // Load the entry by ID if the option "loadSource" is set to "query" (this is the default mode) + if (dataSourceEntryId && (!data.loadSource || data.loadSource === 'query')) { + return connection.findById(dataSourceEntryId); + } - return result.then(res => this._setData(key, res)); - }, - connection() { - return getConnection(); - } + // Scheduled automated updates when set + vm._scheduleUpdate(); + }).catch((error) => { + if (error && error.status === 404) { + return Promise.resolve(); + } + + return Promise.reject(error); + }); + }); + } else { + loadData = Promise.resolve(); } - }); - if (parent && typeof parent.connection === 'function') { - loadData = parent.connection().then((connection) => { - return Fliplet.Hooks.run('recordContainerBeforeRetrieveData', { - container: this, - connection: connection, - vm: vm, - dataSourceId: connection.id, - dataSourceEntryId: dataSourceEntryId - }).then((result) => { - // Merge all results into a single object - result = _.extend.apply(this, [{}].concat(result)); - - // If the result is an object and it has keys, we assume it's a query - if (typeof result === 'object' && Object.keys(result).length) { - return connection.findOne(result); - } + loadData.then((entry) => { + vm.isLoading = false; - // Load the entry by ID if the option "loadSource" is set to "query" (this is the default mode) - if (dataSourceEntryId && (!data.loadSource || data.loadSource === 'query')) { - return connection.findById(dataSourceEntryId); - } + // Set the entry data + vm.entry = entry; - // Scheduled automated updates when set - vm._scheduleUpdate(); - }); - }); - } else { - loadData = Promise.resolve(); - } + // Resolve the promise and return the Vue instance + resolve(vm); - loadData.then((entry) => { - if (typeof entry === 'object') { Fliplet.Hooks.run('recordContainerDataRetrieved', { container: this, - entry: entry, - vm: vm + entry, + instance: vm }); - } + }).catch((error) => { + vm.isLoading = false; + vm.error = error; - // Set the entry data - vm._setData('entry', entry); + Fliplet.Hooks.run('recordContainerDataRetrieveError', { instance: vm, error }); - // Initialize children - Fliplet.Widget.initializeChildren(this, vm); + vm.$nextTick(() => { + $(vm.$el).find('.record-container-load-error').translate(); + }); + + // eslint-disable-next-line no-console + console.error('[RECORD CONTAINER] Error fetching data', error); + resolve(vm); + }); - // Resolve the promise and return the Vue instance - resolve(vm); - }).catch((err) => { - // eslint-disable-next-line no-console - console.error('[RECORD CONTAINER] Error fetching data', err); resolve(vm); }); - resolve(vm); + container.id = data.id; + recordContainerInstances[data.id] = container; + }, { + supportsDynamicContext: true }); - recordContainerInstances.push(container); -}, { - supportsDynamicContext: true -}); - -Fliplet.RecordContainer.get = function(filter, options) { - if (typeof filter === 'string') { - filter = { name: filter }; - } - - options = options || { ts: 10 }; + Fliplet.RecordContainer.get = function(filter, options) { + if (typeof filter === 'string') { + filter = { name: filter }; + } - return Fliplet().then(function() { - return Promise.all(recordContainerInstances).then(function(containers) { - var container; + options = options || { ts: 10 }; - if (typeof filter === 'undefined') { - container = containers.length ? containers[0] : undefined; - } else { - _.find(containers, filter); - } + return Fliplet().then(function() { + return Promise.all(_.values(recordContainerInstances)).then(function(containers) { + var container; - if (!container) { - if (options.ts > 5000) { - return Promise.reject('Record container not found after ' + Math.ceil(options.ts / 1000) + ' seconds.'); + if (typeof filter === 'undefined') { + container = containers.length ? containers[0] : undefined; + } else { + _.find(containers, filter); } - // Containers can render over time, so we need to retry later in the process - return new Promise(function(resolve) { - setTimeout(function() { - options.ts = options.ts * 1.5; + if (!container) { + if (options.ts > 5000) { + return Promise.reject('Record container not found after ' + Math.ceil(options.ts / 1000) + ' seconds.'); + } - Fliplet.RecordContainer.get(filter, options).then(resolve); - }, options.ts); - }); - } + // Containers can render over time, so we need to retry later in the process + return new Promise(function(resolve) { + setTimeout(function() { + options.ts = options.ts * 1.5; + + Fliplet.RecordContainer.get(filter, options).then(resolve); + }, options.ts); + }); + } - return container; + return container; + }); }); - }); -}; + }; -Fliplet.RecordContainer.getAll = function(filter) { - if (typeof filter === 'string') { - filter = { name: filter }; - } + Fliplet.RecordContainer.getAll = function(filter) { + if (typeof filter === 'string') { + filter = { name: filter }; + } - return Fliplet().then(function() { - return Promise.all(recordContainerInstances).then(function(containers) { - if (typeof filter === 'undefined') { - return containers; - } + return Fliplet().then(function() { + return Promise.all(_.values(recordContainerInstances)).then(function(containers) { + if (typeof filter === 'undefined') { + return containers; + } - return _.filter(containers, filter); + return _.filter(containers, filter); + }); }); - }); -}; + }; +})(); diff --git a/js/interface.js b/js/interface.js new file mode 100644 index 0000000..73a8e48 --- /dev/null +++ b/js/interface.js @@ -0,0 +1,29 @@ +Fliplet.Widget.generateInterface({ + fields: [ + { + type: 'radio', + name: 'updateType', + label: 'Select data update mode', + options: [ + { + value: 'none', + label: 'No Update - Updates are not silently applied and users won\'t see the changes until they load the list for the next time.' + }, + { + value: 'informed', + label: 'Informed Update - Users are informed if an update is available. When the user chooses to apply it, changes are applied in-situ, i.e. without a complete reload.' + }, + { + value: 'live', + label: 'Real-time Update - Updates are automatically applied when they are available. Detail view can be directly loaded (via query parameter) without loading the list first.' + } + ] + }, + { + name: 'noDataContent', + type: 'textarea', + label: 'Text to show if no data loaded', + placeholder: 'Default: No data found' + } + ] +}); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..67801b6 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1126 @@ +{ + "name": "fliplet-record-container", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + } + }, + "@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "dev": true + }, + "@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + } + }, + "eslint-config-fliplet": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/eslint-config-fliplet/-/eslint-config-fliplet-1.0.11.tgz", + "integrity": "sha512-45eeb7lJL/Fv803dPAi/b6IzI8qT57ytH3h41hMxsRIhynIbF+BqmewlnyCEHCSW6rAo1Q6WjHnmw7HIrsN2WA==", + "dev": true + }, + "eslint-loader": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-4.0.2.tgz", + "integrity": "sha512-EDpXor6lsjtTzZpLUn7KmXs02+nIjGcgees9BYjNkWra3jVq5vVa8IoCKgzT2M7dNNeoMBtaSG83Bd40N3poLw==", + "dev": true, + "requires": { + "find-cache-dir": "^3.3.1", + "fs-extra": "^8.1.0", + "loader-utils": "^2.0.0", + "object-hash": "^2.0.3", + "schema-utils": "^2.6.5" + } + }, + "eslint-plugin-vue": { + "version": "9.21.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.21.0.tgz", + "integrity": "sha512-B3NgZRtbi9kSl7M0x/PqhSMk7ULJUwWxQpTvM8b2Z6gNTORK0YSt5v1vzwY84oMs/2+3BWH5XmTepaQebcJwfA==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.13", + "semver": "^7.5.4", + "vue-eslint-parser": "^9.4.2", + "xml-name-validator": "^4.0.0" + }, + "dependencies": { + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + }, + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + } + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fastq": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", + "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "requires": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "requires": { + "boolbase": "^1.0.0" + } + }, + "object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + } + } + }, + "postcss-selector-parser": { + "version": "6.0.15", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", + "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "vue-eslint-parser": { + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz", + "integrity": "sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==", + "dev": true, + "requires": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "dependencies": { + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/package.json b/package.json index 7595a85..57cc8a8 100644 --- a/package.json +++ b/package.json @@ -4,39 +4,10 @@ "description": "fliplet-record-container", "author": "", "private": true, - "scripts": { - "watch": "gulp build && gulp watch", - "build": "gulp build" - }, - "dependencies": { - "core-js": "^3.1.4", - "regenerator-runtime": "^0.13.2" - }, "devDependencies": { - "@babel/core": "^7.4.5", - "@babel/plugin-transform-modules-amd": "^7.2.0", - "@babel/plugin-transform-runtime": "^7.4.4", - "@babel/preset-env": "^7.4.5", - "@babel/runtime": "^7.4.5", - "babel-eslint": "^10.0.3", - "babel-loader": "^8.0.6", - "css-loader": "^3.0.0", - "del": "^4.1.1", - "eslint": "^6.8.0", - "eslint-config-fliplet": "^0.7.0", - "eslint-loader": "^3.0.3", - "eslint-plugin-vue": "^6.1.2", - "gulp": "^4.0.2", - "gulp-sass": "^5.1.0", - "gulp-vueify2": "0.0.3", - "path": "^0.12.7", - "sass": "^1.51.0", - "sass-loader": "^7.1.0", - "style-loader": "^0.23.1", - "vinyl-named": "^1.1.0", - "vue-loader": "^15.7.0", - "vue-template-compiler": "^2.6.10", - "webpack": "^4.34.0", - "webpack-stream": "^5.2.1" + "eslint": "^8.56.0", + "eslint-config-fliplet": "^1.0.11", + "eslint-loader": "^4.0.2", + "eslint-plugin-vue": "^9.20.1" } } diff --git a/src/Application.vue b/src/Application.vue deleted file mode 100644 index 0e80044..0000000 --- a/src/Application.vue +++ /dev/null @@ -1,37 +0,0 @@ - - - diff --git a/src/components/DataSourceProvider.vue b/src/components/DataSourceProvider.vue deleted file mode 100644 index 5446966..0000000 --- a/src/components/DataSourceProvider.vue +++ /dev/null @@ -1,51 +0,0 @@ - - - - - diff --git a/src/components/LoadSourceOption.vue b/src/components/LoadSourceOption.vue deleted file mode 100644 index a9d109a..0000000 --- a/src/components/LoadSourceOption.vue +++ /dev/null @@ -1,43 +0,0 @@ - - - - - diff --git a/src/components/UpdateType.vue b/src/components/UpdateType.vue deleted file mode 100644 index 6ec12f9..0000000 --- a/src/components/UpdateType.vue +++ /dev/null @@ -1,49 +0,0 @@ - - - - - diff --git a/src/main.js b/src/main.js deleted file mode 100644 index 5aed0ab..0000000 --- a/src/main.js +++ /dev/null @@ -1,8 +0,0 @@ -import Application from './Application.vue'; - -new Vue({ - el: '#record-container-configuration', - render: (createElement) => { - return createElement(Application); - } -}); diff --git a/src/scss/index.scss b/src/scss/index.scss deleted file mode 100644 index c08a722..0000000 --- a/src/scss/index.scss +++ /dev/null @@ -1,13 +0,0 @@ -.fl-widget-provider { - width: 100%; - border: 0; -} - -#data-source-provider { - margin-bottom: -10px; - padding: 20px; -} - -.small { - opacity: 0.9; -} \ No newline at end of file diff --git a/src/state.js b/src/state.js deleted file mode 100644 index e132a18..0000000 --- a/src/state.js +++ /dev/null @@ -1 +0,0 @@ -export default Fliplet.Widget.getData(); diff --git a/translation.json b/translation.json new file mode 100644 index 0000000..7617f50 --- /dev/null +++ b/translation.json @@ -0,0 +1,10 @@ +{ + "widgets": { + "recordContainer": { + "noDataContent": "No data found", + "errors": { + "loadingData": "Error loading data" + } + } + } +} diff --git a/widget.json b/widget.json index a0e2095..5ef232a 100644 --- a/widget.json +++ b/widget.json @@ -6,29 +6,16 @@ "icon": "img/icon.png", "tags": ["type:component", "category:layout"], "provider_only": false, - "references": [ - "content:richContent" - ], + "references": ["content:richContent"], "html_tag": "div", + "settings": { + "interfaceWidgetPackage": "com.fliplet.helper-configuration" + }, "interface": { - "dependencies": [ - "vue.js", - "fliplet-core", - "fliplet-studio-ui" - ], - "assets": [ - "dist/css/index.css", - "dist/app.js" - ] + "assets": ["js/interface.js"] }, "build": { - "dependencies": [ - "vue.js", - "fliplet-core", - "fliplet-datasources" - ], - "assets": [ - "js/build.js" - ] + "dependencies": ["vue.js", "fliplet-core"], + "assets": ["css/build.css", "js/build.js"] } } From 8d73c4a29a1ba1a6476c876ad0c923a12cea8704 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 3 Apr 2024 17:17:19 +0100 Subject: [PATCH 02/14] ID-3903 Subscribe to data updates to reflect them based on update mode --- js/build.js | 117 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 108 insertions(+), 9 deletions(-) diff --git a/js/build.js b/js/build.js index ec3ee82..8be66f5 100644 --- a/js/build.js +++ b/js/build.js @@ -124,7 +124,16 @@ error: undefined, entry: undefined, noDataTemplate: data.noDataContent || T('widgets.recordContainer.noDataContent'), - parent + parent, + pendingUpdates: { + updated: [], + deleted: [] + } + }, + computed: { + hasPendingUpdates() { + return Object.values(this.pendingUpdates).some(value => value.length); + } }, components: { record: recordComponent @@ -135,15 +144,104 @@ } }, methods: { - /** - * Schedules an update of the data source entry - * @return {undefined} - */ - _scheduleUpdate() { + onUpdate(updates = []) { + updates.forEach(update => { + // Otherwise, update or add to the updated array + const existingIndex = this.pendingUpdates.updated.findIndex(row => row.id === update.id); + + if (existingIndex !== -1) { + this.$set(this.pendingUpdates.updated, existingIndex, update); + } else { + this.pendingUpdates.updated.push(update); + } + }); + }, + onDelete(deletions = []) { + deletions.forEach(deletion => { + // Remove from updated if present + const updatedIndex = this.pendingUpdates.updated.findIndex(row => row.id === deletion.id); + + if (updatedIndex !== -1) { + this.pendingUpdates.updated.splice(updatedIndex, 1); + } + + // Finally, add to deleted if not already there and not in inserted + if (!this.pendingUpdates.deleted.includes(deletion.id)) { + this.pendingUpdates.deleted.push(deletion.id); + } + }); + }, + applyUpdates() { + // Apply updated entries + this.pendingUpdates.updated.forEach(update => { + if (update.id !== this.entry.id) { + return; + } + + this.entry = update; + }); + + // Remove deleted entries + this.pendingUpdates.deleted.forEach(deletedId => { + if (deletedId.id !== this.entry.id) { + return; + } + + this.entry = undefined; + }); + + // Reset pendingUpdates + this.pendingUpdates = { + updated: [], + deleted: [] + }; + }, + subscribe(connection, entry) { + if (!entry) { + return; // No entry to subscribe to + } + switch (data.updateType) { case 'informed': case 'live': - // TODO: Update the data source entry in real time + // Deletions can be handled but currently isn't being monitored + // because API is incomplete to provide the necessary information + var events = ['update']; + + this.subscription = connection.subscribe({ id: entry.id, events }, (bundle) => { + if (events.includes('update')) { + this.onUpdate(bundle.updated); + } + + if (events.includes('delete')) { + this.onDelete(bundle.deleted); + } + + if (data.updateType === 'live') { + this.applyUpdates(); + } else if (this.hasPendingUpdates) { + // Show toast message + Fliplet.UI.Toast({ + message: 'New data available', + duration: false, + actions: [ + { + label: 'Refresh', + action() { + vm.applyUpdates(); + } + }, + { + icon: 'fa-times', + title: 'Ignore', + action() { + // Do nothing + } + } + ] + }); + } + }); break; case 'none': default: @@ -179,9 +277,10 @@ if (dataSourceEntryId && (!data.loadSource || data.loadSource === 'query')) { return connection.findById(dataSourceEntryId); } + }).then((entry) => { + vm.subscribe(connection, entry); - // Scheduled automated updates when set - vm._scheduleUpdate(); + return entry; }).catch((error) => { if (error && error.status === 404) { return Promise.resolve(); From 0e33244fd36aaebef48696049a6805ec9c4708ee Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 10 Apr 2024 16:13:00 +0100 Subject: [PATCH 03/14] ID-4266 Allow template tags without wrappers --- js/build.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/build.js b/js/build.js index ec3ee82..830e63a 100644 --- a/js/build.js +++ b/js/build.js @@ -25,7 +25,7 @@ const testDataObject = {}; let compiledRecordTemplate; - let recordTemplate = $('
').append($($recordTemplate.html() || '').find('fl-prop[data-path]').each(function(i, el) { + let recordTemplate = $('
').html($recordTemplate.html() || '').find('fl-prop[data-path]').each(function(i, el) { const path = normalizePath(el.getAttribute('data-path')); let pathObject = _.get(testDataObject, path); @@ -37,7 +37,7 @@ } el.setAttribute('v-html', `data.${ pathObject.key }`); - }).end()).html(); + }).end().html(); const emptyTemplate = $emptyTemplate.html(); $recordTemplate.remove(); From e81f7c4e55d9cc412fad8bca3beb6e2d998ceeeb Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Thu, 18 Apr 2024 17:12:35 +0100 Subject: [PATCH 04/14] ID-4266 Use Fliplet.Widget.findParents() to find the right parent --- js/build.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/js/build.js b/js/build.js index 830e63a..9ac2826 100644 --- a/js/build.js +++ b/js/build.js @@ -16,7 +16,7 @@ return path.startsWith('$') ? path.substr(1) : `entry.data.${path}`; } - Fliplet.Widget.instance('record-container', function(data, parent) { + Fliplet.Widget.instance('record-container', async function(data, parent) { const $recordTemplate = $(this).find('template[name="record"]').eq(0); const $emptyTemplate = $(this).find('template[name="empty"]').eq(0); const templateViewName = 'content'; @@ -43,6 +43,15 @@ $recordTemplate.remove(); $emptyTemplate.remove(); + let [parent] = await Fliplet.Widget.findParents({ + instanceId: data.id, + filter: { package: 'com.fliplet.dynamic-container' } + }); + + if (parent) { + parent = await Fliplet.DynamicContainer.get(parent.id); + } + const container = new Promise((resolve) => { let loadData; From 5fd8b27247c954e728e71db5171ccb2b468baee4 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Fri, 19 Apr 2024 13:24:14 +0100 Subject: [PATCH 05/14] ID-4266 Remove unused parameter --- js/build.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/build.js b/js/build.js index 9ac2826..488dac1 100644 --- a/js/build.js +++ b/js/build.js @@ -16,7 +16,7 @@ return path.startsWith('$') ? path.substr(1) : `entry.data.${path}`; } - Fliplet.Widget.instance('record-container', async function(data, parent) { + Fliplet.Widget.instance('record-container', async function(data) { const $recordTemplate = $(this).find('template[name="record"]').eq(0); const $emptyTemplate = $(this).find('template[name="empty"]').eq(0); const templateViewName = 'content'; From c8a852814aeaf2804ad5d9d1a43165532f577676 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 24 Apr 2024 17:59:03 +0100 Subject: [PATCH 06/14] Empty state copy update --- build.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.html b/build.html index e90518a..4c16e49 100644 --- a/build.html +++ b/build.html @@ -1,6 +1,6 @@ - +