diff --git a/CHANGELOG for v1.5.x.md b/CHANGELOG for v1.5.x.md new file mode 100644 index 0000000..743d22b --- /dev/null +++ b/CHANGELOG for v1.5.x.md @@ -0,0 +1,17 @@ +# CHANGELOG for v1.5.x + +#### This changelog consists the bug & security fixes and new features being included in the releases listed below. + +## **v1.5.1(22th of Nov, 2023)** - _Release_ + +- [compatible] Compatible with bagisto v1.5.1. + +## **v1.3.3(24th of Oct, 2021)** - _Release_ + +- [compatible] Compatible with bagisto v1.3.3. + +## **v1.3.2(27th of Sept, 2021)** - _Release_ + +- [compatible] Compatible with bagisto v1.3.2. +- [fix] datagrid issue with bagisto v1.3.2. + diff --git a/README.md b/README.md index 7719ec0..951dcf8 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ It packs in lots of demanding features that allows your business to scale in no ## Requirements: -- **Bagisto**: v1.3.3 +- **Bagisto**: v1.5.1 ## Installation with composer: - Run the following command diff --git a/composer.json b/composer.json deleted file mode 100644 index e7ab19b..0000000 --- a/composer.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "bagisto/bagisto-bulk-upload", - "description": "Add products using CSV or XLS in bagisto.", - "keywords": [ - "bagisto", - "product upload", - "bulk upload" - ], - "homepage": "https://github.com/bagisto/bagisto-bulk-upload", - "license": "MIT", - "authors": [ - { - "name": "Prateek Srivastava", - "email": "prateek.srivastava781@webkul.com", - "homepage": "https://bagisto.com", - "role": "Developer" - } - ], - "require": { - "konekt/concord": "^1.2" - }, - "autoload": { - "psr-4": { - "Webkul\\Bulkupload\\": "src" - } - }, - "extra": { - "laravel": { - "providers": [ - "Webkul\\Bulkupload\\Providers\\BulkUploadServiceProvider" - ], - "aliases": {} - } - }, - "minimum-stability": "dev" -} diff --git a/package.json b/package.json index 7b6644f..14a65c4 100644 --- a/package.json +++ b/package.json @@ -4,18 +4,23 @@ "dev": "npm run development", "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", - "watch-poll": "cross-env npm run watch -- --watch-poll --progress", + "watch-poll": "npm run watch -- --watch-poll", "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", "prod": "npm run production", "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" }, "devDependencies": { - "axios": "^0.18", - "cross-env": "^5.1.4", - "laravel-mix": "^2.1", - "laravel-mix-merge-manifest": "^0.1.1", - "jquery": "^3.2", - "vue": "^2.1.10" + "clean-webpack-plugin": "^4.0.0", + "cross-env": "^6.0.3", + "laravel-mix": "^5.0.0", + "laravel-mix-clean": "^0.1.0", + "laravel-mix-merge-manifest": "^0.1.2", + "sass": "^1.24.4", + "sass-loader": "^8.0.2", + "vue": "^2.7.14", + "vue-template-compiler": "^2.6.11" }, - "dependencies": {} + "dependencies": { + "axios": "^1.5.0" + } } diff --git a/publishable/assets/css/bk_upload.css b/publishable/assets/css/bk_upload.css deleted file mode 100644 index f1e21d6..0000000 --- a/publishable/assets/css/bk_upload.css +++ /dev/null @@ -1 +0,0 @@ -.bulk-upload-icon{background-image:url("../images/Icon-Bulk-Upload.svg")}.active .bulk-upload-icon,.bulk-upload-icon{width:48px;height:48px;display:inline-block;background-size:cover}.active .bulk-upload-icon{background-image:url("../images/Icon-Bulk-Upload-Active.svg")}progress{margin:15px 0 15px 34px;width:70%;height:15px}.icon{background-size:cover;display:inline-block}.icon.check-accent{width:22px;height:18px;background-image:url("../images/check-accent.svg")}.icon.icon-crossed{width:18px;height:15px;background-image:url("../images/Icon-Crossed.svg")}.icon.cross-accent{width:22px;height:18px;background-image:url("../images/cross-accent.svg")}.icon.finish-icon{width:22px;height:18px;background-image:url("../images/finish.svg")} \ No newline at end of file diff --git a/publishable/assets/css/bulk-admin.css b/publishable/assets/css/bulk-admin.css deleted file mode 100644 index 1c7a1dd..0000000 --- a/publishable/assets/css/bulk-admin.css +++ /dev/null @@ -1,40 +0,0 @@ -.bulk-upload-icon { - width: 48px; - height: 48px; - display: inline-block; - background-size: cover; - background-image: url("../images/Icon-Bulk-Upload.svg"); -} -.active.bulk-upload-icon, -.active .bulk-upload-icon { - background-image: url("../images/Icon-Bulk-Upload-Active.svg"); -} -progress { - margin: 15px 0 15px 34px; - width: 70%; - height: 15px; -} -.icon { - background-size: cover; - display: inline-block; -} -.icon.check-accent { - background-image: url("../images/check-accent.svg"); - width: 22px; - height: 18px; -} -.icon.icon-crossed { - width: 18px; - height: 15px; - background-image: url("../images/Icon-Crossed.svg"); -} -.icon.cross-accent { - width: 22px; - height: 18px; - background-image: url("../images/cross-accent.svg"); -} -.icon.finish-icon { - width: 22px; - height: 18px; - background-image: url("../images/finish.svg"); -} diff --git a/publishable/assets/css/bulk-upload-admin.css b/publishable/assets/css/bulk-upload-admin.css new file mode 100644 index 0000000..24cf47f --- /dev/null +++ b/publishable/assets/css/bulk-upload-admin.css @@ -0,0 +1 @@ +.bulk-upload-icon{width:48px;height:48px;display:inline-block;background-image:url(../images/Icon-Bulk-Upload.svg) no-repeat center/cover}.active.bulk-upload-icon,.active .bulk-upload-icon{background-image:url(../images/Icon-Bulk-Upload-Active.svg)}progress{margin:15px 0 15px 34px;width:70%;height:15px}.icon{background-size:cover;display:inline-block}.icon.check-accent{background-image:url(../images/check-accent.svg) no-repeat center/cover;width:22px;height:18px}.icon.cross-accent,.icon.finish-icon,.icon.icon-crossed{width:18px;height:15px}.icon.icon-crossed{background:url(../images/Icon-Crossed.svg) no-repeat 50%/cover}.icon.cross-accent{background:url(../images/cross-accent.svg) no-repeat 50%/cover}.icon.finish-icon{background:url(../images/finish.svg) no-repeat 50%/cover}.ms-15{margin-left:15px} \ No newline at end of file diff --git a/publishable/assets/images/Icon-Bulk-Upload-Active.svg b/publishable/assets/images/Icon-Bulk-Upload-Active.svg deleted file mode 100644 index db0b09c..0000000 --- a/publishable/assets/images/Icon-Bulk-Upload-Active.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - Icon-Bulk-Upload-Active - Created with Sketch. - - - - - - - - - - - \ No newline at end of file diff --git a/publishable/assets/images/Icon-Bulk-Upload.svg b/publishable/assets/images/Icon-Bulk-Upload.svg deleted file mode 100644 index e987ea4..0000000 --- a/publishable/assets/images/Icon-Bulk-Upload.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - Icon-Bulk-Upload - Created with Sketch. - - - - - - - - - - - \ No newline at end of file diff --git a/publishable/assets/images/Icon-Crossed.svg b/publishable/assets/images/Icon-Crossed.svg deleted file mode 100644 index 038759b..0000000 --- a/publishable/assets/images/Icon-Crossed.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - Icon-Crossed - Created with Sketch. - - - - - \ No newline at end of file diff --git a/publishable/assets/images/Icon-Temp-Active.svg b/publishable/assets/images/Icon-Temp-Active.svg new file mode 100644 index 0000000..d4c6168 --- /dev/null +++ b/publishable/assets/images/Icon-Temp-Active.svg @@ -0,0 +1,12 @@ + + + + Icon-Catalog-Active + Created with Sketch. + + + + + + + \ No newline at end of file diff --git a/src/Resources/assets/images/check-accent.svg b/publishable/assets/images/Icon-Temp.svg similarity index 50% rename from src/Resources/assets/images/check-accent.svg rename to publishable/assets/images/Icon-Temp.svg index 8334c77..7dba04b 100644 --- a/src/Resources/assets/images/check-accent.svg +++ b/publishable/assets/images/Icon-Temp.svg @@ -1,10 +1,12 @@ - + - Check-Accent + Icon-Catalog Created with Sketch. - - + + + + \ No newline at end of file diff --git a/publishable/assets/images/cross-accent.svg b/publishable/assets/images/cross-accent.svg deleted file mode 100644 index be35112..0000000 --- a/publishable/assets/images/cross-accent.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - Cross-Accent - Created with Sketch. - - - - - - \ No newline at end of file diff --git a/publishable/assets/images/finish.svg b/publishable/assets/images/finish.svg deleted file mode 100644 index 2401834..0000000 --- a/publishable/assets/images/finish.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - tab/heading/icon/finish - Created with Sketch. - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/publishable/assets/js/bulk-upload-app.js b/publishable/assets/js/bulk-upload-app.js new file mode 100644 index 0000000..9e854cc --- /dev/null +++ b/publishable/assets/js/bulk-upload-app.js @@ -0,0 +1,2 @@ +/*! For license information please see bulk-upload-app.js.LICENSE.txt */ +!function(t){var e={};function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)n.d(r,o,function(e){return t[e]}.bind(null,o));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="/",n(n.s=0)}({0:function(t,e,n){n("uPOf"),t.exports=n("y62a")},"49sm":function(t,e){var n={}.toString;t.exports=Array.isArray||function(t){return"[object Array]"==n.call(t)}},"5GeT":function(t,e,n){"use strict";(function(t){var r=n("xTJ+"),o=n("eRe6"),i=n("RYHr");function s(t){return r.a.isPlainObject(t)||r.a.isArray(t)}function a(t){return r.a.endsWith(t,"[]")?t.slice(0,-2):t}function c(t,e,n){return t?t.concat(e).map((function(t,e){return t=a(t),!n&&e?"["+t+"]":t})).join(n?".":""):e}const u=r.a.toFlatObject(r.a,{},null,(function(t){return/^is[A-Z]/.test(t)}));e.a=function(e,n,l){if(!r.a.isObject(e))throw new TypeError("target must be an object");n=n||new(i.a||FormData);const f=(l=r.a.toFlatObject(l,{metaTokens:!0,dots:!1,indexes:!1},!1,(function(t,e){return!r.a.isUndefined(e[t])}))).metaTokens,p=l.visitor||y,d=l.dots,h=l.indexes,m=(l.Blob||"undefined"!=typeof Blob&&Blob)&&r.a.isSpecCompliantForm(n);if(!r.a.isFunction(p))throw new TypeError("visitor must be a function");function g(e){if(null===e)return"";if(r.a.isDate(e))return e.toISOString();if(!m&&r.a.isBlob(e))throw new o.a("Blob is not supported. Use a Buffer instead.");return r.a.isArrayBuffer(e)||r.a.isTypedArray(e)?m&&"function"==typeof Blob?new Blob([e]):t.from(e):e}function y(t,e,o){let i=t;if(t&&!o&&"object"==typeof t)if(r.a.endsWith(e,"{}"))e=f?e:e.slice(0,-2),t=JSON.stringify(t);else if(r.a.isArray(t)&&function(t){return r.a.isArray(t)&&!t.some(s)}(t)||(r.a.isFileList(t)||r.a.endsWith(e,"[]"))&&(i=r.a.toArray(t)))return e=a(e),i.forEach((function(t,o){!r.a.isUndefined(t)&&null!==t&&n.append(!0===h?c([e],o,d):null===h?e:e+"[]",g(t))})),!1;return!!s(t)||(n.append(c(o,e,d),g(t)),!1)}const v=[],_=Object.assign(u,{defaultVisitor:y,convertValue:g,isVisitable:s});if(!r.a.isObject(e))throw new TypeError("data must be an object");return function t(e,o){if(!r.a.isUndefined(e)){if(-1!==v.indexOf(e))throw Error("Circular reference detected in "+o.join("."));v.push(e),r.a.forEach(e,(function(e,i){!0===(!(r.a.isUndefined(e)||null===e)&&p.call(n,e,r.a.isString(i)?i.trim():i,o,_))&&t(e,o?o.concat(i):[i])})),v.pop()}}(e),n}}).call(this,n("tjlA").Buffer)},"8oxB":function(t,e){var n,r,o=t.exports={};function i(){throw new Error("setTimeout has not been defined")}function s(){throw new Error("clearTimeout has not been defined")}function a(t){if(n===setTimeout)return setTimeout(t,0);if((n===i||!n)&&setTimeout)return n=setTimeout,setTimeout(t,0);try{return n(t,0)}catch(e){try{return n.call(null,t,0)}catch(e){return n.call(this,t,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:i}catch(t){n=i}try{r="function"==typeof clearTimeout?clearTimeout:s}catch(t){r=s}}();var c,u=[],l=!1,f=-1;function p(){l&&c&&(l=!1,c.length?u=c.concat(u):f=-1,u.length&&d())}function d(){if(!l){var t=a(p);l=!0;for(var e=u.length;e;){for(c=u,u=[];++f1)for(var n=1;n0?s-4:s;for(n=0;n>16&255,c[l++]=e>>8&255,c[l++]=255&e;2===a&&(e=o[t.charCodeAt(n)]<<2|o[t.charCodeAt(n+1)]>>4,c[l++]=255&e);1===a&&(e=o[t.charCodeAt(n)]<<10|o[t.charCodeAt(n+1)]<<4|o[t.charCodeAt(n+2)]>>2,c[l++]=e>>8&255,c[l++]=255&e);return c},e.fromByteArray=function(t){for(var e,n=t.length,o=n%3,i=[],s=0,a=n-o;sa?a:s+16383));1===o?(e=t[n-1],i.push(r[e>>2]+r[e<<4&63]+"==")):2===o&&(e=(t[n-2]<<8)+t[n-1],i.push(r[e>>10]+r[e>>4&63]+r[e<<2&63]+"="));return i.join("")};for(var r=[],o=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=0,c=s.length;a0)throw new Error("Invalid string. Length must be a multiple of 4");var n=t.indexOf("=");return-1===n&&(n=e),[n,n===e?0:4-n%4]}function l(t,e,n){for(var o,i,s=[],a=e;a>18&63]+r[i>>12&63]+r[i>>6&63]+r[63&i]);return s.join("")}o["-".charCodeAt(0)]=62,o["_".charCodeAt(0)]=63},HSsa:function(t,e,n){"use strict";function r(t,e){return function(){return t.apply(e,arguments)}}n.d(e,"a",(function(){return r}))},INkZ:function(t,e,n){"use strict";(function(e,n){const r=Object.freeze({}),o=Array.isArray;function i(t){return null==t}function s(t){return null!=t}function a(t){return!0===t}function c(t){return"string"==typeof t||"number"==typeof t||"symbol"==typeof t||"boolean"==typeof t}function u(t){return"function"==typeof t}function l(t){return null!==t&&"object"==typeof t}const f=Object.prototype.toString;function p(t){return"[object Object]"===f.call(t)}function d(t){const e=parseFloat(String(t));return e>=0&&Math.floor(e)===e&&isFinite(t)}function h(t){return s(t)&&"function"==typeof t.then&&"function"==typeof t.catch}function m(t){return null==t?"":Array.isArray(t)||p(t)&&t.toString===f?JSON.stringify(t,null,2):String(t)}function g(t){const e=parseFloat(t);return isNaN(e)?t:e}function y(t,e){const n=Object.create(null),r=t.split(",");for(let t=0;tn[t.toLowerCase()]:t=>n[t]}const v=y("slot,component",!0),_=y("key,ref,slot,slot-scope,is");function b(t,e){const n=t.length;if(n){if(e===t[n-1])return void(t.length=n-1);const r=t.indexOf(e);if(r>-1)return t.splice(r,1)}}const w=Object.prototype.hasOwnProperty;function $(t,e){return w.call(t,e)}function O(t){const e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}const S=/-(\w)/g,E=O(t=>t.replace(S,(t,e)=>e?e.toUpperCase():"")),x=O(t=>t.charAt(0).toUpperCase()+t.slice(1)),C=/\B([A-Z])/g,A=O(t=>t.replace(C,"-$1").toLowerCase()),T=Function.prototype.bind?function(t,e){return t.bind(e)}:function(t,e){function n(n){const r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}return n._length=t.length,n};function k(t,e){e=e||0;let n=t.length-e;const r=new Array(n);for(;n--;)r[n]=t[n+e];return r}function R(t,e){for(const n in e)t[n]=e[n];return t}function P(t){const e={};for(let n=0;n!1,L=t=>t;function D(t,e){if(t===e)return!0;const n=l(t),r=l(e);if(!n||!r)return!n&&!r&&String(t)===String(e);try{const n=Array.isArray(t),r=Array.isArray(e);if(n&&r)return t.length===e.length&&t.every((t,n)=>D(t,e[n]));if(t instanceof Date&&e instanceof Date)return t.getTime()===e.getTime();if(n||r)return!1;{const n=Object.keys(t),r=Object.keys(e);return n.length===r.length&&n.every(n=>D(t[n],e[n]))}}catch(t){return!1}}function I(t,e){for(let n=0;n0,Z=W&&W.indexOf("edge/")>0;W&&W.indexOf("android");const Q=W&&/iphone|ipad|ipod|ios/.test(W);W&&/chrome\/\d+/.test(W),W&&/phantomjs/.test(W);const tt=W&&W.match(/firefox\/(\d+)/),et={}.watch;let nt,rt=!1;if(K)try{const t={};Object.defineProperty(t,"passive",{get(){rt=!0}}),window.addEventListener("test-passive",null,t)}catch(r){}const ot=()=>(void 0===nt&&(nt=!K&&void 0!==e&&e.process&&"server"===e.process.env.VUE_ENV),nt),it=K&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function st(t){return"function"==typeof t&&/native code/.test(t.toString())}const at="undefined"!=typeof Symbol&&st(Symbol)&&"undefined"!=typeof Reflect&&st(Reflect.ownKeys);let ct;ct="undefined"!=typeof Set&&st(Set)?Set:class{constructor(){this.set=Object.create(null)}has(t){return!0===this.set[t]}add(t){this.set[t]=!0}clear(){this.set=Object.create(null)}};let ut=null;function lt(t=null){t||ut&&ut._scope.off(),ut=t,t&&t._scope.on()}class ft{constructor(t,e,n,r,o,i,s,a){this.tag=t,this.data=e,this.children=n,this.text=r,this.elm=o,this.ns=void 0,this.context=i,this.fnContext=void 0,this.fnOptions=void 0,this.fnScopeId=void 0,this.key=e&&e.key,this.componentOptions=s,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1,this.asyncFactory=a,this.asyncMeta=void 0,this.isAsyncPlaceholder=!1}get child(){return this.componentInstance}}const pt=(t="")=>{const e=new ft;return e.text=t,e.isComment=!0,e};function dt(t){return new ft(void 0,void 0,void 0,String(t))}function ht(t){const e=new ft(t.tag,t.data,t.children&&t.children.slice(),t.text,t.elm,t.context,t.componentOptions,t.asyncFactory);return e.ns=t.ns,e.isStatic=t.isStatic,e.key=t.key,e.isComment=t.isComment,e.fnContext=t.fnContext,e.fnOptions=t.fnOptions,e.fnScopeId=t.fnScopeId,e.asyncMeta=t.asyncMeta,e.isCloned=!0,e}let mt=0;const gt=[];class yt{constructor(){this._pending=!1,this.id=mt++,this.subs=[]}addSub(t){this.subs.push(t)}removeSub(t){this.subs[this.subs.indexOf(t)]=null,this._pending||(this._pending=!0,gt.push(this))}depend(t){yt.target&&yt.target.addDep(this)}notify(t){const e=this.subs.filter(t=>t);for(let t=0,n=e.length;t{const t=e[n];if(Mt(t))return t.value;{const e=t&&t.__ob__;return e&&e.dep.depend(),t}},set:t=>{const r=e[n];Mt(r)&&!Mt(t)?r.value=t:e[n]=t}})}function Ht(t,e,n){const r=t[e];if(Mt(r))return r;const o={get value(){const r=t[e];return void 0===r?n:r},set value(n){t[e]=n}};return V(o,"__v_isRef",!0),o}function zt(t){return Yt(t,!1)}function Yt(t,e){if(!p(t))return t;if(Bt(t))return t;const n=e?"__v_rawToShallowReadonly":"__v_rawToReadonly",r=t[n];if(r)return r;const o=Object.create(Object.getPrototypeOf(t));V(t,n,o),V(o,"__v_isReadonly",!0),V(o,"__v_raw",t),Mt(t)&&V(o,"__v_isRef",!0),(e||It(t))&&V(o,"__v_isShallow",!0);const i=Object.keys(t);for(let n=0;n{const e="&"===t.charAt(0),n="~"===(t=e?t.slice(1):t).charAt(0),r="!"===(t=n?t.slice(1):t).charAt(0);return{name:t=r?t.slice(1):t,once:n,capture:r,passive:e}});function Jt(t,e){function n(){const t=n.fns;if(!o(t))return on(t,null,arguments,e,"v-on handler");{const n=t.slice();for(let t=0;t0&&(l=t(l,`${n||""}_${u}`),Zt(l[0])&&Zt(p)&&(r[f]=dt(p.text+l[0].text),l.shift()),r.push.apply(r,l)):c(l)?Zt(p)?r[f]=dt(p.text+l):""!==l&&r.push(dt(l)):Zt(l)&&Zt(p)?r[f]=dt(p.text+l.text):(a(e._isVList)&&s(l.tag)&&i(l.key)&&s(n)&&(l.key=`__vlist${n}_${u}__`),r.push(l)));return r}(t):void 0}function Zt(t){return s(t)&&s(t.text)&&!1===t.isComment}function Qt(t,e,n,r,i,f){return(o(n)||c(n))&&(i=r,r=n,n=void 0),a(f)&&(i=2),function(t,e,n,r,i){if(s(n)&&s(n.__ob__))return pt();if(s(n)&&s(n.is)&&(e=n.is),!e)return pt();let a,c;if(o(r)&&u(r[0])&&((n=n||{}).scopedSlots={default:r[0]},r.length=0),2===i?r=Xt(r):1===i&&(r=function(t){for(let e=0;e0,a=e?!!e.$stable:!s,c=e&&e.$key;if(e){if(e._normalized)return e._normalized;if(a&&o&&o!==r&&c===o.$key&&!s&&!o.$hasNormal)return o;i={};for(const r in e)e[r]&&"$"!==r[0]&&(i[r]=be(t,n,r,e[r]))}else i={};for(const t in n)t in i||(i[t]=we(n,t));return e&&Object.isExtensible(e)&&(e._normalized=i),V(i,"$stable",a),V(i,"$key",c),V(i,"$hasNormal",s),i}function be(t,e,n,r){const i=function(){const e=ut;lt(t);let n=arguments.length?r.apply(null,arguments):r({});n=n&&"object"==typeof n&&!o(n)?[n]:Xt(n);const i=n&&n[0];return lt(e),n&&(!i||1===n.length&&i.isComment&&!ve(i))?void 0:n};return r.proxy&&Object.defineProperty(e,n,{get:i,enumerable:!0,configurable:!0}),i}function we(t,e){return()=>t[e]}function $e(t){return{get attrs(){if(!t._attrsProxy){const e=t._attrsProxy={};V(e,"_v_attr_proxy",!0),Oe(e,t.$attrs,r,t,"$attrs")}return t._attrsProxy},get listeners(){return t._listenersProxy||Oe(t._listenersProxy={},t.$listeners,r,t,"$listeners"),t._listenersProxy},get slots(){return function(t){return t._slotsProxy||Ee(t._slotsProxy={},t.$scopedSlots),t._slotsProxy}(t)},emit:T(t.$emit,t),expose(e){e&&Object.keys(e).forEach(n=>Ft(t,e,n))}}}function Oe(t,e,n,r,o){let i=!1;for(const s in e)s in t?e[s]!==n[s]&&(i=!0):(i=!0,Se(t,s,r,o));for(const n in t)n in e||(i=!0,delete t[n]);return i}function Se(t,e,n,r){Object.defineProperty(t,e,{enumerable:!0,configurable:!0,get:()=>n[r][e]})}function Ee(t,e){for(const n in e)t[n]=e[n];for(const n in t)n in e||delete t[n]}function xe(){const t=ut;return t._setupContext||(t._setupContext=$e(t))}let Ce,Ae=null;function Te(t,e){return(t.__esModule||at&&"Module"===t[Symbol.toStringTag])&&(t=t.default),l(t)?e.extend(t):t}function ke(t){if(o(t))for(let e=0;e{Le=e}}function Ie(t){for(;t&&(t=t.$parent);)if(t._inactive)return!0;return!1}function Be(t,e){if(e){if(t._directInactive=!1,Ie(t))return}else if(t._directInactive)return;if(t._inactive||null===t._inactive){t._inactive=!1;for(let e=0;edocument.createEvent("Event").timeStamp&&(Je=()=>t.now())}const Ke=(t,e)=>{if(t.post){if(!e.post)return 1}else if(e.post)return-1;return t.id-e.id};function We(){let t,e;for(qe=Je(),Ye=!0,Ue.sort(Ke),Ve=0;Ve{for(let t=0;tt),e._pending=!1}gt.length=0})(),it&&H.devtools&&it.emit("flush")}function Ge(t){const e=t.id;if(null==He[e]&&(t!==yt.target||!t.noRecurse)){if(He[e]=!0,Ye){let e=Ue.length-1;for(;e>Ve&&Ue[e].id>t.id;)e--;Ue.splice(e+1,0,t)}else Ue.push(t);ze||(ze=!0,dn(We))}}function Xe(t,e){return Qe(t,null,{flush:"post"})}const Ze={};function Qe(t,e,{immediate:n,deep:i,flush:s="pre",onTrack:a,onTrigger:c}=r){const l=ut,f=(t,e,n=null)=>on(t,null,n,l,e);let p,d,h=!1,m=!1;if(Mt(t)?(p=()=>t.value,h=It(t)):Dt(t)?(p=()=>(t.__ob__.dep.depend(),t),i=!0):o(t)?(m=!0,h=t.some(t=>Dt(t)||It(t)),p=()=>t.map(t=>Mt(t)?t.value:Dt(t)?Tn(t):u(t)?f(t,"watcher getter"):void 0)):p=u(t)?e?()=>f(t,"watcher getter"):()=>{if(!l||!l._isDestroyed)return d&&d(),f(t,"watcher",[g])}:j,e&&i){const t=p;p=()=>Tn(t())}let g=t=>{d=y.onStop=()=>{f(t,"watcher cleanup")}};if(ot())return g=j,e?n&&f(e,"watcher callback",[p(),m?[]:void 0,g]):p(),j;const y=new Rn(ut,p,j,{lazy:!0});y.noRecurse=!e;let v=m?[]:Ze;return y.run=()=>{if(y.active)if(e){const t=y.get();(i||h||(m?t.some((t,e)=>M(t,v[e])):M(t,v)))&&(d&&d(),f(e,"watcher callback",[t,v===Ze?void 0:v,g]),v=t)}else y.get()},"sync"===s?y.update=y.run:"post"===s?(y.post=!0,y.update=()=>Ge(y)):y.update=()=>{if(l&&l===ut&&!l._isMounted){const t=l._preWatchers||(l._preWatchers=[]);t.indexOf(y)<0&&t.push(y)}else Ge(y)},e?n?y.run():v=y.get():"post"===s&&l?l.$once("hook:mounted",()=>y.get()):y.get(),()=>{y.teardown()}}let tn;class en{constructor(t=!1){this.detached=t,this.active=!0,this.effects=[],this.cleanups=[],this.parent=tn,!t&&tn&&(this.index=(tn.scopes||(tn.scopes=[])).push(this)-1)}run(t){if(this.active){const e=tn;try{return tn=this,t()}finally{tn=e}}}on(){tn=this}off(){tn=this.parent}stop(t){if(this.active){let e,n;for(e=0,n=this.effects.length;ern(t,r,o+" (Promise/async)")),i._handled=!0)}catch(t){rn(t,r,o)}return i}function sn(t,e,n){if(H.errorHandler)try{return H.errorHandler.call(null,t,e,n)}catch(e){e!==t&&an(e)}an(t)}function an(t,e,n){if(!K||"undefined"==typeof console)throw t;console.error(t)}let cn=!1;const un=[];let ln,fn=!1;function pn(){fn=!1;const t=un.slice(0);un.length=0;for(let e=0;e{t.then(pn),Q&&setTimeout(j)},cn=!0}else if(G||"undefined"==typeof MutationObserver||!st(MutationObserver)&&"[object MutationObserverConstructor]"!==MutationObserver.toString())ln=void 0!==n&&st(n)?()=>{n(pn)}:()=>{setTimeout(pn,0)};else{let t=1;const e=new MutationObserver(pn),n=document.createTextNode(String(t));e.observe(n,{characterData:!0}),ln=()=>{t=(t+1)%2,n.data=String(t)},cn=!0}function dn(t,e){let n;if(un.push(()=>{if(t)try{t.call(e)}catch(t){rn(t,e,"nextTick")}else n&&n(e)}),fn||(fn=!0,ln()),!t&&"undefined"!=typeof Promise)return new Promise(t=>{n=t})}function hn(t){return(e,n=ut)=>{if(n)return function(t,e,n){const r=t.$options;r[e]=er(r[e],n)}(n,t,e)}}const mn=hn("beforeMount"),gn=hn("mounted"),yn=hn("beforeUpdate"),vn=hn("updated"),_n=hn("beforeDestroy"),bn=hn("destroyed"),wn=hn("activated"),$n=hn("deactivated"),On=hn("serverPrefetch"),Sn=hn("renderTracked"),En=hn("renderTriggered"),xn=hn("errorCaptured");var Cn=Object.freeze({__proto__:null,version:"2.7.14",defineComponent:function(t){return t},ref:function(t){return Ut(t,!1)},shallowRef:function(t){return Ut(t,!0)},isRef:Mt,toRef:Ht,toRefs:function(t){const e=o(t)?new Array(t.length):{};for(const n in t)e[n]=Ht(t,n);return e},unref:function(t){return Mt(t)?t.value:t},proxyRefs:function(t){if(Dt(t))return t;const e={},n=Object.keys(t);for(let r=0;r{e.depend()},()=>{e.notify()}),o={get value(){return n()},set value(t){r(t)}};return V(o,"__v_isRef",!0),o},triggerRef:function(t){t.dep&&t.dep.notify()},reactive:function(t){return Lt(t,!1),t},isReactive:Dt,isReadonly:Bt,isShallow:It,isProxy:function(t){return Dt(t)||Bt(t)},shallowReactive:Nt,markRaw:function(t){return Object.isExtensible(t)&&V(t,"__v_skip",!0),t},toRaw:function t(e){const n=e&&e.__v_raw;return n?t(n):e},readonly:zt,shallowReadonly:function(t){return Yt(t,!0)},computed:function(t,e){let n,r;const o=u(t);o?(n=t,r=j):(n=t.get,r=t.set);const i=ot()?null:new Rn(ut,n,j,{lazy:!0}),s={effect:i,get value(){return i?(i.dirty&&i.evaluate(),yt.target&&i.depend(),i.value):n()},set value(t){r(t)}};return V(s,"__v_isRef",!0),V(s,"__v_isReadonly",o),s},watch:function(t,e,n){return Qe(t,e,n)},watchEffect:function(t,e){return Qe(t,null,e)},watchPostEffect:Xe,watchSyncEffect:function(t,e){return Qe(t,null,{flush:"sync"})},EffectScope:en,effectScope:function(t){return new en(t)},onScopeDispose:function(t){tn&&tn.cleanups.push(t)},getCurrentScope:function(){return tn},provide:function(t,e){ut&&(nn(ut)[t]=e)},inject:function(t,e,n=!1){const r=ut;if(r){const o=r.$parent&&r.$parent._provided;if(o&&t in o)return o[t];if(arguments.length>1)return n&&u(e)?e.call(r):e}},h:function(t,e,n){return Qt(ut,t,e,n,2,!0)},getCurrentInstance:function(){return ut&&{proxy:ut}},useSlots:function(){return xe().slots},useAttrs:function(){return xe().attrs},useListeners:function(){return xe().listeners},mergeDefaults:function(t,e){const n=o(t)?t.reduce((t,e)=>(t[e]={},t),{}):t;for(const t in e){const r=n[t];r?o(r)||u(r)?n[t]={type:r,default:e[t]}:r.default=e[t]:null===r&&(n[t]={default:e[t]})}return n},nextTick:dn,set:Rt,del:Pt,useCssModule:function(t="$style"){if(!ut)return r;return ut[t]||r},useCssVars:function(t){if(!K)return;const e=ut;e&&Xe(()=>{const n=e.$el,r=t(e,e._setupProxy);if(n&&1===n.nodeType){const t=n.style;for(const e in r)t.setProperty("--"+e,r[e])}})},defineAsyncComponent:function(t){u(t)&&(t={loader:t});const{loader:e,loadingComponent:n,errorComponent:r,delay:o=200,timeout:i,suspensible:s=!1,onError:a}=t;let c=null,l=0;const f=()=>{let t;return c||(t=c=e().catch(t=>{if(t=t instanceof Error?t:new Error(String(t)),a)return new Promise((e,n)=>{a(t,()=>e((l++,c=null,f())),()=>n(t),l+1)});throw t}).then(e=>t!==c&&c?c:(e&&(e.__esModule||"Module"===e[Symbol.toStringTag])&&(e=e.default),e)))};return()=>({component:f(),delay:o,timeout:i,error:r,loading:n})},onBeforeMount:mn,onMounted:gn,onBeforeUpdate:yn,onUpdated:vn,onBeforeUnmount:_n,onUnmounted:bn,onActivated:wn,onDeactivated:$n,onServerPrefetch:On,onRenderTracked:Sn,onRenderTriggered:En,onErrorCaptured:function(t,e=ut){xn(t,e)}});const An=new ct;function Tn(t){return function t(e,n){let r,i;const s=o(e);if(!(!s&&!l(e)||e.__v_skip||Object.isFrozen(e)||e instanceof ft)){if(e.__ob__){const t=e.__ob__.dep.id;if(n.has(t))return;n.add(t)}if(s)for(r=e.length;r--;)t(e[r],n);else if(Mt(e))t(e.value,n);else for(i=Object.keys(e),r=i.length;r--;)t(e[i[r]],n)}}(t,An),An.clear(),t}let kn=0;class Rn{constructor(t,e,n,r,o){!function(t,e=tn){e&&e.active&&e.effects.push(t)}(this,tn&&!tn._vm?tn:t?t._scope:void 0),(this.vm=t)&&o&&(t._watcher=this),r?(this.deep=!!r.deep,this.user=!!r.user,this.lazy=!!r.lazy,this.sync=!!r.sync,this.before=r.before):this.deep=this.user=this.lazy=this.sync=!1,this.cb=n,this.id=++kn,this.active=!0,this.post=!1,this.dirty=this.lazy,this.deps=[],this.newDeps=[],this.depIds=new ct,this.newDepIds=new ct,this.expression="",u(e)?this.getter=e:(this.getter=function(t){if(q.test(t))return;const e=t.split(".");return function(t){for(let n=0;n(this.$slots||_e(i,t.scopedSlots,this.$slots=ge(n,i)),this.$slots),Object.defineProperty(this,"scopedSlots",{enumerable:!0,get(){return _e(i,t.scopedSlots,this.slots())}}),l&&(this.$options=c,this.$slots=this.slots(),this.$scopedSlots=_e(i,t.scopedSlots,this.$slots)),c._scopeId?this._c=(t,e,n,r)=>{const s=Qt(u,t,e,n,r,f);return s&&!o(s)&&(s.fnScopeId=c._scopeId,s.fnContext=i),s}:this._c=(t,e,n,r)=>Qt(u,t,e,n,r,f)}function Yn(t,e,n,r,o){const i=ht(t);return i.fnContext=n,i.fnOptions=r,e.slot&&((i.data||(i.data={})).slot=e.slot),i}function Vn(t,e){for(const n in e)t[E(n)]=e[n]}function qn(t){return t.name||t.__name||t._componentTag}me(zn.prototype);const Jn={init(t,e){if(t.componentInstance&&!t.componentInstance._isDestroyed&&t.data.keepAlive){const e=t;Jn.prepatch(e,e)}else(t.componentInstance=function(t,e){const n={_isComponent:!0,_parentVnode:t,parent:e},r=t.data.inlineTemplate;return s(r)&&(n.render=r.render,n.staticRenderFns=r.staticRenderFns),new t.componentOptions.Ctor(n)}(t,Le)).$mount(e?t.elm:void 0,e)},prepatch(t,e){const n=e.componentOptions;!function(t,e,n,o,i){const s=o.data.scopedSlots,a=t.$scopedSlots,c=!!(s&&!s.$stable||a!==r&&!a.$stable||s&&t.$scopedSlots.$key!==s.$key||!s&&t.$scopedSlots.$key);let u=!!(i||t.$options._renderChildren||c);const l=t.$vnode;t.$options._parentVnode=o,t.$vnode=o,t._vnode&&(t._vnode.parent=o),t.$options._renderChildren=i;const f=o.data.attrs||r;t._attrsProxy&&Oe(t._attrsProxy,f,l.data&&l.data.attrs||r,t,"$attrs")&&(u=!0),t.$attrs=f,n=n||r;const p=t.$options._parentListeners;if(t._listenersProxy&&Oe(t._listenersProxy,n,p||r,t,"$listeners"),t.$listeners=t.$options._parentListeners=n,Ne(t,n,p),e&&t.$options.props){xt(!1);const n=t._props,r=t.$options._propKeys||[];for(let o=0;ob(r,n));const u=t=>{for(let t=0,e=r.length;t{t.resolved=Te(n,e),o?r.length=0:u(!0)}),p=B(e=>{s(t.errorComp)&&(t.error=!0,u(!0))}),d=t(f,p);return l(d)&&(h(d)?i(t.resolved)&&d.then(f,p):h(d.component)&&(d.component.then(f,p),s(d.error)&&(t.errorComp=Te(d.error,e)),s(d.loading)&&(t.loadingComp=Te(d.loading,e),0===d.delay?t.loading=!0:a=setTimeout(()=>{a=null,i(t.resolved)&&i(t.error)&&(t.loading=!0,u(!1))},d.delay||200)),s(d.timeout)&&(c=setTimeout(()=>{c=null,i(t.resolved)&&p(null)},d.timeout)))),o=!1,t.loading?t.loadingComp:t.resolved}}(p,f))))return function(t,e,n,r,o){const i=pt();return i.asyncFactory=t,i.asyncMeta={data:e,context:n,children:r,tag:o},i}(p,e,n,c,u);e=e||{},Hn(t),s(e.model)&&function(t,e){const n=t.model&&t.model.prop||"value",r=t.model&&t.model.event||"input";(e.attrs||(e.attrs={}))[n]=e.model.value;const i=e.on||(e.on={}),a=i[r],c=e.model.callback;s(a)?(o(a)?-1===a.indexOf(c):a!==c)&&(i[r]=[c].concat(a)):i[r]=c}(t.options,e);const d=function(t,e,n){const r=e.options.props;if(i(r))return;const o={},{attrs:a,props:c}=t;if(s(a)||s(c))for(const t in r){const e=A(t);Gt(o,c,t,e,!0)||Gt(o,a,t,e,!1)}return o}(e,t);if(a(t.options.functional))return function(t,e,n,i,a){const c=t.options,u={},l=c.props;if(s(l))for(const t in l)u[t]=sr(t,l,e||r);else s(n.attrs)&&Vn(u,n.attrs),s(n.props)&&Vn(u,n.props);const f=new zn(n,u,a,i,t),p=c.render.call(null,f._c,f);if(p instanceof ft)return Yn(p,n,f.parent,c);if(o(p)){const t=Xt(p)||[],e=new Array(t.length);for(let r=0;r{t(n,r),e(n,r)};return n._merged=!0,n}let Xn=j;const Zn=H.optionMergeStrategies;function Qn(t,e,n=!0){if(!e)return t;let r,o,i;const s=at?Reflect.ownKeys(e):Object.keys(e);for(let a=0;a{Zn[t]=er}),U.forEach((function(t){Zn[t+"s"]=nr})),Zn.watch=function(t,e,n,r){if(t===et&&(t=void 0),e===et&&(e=void 0),!e)return Object.create(t||null);if(!t)return e;const i={};R(i,t);for(const t in e){let n=i[t];const r=e[t];n&&!o(n)&&(n=[n]),i[t]=n?n.concat(r):o(r)?r:[r]}return i},Zn.props=Zn.methods=Zn.inject=Zn.computed=function(t,e,n,r){if(!t)return e;const o=Object.create(null);return R(o,t),e&&R(o,e),o},Zn.provide=function(t,e){return t?function(){const n=Object.create(null);return Qn(n,u(t)?t.call(this):t),e&&Qn(n,u(e)?e.call(this):e,!1),n}:e};const rr=function(t,e){return void 0===e?t:e};function or(t,e,n){if(u(e)&&(e=e.options),function(t,e){const n=t.props;if(!n)return;const r={};let i,s,a;if(o(n))for(i=n.length;i--;)s=n[i],"string"==typeof s&&(a=E(s),r[a]={type:null});else if(p(n))for(const t in n)s=n[t],a=E(t),r[a]=p(s)?s:{type:s};t.props=r}(e),function(t,e){const n=t.inject;if(!n)return;const r=t.inject={};if(o(n))for(let t=0;t-1)if(i&&!$(o,"default"))s=!1;else if(""===s||s===A(t)){const t=lr(String,o.type);(t<0||a-1:"string"==typeof t?t.split(",").indexOf(e)>-1:(n=t,"[object RegExp]"===f.call(n)&&t.test(e));var n}function hr(t,e){const{cache:n,keys:r,_vnode:o}=t;for(const t in n){const i=n[t];if(i){const s=i.name;s&&!e(s)&&mr(n,t,r,o)}}}function mr(t,e,n,r){const o=t[e];!o||r&&o.tag===r.tag||o.componentInstance.$destroy(),t[e]=null,b(n,e)}!function(t){t.prototype._init=function(t){const e=this;e._uid=Fn++,e._isVue=!0,e.__v_skip=!0,e._scope=new en(!0),e._scope._vm=!0,t&&t._isComponent?function(t,e){const n=t.$options=Object.create(t.constructor.options),r=e._parentVnode;n.parent=e.parent,n._parentVnode=r;const o=r.componentOptions;n.propsData=o.propsData,n._parentListeners=o.listeners,n._renderChildren=o.children,n._componentTag=o.tag,e.render&&(n.render=e.render,n.staticRenderFns=e.staticRenderFns)}(e,t):e.$options=or(Hn(e.constructor),t||{},e),e._renderProxy=e,e._self=e,function(t){const e=t.$options;let n=e.parent;if(n&&!e.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(t)}t.$parent=n,t.$root=n?n.$root:t,t.$children=[],t.$refs={},t._provided=n?n._provided:Object.create(null),t._watcher=null,t._inactive=null,t._directInactive=!1,t._isMounted=!1,t._isDestroyed=!1,t._isBeingDestroyed=!1}(e),function(t){t._events=Object.create(null),t._hasHookEvent=!1;const e=t.$options._parentListeners;e&&Ne(t,e)}(e),function(t){t._vnode=null,t._staticTrees=null;const e=t.$options,n=t.$vnode=e._parentVnode,o=n&&n.context;t.$slots=ge(e._renderChildren,o),t.$scopedSlots=n?_e(t.$parent,n.data.scopedSlots,t.$slots):r,t._c=(e,n,r,o)=>Qt(t,e,n,r,o,!1),t.$createElement=(e,n,r,o)=>Qt(t,e,n,r,o,!0);const i=n&&n.data;kt(t,"$attrs",i&&i.attrs||r,null,!0),kt(t,"$listeners",e._parentListeners||r,null,!0)}(e),Me(e,"beforeCreate",void 0,!1),function(t){const e=Un(t.$options.inject,t);e&&(xt(!1),Object.keys(e).forEach(n=>{kt(t,n,e[n])}),xt(!0))}(e),Nn(e),function(t){const e=t.$options.provide;if(e){const n=u(e)?e.call(t):e;if(!l(n))return;const r=nn(t),o=at?Reflect.ownKeys(n):Object.keys(n);for(let t=0;t1?k(n):n;const r=k(arguments,1),o=`event handler for "${t}"`;for(let t=0,i=n.length;tparseInt(this.max)&&mr(t,e[0],e,this._vnode),this.vnodeToCache=null}}},created(){this.cache=Object.create(null),this.keys=[]},destroyed(){for(const t in this.cache)mr(this.cache,t,this.keys)},mounted(){this.cacheVNode(),this.$watch("include",t=>{hr(this,e=>dr(t,e))}),this.$watch("exclude",t=>{hr(this,e=>!dr(t,e))})},updated(){this.cacheVNode()},render(){const t=this.$slots.default,e=ke(t),n=e&&e.componentOptions;if(n){const t=pr(n),{include:r,exclude:o}=this;if(r&&(!t||!dr(r,t))||o&&t&&dr(o,t))return e;const{cache:i,keys:s}=this,a=null==e.key?n.Ctor.cid+(n.tag?"::"+n.tag:""):e.key;i[a]?(e.componentInstance=i[a].componentInstance,b(s,a),s.push(a)):(this.vnodeToCache=e,this.keyToCache=a),e.data.keepAlive=!0}return e||t&&t[0]}}};!function(t){const e={get:()=>H};Object.defineProperty(t,"config",e),t.util={warn:Xn,extend:R,mergeOptions:or,defineReactive:kt},t.set=Rt,t.delete=Pt,t.nextTick=dn,t.observable=t=>(Tt(t),t),t.options=Object.create(null),U.forEach(e=>{t.options[e+"s"]=Object.create(null)}),t.options._base=t,R(t.options.components,yr),function(t){t.use=function(t){const e=this._installedPlugins||(this._installedPlugins=[]);if(e.indexOf(t)>-1)return this;const n=k(arguments,1);return n.unshift(this),u(t.install)?t.install.apply(t,n):u(t)&&t.apply(null,n),e.push(t),this}}(t),function(t){t.mixin=function(t){return this.options=or(this.options,t),this}}(t),function(t){t.cid=0;let e=1;t.extend=function(t){t=t||{};const n=this,r=n.cid,o=t._Ctor||(t._Ctor={});if(o[r])return o[r];const i=qn(t)||qn(n.options),s=function(t){this._init(t)};return(s.prototype=Object.create(n.prototype)).constructor=s,s.cid=e++,s.options=or(n.options,t),s.super=n,s.options.props&&function(t){const e=t.options.props;for(const n in e)jn(t.prototype,"_props",n)}(s),s.options.computed&&function(t){const e=t.options.computed;for(const n in e)Dn(t.prototype,n,e[n])}(s),s.extend=n.extend,s.mixin=n.mixin,s.use=n.use,U.forEach((function(t){s[t]=n[t]})),i&&(s.options.components[i]=s),s.superOptions=n.options,s.extendOptions=t,s.sealedOptions=R({},s.options),o[r]=s,s}}(t),function(t){U.forEach(e=>{t[e]=function(t,n){return n?("component"===e&&p(n)&&(n.name=n.name||t,n=this.options._base.extend(n)),"directive"===e&&u(n)&&(n={bind:n,update:n}),this.options[e+"s"][t]=n,n):this.options[e+"s"][t]}})}(t)}(fr),Object.defineProperty(fr.prototype,"$isServer",{get:ot}),Object.defineProperty(fr.prototype,"$ssrContext",{get(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(fr,"FunctionalRenderContext",{value:zn}),fr.version="2.7.14";const vr=y("style,class"),_r=y("input,textarea,option,select,progress"),br=(t,e,n)=>"value"===n&&_r(t)&&"button"!==e||"selected"===n&&"option"===t||"checked"===n&&"input"===t||"muted"===n&&"video"===t,wr=y("contenteditable,draggable,spellcheck"),$r=y("events,caret,typing,plaintext-only"),Or=y("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,truespeed,typemustmatch,visible"),Sr="http://www.w3.org/1999/xlink",Er=t=>":"===t.charAt(5)&&"xlink"===t.slice(0,5),xr=t=>Er(t)?t.slice(6,t.length):"",Cr=t=>null==t||!1===t;function Ar(t,e){return{staticClass:Tr(t.staticClass,e.staticClass),class:s(t.class)?[t.class,e.class]:e.class}}function Tr(t,e){return t?e?t+" "+e:t:e||""}function kr(t){return Array.isArray(t)?function(t){let e,n="";for(let r=0,o=t.length;rPr(t)||jr(t);function Lr(t){return jr(t)?"svg":"math"===t?"math":void 0}const Dr=Object.create(null),Ir=y("text,number,password,search,email,tel,url");function Br(t){if("string"==typeof t){return document.querySelector(t)||document.createElement("div")}return t}var Mr=Object.freeze({__proto__:null,createElement:function(t,e){const n=document.createElement(t);return"select"!==t||e.data&&e.data.attrs&&void 0!==e.data.attrs.multiple&&n.setAttribute("multiple","multiple"),n},createElementNS:function(t,e){return document.createElementNS(Rr[t],e)},createTextNode:function(t){return document.createTextNode(t)},createComment:function(t){return document.createComment(t)},insertBefore:function(t,e,n){t.insertBefore(e,n)},removeChild:function(t,e){t.removeChild(e)},appendChild:function(t,e){t.appendChild(e)},parentNode:function(t){return t.parentNode},nextSibling:function(t){return t.nextSibling},tagName:function(t){return t.tagName},setTextContent:function(t,e){t.textContent=e},setStyleScope:function(t,e){t.setAttribute(e,"")}}),Ur={create(t,e){Fr(e)},update(t,e){t.data.ref!==e.data.ref&&(Fr(t,!0),Fr(e))},destroy(t){Fr(t,!0)}};function Fr(t,e){const n=t.data.ref;if(!s(n))return;const r=t.context,i=t.componentInstance||t.elm,a=e?null:i,c=e?void 0:i;if(u(n))return void on(n,r,[a],r,"template ref function");const l=t.data.refInFor,f="string"==typeof n||"number"==typeof n,p=Mt(n),d=r.$refs;if(f||p)if(l){const t=f?d[n]:n.value;e?o(t)&&b(t,i):o(t)?t.includes(i)||t.push(i):f?(d[n]=[i],Hr(r,n,d[n])):n.value=[i]}else if(f){if(e&&d[n]!==i)return;d[n]=c,Hr(r,n,a)}else if(p){if(e&&n.value!==i)return;n.value=a}}function Hr({_setupState:t},e,n){t&&$(t,e)&&(Mt(t[e])?t[e].value=n:t[e]=n)}const zr=new ft("",{},[]),Yr=["create","activate","update","remove","destroy"];function Vr(t,e){return t.key===e.key&&t.asyncFactory===e.asyncFactory&&(t.tag===e.tag&&t.isComment===e.isComment&&s(t.data)===s(e.data)&&function(t,e){if("input"!==t.tag)return!0;let n;const r=s(n=t.data)&&s(n=n.attrs)&&n.type,o=s(n=e.data)&&s(n=n.attrs)&&n.type;return r===o||Ir(r)&&Ir(o)}(t,e)||a(t.isAsyncPlaceholder)&&i(e.asyncFactory.error))}function qr(t,e,n){let r,o;const i={};for(r=e;r<=n;++r)o=t[r].key,s(o)&&(i[o]=r);return i}var Jr={create:Kr,update:Kr,destroy:function(t){Kr(t,zr)}};function Kr(t,e){(t.data.directives||e.data.directives)&&function(t,e){const n=t===zr,r=e===zr,o=Gr(t.data.directives,t.context),i=Gr(e.data.directives,e.context),s=[],a=[];let c,u,l;for(c in i)u=o[c],l=i[c],u?(l.oldValue=u.value,l.oldArg=u.arg,Zr(l,"update",e,t),l.def&&l.def.componentUpdated&&a.push(l)):(Zr(l,"bind",e,t),l.def&&l.def.inserted&&s.push(l));if(s.length){const r=()=>{for(let n=0;n{for(let n=0;n-1?no(t,e,n):Or(e)?Cr(n)?t.removeAttribute(e):(n="allowfullscreen"===e&&"EMBED"===t.tagName?"true":e,t.setAttribute(e,n)):wr(e)?t.setAttribute(e,((t,e)=>Cr(e)||"false"===e?"false":"contenteditable"===t&&$r(e)?e:"true")(e,n)):Er(e)?Cr(n)?t.removeAttributeNS(Sr,xr(e)):t.setAttributeNS(Sr,e,n):no(t,e,n)}function no(t,e,n){if(Cr(n))t.removeAttribute(e);else{if(G&&!X&&"TEXTAREA"===t.tagName&&"placeholder"===e&&""!==n&&!t.__ieph){const e=n=>{n.stopImmediatePropagation(),t.removeEventListener("input",e)};t.addEventListener("input",e),t.__ieph=!0}t.setAttribute(e,n)}}var ro={create:to,update:to};function oo(t,e){const n=e.elm,r=e.data,o=t.data;if(i(r.staticClass)&&i(r.class)&&(i(o)||i(o.staticClass)&&i(o.class)))return;let a=function(t){let e=t.data,n=t,r=t;for(;s(r.componentInstance);)r=r.componentInstance._vnode,r&&r.data&&(e=Ar(r.data,e));for(;s(n=n.parent);)n&&n.data&&(e=Ar(e,n.data));return function(t,e){return s(t)||s(e)?Tr(t,kr(e)):""}(e.staticClass,e.class)}(e);const c=n._transitionClasses;s(c)&&(a=Tr(a,kr(c))),a!==n._prevClass&&(n.setAttribute("class",a),n._prevClass=a)}var io={create:oo,update:oo};const so=/[\w).+\-_$\]]/;function ao(t){let e,n,r,o,i,s=!1,a=!1,c=!1,u=!1,l=0,f=0,p=0,d=0;for(r=0;r=0&&(e=t.charAt(n)," "===e);n--);e&&so.test(e)||(u=!0)}}else void 0===o?(d=r+1,o=t.slice(0,r).trim()):h();function h(){(i||(i=[])).push(t.slice(d,r).trim()),d=r+1}if(void 0===o?o=t.slice(0,r).trim():0!==d&&h(),i)for(r=0;rt[e]).filter(t=>t):[]}function fo(t,e,n,r,o){(t.props||(t.props=[])).push(wo({name:e,value:n,dynamic:o},r)),t.plain=!1}function po(t,e,n,r,o){(o?t.dynamicAttrs||(t.dynamicAttrs=[]):t.attrs||(t.attrs=[])).push(wo({name:e,value:n,dynamic:o},r)),t.plain=!1}function ho(t,e,n,r){t.attrsMap[e]=n,t.attrsList.push(wo({name:e,value:n},r))}function mo(t,e,n,r,o,i,s,a){(t.directives||(t.directives=[])).push(wo({name:e,rawName:n,value:r,arg:o,isDynamicArg:i,modifiers:s},a)),t.plain=!1}function go(t,e,n){return n?`_p(${e},"${t}")`:t+e}function yo(t,e,n,o,i,s,a,c){let u;(o=o||r).right?c?e=`(${e})==='click'?'contextmenu':(${e})`:"click"===e&&(e="contextmenu",delete o.right):o.middle&&(c?e=`(${e})==='click'?'mouseup':(${e})`:"click"===e&&(e="mouseup")),o.capture&&(delete o.capture,e=go("!",e,c)),o.once&&(delete o.once,e=go("~",e,c)),o.passive&&(delete o.passive,e=go("&",e,c)),o.native?(delete o.native,u=t.nativeEvents||(t.nativeEvents={})):u=t.events||(t.events={});const l=wo({value:n.trim(),dynamic:c},a);o!==r&&(l.modifiers=o);const f=u[e];Array.isArray(f)?i?f.unshift(l):f.push(l):u[e]=f?i?[l,f]:[f,l]:l,t.plain=!1}function vo(t,e,n){const r=_o(t,":"+e)||_o(t,"v-bind:"+e);if(null!=r)return ao(r);if(!1!==n){const n=_o(t,e);if(null!=n)return JSON.stringify(n)}}function _o(t,e,n){let r;if(null!=(r=t.attrsMap[e])){const n=t.attrsList;for(let t=0,r=n.length;t-1?{exp:t.slice(0,Co),key:'"'+t.slice(Co+1)+'"'}:{exp:t,key:null};for(Eo=t,Co=Ao=To=0;!Po();)xo=Ro(),jo(xo)?Lo(xo):91===xo&&No(xo);return{exp:t.slice(0,Ao),key:t.slice(Ao+1,To)}}(t);return null===n.key?`${t}=${e}`:`$set(${n.exp}, ${n.key}, ${e})`}let So,Eo,xo,Co,Ao,To,ko;function Ro(){return Eo.charCodeAt(++Co)}function Po(){return Co>=So}function jo(t){return 34===t||39===t}function No(t){let e=1;for(Ao=Co;!Po();)if(jo(t=Ro()))Lo(t);else if(91===t&&e++,93===t&&e--,0===e){To=Co;break}}function Lo(t){const e=t;for(;!Po()&&(t=Ro())!==e;);}function Do(t,e,n){const r=ko;return function o(){const i=e.apply(null,arguments);null!==i&&Mo(t,o,n,r)}}const Io=cn&&!(tt&&Number(tt[1])<=53);function Bo(t,e,n,r){if(Io){const t=qe,n=e;e=n._wrapper=function(e){if(e.target===e.currentTarget||e.timeStamp>=t||e.timeStamp<=0||e.target.ownerDocument!==document)return n.apply(this,arguments)}}ko.addEventListener(t,e,rt?{capture:n,passive:r}:n)}function Mo(t,e,n,r){(r||ko).removeEventListener(t,e._wrapper||e,n)}function Uo(t,e){if(i(t.data.on)&&i(e.data.on))return;const n=e.data.on||{},r=t.data.on||{};ko=e.elm||t.elm,function(t){if(s(t.__r)){const e=G?"change":"input";t[e]=[].concat(t.__r,t[e]||[]),delete t.__r}s(t.__c)&&(t.change=[].concat(t.__c,t.change||[]),delete t.__c)}(n),Kt(n,r,Bo,Mo,Do,e.context),ko=void 0}var Fo={create:Uo,update:Uo,destroy:t=>Uo(t,zr)};let Ho;function zo(t,e){if(i(t.data.domProps)&&i(e.data.domProps))return;let n,r;const o=e.elm,c=t.data.domProps||{};let u=e.data.domProps||{};for(n in(s(u.__ob__)||a(u._v_attr_proxy))&&(u=e.data.domProps=R({},u)),c)n in u||(o[n]="");for(n in u){if(r=u[n],"textContent"===n||"innerHTML"===n){if(e.children&&(e.children.length=0),r===c[n])continue;1===o.childNodes.length&&o.removeChild(o.childNodes[0])}if("value"===n&&"PROGRESS"!==o.tagName){o._value=r;const t=i(r)?"":String(r);Yo(o,t)&&(o.value=t)}else if("innerHTML"===n&&jr(o.tagName)&&i(o.innerHTML)){Ho=Ho||document.createElement("div"),Ho.innerHTML=`${r}`;const t=Ho.firstChild;for(;o.firstChild;)o.removeChild(o.firstChild);for(;t.firstChild;)o.appendChild(t.firstChild)}else if(r!==c[n])try{o[n]=r}catch(t){}}}function Yo(t,e){return!t.composing&&("OPTION"===t.tagName||function(t,e){let n=!0;try{n=document.activeElement!==t}catch(t){}return n&&t.value!==e}(t,e)||function(t,e){const n=t.value,r=t._vModifiers;if(s(r)){if(r.number)return g(n)!==g(e);if(r.trim)return n.trim()!==e.trim()}return n!==e}(t,e))}var Vo={create:zo,update:zo};const qo=O((function(t){const e={},n=/:(.+)/;return t.split(/;(?![^(]*\))/g).forEach((function(t){if(t){const r=t.split(n);r.length>1&&(e[r[0].trim()]=r[1].trim())}})),e}));function Jo(t){const e=Ko(t.style);return t.staticStyle?R(t.staticStyle,e):e}function Ko(t){return Array.isArray(t)?P(t):"string"==typeof t?qo(t):t}const Wo=/^--/,Go=/\s*!important$/,Xo=(t,e,n)=>{if(Wo.test(e))t.style.setProperty(e,n);else if(Go.test(n))t.style.setProperty(A(e),n.replace(Go,""),"important");else{const r=ti(e);if(Array.isArray(n))for(let e=0,o=n.length;e-1?e.split(ri).forEach(e=>t.classList.add(e)):t.classList.add(e);else{const n=` ${t.getAttribute("class")||""} `;n.indexOf(" "+e+" ")<0&&t.setAttribute("class",(n+e).trim())}}function ii(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(ri).forEach(e=>t.classList.remove(e)):t.classList.remove(e),t.classList.length||t.removeAttribute("class");else{let n=` ${t.getAttribute("class")||""} `;const r=" "+e+" ";for(;n.indexOf(r)>=0;)n=n.replace(r," ");n=n.trim(),n?t.setAttribute("class",n):t.removeAttribute("class")}}function si(t){if(t){if("object"==typeof t){const e={};return!1!==t.css&&R(e,ai(t.name||"v")),R(e,t),e}return"string"==typeof t?ai(t):void 0}}const ai=O(t=>({enterClass:t+"-enter",enterToClass:t+"-enter-to",enterActiveClass:t+"-enter-active",leaveClass:t+"-leave",leaveToClass:t+"-leave-to",leaveActiveClass:t+"-leave-active"})),ci=K&&!X;let ui="transition",li="transitionend",fi="animation",pi="animationend";ci&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(ui="WebkitTransition",li="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(fi="WebkitAnimation",pi="webkitAnimationEnd"));const di=K?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:t=>t();function hi(t){di(()=>{di(t)})}function mi(t,e){const n=t._transitionClasses||(t._transitionClasses=[]);n.indexOf(e)<0&&(n.push(e),oi(t,e))}function gi(t,e){t._transitionClasses&&b(t._transitionClasses,e),ii(t,e)}function yi(t,e,n){const{type:r,timeout:o,propCount:i}=_i(t,e);if(!r)return n();const s="transition"===r?li:pi;let a=0;const c=()=>{t.removeEventListener(s,u),n()},u=e=>{e.target===t&&++a>=i&&c()};setTimeout(()=>{a0&&(u="transition",l=i,f=o.length):"animation"===e?c>0&&(u="animation",l=c,f=a.length):(l=Math.max(i,c),u=l>0?i>c?"transition":"animation":null,f=u?"transition"===u?o.length:a.length:0),{type:u,timeout:l,propCount:f,hasTransform:"transition"===u&&vi.test(n[ui+"Property"])}}function bi(t,e){for(;t.lengthwi(e)+wi(t[n])))}function wi(t){return 1e3*Number(t.slice(0,-1).replace(",","."))}function $i(t,e){const n=t.elm;s(n._leaveCb)&&(n._leaveCb.cancelled=!0,n._leaveCb());const r=si(t.data.transition);if(i(r))return;if(s(n._enterCb)||1!==n.nodeType)return;const{css:o,type:a,enterClass:c,enterToClass:f,enterActiveClass:p,appearClass:d,appearToClass:h,appearActiveClass:m,beforeEnter:y,enter:v,afterEnter:_,enterCancelled:b,beforeAppear:w,appear:$,afterAppear:O,appearCancelled:S,duration:E}=r;let x=Le,C=Le.$vnode;for(;C&&C.parent;)x=C.context,C=C.parent;const A=!x._isMounted||!t.isRootInsert;if(A&&!$&&""!==$)return;const T=A&&d?d:c,k=A&&m?m:p,R=A&&h?h:f,P=A&&w||y,j=A&&u($)?$:v,N=A&&O||_,L=A&&S||b,D=g(l(E)?E.enter:E),I=!1!==o&&!X,M=Ei(j),U=n._enterCb=B(()=>{I&&(gi(n,R),gi(n,k)),U.cancelled?(I&&gi(n,T),L&&L(n)):N&&N(n),n._enterCb=null});t.data.show||Wt(t,"insert",()=>{const e=n.parentNode,r=e&&e._pending&&e._pending[t.key];r&&r.tag===t.tag&&r.elm._leaveCb&&r.elm._leaveCb(),j&&j(n,U)}),P&&P(n),I&&(mi(n,T),mi(n,k),hi(()=>{gi(n,T),U.cancelled||(mi(n,R),M||(Si(D)?setTimeout(U,D):yi(n,a,U)))})),t.data.show&&(e&&e(),j&&j(n,U)),I||M||U()}function Oi(t,e){const n=t.elm;s(n._enterCb)&&(n._enterCb.cancelled=!0,n._enterCb());const r=si(t.data.transition);if(i(r)||1!==n.nodeType)return e();if(s(n._leaveCb))return;const{css:o,type:a,leaveClass:c,leaveToClass:u,leaveActiveClass:f,beforeLeave:p,leave:d,afterLeave:h,leaveCancelled:m,delayLeave:y,duration:v}=r,_=!1!==o&&!X,b=Ei(d),w=g(l(v)?v.leave:v),$=n._leaveCb=B(()=>{n.parentNode&&n.parentNode._pending&&(n.parentNode._pending[t.key]=null),_&&(gi(n,u),gi(n,f)),$.cancelled?(_&&gi(n,c),m&&m(n)):(e(),h&&h(n)),n._leaveCb=null});function O(){$.cancelled||(!t.data.show&&n.parentNode&&((n.parentNode._pending||(n.parentNode._pending={}))[t.key]=t),p&&p(n),_&&(mi(n,c),mi(n,f),hi(()=>{gi(n,c),$.cancelled||(mi(n,u),b||(Si(w)?setTimeout($,w):yi(n,a,$)))})),d&&d(n,$),_||b||$())}y?y(O):O()}function Si(t){return"number"==typeof t&&!isNaN(t)}function Ei(t){if(i(t))return!1;const e=t.fns;return s(e)?Ei(Array.isArray(e)?e[0]:e):(t._length||t.length)>1}function xi(t,e){!0!==e.data.show&&$i(e)}const Ci=function(t){let e,n;const r={},{modules:u,nodeOps:l}=t;for(e=0;em?(f=i(n[v+1])?null:n[v+1].elm,b(t,f,n,h,v,r)):h>v&&$(e,d,m)}(f,m,y,n,u):s(y)?(s(t.text)&&l.setTextContent(f,""),b(f,null,y,0,y.length-1,n)):s(m)?$(m,0,m.length-1):s(t.text)&&l.setTextContent(f,""):t.text!==e.text&&l.setTextContent(f,e.text),s(h)&&s(d=h.hook)&&s(d=d.postpatch)&&d(t,e)}function x(t,e,n){if(a(n)&&s(t.parent))t.parent.data.pendingInsert=e;else for(let t=0;t{const t=document.activeElement;t&&t.vmodel&&Li(t,"input")});const Ai={inserted(t,e,n,r){"select"===n.tag?(r.elm&&!r.elm._vOptions?Wt(n,"postpatch",()=>{Ai.componentUpdated(t,e,n)}):Ti(t,e,n.context),t._vOptions=[].map.call(t.options,Pi)):("textarea"===n.tag||Ir(t.type))&&(t._vModifiers=e.modifiers,e.modifiers.lazy||(t.addEventListener("compositionstart",ji),t.addEventListener("compositionend",Ni),t.addEventListener("change",Ni),X&&(t.vmodel=!0)))},componentUpdated(t,e,n){if("select"===n.tag){Ti(t,e,n.context);const r=t._vOptions,o=t._vOptions=[].map.call(t.options,Pi);o.some((t,e)=>!D(t,r[e]))&&(t.multiple?e.value.some(t=>Ri(t,o)):e.value!==e.oldValue&&Ri(e.value,o))&&Li(t,"change")}}};function Ti(t,e,n){ki(t,e),(G||Z)&&setTimeout(()=>{ki(t,e)},0)}function ki(t,e,n){const r=e.value,o=t.multiple;if(o&&!Array.isArray(r))return;let i,s;for(let e=0,n=t.options.length;e-1,s.selected!==i&&(s.selected=i);else if(D(Pi(s),r))return void(t.selectedIndex!==e&&(t.selectedIndex=e));o||(t.selectedIndex=-1)}function Ri(t,e){return e.every(e=>!D(e,t))}function Pi(t){return"_value"in t?t._value:t.value}function ji(t){t.target.composing=!0}function Ni(t){t.target.composing&&(t.target.composing=!1,Li(t.target,"input"))}function Li(t,e){const n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0),t.dispatchEvent(n)}function Di(t){return!t.componentInstance||t.data&&t.data.transition?t:Di(t.componentInstance._vnode)}var Ii={model:Ai,show:{bind(t,{value:e},n){const r=(n=Di(n)).data&&n.data.transition,o=t.__vOriginalDisplay="none"===t.style.display?"":t.style.display;e&&r?(n.data.show=!0,$i(n,()=>{t.style.display=o})):t.style.display=e?o:"none"},update(t,{value:e,oldValue:n},r){!e!=!n&&((r=Di(r)).data&&r.data.transition?(r.data.show=!0,e?$i(r,()=>{t.style.display=t.__vOriginalDisplay}):Oi(r,()=>{t.style.display="none"})):t.style.display=e?t.__vOriginalDisplay:"none")},unbind(t,e,n,r,o){o||(t.style.display=t.__vOriginalDisplay)}}};const Bi={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function Mi(t){const e=t&&t.componentOptions;return e&&e.Ctor.options.abstract?Mi(ke(e.children)):t}function Ui(t){const e={},n=t.$options;for(const r in n.propsData)e[r]=t[r];const r=n._parentListeners;for(const t in r)e[E(t)]=r[t];return e}function Fi(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{props:e.componentOptions.propsData})}const Hi=t=>t.tag||ve(t),zi=t=>"show"===t.name;var Yi={name:"transition",props:Bi,abstract:!0,render(t){let e=this.$slots.default;if(!e)return;if(e=e.filter(Hi),!e.length)return;const n=this.mode,r=e[0];if(function(t){for(;t=t.parent;)if(t.data.transition)return!0}(this.$vnode))return r;const o=Mi(r);if(!o)return r;if(this._leaving)return Fi(t,r);const i=`__transition-${this._uid}-`;o.key=null==o.key?o.isComment?i+"comment":i+o.tag:c(o.key)?0===String(o.key).indexOf(i)?o.key:i+o.key:o.key;const s=(o.data||(o.data={})).transition=Ui(this),a=this._vnode,u=Mi(a);if(o.data.directives&&o.data.directives.some(zi)&&(o.data.show=!0),u&&u.data&&!function(t,e){return e.key===t.key&&e.tag===t.tag}(o,u)&&!ve(u)&&(!u.componentInstance||!u.componentInstance._vnode.isComment)){const e=u.data.transition=R({},s);if("out-in"===n)return this._leaving=!0,Wt(e,"afterLeave",()=>{this._leaving=!1,this.$forceUpdate()}),Fi(t,r);if("in-out"===n){if(ve(o))return a;let t;const n=()=>{t()};Wt(s,"afterEnter",n),Wt(s,"enterCancelled",n),Wt(e,"delayLeave",e=>{t=e})}}return r}};const Vi=R({tag:String,moveClass:String},Bi);function qi(t){t.elm._moveCb&&t.elm._moveCb(),t.elm._enterCb&&t.elm._enterCb()}function Ji(t){t.data.newPos=t.elm.getBoundingClientRect()}function Ki(t){const e=t.data.pos,n=t.data.newPos,r=e.left-n.left,o=e.top-n.top;if(r||o){t.data.moved=!0;const e=t.elm.style;e.transform=e.WebkitTransform=`translate(${r}px,${o}px)`,e.transitionDuration="0s"}}delete Vi.mode;var Wi={Transition:Yi,TransitionGroup:{props:Vi,beforeMount(){const t=this._update;this._update=(e,n)=>{const r=De(this);this.__patch__(this._vnode,this.kept,!1,!0),this._vnode=this.kept,r(),t.call(this,e,n)}},render(t){const e=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,o=this.$slots.default||[],i=this.children=[],s=Ui(this);for(let t=0;t{if(t.data.moved){const n=t.elm,r=n.style;mi(n,e),r.transform=r.WebkitTransform=r.transitionDuration="",n.addEventListener(li,n._moveCb=function t(r){r&&r.target!==n||r&&!/transform$/.test(r.propertyName)||(n.removeEventListener(li,t),n._moveCb=null,gi(n,e))})}}))},methods:{hasMove(t,e){if(!ci)return!1;if(this._hasMove)return this._hasMove;const n=t.cloneNode();t._transitionClasses&&t._transitionClasses.forEach(t=>{ii(n,t)}),oi(n,e),n.style.display="none",this.$el.appendChild(n);const r=_i(n);return this.$el.removeChild(n),this._hasMove=r.hasTransform}}}};fr.config.mustUseProp=br,fr.config.isReservedTag=Nr,fr.config.isReservedAttr=vr,fr.config.getTagNamespace=Lr,fr.config.isUnknownElement=function(t){if(!K)return!0;if(Nr(t))return!1;if(t=t.toLowerCase(),null!=Dr[t])return Dr[t];const e=document.createElement(t);return t.indexOf("-")>-1?Dr[t]=e.constructor===window.HTMLUnknownElement||e.constructor===window.HTMLElement:Dr[t]=/HTMLUnknownElement/.test(e.toString())},R(fr.options.directives,Ii),R(fr.options.components,Wi),fr.prototype.__patch__=K?Ci:j,fr.prototype.$mount=function(t,e){return function(t,e,n){let r;t.$el=e,t.$options.render||(t.$options.render=pt),Me(t,"beforeMount"),r=()=>{t._update(t._render(),n)},new Rn(t,r,j,{before(){t._isMounted&&!t._isDestroyed&&Me(t,"beforeUpdate")}},!0),n=!1;const o=t._preWatchers;if(o)for(let t=0;t{H.devtools&&it&&it.emit("init",fr)},0);const Gi=/\{\{((?:.|\r?\n)+?)\}\}/g,Xi=/[-.*+?^${}()|[\]\/\\]/g,Zi=O(t=>{const e=t[0].replace(Xi,"\\$&"),n=t[1].replace(Xi,"\\$&");return new RegExp(e+"((?:.|\\n)+?)"+n,"g")});var Qi={staticKeys:["staticClass"],transformNode:function(t,e){e.warn;const n=_o(t,"class");n&&(t.staticClass=JSON.stringify(n.replace(/\s+/g," ").trim()));const r=vo(t,"class",!1);r&&(t.classBinding=r)},genData:function(t){let e="";return t.staticClass&&(e+=`staticClass:${t.staticClass},`),t.classBinding&&(e+=`class:${t.classBinding},`),e}},ts={staticKeys:["staticStyle"],transformNode:function(t,e){e.warn;const n=_o(t,"style");n&&(t.staticStyle=JSON.stringify(qo(n)));const r=vo(t,"style",!1);r&&(t.styleBinding=r)},genData:function(t){let e="";return t.staticStyle&&(e+=`staticStyle:${t.staticStyle},`),t.styleBinding&&(e+=`style:(${t.styleBinding}),`),e}};let es;var ns=t=>(es=es||document.createElement("div"),es.innerHTML=t,es.textContent);const rs=y("area,base,br,col,embed,frame,hr,img,input,isindex,keygen,link,meta,param,source,track,wbr"),os=y("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source"),is=y("address,article,aside,base,blockquote,body,caption,col,colgroup,dd,details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,title,tr,track"),ss=/^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,as=/^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+?\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,cs=`[a-zA-Z_][\\-\\.0-9_a-zA-Z${z.source}]*`,us=`((?:${cs}\\:)?${cs})`,ls=new RegExp("^<"+us),fs=/^\s*(\/?)>/,ps=new RegExp(`^<\\/${us}[^>]*>`),ds=/^]+>/i,hs=/^",""":'"',"&":"&"," ":"\n"," ":"\t","'":"'"},_s=/&(?:lt|gt|quot|amp|#39);/g,bs=/&(?:lt|gt|quot|amp|#39|#10|#9);/g,ws=y("pre,textarea",!0),$s=(t,e)=>t&&ws(t)&&"\n"===e[0];function Os(t,e){const n=e?bs:_s;return t.replace(n,t=>vs[t])}const Ss=/^@|^v-on:/,Es=/^v-|^@|^:|^#/,xs=/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/,Cs=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,As=/^\(|\)$/g,Ts=/^\[.*\]$/,ks=/:(.*)$/,Rs=/^:|^\.|^v-bind:/,Ps=/\.[^.\]]+(?=[^\]]*$)/g,js=/^v-slot(:|$)|^#/,Ns=/[\r\n]/,Ls=/[ \f\t\r\n]+/g,Ds=O(ns);let Is,Bs,Ms,Us,Fs,Hs,zs,Ys;function Vs(t,e,n){return{type:1,tag:t,attrsList:e,attrsMap:Xs(e),rawAttrsMap:{},parent:n,children:[]}}function qs(t,e){var n;!function(t){const e=vo(t,"key");e&&(t.key=e)}(t),t.plain=!t.key&&!t.scopedSlots&&!t.attrsList.length,function(t){const e=vo(t,"ref");e&&(t.ref=e,t.refInFor=function(t){let e=t;for(;e;){if(void 0!==e.for)return!0;e=e.parent}return!1}(t))}(t),function(t){let e;"template"===t.tag?(e=_o(t,"scope"),t.slotScope=e||_o(t,"slot-scope")):(e=_o(t,"slot-scope"))&&(t.slotScope=e);const n=vo(t,"slot");if(n&&(t.slotTarget='""'===n?'"default"':n,t.slotTargetDynamic=!(!t.attrsMap[":slot"]&&!t.attrsMap["v-bind:slot"]),"template"===t.tag||t.slotScope||po(t,"slot",n,function(t,e){return t.rawAttrsMap[":"+e]||t.rawAttrsMap["v-bind:"+e]||t.rawAttrsMap[e]}(t,"slot"))),"template"===t.tag){const e=bo(t,js);if(e){const{name:n,dynamic:r}=Ws(e);t.slotTarget=n,t.slotTargetDynamic=r,t.slotScope=e.value||"_empty_"}}else{const e=bo(t,js);if(e){const n=t.scopedSlots||(t.scopedSlots={}),{name:r,dynamic:o}=Ws(e),i=n[r]=Vs("template",[],t);i.slotTarget=r,i.slotTargetDynamic=o,i.children=t.children.filter(t=>{if(!t.slotScope)return t.parent=i,!0}),i.slotScope=e.value||"_empty_",t.children=[],t.plain=!1}}}(t),"slot"===(n=t).tag&&(n.slotName=vo(n,"name")),function(t){let e;(e=vo(t,"is"))&&(t.component=e),null!=_o(t,"inline-template")&&(t.inlineTemplate=!0)}(t);for(let n=0;n{t[e.slice(1)]=!0}),t}}function Xs(t){const e={};for(let n=0,r=t.length;n-1`+("true"===i?`:(${e})`:`:_q(${e},${i})`)),yo(t,"change",`var $$a=${e},$$el=$event.target,$$c=$$el.checked?(${i}):(${s});if(Array.isArray($$a)){var $$v=${r?"_n("+o+")":o},$$i=_i($$a,$$v);if($$el.checked){$$i<0&&(${Oo(e,"$$a.concat([$$v])")})}else{$$i>-1&&(${Oo(e,"$$a.slice(0,$$i).concat($$a.slice($$i+1))")})}}else{${Oo(e,"$$c")}}`,null,!0)}(t,r,o);else if("input"===i&&"radio"===s)!function(t,e,n){const r=n&&n.number;let o=vo(t,"value")||"null";o=r?`_n(${o})`:o,fo(t,"checked",`_q(${e},${o})`),yo(t,"change",Oo(e,o),null,!0)}(t,r,o);else if("input"===i||"textarea"===i)!function(t,e,n){const r=t.attrsMap.type,{lazy:o,number:i,trim:s}=n||{},a=!o&&"range"!==r,c=o?"change":"range"===r?"__r":"input";let u="$event.target.value";s&&(u="$event.target.value.trim()"),i&&(u=`_n(${u})`);let l=Oo(e,u);a&&(l="if($event.target.composing)return;"+l),fo(t,"value",`(${e})`),yo(t,c,l,null,!0),(s||i)&&yo(t,"blur","$forceUpdate()")}(t,r,o);else if(!H.isReservedTag(i))return $o(t,r,o),!1;return!0},text:function(t,e){e.value&&fo(t,"textContent",`_s(${e.value})`,e)},html:function(t,e){e.value&&fo(t,"innerHTML",`_s(${e.value})`,e)}},isPreTag:t=>"pre"===t,isUnaryTag:rs,mustUseProp:br,canBeLeftOpenTag:os,isReservedTag:Nr,getTagNamespace:Lr,staticKeys:function(t){return t.reduce((t,e)=>t.concat(e.staticKeys||[]),[]).join(",")}(ea)};let ra,oa;const ia=O((function(t){return y("type,tag,attrsList,attrsMap,plain,parent,children,attrs,start,end,rawAttrsMap"+(t?","+t:""))}));function sa(t,e){t&&(ra=ia(e.staticKeys||""),oa=e.isReservedTag||N,function t(e){if(e.static=function(t){return 2!==t.type&&(3===t.type||!(!t.pre&&(t.hasBindings||t.if||t.for||v(t.tag)||!oa(t.tag)||function(t){for(;t.parent;){if("template"!==(t=t.parent).tag)return!1;if(t.for)return!0}return!1}(t)||!Object.keys(t).every(ra))))}(e),1===e.type){if(!oa(e.tag)&&"slot"!==e.tag&&null==e.attrsMap["inline-template"])return;for(let n=0,r=e.children.length;n|^function(?:\s+[\w$]+)?\s*\(/,ca=/\([^)]*?\);*$/,ua=/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/,la={esc:27,tab:9,enter:13,space:32,up:38,left:37,right:39,down:40,delete:[8,46]},fa={esc:["Esc","Escape"],tab:"Tab",enter:"Enter",space:[" ","Spacebar"],up:["Up","ArrowUp"],left:["Left","ArrowLeft"],right:["Right","ArrowRight"],down:["Down","ArrowDown"],delete:["Backspace","Delete","Del"]},pa=t=>`if(${t})return null;`,da={stop:"$event.stopPropagation();",prevent:"$event.preventDefault();",self:pa("$event.target !== $event.currentTarget"),ctrl:pa("!$event.ctrlKey"),shift:pa("!$event.shiftKey"),alt:pa("!$event.altKey"),meta:pa("!$event.metaKey"),left:pa("'button' in $event && $event.button !== 0"),middle:pa("'button' in $event && $event.button !== 1"),right:pa("'button' in $event && $event.button !== 2")};function ha(t,e){const n=e?"nativeOn:":"on:";let r="",o="";for(const e in t){const n=ma(t[e]);t[e]&&t[e].dynamic?o+=`${e},${n},`:r+=`"${e}":${n},`}return r=`{${r.slice(0,-1)}}`,o?n+`_d(${r},[${o.slice(0,-1)}])`:n+r}function ma(t){if(!t)return"function(){}";if(Array.isArray(t))return`[${t.map(t=>ma(t)).join(",")}]`;const e=ua.test(t.value),n=aa.test(t.value),r=ua.test(t.value.replace(ca,""));if(t.modifiers){let o="",i="";const s=[];for(const e in t.modifiers)if(da[e])i+=da[e],la[e]&&s.push(e);else if("exact"===e){const e=t.modifiers;i+=pa(["ctrl","shift","alt","meta"].filter(t=>!e[t]).map(t=>`$event.${t}Key`).join("||"))}else s.push(e);return s.length&&(o+=function(t){return`if(!$event.type.indexOf('key')&&${t.map(ga).join("&&")})return null;`}(s)),i&&(o+=i),`function($event){${o}${e?`return ${t.value}.apply(null, arguments)`:n?`return (${t.value}).apply(null, arguments)`:r?"return "+t.value:t.value}}`}return e||n?t.value:`function($event){${r?"return "+t.value:t.value}}`}function ga(t){const e=parseInt(t,10);if(e)return"$event.keyCode!=="+e;const n=la[t],r=fa[t];return`_k($event.keyCode,${JSON.stringify(t)},${JSON.stringify(n)},$event.key,${JSON.stringify(r)})`}var ya={on:function(t,e){t.wrapListeners=t=>`_g(${t},${e.value})`},bind:function(t,e){t.wrapData=n=>`_b(${n},'${t.tag}',${e.value},${e.modifiers&&e.modifiers.prop?"true":"false"}${e.modifiers&&e.modifiers.sync?",true":""})`},cloak:j};class va{constructor(t){this.options=t,this.warn=t.warn||uo,this.transforms=lo(t.modules,"transformCode"),this.dataGenFns=lo(t.modules,"genData"),this.directives=R(R({},ya),t.directives);const e=t.isReservedTag||N;this.maybeComponent=t=>!!t.component||!e(t.tag),this.onceId=0,this.staticRenderFns=[],this.pre=!1}}function _a(t,e){const n=new va(e);return{render:`with(this){return ${t?"script"===t.tag?"null":ba(t,n):'_c("div")'}}`,staticRenderFns:n.staticRenderFns}}function ba(t,e){if(t.parent&&(t.pre=t.pre||t.parent.pre),t.staticRoot&&!t.staticProcessed)return wa(t,e);if(t.once&&!t.onceProcessed)return $a(t,e);if(t.for&&!t.forProcessed)return Sa(t,e);if(t.if&&!t.ifProcessed)return Oa(t,e);if("template"!==t.tag||t.slotTarget||e.pre){if("slot"===t.tag)return function(t,e){const n=t.slotName||'"default"',r=Aa(t,e);let o=`_t(${n}${r?`,function(){return ${r}}`:""}`;const i=t.attrs||t.dynamicAttrs?Ra((t.attrs||[]).concat(t.dynamicAttrs||[]).map(t=>({name:E(t.name),value:t.value,dynamic:t.dynamic}))):null,s=t.attrsMap["v-bind"];return!i&&!s||r||(o+=",null"),i&&(o+=","+i),s&&(o+=`${i?"":",null"},${s}`),o+")"}(t,e);{let n;if(t.component)n=function(t,e,n){const r=e.inlineTemplate?null:Aa(e,n,!0);return`_c(${t},${Ea(e,n)}${r?","+r:""})`}(t.component,t,e);else{let r;const o=e.maybeComponent(t);let i;(!t.plain||t.pre&&o)&&(r=Ea(t,e));const s=e.options.bindings;o&&s&&!1!==s.__isScriptSetup&&(i=function(t,e){const n=E(e),r=x(n),o=o=>t[e]===o?e:t[n]===o?n:t[r]===o?r:void 0,i=o("setup-const")||o("setup-reactive-const");if(i)return i;const s=o("setup-let")||o("setup-ref")||o("setup-maybe-ref");return s||void 0}(s,t.tag)),i||(i=`'${t.tag}'`);const a=t.inlineTemplate?null:Aa(t,e,!0);n=`_c(${i}${r?","+r:""}${a?","+a:""})`}for(let r=0;r{const n=e[t];return n.slotTargetDynamic||n.if||n.for||xa(n)}),o=!!t.if;if(!r){let e=t.parent;for(;e;){if(e.slotScope&&"_empty_"!==e.slotScope||e.for){r=!0;break}e.if&&(o=!0),e=e.parent}}const i=Object.keys(e).map(t=>Ca(e[t],n)).join(",");return`scopedSlots:_u([${i}]${r?",null,true":""}${!r&&o?",null,false,"+function(t){let e=5381,n=t.length;for(;n;)e=33*e^t.charCodeAt(--n);return e>>>0}(i):""})`}(t,t.scopedSlots,e)+","),t.model&&(n+=`model:{value:${t.model.value},callback:${t.model.callback},expression:${t.model.expression}},`),t.inlineTemplate){const r=function(t,e){const n=t.children[0];if(n&&1===n.type){const t=_a(n,e.options);return`inlineTemplate:{render:function(){${t.render}},staticRenderFns:[${t.staticRenderFns.map(t=>`function(){${t}}`).join(",")}]}`}}(t,e);r&&(n+=r+",")}return n=n.replace(/,$/,"")+"}",t.dynamicAttrs&&(n=`_b(${n},"${t.tag}",${Ra(t.dynamicAttrs)})`),t.wrapData&&(n=t.wrapData(n)),t.wrapListeners&&(n=t.wrapListeners(n)),n}function xa(t){return 1===t.type&&("slot"===t.tag||t.children.some(xa))}function Ca(t,e){const n=t.attrsMap["slot-scope"];if(t.if&&!t.ifProcessed&&!n)return Oa(t,e,Ca,"null");if(t.for&&!t.forProcessed)return Sa(t,e,Ca);const r="_empty_"===t.slotScope?"":String(t.slotScope),o=`function(${r}){return ${"template"===t.tag?t.if&&n?`(${t.if})?${Aa(t,e)||"undefined"}:undefined`:Aa(t,e)||"undefined":ba(t,e)}}`,i=r?"":",proxy:true";return`{key:${t.slotTarget||'"default"'},fn:${o}${i}}`}function Aa(t,e,n,r,o){const i=t.children;if(i.length){const t=i[0];if(1===i.length&&t.for&&"template"!==t.tag&&"slot"!==t.tag){const o=n?e.maybeComponent(t)?",1":",0":"";return`${(r||ba)(t,e)}${o}`}const s=n?function(t,e){let n=0;for(let r=0;rTa(t.block))){n=2;break}(e(o)||o.ifConditions&&o.ifConditions.some(t=>e(t.block)))&&(n=1)}}return n}(i,e.maybeComponent):0,a=o||ka;return`[${i.map(t=>a(t,e)).join(",")}]${s?","+s:""}`}}function Ta(t){return void 0!==t.for||"template"===t.tag||"slot"===t.tag}function ka(t,e){return 1===t.type?ba(t,e):3===t.type&&t.isComment?function(t){return`_e(${JSON.stringify(t.text)})`}(t):function(t){return`_v(${2===t.type?t.expression:Pa(JSON.stringify(t.text))})`}(t)}function Ra(t){let e="",n="";for(let r=0;rja(t,c)),e[i]=a}}new RegExp("\\b"+"do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,super,throw,while,yield,delete,export,import,return,switch,default,extends,finally,continue,debugger,function,arguments".split(",").join("\\b|\\b")+"\\b"),new RegExp("\\b"+"delete,typeof,void".split(",").join("\\s*\\([^\\)]*\\)|\\b")+"\\s*\\([^\\)]*\\)");const La=(Da=function(t,e){const n=function(t,e){Is=e.warn||uo,Hs=e.isPreTag||N,zs=e.mustUseProp||N,Ys=e.getTagNamespace||N,e.isReservedTag,Ms=lo(e.modules,"transformNode"),Us=lo(e.modules,"preTransformNode"),Fs=lo(e.modules,"postTransformNode"),Bs=e.delimiters;const n=[],r=!1!==e.preserveWhitespace,o=e.whitespace;let i,s,a=!1,c=!1;function u(t){if(l(t),a||t.processed||(t=qs(t,e)),n.length||t===i||i.if&&(t.elseif||t.else)&&Ks(i,{exp:t.elseif,block:t}),s&&!t.forbidden)if(t.elseif||t.else)!function(t,e){const n=function(t){let e=t.length;for(;e--;){if(1===t[e].type)return t[e];t.pop()}}(e.children);n&&n.if&&Ks(n,{exp:t.elseif,block:t})}(t,s);else{if(t.slotScope){const e=t.slotTarget||'"default"';(s.scopedSlots||(s.scopedSlots={}))[e]=t}s.children.push(t),t.parent=s}t.children=t.children.filter(t=>!t.slotScope),l(t),t.pre&&(a=!1),Hs(t.tag)&&(c=!1);for(let n=0;n]*>)","i")),i=t.replace(o,(function(t,o,i){return n=i.length,gs(r)||"noscript"===r||(o=o.replace(//g,"$1").replace(//g,"$1")),$s(r,o)&&(o=o.slice(1)),e.chars&&e.chars(o),""}));c+=t.length-i.length,t=i,p(r,c-n,c)}else{let n,r,o,i=t.indexOf("<");if(0===i){if(hs.test(t)){const n=t.indexOf("--\x3e");if(n>=0){e.shouldKeepComment&&e.comment&&e.comment(t.substring(4,n),c,c+n+3),u(n+3);continue}}if(ms.test(t)){const e=t.indexOf("]>");if(e>=0){u(e+2);continue}}const n=t.match(ds);if(n){u(n[0].length);continue}const r=t.match(ps);if(r){const t=c;u(r[0].length),p(r[1],t,c);continue}const o=l();if(o){f(o),$s(o.tagName,t)&&u(1);continue}}if(i>=0){for(r=t.slice(i);!(ps.test(r)||ls.test(r)||hs.test(r)||ms.test(r)||(o=r.indexOf("<",1),o<0));)i+=o,r=t.slice(i);n=t.substring(0,i)}i<0&&(n=t),n&&u(n.length),e.chars&&n&&e.chars(n,c-n.length,c)}if(t===s){e.chars&&e.chars(t);break}}function u(e){c+=e,t=t.substring(e)}function l(){const e=t.match(ls);if(e){const n={tagName:e[1],attrs:[],start:c};let r,o;for(u(e[0].length);!(r=t.match(fs))&&(o=t.match(as)||t.match(ss));)o.start=c,u(o[0].length),o.end=c,n.attrs.push(o);if(r)return n.unarySlash=r[1],u(r[0].length),n.end=c,n}}function f(t){const s=t.tagName,c=t.unarySlash;r&&("p"===a&&is(s)&&p(a),i(s)&&a===s&&p(s));const u=o(s)||!!c,l=t.attrs.length,f=new Array(l);for(let n=0;n=0&&n[i].lowerCasedTag!==s;i--);else i=0;if(i>=0){for(let t=n.length-1;t>=i;t--)e.end&&e.end(n[t].tag,r,o);n.length=i,a=i&&n[i-1].tag}else"br"===s?e.start&&e.start(t,[],!0,r,o):"p"===s&&(e.start&&e.start(t,[],!1,r,o),e.end&&e.end(t,r,o))}p()}(t,{warn:Is,expectHTML:e.expectHTML,isUnaryTag:e.isUnaryTag,canBeLeftOpenTag:e.canBeLeftOpenTag,shouldDecodeNewlines:e.shouldDecodeNewlines,shouldDecodeNewlinesForHref:e.shouldDecodeNewlinesForHref,shouldKeepComment:e.comments,outputSourceRange:e.outputSourceRange,start(t,r,o,l,f){const p=s&&s.ns||Ys(t);G&&"svg"===p&&(r=function(t){const e=[];for(let n=0;nc&&(o.push(a=t.slice(c,s)),r.push(JSON.stringify(a)));const e=ao(i[1].trim());r.push(`_s(${e})`),o.push({"@binding":e}),c=s+i[0].length}return c{(n?i:o).push(t)};const s=Da(e.trim(),r);return s.errors=o,s.tips=i,s}return{compile:e,compileToFunctions:Na(e)}});var Da;const{compile:Ia,compileToFunctions:Ba}=La(na);let Ma;function Ua(t){return Ma=Ma||document.createElement("div"),Ma.innerHTML=t?'':'
',Ma.innerHTML.indexOf(" ")>0}const Fa=!!K&&Ua(!1),Ha=!!K&&Ua(!0),za=O(t=>{const e=Br(t);return e&&e.innerHTML}),Ya=fr.prototype.$mount;fr.prototype.$mount=function(t,e){if((t=t&&Br(t))===document.body||t===document.documentElement)return this;const n=this.$options;if(!n.render){let e=n.template;if(e)if("string"==typeof e)"#"===e.charAt(0)&&(e=za(e));else{if(!e.nodeType)return this;e=e.innerHTML}else t&&(e=function(t){if(t.outerHTML)return t.outerHTML;{const e=document.createElement("div");return e.appendChild(t.cloneNode(!0)),e.innerHTML}}(t));if(e){const{render:t,staticRenderFns:r}=Ba(e,{outputSourceRange:!1,shouldDecodeNewlines:Fa,shouldDecodeNewlinesForHref:Ha,delimiters:n.delimiters,comments:n.comments},this);n.render=t,n.staticRenderFns=r}}return Ya.call(this,t,e)},fr.compile=Ba,R(fr,Cn),fr.effect=function(t,e){const n=new Rn(ut,t,j,{sync:!0});e&&(n.update=()=>{e(()=>n.run())})},t.exports=fr}).call(this,n("yLpj"),n("URgk").setImmediate)},RYHr:function(t,e,n){"use strict";e.a=null},URgk:function(t,e,n){(function(t){var r=void 0!==t&&t||"undefined"!=typeof self&&self||window,o=Function.prototype.apply;function i(t,e){this._id=t,this._clearFn=e}e.setTimeout=function(){return new i(o.call(setTimeout,r,arguments),clearTimeout)},e.setInterval=function(){return new i(o.call(setInterval,r,arguments),clearInterval)},e.clearTimeout=e.clearInterval=function(t){t&&t.close()},i.prototype.unref=i.prototype.ref=function(){},i.prototype.close=function(){this._clearFn.call(r,this._id)},e.enroll=function(t,e){clearTimeout(t._idleTimeoutId),t._idleTimeout=e},e.unenroll=function(t){clearTimeout(t._idleTimeoutId),t._idleTimeout=-1},e._unrefActive=e.active=function(t){clearTimeout(t._idleTimeoutId);var e=t._idleTimeout;e>=0&&(t._idleTimeoutId=setTimeout((function(){t._onTimeout&&t._onTimeout()}),e))},n("YBdB"),e.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==t&&t.setImmediate||this&&this.setImmediate,e.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==t&&t.clearImmediate||this&&this.clearImmediate}).call(this,n("yLpj"))},XuX8:function(t,e,n){t.exports=n("INkZ")},YBdB:function(t,e,n){(function(t,e){!function(t,n){"use strict";if(!t.setImmediate){var r,o,i,s,a,c=1,u={},l=!1,f=t.document,p=Object.getPrototypeOf&&Object.getPrototypeOf(t);p=p&&p.setTimeout?p:t,"[object process]"==={}.toString.call(t.process)?r=function(t){e.nextTick((function(){h(t)}))}:!function(){if(t.postMessage&&!t.importScripts){var e=!0,n=t.onmessage;return t.onmessage=function(){e=!1},t.postMessage("","*"),t.onmessage=n,e}}()?t.MessageChannel?((i=new MessageChannel).port1.onmessage=function(t){h(t.data)},r=function(t){i.port2.postMessage(t)}):f&&"onreadystatechange"in f.createElement("script")?(o=f.documentElement,r=function(t){var e=f.createElement("script");e.onreadystatechange=function(){h(t),e.onreadystatechange=null,o.removeChild(e),e=null},o.appendChild(e)}):r=function(t){setTimeout(h,0,t)}:(s="setImmediate$"+Math.random()+"$",a=function(e){e.source===t&&"string"==typeof e.data&&0===e.data.indexOf(s)&&h(+e.data.slice(s.length))},t.addEventListener?t.addEventListener("message",a,!1):t.attachEvent("onmessage",a),r=function(e){t.postMessage(s+e,"*")}),p.setImmediate=function(t){"function"!=typeof t&&(t=new Function(""+t));for(var e=new Array(arguments.length-1),n=0;n{s[t]={value:t}}),Object.defineProperties(o,s),Object.defineProperty(i,"isAxiosError",{value:!0}),o.from=(t,e,n,s,a,c)=>{const u=Object.create(i);return r.a.toFlatObject(t,u,(function(t){return t!==Error.prototype}),t=>"isAxiosError"!==t),o.call(u,t.message,e,n,s,a),u.cause=t,u.name=t.name,c&&Object.assign(u,c),u},e.a=o},"kVK+":function(t,e){e.read=function(t,e,n,r,o){var i,s,a=8*o-r-1,c=(1<>1,l=-7,f=n?o-1:0,p=n?-1:1,d=t[e+f];for(f+=p,i=d&(1<<-l)-1,d>>=-l,l+=a;l>0;i=256*i+t[e+f],f+=p,l-=8);for(s=i&(1<<-l)-1,i>>=-l,l+=r;l>0;s=256*s+t[e+f],f+=p,l-=8);if(0===i)i=1-u;else{if(i===c)return s?NaN:1/0*(d?-1:1);s+=Math.pow(2,r),i-=u}return(d?-1:1)*s*Math.pow(2,i-r)},e.write=function(t,e,n,r,o,i){var s,a,c,u=8*i-o-1,l=(1<>1,p=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,d=r?0:i-1,h=r?1:-1,m=e<0||0===e&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(a=isNaN(e)?1:0,s=l):(s=Math.floor(Math.log(e)/Math.LN2),e*(c=Math.pow(2,-s))<1&&(s--,c*=2),(e+=s+f>=1?p/c:p*Math.pow(2,1-f))*c>=2&&(s++,c/=2),s+f>=l?(a=0,s=l):s+f>=1?(a=(e*c-1)*Math.pow(2,o),s+=f):(a=e*Math.pow(2,f-1)*Math.pow(2,o),s=0));o>=8;t[n+d]=255&a,d+=h,a/=256,o-=8);for(s=s<0;t[n+d]=255&s,d+=h,s/=256,u-=8);t[n+d-h]|=128*m}},tjlA:function(t,e,n){"use strict";(function(t){var r=n("H7XF"),o=n("kVK+"),i=n("49sm");function s(){return c.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function a(t,e){if(s()=s())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+s().toString(16)+" bytes");return 0|t}function h(t,e){if(c.isBuffer(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var n=t.length;if(0===n)return 0;for(var r=!1;;)switch(e){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return U(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return F(t).length;default:if(r)return U(t).length;e=(""+e).toLowerCase(),r=!0}}function m(t,e,n){var r=!1;if((void 0===e||e<0)&&(e=0),e>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(e>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return T(this,e,n);case"utf8":case"utf-8":return x(this,e,n);case"ascii":return C(this,e,n);case"latin1":case"binary":return A(this,e,n);case"base64":return E(this,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return k(this,e,n);default:if(r)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),r=!0}}function g(t,e,n){var r=t[e];t[e]=t[n],t[n]=r}function y(t,e,n,r,o){if(0===t.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:t.length-1),n<0&&(n=t.length+n),n>=t.length){if(o)return-1;n=t.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof e&&(e=c.from(e,r)),c.isBuffer(e))return 0===e.length?-1:v(t,e,n,r,o);if("number"==typeof e)return e&=255,c.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(t,e,n):Uint8Array.prototype.lastIndexOf.call(t,e,n):v(t,[e],n,r,o);throw new TypeError("val must be string, number or Buffer")}function v(t,e,n,r,o){var i,s=1,a=t.length,c=e.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(t.length<2||e.length<2)return-1;s=2,a/=2,c/=2,n/=2}function u(t,e){return 1===s?t[e]:t.readUInt16BE(e*s)}if(o){var l=-1;for(i=n;ia&&(n=a-c),i=n;i>=0;i--){for(var f=!0,p=0;po&&(r=o):r=o;var i=e.length;if(i%2!=0)throw new TypeError("Invalid hex string");r>i/2&&(r=i/2);for(var s=0;s>8,o=n%256,i.push(o),i.push(r);return i}(e,t.length-n),t,n,r)}function E(t,e,n){return 0===e&&n===t.length?r.fromByteArray(t):r.fromByteArray(t.slice(e,n))}function x(t,e,n){n=Math.min(t.length,n);for(var r=[],o=e;o239?4:u>223?3:u>191?2:1;if(o+f<=n)switch(f){case 1:u<128&&(l=u);break;case 2:128==(192&(i=t[o+1]))&&(c=(31&u)<<6|63&i)>127&&(l=c);break;case 3:i=t[o+1],s=t[o+2],128==(192&i)&&128==(192&s)&&(c=(15&u)<<12|(63&i)<<6|63&s)>2047&&(c<55296||c>57343)&&(l=c);break;case 4:i=t[o+1],s=t[o+2],a=t[o+3],128==(192&i)&&128==(192&s)&&128==(192&a)&&(c=(15&u)<<18|(63&i)<<12|(63&s)<<6|63&a)>65535&&c<1114112&&(l=c)}null===l?(l=65533,f=1):l>65535&&(l-=65536,r.push(l>>>10&1023|55296),l=56320|1023&l),r.push(l),o+=f}return function(t){var e=t.length;if(e<=4096)return String.fromCharCode.apply(String,t);var n="",r=0;for(;r0&&(t=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(t+=" ... ")),""},c.prototype.compare=function(t,e,n,r,o){if(!c.isBuffer(t))throw new TypeError("Argument must be a Buffer");if(void 0===e&&(e=0),void 0===n&&(n=t?t.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),e<0||n>t.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&e>=n)return 0;if(r>=o)return-1;if(e>=n)return 1;if(this===t)return 0;for(var i=(o>>>=0)-(r>>>=0),s=(n>>>=0)-(e>>>=0),a=Math.min(i,s),u=this.slice(r,o),l=t.slice(e,n),f=0;fo)&&(n=o),t.length>0&&(n<0||e<0)||e>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var i=!1;;)switch(r){case"hex":return _(this,t,e,n);case"utf8":case"utf-8":return b(this,t,e,n);case"ascii":return w(this,t,e,n);case"latin1":case"binary":return $(this,t,e,n);case"base64":return O(this,t,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return S(this,t,e,n);default:if(i)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),i=!0}},c.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function C(t,e,n){var r="";n=Math.min(t.length,n);for(var o=e;or)&&(n=r);for(var o="",i=e;in)throw new RangeError("Trying to access beyond buffer length")}function P(t,e,n,r,o,i){if(!c.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>o||et.length)throw new RangeError("Index out of range")}function j(t,e,n,r){e<0&&(e=65535+e+1);for(var o=0,i=Math.min(t.length-n,2);o>>8*(r?o:1-o)}function N(t,e,n,r){e<0&&(e=4294967295+e+1);for(var o=0,i=Math.min(t.length-n,4);o>>8*(r?o:3-o)&255}function L(t,e,n,r,o,i){if(n+r>t.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function D(t,e,n,r,i){return i||L(t,0,n,4),o.write(t,e,n,r,23,4),n+4}function I(t,e,n,r,i){return i||L(t,0,n,8),o.write(t,e,n,r,52,8),n+8}c.prototype.slice=function(t,e){var n,r=this.length;if((t=~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),(e=void 0===e?r:~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),e0&&(o*=256);)r+=this[t+--e]*o;return r},c.prototype.readUInt8=function(t,e){return e||R(t,1,this.length),this[t]},c.prototype.readUInt16LE=function(t,e){return e||R(t,2,this.length),this[t]|this[t+1]<<8},c.prototype.readUInt16BE=function(t,e){return e||R(t,2,this.length),this[t]<<8|this[t+1]},c.prototype.readUInt32LE=function(t,e){return e||R(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},c.prototype.readUInt32BE=function(t,e){return e||R(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},c.prototype.readIntLE=function(t,e,n){t|=0,e|=0,n||R(t,e,this.length);for(var r=this[t],o=1,i=0;++i=(o*=128)&&(r-=Math.pow(2,8*e)),r},c.prototype.readIntBE=function(t,e,n){t|=0,e|=0,n||R(t,e,this.length);for(var r=e,o=1,i=this[t+--r];r>0&&(o*=256);)i+=this[t+--r]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*e)),i},c.prototype.readInt8=function(t,e){return e||R(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},c.prototype.readInt16LE=function(t,e){e||R(t,2,this.length);var n=this[t]|this[t+1]<<8;return 32768&n?4294901760|n:n},c.prototype.readInt16BE=function(t,e){e||R(t,2,this.length);var n=this[t+1]|this[t]<<8;return 32768&n?4294901760|n:n},c.prototype.readInt32LE=function(t,e){return e||R(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},c.prototype.readInt32BE=function(t,e){return e||R(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},c.prototype.readFloatLE=function(t,e){return e||R(t,4,this.length),o.read(this,t,!0,23,4)},c.prototype.readFloatBE=function(t,e){return e||R(t,4,this.length),o.read(this,t,!1,23,4)},c.prototype.readDoubleLE=function(t,e){return e||R(t,8,this.length),o.read(this,t,!0,52,8)},c.prototype.readDoubleBE=function(t,e){return e||R(t,8,this.length),o.read(this,t,!1,52,8)},c.prototype.writeUIntLE=function(t,e,n,r){(t=+t,e|=0,n|=0,r)||P(this,t,e,n,Math.pow(2,8*n)-1,0);var o=1,i=0;for(this[e]=255&t;++i=0&&(i*=256);)this[e+o]=t/i&255;return e+n},c.prototype.writeUInt8=function(t,e,n){return t=+t,e|=0,n||P(this,t,e,1,255,0),c.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[e]=255&t,e+1},c.prototype.writeUInt16LE=function(t,e,n){return t=+t,e|=0,n||P(this,t,e,2,65535,0),c.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):j(this,t,e,!0),e+2},c.prototype.writeUInt16BE=function(t,e,n){return t=+t,e|=0,n||P(this,t,e,2,65535,0),c.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):j(this,t,e,!1),e+2},c.prototype.writeUInt32LE=function(t,e,n){return t=+t,e|=0,n||P(this,t,e,4,4294967295,0),c.TYPED_ARRAY_SUPPORT?(this[e+3]=t>>>24,this[e+2]=t>>>16,this[e+1]=t>>>8,this[e]=255&t):N(this,t,e,!0),e+4},c.prototype.writeUInt32BE=function(t,e,n){return t=+t,e|=0,n||P(this,t,e,4,4294967295,0),c.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):N(this,t,e,!1),e+4},c.prototype.writeIntLE=function(t,e,n,r){if(t=+t,e|=0,!r){var o=Math.pow(2,8*n-1);P(this,t,e,n,o-1,-o)}var i=0,s=1,a=0;for(this[e]=255&t;++i>0)-a&255;return e+n},c.prototype.writeIntBE=function(t,e,n,r){if(t=+t,e|=0,!r){var o=Math.pow(2,8*n-1);P(this,t,e,n,o-1,-o)}var i=n-1,s=1,a=0;for(this[e+i]=255&t;--i>=0&&(s*=256);)t<0&&0===a&&0!==this[e+i+1]&&(a=1),this[e+i]=(t/s>>0)-a&255;return e+n},c.prototype.writeInt8=function(t,e,n){return t=+t,e|=0,n||P(this,t,e,1,127,-128),c.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[e]=255&t,e+1},c.prototype.writeInt16LE=function(t,e,n){return t=+t,e|=0,n||P(this,t,e,2,32767,-32768),c.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):j(this,t,e,!0),e+2},c.prototype.writeInt16BE=function(t,e,n){return t=+t,e|=0,n||P(this,t,e,2,32767,-32768),c.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):j(this,t,e,!1),e+2},c.prototype.writeInt32LE=function(t,e,n){return t=+t,e|=0,n||P(this,t,e,4,2147483647,-2147483648),c.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8,this[e+2]=t>>>16,this[e+3]=t>>>24):N(this,t,e,!0),e+4},c.prototype.writeInt32BE=function(t,e,n){return t=+t,e|=0,n||P(this,t,e,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),c.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):N(this,t,e,!1),e+4},c.prototype.writeFloatLE=function(t,e,n){return D(this,t,e,!0,n)},c.prototype.writeFloatBE=function(t,e,n){return D(this,t,e,!1,n)},c.prototype.writeDoubleLE=function(t,e,n){return I(this,t,e,!0,n)},c.prototype.writeDoubleBE=function(t,e,n){return I(this,t,e,!1,n)},c.prototype.copy=function(t,e,n,r){if(n||(n=0),r||0===r||(r=this.length),e>=t.length&&(e=t.length),e||(e=0),r>0&&r=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),t.length-e=0;--o)t[o+e]=this[o+n];else if(i<1e3||!c.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,n=void 0===n?this.length:n>>>0,t||(t=0),"number"==typeof t)for(i=e;i55295&&n<57344){if(!o){if(n>56319){(e-=3)>-1&&i.push(239,191,189);continue}if(s+1===r){(e-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(e-=3)>-1&&i.push(239,191,189),o=n;continue}n=65536+(o-55296<<10|n-56320)}else o&&(e-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((e-=1)<0)break;i.push(n)}else if(n<2048){if((e-=2)<0)break;i.push(n>>6|192,63&n|128)}else if(n<65536){if((e-=3)<0)break;i.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((e-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return i}function F(t){return r.toByteArray(function(t){if((t=function(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")}(t).replace(B,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function H(t,e,n,r){for(var o=0;o=e.length||o>=t.length);++o)e[o+n]=t[o];return o}}).call(this,n("yLpj"))},uPOf:function(t,e,n){window.Vue=n("XuX8"),window.axios=n("vDqi"),Vue.prototype.$http=axios,window.eventBus=new Vue},vDqi:function(t,e,n){"use strict";n.r(e),n.d(e,"default",(function(){return tt})),n.d(e,"Axios",(function(){return et})),n.d(e,"AxiosError",(function(){return nt})),n.d(e,"CanceledError",(function(){return rt})),n.d(e,"isCancel",(function(){return ot})),n.d(e,"CancelToken",(function(){return it})),n.d(e,"VERSION",(function(){return st})),n.d(e,"all",(function(){return at})),n.d(e,"Cancel",(function(){return ct})),n.d(e,"isAxiosError",(function(){return ut})),n.d(e,"spread",(function(){return lt})),n.d(e,"toFormData",(function(){return ft})),n.d(e,"AxiosHeaders",(function(){return pt})),n.d(e,"HttpStatusCode",(function(){return dt})),n.d(e,"formToJSON",(function(){return ht})),n.d(e,"getAdapter",(function(){return mt})),n.d(e,"mergeConfig",(function(){return gt}));var r=n("xTJ+"),o=n("HSsa"),i=n("5GeT");function s(t){const e={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+","%00":"\0"};return encodeURIComponent(t).replace(/[!'()~]|%20|%00/g,(function(t){return e[t]}))}function a(t,e){this._pairs=[],t&&Object(i.a)(t,this,e)}const c=a.prototype;c.append=function(t,e){this._pairs.push([t,e])},c.toString=function(t){const e=t?function(e){return t.call(this,e,s)}:s;return this._pairs.map((function(t){return e(t[0])+"="+e(t[1])}),"").join("&")};var u=a;function l(t){return encodeURIComponent(t).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}function f(t,e,n){if(!e)return t;const o=n&&n.encode||l,i=n&&n.serialize;let s;if(s=i?i(e,n):r.a.isURLSearchParams(e)?e.toString():new u(e,n).toString(o),s){const e=t.indexOf("#");-1!==e&&(t=t.slice(0,e)),t+=(-1===t.indexOf("?")?"?":"&")+s}return t}var p=class{constructor(){this.handlers=[]}use(t,e,n){return this.handlers.push({fulfilled:t,rejected:e,synchronous:!!n&&n.synchronous,runWhen:n?n.runWhen:null}),this.handlers.length-1}eject(t){this.handlers[t]&&(this.handlers[t]=null)}clear(){this.handlers&&(this.handlers=[])}forEach(t){r.a.forEach(this.handlers,(function(e){null!==e&&t(e)}))}},d=n("eRe6"),h={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1};var m={isBrowser:!0,classes:{URLSearchParams:"undefined"!=typeof URLSearchParams?URLSearchParams:u,FormData:"undefined"!=typeof FormData?FormData:null,Blob:"undefined"!=typeof Blob?Blob:null},isStandardBrowserEnv:(()=>{let t;return("undefined"==typeof navigator||"ReactNative"!==(t=navigator.product)&&"NativeScript"!==t&&"NS"!==t)&&("undefined"!=typeof window&&"undefined"!=typeof document)})(),isStandardBrowserWebWorkerEnv:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope&&"function"==typeof self.importScripts,protocols:["http","https","file","blob","url","data"]};var g=function(t){function e(t,n,o,i){let s=t[i++];const a=Number.isFinite(+s),c=i>=t.length;if(s=!s&&r.a.isArray(o)?o.length:s,c)return r.a.hasOwnProp(o,s)?o[s]=[o[s],n]:o[s]=n,!a;o[s]&&r.a.isObject(o[s])||(o[s]=[]);return e(t,n,o[s],i)&&r.a.isArray(o[s])&&(o[s]=function(t){const e={},n=Object.keys(t);let r;const o=n.length;let i;for(r=0;r{e(function(t){return r.a.matchAll(/\w+|\[(\w*)]/g,t).map(t=>"[]"===t[0]?"":t[1]||t[0])}(t),o,n,0)}),n}return null};const y={transitional:h,adapter:m.isNode?"http":"xhr",transformRequest:[function(t,e){const n=e.getContentType()||"",o=n.indexOf("application/json")>-1,s=r.a.isObject(t);s&&r.a.isHTMLForm(t)&&(t=new FormData(t));if(r.a.isFormData(t))return o&&o?JSON.stringify(g(t)):t;if(r.a.isArrayBuffer(t)||r.a.isBuffer(t)||r.a.isStream(t)||r.a.isFile(t)||r.a.isBlob(t))return t;if(r.a.isArrayBufferView(t))return t.buffer;if(r.a.isURLSearchParams(t))return e.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),t.toString();let a;if(s){if(n.indexOf("application/x-www-form-urlencoded")>-1)return function(t,e){return Object(i.a)(t,new m.classes.URLSearchParams,Object.assign({visitor:function(t,e,n,o){return m.isNode&&r.a.isBuffer(t)?(this.append(e,t.toString("base64")),!1):o.defaultVisitor.apply(this,arguments)}},e))}(t,this.formSerializer).toString();if((a=r.a.isFileList(t))||n.indexOf("multipart/form-data")>-1){const e=this.env&&this.env.FormData;return Object(i.a)(a?{"files[]":t}:t,e&&new e,this.formSerializer)}}return s||o?(e.setContentType("application/json",!1),function(t,e,n){if(r.a.isString(t))try{return(e||JSON.parse)(t),r.a.trim(t)}catch(t){if("SyntaxError"!==t.name)throw t}return(n||JSON.stringify)(t)}(t)):t}],transformResponse:[function(t){const e=this.transitional||y.transitional,n=e&&e.forcedJSONParsing,o="json"===this.responseType;if(t&&r.a.isString(t)&&(n&&!this.responseType||o)){const n=!(e&&e.silentJSONParsing)&&o;try{return JSON.parse(t)}catch(t){if(n){if("SyntaxError"===t.name)throw d.a.from(t,d.a.ERR_BAD_RESPONSE,this,null,this.response);throw t}}}return t}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:m.classes.FormData,Blob:m.classes.Blob},validateStatus:function(t){return t>=200&&t<300},headers:{common:{Accept:"application/json, text/plain, */*","Content-Type":void 0}}};r.a.forEach(["delete","get","head","post","put","patch"],t=>{y.headers[t]={}});var v=y;const _=r.a.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]);const b=Symbol("internals");function w(t){return t&&String(t).trim().toLowerCase()}function $(t){return!1===t||null==t?t:r.a.isArray(t)?t.map($):String(t)}function O(t,e,n,o,i){return r.a.isFunction(o)?o.call(this,e,n):(i&&(e=n),r.a.isString(e)?r.a.isString(o)?-1!==e.indexOf(o):r.a.isRegExp(o)?o.test(e):void 0:void 0)}class S{constructor(t){t&&this.set(t)}set(t,e,n){const o=this;function i(t,e,n){const i=w(e);if(!i)throw new Error("header name must be a non-empty string");const s=r.a.findKey(o,i);(!s||void 0===o[s]||!0===n||void 0===n&&!1!==o[s])&&(o[s||e]=$(t))}const s=(t,e)=>r.a.forEach(t,(t,n)=>i(t,n,e));return r.a.isPlainObject(t)||t instanceof this.constructor?s(t,e):r.a.isString(t)&&(t=t.trim())&&!/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(t.trim())?s((t=>{const e={};let n,r,o;return t&&t.split("\n").forEach((function(t){o=t.indexOf(":"),n=t.substring(0,o).trim().toLowerCase(),r=t.substring(o+1).trim(),!n||e[n]&&_[n]||("set-cookie"===n?e[n]?e[n].push(r):e[n]=[r]:e[n]=e[n]?e[n]+", "+r:r)})),e})(t),e):null!=t&&i(e,t,n),this}get(t,e){if(t=w(t)){const n=r.a.findKey(this,t);if(n){const t=this[n];if(!e)return t;if(!0===e)return function(t){const e=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let r;for(;r=n.exec(t);)e[r[1]]=r[2];return e}(t);if(r.a.isFunction(e))return e.call(this,t,n);if(r.a.isRegExp(e))return e.exec(t);throw new TypeError("parser must be boolean|regexp|function")}}}has(t,e){if(t=w(t)){const n=r.a.findKey(this,t);return!(!n||void 0===this[n]||e&&!O(0,this[n],n,e))}return!1}delete(t,e){const n=this;let o=!1;function i(t){if(t=w(t)){const i=r.a.findKey(n,t);!i||e&&!O(0,n[i],i,e)||(delete n[i],o=!0)}}return r.a.isArray(t)?t.forEach(i):i(t),o}clear(t){const e=Object.keys(this);let n=e.length,r=!1;for(;n--;){const o=e[n];t&&!O(0,this[o],o,t,!0)||(delete this[o],r=!0)}return r}normalize(t){const e=this,n={};return r.a.forEach(this,(o,i)=>{const s=r.a.findKey(n,i);if(s)return e[s]=$(o),void delete e[i];const a=t?function(t){return t.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(t,e,n)=>e.toUpperCase()+n)}(i):String(i).trim();a!==i&&delete e[i],e[a]=$(o),n[a]=!0}),this}concat(...t){return this.constructor.concat(this,...t)}toJSON(t){const e=Object.create(null);return r.a.forEach(this,(n,o)=>{null!=n&&!1!==n&&(e[o]=t&&r.a.isArray(n)?n.join(", "):n)}),e}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map(([t,e])=>t+": "+e).join("\n")}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(t){return t instanceof this?t:new this(t)}static concat(t,...e){const n=new this(t);return e.forEach(t=>n.set(t)),n}static accessor(t){const e=(this[b]=this[b]={accessors:{}}).accessors,n=this.prototype;function o(t){const o=w(t);e[o]||(!function(t,e){const n=r.a.toCamelCase(" "+e);["get","set","has"].forEach(r=>{Object.defineProperty(t,r+n,{value:function(t,n,o){return this[r].call(this,e,t,n,o)},configurable:!0})})}(n,t),e[o]=!0)}return r.a.isArray(t)?t.forEach(o):o(t),this}}S.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]),r.a.reduceDescriptors(S.prototype,({value:t},e)=>{let n=e[0].toUpperCase()+e.slice(1);return{get:()=>t,set(t){this[n]=t}}}),r.a.freezeMethods(S);var E=S;function x(t,e){const n=this||v,o=e||n,i=E.from(o.headers);let s=o.data;return r.a.forEach(t,(function(t){s=t.call(n,s,i.normalize(),e?e.status:void 0)})),i.normalize(),s}function C(t){return!(!t||!t.__CANCEL__)}function A(t,e,n){d.a.call(this,null==t?"canceled":t,d.a.ERR_CANCELED,e,n),this.name="CanceledError"}r.a.inherits(A,d.a,{__CANCEL__:!0});var T=A,k=n("RYHr");var R=m.isStandardBrowserEnv?{write:function(t,e,n,o,i,s){const a=[];a.push(t+"="+encodeURIComponent(e)),r.a.isNumber(n)&&a.push("expires="+new Date(n).toGMTString()),r.a.isString(o)&&a.push("path="+o),r.a.isString(i)&&a.push("domain="+i),!0===s&&a.push("secure"),document.cookie=a.join("; ")},read:function(t){const e=document.cookie.match(new RegExp("(^|;\\s*)("+t+")=([^;]*)"));return e?decodeURIComponent(e[3]):null},remove:function(t){this.write(t,"",Date.now()-864e5)}}:{write:function(){},read:function(){return null},remove:function(){}};function P(t,e){return t&&!/^([a-z][a-z\d+\-.]*:)?\/\//i.test(e)?function(t,e){return e?t.replace(/\/+$/,"")+"/"+e.replace(/^\/+/,""):t}(t,e):e}var j=m.isStandardBrowserEnv?function(){const t=/(msie|trident)/i.test(navigator.userAgent),e=document.createElement("a");let n;function o(n){let r=n;return t&&(e.setAttribute("href",r),r=e.href),e.setAttribute("href",r),{href:e.href,protocol:e.protocol?e.protocol.replace(/:$/,""):"",host:e.host,search:e.search?e.search.replace(/^\?/,""):"",hash:e.hash?e.hash.replace(/^#/,""):"",hostname:e.hostname,port:e.port,pathname:"/"===e.pathname.charAt(0)?e.pathname:"/"+e.pathname}}return n=o(window.location.href),function(t){const e=r.a.isString(t)?o(t):t;return e.protocol===n.protocol&&e.host===n.host}}():function(){return!0};var N=function(t,e){t=t||10;const n=new Array(t),r=new Array(t);let o,i=0,s=0;return e=void 0!==e?e:1e3,function(a){const c=Date.now(),u=r[s];o||(o=c),n[i]=a,r[i]=c;let l=s,f=0;for(;l!==i;)f+=n[l++],l%=t;if(i=(i+1)%t,i===s&&(s=(s+1)%t),c-o{const i=o.loaded,s=o.lengthComputable?o.total:void 0,a=i-n,c=r(a);n=i;const u={loaded:i,total:s,progress:s?i/s:void 0,bytes:a,rate:c||void 0,estimated:c&&s&&i<=s?(s-i)/c:void 0,event:o};u[e?"download":"upload"]=!0,t(u)}}var D="undefined"!=typeof XMLHttpRequest&&function(t){return new Promise((function(e,n){let o=t.data;const i=E.from(t.headers).normalize(),s=t.responseType;let a;function c(){t.cancelToken&&t.cancelToken.unsubscribe(a),t.signal&&t.signal.removeEventListener("abort",a)}r.a.isFormData(o)&&(m.isStandardBrowserEnv||m.isStandardBrowserWebWorkerEnv?i.setContentType(!1):i.setContentType("multipart/form-data;",!1));let u=new XMLHttpRequest;if(t.auth){const e=t.auth.username||"",n=t.auth.password?unescape(encodeURIComponent(t.auth.password)):"";i.set("Authorization","Basic "+btoa(e+":"+n))}const l=P(t.baseURL,t.url);function p(){if(!u)return;const r=E.from("getAllResponseHeaders"in u&&u.getAllResponseHeaders());!function(t,e,n){const r=n.config.validateStatus;n.status&&r&&!r(n.status)?e(new d.a("Request failed with status code "+n.status,[d.a.ERR_BAD_REQUEST,d.a.ERR_BAD_RESPONSE][Math.floor(n.status/100)-4],n.config,n.request,n)):t(n)}((function(t){e(t),c()}),(function(t){n(t),c()}),{data:s&&"text"!==s&&"json"!==s?u.response:u.responseText,status:u.status,statusText:u.statusText,headers:r,config:t,request:u}),u=null}if(u.open(t.method.toUpperCase(),f(l,t.params,t.paramsSerializer),!0),u.timeout=t.timeout,"onloadend"in u?u.onloadend=p:u.onreadystatechange=function(){u&&4===u.readyState&&(0!==u.status||u.responseURL&&0===u.responseURL.indexOf("file:"))&&setTimeout(p)},u.onabort=function(){u&&(n(new d.a("Request aborted",d.a.ECONNABORTED,t,u)),u=null)},u.onerror=function(){n(new d.a("Network Error",d.a.ERR_NETWORK,t,u)),u=null},u.ontimeout=function(){let e=t.timeout?"timeout of "+t.timeout+"ms exceeded":"timeout exceeded";const r=t.transitional||h;t.timeoutErrorMessage&&(e=t.timeoutErrorMessage),n(new d.a(e,r.clarifyTimeoutError?d.a.ETIMEDOUT:d.a.ECONNABORTED,t,u)),u=null},m.isStandardBrowserEnv){const e=(t.withCredentials||j(l))&&t.xsrfCookieName&&R.read(t.xsrfCookieName);e&&i.set(t.xsrfHeaderName,e)}void 0===o&&i.setContentType(null),"setRequestHeader"in u&&r.a.forEach(i.toJSON(),(function(t,e){u.setRequestHeader(e,t)})),r.a.isUndefined(t.withCredentials)||(u.withCredentials=!!t.withCredentials),s&&"json"!==s&&(u.responseType=t.responseType),"function"==typeof t.onDownloadProgress&&u.addEventListener("progress",L(t.onDownloadProgress,!0)),"function"==typeof t.onUploadProgress&&u.upload&&u.upload.addEventListener("progress",L(t.onUploadProgress)),(t.cancelToken||t.signal)&&(a=e=>{u&&(n(!e||e.type?new T(null,t,u):e),u.abort(),u=null)},t.cancelToken&&t.cancelToken.subscribe(a),t.signal&&(t.signal.aborted?a():t.signal.addEventListener("abort",a)));const g=function(t){const e=/^([-+\w]{1,25})(:?\/\/|:)/.exec(t);return e&&e[1]||""}(l);g&&-1===m.protocols.indexOf(g)?n(new d.a("Unsupported protocol "+g+":",d.a.ERR_BAD_REQUEST,t)):u.send(o||null)}))};const I={http:k.a,xhr:D};r.a.forEach(I,(t,e)=>{if(t){try{Object.defineProperty(t,"name",{value:e})}catch(t){}Object.defineProperty(t,"adapterName",{value:e})}});var B=t=>{t=r.a.isArray(t)?t:[t];const{length:e}=t;let n,o;for(let i=0;it instanceof E?t.toJSON():t;function H(t,e){e=e||{};const n={};function o(t,e,n){return r.a.isPlainObject(t)&&r.a.isPlainObject(e)?r.a.merge.call({caseless:n},t,e):r.a.isPlainObject(e)?r.a.merge({},e):r.a.isArray(e)?e.slice():e}function i(t,e,n){return r.a.isUndefined(e)?r.a.isUndefined(t)?void 0:o(void 0,t,n):o(t,e,n)}function s(t,e){if(!r.a.isUndefined(e))return o(void 0,e)}function a(t,e){return r.a.isUndefined(e)?r.a.isUndefined(t)?void 0:o(void 0,t):o(void 0,e)}function c(n,r,i){return i in e?o(n,r):i in t?o(void 0,n):void 0}const u={url:s,method:s,data:s,baseURL:a,transformRequest:a,transformResponse:a,paramsSerializer:a,timeout:a,timeoutMessage:a,withCredentials:a,adapter:a,responseType:a,xsrfCookieName:a,xsrfHeaderName:a,onUploadProgress:a,onDownloadProgress:a,decompress:a,maxContentLength:a,maxBodyLength:a,beforeRedirect:a,transport:a,httpAgent:a,httpsAgent:a,cancelToken:a,socketPath:a,responseEncoding:a,validateStatus:c,headers:(t,e)=>i(F(t),F(e),!0)};return r.a.forEach(Object.keys(Object.assign({},t,e)),(function(o){const s=u[o]||i,a=s(t[o],e[o],o);r.a.isUndefined(a)&&s!==c||(n[o]=a)})),n}const z={};["object","boolean","number","function","string","symbol"].forEach((t,e)=>{z[t]=function(n){return typeof n===t||"a"+(e<1?"n ":" ")+t}});const Y={};z.transitional=function(t,e,n){function r(t,e){return"[Axios v1.5.0] Transitional option '"+t+"'"+e+(n?". "+n:"")}return(n,o,i)=>{if(!1===t)throw new d.a(r(o," has been removed"+(e?" in "+e:"")),d.a.ERR_DEPRECATED);return e&&!Y[o]&&(Y[o]=!0,console.warn(r(o," has been deprecated since v"+e+" and will be removed in the near future"))),!t||t(n,o,i)}};var V={assertOptions:function(t,e,n){if("object"!=typeof t)throw new d.a("options must be an object",d.a.ERR_BAD_OPTION_VALUE);const r=Object.keys(t);let o=r.length;for(;o-- >0;){const i=r[o],s=e[i];if(s){const e=t[i],n=void 0===e||s(e,i,t);if(!0!==n)throw new d.a("option "+i+" must be "+n,d.a.ERR_BAD_OPTION_VALUE)}else if(!0!==n)throw new d.a("Unknown option "+i,d.a.ERR_BAD_OPTION)}},validators:z};const q=V.validators;class J{constructor(t){this.defaults=t,this.interceptors={request:new p,response:new p}}request(t,e){"string"==typeof t?(e=e||{}).url=t:e=t||{},e=H(this.defaults,e);const{transitional:n,paramsSerializer:o,headers:i}=e;void 0!==n&&V.assertOptions(n,{silentJSONParsing:q.transitional(q.boolean),forcedJSONParsing:q.transitional(q.boolean),clarifyTimeoutError:q.transitional(q.boolean)},!1),null!=o&&(r.a.isFunction(o)?e.paramsSerializer={serialize:o}:V.assertOptions(o,{encode:q.function,serialize:q.function},!0)),e.method=(e.method||this.defaults.method||"get").toLowerCase();let s=i&&r.a.merge(i.common,i[e.method]);i&&r.a.forEach(["delete","get","head","post","put","patch","common"],t=>{delete i[t]}),e.headers=E.concat(s,i);const a=[];let c=!0;this.interceptors.request.forEach((function(t){"function"==typeof t.runWhen&&!1===t.runWhen(e)||(c=c&&t.synchronous,a.unshift(t.fulfilled,t.rejected))}));const u=[];let l;this.interceptors.response.forEach((function(t){u.push(t.fulfilled,t.rejected)}));let f,p=0;if(!c){const t=[U.bind(this),void 0];for(t.unshift.apply(t,a),t.push.apply(t,u),f=t.length,l=Promise.resolve(e);p{if(!n._listeners)return;let e=n._listeners.length;for(;e-- >0;)n._listeners[e](t);n._listeners=null}),this.promise.then=t=>{let e;const r=new Promise(t=>{n.subscribe(t),e=t}).then(t);return r.cancel=function(){n.unsubscribe(e)},r},t((function(t,r,o){n.reason||(n.reason=new T(t,r,o),e(n.reason))}))}throwIfRequested(){if(this.reason)throw this.reason}subscribe(t){this.reason?t(this.reason):this._listeners?this._listeners.push(t):this._listeners=[t]}unsubscribe(t){if(!this._listeners)return;const e=this._listeners.indexOf(t);-1!==e&&this._listeners.splice(e,1)}static source(){let t;return{token:new W((function(e){t=e})),cancel:t}}}var G=W;const X={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(X).forEach(([t,e])=>{X[e]=t});var Z=X;const Q=function t(e){const n=new K(e),i=Object(o.a)(K.prototype.request,n);return r.a.extend(i,K.prototype,n,{allOwnKeys:!0}),r.a.extend(i,n,null,{allOwnKeys:!0}),i.create=function(n){return t(H(e,n))},i}(v);Q.Axios=K,Q.CanceledError=T,Q.CancelToken=G,Q.isCancel=C,Q.VERSION="1.5.0",Q.toFormData=i.a,Q.AxiosError=d.a,Q.Cancel=Q.CanceledError,Q.all=function(t){return Promise.all(t)},Q.spread=function(t){return function(e){return t.apply(null,e)}},Q.isAxiosError=function(t){return r.a.isObject(t)&&!0===t.isAxiosError},Q.mergeConfig=H,Q.AxiosHeaders=E,Q.formToJSON=t=>g(r.a.isHTMLForm(t)?new FormData(t):t),Q.getAdapter=B,Q.HttpStatusCode=Z,Q.default=Q;var tt=Q;const{Axios:et,AxiosError:nt,CanceledError:rt,isCancel:ot,CancelToken:it,VERSION:st,all:at,Cancel:ct,isAxiosError:ut,spread:lt,toFormData:ft,AxiosHeaders:pt,HttpStatusCode:dt,formToJSON:ht,getAdapter:mt,mergeConfig:gt}=tt},"xTJ+":function(t,e,n){"use strict";(function(t){var r=n("HSsa");const{toString:o}=Object.prototype,{getPrototypeOf:i}=Object,s=(a=Object.create(null),t=>{const e=o.call(t);return a[e]||(a[e]=e.slice(8,-1).toLowerCase())});var a;const c=t=>(t=t.toLowerCase(),e=>s(e)===t),u=t=>e=>typeof e===t,{isArray:l}=Array,f=u("undefined");const p=c("ArrayBuffer");const d=u("string"),h=u("function"),m=u("number"),g=t=>null!==t&&"object"==typeof t,y=t=>{if("object"!==s(t))return!1;const e=i(t);return!(null!==e&&e!==Object.prototype&&null!==Object.getPrototypeOf(e)||Symbol.toStringTag in t||Symbol.iterator in t)},v=c("Date"),_=c("File"),b=c("Blob"),w=c("FileList"),$=c("URLSearchParams");function O(t,e,{allOwnKeys:n=!1}={}){if(null==t)return;let r,o;if("object"!=typeof t&&(t=[t]),l(t))for(r=0,o=t.length;r0;)if(r=n[o],e===r.toLowerCase())return r;return null}const E="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:t,x=t=>!f(t)&&t!==E;const C=(A="undefined"!=typeof Uint8Array&&i(Uint8Array),t=>A&&t instanceof A);var A;const T=c("HTMLFormElement"),k=(({hasOwnProperty:t})=>(e,n)=>t.call(e,n))(Object.prototype),R=c("RegExp"),P=(t,e)=>{const n=Object.getOwnPropertyDescriptors(t),r={};O(n,(n,o)=>{let i;!1!==(i=e(n,o,t))&&(r[o]=i||n)}),Object.defineProperties(t,r)},j="abcdefghijklmnopqrstuvwxyz",N={DIGIT:"0123456789",ALPHA:j,ALPHA_DIGIT:j+j.toUpperCase()+"0123456789"};const L=c("AsyncFunction");e.a={isArray:l,isArrayBuffer:p,isBuffer:function(t){return null!==t&&!f(t)&&null!==t.constructor&&!f(t.constructor)&&h(t.constructor.isBuffer)&&t.constructor.isBuffer(t)},isFormData:t=>{let e;return t&&("function"==typeof FormData&&t instanceof FormData||h(t.append)&&("formdata"===(e=s(t))||"object"===e&&h(t.toString)&&"[object FormData]"===t.toString()))},isArrayBufferView:function(t){let e;return e="undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(t):t&&t.buffer&&p(t.buffer),e},isString:d,isNumber:m,isBoolean:t=>!0===t||!1===t,isObject:g,isPlainObject:y,isUndefined:f,isDate:v,isFile:_,isBlob:b,isRegExp:R,isFunction:h,isStream:t=>g(t)&&h(t.pipe),isURLSearchParams:$,isTypedArray:C,isFileList:w,forEach:O,merge:function t(){const{caseless:e}=x(this)&&this||{},n={},r=(r,o)=>{const i=e&&S(n,o)||o;y(n[i])&&y(r)?n[i]=t(n[i],r):y(r)?n[i]=t({},r):l(r)?n[i]=r.slice():n[i]=r};for(let t=0,e=arguments.length;t(O(e,(e,o)=>{n&&h(e)?t[o]=Object(r.a)(e,n):t[o]=e},{allOwnKeys:o}),t),trim:t=>t.trim?t.trim():t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,""),stripBOM:t=>(65279===t.charCodeAt(0)&&(t=t.slice(1)),t),inherits:(t,e,n,r)=>{t.prototype=Object.create(e.prototype,r),t.prototype.constructor=t,Object.defineProperty(t,"super",{value:e.prototype}),n&&Object.assign(t.prototype,n)},toFlatObject:(t,e,n,r)=>{let o,s,a;const c={};if(e=e||{},null==t)return e;do{for(o=Object.getOwnPropertyNames(t),s=o.length;s-- >0;)a=o[s],r&&!r(a,t,e)||c[a]||(e[a]=t[a],c[a]=!0);t=!1!==n&&i(t)}while(t&&(!n||n(t,e))&&t!==Object.prototype);return e},kindOf:s,kindOfTest:c,endsWith:(t,e,n)=>{t=String(t),(void 0===n||n>t.length)&&(n=t.length),n-=e.length;const r=t.indexOf(e,n);return-1!==r&&r===n},toArray:t=>{if(!t)return null;if(l(t))return t;let e=t.length;if(!m(e))return null;const n=new Array(e);for(;e-- >0;)n[e]=t[e];return n},forEachEntry:(t,e)=>{const n=(t&&t[Symbol.iterator]).call(t);let r;for(;(r=n.next())&&!r.done;){const n=r.value;e.call(t,n[0],n[1])}},matchAll:(t,e)=>{let n;const r=[];for(;null!==(n=t.exec(e));)r.push(n);return r},isHTMLForm:T,hasOwnProperty:k,hasOwnProp:k,reduceDescriptors:P,freezeMethods:t=>{P(t,(e,n)=>{if(h(t)&&-1!==["arguments","caller","callee"].indexOf(n))return!1;const r=t[n];h(r)&&(e.enumerable=!1,"writable"in e?e.writable=!1:e.set||(e.set=()=>{throw Error("Can not rewrite read-only method '"+n+"'")}))})},toObjectSet:(t,e)=>{const n={},r=t=>{t.forEach(t=>{n[t]=!0})};return l(t)?r(t):r(String(t).split(e)),n},toCamelCase:t=>t.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,(function(t,e,n){return e.toUpperCase()+n})),noop:()=>{},toFiniteNumber:(t,e)=>(t=+t,Number.isFinite(t)?t:e),findKey:S,global:E,isContextDefined:x,ALPHABET:N,generateString:(t=16,e=N.ALPHA_DIGIT)=>{let n="";const{length:r}=e;for(;t--;)n+=e[Math.random()*r|0];return n},isSpecCompliantForm:function(t){return!!(t&&h(t.append)&&"FormData"===t[Symbol.toStringTag]&&t[Symbol.iterator])},toJSONObject:t=>{const e=new Array(10),n=(t,r)=>{if(g(t)){if(e.indexOf(t)>=0)return;if(!("toJSON"in t)){e[r]=t;const o=l(t)?[]:{};return O(t,(t,e)=>{const i=n(t,r+1);!f(i)&&(o[e]=i)}),e[r]=void 0,o}}return t};return n(t,0)},isAsyncFn:L,isThenable:t=>t&&(g(t)||h(t))&&h(t.then)&&h(t.catch)}}).call(this,n("yLpj"))},y62a:function(t,e){},yLpj:function(t,e){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(t){"object"==typeof window&&(n=window)}t.exports=n}}); \ No newline at end of file diff --git a/publishable/assets/js/bulk-upload-app.js.LICENSE.txt b/publishable/assets/js/bulk-upload-app.js.LICENSE.txt new file mode 100644 index 0000000..a373f46 --- /dev/null +++ b/publishable/assets/js/bulk-upload-app.js.LICENSE.txt @@ -0,0 +1,14 @@ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ + +/*! + * Vue.js v2.7.14 + * (c) 2014-2022 Evan You + * Released under the MIT License. + */ + +/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh */ diff --git a/publishable/assets/mix-manifest.json b/publishable/assets/mix-manifest.json index c4d4c62..5d0b3b9 100644 --- a/publishable/assets/mix-manifest.json +++ b/publishable/assets/mix-manifest.json @@ -1,4 +1,4 @@ { - "/css/bk_upload.css": "/css/bk_upload.css?id=b316e32901a4fff5f3a0", - "/css/bulk-admin.css": "/css/bulk-admin.css?id=d3639ab33677e9640729" + "/js/bulk-upload-app.js": "/js/bulk-upload-app.js?id=ebc4e123bd8d9a514193", + "/css/bulk-upload-admin.css": "/css/bulk-upload-admin.css?id=ba0810725cfe4f929288" } diff --git a/storage/app/public/downloads/sample-files/bulkbookingproductupload.csv b/publishable/assets/sample-files/booking-product-upload.csv similarity index 100% rename from storage/app/public/downloads/sample-files/bulkbookingproductupload.csv rename to publishable/assets/sample-files/booking-product-upload.csv diff --git a/storage/app/public/downloads/sample-files/bulkbookingproductupload.xlsx b/publishable/assets/sample-files/booking-product-upload.xlsx similarity index 100% rename from storage/app/public/downloads/sample-files/bulkbookingproductupload.xlsx rename to publishable/assets/sample-files/booking-product-upload.xlsx diff --git a/storage/app/public/downloads/sample-files/bulkbundleproductupload.csv b/publishable/assets/sample-files/bundle-product-upload.csv similarity index 100% rename from storage/app/public/downloads/sample-files/bulkbundleproductupload.csv rename to publishable/assets/sample-files/bundle-product-upload.csv diff --git a/storage/app/public/downloads/sample-files/bulkbundleproductupload.xlsx b/publishable/assets/sample-files/bundle-product-upload.xlsx similarity index 100% rename from storage/app/public/downloads/sample-files/bulkbundleproductupload.xlsx rename to publishable/assets/sample-files/bundle-product-upload.xlsx diff --git a/storage/app/public/downloads/sample-files/bulkconfigurableproductupload.csv b/publishable/assets/sample-files/configurable-product-upload.csv similarity index 100% rename from storage/app/public/downloads/sample-files/bulkconfigurableproductupload.csv rename to publishable/assets/sample-files/configurable-product-upload.csv diff --git a/storage/app/public/downloads/sample-files/bulkconfigurableproductupload.xlsx b/publishable/assets/sample-files/configurable-product-upload.xlsx similarity index 100% rename from storage/app/public/downloads/sample-files/bulkconfigurableproductupload.xlsx rename to publishable/assets/sample-files/configurable-product-upload.xlsx diff --git a/storage/app/public/downloads/sample-files/bulkdownloadableproductupload.csv b/publishable/assets/sample-files/downloadable-product-upload.csv similarity index 100% rename from storage/app/public/downloads/sample-files/bulkdownloadableproductupload.csv rename to publishable/assets/sample-files/downloadable-product-upload.csv diff --git a/storage/app/public/downloads/sample-files/bulkdownloadableproductupload.xlsx b/publishable/assets/sample-files/downloadable-product-upload.xlsx similarity index 100% rename from storage/app/public/downloads/sample-files/bulkdownloadableproductupload.xlsx rename to publishable/assets/sample-files/downloadable-product-upload.xlsx diff --git a/storage/app/public/downloads/sample-files/bulkgroupedproductupload.csv b/publishable/assets/sample-files/grouped-product-upload.csv similarity index 100% rename from storage/app/public/downloads/sample-files/bulkgroupedproductupload.csv rename to publishable/assets/sample-files/grouped-product-upload.csv diff --git a/storage/app/public/downloads/sample-files/bulkgroupedproductupload.xlsx b/publishable/assets/sample-files/grouped-product-upload.xlsx similarity index 100% rename from storage/app/public/downloads/sample-files/bulkgroupedproductupload.xlsx rename to publishable/assets/sample-files/grouped-product-upload.xlsx diff --git a/storage/app/public/downloads/sample-files/bulksimpleproductupload.csv b/publishable/assets/sample-files/simple-product-upload.csv similarity index 100% rename from storage/app/public/downloads/sample-files/bulksimpleproductupload.csv rename to publishable/assets/sample-files/simple-product-upload.csv diff --git a/storage/app/public/downloads/sample-files/bulksimpleproductupload.xlsx b/publishable/assets/sample-files/simple-product-upload.xlsx similarity index 100% rename from storage/app/public/downloads/sample-files/bulksimpleproductupload.xlsx rename to publishable/assets/sample-files/simple-product-upload.xlsx diff --git a/storage/app/public/downloads/sample-files/bulkvirtualproductupload.csv b/publishable/assets/sample-files/virtual-product-upload.csv similarity index 100% rename from storage/app/public/downloads/sample-files/bulkvirtualproductupload.csv rename to publishable/assets/sample-files/virtual-product-upload.csv diff --git a/storage/app/public/downloads/sample-files/bulkvirtualproductupload.xlsx b/publishable/assets/sample-files/virtual-product-upload.xlsx similarity index 100% rename from storage/app/public/downloads/sample-files/bulkvirtualproductupload.xlsx rename to publishable/assets/sample-files/virtual-product-upload.xlsx diff --git a/src/Config/admin-menu.php b/src/Config/admin-menu.php index 6652a2b..9bba4b1 100644 --- a/src/Config/admin-menu.php +++ b/src/Config/admin-menu.php @@ -4,25 +4,25 @@ [ 'key' => 'catalog.bulkupload', 'name' => 'bulkupload::app.admin.bulk-upload.manage-bulk-upload', - 'route' => 'admin.dataflow-profile.index', + 'route' => 'admin.bulk-upload.bulk-product-importer.index', 'sort' => 5, 'icon-class' => '', ], [ - 'key' => 'catalog.bulkupload.data-flow-profile', - 'name' => 'bulkupload::app.admin.bulk-upload.data-flow-profile.index', - 'route' => 'admin.dataflow-profile.index', + 'key' => 'catalog.bulkupload.bulk-product-importer-profile', + 'name' => 'bulkupload::app.admin.bulk-upload.bulk-product-importer.index', + 'route' => 'admin.bulk-upload.bulk-product-importer.index', 'sort' => 1, 'icon-class' => '', ], [ 'key' => 'catalog.bulkupload.upload-files', - 'name' => 'bulkupload::app.admin.bulk-upload.upload-files.index', - 'route' => 'admin.bulk-upload.index', + 'name' => 'bulkupload::app.admin.bulk-upload.bulk-product-importer.index', + 'route' => 'admin.bulk-upload.upload-file.index', 'sort' => 2, 'icon-class' => '', ], [ 'key' => 'catalog.bulkupload.run-profile', 'name' => 'bulkupload::app.admin.bulk-upload.run-profile.index', - 'route' => 'admin.run-profile.index', + 'route' => 'admin.bulk-upload.import-file.run-profile.index', 'sort' => 3, 'icon-class' => '', ] diff --git a/src/Contracts/DataFlowProfile.php b/src/Contracts/BulkProductImporter.php similarity index 60% rename from src/Contracts/DataFlowProfile.php rename to src/Contracts/BulkProductImporter.php index 0f1f4ff..7968c0b 100644 --- a/src/Contracts/DataFlowProfile.php +++ b/src/Contracts/BulkProductImporter.php @@ -2,6 +2,6 @@ namespace Webkul\Bulkupload\Contracts; -interface DataFlowProfile +interface BulkProductImporter { -} \ No newline at end of file +} diff --git a/src/DataGrids/Admin/ProfileDataGrid.php b/src/DataGrids/Admin/BulkProductImporterDataGrid.php similarity index 51% rename from src/DataGrids/Admin/ProfileDataGrid.php rename to src/DataGrids/Admin/BulkProductImporterDataGrid.php index f0c9404..70a49b8 100644 --- a/src/DataGrids/Admin/ProfileDataGrid.php +++ b/src/DataGrids/Admin/BulkProductImporterDataGrid.php @@ -9,32 +9,61 @@ * Profile Datagrid class * */ -class ProfileDataGrid extends DataGrid +class BulkProductImporterDataGrid extends DataGrid { /** * @var integer */ protected $index = 'id'; + /** + * Sort order. + * + * @var string + */ + protected $sortOrder = 'desc'; + + /** + * Items per page. + * + * @var int + */ + protected $itemsPerPage = 10; + + /** + * Prepare query builder. + * + * @return void + */ public function prepareQueryBuilder() { - $queryBuilder = DB::table('bulkupload_data_flow_profiles') - ->leftJoin('attribute_families', 'bulkupload_data_flow_profiles.attribute_family_id', '=', 'attribute_families.id') - ->select('bulkupload_data_flow_profiles.id', - 'bulkupload_data_flow_profiles.name as profile_name', 'attribute_families.name', 'bulkupload_data_flow_profiles.locale_code', 'bulkupload_data_flow_profiles.created_at'); + $queryBuilder = DB::table('bulk_product_importers') + ->leftJoin('attribute_families', 'bulk_product_importers.attribute_family_id', '=', 'attribute_families.id') + ->select( + 'bulk_product_importers.id', + 'bulk_product_importers.name as profile_name', + 'attribute_families.name', + 'bulk_product_importers.locale_code', + 'bulk_product_importers.created_at' + ); - $this->addFilter('created_at', 'bulkupload_data_flow_profiles.created_at'); - $this->addFilter('profile_name', 'bulkupload_data_flow_profiles.name'); + $this->addFilter('created_at', 'bulk_product_importers.created_at'); + $this->addFilter('profile_name', 'bulk_product_importers.name'); $this->addFilter('name', 'attribute_families.name'); $this->setQueryBuilder($queryBuilder); } + /** + * Add columns. + * + * @return void + */ public function addColumns() { $this->addColumn([ 'index' => 'profile_name', - 'label' => trans('bulkupload::app.admin.bulk-upload.data-flow-profile.name'), + 'label' => trans('bulkupload::app.admin.bulk-upload.bulk-product-importer.name'), 'type' => 'string', 'searchable' => true, 'sortable' => true, @@ -43,7 +72,7 @@ public function addColumns() $this->addColumn([ 'index' => 'name', - 'label' => trans('admin::app.catalog.products.familiy'), + 'label' => trans('admin::app.catalog.products.family'), 'type' => 'string', 'searchable' => true, 'sortable' => true, @@ -52,7 +81,7 @@ public function addColumns() $this->addColumn([ 'index' => 'locale_code', - 'label' => trans('bulkupload::app.admin.bulk-upload.data-flow-profile.data-grid.locale_code'), + 'label' => trans('bulkupload::app.admin.bulk-upload.bulk-product-importer.data-grid.locale_code'), 'type' => 'string', 'searchable' => true, 'sortable' => true, @@ -61,7 +90,7 @@ public function addColumns() $this->addColumn([ 'index' => 'created_at', - 'label' => trans('bulkupload::app.admin.bulk-upload.data-flow-profile.data-grid.created-at'), + 'label' => trans('bulkupload::app.admin.bulk-upload.bulk-product-importer.data-grid.created-at'), 'type' => 'datetime', 'sortable' => true, 'searchable' => false, @@ -69,35 +98,40 @@ public function addColumns() ]); } + /** + * Prepare actions. + * + * @return void + */ public function prepareActions() { $this->addAction([ - 'type' => 'Edit', + 'title' => trans('admin::app.datagrid.edit'), 'method' => 'GET', - 'route' => 'bulkupload.admin.profile.edit', + 'route' => 'admin.bulk-upload.bulk-product-importer.edit', 'icon' => 'icon pencil-lg-icon', - 'title' => '' - ]); $this->addAction([ - 'type' => trans('admin::app.datagrid.delete'), - 'method' => 'POST', - 'route' => 'bulkupload.admin.profile.delete', - 'confirm_text' => trans('ui::app.datagrid.massaction.delete'), - 'icon' => 'icon trash-icon', - 'title' => '' + 'title' => trans('admin::app.datagrid.delete'), + 'method' => 'POST', + 'route' => 'admin.bulk-upload.bulk-product-importer.delete', + 'confirm_text' => trans('ui::app.datagrid.mass-action.delete', ['resource' => 'address']), + 'icon' => 'icon trash-icon', ]); - - $this->enableAction = true; } + /** + * Prepare mass actions. + * + * @return void + */ public function prepareMassActions() { $this->addMassAction([ 'type' => 'delete', 'label' => 'Delete', - 'action' => route('bulkupload.admin.profile.massDelete'), + 'action' => route('admin.bulk-upload.bulk-product-importer.massDelete'), 'method' => 'POST', 'title' => '' ]); diff --git a/src/Database/Migrations/2019_04_23_115227_create_bulkupload_data_flow_profiles_table.php b/src/Database/Migrations/2019_04_23_115227_create_bulkupload_data_flow_profiles_table.php deleted file mode 100644 index bfb110a..0000000 --- a/src/Database/Migrations/2019_04_23_115227_create_bulkupload_data_flow_profiles_table.php +++ /dev/null @@ -1,35 +0,0 @@ -increments('id'); - $table->string('name'); - $table->integer('attribute_family_id')->unsigned(); - $table->foreign('attribute_family_id', 'bulkupload_foreign_attribute_family_id')->references('id')->on('attribute_families')->onDelete('cascade'); - $table->boolean('run_status')->default(0); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('bulkupload_data_flow_profiles'); - } -} diff --git a/src/Database/Migrations/2021_12_28_150311_alter_bulkupload_data_flow_profiles_table.php b/src/Database/Migrations/2021_12_28_150311_alter_bulkupload_data_flow_profiles_table.php deleted file mode 100644 index 7d0e24e..0000000 --- a/src/Database/Migrations/2021_12_28_150311_alter_bulkupload_data_flow_profiles_table.php +++ /dev/null @@ -1,30 +0,0 @@ -string('locale_code'); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - // - } -} diff --git a/src/Database/Migrations/2023_09_20_170448_create_bulk_product_importers_table.php b/src/Database/Migrations/2023_09_20_170448_create_bulk_product_importers_table.php new file mode 100644 index 0000000..9b6462e --- /dev/null +++ b/src/Database/Migrations/2023_09_20_170448_create_bulk_product_importers_table.php @@ -0,0 +1,34 @@ +increments('id'); + $table->string('name'); + $table->string('locale_code'); + + $table->integer('attribute_family_id')->unsigned(); + + $table->foreign('attribute_family_id')->references('id')->on('attribute_families')->onDelete('cascade'); + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('bulk_product_importers'); + } +}; diff --git a/src/Database/Migrations/2020_05_13_223920_create_import_products_table.php b/src/Database/Migrations/2023_09_20_173705_create_import_products_table.php similarity index 66% rename from src/Database/Migrations/2020_05_13_223920_create_import_products_table.php rename to src/Database/Migrations/2023_09_20_173705_create_import_products_table.php index 4dd9b51..eb9941a 100644 --- a/src/Database/Migrations/2020_05_13_223920_create_import_products_table.php +++ b/src/Database/Migrations/2023_09_20_173705_create_import_products_table.php @@ -8,31 +8,28 @@ class CreateImportProductsTable extends Migration { /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { Schema::create('import_products', function (Blueprint $table) { $table->increments('id'); - $table->integer('attribute_family_id')->unsigned(); - $table->foreign('attribute_family_id', 'import_admin_foreign_attribute_family_id')->references('id')->on('attribute_families')->onDelete('cascade'); - - $table->integer('data_flow_profile_id')->unsigned(); - $table->foreign('data_flow_profile_id', 'import_admin_foreign_data_flow_profile_id')->references('id')->on('bulkupload_data_flow_profiles')->onDelete('cascade'); - $table->boolean('is_downloadable')->default(0); $table->string('upload_link_files'); - $table->boolean('is_links_have_samples')->default(0); $table->string('upload_link_sample_files'); - $table->boolean('is_samples_available')->default(0); $table->string('upload_sample_files'); - + $table->string('file_name'); $table->string('file_path'); $table->string('image_path'); + $table->boolean('status')->default(1); + + $table->integer('attribute_family_id')->unsigned(); + $table->integer('bulk_product_importer_id')->unsigned(); + + $table->foreign('attribute_family_id')->references('id')->on('attribute_families')->onDelete('cascade'); + $table->foreign('bulk_product_importer_id')->references('id')->on('bulk_product_importers')->onDelete('cascade'); $table->timestamps(); }); @@ -40,11 +37,9 @@ public function up() /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::dropIfExists('import_products'); } -} +}; diff --git a/src/Helpers/ImportProduct.php b/src/Helpers/ImportProduct.php deleted file mode 100644 index 31b82f2..0000000 --- a/src/Helpers/ImportProduct.php +++ /dev/null @@ -1,163 +0,0 @@ -importProductRepository = $importProductRepository; - - $this->dataFlowProfileRepository = $dataFlowProfileRepository; - } - - /** - * store import products for profile execution - * - * @return \Illuminate\Http\Response - */ - public function store() - { - request()->validate ([ - 'attribute_family' => 'required', - 'file_path' => 'required', - 'image_path' => 'mimetypes:application/zip|max:10000', - 'data_flow_profile' => 'required', - ]); - - $valid_extension = ['csv', 'xls', 'xlsx']; - $valid_image_extension = ['zip', 'rar']; - - $imageDir = 'imported-products/admin/images'; - $fileDir = 'imported-products/admin/files'; - $linkFilesDir = 'imported-products/admin/link-files'; - $linkSampleFilesDir = 'imported-products/admin/link-sample-files'; - $sampleFileDir = 'imported-products/admin/sample-file'; - - $attribute_family_id = request()->attribute_family; - $data_flow_profile_id = request()->data_flow_profile; - - $image = request()->file('image_path'); - $file = request()->file('file_path'); - $linkFiles = request()->file('link_files'); - $linkSampleFiles = request()->file('link_sample_files'); - $sampleFile = request()->file('sample_file'); - - if (! isset($image)) { - $image = ''; - } - - if (request()->is_downloadable) { - $product['is_downloadable'] = 1; - - if (! empty($linkFiles) && in_array($linkFiles->getClientOriginalExtension(), $valid_image_extension)) { - $uploadedLinkFiles = $linkFiles->storeAs($linkFilesDir, uniqid().'.'.$linkFiles->getClientOriginalExtension()); - - $product['upload_link_files'] = $uploadedLinkFiles; - } else { - session()->flash('error', trans('bulkupload::app.admin.bulk-upload.messages.file-format-error')); - - return redirect()->route('admin.bulk-upload.index'); - } - - if (request()->is_link_have_sample) { - $product['is_links_have_samples'] = 1; - - if (in_array($linkSampleFiles->getClientOriginalExtension(), $valid_image_extension)) { - $uploadedLinkSampleFiles = $linkSampleFiles->storeAs($linkSampleFilesDir, uniqid().'.'.$linkSampleFiles->getClientOriginalExtension()); - - $product['upload_link_sample_files'] = $uploadedLinkSampleFiles; - } else { - session()->flash('error', trans('bulkupload::app.admin.bulk-upload.messages.file-format-error')); - - return redirect()->route('admin.bulk-upload.index'); - } - } - - if (request()->is_sample) { - $product['is_samples_available'] = 1; - - if (in_array($sampleFile->getClientOriginalExtension(), $valid_image_extension)) { - $uploadedSampleFiles = $sampleFile->storeAs($sampleFileDir, uniqid().'.'.$sampleFile->getClientOriginalExtension()); - - $product['upload_sample_files'] = $uploadedSampleFiles; - } else { - session()->flash('error', trans('bulkupload::app.admin.bulk-upload.messages.file-format-error')); - - return redirect()->route('admin.bulk-upload.index'); - } - } - } - - $product['data_flow_profile_id'] = $data_flow_profile_id; - $product['attribute_family_id'] = $attribute_family_id; - - if ((! empty($image) && in_array($image->getClientOriginalExtension(), $valid_image_extension)) && (in_array($file->getClientOriginalExtension(), $valid_extension))) { - $uploadedImage = $image->storeAs($imageDir, uniqid().'.'.$image->getClientOriginalExtension()); - - $product['image_path'] = $uploadedImage; - - $uploadedFile = $file->storeAs($fileDir, uniqid().'.'.$file->getClientOriginalExtension()); - - $product['file_path'] = $uploadedFile; - } else if ( empty($image) && (in_array($file->getClientOriginalExtension(), $valid_extension))) { - $product['image_path'] = ''; - - $uploadedFile = $file->storeAs($fileDir, uniqid().'.'.$file->getClientOriginalExtension()); - - $product['file_path'] = $uploadedFile; - } else { - session()->flash('error', trans('bulkupload::app.admin.bulk-upload.messages.file-format-error')); - - return redirect()->route('admin.bulk-upload.index'); - } - - $data = $this->importProductRepository->findOneByField('data_flow_profile_id', $data_flow_profile_id); - - if ($data) { - $this->dataFlowProfileRepository->update(['run_status' => '0'], $data_flow_profile_id); - - $this->importProductRepository->Update($product, $data->id); - - session()->flash('success',trans('bulkupload::app.admin.bulk-upload.messages.update-profile')); - - return redirect()->route('admin.bulk-upload.index'); - } else { - $importNewProductsStore = $this->importProductRepository->create($product); - - session()->flash('success',trans('bulkupload::app.admin.bulk-upload.messages.profile-saved')); - - return redirect()->route('admin.bulk-upload.index'); - } - } -} \ No newline at end of file diff --git a/src/Http/Controllers/Admin/BulkProductImporterController.php b/src/Http/Controllers/Admin/BulkProductImporterController.php new file mode 100644 index 0000000..bd0456f --- /dev/null +++ b/src/Http/Controllers/Admin/BulkProductImporterController.php @@ -0,0 +1,128 @@ +ajax()) { + return app(BulkProductImporterDataGrid::class)->toJson(); + } + + $families = $this->attributeFamilyRepository->all(); + + return view('bulkupload::admin.bulk-upload.bulk-product-importer.index', compact('families')); + } + + /** + * Store a newly created resource in storage. + * + * @return \Illuminate\Http\Response + */ + public function store() + { + request()->validate([ + 'name' => 'required|unique:bulk_product_importers', + 'attribute_family_id' => 'required', + 'locale_code' => 'required' + ]); + + $this->bulkProductImporterRepository->create(request()->all()); + + session()->flash('success',trans('bulkupload::app.admin.bulk-upload.messages.profile-saved')); + + return redirect()->route('admin.bulk-upload.bulk-product-importer.index'); + } + + /** + * Show the form for editing the specified resource. + * + * @param int $id + * @return \Illuminate\View\View + */ + public function edit($id) + { + $families = $this->attributeFamilyRepository->all(); + + $profiles = $this->bulkProductImporterRepository->findOrFail($id); + + return view('bulkupload::admin.bulk-upload.bulk-product-importer.edit', compact('families', 'profiles')); + } + + /** + * Update the specified resource in storage. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function update($id) + { + $this->validate(request(), [ + 'name' => ['required', 'unique:bulk_product_importers,name,' . $id, new \Webkul\Core\Contracts\Validations\Code], + 'attribute_family_id' => 'required' + ]); + + $this->bulkProductImporterRepository->update(request()->all(), $id); + + session()->flash('success', trans('bulkupload::app.admin.bulk-upload.messages.update-profile', ['name' => 'Product'])); + + return redirect()->route('admin.bulk-upload.bulk-product-importer.index'); + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function destroy($id) + { + $this->bulkProductImporterRepository->findOrFail($id)->delete(); + + session()->flash('success', trans('bulkupload::app.admin.bulk-upload.messages.profile-deleted')); + + return redirect()->route('admin.bulk-upload.bulk-product-importer.index'); + } + + /** + * Mass Delete the dataflowprofiles + * + * @return \Illuminate\Http\Response + */ + public function massDestroy() + { + $profileIds = explode(',', request()->input('indexes')); + + $this->bulkProductImporterRepository->whereIn('id', $profileIds)->delete(); + + session()->flash('success', trans('bulkupload::app.admin.bulk-upload.messages.all-profile-deleted')); + + return redirect()->route('admin.bulk-upload.bulk-product-importer.index'); + } +} diff --git a/src/Http/Controllers/Admin/BulkUploadController.php b/src/Http/Controllers/Admin/BulkUploadController.php deleted file mode 100644 index 62966a1..0000000 --- a/src/Http/Controllers/Admin/BulkUploadController.php +++ /dev/null @@ -1,188 +0,0 @@ -_config = request('_config'); - - $this->attributeFamilyRepository = $attributeFamilyRepository; - - $this->importProductRepository = $importProductRepository; - - $this->dataFlowProfileRepository = $dataFlowProfileRepository; - } - - /** - * Display a listing of the resource. - * - * @return \Illuminate\View\View - */ - public function index() - { - $profiles = null; - $families = $this->attributeFamilyRepository->all(); - $allProfiles = $this->importProductRepository->get()->toArray(); - - if (! empty($allProfiles)) { - foreach ($allProfiles as $allProfile) { - $profilers[] = $allProfile['data_flow_profile_id']; - } - - foreach ($profilers as $key => $profiler) { - $profiles[] = $this->dataFlowProfileRepository->findByfield(['id' => $profilers[$key], 'run_status' => '0']); - } - } - - return view($this->_config['view'], compact('families', 'profiles')); - } - - /** - * Store a newly created resource in storage. - * - * @return \Illuminate\Http\Response - */ - public function store() - { - request()->validate([ - 'name' => 'required|unique:bulkupload_data_flow_profiles', - 'attribute_family' => 'required', - 'locale_code' => 'required' - ]); - - $dataFlowProfileAdmin['name'] = request()->name; - $dataFlowProfileAdmin['attribute_family_id'] = request()->attribute_family; - $dataFlowProfileAdmin['locale_code'] = request()->locale_code; - - - $this->dataFlowProfileRepository->create($dataFlowProfileAdmin); - - session()->flash('success',trans('bulkupload::app.admin.bulk-upload.messages.profile-saved')); - - return redirect()->route('admin.dataflow-profile.index'); - } - - /** - * Show the form for editing the specified resource. - * - * @param int $id - * @return \Illuminate\View\View - */ - public function edit($id) - { - $families = $this->attributeFamilyRepository->all(); - $profiles = $this->dataFlowProfileRepository->findOrFail($id); - - return view($this->_config['view'], compact('families', 'profiles')); - } - - /** - * Update the specified resource in storage. - * - * @param int $id - * @return \Illuminate\Http\Response - */ - public function update($id) - { - $product = $this->dataFlowProfileRepository->update(request()->except('_token'), $id); - $families = $this->attributeFamilyRepository->all(); - $profiles = $this->dataFlowProfileRepository->findOrFail($id); - - session()->flash('success', trans('admin::app.response.update-success', ['name' => 'Product'])); - - return redirect()->route('admin.dataflow-profile.index'); - } - - /** - * Remove the specified resource from storage. - * - * @param int $id - * @return \Illuminate\Http\Response - */ - public function destroy($id) - { - $product = $this->dataFlowProfileRepository->findOrFail($id)->delete(); - - session()->flash('success',trans('bulkupload::app.admin.bulk-upload.messages.profile-deleted')); - - return response()->json(['message' => true], 200); - } - - /** - * Mass Delete the dataflowprofiles - * - * @return \Illuminate\Http\Response - */ - public function massDestroy() - { - $profileIds = explode(',', request()->input('indexes')); - - foreach ($profileIds as $profileId) { - $profile = $this->dataFlowProfileRepository->find($profileId); - - if (isset($profile)) { - $this->dataFlowProfileRepository->delete($profileId); - } - } - - session()->flash('success', trans('admin::app.catalog.products.mass-delete-success')); - - return redirect()->route($this->_config['redirect']); - } -} \ No newline at end of file diff --git a/src/Http/Controllers/Admin/Controller.php b/src/Http/Controllers/Admin/Controller.php index 5970243..0dce256 100644 --- a/src/Http/Controllers/Admin/Controller.php +++ b/src/Http/Controllers/Admin/Controller.php @@ -2,8 +2,8 @@ namespace Webkul\Bulkupload\Http\Controllers\Admin; -use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Routing\Controller as BaseController; +use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; diff --git a/src/Http/Controllers/Admin/HelperController.php b/src/Http/Controllers/Admin/HelperController.php deleted file mode 100644 index dd0406b..0000000 --- a/src/Http/Controllers/Admin/HelperController.php +++ /dev/null @@ -1,341 +0,0 @@ -importProductRepository = $importProductRepository; - - $this->dataFlowProfileRepository = $dataFlowProfileRepository; - - $this->simpleProductRepository = $simpleProductRepository; - - $this->configurableProductRepository = $configurableProductRepository; - - $this->virtualProductRepository = $virtualProductRepository; - - $this->downloadableProductRepository = $downloadableProductRepository; - - $this->bundledProductRepository = $bundledProductRepository; - - $this->bookingProductRepository = $bookingProductRepository; - - $this->groupedProductRepository = $groupedProductRepository; - - $this->importProduct = $importProduct; - } - - /** - * Download sample files. - * - * @return \Illuminate\Http\Response - */ - public function downloadFile() - { - $items = []; - - foreach (config('product_types') as $item) { - $item['children'] = []; - - array_push($items, $item); - } - - $types = core()->sortItems($items); - - foreach ($types as $key => $productType) { - if (request()->download_sample == $key.'-csv') { - return response()->download(public_path('storage/downloads/sample-files/bulk'.$key.'productupload.csv')); - } else if (request()->download_sample == $key.'-xls') { - return response()->download(public_path('storage/downloads/sample-files/bulk'.$key.'productupload.xlsx')); - } else if (empty(request()->download_sample)) { - return redirect()->back(); - } - } - } - - /** - * Get profiles on basis of attribute family - * - * @return array - */ - public function getAllDataFlowProfiles() - { - $attribute_family_id = request()->attribute_family_id; - - $dataFlowProfiles = $this->dataFlowProfileRepository->findByField('attribute_family_id', request()->attribute_family_id); - - return ['dataFlowProfiles' => $dataFlowProfiles]; - } - - /** - * Read count of records in CSV/XLSX - * - * @return \Illuminate\Http\Response - */ - public function readCSVData() - { - $countCSV = 0; - - $dataFlowProfileRecord = $this->importProductRepository->findOneByField('data_flow_profile_id', request()->data_flow_profile_id); - - $this->dataFlowProfileRepository->update(['run_status' => '1'], request()->data_flow_profile_id); - - if ($dataFlowProfileRecord) { - $csvData = (new DataGridImport)->toArray($dataFlowProfileRecord->file_path)[0]; - - for ($i = 0; $i < count($csvData); $i++) { - if ($csvData[$i]['type'] == 'configurable') { - $countCSV += 1; - } else if ($csvData[0]['type'] != 'configurable') { - $countCSV = count($csvData); - } - } - - return $countCSV; - } - } - - /** - * store import products for profile execution - * - * @return \Illuminate\Http\Response - */ - public function importNewProductsStore() - { - $dataFlowProfileId = request()->data_flow_profile; - - if ($dataFlowProfileId) { - $importedProducts = $this->importProduct->store(); - - return $importedProducts; - } else { - session()->flash('error', trans('bulkupload::app.admin.bulk-upload.messages.data-profile-not-selected')); - - return back(); - } - } - - /** - * profile execution to upload products - * - * @return \Illuminate\Http\Response - */ - public function runProfile() - { - $data_flow_profile_id = request()->data_flow_profile_id; - $numberOfCSVRecord = request()->numberOfCSVRecord; - $countOfStartedProfiles = request()->countOfStartedProfiles; - $product = []; - $imageZipName = null; - - $dataFlowProfileRecord = $this->importProductRepository->findOneByField - ('data_flow_profile_id', $data_flow_profile_id); - - if ($dataFlowProfileRecord) { - $csvData = (new DataGridImport)->toArray($dataFlowProfileRecord->file_path)[0]; - - if (isset($dataFlowProfileRecord->image_path) && ($dataFlowProfileRecord->image_path != "") ) { - $imageZipName = $this->storeImageZip($dataFlowProfileRecord); - } - - if ($numberOfCSVRecord >= 0) { - for ($i = $countOfStartedProfiles; $i < count($csvData); $i++) { - $product['loopCount'] = $i; - - switch($csvData[$i]['type']) { - case "simple": - $simpleProduct = $this->simpleProductRepository->createProduct(request()->all(), $imageZipName, $product); - - return response()->json($simpleProduct); - - case "virtual": - $virtualProduct = $this->virtualProductRepository->createProduct(request()->all(), $imageZipName); - - return response()->json($virtualProduct); - case "downloadable": - $downloadableProduct = $this->downloadableProductRepository->createProduct(request()->all(), $imageZipName); - - return response()->json($downloadableProduct); - case "grouped": - $groupedProduct = $this->groupedProductRepository->createProduct(request()->all(), $imageZipName); - - return response()->json($groupedProduct); - case "booking": - $bookingProduct = $this->bookingProductRepository->createProduct(request()->all(), $imageZipName); - - return response()->json($bookingProduct); - case "bundle": - $bundledProduct = $this->bundledProductRepository->createProduct(request()->all(), $imageZipName); - - return response()->json($bundledProduct); - case "configurable" OR "variant": - $configurableProduct = $this->configurableProductRepository->createProduct(request()->all(), $imageZipName, $product); - - return response()->json($configurableProduct); - } - } - } else { - return response()->json([ - "success" => true, - "message" => "CSV Product Successfully Imported" - ]); - } - } - } - - public function storeImageZip($dataFlowProfileRecord) - { - $imageZip = new \ZipArchive(); - - $extractedPath = storage_path('app/public/imported-products/extracted-images/admin/'.$dataFlowProfileRecord->id.'/'); - - if ($imageZip->open(storage_path('app/public/'.$dataFlowProfileRecord->image_path))) { - for ($i = 0; $i < $imageZip->numFiles; $i++) { - $filename = $imageZip->getNameIndex($i); - $imageZipName = pathinfo($filename); - } - - $imageZip->extractTo($extractedPath); - $imageZip->close(); - } - - $listOfImages = scandir($extractedPath.$imageZipName['dirname'].'/'); - - foreach ($listOfImages as $key => $imageName) { - if (preg_match_all('/[\'"]/', $imageName)) { - $fileName = preg_replace('/[\'"]/', '',$imageName); - - rename($extractedPath.$imageZipName['dirname'].'/'.$imageName, $extractedPath.$imageZipName['dirname'].'/'.$fileName); - } - } - - return $imageZipName; - } -} diff --git a/src/Http/Controllers/Admin/UploadFileController.php b/src/Http/Controllers/Admin/UploadFileController.php new file mode 100644 index 0000000..3531849 --- /dev/null +++ b/src/Http/Controllers/Admin/UploadFileController.php @@ -0,0 +1,452 @@ +attributeFamilyRepository->all(); + + return view('bulkupload::admin.bulk-upload.upload-files.index', compact('families')); + } + + /** + * Download sample files. + * + * @return \Illuminate\Http\Response + */ + public function downloadSampleFile() + { + if (! empty(request()->download_sample)) { + return response()->download(public_path("vendor/webkul/admin/assets/sample-files/".request()->download_sample)); + } + + session()->flash('error', 'Product type is not available, Please select valid product type'); + + return redirect()->route('admin.bulk-upload.upload-file.index'); + } + + /** + * Get profiles on basis of attribute family + * + * @return array + */ + public function getBulkProductImporter() + { + $dataFlowProfiles = $this->bulkProductImporterRepository->findByField('attribute_family_id', request()->attribute_family_id); + + return ['dataFlowProfiles' => $dataFlowProfiles]; + } + + /** + * store import products for profile execution + * + * @return \Illuminate\Http\Response + */ + public function storeProductsFile() + { + $request = request(); + $importerId = $request->bulk_product_importer_id; + + $validExtensions = ['csv', 'xls', 'xlsx']; + $validImageExtensions = ['zip', 'rar']; + + // Validate the request + $request->validate([ + 'file_path' => 'required', + 'image_path' => 'mimetypes:application/zip|max:10000', + 'attribute_family_id' => 'required', + 'bulk_product_importer_id' => 'required', + ]); + + $importer = $this->bulkProductImporterRepository->find($importerId); + + if (empty($importer)) { + session()->flash('error', trans('bulkupload::app.admin.bulk-upload.messages.data-profile-not-selected')); + + return back(); + } + + $product = [ + 'attribute_family_id' => $request->attribute_family_id, + 'bulk_product_importer_id' => $importerId, + 'is_downloadable' => $request->is_downloadable ? 1 : 0, + 'is_links_have_samples' => $request->is_link_have_sample ? 1 : 0, + 'is_samples_available' => $request->is_sample ? 1 : 0, + 'image_path' => '', + 'file_path' => '', + 'file_name' => $request->file('file_path')->getClientOriginalName() + ]; + + $fileStorePath = 'imported-products/admin'; + + // Handle link files + if ($request->hasFile('link_files')) { + $linkFiles = $request->file('link_files'); + + if (in_array($linkFiles->getClientOriginalExtension(), $validImageExtensions)) { + $product['upload_link_files'] = $linkFiles->storeAs($fileStorePath . '/link-files', uniqid() . '.' . $linkFiles->getClientOriginalExtension()); + } else { + session()->flash('error', trans('bulkupload::app.admin.bulk-upload.messages.file-format-error')); + + return back(); + } + } + + // Handle link sample files + if ($request->is_link_have_sample && $request->hasFile('link_sample_files')) { + $linkSampleFiles = $request->file('link_sample_files'); + + if (in_array($linkSampleFiles->getClientOriginalExtension(), $validImageExtensions)) { + $product['upload_link_sample_files'] = $linkSampleFiles->storeAs($fileStorePath . '/link-sample-files', uniqid() . '.' . $linkSampleFiles->getClientOriginalExtension()); + } else { + session()->flash('error', trans('bulkupload::app.admin.bulk-upload.messages.file-format-error')); + + return back(); + } + } + + // Handle sample files + if ($request->is_sample && $request->hasFile('sample_file')) { + $sampleFile = $request->file('sample_file'); + + if (in_array($sampleFile->getClientOriginalExtension(), $validImageExtensions)) { + $product['upload_sample_files'] = $sampleFile->storeAs($fileStorePath . '/sample-file', uniqid() . '.' . $sampleFile->getClientOriginalExtension()); + } else { + session()->flash('error', trans('bulkupload::app.admin.bulk-upload.messages.file-format-error')); + + return back(); + } + } + + // Handle image uploads + if ($request->hasFile('image_path')) { + $uploadedImage = request()->file('image_path'); + + if (in_array($uploadedImage->getClientOriginalExtension(), $validImageExtensions)) { + $product['image_path'] = $uploadedImage->storeAs($fileStorePath . '/images', uniqid() . '.' . $uploadedImage->getClientOriginalExtension()); + } else { + session()->flash('error', trans('bulkupload::app.admin.bulk-upload.messages.file-format-error')); + + return back(); + } + } + + // Handle file uploads + if ($request->hasFile('file_path')) { + $uploadedFile = request()->file('file_path'); + + if (in_array($uploadedFile->getClientOriginalExtension(), $validExtensions)) { + $product['file_path'] = $uploadedFile->storeAs($fileStorePath . '/files', uniqid() . '.' . $uploadedFile->getClientOriginalExtension()); + } else { + session()->flash('error', trans('bulkupload::app.admin.bulk-upload.messages.file-format-error')); + + return back(); + } + } + + $this->importProductRepository->create($product); + + session()->flash('success', trans('bulkupload::app.admin.bulk-upload.messages.profile-saved')); + + return back(); + } + + public function getFamilyAttributesToUploadFile() + { + $uniqueAttributeFamilyIds = $this->importProductRepository->distinct()->pluck('attribute_family_id'); + + $families = $this->attributeFamilyRepository->whereIn('id', $uniqueAttributeFamilyIds)->get(); + + return view('bulkupload::admin.bulk-upload.run-profile.index', compact('families')); + } + + /** + * Get profiles on basis of attribute family + * + * @return array + */ + public function getProductImporter() + { + $dataFlowProfiles = $this->bulkProductImporterRepository->findByField('attribute_family_id', request()->attribute_family_id); + + $productImporter = $dataFlowProfiles->filter(function ($dataFlowProfile) { + + return $dataFlowProfile->import_product->isNotEmpty(); + }); + + return ['dataFlowProfiles' => $productImporter]; + } + + public function deleteProductFile() + { + try { + $dataFlowProfile = $this->bulkProductImporterRepository->findOrFail(request()->bulk_product_importer_id); + + $dataFlowProfile->import_product()->where('id', request()->product_file_id)->delete(); + + return ['importer_product_file' => $dataFlowProfile->import_product]; + } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) { + // Handle the case where the bulk_product_importer_id does not exist + return response()->json(['error' => 'Data Flow Profile not found'], 404); + } + } + + public function readCSVData() + { + $productFileRecord = $this->importProductRepository->where([ + 'bulk_product_importer_id' => request()->bulk_product_importer_id, + 'id' => request()->product_file_id, + ])->first(); + + if (! $productFileRecord) { + return response()->json([ + 'error' => true, + 'message' => 'Selected File not found.' + ]); + } + + $csvData = (new DataGridImport)->toArray($productFileRecord->file_path)[0]; + + // $productFileRecord->update(['status' => 0]); + + $countConfig = count(array_filter($csvData, function ($item) { + return $item['type'] === 'configurable'; + })); + + $countCSV = ($countConfig > 0) ? $countConfig : count($csvData); + + if (! $countCSV) { + // Handle the case when $countCSV is false (or any condition you need). + return response()->json([ + "success" => false, + "message" => "No CSV Data to Import" + ]); + } + + $imageZipName = null; + + if (isset($productFileRecord->image_path) && !empty($productFileRecord->image_path)) { + $imageZipName = $this->storeImageZip($productFileRecord); + } + + $chunks = array_chunk($csvData, 100); + + $batch = Bus::batch([])->dispatch(); + + $batch->add(new ProductUploadJob($imageZipName, $productFileRecord, $chunks, $countCSV)); + + // $productFileRecord->delete(); + + return response()->json([ + "success" => true, + "message" => "CSV Product Successfully Imported" + ]); + } + + /** + * Store and extract images from a zip file, removing any single quotes or double quotes in image filenames. + * + * @param $dataFlowProfileRecord - The data flow profile record containing image information. + * @return array - An array containing information about the extracted images. + */ + public function storeImageZip($dataFlowProfileRecord) + { + // Create a ZipArchive instance to work with the zip file. + $imageZip = new \ZipArchive(); + + // Define the path where extracted images will be stored. + $extractedPath = storage_path('app/public/imported-products/extracted-images/admin/'.$dataFlowProfileRecord->id.'/'); + + // Check if the zip file can be opened successfully. + if ($imageZip->open(storage_path('app/public/'.$dataFlowProfileRecord->image_path))) { + $imageZipName = null; // Initialize the variable to store image zip information. + + // Loop through each file in the zip archive. + for ($i = 0; $i < $imageZip->numFiles; $i++) { + $filename = $imageZip->getNameIndex($i); + + // Extract information about the file, including its dirname. + $imageZipName = pathinfo($filename); + + // Ensure the extracted path exists. + if (!is_dir($extractedPath.$imageZipName['dirname'])) { + mkdir($extractedPath.$imageZipName['dirname'], 0777, true); + } + } + + // Extract all files from the zip archive to the specified path. + $imageZip->extractTo($extractedPath); + $imageZip->close(); + } + + // List all files in the extracted directory. + $listOfImages = scandir($extractedPath.$imageZipName['dirname'].'/'); + + // Iterate through the list of images to remove quotes from filenames. + foreach ($listOfImages as $key => $imageName) { + if (preg_match_all('/[\'"]/', $imageName)) { + $fileName = preg_replace('/[\'"]/', '', $imageName); + + // Rename the file to remove quotes from its name. + rename($extractedPath.$imageZipName['dirname'].'/'.$imageName, $extractedPath.$imageZipName['dirname'].'/'.$fileName); + } + } + + // Return information about the extracted images. + return $imageZipName; + } + + public function downloadCsv() + { + + $folderPath = public_path('storage/error-csv-file'); + + // Check if the folder exists + if (!File::exists($folderPath)) { + // If it doesn't exist, create it + File::makeDirectory($folderPath, 0755, true, true); + } + + $uploadedFilesError = File::allFiles($folderPath); + + $resultArray = collect($uploadedFilesError) + ->map(function ($file) { + return [ + $file->getRelativePath() => [ + 'link' => asset('storage/error-csv-file/' . $file->getRelativePathname()), + 'time' => date('Y-m-d H:i:s', filectime($file)), + 'fileName' => $file->getFilename(), + ], + ]; + }) + ->groupBy(function ($item) { + return key($item); + }) + ->map(function ($group) { + return $group->map(function ($item) { + return $item[key($item)]; + }); + }) + ->toArray(); + + $ids = array_keys($resultArray); + + $profilerName = $this->bulkProductImporterRepository + ->get() + ->whereIn('id', $ids) + ->pluck('name') + ->all(); + + return response()->json([ + 'resultArray' => $resultArray, + 'profilerNames' => array_combine($ids, $profilerName), + ]); + } + + public function getProfiler() + { + return $this->bulkProductImporterRepository->find(request()->input('id'))->name; + } + + public function deleteCSV() + { + + $fileToDelete = 'error-csv-file/' . request('id') . '/' . request('name'); + + if (Storage::delete($fileToDelete)) { + return response()->json(['message' => 'File deleted successfully']); + } + + return response()->json(['message' => 'File not found'], 404); + } + + public function readErrorFile() + { + // Read the CSV file and generate HTML to display product data + $csvFilePath = public_path('storage/error-csv-file/' . request()->bulk_product_importer_id . '/' . request()->product_file_id . '/error-file.csv'); + + $csvData = []; + + if (($handle = fopen($csvFilePath, 'r')) !== false) { + while (($data = fgetcsv($handle)) !== false) { + $csvData[] = $data; + } + fclose($handle); + } + + return $csvData; + } + + + // Get Uploaded and not uploaded product detail + public function getUploadedProductOrNotUploadedProduct() + { + $data = []; + $isFileUploadComplete = false; + $status = request()->status; + $message = false; + + if (session()->has('notUploadedProduct')) { + $data['notUploadedProduct'] = session()->get('notUploadedProduct'); + } + + if (session()->has('uploadedProduct')) { + $data['uploadedProduct'] = session()->get('uploadedProduct'); + } + + + if (session()->has('isFileUploadComplete')) { + $isFileUploadComplete = session()->get('isFileUploadComplete'); + $status = false; + } + + if (session()->has('message')) { + $message = session()->get('message'); + $status = false; + } + + if (empty($data)) { + $status = false; + } + + return response()->json(['message' => $data ,'status' => $status,'success'=>$message, 'isFileUploadComplete' => $isFileUploadComplete], 200); + } +} diff --git a/src/Http/Controllers/Shop/BulkuploadController.php b/src/Http/Controllers/Shop/BulkuploadController.php new file mode 100644 index 0000000..2e26c58 --- /dev/null +++ b/src/Http/Controllers/Shop/BulkuploadController.php @@ -0,0 +1,39 @@ +_config = request('_config'); + } + + /** + * Display a listing of the resource. + * + * @return \Illuminate\View\View + */ + public function index() + { + return view($this->_config['view']); + } +} diff --git a/src/Http/admin-routes.php b/src/Http/admin-routes.php deleted file mode 100644 index 7f97b0a..0000000 --- a/src/Http/admin-routes.php +++ /dev/null @@ -1,65 +0,0 @@ - ['web']], function () { - - Route::prefix(config('app.admin_url'))->group(function () { - - Route::group(['middleware' => ['admin']], function () { - Route::prefix('bulkupload')->group(function () { - - // Bulk Upload Products - Route::get('/upload-files', 'Webkul\Bulkupload\Http\Controllers\Admin\BulkUploadController@index')->defaults('_config', [ - 'view' => 'bulkupload::admin.bulk-upload.upload-files.index' - ])->name('admin.bulk-upload.index'); - - Route::get('/run-profile', 'Webkul\Bulkupload\Http\Controllers\Admin\BulkUploadController@index')->defaults('_config', [ - 'view' => 'bulkupload::admin.bulk-upload.run-profile.index' - ])->name('admin.run-profile.index'); - - Route::post('/read-csv', 'Webkul\Bulkupload\Http\Controllers\Admin\HelperController@readCSVData') - ->name('bulk-upload-admin.read-csv'); - - Route::post('/getprofiles', 'Webkul\Bulkupload\Http\Controllers\Admin\HelperController@getAllDataFlowProfiles') - ->name('bulk-upload-admin.get-all-profile'); - - // Download Sample Files - Route::post('/download','Webkul\Bulkupload\Http\Controllers\Admin\HelperController@downloadFile')->defaults('_config',[ - 'view' => 'bulkupload::admin.bulk-upload.upload-files.index' - ])->name('download-sample-files'); - - // import new products - Route::post('/importnew', 'Webkul\Bulkupload\Http\Controllers\Admin\HelperController@importNewProductsStore')->defaults('_config',['view' => 'bulkupload::admin.bulk-upload.upload-files.index' ])->name('import-new-products-form-submit'); - - Route::prefix('dataflowprofile')->group(function () { - Route::get('/', 'Webkul\Bulkupload\Http\Controllers\Admin\BulkUploadController@index')->defaults('_config', [ - 'view' => 'bulkupload::admin.bulk-upload.data-flow-profile.index' - ])->name('admin.dataflow-profile.index'); - - Route::post('/addprofile', 'Webkul\Bulkupload\Http\Controllers\Admin\BulkUploadController@store')->defaults('_config', [ - 'view' => 'bulkupload::admin.bulk-upload.data-flow-profile.index' - ])->name('bulkupload.bulk-upload.dataflow.add-profile'); - - Route::post('/runprofile', 'Webkul\Bulkupload\Http\Controllers\Admin\HelperController@runProfile')->defaults('_config', [ - 'view' => 'bulkupload::admin.bulk-upload.run-profile.progressbar' - ])->name('bulk-upload-admin.run-profile'); - - // edit actions - Route::post('/delete/{id}','Webkul\Bulkupload\Http\Controllers\Admin\BulkUploadController@destroy')->name('bulkupload.admin.profile.delete'); - - Route::get('/edit/{id}', 'Webkul\Bulkupload\Http\Controllers\Admin\BulkUploadController@edit')->defaults('_config', [ - 'view' => 'bulkupload::admin.bulk-upload.data-flow-profile.edit' - ])->name('bulkupload.admin.profile.edit'); - - Route::post('/update/{id}', 'Webkul\Bulkupload\Http\Controllers\Admin\BulkUploadController@update')->defaults('_config', [ - 'view' => 'bulkupload::admin.bulk-upload.data-flow-profile.index' - ])->name('admin.bulk-upload.dataflow.update-profile'); - - //mass destroy - Route::post('/massdestroy', 'Webkul\Bulkupload\Http\Controllers\Admin\BulkUploadController@massDestroy')->defaults('_config', [ - 'redirect' => 'admin.dataflow-profile.index' - ])->name('bulkupload.admin.profile.massDelete'); - }); - }); - }); - }); -}); diff --git a/src/Jobs/ProductUploadJob.php b/src/Jobs/ProductUploadJob.php new file mode 100644 index 0000000..6b803db --- /dev/null +++ b/src/Jobs/ProductUploadJob.php @@ -0,0 +1,75 @@ +forget('notUploadedProduct'); + session()->forget('uploadedProduct'); + session()->forget('isFileUploadComplete'); + session()->forget('message'); + + $simpleProductRepository = app('Webkul\Bulkupload\Repositories\Products\SimpleProductRepository'); + $errorArray = []; + $records = []; + $uploadedProduct = []; + $isError = false; + $count = 0; + + foreach($this->chunk as $data) { + foreach($data as $key => $arr) { + $count++; + + $uploadedProduct = $simpleProductRepository->createProduct($this->imageZipName, $this->dataFlowProfileRecord, $arr, $key); + + if (! empty($uploadedProduct)) { + $isError = true; + $errorArray['error'] = json_encode($uploadedProduct['error']); + $records[$key] = (object) array_merge($errorArray, $arr); + // store validation for products which is not uploads. + session()->push('notUploadedProduct', $errorArray); + } + } + } + // After Uploded Product store success message in session + if ($this->countCSV == $count) { + session()->put('message', "CSV Product Successfully Imported"); + session()->put('isFileUploadComplete', true); + } + + if ($isError) { + + Excel::store(new DataGridExport(collect($records)), 'error-csv-file/'.$this->dataFlowProfileRecord->profiler->id.'/'.Str::random(10).'.csv'); + } + + } +} diff --git a/src/Models/BulkProductImporter.php b/src/Models/BulkProductImporter.php new file mode 100644 index 0000000..5fd23e4 --- /dev/null +++ b/src/Models/BulkProductImporter.php @@ -0,0 +1,33 @@ +belongsTo(AttributeFamilyProxy::modelClass()); + } + + /** + * Get the product files. + */ + public function import_product(): HasMany + { + return $this->hasMany(ImportProductProxy::modelClass()); + } +} diff --git a/src/Models/DataFlowProfileProxy.php b/src/Models/BulkProductImporterProxy.php similarity index 62% rename from src/Models/DataFlowProfileProxy.php rename to src/Models/BulkProductImporterProxy.php index cc7f914..5e0fff5 100644 --- a/src/Models/DataFlowProfileProxy.php +++ b/src/Models/BulkProductImporterProxy.php @@ -4,6 +4,6 @@ use Konekt\Concord\Proxies\ModelProxy; -class DataFlowProfileProxy extends ModelProxy +class BulkProductImporterProxy extends ModelProxy { -} \ No newline at end of file +} diff --git a/src/Models/DataFlowProfile.php b/src/Models/DataFlowProfile.php deleted file mode 100644 index f452d63..0000000 --- a/src/Models/DataFlowProfile.php +++ /dev/null @@ -1,20 +0,0 @@ -hasOne(AttributeFamily::class, 'id', 'attribute_family_id'); - } -} diff --git a/src/Models/ImportProduct.php b/src/Models/ImportProduct.php index 387a540..c615b42 100644 --- a/src/Models/ImportProduct.php +++ b/src/Models/ImportProduct.php @@ -10,4 +10,9 @@ class ImportProduct extends Model implements ImportProductContract protected $table = "import_products"; protected $guarded = []; + + public function profiler() + { + return $this->belongsTo(BulkProductImporter::class, 'bulk_product_importer_id', 'id'); + } } diff --git a/src/Providers/BulkUploadServiceProvider.php b/src/Providers/BulkUploadServiceProvider.php index 64d5a18..305ca6f 100644 --- a/src/Providers/BulkUploadServiceProvider.php +++ b/src/Providers/BulkUploadServiceProvider.php @@ -6,40 +6,28 @@ class BulkUploadServiceProvider extends ServiceProvider { + /** + * Bootstrap services. + * + * @return void + */ public function boot() { - include __DIR__ . '/../Http/admin-routes.php'; - - $this->app->register(ModuleServiceProvider::class); - $this->app->register(EventServiceProvider::class); - $this->loadMigrationsFrom(__DIR__ . '/../Database/Migrations'); - $this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'bulkupload'); + $this->loadRoutesFrom(__DIR__ . '/../Routes/admin-routes.php'); - $this->loadViewsFrom(__DIR__ . '/../Resources/views', 'bulkupload'); + $this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'bulkupload'); $this->publishes([ - __DIR__ . '/../../publishable/assets' => public_path('themes/default/assets'), + __DIR__ . '/../../publishable/assets' => public_path('vendor/webkul/admin/assets'), ], 'public'); - $this->publishes([ - __DIR__ . '/../Resources/views/admin/bulk-upload/layouts/nav-aside.blade.php' => resource_path('views/vendor/admin/layouts/nav-left.blade.php'), - ]); - - view()->composer(['bulkupload::admin.bulk-upload.upload-files.index'], function ($view) { - $items = []; - - foreach (config('product_types') as $item) { - $item['children'] = []; - - array_push($items, $item); - } + $this->loadViewsFrom(__DIR__ . '/../Resources/views', 'bulkupload'); - $types = core()->sortItems($items); + $this->app->register(ModuleServiceProvider::class); - $view->with('productTypes', $types); - }); + $this->app->register(EventServiceProvider::class); } /** diff --git a/src/Providers/ModuleServiceProvider.php b/src/Providers/ModuleServiceProvider.php index b92eac1..62e8e63 100644 --- a/src/Providers/ModuleServiceProvider.php +++ b/src/Providers/ModuleServiceProvider.php @@ -7,7 +7,7 @@ class ModuleServiceProvider extends BaseModuleServiceProvider { protected $models = [ + \Webkul\Bulkupload\Models\BulkProductImporter::class, \Webkul\Bulkupload\Models\ImportProduct::class, - \Webkul\Bulkupload\Models\DataFlowProfile::class, ]; -} \ No newline at end of file +} diff --git a/src/Repositories/DataFlowProfileRepository.php b/src/Repositories/BulkProductImporterRepository.php similarity index 57% rename from src/Repositories/DataFlowProfileRepository.php rename to src/Repositories/BulkProductImporterRepository.php index 81f9916..6996751 100644 --- a/src/Repositories/DataFlowProfileRepository.php +++ b/src/Repositories/BulkProductImporterRepository.php @@ -5,10 +5,10 @@ use Webkul\Core\Eloquent\Repository; /** - * DataFlowProfile Repository + * BulkProductImporter Repository * */ -class DataFlowProfileRepository extends Repository +class BulkProductImporterRepository extends Repository { /** * Specify Model class name @@ -17,6 +17,6 @@ class DataFlowProfileRepository extends Repository */ function model() { - return 'Webkul\Bulkupload\Contracts\DataFlowProfile'; + return 'Webkul\Bulkupload\Contracts\BulkProductImporter'; } -} \ No newline at end of file +} diff --git a/src/Repositories/BulkProductRepository.php b/src/Repositories/BulkProductRepository.php deleted file mode 100644 index f8d9d18..0000000 --- a/src/Repositories/BulkProductRepository.php +++ /dev/null @@ -1,213 +0,0 @@ -productAttributeValueRepository = $productAttributeValueRepository; - - $this->productRepository = $productRepository; - - $this->productInventoryRepository = $productInventoryRepository; - - $this->productImageRepository = $productImageRepository; - - parent::__construct($app); - } - - /** - * Specify Model class name - * - * @return mixed - */ - function model() - { - return 'Webkul\Product\Contracts\Product'; - } - - /** - * update configurable product variants - * - * @param array $data - * @param integer $id - * @param string $attribute - * - * @return mixed - */ - public function productRepositoryUpdateForVariants(array $data, $id, $attribute = "id") - { - Event::dispatch('catalog.product.update.before', $id); - - $product = $this->find($id); - - $configurable = app('Webkul\Product\Type\Configurable'); - - if ($product->parent_id && $configurable->checkVariantOptionAvailabiliy($data, $product)) { - $data['parent_id'] = NULL; - } - - $product->update($data); - - $attributes = $product->attribute_family->custom_attributes; - - foreach ($attributes as $attribute) { - if (! isset($data[$attribute->code]) || (in_array($attribute->type, ['date', 'datetime']) && ! $data[$attribute->code])) - continue; - - if ($attribute->type == 'multiselect' || $attribute->type == 'checkbox') { - $data[$attribute->code] = implode(",", $data[$attribute->code]); - } - - if ($attribute->type == 'image' || $attribute->type == 'file') { - $dir = 'product'; - if (gettype($data[$attribute->code]) == 'object') { - $data[$attribute->code] = request()->file($attribute->code)->store($dir); - } else { - $data[$attribute->code] = NULL; - } - } - - $attributeValue = $this->productAttributeValueRepository->findOneWhere([ - 'product_id' => $product->id, - 'attribute_id' => $attribute->id, - 'channel' => $attribute->value_per_channel ? $data['channel'] : null, - 'locale' => $attribute->value_per_locale ? $data['locale'] : null - ]); - - if (! $attributeValue) { - $this->productAttributeValueRepository->create([ - 'product_id' => $product->id, - 'attribute_id' => $attribute->id, - 'value' => $data[$attribute->code], - 'channel' => $attribute->value_per_channel ? $data['channel'] : null, - 'locale' => $attribute->value_per_locale ? $data['locale'] : null - ]); - } else { - $this->productAttributeValueRepository->update([ - ProductAttributeValue::$attributeTypeFields[$attribute->type] => $data[$attribute->code] - ], $attributeValue->id - ); - - if ($attribute->type == 'image' || $attribute->type == 'file') { - Storage::delete($attributeValue->text_value); - } - } - } - - if (request()->route()->getName() != 'admin.catalog.products.massupdate') { - if (isset($data['categories'])) { - $product->categories()->sync($data['categories']); - } - - if (isset($data['up_sell'])) { - $product->up_sells()->sync($data['up_sell']); - } else { - $data['up_sell'] = []; - $product->up_sells()->sync($data['up_sell']); - } - - if (isset($data['cross_sell'])) { - $product->cross_sells()->sync($data['cross_sell']); - } else { - $data['cross_sell'] = []; - $product->cross_sells()->sync($data['cross_sell']); - } - - if (isset($data['related_products'])) { - $product->related_products()->sync($data['related_products']); - } else { - $data['related_products'] = []; - $product->related_products()->sync($data['related_products']); - } - - $previousVariantIds = $product->variants->pluck('id'); - if (isset($data['variants'])) { - foreach ($data['variants'] as $variantId => $variantData) { - if (str_contains($variantId, 'variant_')) { - $permutation = []; - foreach ($product->super_attributes as $superAttribute) { - $permutation[$superAttribute->id] = $variantData[$superAttribute->code]; - } - - $this->productRepository>createVariant($product, $permutation, $variantData); - } else { - if (is_numeric($index = $previousVariantIds->search($variantId))) { - $previousVariantIds->forget($index); - } - - $variantData['channel'] = $data['channel']; - $variantData['locale'] = $data['locale']; - - $this->productRepository->updateVariant($variantData, $variantId); - } - } - } - - $this->productInventoryRepository->saveInventories($data, $product); - - $this->productImageRepository->uploadImages($data, $product); - } - - if (isset($data['channels'])) { - $product['channels'] = $data['channels']; - } - - Event::dispatch('catalog.product.update.after', $product); - - return $product; - } -} \ No newline at end of file diff --git a/src/Repositories/ImportProductRepository.php b/src/Repositories/ImportProductRepository.php index 63041aa..95fb1d9 100644 --- a/src/Repositories/ImportProductRepository.php +++ b/src/Repositories/ImportProductRepository.php @@ -19,4 +19,4 @@ function model() { return 'Webkul\Bulkupload\Contracts\ImportProduct'; } -} \ No newline at end of file +} diff --git a/src/Repositories/ProductImageRepository.php b/src/Repositories/ProductImageRepository.php index 3614913..048be78 100644 --- a/src/Repositories/ProductImageRepository.php +++ b/src/Repositories/ProductImageRepository.php @@ -53,8 +53,8 @@ public function uploadImages($data, $product) } $this->update([ - 'path' => request()->file($file)->store($dir) - ], $imageId); + 'path' => request()->file($file)->store($dir) + ], $imageId); } } } @@ -76,25 +76,26 @@ public function uploadImages($data, $product) * * @return mixed */ - public function bulkuploadImages($data, $product, $imageZipName) + public function bulkuploadImages($data, $product, $imageZipName, $importerId) { if (isset($data['images'])) { - foreach($data['images'] as $key => $value) { - if ( ! is_null($imageZipName)) { - $files = "imported-products/extracted-images/admin/".$data['dataFlowProfileRecordId'].'/'. $imageZipName['dirname'].'/'.basename($value); - } else { - $files = "imported-products/extracted-images/admin/".$data['dataFlowProfileRecordId'].'/'.basename($value); - } + foreach($data['images'] as $value) { + + $importPath = "imported-products/extracted-images/admin/{$importerId}"; + + $sourcePath = isset($imageZipName) ? "{$importPath}/{$imageZipName['dirname']}/" : "{$importPath}/"; + + $files = $sourcePath . basename($value); - $destination = "product/".$product->id.'/'.basename($value); + $destination = "product/{$product->id}/" . basename($value); Storage::copy($files, $destination); $this->create([ - 'path' => 'product/' . $product->id .'/'. basename($value), + 'path' => $destination, 'product_id' => $product->id ]); } } } -} \ No newline at end of file +} diff --git a/src/Repositories/Products/BookingProductRepository.php b/src/Repositories/Products/BookingProductRepository.php deleted file mode 100644 index 85dfee3..0000000 --- a/src/Repositories/Products/BookingProductRepository.php +++ /dev/null @@ -1,1009 +0,0 @@ -importProductRepository = $importProductRepository; - - $this->categoryRepository = $categoryRepository; - - $this->productFlatRepository = $productFlatRepository; - - $this->productRepository = $productRepository; - - $this->productImageRepository = $productImageRepository; - - $this->attributeOptionRepository = $attributeOptionRepository; - - $this->attributeFamilyRepository = $attributeFamilyRepository; - - $this->helperRepository = $helperRepository; - } - - /* - * Specify Model class name - * - * @return mixed - */ - function model() - { - return 'Webkul\Product\Contracts\Product'; - } - - /** - * create & update booking-type product - * - * @param array $requestData - * @param array $imageZipName - * - * @return mixed - */ - public function createProduct($requestData, $imageZipName) - { - try { - $dataFlowProfileRecord = $this->importProductRepository->findOneByField - ('data_flow_profile_id', $requestData['data_flow_profile_id']); - - $csvData = (new DataGridImport)->toArray($dataFlowProfileRecord->file_path)[0]; - - if ($requestData['totalNumberOfCSVRecord'] < 1000) { - $processCSVRecords = $requestData['totalNumberOfCSVRecord']/($requestData['totalNumberOfCSVRecord']/10); - } else { - $processCSVRecords = $requestData['totalNumberOfCSVRecord']/($requestData['totalNumberOfCSVRecord']/100); - } - - $uptoProcessCSVRecords = (int)$requestData['countOfStartedProfiles'] + 10; - $processRecords = (int)$requestData['countOfStartedProfiles'] + (int)$requestData['numberOfCSVRecord']; - - $slot = []; - - if ($requestData['numberOfCSVRecord'] > $processCSVRecords) { - for ($i = $requestData['countOfStartedProfiles']; $i < $uptoProcessCSVRecords; $i++) { - $invalidateProducts = $this->store($csvData[$i], $i, $dataFlowProfileRecord, $requestData, $imageZipName); - - if (isset($invalidateProducts) && !empty($invalidateProducts)) { - return $invalidateProducts; - } - } - } else if ($requestData['numberOfCSVRecord'] <= 10) { - for ($i = $requestData['countOfStartedProfiles']; $i < $processRecords; $i++) { - $invalidateProducts = $this->store($csvData[$i], $i, $dataFlowProfileRecord, $requestData, $imageZipName); - - if (isset($invalidateProducts) && !empty($invalidateProducts)) { - return $invalidateProducts; - } - } - } - - if ($requestData['numberOfCSVRecord'] > 10) { - $remainDataInCSV = (int)$requestData['numberOfCSVRecord'] - (int)$processCSVRecords; - } else { - $remainDataInCSV = 0; - - if($requestData['errorCount'] > 0) { - $uptoProcessCSVRecords = $requestData['totalNumberOfCSVRecord'] - $requestData['errorCount']; - } else { - $uptoProcessCSVRecords = $processRecords; - } - } - - $requestData['countOfStartedProfiles'] = $i; - - $dataToBeReturn = [ - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $uptoProcessCSVRecords, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - ]; - - return $dataToBeReturn; - } catch(\Exception $e) { - \Log::error('booking create product log: '. $e->getMessage()); - - $categoryError = explode('[' ,$e->getMessage()); - $categorySlugError = explode(']' ,$e->getMessage()); - $requestData['countOfStartedProfiles'] = $i + 1; - $productsUploaded = $i - $requestData['errorCount']; - - if ($requestData['numberOfCSVRecord'] != 0) { - $remainDataInCSV = (int)$requestData['totalNumberOfCSVRecord'] - (int)$requestData['countOfStartedProfiles']; - } else { - $remainDataInCSV = 0; - } - - if ($categoryError[0] == "No query results for model ") { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => "Invalid Category Slug: " . $categorySlugError[1], - ); - $categoryError[0] = null; - } else if (isset($e->errorInfo)) { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $e->errorInfo[2], - ); - } else { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $e->getMessage(), - ); - } - - return $dataToBeReturn; - } - } - - /** - * function to store product - * - * @param array $csvData - * @param integer $i - * @param \Webkul\Bulkupload\Contracts\ImportProduct $dataFlowProfileRecord - * @param array $requestData - * @param array $imageZipName - * - * @return mixed - */ - public function store($csvData, $i, $dataFlowProfileRecord, $requestData, $imageZipName) - { - try { - $createValidation = $this->helperRepository->createProductValidation($csvData, $i); - - if (isset($createValidation)) { - return $createValidation; - } - - request()->request->add(['i' => $i]); - - $productFlatData = $this->productFlatRepository->findWhere(['sku' => $csvData['sku'], 'url_key' => $csvData['url_key']])->first(); - - $productData = $this->productRepository->findWhere(['sku' => $csvData['sku']])->first(); - - $attributeFamilyData = $this->attributeFamilyRepository->findOneByfield(['name' => $csvData['attribute_family_name']]); - - if (! isset($productFlatData) && empty($productFlatData)) { - $data['type'] = $csvData['type']; - $data['attribute_family_id'] = $attributeFamilyData->id; - $data['sku'] = $csvData['sku']; - Event::dispatch('catalog.product.create.before'); - $bookingProductData = $this->productRepository->create($data); - Event::dispatch('catalog.product.create.after', $bookingProductData); - - } else { - $bookingProductData = $productData; - } - - unset($data); - $data = []; - $attributeCode = []; - $attributeValue = []; - - //default attributes - foreach ($bookingProductData->getTypeInstance()->getEditableAttributes()->toArray() as $key => $value) { - $searchIndex = $value['code']; - if (array_key_exists($searchIndex, $csvData)) { - if (is_null($csvData[$searchIndex])) { - continue; - } - - array_push($attributeCode, $searchIndex); - - if ($searchIndex == "color" || $searchIndex == "size" || $searchIndex == "brand") { - $attributeOption = $this->attributeOptionRepository->findOneByField(['admin_name' => ucwords($csvData[$searchIndex])]); - - array_push($attributeValue, $attributeOption['id']); - } else { - array_push($attributeValue, $csvData[$searchIndex]); - } - - $data = array_combine($attributeCode, $attributeValue); - } - } - - $data['dataFlowProfileRecordId'] = $dataFlowProfileRecord->id; - - $categoryData = explode(',', $csvData['categories_slug']); - - - if (is_null($csvData['categories_slug']) || empty($csvData['categories_slug'])) { - $categoryID = $this->categoryRepository->findBySlugOrFail('root')->id; - } else { - foreach ($categoryData as $key => $value) { - $categoryID[$key] = $this->categoryRepository->findBySlugOrFail($categoryData[$key])->id; - } - } - - $data['categories'] = $categoryID; - - $data['channel'] = core()->getCurrentChannel()->code; - - $dataProfile = app('Webkul\Bulkupload\Repositories\DataFlowProfileRepository')->findOneByfield(['id' => $data['dataFlowProfileRecordId']]); - $data['locale'] = $dataProfile->locale_code; - - //customerGroupPricing - if (isset($csvData['customer_group_prices']) && ! empty($csvData['customer_group_prices'])) { - $data['customer_group_prices'] = json_decode($csvData['customer_group_prices'], true); - app(ProductCustomerGroupPriceRepository::class)->saveCustomerGroupPrices($data, $simpleproductData); - } - - //booking product attributes - - if (strtolower($csvData['booking_type']) == "default") { - $booking = $this->defaultBookingType($csvData); - } else if (strtolower($csvData['booking_type']) == "appointment") { - $booking = $this->appointmentBookingType($csvData); - } else if (strtolower($csvData['booking_type']) == "event") { - $booking = $this->eventBookingType($csvData); - } else if (strtolower($csvData['booking_type']) == "rental") { - $booking = $this->rentalBookingType($csvData); - } else if (strtolower($csvData['booking_type']) == "table") { - $booking = $this->tableBookingType($csvData); - } else { - \Log::error('booking type not found'); - } - - $data['booking'] = $booking; - - //images - $individualProductimages = explode(',', $csvData['images']); - - if (isset($imageZipName)) { - $images = Storage::disk('local')->files('public/imported-products/extracted-images/admin/'.$dataFlowProfileRecord->id.'/'.$imageZipName['dirname'].'/'); - - foreach ($images as $imageArraykey => $imagePath) { - $imageName = explode('/', $imagePath); - - if (in_array(last($imageName), preg_replace('/[\'"]/', '',$individualProductimages))) { - $data['images'][$imageArraykey] = $imagePath; - } - } - } else if (isset($csvData['images'])) { - foreach ($individualProductimages as $imageArraykey => $imageURL) - { - if (filter_var(trim($imageURL), FILTER_VALIDATE_URL)) { - $imagePath = storage_path('app/public/imported-products/extracted-images/admin/'.$dataFlowProfileRecord->id); - - if (!file_exists($imagePath)) { - mkdir($imagePath, 0777, true); - } - - $imageFile = $imagePath.'/'.basename($imageURL); - - file_put_contents($imageFile, file_get_contents(trim($imageURL))); - - $data['images'][$imageArraykey] = $imageFile; - } - } - } - - // to check validation - $validationRules = $this->helperRepository->validateCSV($requestData['data_flow_profile_id'], $data, $dataFlowProfileRecord, $bookingProductData); - - $csvValidator = Validator::make($data, $validationRules); - - if ($csvValidator->fails()) { - $errors = $csvValidator->errors()->getMessages(); - - $this->helperRepository->deleteProductIfNotValidated($bookingProductData->id); - - foreach($errors as $key => $error) { - if ($error[0] == "The url key has already been taken.") { - $errorToBeReturn[] = "The url key " . $data['url_key'] . " has already been taken"; - } else { - $errorToBeReturn[] = str_replace(".", "", $error[0]). " for sku " . $data['sku']; - } - } - - $requestData['countOfStartedProfiles'] = $i + 1; - - $productsUploaded = $i - $requestData['errorCount']; - - if ($requestData['numberOfCSVRecord'] != 0) { - $remainDataInCSV = (int)$requestData['totalNumberOfCSVRecord'] - (int)$requestData['countOfStartedProfiles']; - } else { - $remainDataInCSV = 0; - } - - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $errorToBeReturn, - ); - - return $dataToBeReturn; - } - - request()->request->add(['booking' => $booking]); - - Event::dispatch('catalog.product.update.before', $bookingProductData->id); - $configBookingProduct = $this->productRepository->update($data, $bookingProductData->id); - Event::dispatch('catalog.product.update.after',$configBookingProduct); - - if (isset($imageZipName)) { - $this->productImageRepository->bulkuploadImages($data, $bookingProductData, $imageZipName); - } else if (isset($csvData['images'])) { - $this->productImageRepository->bulkuploadImages($data, $bookingProductData, $imageZipName = null); - } - } catch(\Exception $e) { - \Log::error('booking product store function'. $e->getMessage()); - } - } - - /** - * prepare data for default booking-type - * - * @param array $data - * - * @return mixed - */ - public function defaultBookingType($data) - { - try { - if (isset($data['booking_slot_from']) && !empty($data['booking_slot_from'])) { - $slot = $this->prepareDefaultBookingSlots($data); - } - - if (strtolower($data['booking_type_day_wise']) == "many") { - $bookingType = "many"; - $duration = $data['duration'] ?? 45; - $breakTime = $data['break_time'] ?? 15; - } else { - $bookingType = "one"; - } - - $availableFrom = explode(',', $data['booking_available_from']); - - foreach ($availableFrom as $key => $availableDateTime) { - $dateFormat = str_replace('/', '-', $availableFrom["0"]); - $date = date('Y-m-d', strtotime($dateFormat)); - - $time = date("H:i:s", strtotime($availableFrom["1"])); - - $from = $date.' '.$time; - } - - $availableTo = explode(',' , $data['booking_available_to']); - - foreach ($availableTo as $key => $availableDateTime) { - $dateFormat = str_replace('/', '-', $availableTo["0"]); - $date = date('Y-m-d', strtotime($dateFormat)); - - $time = date("H:i:s", strtotime($availableTo["1"])); - - $to = $date.' '.$time; - } - - $booking = [ - "type" => "default", - "location" => $data['booking_location'], - "qty" => $data['booking_qty'] ?? 0, - "available_from" => $from, - "available_to" => $to, - "booking_type" => $bookingType, - "duration" => $duration ?? "", - "break_time" => $breakTime ?? "" - ]; - - if (! empty($slot)) { - $booking['slots'] = $slot; - } - - return $booking; - } catch (\Exception $e) { - \Log::error('booking defaultBookingType log: '. $e->getMessage()); - } - } - - /** - * prepare data for appointment booking-type - * - * @param array $data - * - * @return mixed - */ - public function appointmentBookingType($data) - { - try { - if (isset($data['booking_slot_from']) && !empty($data['booking_slot_from'])) { - $slot = $this->prepareAppointmentBookingSlots($data); - } - - if ($data['available_every_week'] == "yes") { - $appointment = [ - "type" => "appointment", - "location" => $data['booking_location'], - "qty" => $data['booking_qty'] ?? 0, - "available_every_week" => "1", - "duration" => $data['duration'] ?? 45, - "break_time" => $data['break_time'] ?? 15, - "same_slot_all_days" => $data['same_slot_all_days'] ? 1 : 0 - ]; - } else { - $availableFrom = explode(',', $data['booking_available_from']); - - foreach ($availableFrom as $key => $availableDateTime) { - $dateFormat = str_replace('/', '-', $availableFrom["0"]); - $date = date('Y-m-d', strtotime($dateFormat)); - - $time = date("H:i:s", strtotime($availableFrom["1"])); - - $from = $date.' '.$time; - } - - $availableTo = explode(',' , $data['booking_available_to']); - - foreach ($availableTo as $key => $availableDateTime) { - $dateFormat = str_replace('/', '-', $availableTo["0"]); - $date = date('Y-m-d', strtotime($dateFormat)); - - $time = date("H:i:s", strtotime($availableTo["1"])); - - $to = $date.' '.$time; - } - - $appointment = [ - "type" => "appointment", - "location" => $data['booking_location'], - "qty" => $data['booking_qty'] ?? 0, - "available_every_week" => "0", - "available_from" => $from, - "available_to" => $to, - "duration" => $data['duration'], - "break_time" => $data['break_time'], - "same_slot_all_days" => $data['same_slot_all_days'] ? 1 : 0 - ]; - } - - if (! empty($slot)) { - $appointment['slots'] = $slot; - } - - return $appointment; - } catch (\Exception $e) { - \Log::error('booking appointmentBookingType log: '. $e->getMessage()); - } - } - - /** - * prepare data for event booking-type - * - * @param array $data - * - * @return mixed - */ - public function eventBookingType($data) - { - try { - if (isset($data['booking_available_from']) && !empty($data['booking_available_to'])) { - $ticket = $this->prepareEventBookingTickets($data); - } - - $availableFrom = explode(',', $data['booking_available_from']); - - foreach ($availableFrom as $key => $availableDateTime) { - $dateFormat = str_replace('/', '-', $availableFrom["0"]); - $date = date('Y-m-d', strtotime($dateFormat)); - - $time = date("H:i:s", strtotime($availableFrom["1"])); - - $from = $date.' '.$time; - } - - $availableTo = explode(',' , $data['booking_available_to']); - - foreach ($availableTo as $key => $availableDateTime) { - $dateFormat = str_replace('/', '-', $availableTo["0"]); - $date = date('Y-m-d', strtotime($dateFormat)); - - $time = date("H:i:s", strtotime($availableTo["1"])); - - $to = $date.' '.$time; - } - - $booking = [ - "type" => "event", - "location" => $data['booking_location'], - "available_from" => $from, - "available_to" => $to, - ]; - - if (! empty($ticket)) { - $booking['tickets'] = $ticket; - } - - return $booking; - } catch (\Exception $e) { - \Log::error('booking eventBookingType log: '. $e->getMessage()); - } - } - - /** - * prepare data for rental booking-type - * - * @param array $data - * - * @return mixed - */ - public function rentalBookingType($data) - { - try { - if ($data['available_every_week'] == "no" || empty($data['available_every_week'])) { - $availableEveryWeek = "0"; - - $availableFrom = explode(',', $data['booking_available_from']); - - foreach ($availableFrom as $key => $availableDateTime) { - $dateFormat = str_replace('/', '-', $availableFrom["0"]); - $date = date('Y-m-d', strtotime($dateFormat)); - - $time = date("H:i:s", strtotime($availableFrom["1"])); - - $from = $date.' '.$time; - } - - $availableTo = explode(',' , $data['booking_available_to']); - - foreach ($availableTo as $key => $availableDateTime) { - $dateFormat = str_replace('/', '-', $availableTo["0"]); - $date = date('Y-m-d', strtotime($dateFormat)); - - $time = date("H:i:s", strtotime($availableTo["1"])); - - $to = $date.' '.$time; - } - - $booking['booking_available_from'] = $from; - $booking['booking_available_to'] = $to; - } else { - $availableEveryWeek = "1"; - } - - if ($data['renting_type'] == "daily") { - $booking = [ - "type" => "rental", - "location" => $data['booking_location'], - "qty" => $data['booking_qty'], - "available_every_week" => $availableEveryWeek, - "renting_type" => "daily", - "daily_price" => $data['daily_price'] ?? 0, - ]; - } else if ($data['renting_type'] == "hourly") { - $slot = $this->prepareRentalBookingSlots($data); - - $booking = [ - "type" => "rental", - "location" => $data['booking_location'], - "qty" => $data['booking_qty'], - "available_every_week" => $availableEveryWeek, - "renting_type" => "hourly", - "hourly_price" => $data['hourly_price'] ?? 0, - "same_slot_all_days" => $data['same_slot_all_days'] - ]; - - if (! empty($slot)) { - $booking['slots'] = $slot; - } - } else if ($data['renting_type'] == "daily_hourly") { - $slot = $this->prepareRentalBookingSlots($data); - - if (trim(strtolower($data['same_slot_all_days'])) == "no" || empty($data['same_slot_all_days'])) { - $data['same_slot_all_days'] = null; - } - - $booking = [ - "type" => "rental", - "location" => $data['booking_location'], - "qty" => $data['booking_qty'], - "available_every_week" => $availableEveryWeek, - "renting_type" => "daily_hourly", - "daily_price" => $data['daily_price'] ?? 0, - "hourly_price" => $data['hourly_price'] ?? 0, - "same_slot_all_days" => $data['same_slot_all_days'] ? 1 : 0 - ]; - - if (! empty($slot)) { - $booking['slots'] = $slot; - } - } - - return $booking; - } catch (\Exception $e) { - \Log::error('booking rentalBookingType log: '. $e->getMessage()); - } - } - - /** - * prepare data for table booking-type - * - * @param array $data - * - * @return mixed - */ - public function tableBookingType($data) - { - try { - if ($data['available_every_week'] == "no" || empty($data['available_every_week'])) { - $availableEveryWeek = "0"; - - $availableFrom = explode(',', $data['booking_available_from']); - - foreach ($availableFrom as $key => $availableDateTime) { - $dateFormat = str_replace('/', '-', $availableFrom["0"]); - $date = date('Y-m-d', strtotime($dateFormat)); - - $time = date("H:i:s", strtotime($availableFrom["1"])); - - $from = $date.' '.$time; - } - - $availableTo = explode(',' , $data['booking_available_to']); - - foreach ($availableTo as $key => $availableDateTime) { - $dateFormat = str_replace('/', '-', $availableTo["0"]); - $date = date('Y-m-d', strtotime($dateFormat)); - - $time = date("H:i:s", strtotime($availableTo["1"])); - - $to = $date.' '.$time; - } - - $booking['booking_available_from'] = $from; - $booking['booking_available_to'] = $to; - } else { - $availableEveryWeek = "1"; - } - - if ($data['price_type'] == "table") { - $booking['guest_limit'] = $data['guest_limit'] ?? 0; - } - - if (trim(strtolower($data['same_slot_all_days'])) == "no" || empty($data['same_slot_all_days'])) { - $data['same_slot_all_days'] = null; - } - - $slot = $this->prepareRentalBookingSlots($data); - - $booking = [ - "type" => "table", - "location" => $data['booking_location'], - "qty" => $data['booking_qty'], - "available_every_week" => $availableEveryWeek, - "price_type" => $data['price_type'], - "duration" => $data['duration'], - "break_time" => $data['break_time'], - "prevent_scheduling_before" => $data['prevent_scheduling_before'], - "same_slot_all_days" => $data['same_slot_all_days'] ? 1 : 0 - ]; - - if (! empty($slot)) { - $booking['slots'] = $slot; - } - - return $booking; - } catch (\Exception $e) { - \Log::error('booking tableBookingType log: '. $e->getMessage()); - } - } - - /** - * prepare slots for default booking type - * - * @param array $data - * - * @return array - */ - public function prepareDefaultBookingSlots($record) - { - try { - $weekNames = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'); - - $bookingSlotFromDay = explode(',', $record['booking_slot_from_day']); - $bookingSlotFrom = explode(',', $record['booking_slot_from']) ?? "12:00:00"; - $bookingSlotToDay = explode(',', $record['booking_slot_to_day']); - $bookingSlotTo = explode(',', $record['booking_slot_to']) ?? "13:00:00"; - - if (strtolower($record['booking_type_day_wise']) == "one") { - for ($j = 0; $j < count($bookingSlotFrom); $j++) { - $fromDay = array_search(strtolower($bookingSlotFromDay[$j]), $weekNames); - $toDay = array_search(strtolower($bookingSlotToDay[$j]), $weekNames); - - $from = date("H:i:s", strtotime($bookingSlotFrom[$j])); - $to = date("H:i:s", strtotime($bookingSlotTo[$j])); - - $slotter[$j] = [ - "from_day" => $fromDay, - "from" => $from, - "to_day" => $toDay, - "to" => $to, - ]; - } - } else { - $defaultBookingStatus = explode(',', $record['default_booking_status']); - - for ($j = 0; $j < count($weekNames); $j++) { - $from = date("H:i:s", strtotime($bookingSlotFrom[$j])); - $to = date("H:i:s", strtotime($bookingSlotTo[$j])); - - $slotter[$j] = [ - "from" => $from, - "to" => $to, - "status" => $defaultBookingStatus[$j] ?? 0 - ]; - } - } - - return $slotter; - } catch(\Exception $e) { - \Log::error('booking prepareDefaultBookingSlots log: '. $e->getMessage()); - } - } - - /** - * prepare slots for appointment booking type - * - * @param array $data - * - * @return array - */ - public function prepareAppointmentBookingSlots($record) - { - try { - $bookingSlotFrom = explode(',', $record['booking_slot_from']); - $bookingSlotTo = explode(',', $record['booking_slot_to']); - - for($j = 0; $j < count($bookingSlotFrom); $j++) { - $from = date("H:i:s", strtotime($bookingSlotFrom[$j])); - $to = date("H:i:s", strtotime($bookingSlotTo[$j])); - - if ($record['same_slot_all_days'] == "no" || empty($record['same_slot_all_days'])) { - $weekNames = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'); - - $dayWiseSlots = explode(',', $record['day_wise_slots']); - - $weekDayNumber = array_search(trim(strtolower($dayWiseSlots[$j])), $weekNames); - $slotter[$weekDayNumber] = [ - $slotArray[$j] = [ - "from" => $from, - "to" => $to, - ] - ]; - } else { - $slotter[$j] = [ - "from" => $from, - "to" => $to, - ]; - } - } - - return $slotter; - } catch (\Exception $e) { - \Log::error('booking prepareAppointmentBookingSlots log: '. $e->getMessage()); - } - } - - /** - * prepare tickets for event booking type - * - * @param array $data - * - * @return array - */ - public function prepareEventBookingTickets($record) - { - try { - $ticketName = explode(',', $record['event_ticket_name']); - $ticketDescription = explode(',', $record['event_ticket_description']); - $ticketPrice = explode(',', $record['event_ticket_price']); - $ticketQty = explode(',', $record['event_ticket_qty']); - - for($j = 0; $j < count($ticketName); $j++) { - $slotter['ticket_'.$j] = [ - core()->getCurrentLocale()->code => [ - "name" => $ticketName[$j], - "description" => $ticketDescription[$j] - ], - "price" => $ticketPrice[$j], - "qty" => $ticketQty[$j], - ]; - } - - return $slotter; - } catch (\Exception $e) { - \Log::error('booking prepareEventBookingTickets log: '. $e->getMessage()); - } - } - - /** - * prepare slots for rental booking type - * - * @param array $data - * - * @return array - */ - public function prepareRentalBookingSlots($record) - { - try { - $bookingSlotFrom = explode(',', $record['booking_slot_from']); - $bookingSlotTo = explode(',', $record['booking_slot_to']); - $weekDayNumber = []; - $slotter = []; - - for($j = 0; $j < count($bookingSlotFrom); $j++) { - $from = date("H:i:s", strtotime($bookingSlotFrom[$j])); - $to = date("H:i:s", strtotime($bookingSlotTo[$j])); - - if ($record['same_slot_all_days'] == "no" || empty($record['same_slot_all_days'])) { - $weekNames = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'); - - $dayWiseSlots = explode(',', $record['day_wise_slots']); - - $weekDayNumber = array_search(trim(strtolower($dayWiseSlots[$j])), $weekNames); - $slotter[$weekDayNumber] = [ - $slotArray[$j] = [ - "from" => $from, - "to" => $to, - ] - ]; - } else { - $slotter[$j] = [ - "from" => $from, - "to" => $to, - ]; - } - } - - return $slotter; - } catch (\Exception $e) { - \Log::error('booking prepareRentalBookingSlots log: '. $e->getMessage()); - } - } - - /** - * prepare slots for table booking type - * - * @param array $data - * - * @return array - */ - public function prepareTableBookingSlots($record) - { - try { - $bookingSlotFrom = explode(',', $record['booking_slot_from']); - $bookingSlotTo = explode(',', $record['booking_slot_to']); - $weekDayNumber = []; - $slotter = []; - - for($j = 0; $j < count($bookingSlotFrom); $j++) { - $from = date("H:i:s", strtotime($bookingSlotFrom[$j])); - $to = date("H:i:s", strtotime($bookingSlotTo[$j])); - - if ($record['same_slot_all_days'] == "no" || empty($record['same_slot_all_days'])) { - $weekNames = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'); - - $dayWiseSlots = explode(',', $record['day_wise_slots']); - - $weekDayNumber = array_search(trim(strtolower($dayWiseSlots[$j])), $weekNames); - $slotter[$weekDayNumber] = [ - $slotArray[$j] = [ - "from" => $from, - "to" => $to, - ] - ]; - } else { - $slotter[$j] = [ - "from" => $from, - "to" => $to, - ]; - } - } - - return $slotter; - } catch (\Exception $e) { - \Log::error('booking prepareTableBookingSlots log: '. $e->getMessage()); - } - } -} \ No newline at end of file diff --git a/src/Repositories/Products/BundledProductRepository.php b/src/Repositories/Products/BundledProductRepository.php deleted file mode 100644 index af8af57..0000000 --- a/src/Repositories/Products/BundledProductRepository.php +++ /dev/null @@ -1,408 +0,0 @@ -importProductRepository = $importProductRepository; - - $this->categoryRepository = $categoryRepository; - - $this->productFlatRepository = $productFlatRepository; - - $this->productRepository = $productRepository; - - $this->productImageRepository = $productImageRepository; - - $this->attributeFamilyRepository = $attributeFamilyRepository; - - $this->helperRepository = $helperRepository; - - $this->attributeOptionRepository = $attributeOptionRepository; - } - - /* - * Specify Model class name - * - * @return mixed - */ - function model() - { - return 'Webkul\Product\Contracts\Product'; - } - - /** - * create & update bundled-type product - * - * @param array $requestData - * @param array $imageZipName - * - * @return mixed - */ - public function createProduct($requestData, $imageZipName) - { - try { - $dataFlowProfileRecord = $this->importProductRepository->findOneByField - ('data_flow_profile_id', $requestData['data_flow_profile_id']); - - $csvData = (new DataGridImport)->toArray($dataFlowProfileRecord->file_path)[0]; - - if ($requestData['totalNumberOfCSVRecord'] < 1000) { - $processCSVRecords = $requestData['totalNumberOfCSVRecord']/($requestData['totalNumberOfCSVRecord']/10); - } else { - $processCSVRecords = $requestData['totalNumberOfCSVRecord']/($requestData['totalNumberOfCSVRecord']/100); - } - - $uptoProcessCSVRecords = (int)$requestData['countOfStartedProfiles'] + 10; - $processRecords = (int)$requestData['countOfStartedProfiles'] + (int)$requestData['numberOfCSVRecord']; - - if ($requestData['numberOfCSVRecord'] > $processCSVRecords) { - for ($i = $requestData['countOfStartedProfiles']; $i < $uptoProcessCSVRecords; $i++) { - $invalidateProducts = $this->store($csvData[$i], $i, $dataFlowProfileRecord, $requestData, $imageZipName); - - if (isset($invalidateProducts) && !empty($invalidateProducts)) { - return $invalidateProducts; - } - } - } else if ($requestData['numberOfCSVRecord'] <= 10) { - for ($i = $requestData['countOfStartedProfiles']; $i < $processRecords; $i++) { - $invalidateProducts = $this->store($csvData[$i], $i, $dataFlowProfileRecord, $requestData, $imageZipName); - - if (isset($invalidateProducts) && !empty($invalidateProducts)) { - return $invalidateProducts; - } - } - } - - if ($requestData['numberOfCSVRecord'] > 10) { - $remainDataInCSV = (int)$requestData['numberOfCSVRecord'] - (int)$processCSVRecords; - } else { - $remainDataInCSV = 0; - - if($requestData['errorCount'] > 0) { - $uptoProcessCSVRecords = $requestData['totalNumberOfCSVRecord'] - $requestData['errorCount']; - } else { - $uptoProcessCSVRecords = $processRecords; - } - } - - $requestData['countOfStartedProfiles'] = $i; - - $dataToBeReturn = [ - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $uptoProcessCSVRecords, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - ]; - - return $dataToBeReturn; - } catch(\Exception $e) { - $categoryError = explode('[' ,$e->getMessage()); - $categorySlugError = explode(']' ,$e->getMessage()); - $requestData['countOfStartedProfiles'] = $i + 1; - $productsUploaded = $i - $requestData['errorCount']; - - if ($requestData['numberOfCSVRecord'] != 0) { - $remainDataInCSV = (int)$requestData['totalNumberOfCSVRecord'] - (int)$requestData['countOfStartedProfiles']; - } else { - $remainDataInCSV = 0; - } - - if ($categoryError[0] == "No query results for model ") { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => "Invalid Category Slug: " . $categorySlugError[1], - ); - $categoryError[0] = null; - } else if (isset($e->errorInfo)) { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $e->errorInfo[2], - ); - } else { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $e->getMessage(), - ); - } - - return $dataToBeReturn; - } - } - - /** - * function to store product - * - * @param array $csvData - * @param integer $i - * @param \Webkul\Bulkupload\Contracts\ImportProduct $dataFlowProfileRecord - * @param array $requestData - * @param array $imageZipName - * - * @return mixed - */ - public function store($csvData, $i, $dataFlowProfileRecord, $requestData, $imageZipName) - { - $createValidation = $this->helperRepository->createProductValidation($csvData, $i); - - if (isset($createValidation)) { - return $createValidation; - } - - $productFlatData = $this->productFlatRepository->findWhere(['sku' => $csvData['sku'], 'url_key' => $csvData['url_key']])->first(); - - $productData = $this->productRepository->findWhere(['sku' => $csvData['sku']])->first(); - - $attributeFamilyData = $this->attributeFamilyRepository->findOneByfield(['name' => $csvData['attribute_family_name']]); - - if (! isset($productFlatData) && empty($productFlatData)) { - $data['type'] = $csvData['type']; - $data['attribute_family_id'] = $attributeFamilyData->id; - $data['sku'] = $csvData['sku']; - Event::dispatch('catalog.product.create.before'); - $bundledProduct = $this->productRepository->create($data); - Event::dispatch('catalog.product.create.after', $bundledProduct); - } else { - $bundledProduct = $productData; - } - - unset($data); - - $data = []; - $attributeCode = []; - $attributeValue = []; - - //default attributes - foreach ($bundledProduct->getTypeInstance()->getEditableAttributes()->toArray() as $key => $value) { - $searchIndex = $value['code']; - - if (array_key_exists($searchIndex, $csvData)) { - if (is_null($csvData[$searchIndex])) { - continue; - } - - array_push($attributeCode, $searchIndex); - - if ($searchIndex == "color" || $searchIndex == "size" || $searchIndex == "brand") { - $attributeOption = $this->attributeOptionRepository->findOneByField(['admin_name' => ucwords($csvData[$searchIndex])]); - - array_push($attributeValue, $attributeOption['id']); - } else { - array_push($attributeValue, $csvData[$searchIndex]); - } - - $data = array_combine($attributeCode, $attributeValue); - } - } - - $data['dataFlowProfileRecordId'] = $dataFlowProfileRecord->id; - - $categoryData = explode(',', $csvData['categories_slug']); - - if (is_null($csvData['categories_slug']) || empty($csvData['categories_slug'])) { - $categoryID = $this->categoryRepository->findBySlugOrFail('root')->id; - } else { - foreach ($categoryData as $key => $value) { - $categoryID[$key] = $this->categoryRepository->findBySlugOrFail($categoryData[$key])->id; - } - } - - $data['categories'] = $categoryID; - $data['channel'] = core()->getCurrentChannel()->code; - - $dataProfile = app('Webkul\Bulkupload\Repositories\DataFlowProfileRepository')->findOneByfield(['id' => $data['dataFlowProfileRecordId']]); - $data['locale'] = $dataProfile->locale_code; - - //customerGroupPricing - if (isset($csvData['customer_group_prices']) && ! empty($csvData['customer_group_prices'])) { - $data['customer_group_prices'] = json_decode($csvData['customer_group_prices'], true); - app(ProductCustomerGroupPriceRepository::class)->saveCustomerGroupPrices($data, $simpleproductData); - } - - //prepare bundle options - $bundleOptions = json_decode($csvData['bundle_options'], true); - - $data['bundle_options'] = $bundleOptions; - - //Product Images - $individualProductimages = explode(',', $csvData['images']); - - if (isset($imageZipName)) { - $images = Storage::disk('local')->files('public/imported-products/extracted-images/admin/'.$dataFlowProfileRecord->id.'/'.$imageZipName['dirname'].'/'); - - foreach ($images as $imageArraykey => $imagePath) { - $imageName = explode('/', $imagePath); - - if (in_array(last($imageName), preg_replace('/[\'"]/', '',$individualProductimages))) { - $data['images'][$imageArraykey] = $imagePath; - } - } - } else if (isset($csvData['images'])) { - foreach ($individualProductimages as $imageArraykey => $imageURL) - { - if (filter_var(trim($imageURL), FILTER_VALIDATE_URL)) { - $imagePath = storage_path('app/public/imported-products/extracted-images/admin/'.$dataFlowProfileRecord->id); - - if (!file_exists($imagePath)) { - mkdir($imagePath, 0777, true); - } - - $imageFile = $imagePath.'/'.basename($imageURL); - - file_put_contents($imageFile, file_get_contents(trim($imageURL))); - - $data['images'][$imageArraykey] = $imageFile; - } - } - } - - $validationRules = $this->helperRepository->validateCSV($requestData['data_flow_profile_id'], $data, $dataFlowProfileRecord, $bundledProduct); - - $csvValidator = Validator::make($data, $validationRules); - - if ($csvValidator->fails()) { - $errors = $csvValidator->errors()->getMessages(); - - $this->helperRepository->deleteProductIfNotValidated($bundledProduct->id); - - foreach($errors as $key => $error) { - if ($error[0] == "The url key has already been taken.") { - $errorToBeReturn[] = "The url key " . $data['url_key'] . " has already been taken"; - } else { - $errorToBeReturn[] = str_replace(".", "", $error[0]). " for sku " . $data['sku']; - } - } - - $requestData['countOfStartedProfiles'] = $i + 1; - - $productsUploaded = $i - $requestData['errorCount']; - - if ($requestData['numberOfCSVRecord'] != 0) { - $remainDataInCSV = (int)$requestData['totalNumberOfCSVRecord'] - (int)$requestData['countOfStartedProfiles']; - } else { - $remainDataInCSV = 0; - } - - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $errorToBeReturn, - ); - - return $dataToBeReturn; - } - - Event::dispatch('catalog.product.update.before', $bundledProduct->id); - $configBundledProduct = $this->productRepository->update($data, $bundledProduct->id); - Event::dispatch('catalog.product.update.after',$configBundledProduct); - - if (isset($imageZipName)) { - $this->productImageRepository->bulkuploadImages($data, $bundledProduct, $imageZipName); - } else if (isset($csvData['images'])) { - $this->productImageRepository->bulkuploadImages($data, $bundledProduct, $imageZipName = null); - } - } -} \ No newline at end of file diff --git a/src/Repositories/Products/ConfigurableProductRepository.php b/src/Repositories/Products/ConfigurableProductRepository.php deleted file mode 100644 index 5bafb62..0000000 --- a/src/Repositories/Products/ConfigurableProductRepository.php +++ /dev/null @@ -1,745 +0,0 @@ -importProductRepository = $importProductRepository; - - $this->categoryRepository = $categoryRepository; - - $this->productFlatRepository = $productFlatRepository; - - $this->productRepository = $productRepository; - - $this->productImageRepository = $productImageRepository; - - $this->attributeFamilyRepository = $attributeFamilyRepository; - - $this->attributeRepository = $attributeRepository; - - $this->productInventoryRepository = $productInventoryRepository; - - $this->helperRepository = $helperRepository; - - $this->bulkProductRepository = $bulkProductRepository; - - $this->attributeOptionRepository = $attributeOptionRepository; - } - - /* - * Specify Model class name - * - * @return mixed - */ - function model() - { - return 'Webkul\Product\Contracts\Product'; - } - - /** - * create & update configurable-type product - * - * @param array $requestData - * @param array $imageZipName - * @param array $product - * - * @return mixed - */ - public function createProduct($requestData, $imageZipName, $product) - { - try { - if ($requestData['totalNumberOfCSVRecord'] < 1000) { - $processCSVRecords = $requestData['totalNumberOfCSVRecord']/($requestData['totalNumberOfCSVRecord']/10); - } else { - $processCSVRecords = $requestData['totalNumberOfCSVRecord']/($requestData['totalNumberOfCSVRecord']/100); - } - - $dataFlowProfileRecord = $this->importProductRepository->findOneByField - ('data_flow_profile_id', $requestData['data_flow_profile_id']); - - if ($dataFlowProfileRecord) { - $csvData = (new DataGridImport)->toArray($dataFlowProfileRecord->file_path)[0]; - - foreach ($csvData as $key => $value) { - if ($requestData['numberOfCSVRecord'] >= 0) { - for ($i = $requestData['countOfStartedProfiles']; $i < count($csvData); $i++) { - $product['loopCount'] = $i; - - if ($csvData[$i]['type'] == 'configurable') { - try { - $createValidation = $this->helperRepository->createProductValidation($csvData[$i], $i); - - if ( isset($createValidation)) { - return $createValidation; - } - - unset($data); - - $productFlatData = $this->productFlatRepository->findOneWhere([ - 'sku' => $csvData[$i]['sku'], - 'url_key' => $csvData[$i]['url_key'] - ]); - - $productData = $this->productRepository->findOneWhere([ - 'sku' => $csvData[$i]['sku'] - ]); - - $attributeFamilyData = $this->attributeFamilyRepository->findOneByfield('name', $csvData[$i]['attribute_family_name']); - - if (! isset($productFlatData) && empty($productData)) { - $data['type'] = $csvData[$i]['type']; - $data['attribute_family_id'] = $attributeFamilyData->id; - $data['sku'] = $csvData[$i]['sku']; - - Event::dispatch('catalog.product.create.before'); - $configSimpleproduct = $this->productRepository->create($data); - Event::dispatch('catalog.product.create.after', $configSimpleproduct); - } else { - $product = $productData; - } - - unset($data); - $data = []; - $attributeCode = []; - $attributeValue = []; - - foreach ($product->getTypeInstance()->getEditableAttributes()->toArray() as $key => $value) { - $attributeOptionArray = []; - $searchIndex = strtolower($value['code']); - - if (array_key_exists($searchIndex, $csvData[$i])) { - if ($searchIndex == 'tax_category_id') { - continue; - } - - array_push($attributeCode, $searchIndex); - - if ($value['type'] == "select") { - $attributeOption = $this->attributeOptionRepository->findOneByField('admin_name', $csvData[$i][$searchIndex]); - - array_push($attributeValue, (isset($attributeOption['id']) ? $attributeOption['id'] : null)); - - } else if ($value['type'] == "checkbox") { - $attributeOption = $this->attributeOptionRepository->findOneWhere([ - 'attribute_id' => $value['id'], - 'admin_name' => $csvData[$i][$searchIndex] - ]); - - array_push($attributeOptionArray, (isset($attributeOption['id']) ? $attributeOption['id'] : null)); - - array_push($attributeValue, $attributeOptionArray); - - unset($attributeOptionArray); - } else { - array_push($attributeValue, $csvData[$i][$searchIndex]); - } - - $data = array_combine($attributeCode, $attributeValue); - } - } - - $data['dataFlowProfileRecordId'] = $dataFlowProfileRecord->id; - $data['channel'] = core()->getCurrentChannel()->code; - - $dataProfile = app('Webkul\Bulkupload\Repositories\DataFlowProfileRepository')->findOneByfield(['id' => $data['dataFlowProfileRecordId']]); - $data['locale'] = $dataProfile->locale_code; - - $data['tax_category_id'] = (isset($csvData[$i]['tax_category_id']) && $csvData[$i]['tax_category_id']) ? $csvData[$i]['tax_category_id'] : null; - - $categoryData = explode(',', $csvData[$i]['categories_slug']); - - if (is_null($csvData[$i]['categories_slug']) || empty($csvData[$i]['categories_slug'])) { - $categoryID = $this->categoryRepository->findBySlugOrFail('root')->id; - } else { - foreach ($categoryData as $key => $value) { - $categoryID[$key] = $this->categoryRepository->findBySlugOrFail($categoryData[$key])->id; - } - } - - $data['categories'] = $categoryID; - - $individualProductimages = explode(',', $csvData[$i]['images']); - - if (isset($imageZipName)) { - $images = Storage::disk('local')->files('public/imported-products/extracted-images/admin/'.$dataFlowProfileRecord->id.'/'.$imageZipName['dirname'].'/'); - - foreach ($images as $imageArraykey => $imagePath) { - $imageName = explode('/', $imagePath); - - if (in_array(last($imageName), preg_replace('/[\'"]/', '',$individualProductimages))) { - $data['images'][$imageArraykey] = $imagePath; - } - } - } else if (isset($csvData['images'])) { - foreach ($individualProductimages as $imageArraykey => $imageURL) - { - if (filter_var(trim($imageURL), FILTER_VALIDATE_URL)) { - $imagePath = storage_path('app/public/ imported-products/extracted-images/admin/'. $dataFlowProfileRecord->id); - - if (!file_exists($imagePath)) { - mkdir($imagePath, 0777, true); - } - - $imageFile = $imagePath.'/'.basename($imageURL) ; - - file_put_contents($imageFile, file_get_contents (trim($imageURL))); - - $data['images'][$imageArraykey] = $imageFile; - } - } - } - - $productAttributeStore = $this->bulkProductRepository->productRepositoryUpdateForVariants($data, $product->id); - - if (isset($imageZipName)) { - $this->productImageRepository->bulkuploadImages($data, $product, $imageZipName); - } else if (isset($csvData['images'])) { - $this->productImageRepository->bulkuploadImages($data, $product, $imageZipName = null); - } - - if (! isset($productFlatData) && empty($productFlatData)) { - $productFlatData = DB::table('product_flat')->select('id')->orderBy('id', 'desc')->first(); - } - - $product['productFlatId'] = $productFlatData->id; - - $arr[] = $productFlatData->id; - - unset($categoryID); - } catch (\Exception $e) { - $categoryError = explode('[' ,$e->getMessage()); - $categorySlugError = explode(']' ,$e->getMessage()); - - $error = $e; - - $productUploadedWithError = $requestData['productUploaded'] + 1; - $remainDataInCSV = $requestData['totalNumberOfCSVRecord'] - $productUploadedWithError; - $requestData['countOfStartedProfiles'] = $i + 1; - - if ($categoryError[0] == "No query results for model ") { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $requestData['productUploaded'], - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => "Invalid Category Slug: " . $categorySlugError[1], - ); - $categoryError[0] = null; - } else if (isset($e->errorInfo)) { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $requestData['productUploaded'], - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $e->errorInfo[2], - ); - } else { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $requestData['productUploaded'], - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $e->getMessage(), - ); - } - return $dataToBeReturn; - } - } else if (isset($product['productFlatId'])) { - try { - $current = $product['loopCount']; - $num = 0; - $inventory = []; - - $csvData = (new DataGridImport)->toArray($dataFlowProfileRecord->file_path)[0]; - - for ($i = $current; $i < count($csvData); $i++) { - $product['loopCount'] = $i; - - if ($csvData[$i]['type'] != 'configurable') { - $productFlatData = $this->productFlatRepository->findOneWhere([ - 'sku' => $csvData[$i]['sku'], - 'url_key' => null - ]); - - $productData = $this->productRepository->findOneWhere([ - 'sku' => $csvData[$i]['sku'] - ]); - - $attributeFamilyData = $this->attributeFamilyRepository->findOneWhere([ - 'name' => $csvData[$i]['attribute_family_name'] - ]); - - if (! isset($productFlatData) && empty($productData)) { - $data['parent_id'] = $product->id; - $data['type'] = "simple"; - $data['attribute_family_id'] = $attributeFamilyData->id; - $data['sku'] = $csvData[$i]['sku']; - - $configSimpleproduct = $this->productRepository->create($data); - } else { - $configSimpleproduct = $productData; - } - - unset($data); - - $validateVariant = Validator::make($csvData[$i], [ - 'sku' => ['required', 'unique:products,sku,' . $configSimpleproduct->id, new \Webkul\Core\Contracts\Validations\Slug], - 'name' => 'required', - 'super_attribute_price' => 'required', - 'super_attribute_weight' => 'required', - 'super_attribute_option' => 'required', - 'super_attributes' => 'required' - ]); - - if ($validateVariant->fails()) { - $errors = $validateVariant->errors()->getMessages(); - - $this->helperRepository->deleteProductIfNotValidated($product->id); - - foreach($errors as $key => $error) { - $errorToBeReturn[] = str_replace(".", "", $error[0]). " for sku " .$csvData[$i]['sku']; - } - - $productUploadedWithError = $requestData['productUploaded'] + 1; - - $requestData['countOfStartedProfiles'] = $i + 1; - - if ($requestData['numberOfCSVRecord'] != 0) { - $remainDataInCSV = $requestData['totalNumberOfCSVRecord'] - $productUploadedWithError; - } else { - $remainDataInCSV = 0; - } - - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $requestData['productUploaded'], - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $errorToBeReturn, - ); - - return $dataToBeReturn; - } - - $inventory_data = core()->getCurrentChannel()->inventory_sources; - - foreach($inventory_data as $key => $datas) { - $inventoryId = $datas->id; - } - - $inventoryData[] = (string)$csvData[$i]['super_attribute_qty']; - - foreach ($inventoryData as $key => $d) { - $inventory[$inventoryId] = $d; - } - - $productInventory = $this->productInventoryRepository->findOneByField('product_id', $configSimpleproduct->id); - - if (! isset($productInventory) && empty($productInventory) || $productInventory->count() < 1) { - $data['inventories'] = $inventory; - } - - $superAttributes = explode(',', $csvData[$i]['super_attributes']); - $superAttributesOption = explode(',', $csvData[$i]['super_attribute_option']); - - $data['super_attributes'] = array_combine($superAttributes, $superAttributesOption); - - if (isset($data['super_attributes']) && $i == $current) { - $super_attributes = []; - - foreach ($data['super_attributes'] as $attributeCode => $attributeOptions) { - $attribute = $this->attributeRepository->findOneByField('code', $attributeCode); - - $super_attributes[$attribute->id] = $attributeOptions; - - $users = $product->super_attributes()->where('id', $attribute->id)->exists(); - - if (! $users) { - $product->super_attributes()->attach($attribute->id); - } - } - } - - $data['dataFlowProfileRecordId'] = $dataFlowProfileRecord->id; - $data['channel'] = core()->getCurrentChannel()->code; - - $dataProfile = app('Webkul\Bulkupload\Repositories\DataFlowProfileRepository')->findOneByfield(['id' => $data['dataFlowProfileRecordId']]); - $data['locale'] = $dataProfile->locale_code; - - $data['price'] = (string)$csvData[$i]['super_attribute_price']; - $data['special_price'] = (string)$csvData[$i]['special_price']; - $data['special_price_from'] = (string)$csvData[$i]['special_price_from']; - $data['special_price_to'] = (string)$csvData[$i]['special_price_to']; - $data['new'] = (string)$csvData[$i]['new']; - $data['featured'] = (string)$csvData[$i]['featured']; - $data['visible_individually'] = (string)$csvData[$i]['visible_individually']; - $data['tax_category_id'] = (string)$csvData[$i]['tax_category_id']; - $data['cost'] = (string)$csvData[$i]['cost']; - $data['width'] = (string)$csvData[$i]['width']; - $data['height'] = (string)$csvData[$i]['height']; - $data['depth'] = (string)$csvData[$i]['depth']; - $data['status'] = (string)$csvData[$i]['status']; - $data['attribute_family_id'] = $attributeFamilyData->id; - $data['short_description'] = (string)$csvData[$i]['short_description']; - $data['sku'] = (string)$csvData[$i]['sku']; - $data['name'] = (string)$csvData[$i]['name']; - $data['weight'] = (string)$csvData[$i]['super_attribute_weight']; - $data['status'] = (string)$csvData[$i]['status']; - - if ( isset($data['super_attributes'])) { - foreach ($data['super_attributes'] as $attributeCode => $attributeOptions) { - $attribute = $this->attributeRepository->findOneByField('code', $attributeCode); - - if ( $attribute ) { - $attributeOptionColor = $this->attributeOptionRepository->findOneWhere([ - 'attribute_id' => $attribute->id, - 'admin_name' => $attributeOptions, - ]); - - $data[$attributeCode] = $attributeOptionColor->id; - } - } - } - - $individualProductimages = explode(',', $csvData[$i]['images']); - - if (isset($imageZipName)) { - $images = Storage::disk('local')->files('public/imported-products/extracted-images/admin/'.$dataFlowProfileRecord->id.'/'.$imageZipName['dirname'].'/'); - - foreach ($images as $imageArraykey => $imagePath) { - $imageName = explode('/', $imagePath); - - if (in_array(last($imageName), preg_replace('/[\'"]/', '',$individualProductimages))) { - $data['images'][$imageArraykey] = $imagePath; - } - } - } else if (isset($csvData['images'])) { - foreach ($individualProductimages as $imageArraykey => $imageURL) - { - if (filter_var(trim($imageURL), FILTER_VALIDATE_URL)) { - $imagePath = storage_path('app/public/ imported-products/extracted-images/admin/'. $dataFlowProfileRecord->id); - - if (!file_exists($imagePath)) { - mkdir($imagePath, 0777, true); - } - - $imageFile = $imagePath.'/'.basename($imageURL) ; - - file_put_contents($imageFile, file_get_contents (trim($imageURL))); - - $data['images'][$imageArraykey] = $imageFile; - } - } - } - - $configSimpleProductAttributeStore = $this->bulkProductRepository->productRepositoryUpdateForVariants($data, $configSimpleproduct->id); - - if (isset($imageZipName)) { - $this->productImageRepository->bulkuploadImages($data, $configSimpleproduct, $imageZipName); - } else if (isset($csvData['images'])) { - $this->productImageRepository->bulkuploadImages($data, $configSimpleproduct, $imageZipName = null); - } - - $configSimpleProductAttributeStore['parent_id'] = $product['productFlatId']; - - $this->createFlat($configSimpleProductAttributeStore); - - } else { - $savedProduct = $requestData['productUploaded'] + 1; - $remainDataInCSV = $requestData['totalNumberOfCSVRecord'] - $savedProduct; - $productsUploaded = $savedProduct; - - $requestData['countOfStartedProfiles'] = $product['loopCount']; - - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'] - ); - - return $dataToBeReturn; - } - } - - if ($requestData['errorCount'] == 0) { - $dataToBeReturn = [ - 'remainDataInCSV' => 0, - 'productsUploaded' => $requestData['totalNumberOfCSVRecord'], - 'countOfStartedProfiles' => count($csvData), - ]; - - return $dataToBeReturn; - } else { - $dataToBeReturn = [ - 'remainDataInCSV' => 0, - 'productsUploaded' => $requestData['totalNumberOfCSVRecord'] - $requestData['errorCount'], - 'countOfStartedProfiles' => count($csvData), - ]; - - return $dataToBeReturn; - } - - $product['productFlatId'] = null; - } catch (\Exception $e) { - $error = $e; - $requestData['countOfStartedProfiles'] = $i + 1; - $remainDataInCSV = $requestData['totalNumberOfCSVRecord'] - $requestData['productUploaded']; - - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $requestData['productUploaded'], - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $error->errorInfo[2] ?? $error->getMessage(), - ); - - return $dataToBeReturn; - } - } - } - } - } - } - } catch(\Exception $e) { - \Log::error('configurable create product log: '. $e->getMessage()); - } - } - - /** - * create product flat for variants - * - * @param \Webkul\Product\Contracts\Product $product - * - * @return mixed - */ - public function createFlat($product, $parentProduct = null) - { - static $familyAttributes = []; - - static $superAttributes = []; - - if (! array_key_exists($product->attribute_family->id, $familyAttributes)) - $familyAttributes[$product->attribute_family->id] = $product->attribute_family->custom_attributes; - - if ($parentProduct && ! array_key_exists($parentProduct->id, $superAttributes)) - $superAttributes[$parentProduct->id] = $parentProduct->super_attributes()->pluck('code')->toArray(); - - foreach (core()->getAllChannels() as $channel) { - foreach ($channel->locales as $locale) { - $productFlat = $this->productFlatRepository->findOneWhere([ - 'product_id' => $product->id, - 'channel' => $channel->code, - 'locale' => $locale->code - ]); - - if (! $productFlat) { - $productFlat = $this->productFlatRepository->create([ - 'product_id' => $product->id, - 'channel' => $channel->code, - 'locale' => $locale->code - ]); - } - foreach ($familyAttributes[$product->attribute_family->id] as $attribute) { - if ($parentProduct && ! in_array($attribute->code, array_merge($superAttributes[$parentProduct->id], ['sku', 'name', 'price', 'weight', 'status']))) - continue; - - if (in_array($attribute->code, ['tax_category_id'])) - continue; - - if (! Schema::hasColumn('product_flat', $attribute->code)) - continue; - - if ($attribute->value_per_channel) { - if ($attribute->value_per_locale) { - $productAttributeValue = $product->attribute_values()->where('channel', $channel->code)->where('locale', $locale->code)->where('attribute_id', $attribute->id)->first(); - } else { - $productAttributeValue = $product->attribute_values()->where('channel', $channel->code)->where('attribute_id', $attribute->id)->first(); - } - } else { - if ($attribute->value_per_locale) { - $productAttributeValue = $product->attribute_values()->where('locale', $locale->code)->where('attribute_id', $attribute->id)->first(); - } else { - $productAttributeValue = $product->attribute_values()->where('attribute_id', $attribute->id)->first(); - } - } - - if ($product->type == 'configurable' && $attribute->code == 'price') { - try { - $productFlat->{$attribute->code} = app('Webkul\Bulkupload\Helpers\Price')->getVariantMinPrice($product); - } catch(\Exception $e) {} - } else { - try { - $productFlat->{$attribute->code} = $productAttributeValue[ProductAttributeValue::$attributeTypeFields[$attribute->type]]; - } catch(\Exception $e) {} - } - - if ($attribute->type == 'select') { - $attributeOption = $this->attributeOptionRepository->find($product->{$attribute->code}); - - if ($attributeOption) { - if ($attributeOptionTranslation = $attributeOption->translate($locale->code)) { - $productFlat->{$attribute->code . '_label'} = $attributeOptionTranslation->label; - } else { - $productFlat->{$attribute->code . '_label'} = $attributeOption->admin_name; - } - } - } elseif ($attribute->type == 'multiselect') { - $attributeOptionIds = explode(',', $product->{$attribute->code}); - - if (count($attributeOptionIds)) { - $attributeOptions = $this->attributeOptionRepository->findWhereIn('id', $attributeOptionIds); - - $optionLabels = []; - - foreach ($attributeOptions as $attributeOption) { - if ($attributeOptionTranslation = $attributeOption->translate($locale->code)) { - $optionLabels[] = $attributeOptionTranslation->label; - } else { - $optionLabels[] = $attributeOption->admin_name; - } - } - - $productFlat->{$attribute->code . '_label'} = implode(', ', $optionLabels); - } - } - } - - $productFlat->created_at = $product->created_at; - - $productFlat->updated_at = $product->updated_at; - - if ($parentProduct) { - $parentProductFlat = $this->productFlatRepository->findOneWhere([ - 'product_id' => $parentProduct->id, - 'channel' => $channel->code, - 'locale' => $locale->code - ]); - } - - $productFlat->parent_id = $product->parent_id; - - $productFlat->save(); - - $product->parent_id--; - } - } - } -} \ No newline at end of file diff --git a/src/Repositories/Products/DownloadableProductRepository.php b/src/Repositories/Products/DownloadableProductRepository.php deleted file mode 100644 index 827ac8c..0000000 --- a/src/Repositories/Products/DownloadableProductRepository.php +++ /dev/null @@ -1,793 +0,0 @@ -importProductRepository = $importProductRepository; - - $this->productDownloadableLinkRepository = $productDownloadableLinkRepository; - - $this->categoryRepository = $categoryRepository; - - $this->productFlatRepository = $productFlatRepository; - - $this->productRepository = $productRepository; - - $this->productImageRepository = $productImageRepository; - - $this->attributeFamilyRepository = $attributeFamilyRepository; - - $this->helperRepository = $helperRepository; - - $this->attributeOptionRepository = $attributeOptionRepository; - } - - /* - * Specify Model class name - * - * @return mixed - */ - function model() - { - return 'Webkul\Product\Contracts\Product'; - } - - /** - * create & update downloadable-type product - * - * @param array $requestData - * @param array $imageZipName - * - * @return mixed - */ - public function createProduct($requestData, $imageZipName) - { - $uploadLinkFilesZipName = null; - $uploadSampleFilesZipName = null; - $uploadLinkSampleFilesZipName = null; - - try { - $dataFlowProfileRecord = $this->importProductRepository->findOneByField - ('data_flow_profile_id', $requestData['data_flow_profile_id']); - - $csvData = (new DataGridImport)->toArray($dataFlowProfileRecord->file_path)[0]; - - $downloadableLinks = $this->extractDownloadableFiles($dataFlowProfileRecord); - - if ($requestData['totalNumberOfCSVRecord'] < 1000) { - $processCSVRecords = $requestData['totalNumberOfCSVRecord']/($requestData['totalNumberOfCSVRecord']/10); - } else { - $processCSVRecords = $requestData['totalNumberOfCSVRecord']/($requestData['totalNumberOfCSVRecord']/100); - } - - $uptoProcessCSVRecords = (int)$requestData['countOfStartedProfiles'] + 10; - $processRecords = (int)$requestData['countOfStartedProfiles'] + (int)$requestData['numberOfCSVRecord']; - - if ($requestData['numberOfCSVRecord'] > $processCSVRecords) { - for ($i = $requestData['countOfStartedProfiles']; $i < $uptoProcessCSVRecords; $i++) { - $invalidateProducts = $this->store($csvData[$i], $i, $dataFlowProfileRecord, $requestData, $imageZipName, $downloadableLinks); - - if (isset($invalidateProducts) && !empty($invalidateProducts)) { - return $invalidateProducts; - } - } - } else if ($requestData['numberOfCSVRecord'] <= 10) { - for ($i = $requestData['countOfStartedProfiles']; $i < $processRecords; $i++) { - $invalidateProducts = $this->store($csvData[$i], $i, $dataFlowProfileRecord, $requestData, $imageZipName, $downloadableLinks); - - if (isset($invalidateProducts) && !empty($invalidateProducts)) { - return $invalidateProducts; - } - } - } - - if ($requestData['numberOfCSVRecord'] > 10) { - $remainDataInCSV = (int)$requestData['numberOfCSVRecord'] - (int)$processCSVRecords; - } else { - $remainDataInCSV = 0; - - if ($requestData['errorCount'] > 0) { - $uptoProcessCSVRecords = $requestData['totalNumberOfCSVRecord'] - $requestData['errorCount']; - } else { - $uptoProcessCSVRecords = $processRecords; - } - } - - $requestData['countOfStartedProfiles'] = $i; - - $dataToBeReturn = [ - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $uptoProcessCSVRecords, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - ]; - - return $dataToBeReturn; - - } catch(\Exception $e) { - Log::error('downloadable create product log: '. $e->getMessage()); - - $categoryError = explode('[' ,$e->getMessage()); - $categorySlugError = explode(']' ,$e->getMessage()); - $requestData['countOfStartedProfiles'] = $i + 1; - $productsUploaded = $i - $requestData['errorCount']; - - if ($requestData['numberOfCSVRecord'] != 0) { - $remainDataInCSV = (int)$requestData['totalNumberOfCSVRecord'] - (int)$requestData['countOfStartedProfiles']; - } else { - $remainDataInCSV = 0; - } - - if ($categoryError[0] == "No query results for model ") { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => "Invalid Category Slug: " . $categorySlugError[1], - ); - $categoryError[0] = null; - } else if (isset($e->errorInfo)) { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $e->errorInfo[2], - ); - } else { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $e->getMessage(), - ); - } - - return $dataToBeReturn; - } - } - - /** - * function to store product - * - * @param array $csvData - * @param integer $i - * @param \Webkul\Bulkupload\Contracts\ImportProduct $dataFlowProfileRecord - * @param array $requestData - * @param array $imageZipName - * @param array $downloadableLinks - * - * @return mixed - */ - public function store($csvData, $i, $dataFlowProfileRecord, $requestData, $imageZipName, $downloadableLinks) - { - $createValidation = $this->helperRepository->createProductValidation($csvData, $i); - - if (isset($createValidation)) { - return $createValidation; - } - - $d_samples = []; - $sampleNameKey = []; - $linkNameKey = []; - $d_links = []; - - if (isset($csvData['samples_title'])) { - $csvData['sample_sort_order'] = ""; - $sampleTitles = explode(',', $csvData['samples_title']) ; - $sampleType = explode(',', $csvData['sample_type']) ; - $sampleFiles = explode(',', $csvData['sample_files']) ; - $urlFiles = explode(',', $csvData['sample_url']) ; - $sampleSortOrder = !empty($csvData['sample_sort_order']) ? explode(',', $csvData['sample_sort_order']) : 0; - } - - //for downloadable link explode - if (isset($csvData['link_titles'])) { - $linkTitles = explode(',', $csvData['link_titles']); - $linkTypes = explode(',', $csvData['link_types']); - - $linkFileNames = explode(',', $csvData['link_file_names']); - - $linkPrices = !empty($csvData['link_prices']) ? explode(',', $csvData['link_prices']) : ""; - - $linkSampleTypes = !empty($csvData['link_sample_types']) ? explode(',', $csvData['link_sample_types']) : "file"; - - $linkSampleFileNames = !empty($csvData['link_sample_file_names']) ? explode(',', $csvData['link_sample_file_names']) : ""; - - $linkDownloads = !empty($csvData['link_downloads']) ? explode(',', $csvData['link_downloads']) : 0; - - $linkSortOrders = !empty($csvData['link_sort_orders']) ? explode(',', $csvData['link_sort_orders']) : 0; - - $linkSampleUrlNames = explode(',', $csvData['link_sample_url']); - $linkUrlNames = explode(',', $csvData['link_url']); - } - - $productFlatData = $this->productFlatRepository->findWhere(['sku' => $csvData['sku'], 'url_key' => $csvData['url_key']])->first(); - - $productData = $this->productRepository->findWhere(['sku' => $csvData['sku']])->first(); - - $attributeFamilyData = $this->attributeFamilyRepository->findOneByfield(['name' => $csvData['attribute_family_name']]); - - if (! isset($productFlatData) && empty($productFlatData)) { - $data['type'] = $csvData['type']; - $data['attribute_family_id'] = $attributeFamilyData->id; - $data['sku'] = $csvData['sku']; - Event::dispatch('catalog.product.create.before'); - $downloadableProduct = $this->productRepository->create($data); - Event::dispatch('catalog.product.create.after', $downloadableProduct); - } else { - $downloadableProduct = $productData; - } - - unset($data); - $data = []; - $attributeCode = []; - $attributeValue = []; - - //default attributes - foreach ($downloadableProduct->getTypeInstance()->getEditableAttributes()->toArray() as $key => $value) { - $searchIndex = $value['code']; - if (array_key_exists($searchIndex, $csvData)) { - if (is_null($csvData[$searchIndex])) { - continue; - } - - array_push($attributeCode, $searchIndex); - - if ($searchIndex == "color" || $searchIndex == "size" || $searchIndex == "brand") { - $attributeOption = $this->attributeOptionRepository->findOneByField(['admin_name' => ucwords($csvData[$searchIndex])]); - - array_push($attributeValue, $attributeOption['id']); - } else { - array_push($attributeValue, $csvData[$searchIndex]); - } - - $data = array_combine($attributeCode, $attributeValue); - } - } - - $data['dataFlowProfileRecordId'] = $dataFlowProfileRecord->id; - - $categoryData = explode(',', $csvData['categories_slug']); - - if (is_null($csvData['categories_slug']) || empty($csvData['categories_slug'])) { - $categoryID = $this->categoryRepository->findBySlugOrFail('root')->id; - } else { - foreach ($categoryData as $key => $value) { - $categoryID[$key] = $this->categoryRepository->findBySlugOrFail($categoryData[$key])->id; - } - } - - $data['categories'] = $categoryID; - $data['channel'] = core()->getCurrentChannel()->code; - - $dataProfile = app('Webkul\Bulkupload\Repositories\DataFlowProfileRepository')->findOneByfield(['id' => $data['dataFlowProfileRecordId']]); - $data['locale'] = $dataProfile->locale_code; - - //customerGroupPricing - if (isset($csvData['customer_group_prices']) && ! empty($csvData['customer_group_prices'])) { - $data['customer_group_prices'] = json_decode($csvData['customer_group_prices'], true); - app(ProductCustomerGroupPriceRepository::class)->saveCustomerGroupPrices($data, $simpleproductData); - } - - - //prepare downloadable sample data - for ($j = 0; $j < count($sampleTitles); $j++) { - if (trim(strtolower($sampleType[$j])) == "file") { - if (isset($downloadableLinks['uploadSampleFilesZipName'])) { - if (trim(strtolower($sampleType[$j-1])) == "url") { - $sampleFileName = $sampleFiles[$j-1]; - } else { - $sampleFileName = $sampleFiles[$j]; - } - - $files = $this->fileOrUrlUpload($dataFlowProfileRecord, $sampleType[$j], $sampleFileName, $downloadableProduct->id, $downloadableLinks, $sampleFile = true); - - if (isset($files)) { - $sample['sample_'.$j] = [ - core()->getCurrentLocale()->code => [ - "title" => $sampleTitles[$j], - ], - "type" => trim($sampleType[$j]), - "file" => trim($files), - "file_name" => $sampleFileName, - "sort_order" => $sampleSortOrder[$j] ?? 0, - ]; - - array_push($sampleNameKey, 'sample_'.$j); - array_push($d_samples, $sample['sample_'.$j]); - } - } - } else if (trim(strtolower($sampleType[$j])) == "url") { - $files = $this->fileOrUrlUpload($dataFlowProfileRecord, $sampleType[$j], $urlFiles[$j], $downloadableProduct->id, $downloadableLinks, $sampleFile = true); - - if (isset($files)) { - $sample['sample_'.$j] = [ - core()->getCurrentLocale()->code => [ - "title" => $sampleTitles[$j], - ], - "type" => trim($sampleType[$j]), - "url" => trim($urlFiles[$j]), - "sort_order" => $sampleSortOrder[$j] ?? 0, - ]; - - array_push($sampleNameKey, 'sample_'.$j); - array_push($d_samples, $sample['sample_'.$j]); - } - } - } - - $combinedArray = array_combine($sampleNameKey, $d_samples); - - $data['downloadable_samples'] = $combinedArray; - - //for downloadable links - for ($j = 0; $j < count($linkTitles); $j++) { - if (trim(strtolower($linkTypes[$j])) == "file") { - if (trim(strtolower($linkSampleTypes[$j])) == "file") { - if (isset($downloadableLinks['uploadLinkSampleFilesZipName'])) { - if (trim(strtolower($linkSampleTypes[$j-1])) == "url") { - $linkSampleFile = $linkSampleFileNames[$j-1]; - } else { - $linkSampleFile = $linkSampleFileNames[$j]; - } - - $sampleFileLink = $this->fileOrUrlUpload($dataFlowProfileRecord, $linkSampleTypes[$j], $linkSampleFile, $downloadableProduct->id, $downloadableLinks, $sampleLinkfile = false); - } - } else if (trim(strtolower($linkSampleTypes[$j])) == "url") { - $sampleFileLink = $this->fileOrUrlUpload($dataFlowProfileRecord, $linkSampleTypes[$j], $linkSampleUrlNames[$j], $downloadableProduct->id, $downloadableLinks, $sampleLinkfile = false); - } - - if (isset($downloadableLinks['uploadLinkFilesZipName'])) { - if (trim(strtolower($linkSampleTypes[$j-1])) == "url") { - $linkFileName = $linkFileNames[$j-1]; - } else { - $linkFileName = $linkFileNames[$j]; - } - - $fileLink = $this->linkFileOrUrlUpload($dataFlowProfileRecord, $linkTypes[$j], $linkFileName, $downloadableProduct->id, $downloadableLinks); - } - - if (isset($fileLink)) { - $link['link_'.$j] = [ - core()->getCurrentLocale()->code => [ - "title" => $linkTitles[$j], - ], - "price" => $linkPrices[$j], - "type" => trim($linkTypes[$j]), - "file" => trim($fileLink), - "file_name" => $linkFileName, - "sample_type" => trim($linkSampleTypes[$j]), - "downloads" => $linkDownloads[$j] ?? 0, - "sort_order" => $linkSortOrders[$j] ?? 0, - ]; - - if (trim($linkSampleTypes[$j]) == "url") { - $link['link_'.$j]['sample_url'] = trim($linkSampleUrlNames[$j]); - } else if (trim($linkSampleTypes[$j]) == "file") { - $link['link_'.$j]['sample_file'] = trim($sampleFileLink); - - $link['link_'.$j]['sample_file_name'] = trim($linkSampleFile); - } - - array_push($linkNameKey, 'link_'.$j); - array_push($d_links, $link['link_'.$j]); - } - } else if (trim(strtolower($linkTypes[$j])) == "url") { - if (trim(strtolower($linkSampleTypes[$j])) == "file") { - if (isset($downloadableLinks['uploadLinkSampleFilesZipName'])) { - $sampleFileLink = $this->fileOrUrlUpload($dataFlowProfileRecord, $linkSampleTypes[$j], $linkSampleFileNames[$j], $downloadableProduct->id, $downloadableLinks, $sampleLinkfile = false); - } - } else if (trim(strtolower($linkSampleTypes[$j])) == "url") { - $sampleFileLink = $this->fileOrUrlUpload($dataFlowProfileRecord, $linkSampleTypes[$j], $linkSampleUrlNames[$j], $downloadableProduct->id, $downloadableLinks, $sampleLinkfile = false); - } - - $fileLink = $this->linkFileOrUrlUpload($dataFlowProfileRecord, $linkTypes[$j], $linkUrlNames[$j], $downloadableProduct->id, $downloadableLinks); - - if (isset($fileLink)) { - $link['link_'.$j] = [ - core()->getCurrentLocale()->code => [ - "title" => $linkTitles[$j], - ], - "price" => $linkPrices[$j], - "type" => trim($linkTypes[$j]), - "url" => trim($linkUrlNames[$j]) ?? "", - "sample_type" => trim($linkSampleTypes[$j]), - "downloads" => $linkDownloads[$j] ?? 0, - "sort_order" => $linkSortOrders[$j] ?? 0, - ]; - - if (trim($linkSampleTypes[$j]) == "url") { - $link['link_'.$j]['sample_url'] = trim($linkSampleUrlNames[$j]); - } else if (trim($linkSampleTypes[$j]) == "file") { - $link['link_'.$j]['sample_file'] = trim($sampleFileLink); - $link['link_'.$j]['sample_file_name'] = trim($linkSampleFileNames[$j]); - } - - array_push($linkNameKey, 'link_'.$j); - array_push($d_links, $link['link_'.$j]); - } - } - } - - $combinedLinksArray = array_combine($linkNameKey, $d_links); - - $data['downloadable_links'] = $combinedLinksArray; - - //Product Images - $individualProductimages = explode(',', $csvData['images']); - - if (isset($imageZipName)) { - $images = Storage::disk('local')->files('public/imported-products/extracted-images/admin/'.$dataFlowProfileRecord->id.'/'.$imageZipName['dirname'].'/'); - - foreach ($images as $imageArraykey => $imagePath) { - $imageName = explode('/', $imagePath); - - if (in_array(last($imageName), preg_replace('/[\'"]/', '',$individualProductimages))) { - $data['images'][$imageArraykey] = $imagePath; - } - } - } else if (isset($csvData['images'])) { - foreach ($individualProductimages as $imageArraykey => $imageURL) - { - if (filter_var(trim($imageURL), FILTER_VALIDATE_URL)) { - $imagePath = storage_path('app/public/imported-products/extracted-images/ admin/'.$dataFlowProfileRecord->id); - - if (!file_exists($imagePath)) { - mkdir($imagePath, 0777, true); - } - - $imageFile = $imagePath.'/'.basename($imageURL); - - file_put_contents($imageFile, file_get_contents(trim($imageURL))); - - $data['images'][$imageArraykey] = $imageFile; - } - } - } - - $validationRules = $this->helperRepository->validateCSV($requestData['data_flow_profile_id'], $data, $dataFlowProfileRecord, $downloadableProduct); - - $csvValidator = Validator::make($data, $validationRules); - - if ($csvValidator->fails()) { - $errors = $csvValidator->errors()->getMessages(); - - $this->helperRepository->deleteProductIfNotValidated($downloadableProduct->id); - - foreach($errors as $key => $error){ - if ($error[0] == "The url key has already been taken.") { - $errorToBeReturn[] = "The url key " . $data['url_key'] . " has already been taken"; - } else { - $errorToBeReturn[] = str_replace(".", "", $error[0]). " for sku " . $data['sku']; - } - } - - $requestData['countOfStartedProfiles'] = $i + 1; - - $productsUploaded = $i - $requestData['errorCount']; - - if ($requestData['numberOfCSVRecord'] != 0) { - $remainDataInCSV = (int)$requestData['totalNumberOfCSVRecord'] - (int)$requestData['countOfStartedProfiles']; - } else { - $remainDataInCSV = 0; - } - - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $errorToBeReturn, - ); - - return $dataToBeReturn; - } - - Event::dispatch('catalog.product.update.before', $downloadableProduct->id); - $configDownloadableProduct = $this->productRepository->update($data, $downloadableProduct->id); - Event::dispatch('catalog.product.update.after',$configDownloadableProduct); - - if (isset($imageZipName)) { - $this->productImageRepository->bulkuploadImages($data, $downloadableProduct, $imageZipName); - } else if (isset($csvData['images'])) { - $this->productImageRepository->bulkuploadImages($data, $downloadableProduct, $imageZipName = null); - } - } - - /** - * upload sample file link or url - * - * @param \Webkul\Bulkupload\Contracts\ImportProduct $dataFlowProfileRecord - * @param string $type - * @param string|array $file - * @param integer $id - * @param array $downloadableLinks - * @param string $flag - * - * @return mixed - */ - public function fileOrUrlUpload($dataFlowProfileRecord, $type, $file, $id, $downloadableLinks, $flag) - { - try { - if (trim($type) == "file") { - if ($flag) { - $files = "imported-products/extracted-images/admin/sample-files/".$dataFlowProfileRecord->id.'/'. $downloadableLinks['uploadSampleFilesZipName']['dirname'].'/'.trim(basename($file)); - - $destination = "product/".$id.'/'.trim(basename($file)); - - Storage::copy($files, $destination); - - return $destination; - } else { - $files = "imported-products/extracted-images/admin/link-sample-files/".$dataFlowProfileRecord->id.'/'. $downloadableLinks['uploadLinkSampleFilesZipName']['dirname'].'/'.trim(basename($file)); - - $destination = "product/".$id.'/'.trim(basename($file)); - - Storage::copy($files, $destination); - - return $destination; - } - } else { - if ($flag) { - $imagePath = storage_path('app/public/imported-products/extracted-images/admin/sample-files/'.$dataFlowProfileRecord->id); - - if (!file_exists($imagePath)) { - mkdir($imagePath, 0777, true); - } - - $imageFile = $imagePath.'/'.basename($file); - - file_put_contents($imageFile, file_get_contents(trim($file))); - - $files = "imported-products/extracted-images/admin/sample-files/".$dataFlowProfileRecord->id.'/'.basename($file); - - $destination = "product/".$id.'/'.basename($file); - Storage::copy($files, $destination); - - return $destination; - } else { - $imagePath = storage_path('app/public/imported-products/extracted-images/admin/link-sample-files/'.$dataFlowProfileRecord->id); - - if (!file_exists($imagePath)) { - mkdir($imagePath, 0777, true); - } - - $imageFile = $imagePath.'/'.basename($file); - - file_put_contents($imageFile, file_get_contents(trim($file))); - - $files = "imported-products/extracted-images/admin/link-sample-files/".$dataFlowProfileRecord->id.'/'.basename($file); - - $destination = "product/".$id.'/'.basename($file); - Storage::copy($files, $destination); - - return $destination; - } - } - } catch(\Exception $e) { - Log::error('downloadable fileOrUrlUpload log: '. $e->getMessage()); - } - } - - /** - * upload link file or url - * - * @param \Webkul\Bulkupload\Contracts\ImportProduct $dataFlowProfileRecord - * @param string $type - * @param string|array $file - * @param integer $id - * @param array $downloadableLinks - * - * @return mixed - */ - public function linkFileOrUrlUpload($dataFlowProfileRecord, $type, $file, $id, $downloadableLinks) - { - try { - if (trim($type) == "file") { - $files = "imported-products/extracted-images/admin/link-files/".$dataFlowProfileRecord->id.'/'. $downloadableLinks['uploadLinkFilesZipName']['dirname'].'/'.trim(basename($file)); - - $destination = "product_downloadable_links/".$id.'/'.basename($file); - - Storage::copy($files, $destination); - - return $destination; - } else { - $imagePath = storage_path('app/public/imported-products/extracted-images/admin/link-files/'.$dataFlowProfileRecord->id); - - if (!file_exists($imagePath)) { - mkdir($imagePath, 0777, true); - } - - $imageFile = $imagePath.'/'.basename($file); - - file_put_contents($imageFile, file_get_contents(trim($file))); - - $files = "imported-products/extracted-images/admin/link-files/".$dataFlowProfileRecord->id.'/'.basename($file); - - $destination = "product_downloadable_links/".$id.'/'.basename($file); - - Storage::copy($files, $destination); - - return $destination; - } - } catch(\Exception $e) { - Log::error('downloadable linkFileOrUrlUpload log: '. $e->getMessage()); - } - } - - /** - * unzip zip files and store in storage folder - * - * @param \Webkul\Bulkupload\Contracts\ImportProduct $record - * - * @return mixed - */ - public function extractDownloadableFiles($record) - { - if (isset($record->upload_link_files) && ($record->upload_link_files != "") ) { - $uploadLinkFilesZip = new \ZipArchive(); - - $extractedPath = storage_path('app/public/imported-products/extracted-images/admin/link-files/'.$record->id.'/'); - - if ($uploadLinkFilesZip->open(storage_path('app/public/'.$record->upload_link_files))) { - for ($i = 0; $i < $uploadLinkFilesZip->numFiles; $i++) { - $filename = $uploadLinkFilesZip->getNameIndex($i); - $uploadLinkFilesZipName = pathinfo($filename); - } - - $uploadLinkFilesZip->extractTo($extractedPath); - $uploadLinkFilesZip->close(); - } - } else { - $uploadLinkFilesZipName = null; - } - - if (isset($record->upload_sample_files) && ($record->upload_sample_files != "") ) { - $uploadSampleFilesZip = new \ZipArchive(); - - $extractedPath = storage_path('app/public/imported-products/extracted-images/admin/sample-files/'.$record->id.'/'); - - if ($uploadSampleFilesZip->open(storage_path('app/public/'.$record->upload_sample_files))) { - for ($i = 0; $i < $uploadSampleFilesZip->numFiles; $i++) { - $filename = $uploadSampleFilesZip->getNameIndex($i); - $uploadSampleFilesZipName = pathinfo($filename); - } - - $uploadSampleFilesZip->extractTo($extractedPath); - $uploadSampleFilesZip->close(); - } - } else { - $uploadSampleFilesZipName = null; - } - - if (isset($record->upload_link_sample_files) && ($record->upload_link_sample_files != "") ) { - $uploadLinkSampleFilesZip = new \ZipArchive(); - - $extractedPath = storage_path('app/public/imported-products/extracted-images/admin/link-sample-files/'.$record->id.'/'); - - if ($uploadLinkSampleFilesZip->open(storage_path('app/public/'.$record->upload_link_sample_files))) { - for ($i = 0; $i < $uploadLinkSampleFilesZip->numFiles; $i++) { - $filename = $uploadLinkSampleFilesZip->getNameIndex($i); - $uploadLinkSampleFilesZipName = pathinfo($filename); - } - - $uploadLinkSampleFilesZip->extractTo($extractedPath); - $uploadLinkSampleFilesZip->close(); - } - } else { - $uploadLinkSampleFilesZipName = null; - } - - return [ - 'uploadLinkSampleFilesZipName' => $uploadLinkSampleFilesZipName, 'uploadSampleFilesZipName' => $uploadSampleFilesZipName, - 'uploadLinkFilesZipName' => $uploadLinkFilesZipName - ]; - } -} \ No newline at end of file diff --git a/src/Repositories/Products/GroupedProductRepository.php b/src/Repositories/Products/GroupedProductRepository.php deleted file mode 100644 index 71ed05c..0000000 --- a/src/Repositories/Products/GroupedProductRepository.php +++ /dev/null @@ -1,445 +0,0 @@ -importProductRepository = $importProductRepository; - - $this->categoryRepository = $categoryRepository; - - $this->productFlatRepository = $productFlatRepository; - - $this->attributeOptionRepository = $attributeOptionRepository; - - $this->productRepository = $productRepository; - - $this->productImageRepository = $productImageRepository; - - $this->attributeFamilyRepository = $attributeFamilyRepository; - - $this->helperRepository = $helperRepository; - } - - /* - * Specify Model class name - * - * @return mixed - */ - function model() - { - return 'Webkul\Product\Contracts\Product'; - } - - /** - * create & update grouped-type product - * - * @param array $requestData - * @param array $imageZipName - * @param array $product - * - * @return mixed - */ - public function createProduct($requestData, $imageZipName) - { - try { - $dataFlowProfileRecord = $this->importProductRepository->findOneByField - ('data_flow_profile_id', $requestData['data_flow_profile_id']); - - $csvData = (new DataGridImport)->toArray($dataFlowProfileRecord->file_path)[0]; - - if ($requestData['totalNumberOfCSVRecord'] < 1000) { - $processCSVRecords = $requestData['totalNumberOfCSVRecord']/($requestData['totalNumberOfCSVRecord']/10); - } else { - $processCSVRecords = $requestData['totalNumberOfCSVRecord']/($requestData['totalNumberOfCSVRecord']/100); - } - - $uptoProcessCSVRecords = (int)$requestData['countOfStartedProfiles'] + 10; - $processRecords = (int)$requestData['countOfStartedProfiles'] + (int)$requestData['numberOfCSVRecord']; - - $inventory = []; - - if ($requestData['numberOfCSVRecord'] > $processCSVRecords) { - for ($i = $requestData['countOfStartedProfiles']; $i < $uptoProcessCSVRecords; $i++) { - $invalidateProducts = $this->store($csvData[$i], $i, $dataFlowProfileRecord, $requestData, $imageZipName); - - if (isset($invalidateProducts) && !empty($invalidateProducts)) { - return $invalidateProducts; - } - } - } else if ($requestData['numberOfCSVRecord'] <= 10) { - for ($i = $requestData['countOfStartedProfiles']; $i < $processRecords; $i++) { - $invalidateProducts = $this->store($csvData[$i], $i, $dataFlowProfileRecord, $requestData, $imageZipName); - - if (isset($invalidateProducts) && !empty($invalidateProducts)) { - return $invalidateProducts; - } - } - } - - if ($requestData['numberOfCSVRecord'] > 10) { - $remainDataInCSV = (int)$requestData['numberOfCSVRecord'] - (int)$processCSVRecords; - } else { - $remainDataInCSV = 0; - - if($requestData['errorCount'] > 0) { - $uptoProcessCSVRecords = $requestData['totalNumberOfCSVRecord'] - $requestData['errorCount']; - } else { - $uptoProcessCSVRecords = $processRecords; - } - } - - $requestData['countOfStartedProfiles'] = $i; - - $dataToBeReturn = [ - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $uptoProcessCSVRecords, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - ]; - - return $dataToBeReturn; - } catch(\Exception $e) { - Log::error('grouped create product log: '. $e->getMessage()); - - $categoryError = explode('[' ,$e->getMessage()); - $categorySlugError = explode(']' ,$e->getMessage()); - $requestData['countOfStartedProfiles'] = $i + 1; - $productsUploaded = $i - $requestData['errorCount']; - - if ($requestData['numberOfCSVRecord'] != 0) { - $remainDataInCSV = (int)$requestData['totalNumberOfCSVRecord'] - (int)$requestData['countOfStartedProfiles']; - } else { - $remainDataInCSV = 0; - } - - if ($categoryError[0] == "No query results for model ") { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => "Invalid Category Slug: " . $categorySlugError[1], - ); - $categoryError[0] = null; - } else if (isset($e->errorInfo)) { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $e->errorInfo[2], - ); - } else { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $e->getMessage(), - ); - } - - return $dataToBeReturn; - } - } - - - /** - * function to store product - * - * @param array $csvData - * @param integer $i - * @param \Webkul\Bulkupload\Contracts\ImportProduct $dataFlowProfileRecord - * @param array $requestData - * @param array $imageZipName - * - * @return mixed - */ - public function store($csvData, $i, $dataFlowProfileRecord, $requestData, $imageZipName) - { - $createValidation = $this->helperRepository->createProductValidation($csvData, $i); - - if (isset($createValidation)) { - return $createValidation; - } - - $productFlatData = $this->productFlatRepository->findWhere(['sku' => $csvData['sku'], 'url_key' => $csvData['url_key']])->first(); - - $productData = $this->productRepository->findWhere(['sku' => $csvData['sku']])->first(); - - $attributeFamilyData = $this->attributeFamilyRepository->findOneByfield(['name' => $csvData['attribute_family_name']]); - - if (! isset($productFlatData) && empty($productFlatData)) { - $data['type'] = $csvData['type']; - $data['attribute_family_id'] = $attributeFamilyData->id; - $data['sku'] = $csvData['sku']; - - Event::dispatch('catalog.product.create.before'); - $groupedProduct = $this->productRepository->create($data); - Event::dispatch('catalog.product.create.after', $groupedProduct); - } else { - $groupedProduct = $productData; - } - - unset($data); - $data = []; - $attributeCode = []; - $attributeValue = []; - - //default attributes - foreach ($groupedProduct->getTypeInstance()->getEditableAttributes()->toArray() as $key => $value) { - $searchIndex = $value['code']; - - if (array_key_exists($searchIndex, $csvData)) { - if (is_null($csvData[$searchIndex])) { - continue; - } - - array_push($attributeCode, $searchIndex); - - if ($searchIndex == "color" || $searchIndex == "size" || $searchIndex == "brand") { - $attributeOption = $this->attributeOptionRepository->findOneByField(['admin_name' => ucwords($csvData[$searchIndex])]); - - array_push($attributeValue, $attributeOption['id']); - } else { - array_push($attributeValue, $csvData[$searchIndex]); - } - - $data = array_combine($attributeCode, $attributeValue); - } - } - - $data['dataFlowProfileRecordId'] = $dataFlowProfileRecord->id; - - $categoryData = explode(',', $csvData['categories_slug']); - - if (is_null($csvData['categories_slug']) || empty($csvData['categories_slug'])) { - $categoryID = $this->categoryRepository->findBySlugOrFail('root')->id; - } else { - foreach ($categoryData as $key => $value) { - $categoryID[$key] = $this->categoryRepository->findBySlugOrFail($categoryData[$key])->id; - } - } - - $data['categories'] = $categoryID; - $data['channel'] = core()->getCurrentChannel()->code; - - $dataProfile = app('Webkul\Bulkupload\Repositories\DataFlowProfileRepository')->findOneByfield(['id' => $data['dataFlowProfileRecordId']]); - $data['locale'] = $dataProfile->locale_code; - - //customerGroupPricing - if (isset($csvData['customer_group_prices']) && ! empty($csvData['customer_group_prices'])) { - $data['customer_group_prices'] = json_decode($csvData['customer_group_prices'], true); - app(ProductCustomerGroupPriceRepository::class)->saveCustomerGroupPrices($data, $simpleproductData); - } - - //grouped product links - if (isset($csvData['grouped_product_sku'])) { - $groupedProductSku = explode(",", strtolower($csvData['grouped_product_sku'])); - $groupedQuantity = explode(",", $csvData['grouped_quantity']); - $groupedSortOrder = explode(",", $csvData['grouped_sort_order']); - - for ($j = 0; $j < count($groupedProductSku); $j++) { - $link = $j+1; - - $variants = true; - - $associatedProducts = $this->productRepository->findOneByField(['sku' => strtolower(trim($groupedProductSku[$j]))]); - - if (isset($associatedProducts) && !empty($associatedProducts)) { - if (isset($associatedProducts->parent_id)) { - $groupedLink['link_'.$link] = [ - "associated_product_id" => $associatedProducts->id, - "qty" => $groupedQuantity[$j], - "sort_order" => $groupedSortOrder[$j], - ]; - } else if ($associatedProducts->type == "simple") { - $groupedLink['link_'.$link] = [ - "associated_product_id" => $associatedProducts->id, - "qty" => $groupedQuantity[$j], - "sort_order" => $groupedSortOrder[$j], - ]; - } - } - } - - if(isset($groupedLink) && !empty($groupedLink)) { - $data['links'] = $groupedLink; - } - } - - //Product Images - $individualProductimages = explode(',', $csvData['images']); - - if (isset($imageZipName)) { - $images = Storage::disk('local')->files('public/imported-products/extracted-images/admin/'.$dataFlowProfileRecord->id.'/'.$imageZipName['dirname'].'/'); - - foreach ($images as $imageArraykey => $imagePath) { - $imageName = explode('/', $imagePath); - - if (in_array(last($imageName), preg_replace('/[\'"]/', '',$individualProductimages))) { - $data['images'][$imageArraykey] = $imagePath; - } - } - } else if (isset($csvData['images'])) { - foreach ($individualProductimages as $imageArraykey => $imageURL) - { - if (filter_var(trim($imageURL), FILTER_VALIDATE_URL)) { - $imagePath = storage_path('app/public/imported-products/extracted-images/admin/'.$dataFlowProfileRecord->id); - - if (!file_exists($imagePath)) { - mkdir($imagePath, 0777, true); - } - - $imageFile = $imagePath.'/'.basename($imageURL); - - file_put_contents($imageFile, file_get_contents(trim($imageURL))); - - $data['images'][$imageArraykey] = $imageFile; - } - } - } - - $validationRules = $this->helperRepository->validateCSV($requestData['data_flow_profile_id'], $data, $dataFlowProfileRecord, $groupedProduct); - - $csvValidator = Validator::make($data, $validationRules); - - if ($csvValidator->fails()) { - $errors = $csvValidator->errors()->getMessages(); - - $this->helperRepository->deleteProductIfNotValidated($groupedProduct->id); - - foreach ($errors as $key => $error) { - if ($error[0] == "The url key has already been taken.") { - $errorToBeReturn[] = "The url key " . $data['url_key'] . " has already been taken"; - } else { - $errorToBeReturn[] = str_replace(".", "", $error[0]). " for sku " . $data['sku']; - } - } - - $requestData['countOfStartedProfiles'] = $i + 1; - - $productsUploaded = $i - $requestData['errorCount']; - - if ($requestData['numberOfCSVRecord'] != 0) { - $remainDataInCSV = (int)$requestData['totalNumberOfCSVRecord'] - (int)$requestData['countOfStartedProfiles']; - } else { - $remainDataInCSV = 0; - } - - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $errorToBeReturn, - ); - - return $dataToBeReturn; - } - - Event::dispatch('catalog.product.update.before', $groupedProduct->id); - $configGroupedProduct = $this->productRepository->update($data, $groupedProduct->id); - Event::dispatch('catalog.product.update.after',$configGroupedProduct); - - if (isset($imageZipName)) { - $this->productImageRepository->bulkuploadImages($data, $groupedProduct, $imageZipName); - } else if (isset($csvData['images'])) { - $this->productImageRepository->bulkuploadImages($data, $groupedProduct, $imageZipName = null); - } - } -} \ No newline at end of file diff --git a/src/Repositories/Products/HelperRepository.php b/src/Repositories/Products/HelperRepository.php index 72cab73..1f8e093 100644 --- a/src/Repositories/Products/HelperRepository.php +++ b/src/Repositories/Products/HelperRepository.php @@ -2,68 +2,28 @@ namespace Webkul\Bulkupload\Repositories\Products; -use Illuminate\Container\Container as App; use Webkul\Core\Eloquent\Repository; use Illuminate\Support\Facades\Validator; use Webkul\Product\Models\ProductAttributeValue; -use Webkul\Product\Repositories\ProductRepository; -use Webkul\Product\Repositories\ProductFlatRepository; -use Webkul\Bulkupload\Repositories\DataFlowProfileRepository; -use Webkul\Product\Repositories\ProductAttributeValueRepository; +use Webkul\Admin\Validations\ProductCategoryUniqueSlug; +use Webkul\Product\Repositories\{ProductRepository, ProductFlatRepository, ProductAttributeValueRepository}; class HelperRepository extends Repository { - /** - * DataFlowProfileRepository object - * - * @var \Webkul\Bulkupload\Repositories\DataFlowProfileRepository - */ - protected $dataFlowProfileRepository; - - /** - * ProductFlatRepository object - * - * @var \Webkul\Product\Repositories\ProductFlatRepository - */ - protected $productFlatRepository; - - /** - * ProductRepository object - * - * @var \Webkul\Product\Repositories\ProductRepository - */ - protected $productRepository; - - /** - * ProductAttributeValueRepository object - * - * @var \Webkul\Product\Repositories\ProductAttributeValueRepository - */ - protected $productAttributeValueRepository; - /** * Create a new repository instance. * - * @param \Webkul\Bulkupload\Repositories\DataFlowProfileRepository $dataFlowProfileRepository - * @param \Webkul\Product\Repositories\ProductAttributeValueRepository $productAttributeValueRepository - * @param \Webkul\Product\Repositories\ProductFlatRepository $productFlatRepository * @param \Webkul\Product\Repositories\ProductRepository $productRepository + * @param \Webkul\Product\Repositories\ProductFlatRepository $productFlatRepository + * @param \Webkul\Product\Repositories\ProductAttributeValueRepository $productAttributeValueRepository * @return void */ public function __construct( - DataFlowProfileRepository $dataFlowProfileRepository, - ProductAttributeValueRepository $productAttributeValueRepository, - ProductFlatRepository $productFlatRepository, - ProductRepository $productRepository + protected ProductRepository $productRepository, + protected ProductFlatRepository $productFlatRepository, + protected ProductAttributeValueRepository $productAttributeValueRepository, ) { - $this->dataFlowProfileRepository = $dataFlowProfileRepository; - - $this->productAttributeValueRepository = $productAttributeValueRepository; - - $this->productFlatRepository = $productFlatRepository; - - $this->productRepository = $productRepository; } /** @@ -81,77 +41,53 @@ function model() * * @param integer $dataFlowProfileId * @param array $records - * @param \Webkul\Bulkupload\Contracts\ImportProduct $dataFlowProfileRecord * @param \Webkul\Product\Contracts\Product $product * @return array */ - public function validateCSV($dataFlowProfileId, $records, $dataFlowProfileRecord, $product) + public function validateCSV($product) { - $messages = []; - $rules = []; - - $profiler = $this->dataFlowProfileRepository->findOneByField('id', $dataFlowProfileId); - - if ($dataFlowProfileRecord) { - foreach($records as $data) { - $this->rules = array_merge($product->getTypeInstance()->getTypeValidationRules(), [ - 'sku' => ['required', 'unique:products,sku,' . $product->id, new \Webkul\Core\Contracts\Validations\Slug], - 'special_price_from' => 'nullable|date', - 'special_price_to' => 'nullable|date|after_or_equal:special_price_from', - 'special_price' => ['nullable', new \Webkul\Core\Contracts\Validations\Decimal, 'lt:price'], - ]); - - foreach ($product->getEditableAttributes() as $attribute) { - if ($attribute->code == 'sku' || $attribute->type == 'boolean') { - continue; - } - - $validations = []; - - if (! isset($this->rules[$attribute->code])) { - array_push($validations, $attribute->is_required ? 'required' : 'nullable'); - } else { - $validations = $this->rules[$attribute->code]; - } - - if ($attribute->type == 'text' && $attribute->validation) { - array_push($validations, - $attribute->validation == 'decimal' - ? new \Webkul\Core\Contracts\Validations\Decimal - : $attribute->validation - ); - } + // Initialize rules with type validation rules + $this->rules = array_merge($product->getTypeInstance()->getTypeValidationRules(), [ + 'sku' => ['required', 'unique:products,sku,' . $product->id, new \Webkul\Core\Contracts\Validations\Slug], + 'url_key' => ['required', new ProductCategoryUniqueSlug('products', $product->id)], + 'special_price_from' => 'nullable|date', + 'special_price_to' => 'nullable|date|after_or_equal:special_price_from', + 'special_price' => ['nullable', new \Webkul\Core\Contracts\Validations\Decimal, 'lt:price'], + ]); + + foreach ($product->getEditableAttributes() as $attribute) { + if ($attribute->code == 'sku' || $attribute->type == 'boolean') { + continue; + } - if ($attribute->type == 'price') { - array_push($validations, new \Webkul\Core\Contracts\Validations\Decimal); - } + // Initialize validations with required or nullable based on attribute settings + $validations = [$attribute->is_required ? 'required' : 'nullable']; - if ($attribute->is_unique) { - $this->id = $product; + if ($attribute->type == 'text' && $attribute->validation) { + // Add custom validation rules if applicable + $validations[] = $attribute->validation == 'decimal' ? new \Webkul\Core\Contracts\Validations\Decimal : $attribute->validation; + } - array_push($validations, function ($field, $value, $fail) use ($attribute) { - $column = ProductAttributeValue::$attributeTypeFields[$attribute->type]; + if ($attribute->type == 'price') { + // Add decimal validation for price attributes + $validations[] = new \Webkul\Core\Contracts\Validations\Decimal; + } - if (! $this->productAttributeValueRepository->isValueUnique($this->id, $attribute->id, $column, request($attribute->code))) { - $fail('The :attribute has already been taken.'); - } - }); + if ($attribute->is_unique) { + // Add unique validation for unique attributes + $validations[] = function ($field, $value, $fail) use ($attribute, $product) { + $column = ProductAttributeValue::$attributeTypeFields[$attribute->type]; + if (! $this->productAttributeValueRepository->isValueUnique($product, $attribute->id, $column, request($attribute->code))) { + $fail('The :attribute has already been taken.'); } - - $this->rules[$attribute->code] = $validations; - } - - $validationCheckForUpdateData = $this->productFlatRepository - ->findWhere(['sku' => $records['sku'], 'url_key' => $records['url_key']]); - - if (is_null($validationCheckForUpdateData) || empty($validationCheckForUpdateData)) { - $urlKeyUniqueness = "unique:product_flat,url_key"; - array_push($this->rules["url_key"], $urlKeyUniqueness); - } - - return $this->rules; + }; } + + // Assign validations to the rules array + $this->rules[$attribute->code] = $validations; } + + return $this->rules; } /** @@ -173,41 +109,21 @@ public function deleteProductIfNotValidated($id) * @return void */ public function createProductValidation($record, $loopCount) - { + { try { $validateProduct = Validator::make($record, [ 'type' => 'required', - 'sku' => 'required', - 'attribute_family_name' => 'required' + 'sku' => 'required' ]); - if ( $validateProduct->fails() ) { - $errors = $validateProduct->errors()->getMessages(); - - foreach($errors as $key => $error) { - $recordCount = (int)$loopCount + (int)1; - - $errorToBeReturn[] = str_replace(".", "", $error[0]) . " for record " . $recordCount; - } - - request()->countOfStartedProfiles = $loopCount + 1; - - $productsUploaded = $loopCount - request()->errorCount; - - if (request()->numberOfCSVRecord != 0) { - $remainDataInCSV = (int)request()->totalNumberOfCSVRecord - (int)request()->countOfStartedProfiles; - } else { - $remainDataInCSV = 0; - } - - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => request()->countOfStartedProfiles, - 'error' => $errorToBeReturn, - ); + if ($validateProduct->fails()) { + $errors = $validateProduct->errors()->all(); + $recordCount = (int)$loopCount + 1; + $errorToBeReturn = array_map(function ($error) use ($recordCount) { + return str_replace(".", "", $error) . " for record " . $recordCount; + }, $errors); - return $dataToBeReturn; + return ['error' => $errorToBeReturn]; } return null; diff --git a/src/Repositories/Products/SimpleProductRepository.php b/src/Repositories/Products/SimpleProductRepository.php index 8a4227f..1b6327e 100644 --- a/src/Repositories/Products/SimpleProductRepository.php +++ b/src/Repositories/Products/SimpleProductRepository.php @@ -2,132 +2,48 @@ namespace Webkul\Bulkupload\Repositories\Products; +use Log; use Storage; -use Illuminate\Container\Container as App; -use Webkul\Admin\Imports\DataGridImport; -use Illuminate\Support\Facades\Validator; -use Webkul\Core\Eloquent\Repository; -use Illuminate\Support\Facades\Event; +use Illuminate\Support\Facades\{Event, Validator}; +use Webkul\Core\Eloquent\Repository as BaseRepository; +use Webkul\Attribute\Repositories\{AttributeFamilyRepository, AttributeOptionRepository}; use Webkul\Category\Repositories\CategoryRepository; -use Webkul\Bulkupload\Repositories\ImportProductRepository; -use Webkul\Product\Repositories\ProductFlatRepository; use Webkul\Inventory\Repositories\InventorySourceRepository; -use Webkul\Product\Repositories\ProductRepository; -use Webkul\Attribute\Repositories\AttributeFamilyRepository; +use Webkul\Product\Repositories\{ProductCustomerGroupPriceRepository, ProductRepository}; +use Webkul\Bulkupload\Repositories\{ImportProductRepository, ProductImageRepository}; use Webkul\Bulkupload\Repositories\Products\HelperRepository; -use Webkul\Attribute\Repositories\AttributeOptionRepository; -use Webkul\Bulkupload\Repositories\ProductImageRepository; -use Webkul\Product\Repositories\ProductCustomerGroupPriceRepository; -class SimpleProductRepository extends Repository +class SimpleProductRepository extends BaseRepository { - /** - * ImportProductRepository object - * - * @var \Webkul\Bulkupload\Repositories\ImportProductRepository - */ - protected $importProductRepository; - - /** - * CategoryRepository object - * - * @var \Webkul\Category\Repositories\CategoryRepository - */ - protected $categoryRepository; - - /** - * ProductFlatRepository object - * - * @var \Webkul\Product\Repositories\ProductFlatRepository - */ - protected $productFlatRepository; - - /** - * ProductRepository object - * - * @var \Webkul\Product\Repositories\ProductRepository - */ - protected $productRepository; - - /** - * AttributeFamilyRepository object - * - * @var \Webkul\Attribute\Repositories\AttributeFamilyRepository - */ - protected $attributeFamilyRepository; - - /** - * HelperRepository object - * - * @var \Webkul\Bulkupload\Repositories\Products\HelperRepository - */ - protected $helperRepository; - - /** - * ProductImageRepository object - * - * @var \Webkul\Bulkupload\Repositories\ProductImageRepository - */ - protected $productImageRepository; - - /** - * AttributeOptionRepository object - * - * @var \Webkul\Attribute\Repositories\AttributeOptionRepository - */ - protected $attributeOptionRepository; + protected $errors = []; - /** - * InventorySourceRepository object - * - * @var \Webkul\Inventory\Repositories\InventorySourceRepository - */ - protected $inventorySourceRepository; + protected $dataNotInserted = []; /** * Create a new repository instance. * - * @param \Webkul\Bulkupload\Repositories\ImportProductRepository $importProductRepository + * @param \Webkul\Attribute\Repositories\AttributeFamilyRepository $attributeFamilyRepository * @param \Webkul\Attribute\Repositories\AttributeOptionRepository $attributeOptionRepository * @param \Webkul\Category\Repositories\CategoryRepository $categoryRepository - * @param \Webkul\Product\Repositories\ProductFlatRepository $productFlatRepository * @param \Webkul\Product\Repositories\ProductRepository $productRepository - * @param \Webkul\Attribute\Repositories\AttributeFamilyRepository $attributeFamilyRepository - * @param \Webkul\Bulkupload\Repositories\Products\HelperRepository $helperRepository - * @param \Webkul\Bulkupload\Repositories\ProductImageRepository $productImageRepository * @param \Webkul\Inventory\Repositories\InventorySourceRepository $inventorySourceRepository + * @param \Webkul\Bulkupload\Repositories\ImportProductRepository $importProductRepository + * @param \Webkul\Bulkupload\Repositories\ProductImageRepository $productImageRepository + * @param \Webkul\Bulkupload\Repositories\Products\HelperRepository $helperRepository * * @return void */ public function __construct( - ImportProductRepository $importProductRepository, - AttributeOptionRepository $attributeOptionRepository, - CategoryRepository $categoryRepository, - ProductFlatRepository $productFlatRepository, - ProductRepository $productRepository, - AttributeFamilyRepository $attributeFamilyRepository, - HelperRepository $helperRepository, - ProductImageRepository $productImageRepository, - InventorySourceRepository $inventorySourceRepository + protected AttributeFamilyRepository $attributeFamilyRepository, + protected AttributeOptionRepository $attributeOptionRepository, + protected CategoryRepository $categoryRepository, + protected ProductRepository $productRepository, + protected InventorySourceRepository $inventorySourceRepository, + protected ImportProductRepository $importProductRepository, + protected ProductImageRepository $productImageRepository, + protected HelperRepository $helperRepository, ) { - $this->importProductRepository = $importProductRepository; - - $this->categoryRepository = $categoryRepository; - - $this->attributeOptionRepository = $attributeOptionRepository; - - $this->productFlatRepository = $productFlatRepository; - - $this->productRepository = $productRepository; - - $this->productImageRepository = $productImageRepository; - - $this->attributeFamilyRepository = $attributeFamilyRepository; - - $this->helperRepository = $helperRepository; - - $this->inventorySourceRepository = $inventorySourceRepository; } /* @@ -143,315 +59,647 @@ function model() /** * create & update simple-type product * - * @param array $requestData * @param array $imageZipName - * @param array $product + * @param array $dataFlowProfileRecord + * @param array $csvData + * @param int $key * * @return mixed */ - public function createProduct($requestData, $imageZipName, $product) + public function createProduct($imageZipName, $dataFlowProfileRecord, $csvData, $key) { + + try { - $inventory = []; + //Validation + $createValidation = $this->helperRepository->createProductValidation($csvData, $key); + + if (isset($createValidation)) { - $dataFlowProfileRecord = $this->importProductRepository->findOneByField - ('data_flow_profile_id', $requestData['data_flow_profile_id']); + return $createValidation; + } - $csvData = (new DataGridImport)->toArray($dataFlowProfileRecord->file_path)[0]; + $createProduct = [ + 'sku' => $csvData['sku'], + 'type' => $csvData['type'], + 'attribute_family_id' => $dataFlowProfileRecord->profiler->attribute_family_id, + ]; - if ($requestData['totalNumberOfCSVRecord'] < 1000) { - $processCSVRecords = $requestData['totalNumberOfCSVRecord']/($requestData['totalNumberOfCSVRecord']/10); - } else { - $processCSVRecords = $requestData['totalNumberOfCSVRecord']/($requestData['totalNumberOfCSVRecord']/100); + if ($csvData['type'] == 'configurable') { + $superAttributes['super_attributes'] = $csvData['super_attributes']; + + if (! isset($superAttributes['super_attributes']) || empty($superAttributes['super_attributes'])) { + return [ + 'error' => [trans('admin::app.catalog.products.configurable-error')], + ]; + } + + $createProduct['super_attributes'] = $superAttributes['super_attributes']; } - $uptoProcessCSVRecords = (int)$requestData['countOfStartedProfiles'] + 10; + // Check for Duplicate SKU + $product = $this->productRepository->firstWhere('sku', $csvData['sku']); - $processRecords = (int)$requestData['countOfStartedProfiles'] + (int)$requestData['numberOfCSVRecord']; + if ($product && $product->type != $csvData['type']) { + return [ + 'error' => ["Duplicate entry for sku {$product->sku}"], + ]; + } + // Create Product + if (! $product) { - if ($requestData['numberOfCSVRecord'] > $processCSVRecords) { - for ($i = $requestData['countOfStartedProfiles']; $i < $uptoProcessCSVRecords; $i++) { - $invalidateProducts = $this->store($csvData[$i], $i, $dataFlowProfileRecord, $requestData, $imageZipName); + Event::dispatch('catalog.product.create.before'); - if (isset($invalidateProducts) && !empty($invalidateProducts)) { - return $invalidateProducts; - } - } - } else if ($requestData['numberOfCSVRecord'] <= 10) { - for ($i = $requestData['countOfStartedProfiles']; $i < $processRecords; $i++) { - $invalidateProducts = $this->store($csvData[$i], $i, $dataFlowProfileRecord, $requestData, $imageZipName); + $product = $this->productRepository->create($createProduct); + + Event::dispatch('catalog.product.create.after', $product); + } + + // store uploaded product in session + if (! empty($product)) { + $uploadedProduct = [ + 'id' => $product->id, + 'sku' => $product->sku, + 'type' => $product->type + ]; + + session()->push('uploadedProduct', $uploadedProduct); + } - if (isset($invalidateProducts) && !empty($invalidateProducts)) { - return $invalidateProducts; - } - } + // Process product attributes + $data = $this->processProductAttributes($csvData, $product); + + // Process inventory + if ($product->type == 'simple' || $product->type != 'virtual') { + $this->processProductInventory($csvData, $data); } - if ($requestData['numberOfCSVRecord'] > 10) { - $remainDataInCSV = (int)$requestData['numberOfCSVRecord'] - (int)$processCSVRecords; - } else { - $remainDataInCSV = 0; + // Process categories + $categories = $this->processProductCategories($csvData); - if($requestData['errorCount'] > 0) { - $uptoProcessCSVRecords = $requestData['totalNumberOfCSVRecord'] - $requestData['errorCount']; - } else { - $uptoProcessCSVRecords = $processRecords; + if (isset($categories[0]['error'])) { + $this->helperRepository->deleteProductIfNotValidated($product->id); + + return $categories[0]; + } + + $data['categories'] = $categories; + $data['locale'] = $dataFlowProfileRecord->profiler->locale_code; + $data['channel'] = core()->getCurrentChannel()->code; + + + // Process customer group pricing + $this->processCustomerGroupPricing($csvData, $data, $product); + + // Process product images + $data['images'] = $this->processProductImages($csvData, $imageZipName, $dataFlowProfileRecord); + + if ($product->type == 'downloadable' && isset($csvData['link_titles'])) { + $downloadableLinks = $this->addLinksAndSamples($csvData, $dataFlowProfileRecord, $product); + + if (isset($downloadableLinks['error'])) { + $this->helperRepository->deleteProductIfNotValidated($product->id); + + return $downloadableLinks; } + + $data['downloadable_links'] = $downloadableLinks; } - $requestData['countOfStartedProfiles'] = $i; + if ($product->type == 'downloadable' && isset($csvData['samples_title'])) { + $downloadableSamples = $this->addSamples($csvData, $dataFlowProfileRecord, $product); - $dataToBeReturn = [ - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $uptoProcessCSVRecords, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - ]; + if (isset($downloadableSamples['error'])) { + $this->helperRepository->deleteProductIfNotValidated($product->id); - return $dataToBeReturn; - } catch (\Exception $e) { - Log::error('simple create product log: '. $e->getMessage()); + return $downloadableSamples; + } - $categoryError = explode('[' ,$e->getMessage()); - $categorySlugError = explode(']' ,$e->getMessage()); - $requestData['countOfStartedProfiles'] = $i + 1; - $productsUploaded = $i - $requestData['errorCount']; + $data['downloadable_samples'] = $downloadableSamples; + } - if ($requestData['numberOfCSVRecord'] != 0) { - $remainDataInCSV = (int)$requestData['totalNumberOfCSVRecord'] - (int)$requestData['countOfStartedProfiles']; - } else { - $remainDataInCSV = 0; + //prepare bundle options + if (isset($csvData['bundle_options'])) { + $bundleOptions = json_decode($csvData['bundle_options'], true); + + $data['bundle_options'] = $bundleOptions; } - if ($categoryError[0] == "No query results for model ") { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => "Invalid Category Slug: " . $categorySlugError[1], - ); - $categoryError[0] = null; - } else if (isset($e->errorInfo)) { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $e->errorInfo[2], - ); - } else { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $e->getMessage(), - ); + // //grouped product links + if (isset($csvData['grouped_options'])) { + $groupedOptions = json_decode($csvData['grouped_options'], true); + + $data['links'] = $groupedOptions; + } + + // Validate product data and handle errors + $validationErrors = $this->validateProductData($data, $product); + if ($validationErrors) { + $this->helperRepository->deleteProductIfNotValidated($product->id); + + return $validationErrors; } - return $dataToBeReturn; + Event::dispatch('catalog.product.update.before', $product->id); + + $productFlat = $this->productRepository->update($data, $product->id); + + Event::dispatch('catalog.product.update.after', $productFlat); + + + // Upload images + if (isset($imageZipName) || (!empty($csvData['images']))) { + $imageZip = $imageZipName ?? null; + $this->productImageRepository->bulkuploadImages($data, $productFlat, $imageZip, $dataFlowProfileRecord->id); + } + } catch(\Exception $e) { + Log::error('simple product store function '. $e->getMessage()); } } - /** - * function to store product - * - * @param array $csvData - * @param integer $i - * @param \Webkul\Bulkupload\Contracts\ImportProduct $dataFlowProfileRecord - * @param array $requestData - * @param array $imageZipName - * - * @return mixed - */ - public function store($csvData, $i, $dataFlowProfileRecord, $requestData, $imageZipName) + // Process product attributes and return data array + private function processProductAttributes($csvData, $product) { - try { - $createValidation = $this->helperRepository->createProductValidation($csvData, $i); + $data = []; + $attributeCode = []; + $attributeValue = []; - if (isset($createValidation)) { - return $createValidation; + $attributes = $product->getTypeInstance()->getEditableAttributes()->toArray(); + + foreach ($attributes as $attribute) { + $searchIndex = strtolower($attribute['code']); + + $csvValue = $csvData[$searchIndex] ?? null; + + if (is_null($csvData)) { + continue; } - $productFlatData = $this->productFlatRepository->findWhere(['sku' => $csvData['sku'], 'url_key' => $csvData['url_key']])->first(); + $attributeCode[] = $searchIndex; - $productData = $this->productRepository->findWhere(['sku' => $csvData['sku']])->first(); + switch ($attribute['type']) { + case "select": + $attributeOption = $this->attributeOptionRepository->findOneByField(['admin_name' => $csvValue]); - $attributeFamilyData = $this->attributeFamilyRepository->findOneByfield(['name' => $csvData['attribute_family_name']]); + $attributeValue[] = ($attributeOption !== null) ? $attributeOption['id'] : null; - if (! isset($productFlatData) && empty($productFlatData)) { - $data['type'] = $csvData['type']; - $data['attribute_family_id'] = $attributeFamilyData->id; - $data['sku'] = $csvData['sku']; + break; - Event::dispatch('catalog.product.create.before'); - $simpleproductData = $this->productRepository->create($data); - Event::dispatch('catalog.product.create.after', $simpleproductData); - } else { - $simpleproductData = $productData; - } + case "checkbox": + $attributeOption = $this->attributeOptionRepository->findOneByField(['attribute_id' => $attribute['id'], 'admin_name' => $csvValue]); - unset($data); - $data = []; - $attributeCode = []; - $attributeValue = []; + $attributeValue[] = ($attributeOption !== null) ? $attributeOption['id'] : null; - //default attributes - foreach ($simpleproductData->getTypeInstance()->getEditableAttributes()->toArray() as $key => $value) { - $attributeOptionArray = array(); - $searchIndex = strtolower($value['code']); + break; - if (array_key_exists($searchIndex, $csvData)) { + case in_array($searchIndex, ["color", "size", "brand"]): + $attributeOption = $this->attributeOptionRepository->findOneByField(['admin_name' => ucwords($csvValue)]); - if (is_null($csvData[$searchIndex])) { - continue; + $attributeValue[] = ($attributeOption !== null) ? $attributeOption['id'] : null; + + break; + + default: + if ($searchIndex == 'url_key') { + $csvValue = strtolower($csvValue); } - array_push($attributeCode, $searchIndex); + $attributeValue[] = $csvValue; + break; + } - if ($value['type'] == "select") { - $attributeOption = $this->attributeOptionRepository->findOneByField(['admin_name' => $csvData[$searchIndex]]); + $data = array_combine($attributeCode, $attributeValue); + } - array_push($attributeValue, $attributeOption['id']); - } else if ($value['type'] == "checkbox") { - $attributeOption = $this->attributeOptionRepository->findOneByField(['attribute_id' => $value['id'], 'admin_name' => $csvData[$searchIndex]]); + return $data; + } - array_push($attributeOptionArray, $attributeOption['id']); + // Process product inventory data and update $data array + private function processProductInventory($csvData, &$data) + { + $inventoryCode = preg_split('/,\s*|,/', $csvData['inventory_sources']); - array_push($attributeValue, $attributeOptionArray); - unset($attributeOptionArray); - } else { - array_push($attributeValue, $csvData[$searchIndex]); - } + $inventoryId = $this->inventorySourceRepository->whereIn('code', $inventoryCode)->pluck('id')->toArray(); - $data = array_combine($attributeCode, $attributeValue); + $inventoryData = preg_split('/,\s*|,/', $csvData['inventories']); + + if (count($inventoryId) != count($inventoryData)) { + $inventoryData = array_fill(0, count($inventoryId), 0); + } + + $data['inventories'] = array_combine($inventoryId, $inventoryData);; + } + + // Process product categories and update $data array + private function processProductCategories($csvData) + { + if (is_null($csvData['categories_slug']) || empty($csvData['categories_slug'])) { + $categoryID = $this->categoryRepository->findBySlugOrFail('root')->id; + } else { + $categoryData = preg_split('/,\s*|,/', $csvData['categories_slug']); + + $categoryID = array_map(function ($value) { + try { + return $this->categoryRepository->findBySlugOrFail(strtolower($value))->id; + + } catch(\Exception $e) { + return [ + 'error' => ['category not found', $e->getMessage()], + ]; } - } + }, $categoryData); + } - $data['dataFlowProfileRecordId'] = $dataFlowProfileRecord->id; + return $categoryID; + } - $inventorySource = $csvData['inventory_sources']; - $inventoryCode = explode(',', $inventorySource); + // Process customer group pricing and update $data array + private function processCustomerGroupPricing($csvData, &$data, $product) + { + if (isset($csvData['customer_group_prices']) && ! empty($csvData['customer_group_prices'])) { + $data['customer_group_prices'] = json_decode($csvData['customer_group_prices'], true); + app(ProductCustomerGroupPriceRepository::class)->saveCustomerGroupPrices($data, $product); + } + } - foreach ($inventoryCode as $key => $value) { - $inventoryId = $this->inventorySourceRepository->findOneByfield(['code' => trim($value)])->pluck('id')->toArray(); - } + // Process product images and update $data array + private function processProductImages($csvData, $imageZipName, $dataFlowProfileRecord) + { + $individualProductimages = preg_split('/,\s*|,/', $csvData['images']); + $productImages = []; + + if (isset($imageZipName)) { + $imagePath = 'public/imported-products/extracted-images/admin/' . $dataFlowProfileRecord->id . '/' . $imageZipName['dirname'] . '/'; - $inventoryData[] = (string)$csvData['inventories']; + $images = Storage::disk('local')->files($imagePath); - foreach ($inventoryData as $key => $d) { - $inventoryQuantity = explode(',', trim($d)); + foreach ($images as $imageArraykey => $imagePath) { + $imageName = explode('/', $imagePath); - if (count($inventoryId) != count($inventoryQuantity)) { - array_push($inventoryQuantity, "0"); + if (in_array(last($imageName), preg_replace('/[\'"]/', '',$individualProductimages))) { + $productImages[$imageArraykey] = $imagePath; } + } + } else if (isset($csvData['images'])) { + foreach ($individualProductimages as $imageArraykey => $imageURL) + { + if (filter_var(trim($imageURL), FILTER_VALIDATE_URL)) { + $imagePath = storage_path('app/public/imported-products/extracted-images/admin/'.$dataFlowProfileRecord->id); + + if (! file_exists($imagePath)) { + mkdir($imagePath, 0777, true); + } + + $imageFile = $imagePath . '/' . basename($imageURL); + + file_put_contents($imageFile, file_get_contents(trim($imageURL))); - $inventory = array_combine($inventoryId, $inventoryQuantity); + $productImages[$imageArraykey] = $imageFile; + } } + } - $data['inventories'] = $inventory; + return $productImages; + } - $categoryData = explode(',', $csvData['categories_slug']); + // Validate product data and handle errors + private function validateProductData($data, $product) + { + $returnRules = $this->helperRepository->validateCSV($product); + $csvValidator = Validator::make($data, $returnRules); - if (is_null($csvData['categories_slug']) || empty($csvData['categories_slug'])) { - $categoryID = $this->categoryRepository->findBySlugOrFail('root')->id; - } else { - foreach ($categoryData as $key => $value) { - $categoryID[$key] = $this->categoryRepository->findBySlugOrFail($categoryData[$key])->id; + if ($csvValidator->fails()) { + $errors = $csvValidator->errors()->getMessages(); + + $errorToBeReturn = []; + + foreach ($errors as $error) { + if ($error[0] == "The url key has already been taken.") { + $errorToBeReturn[] = "The url key " . $data['url_key'] . " has already been taken"; + } else { + $errorToBeReturn[] = str_replace(".", "", $error[0]) . " for sku " . $data['sku']; } } - $data['categories'] = $categoryID; - $data['channel'] = core()->getCurrentChannel()->code; + return [ + 'error' => $errorToBeReturn, + ]; + } - $dataProfile = app('Webkul\Bulkupload\Repositories\DataFlowProfileRepository')->findOneByfield(['id' => $data['dataFlowProfileRecordId']]); + return null; // No validation errors + } + + public function addLinksAndSamples($csvData, $dataFlowProfileRecord, $product) + { + $downloadableLinks = $this->extractDownloadableFiles($dataFlowProfileRecord); + + // Initialize arrays to store downloadable links + $linkNameKey = []; + $d_links = []; + + $linkDataKeys = [ + 'link_titles', + 'link_prices', + 'link_types', + 'link_url', + 'link_file_names', + 'link_downloads', + 'link_sort_orders', + 'link_sample_types', + 'link_sample_url', + 'link_sample_file_names', + ]; + + $linkData = []; + + foreach ($linkDataKeys as $key) { + $linkData[$key] = preg_split('/,\s*|,/', $csvData[$key]); + } - $data['locale'] = $dataProfile->locale_code; + // Ensure that all link data arrays have the same length + $dataLengths = array_map('count', $linkData); + $uniqueLengths = array_unique($dataLengths); - //customerGroupPricing - if (isset($csvData['customer_group_prices']) && ! empty($csvData['customer_group_prices'])) { - $data['customer_group_prices'] = json_decode($csvData['customer_group_prices'], true); - app(ProductCustomerGroupPriceRepository::class)->saveCustomerGroupPrices($data, $simpleproductData); + if (! (count($uniqueLengths) === 1)) { + return [ + 'error' => ["Please provide correct value for Lnik, Sample Link realted field for sku: {$product->sku}"], + ]; + } + + $dataLength = reset($uniqueLengths); + + // Loop through the downloadable links data + for ($index = 0; $index < $dataLength; $index++) { + $linkTitle = $linkData['link_titles'][$index]; + $linkType = trim(strtolower($linkData['link_types'][$index])); + $linkSampleType = trim(strtolower($linkData['link_sample_types'][$index])); + + // Determine the file link or URL for the link + $fileLink = $this->linkFileOrUrlUpload( + $dataFlowProfileRecord, + $linkType, + ($linkType == "url") ? $linkData['link_url'][$index] : $linkData['link_file_names'][$index], + $product->id, + $downloadableLinks + ); + + // Determine the sample file or URL for the link + $sampleFileLink = $this->fileOrUrlUpload( + $dataFlowProfileRecord, + $linkSampleType, + ($linkSampleType == "url") ? $linkData['link_sample_url'][$index] : $linkData['link_sample_file_names'][$index], + $product->id, + $downloadableLinks, + false + ); + + // Create the downloadable link array + $link['link_' . $index] = [ + core()->getCurrentLocale()->code => [ + "title" => $linkTitle, + ], + "price" => isset($linkData['link_prices'][$index]) ? $linkData['link_prices'][$index] : "", + "type" => trim($linkData['link_types'][$index]), + "sample_type" => trim($linkData['link_sample_types'][$index]), + "downloads" => isset($linkData['link_downloads'][$index]) ? $linkData['link_downloads'][$index] : 0, + "sort_order" => isset($linkData['link_sort_orders'][$index]) ? $linkData['link_sort_orders'][$index] : 0, + ]; + + if (trim($linkData['link_types'][$index]) == "url") { + $link['link_' . $index]['url'] = trim($fileLink); + } elseif (trim($linkData['link_types'][$index]) == "file" && isset($fileLink)) { + $link['link_' . $index]['file'] = trim($fileLink); + $link['link_' . $index]['file_name'] = trim($linkData['link_file_names'][$index]); } - //Product Images - $individualProductimages = explode(',', $csvData['images']); + if (trim($linkData['link_sample_types'][$index]) == "url") { + $link['link_' . $index]['sample_url'] = trim($linkData['link_sample_url'][$index]); + } elseif (trim($linkData['link_sample_types'][$index]) == "file" && isset($sampleFileLink)) { + $link['link_' . $index]['sample_file'] = trim($sampleFileLink); + $link['link_' . $index]['sample_file_name'] = trim($linkData['link_sample_file_names'][$index]); + } - if (isset($imageZipName)) { - $images = Storage::disk('local')->files('public/imported-products/extracted-images/admin/'.$dataFlowProfileRecord->id.'/'.$imageZipName['dirname'].'/'); + array_push($linkNameKey, 'link_' . $index); + array_push($d_links, $link['link_' . $index]); + } - foreach ($images as $imageArraykey => $imagePath) { - $imageName = explode('/', $imagePath); + $combinedLinksArray = array_combine($linkNameKey, $d_links); - if (in_array(last($imageName), preg_replace('/[\'"]/', '',$individualProductimages))) { - $data['images'][$imageArraykey] = $imagePath; - } - } - } else if (isset($csvData['images'])) { - foreach ($individualProductimages as $imageArraykey => $imageURL) - { - if (filter_var(trim($imageURL), FILTER_VALIDATE_URL)) { - $imagePath = storage_path('app/public/imported-products/extracted-images/admin/'.$dataFlowProfileRecord->id); + return $combinedLinksArray; + } - if (!file_exists($imagePath)) { - mkdir($imagePath, 0777, true); - } + public function addSamples($csvData, $dataFlowProfileRecord, $product) + { + $downloadableLinks = $this->extractDownloadableFiles($dataFlowProfileRecord); - $imageFile = $imagePath.'/'.basename($imageURL); + $d_samples = []; + $sampleNameKey = []; - file_put_contents($imageFile, file_get_contents(trim($imageURL))); + $sampleDataKeys = [ + 'samples_title', + 'sample_type', + 'sample_files', + 'sample_url', + 'sample_sort_order', + ]; - $data['images'][$imageArraykey] = $imageFile; - } - } + $sampleData = []; + + foreach ($sampleDataKeys as $key) { + $sampleData[$key] = preg_split('/,\s*|,/', $csvData[$key]); + } + + // Ensure that all link data arrays have the same length + $dataLengths = array_map('count', $sampleData); + $uniqueLengths = array_unique($dataLengths); + + if (! (count($uniqueLengths) === 1)) { + return [ + 'error' => ["Please provide correct value for Sample realted field for sku: {$product->sku}"], + ]; + } + + $dataLength = reset($uniqueLengths); + + // Loop through the downloadable sample data + for ($index = 0; $index < $dataLength; $index++) { + $sampleTitle = $sampleData['samples_title'][$index]; + $sampleFileType = trim(strtolower($sampleData['sample_type'][$index])); + $sampleFileName = $sampleData['sample_files'][$index]; + $sampleUrl = $sampleData['sample_url'][$index]; + $sampleSortOrder = $sampleData['sample_sort_order'][$index]; + + // Determine the sample file or URL for the link + $sampleFileLink = $this->fileOrUrlUpload( + $dataFlowProfileRecord, + $sampleFileType, + ($sampleFileType == "url") ? $sampleUrl : $sampleFileName, + $product->id, + $downloadableLinks, + false + ); + // Create the downloadable sample array + $sample['sample_' . $index] = [ + core()->getCurrentLocale()->code => [ + "title" => $sampleTitle, + ], + "type" => trim($sampleFileType), + "sort_order" => $sampleSortOrder[$index] ?? 0, + ]; + + if (trim($sampleFileType) == "url") { + $sample['sample_' . $index]['url'] = trim($sampleUrl); + } elseif (trim($sampleFileType) == "file" && isset($sampleFileLink)) { + $sample['sample_' . $index]['file'] = trim($sampleFileLink); + $sample['sample_' . $index]['file_name'] = trim($sampleFileName); } - $returnRules = $this->helperRepository->validateCSV($requestData['data_flow_profile_id'], $data, $dataFlowProfileRecord, $simpleproductData); + array_push($sampleNameKey, 'sample_' . $index); + array_push($d_samples, $sample['sample_' . $index]); + } + + $combinedArray = array_combine($sampleNameKey, $d_samples); + + return $combinedArray; + } - $csvValidator = Validator::make($data, $returnRules); + /** + * upload sample file link or url + * + * @param \Webkul\Bulkupload\Contracts\ImportProduct $dataFlowProfileRecord + * @param string $type + * @param string|array $file + * @param integer $id + * @param array $downloadableLinks + * @param string $flag + * + * @return mixed + */ + public function fileOrUrlUpload($dataFlowProfileRecord, $type, $file, $id, $downloadableLinks, $flag) + { + try { + if (trim($type) == "file") { + // Determine the file path + $sourcePath = $flag ? "imported-products/extracted-images/admin/sample-files/" : "imported-products/extracted-images/admin/link-sample-files/"; - if ($csvValidator->fails()) { - $errors = $csvValidator->errors()->getMessages(); + // 'upload_link_files', 'upload_sample_files', 'upload_link_sample_files' + $sourcePath .= $dataFlowProfileRecord->id.'/'.$downloadableLinks['upload_'.($flag ? 'sample' : 'link_sample').'_filesZipName']['dirname'].'/'.trim(basename($file)); - $this->helperRepository->deleteProductIfNotValidated($simpleproductData->id); + $destination = "product/".$id.'/'.trim(basename($file)); - foreach($errors as $key => $error) { - if ($error[0] == "The url key has already been taken.") { - $errorToBeReturn[] = "The url key " . $data['url_key'] . " has already been taken"; - } else { - $errorToBeReturn[] = str_replace(".", "", $error[0]). " for sku " . $data['sku']; - } + // Copy the file to the destination + Storage::copy($sourcePath, $destination); + + return $destination; + } else { + // Handle URL upload + $imagePath = storage_path('app/public/imported-products/extracted-images/admin/'.($flag ? 'sample-files' : 'link-sample-files').'/'.$dataFlowProfileRecord->id); + + if (!file_exists($imagePath)) { + mkdir($imagePath, 0777, true); } - $requestData['countOfStartedProfiles'] = $i + 1; + $imageFile = $imagePath.'/'.basename($file); - $productsUploaded = $i - $requestData['errorCount']; + file_put_contents($imageFile, file_get_contents(trim($file))); - if ($requestData['numberOfCSVRecord'] != 0) { - $remainDataInCSV = (int)$requestData['totalNumberOfCSVRecord'] - (int)$requestData['countOfStartedProfiles']; - } else { - $remainDataInCSV = 0; - } + $sourcePath = "imported-products/extracted-images/admin/".($flag ? 'sample-files' : 'link-sample-files').'/'.$dataFlowProfileRecord->id.'/'.basename($file); - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $errorToBeReturn, - ); + $destination = "product/".$id.'/'.basename($file); - return $dataToBeReturn; + Storage::copy($sourcePath, $destination); + + return $destination; } + } catch(\Exception $e) { + Log::error('downloadable fileOrUrlUpload log: '. $e->getMessage()); + } + } + + /** + * upload link file or url + * + * @param \Webkul\Bulkupload\Contracts\ImportProduct $dataFlowProfileRecord + * @param string $type + * @param string|array $file + * @param integer $id + * @param array $downloadableLinks + * + * @return mixed + */ + public function linkFileOrUrlUpload($dataFlowProfileRecord, $type, $file, $id, $downloadableLinks) + { + try { + if (trim($type) == "file") { + // Determine the file path + + $sourcePath = "imported-products/extracted-images/admin/link-files/".$dataFlowProfileRecord->id.'/'.$downloadableLinks['upload_link_filesZipName']['dirname'].'/'.trim(basename($file)); + + $destination = "product_downloadable_links/".$id.'/'.basename($file); - Event::dispatch('catalog.product.update.before', $simpleproductData->id); - $configSimpleProductAttributeStore = $this->productRepository->update($data, $simpleproductData->id); - Event::dispatch('catalog.product.update.after',$configSimpleProductAttributeStore); + // Copy the file to the destination + Storage::copy($sourcePath, $destination); - if (isset($imageZipName)) { - $this->productImageRepository->bulkuploadImages($data, $simpleproductData, $imageZipName); - } else if (isset($csvData['images'])) { - $this->productImageRepository->bulkuploadImages($data, $simpleproductData, $imageZipName = null); + return $destination; + } else { + // Handle URL upload + $filePath = storage_path('app/public/imported-products/extracted-images/admin/link-files/'.$dataFlowProfileRecord->id); + + if (!file_exists($filePath)) { + mkdir($filePath, 0777, true); + } + + $imageFile = $filePath.'/'.basename($file); + + file_put_contents($imageFile, file_get_contents(trim($file))); + + $sourcePath = "imported-products/extracted-images/admin/link-files/".$dataFlowProfileRecord->id.'/'.basename($file); + + $destination = "product_downloadable_links/".$id.'/'.basename($file); + + Storage::copy($sourcePath, $destination); + + return $destination; } } catch(\Exception $e) { - \Log::error('simple product store function'. $e->getMessage()); + Log::error('downloadable linkFileOrUrlUpload log: '. $e->getMessage()); } } -} \ No newline at end of file + + /** + * unzip zip files and store in storage folder + * + * @param \Webkul\Bulkupload\Contracts\ImportProduct $record + * + * @return mixed + */ + public function extractDownloadableFiles($record) + { + $result = []; + + $fileTypes = ['upload_link_files', 'upload_sample_files', 'upload_link_sample_files']; + + foreach ($fileTypes as $fileType) { + + if (isset($record->$fileType) && $record->$fileType !== "") { + + $zipArchive = new \ZipArchive(); + + $extractedPath = storage_path("app/public/imported-products/extracted-images/admin/{$fileType}/{$record->id}/"); + + if ($zipArchive->open(storage_path("app/public/{$record->$fileType}"))) { + for ($i = 0; $i < $zipArchive->numFiles; $i++) { + $filename = $zipArchive->getNameIndex($i); + $result["{$fileType}ZipName"] = pathinfo($filename); + } + + $zipArchive->extractTo($extractedPath); + $zipArchive->close(); + } + } + } + + return $result; + } +} diff --git a/src/Repositories/Products/VirtualProductRepository.php b/src/Repositories/Products/VirtualProductRepository.php deleted file mode 100644 index 50191b2..0000000 --- a/src/Repositories/Products/VirtualProductRepository.php +++ /dev/null @@ -1,445 +0,0 @@ -importProductRepository = $importProductRepository; - - $this->categoryRepository = $categoryRepository; - - $this->productFlatRepository = $productFlatRepository; - - $this->productRepository = $productRepository; - - $this->productImageRepository = $productImageRepository; - - $this->attributeFamilyRepository = $attributeFamilyRepository; - - $this->helperRepository = $helperRepository; - - $this->attributeOptionRepository = $attributeOptionRepository; - - $this->inventorySourceRepository = $inventorySourceRepository; - } - - /* - * Specify Model class name - * - * @return mixed - */ - function model() - { - return 'Webkul\Product\Contracts\Product'; - } - - /** - * create & update virtual-type product - * - * @param array $requestData - * @param array $imageZipName - * - * @return mixed - */ - public function createProduct($requestData, $imageZipName) - { - try { - $inventory = []; - - $dataFlowProfileRecord = $this->importProductRepository->findOneByField - ('data_flow_profile_id', $requestData['data_flow_profile_id']); - - $csvData = (new DataGridImport)->toArray($dataFlowProfileRecord->file_path)[0]; - - if ($requestData['totalNumberOfCSVRecord'] < 1000) { - $processCSVRecords = $requestData['totalNumberOfCSVRecord']/($requestData['totalNumberOfCSVRecord']/10); - } else { - $processCSVRecords = $requestData['totalNumberOfCSVRecord']/($requestData['totalNumberOfCSVRecord']/100); - } - - $uptoProcessCSVRecords = (int)$requestData['countOfStartedProfiles'] + 10; - $processRecords = (int)$requestData['countOfStartedProfiles'] + (int)$requestData['numberOfCSVRecord']; - - if ($requestData['numberOfCSVRecord'] > $processCSVRecords) { - for ($i = $requestData['countOfStartedProfiles']; $i < $uptoProcessCSVRecords; $i++) { - $invalidateProducts = $this->store($csvData[$i], $i, $dataFlowProfileRecord, $requestData, $imageZipName); - - if (isset($invalidateProducts) && !empty($invalidateProducts)) { - return $invalidateProducts; - } - } - } else if ($requestData['numberOfCSVRecord'] <= 10) { - for ($i = $requestData['countOfStartedProfiles']; $i < $processRecords; $i++) { - $invalidateProducts = $this->store($csvData[$i], $i, $dataFlowProfileRecord, $requestData, $imageZipName); - - if (isset($invalidateProducts) && !empty($invalidateProducts)) { - return $invalidateProducts; - } - } - } - - if ($requestData['numberOfCSVRecord'] > 10) { - $remainDataInCSV = (int)$requestData['numberOfCSVRecord'] - (int)$processCSVRecords; - } else { - $remainDataInCSV = 0; - - if($requestData['errorCount'] > 0) { - $uptoProcessCSVRecords = $requestData['totalNumberOfCSVRecord'] - $requestData['errorCount']; - } else { - $uptoProcessCSVRecords = $processRecords; - } - } - - $requestData['countOfStartedProfiles'] = $i; - - $dataToBeReturn = [ - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $uptoProcessCSVRecords, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - ]; - - return $dataToBeReturn; - } catch(\Exception $e) { - Log::error('virtual create product log: '. $e->getMessage()); - - $categoryError = explode('[' ,$e->getMessage()); - $categorySlugError = explode(']' ,$e->getMessage()); - $requestData['countOfStartedProfiles'] = $i + 1; - $productsUploaded = $i - $requestData['errorCount']; - - if ($requestData['numberOfCSVRecord'] != 0) { - $remainDataInCSV = (int)$requestData['totalNumberOfCSVRecord'] - (int)$requestData['countOfStartedProfiles']; - } else { - $remainDataInCSV = 0; - } - - if ($categoryError[0] == "No query results for model ") { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => "Invalid Category Slug: " . $categorySlugError[1], - ); - $categoryError[0] = null; - } else if (isset($e->errorInfo)) { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $e->errorInfo[2], - ); - } else { - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $e->getMessage(), - ); - } - - return $dataToBeReturn; - } - } - - /** - * function to store product - * - * @param array $csvData - * @param integer $i - * @param \Webkul\Bulkupload\Contracts\ImportProduct $dataFlowProfileRecord - * @param array $requestData - * @param array $imageZipName - * - * @return mixed - */ - public function store($csvData, $i, $dataFlowProfileRecord, $requestData, $imageZipName) - { - try { - $createValidation = $this->helperRepository->createProductValidation($csvData, $i); - - if (isset($createValidation)) { - return $createValidation; - } - - $productFlatData = $this->productFlatRepository->findWhere(['sku' => $csvData['sku'], 'url_key' => $csvData['url_key']])->first(); - - $productData = $this->productRepository->findWhere(['sku' => $csvData['sku']])->first(); - - $attributeFamilyData = $this->attributeFamilyRepository->findOneByfield(['name' => $csvData['attribute_family_name']]); - - if (! isset($productFlatData) && empty($productFlatData)) { - $data['type'] = $csvData['type']; - $data['attribute_family_id'] = $attributeFamilyData->id; - $data['sku'] = $csvData['sku']; - Event::dispatch('catalog.product.create.before'); - $virtualProductData = $this->productRepository->create($data); - Event::dispatch('catalog.product.create.after', $virtualProductData); - - } else { - $virtualProductData = $productData; - } - - unset($data); - $data = []; - $attributeCode = []; - $attributeValue = []; - - //default attributes - foreach ($virtualProductData->getTypeInstance()->getEditableAttributes()->toArray() as $key => $value) { - $searchIndex = $value['code']; - if (array_key_exists($searchIndex, $csvData)) { - if (is_null($csvData[$searchIndex])) { - continue; - } - - array_push($attributeCode, $searchIndex); - - if ($searchIndex == "color" || $searchIndex == "size" || $searchIndex == "brand") { - $attributeOption = $this->attributeOptionRepository->findOneByField(['admin_name' => ucwords($csvData[$searchIndex])]); - - array_push($attributeValue, $attributeOption['id']); - } else { - array_push($attributeValue, $csvData[$searchIndex]); - } - - $data = array_combine($attributeCode, $attributeValue); - } - } - - $data['dataFlowProfileRecordId'] = $dataFlowProfileRecord->id; - - $inventorySource = $csvData['inventory_sources']; - $inventoryCode = explode(',', $inventorySource); - - foreach ($inventoryCode as $key => $value) { - $inventoryId = $this->inventorySourceRepository->findOneByfield(['code' => trim($value)])->pluck('id')->toArray(); - } - - $inventoryData[] = (string)$csvData['inventories']; - - foreach ($inventoryData as $key => $d) { - $inventoryQuantity = explode(',', trim($d)); - - if (count($inventoryId) != count($inventoryQuantity)) { - array_push($inventoryQuantity, "0"); - } - - $inventory = array_combine($inventoryId, $inventoryQuantity); - } - - $data['inventories'] = $inventory; - - $categoryData = explode(',', $csvData['categories_slug']); - - if (is_null($csvData['categories_slug']) || empty($csvData['categories_slug'])) { - $categoryID = $this->categoryRepository->findBySlugOrFail('root')->id; - } else { - foreach ($categoryData as $key => $value) { - $categoryID[$key] = $this->categoryRepository->findBySlugOrFail($categoryData[$key])->id; - } - } - - $data['categories'] = $categoryID; - $data['channel'] = core()->getCurrentChannel()->code; - - $dataProfile = app('Webkul\Bulkupload\Repositories\DataFlowProfileRepository')->findOneByfield(['id' => $data['dataFlowProfileRecordId']]); - $data['locale'] = $dataProfile->locale_code; - - //customerGroupPricing - if (isset($csvData['customer_group_prices']) && ! empty($csvData['customer_group_prices'])) { - $data['customer_group_prices'] = json_decode($csvData['customer_group_prices'], true); - app(ProductCustomerGroupPriceRepository::class)->saveCustomerGroupPrices($data, $simpleproductData); - } - - //Product Images - $individualProductimages = explode(',', $csvData['images']); - - if (isset($imageZipName)) { - $images = Storage::disk('local')->files('public/imported-products/extracted-images/admin/'.$dataFlowProfileRecord->id.'/'.$imageZipName['dirname'].'/'); - - foreach ($images as $imageArraykey => $imagePath) { - $imageName = explode('/', $imagePath); - - if (in_array(last($imageName), preg_replace('/[\'"]/', '',$individualProductimages))) { - $data['images'][$imageArraykey] = $imagePath; - } - } - } else if (isset($csvData['images'])) { - foreach ($individualProductimages as $imageArraykey => $imageURL) - { - if (filter_var(trim($imageURL), FILTER_VALIDATE_URL)) { - $imagePath = storage_path('app/public/imported-products/extracted-images/admin/'.$dataFlowProfileRecord->id); - - if (!file_exists($imagePath)) { - mkdir($imagePath, 0777, true); - } - - $imageFile = $imagePath.'/'.basename($imageURL); - - file_put_contents($imageFile, file_get_contents(trim($imageURL))); - - $data['images'][$imageArraykey] = $imageFile; - } - } - } - - //to check validation - $validationRules = $this->helperRepository->validateCSV($requestData['data_flow_profile_id'], $data, $dataFlowProfileRecord, $virtualProductData); - - $csvValidator = Validator::make($data, $validationRules); - - if ($csvValidator->fails()) { - $errors = $csvValidator->errors()->getMessages(); - - $this->helperRepository->deleteProductIfNotValidated($virtualProductData->id); - - foreach($errors as $key => $error) { - if ($error[0] == "The url key has already been taken.") { - $errorToBeReturn[] = "The url key " . $data['url_key'] . " has already been taken"; - } else { - $errorToBeReturn[] = str_replace(".", "", $error[0]) . " for sku " . $data['sku']; - } - } - - $requestData['countOfStartedProfiles'] = $i + 1; - - $productsUploaded = $i - $requestData['errorCount']; - - if ($requestData['numberOfCSVRecord'] != 0) { - $remainDataInCSV = (int)$requestData['totalNumberOfCSVRecord'] - (int)$requestData['countOfStartedProfiles']; - } else { - $remainDataInCSV = 0; - } - - $dataToBeReturn = array( - 'remainDataInCSV' => $remainDataInCSV, - 'productsUploaded' => $productsUploaded, - 'countOfStartedProfiles' => $requestData['countOfStartedProfiles'], - 'error' => $errorToBeReturn, - ); - - return $dataToBeReturn; - } - - Event::dispatch('catalog.product.update.before', $virtualProductData->id); - $configVirtualProduct = $this->productRepository->update($data, $virtualProductData->id); - Event::dispatch('catalog.product.update.after',$configVirtualProduct); - - if (isset($imageZipName)) { - $this->productImageRepository->bulkuploadImages($data, $virtualProductData, $imageZipName); - } else if (isset($csvData['images'])) { - $this->productImageRepository->bulkuploadImages($data, $virtualProductData, $imageZipName = null); - } - } catch(\Exception $e) { - \Log::error('virtual product store function'. $e->getMessage()); - } - } -} \ No newline at end of file diff --git a/src/Resources/assets/images/Icon-Bulk-Upload-Active.svg b/src/Resources/assets/images/Icon-Bulk-Upload-Active.svg deleted file mode 100644 index db0b09c..0000000 --- a/src/Resources/assets/images/Icon-Bulk-Upload-Active.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - Icon-Bulk-Upload-Active - Created with Sketch. - - - - - - - - - - - \ No newline at end of file diff --git a/src/Resources/assets/images/Icon-Bulk-Upload.svg b/src/Resources/assets/images/Icon-Bulk-Upload.svg deleted file mode 100644 index e987ea4..0000000 --- a/src/Resources/assets/images/Icon-Bulk-Upload.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - Icon-Bulk-Upload - Created with Sketch. - - - - - - - - - - - \ No newline at end of file diff --git a/src/Resources/assets/images/Icon-Crossed.svg b/src/Resources/assets/images/Icon-Crossed.svg deleted file mode 100644 index 038759b..0000000 --- a/src/Resources/assets/images/Icon-Crossed.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - Icon-Crossed - Created with Sketch. - - - - - \ No newline at end of file diff --git a/src/Resources/assets/images/Icon-Temp-Active.svg b/src/Resources/assets/images/Icon-Temp-Active.svg new file mode 100644 index 0000000..d4c6168 --- /dev/null +++ b/src/Resources/assets/images/Icon-Temp-Active.svg @@ -0,0 +1,12 @@ + + + + Icon-Catalog-Active + Created with Sketch. + + + + + + + \ No newline at end of file diff --git a/publishable/assets/images/check-accent.svg b/src/Resources/assets/images/Icon-Temp.svg similarity index 50% rename from publishable/assets/images/check-accent.svg rename to src/Resources/assets/images/Icon-Temp.svg index 8334c77..7dba04b 100644 --- a/publishable/assets/images/check-accent.svg +++ b/src/Resources/assets/images/Icon-Temp.svg @@ -1,10 +1,12 @@ - + - Check-Accent + Icon-Catalog Created with Sketch. - - + + + + \ No newline at end of file diff --git a/src/Resources/assets/images/cross-accent.svg b/src/Resources/assets/images/cross-accent.svg deleted file mode 100644 index be35112..0000000 --- a/src/Resources/assets/images/cross-accent.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - Cross-Accent - Created with Sketch. - - - - - - \ No newline at end of file diff --git a/src/Resources/assets/images/finish.svg b/src/Resources/assets/images/finish.svg deleted file mode 100644 index 2401834..0000000 --- a/src/Resources/assets/images/finish.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - tab/heading/icon/finish - Created with Sketch. - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Resources/assets/js/app.js b/src/Resources/assets/js/app.js index 205c766..d624e61 100644 --- a/src/Resources/assets/js/app.js +++ b/src/Resources/assets/js/app.js @@ -1,8 +1,9 @@ -window.Vue = require("vue"); -window.axios = require("axios"); +// Import Vue and Axios +window.Vue = require('vue'); +window.axios = require('axios'); +// Set Axios as a default HTTP client for Vue Vue.prototype.$http = axios; +// Create a global event bus window.eventBus = new Vue(); - -Vue.component("demo", require("./components/demo")); diff --git a/src/Resources/assets/sample-files/booking-product-upload.csv b/src/Resources/assets/sample-files/booking-product-upload.csv new file mode 100644 index 0000000..4875a7c --- /dev/null +++ b/src/Resources/assets/sample-files/booking-product-upload.csv @@ -0,0 +1,13 @@ +categories_slug,attribute_family_name,name,description,short_description,url_key,sku,price,special_price,special_price_from,special_price_to,tax_category_id,stock,meta_title,meta_keywords,meta_description,color,brand,type,new,featured,visible_individually,status,guest_checkout,size,inventories,width,booking_type,booking_location,booking_qty,booking_available_from,booking_available_to,booking_type_day_wise,booking_slot_from_day,booking_slot_from,booking_slot_to_day,booking_slot_to,available_every_week,duration,break_time,same_slot_all_days,event_ticket_name,event_ticket_description,event_ticket_price,event_ticket_qty,renting_type,daily_price,hourly_price,day_wise_slots,price_type,guest_limit,prevent_scheduling_before,images,default_booking_status,,dumy +root,default,Default-booking1,booking-product,booking-product,default-booking,dfs,123,100,2016-05-26,2016-05-28,,123,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,,booking,1,1,1,1,1,M,32,32,default,noida,11,"09/04/2020, 12:00:00","16/04/2020, 12:00:00",many,MoNday,"12:00:00, 13:00:00, 12:00:00, 13:00:00, 12:00:00, 13:00:00, 12:00:00",WedneSday,"15:00:00, 16:00:00, 14:00:00, 16:00:00, 14:00:00, 16:00:00, 14:00:00",,50,10,,,,,,,,,,,,,"banner.jpeg,bg.jpg,download.jpeg","0,0,1,1,1,1,1",, +root,default,appointment-product,booking-product,booking-product,appointment-product,appointment-product,123,100,2016-05-26,2016-05-28,,123,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,,booking,1,1,1,1,1,M,32,32,appointment,noida,11,"09/04/2020, 12:00:00","16/04/2020, 12:00:00",,MoNday,12:00:00,WedneSday,14:00:00,yes,,,,,,,,,,,,,,,"download (1).jpeg,download (2).jpeg,men-jacket.jpg",,, +root,default,appointment-product1,booking-product,booking-product,appointment-product1,appointment-product1,123,100,2016-05-26,2016-05-28,,123,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,,booking,1,1,1,1,1,M,32,32,appointment,noida,11,"09/04/2020, 12:00:00","16/04/2020, 12:00:00",,MoNday,12:00:00,WedneSday,14:00:00,no,50,10,yes,,,,,,,,,,,,"w-jeans.jpeg,w-shirt.jpeg,download (2).jpeg",,, +root,default,ticket-product1,booking-product,booking-product,ticket-product1,ticket-product1,200,100,2016-05-26,2016-05-28,,123,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,,booking,1,1,1,1,1,M,32,32,event,noida,11,"09/04/2020, 12:00:00","16/04/2020, 12:00:00",,MoNday,12:00:00,WedneSday,14:00:00,no,50,10,yes,song_ticket,parmish verma concert,45,21,,,,,,,,"bg.jpg,men-jacket.jpg,w-shirt.jpeg",,, +root,default,rental-product,booking-product,booking-product,rental-product,rental-product,200,100,2016-05-26,2016-05-28,,123,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,,booking,1,1,1,1,1,M,32,32,rental,noida,11,"09/04/2020, 12:00:00","16/04/2020, 12:00:00",,MoNday,12:00:00,WedneSday,14:00:00,yes,50,10,yes,song_ticket,parmish verma concert,45,21,daily,23,87,,,,,"download (1).jpeg,download (2).jpeg,men-jacket.jpg",,, +root,default,rental-product1,booking-product,booking-product,rental-product1,rental-product1,200,100,2016-05-26,2016-05-28,,123,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,,booking,1,1,1,1,1,M,32,32,rental,noida,11,"09/04/2020, 12:00:00","16/04/2020, 12:00:00",,MoNday,12:00:00,WedneSday,14:00:00,yes,50,10,yes,song_ticket,parmish verma concert,45,21,hourly,23,35,"tuesday, friday",,,,"download (1).jpeg,download (2).jpeg,men-jacket.jpg",,, +root,default,rental-product3,booking-product,booking-product,rental-product3,rental-product3,200,100,2016-05-26,2016-05-28,,123,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,,booking,1,1,1,1,1,M,32,32,rental,noida,11,"09/04/2020, 12:00:00","16/04/2020, 12:00:00",,MoNday,"12:00:00, 13:00:00",WedneSday,"14:00:00, 16:00:00",yes,50,10,yes,song_ticket,parmish verma concert,45,21,daily_hourly,23,35,"monday, friday",,,,"w-jeans.jpeg,w-shirt.jpeg,download (2).jpeg",,, +root,default,Rental-product4,booking-product,booking-product,rental-product4,rental-product4,200,100,2016-05-26,2016-05-28,,123,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,,booking,1,1,1,1,1,M,32,32,rental,noida,11,"09/04/2020, 12:00:00","16/04/2020, 12:00:00",,MoNday,"12:00:00, 13:00:00",WedneSday,"14:00:00, 16:00:00",no,50,10,no,song_ticket,parmish verma concert,45,21,daily_hourly,23,35,"monday, friday",,,,"banner.jpeg,bg.jpg,download.jpeg",,, +root,default,table-product3,booking-product,booking-product,table-product3,table-product3,200,100,2016-05-26,2016-05-28,,123,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,,booking,1,1,1,1,1,M,32,32,table,noida,11,"09/04/2020, 12:00:00","16/04/2020, 12:00:00",,MoNday,"12:00:00, 13:00:00",WedneSday,"14:00:00, 16:00:00",yes,50,10,yes,song_ticket,parmish verma concert,45,21,daily_hourly,23,35,"monday, friday",table,3,5,"bg.jpg,men-jacket.jpg,w-shirt.jpeg",,, +root,default,dumy1,booking-product,booking-product,gfss,table-product31,200,100,2016-05-26,2016-05-28,,123,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,,booking,1,1,1,1,1,M,32,32,table,noida,11,"09/04/2020, 12:00:00","16/04/2020, 12:00:00",,MoNday,"12:00:00, 13:00:00",WedneSday,"14:00:00, 16:00:00",no,50,10,no,song_ticket,parmish verma concert,45,21,daily_hourly,23,35,"monday, friday",guest,3,5,"w-jeans.jpeg,w-shirt.jpeg,download (2).jpeg",,, +root,default,dumy2,booking-product,booking-product,dfhdfhdf,Ticket-product13,200,100,2016-05-26,2016-05-28,,123,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,,booking,1,1,1,1,1,M,32,32,event,noida,11,"09/04/2020, 12:00:00","16/04/2020, 12:00:00",,MoNday,12:00:00,WedneSday,14:00:00,no,50,10,yes,song_ticket,parmish verma concert,45,21,,,,,,,,"bg.jpg,men-jacket.jpg,w-shirt.jpeg",,, +root,default,defaultbooking2,booking-product,booking-product,default-booking2,defaultbooking2,123,100,2016-05-26,2016-05-28,,123,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,,booking,1,1,1,1,1,M,32,32,default,noida,11,"09/04/2020, 12:00:00","16/04/2020, 12:00:00",one,MoNday,12:00:00,WedneSday,14:00:00,,,,,,,,,,,,,,,,"banner.jpeg,bg.jpg,download.jpeg",,, diff --git a/src/Resources/assets/sample-files/booking-product-upload.xlsx b/src/Resources/assets/sample-files/booking-product-upload.xlsx new file mode 100644 index 0000000..468589c Binary files /dev/null and b/src/Resources/assets/sample-files/booking-product-upload.xlsx differ diff --git a/src/Resources/assets/sample-files/bundle-product-upload.csv b/src/Resources/assets/sample-files/bundle-product-upload.csv new file mode 100644 index 0000000..ba6779b --- /dev/null +++ b/src/Resources/assets/sample-files/bundle-product-upload.csv @@ -0,0 +1,6 @@ +categories_slug,attribute_family_name,name,description,short_description,url_key,sku,price,special_price,special_price_from,special_price_to,tax_category_id,stock,images,meta_title,meta_keywords,meta_description,color,brand,type,new,featured,visible_individually,status,guest_checkout,inventories,bundle_options +root,default,bundled_product1,temp1,temp1,bundled_product1,temp122,123,100,2021-11-04,2021-12-25,Taxable Goods,1000,"1.png,2.png",Test Title,sample_type,Test Description,Red,,bundle,1,1,1,1,1,32,"{""option_0"":{""en"":{""label"":""option1""},""type"":""select"",""is_required"":""1"",""sort_order"":""1"",""products"":{""product_0"":{""is_default"":""1"",""product_id"":""730"",""qty"":""10"",""sort_order"":""1""}}},""option_1"":{""en"":{""label"":""option2""},""type"":""select"",""is_required"":""1"",""sort_order"":""2"",""products"":{""product_0"":{""is_default"":""1"",""product_id"":""731"",""qty"":""20"",""sort_order"":""1""}}}}" +root,default,bundled_product2,temp1,temp1,bundled_product2,temp123,123,100,2021-11-05,2021-12-26,Taxable Goods,1000,"1.png,2.png",Test Title,sample_type,Test Description,Red,,bundle,1,1,1,1,1,32,"{""option_0"":{""en"":{""label"":""option1""},""type"":""select"",""is_required"":""1"",""sort_order"":""1"",""products"":{""product_0"":{""is_default"":""1"",""product_id"":""730"",""qty"":""10"",""sort_order"":""1""}}},""option_1"":{""en"":{""label"":""option2""},""type"":""select"",""is_required"":""1"",""sort_order"":""2"",""products"":{""product_0"":{""is_default"":""1"",""product_id"":""731"",""qty"":""20"",""sort_order"":""1""}}}}" +root,default,bundled_product3,temp1,temp1,bundled_product3,temp124,123,100,2021-11-06,2021-12-27,Taxable Goods,1000,"1.png,2.png",Test Title,sample_type,Test Description,Red,,bundle,1,1,1,1,1,32,"{""option_0"":{""en"":{""label"":""option1""},""type"":""select"",""is_required"":""1"",""sort_order"":""1"",""products"":{""product_0"":{""is_default"":""1"",""product_id"":""730"",""qty"":""10"",""sort_order"":""1""}}},""option_1"":{""en"":{""label"":""option2""},""type"":""select"",""is_required"":""1"",""sort_order"":""2"",""products"":{""product_0"":{""is_default"":""1"",""product_id"":""731"",""qty"":""20"",""sort_order"":""1""}}}}" +root,default,bundled_product4,temp1,temp1,bundled_product4,temp125,123,100,2021-11-07,2021-12-28,Taxable Goods,1000,"1.png,2.png",Test Title,sample_type,Test Description,Red,,bundle,1,1,1,1,1,32,"{""option_0"":{""en"":{""label"":""option1""},""type"":""select"",""is_required"":""1"",""sort_order"":""1"",""products"":{""product_0"":{""is_default"":""1"",""product_id"":""730"",""qty"":""10"",""sort_order"":""1""}}},""option_1"":{""en"":{""label"":""option2""},""type"":""select"",""is_required"":""1"",""sort_order"":""2"",""products"":{""product_0"":{""is_default"":""1"",""product_id"":""731"",""qty"":""20"",""sort_order"":""1""}}}}" +root,default,bundled_product5,temp1,temp1,bundled_product5,temp126,123,100,2021-11-08,2021-12-29,Taxable Goods,1000,"1.png,2.png",Test Title,sample_type,Test Description,Red,,bundle,1,1,1,1,1,32,"{""option_0"":{""en"":{""label"":""option1""},""type"":""select"",""is_required"":""1"",""sort_order"":""1"",""products"":{""product_0"":{""is_default"":""1"",""product_id"":""730"",""qty"":""10"",""sort_order"":""1""}}},""option_1"":{""en"":{""label"":""option2""},""type"":""select"",""is_required"":""1"",""sort_order"":""2"",""products"":{""product_0"":{""is_default"":""1"",""product_id"":""731"",""qty"":""20"",""sort_order"":""1""}}}}" diff --git a/src/Resources/assets/sample-files/bundle-product-upload.xlsx b/src/Resources/assets/sample-files/bundle-product-upload.xlsx new file mode 100644 index 0000000..449464c Binary files /dev/null and b/src/Resources/assets/sample-files/bundle-product-upload.xlsx differ diff --git a/src/Resources/assets/sample-files/configurable-product-upload.csv b/src/Resources/assets/sample-files/configurable-product-upload.csv new file mode 100644 index 0000000..8305cbe --- /dev/null +++ b/src/Resources/assets/sample-files/configurable-product-upload.csv @@ -0,0 +1,7 @@ +categories_slug,name,description,short_description,sku,special_price,special_price_from,special_price_to,weight,meta_title,meta_keywords,meta_description,url_key,tax_category_id,new,featured,visible_individually,status,cost,width,height,depth,type,attribute_family_name,super_attributes,super_attribute_option,super_attribute_price,inventory_sources,super_attribute_qty,super_attribute_weight,images,guest_checkout,barcode +root,Temp1,

temp1

,

fvsdfgs

,demounique236,80,2019-05-02,2019-05-20,12,Test Title,Test Keyword,Test Description,temp23,,1,1,1,1,10,34,34,234,configurable,Default,,,,default,,,banner.jpeg,1,1 +,temp33,

temp22

,

temfp2

,demounique1532,,,,13,,,,,,,,,1,,,,,variant,Default,"color,size","Red,S",150,default,12,10,,,1 +,sda,

temp212

,

sdag

,demounique211,,,,45,,,,,,,,,1,,,,,variant,Default,"color,size","Yellow,S",23,default,13,10,,,1 +,temp35,

temp212

,

teemp2

,demounique311,,,,15,,,,,,,,,1,,,,,variant,Default,"color,size","Green,M",400,default,14,10,,,1 +,update,

temp212

,

teemp2

,demounique411,,,,16,,,,,,,,,1,,,,,variant,Default,"color,size","White,M",77,default,15,10,,,1 +,temp37,

fdgfdsg

,

teemp2

,demounique511,,,,17,,,,,,,,,1,,,,,variant,Default,"color,size","Black,M",400,default,16,10,,,1 diff --git a/src/Resources/assets/sample-files/configurable-product-upload.xlsx b/src/Resources/assets/sample-files/configurable-product-upload.xlsx new file mode 100644 index 0000000..826e1cf Binary files /dev/null and b/src/Resources/assets/sample-files/configurable-product-upload.xlsx differ diff --git a/src/Resources/assets/sample-files/downloadable-product-upload.csv b/src/Resources/assets/sample-files/downloadable-product-upload.csv new file mode 100644 index 0000000..ff5e592 --- /dev/null +++ b/src/Resources/assets/sample-files/downloadable-product-upload.csv @@ -0,0 +1,2 @@ +categories_slug,attribute_family_name,name,description,short_description,url_key,sku,price,special_price,special_price_from,special_price_to,tax_category_id,stock,images,meta_title,meta_keywords,meta_description,sample_type,samples_title,sample_files,sample_sort_order,link_titles,link_types,link_file_names,link_prices,link_sample_types,link_sample_file_names,link_downloads,link_sort_orders,color,brand,type,new,featured,visible_individually,status,guest_checkout,inventories,sample_url,link_sample_url,link_url +root,default,temp1,temp1,temp1,sdsd1,temp122,123,100,2016-05-25,2016-05-27,Taxable Goods,1000,"banner.jpeg,bg.jpg",Test Title,Test Keyword,Test Description,"url, file","Sample Title, sample totle2",sample1.png,"1,1","fdvs, dff","url, file",links1.png,"34, 76","url, file",linksample1.png,"23, 34","1, 6",Red,,downloadable,1,1,1,1,1,32,https://homepages.cae.wisc.edu/~ece533/images/airplane.png,https://homepages.cae.wisc.edu/~ece533/images/boat.png,"https://homepages.cae.wisc.edu/~ece533/images/airplane.png, https://homepages.cae.wisc.edu/~ece533/images/boat.png" diff --git a/src/Resources/assets/sample-files/downloadable-product-upload.xlsx b/src/Resources/assets/sample-files/downloadable-product-upload.xlsx new file mode 100644 index 0000000..55e9566 Binary files /dev/null and b/src/Resources/assets/sample-files/downloadable-product-upload.xlsx differ diff --git a/src/Resources/assets/sample-files/grouped-product-upload.csv b/src/Resources/assets/sample-files/grouped-product-upload.csv new file mode 100644 index 0000000..c04f077 --- /dev/null +++ b/src/Resources/assets/sample-files/grouped-product-upload.csv @@ -0,0 +1,5 @@ +categories_slug,attribute_family_name,name,description,short_description,url_key,sku,price,special_price,special_price_from,special_price_to,tax_category_id,stock,images,meta_title,meta_keywords,meta_description,color,size,brand,type,new,featured,visible_individually,status,guest_checkout,inventories,width,grouped_product_sku,grouped_quantity,grouped_sort_order +root,default,temp1,temp1,temp1,cxvcx1,temp1,123,100,2016-05-26,2016-05-28,,123,banner.jpeg,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,M,,grouped,1,1,1,1,1,32,32,"adminer, admin-simple-product","22, 43","1, 2" +root,default,temp2,temp1,temp1,cxvcx2,temp2,123,100,2016-05-26,2016-05-28,,123,banner.jpeg,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,M,,grouped,1,1,1,1,1,32,32,"adminer, admin-simple-product","22, 43","1, 2" +root,default,temp3,temp1,temp1,cxvcx3,temp3,123,100,2016-05-26,2016-05-28,,123,banner.jpeg,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,M,,grouped,1,1,1,1,1,32,32,"adminer, admin-simple-product","22, 43","1, 2" +root,default,temp4,temp1,temp1,cxvcx4,temp4,123,100,2016-05-26,2016-05-28,,123,banner.jpeg,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,M,,grouped,1,1,1,1,1,32,32,"adminer, admin-simple-product","22, 43","1, 2" diff --git a/src/Resources/assets/sample-files/grouped-product-upload.xlsx b/src/Resources/assets/sample-files/grouped-product-upload.xlsx new file mode 100644 index 0000000..20f2ec0 Binary files /dev/null and b/src/Resources/assets/sample-files/grouped-product-upload.xlsx differ diff --git a/src/Resources/assets/sample-files/simple-product-upload.csv b/src/Resources/assets/sample-files/simple-product-upload.csv new file mode 100644 index 0000000..cba2607 --- /dev/null +++ b/src/Resources/assets/sample-files/simple-product-upload.csv @@ -0,0 +1,5 @@ +categories_slug,name,description,short_description,sku,price,special_price,special_price_from,special_price_to,inventory_sources,inventories,weight,meta_title,meta_keywords,meta_description,color,size,url_key,tax_category_id,new,featured,visible_individually,status,cost,width,height,depth,type,attribute_family_name,images,guest_checkout +root,temp1,temp1,shortdesc,updatedSKU,100,80,2019-05-02,2020-05-20,default,123,12,Test Title,Test Keyword,Test Description,Red,M,erwer,,1,1,1,1,10,34,34,234,simple,Default,"banner.jpeg,bg.jpg,download.jpeg",1 +root,temp1sdvc,fdh,temp1,temp21,200,80,2019-05-02,2020-05-20,default,124,12,Test Title,Test Keyword,Test Description,Green,M,dsfvg,,1,1,1,1,10,34,34,234,simple,Default,"download (1).jpeg,download (2).jpeg,men-jacket.jpg",1 +root,hurray,temp1,temp1,,300,80,2019-05-02,2020-05-20,default,125,12,Test Title,Test Keyword,Test Description,Yellow,M,rthg,,1,1,1,1,10,34,34,234,simple,Default,"w-jeans.jpeg,w-shirt.jpeg,download (2).jpeg",1 +root,cbv,temp1,temp1,temp41,400,80,2019-05-02,2020-05-20,default,126,12,Test Title,Test Keyword,Test Description,Black,M,temp3,,1,1,1,1,10,34,34,234,simple,Default,"bg.jpg,men-jacket.jpg,w-shirt.jpeg",1 diff --git a/src/Resources/assets/sample-files/simple-product-upload.xlsx b/src/Resources/assets/sample-files/simple-product-upload.xlsx new file mode 100644 index 0000000..a3f227f Binary files /dev/null and b/src/Resources/assets/sample-files/simple-product-upload.xlsx differ diff --git a/src/Resources/assets/sample-files/virtual-product-upload.csv b/src/Resources/assets/sample-files/virtual-product-upload.csv new file mode 100644 index 0000000..3929b63 --- /dev/null +++ b/src/Resources/assets/sample-files/virtual-product-upload.csv @@ -0,0 +1,5 @@ +categories_slug,attribute_family_name,name,description,short_description,url_key,sku,price,special_price,special_price_from,special_price_to,tax_category_id,stock,meta_title,meta_keywords,meta_description,color,size,brand,type,new,featured,visible_individually,status,guest_checkout,inventory_sources,inventories,images,width +root,default,temp1,temp1,temp1,cxvcx1,temp1,123,100,2016-05-26,2016-05-28,,123,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,M,,virtual,1,1,1,1,1,default,32,,32 +root,default,temp2,temp1,temp1,cxvcx2,temp2,123,100,2016-05-26,2016-05-28,,123,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,M,,virtual,1,1,1,1,1,default,32,,32 +root,default,temp3,temp1,temp1,cxvcx3,temp3,123,100,2016-05-26,2016-05-28,,123,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,M,,virtual,1,1,1,1,1,default,32,,32 +root,default,temp4,temp1,temp1,cxvcx4,temp4,123,100,2016-05-26,2016-05-28,,123,Test Meta Title,Test Meta Keyword,Test Meta Description,Red,M,,virtual,1,1,1,1,1,default,32,,32 diff --git a/src/Resources/assets/sample-files/virtual-product-upload.xlsx b/src/Resources/assets/sample-files/virtual-product-upload.xlsx new file mode 100644 index 0000000..65519bc Binary files /dev/null and b/src/Resources/assets/sample-files/virtual-product-upload.xlsx differ diff --git a/src/Resources/assets/sass/admin.scss b/src/Resources/assets/sass/admin.scss index fe99fff..0009165 100644 --- a/src/Resources/assets/sass/admin.scss +++ b/src/Resources/assets/sass/admin.scss @@ -1,55 +1,50 @@ .bulk-upload-icon { - width: 48px; - height: 48px; - display: inline-block; - background-size: cover; - background-image: url("../images/Icon-Bulk-Upload.svg"); + width: 48px; + height: 48px; + display: inline-block; + background-image: url("../images/Icon-Bulk-Upload.svg") no-repeat center/cover; } .active { - .bulk-upload-icon { - background-image: url("../images/Icon-Bulk-Upload-Active.svg"); - } - - &.bulk-upload-icon { - background-image: url("../images/Icon-Bulk-Upload-Active.svg"); - } + .bulk-upload-icon, &.bulk-upload-icon { + background-image: url("../images/Icon-Bulk-Upload-Active.svg"); + } } progress { - margin: 15px 0px 15px 34px; - width: 70%; - height: 15px; + margin: 15px 0px 15px 34px; + width: 70%; + height: 15px; } .icon { - background-size: cover; - display: inline-block; - - &.check-accent { - background-image: url("../images/check-accent.svg"); - width: 22px; - height: 18px; - } - - &.icon-crossed { - width: 18px; - height: 15px; - background-image: url("../images/Icon-Crossed.svg"); - } - - &.cross-accent { - width: 22px; - height: 18px; - background-image: url("../images/cross-accent.svg"); - } - - &.finish-icon { - width: 22px; - height: 18px; - background-image: url("../images/finish.svg"); - } + background-size: cover; + display: inline-block; + + &.check-accent { + background-image: url("../images/check-accent.svg") no-repeat center/cover; + width: 22px; + height: 18px; + } + + &.icon-crossed, &.cross-accent, &.finish-icon { + width: 18px; + height: 15px; + } + + &.icon-crossed { + background: url("../images/Icon-Crossed.svg") no-repeat center/cover; + } + + &.cross-accent { + background: url("../images/cross-accent.svg") no-repeat center/cover; + } + + &.finish-icon { + background: url("../images/finish.svg") no-repeat center/cover; + } } + .ms-15 { - margin-left: 15px; + margin-left: 15px; } diff --git a/src/Resources/assets/sass/app.scss b/src/Resources/assets/sass/app.scss deleted file mode 100644 index 7d23555..0000000 --- a/src/Resources/assets/sass/app.scss +++ /dev/null @@ -1,56 +0,0 @@ -.bulk-upload-icon { - width: 48px; - height: 48px; - display: inline-block; - background-size: cover; - background-image: url("../images/Icon-Bulk-Upload.svg"); -} - -.active { - .bulk-upload-icon { - width: 48px; - height: 48px; - display: inline-block; - background-size: cover; - background-image: url("../images/Icon-Bulk-Upload-Active.svg"); - } -} - -progress { - margin: 15px 0px 15px 34px; - width: 70%; - height: 15px; -} - -.icon { - background-size: cover; - display: inline-block; - - &.check-accent { - width: 22px; - height: 18px; - background-image: url("../images/check-accent.svg"); - } - - &.icon-crossed { - width: 18px; - height: 15px; - background-image: url("../images/Icon-Crossed.svg"); - } - - &.cross-accent { - width: 22px; - height: 18px; - background-image: url("../images/cross-accent.svg"); - } - - &.finish-icon { - width: 22px; - height: 18px; - background-image: url("../images/finish.svg"); - } -} - -.ms-15 { - margin-left: 15px; - } \ No newline at end of file diff --git a/src/Resources/lang/ar/app.php b/src/Resources/lang/ar/app.php deleted file mode 100644 index 0e030c6..0000000 --- a/src/Resources/lang/ar/app.php +++ /dev/null @@ -1,60 +0,0 @@ - [ - 'bulk-upload' => [ - 'index' => 'Bulkupload', - 'manage-bulk-upload' => 'Manage Bulk Upload', - - 'data-flow-profile' => [ - 'index' => 'Data Flow Profile', - 'add-profile' => 'Add Profile', - 'grid' => 'Profile Grid', - 'name' => 'Name', - - 'data-grid' => [ - 'created-at' => 'Created At' - ] - ], - - 'run-profile' => [ - 'index' => 'Run Profile', - 'select-file' => 'Select File', - 'please-select' => 'Please Select', - 'run' => 'Run', - 'profile-execution' => 'Starting profile execution, please wait...', - 'error-count' => 'Number of errors while product uploading', - 'error-in-product' => 'Error while product uploading', - 'warning' => 'Warning: Please do not close the window during importing data', - 'products-uploaded' => 'Products Uploaded', - 'finish' => 'Finished Profile Execution', - ], - - 'upload-files' => [ - 'index' => 'Upload Files', - 'download-sample' => 'Download Samples', - 'download' => 'Download', - 'csv-file' => 'Sample :filetype CSV File', - 'xls-file' => 'Sample :filetype XLS File', - 'import-products' => 'Import Products', - 'is-downloadable' => 'Is downloadable have files', - 'sample-links' => 'Is Links have samples', - 'sample-available' => 'Is Samples available', - 'upload-link-files' => 'Upload Link Files', - 'upload-link-sample-files' => 'Upload Link Sample Files', - 'upload-sample-files' => 'Upload Sample Files', - 'file' => 'CSV/XLS/XLSX file', - 'image' => 'Image Zip file', - 'save' => 'Save' - ], - - 'messages' => [ - 'profile-saved' => 'Profile added successfully', - 'profile-deleted' => 'Profile deleted successfully', - 'file-format-error' => 'Invalid File Extension', - 'update-profile' => 'Profile updated successfully', - 'data-profile-not-selected' => 'Data Flow Profile not selected', - ] - ], - ], -]; \ No newline at end of file diff --git a/src/Resources/lang/en/app.php b/src/Resources/lang/en/app.php index 09ba67a..a1d15b1 100644 --- a/src/Resources/lang/en/app.php +++ b/src/Resources/lang/en/app.php @@ -2,69 +2,77 @@ return [ 'admin' => [ - 'system' => [ - 'bulkupload' => 'Bulk-Upload Product', - 'settings' => 'Settings', - 'general' => 'General', - 'status' => 'Status', + 'system' => [ + 'bulkupload' => 'Bulk-Upload Product', + 'settings' => 'Settings', + 'general' => 'General', + 'status' => 'Status', ], 'bulk-upload' => [ - 'index' => 'Bulkupload', + 'index' => 'Bulk-Upload', 'manage-bulk-upload' => 'Manage Bulk Upload', - 'data-flow-profile' => [ - 'index' => 'Data Flow Profile', - 'add-profile' => 'Add Profile', - 'grid' => 'Profile Grid', - 'name' => 'Name', - 'edit-profile' => 'Edit Profile', + 'bulk-product-importer' => [ + 'grid' => 'Profile Grid', + 'name' => 'Name', + 'index' => 'Bulk Product Importer', + 'add-profile' => 'Add Profile', + 'edit-profile' => 'Edit Profile', 'update-profile' => 'Update', 'data-grid' => [ - 'created-at' => 'Created At', + 'created-at' => 'Created At', 'locale_code' => 'Locale code' ] ], 'run-profile' => [ - 'index' => 'Run Profile', - 'select-file' => 'Select File', - 'please-select' => 'Please Select', - 'run' => 'Run', + 'run' => 'Import Products', + 'index' => 'Run Profile', + 'error' => 'Products which are not uploaded', + 'finish' => 'Finished Profile Execution', + 'warning' => 'Warning: Please do not close the window during importing data', + 'run-command' => 'Import Products In BackGround', + 'error-count' => 'Number of errors while product uploading', + 'select-file' => 'Select File', + 'please-select' => 'Please Select', + 'error-in-product' => 'Error while product uploading', 'profile-execution' => 'Starting profile execution, please wait...', - 'error-count' => 'Number of errors while product uploading', - 'error-in-product' => 'Error while product uploading', - 'warning' => 'Warning: Please do not close the window during importing data', 'products-uploaded' => 'Products Uploaded', - 'finish' => 'Finished Profile Execution', + ], + + 'upload-file' => [ + 'delete' => 'Delete File', ], 'upload-files' => [ - 'index' => 'Upload Files', - 'download-sample' => 'Download Samples', - 'download' => 'Download', - 'csv-file' => 'Sample :filetype CSV File', - 'xls-file' => 'Sample :filetype XLS File', - 'import-products' => 'Import Products', - 'is-downloadable' => 'Is downloadable have files', - 'sample-links' => 'Is Links have samples', - 'sample-available' => 'Is Samples available', - 'upload-link-files' => 'Upload Link Files', + 'file' => 'CSV/XLS/XLSX file', + 'save' => 'Save', + 'index' => 'Upload Files', + 'image' => 'Image Zip file', + 'download' => 'Download', + 'csv-file' => 'Sample :filetype CSV File', + 'xls-file' => 'Sample :filetype XLS File', + 'sample-links' => 'Is Links have samples', + 'download-sample' => 'Download Sample', + 'sample-file' => 'Sample Files', + 'import-products' => 'Import Products', + 'is-downloadable' => 'Is downloadable have files', + 'sample-available' => 'Is Samples available', + 'upload-link-files' => 'Upload Link Files', + 'upload-sample-files' => 'Upload Sample Files', 'upload-link-sample-files' => 'Upload Link Sample Files', - 'upload-sample-files' => 'Upload Sample Files', - 'file' => 'CSV/XLS/XLSX file', - 'image' => 'Image Zip file', - 'save' => 'Save' ], 'messages' => [ - 'profile-saved' => 'Profile added successfully', - 'profile-deleted' => 'Profile deleted successfully', - 'file-format-error' => 'Invalid File Extension', - 'update-profile' => 'Profile updated successfully', - 'data-profile-not-selected' => 'Data Flow Profile not selected', + 'profile-saved' => 'Profile added successfully', + 'update-profile' => 'Profile updated successfully', + 'profile-deleted' => 'Profile deleted successfully', + 'file-format-error' => 'Invalid File Extension', + 'all-profile-deleted' => 'All the selected profiles have been deleted successfully', + 'data-profile-not-selected' => 'Bulk Product Importer not selected', ] ], ], -]; \ No newline at end of file +]; diff --git a/src/Resources/lang/fa/app.php b/src/Resources/lang/fa/app.php deleted file mode 100644 index 0e030c6..0000000 --- a/src/Resources/lang/fa/app.php +++ /dev/null @@ -1,60 +0,0 @@ - [ - 'bulk-upload' => [ - 'index' => 'Bulkupload', - 'manage-bulk-upload' => 'Manage Bulk Upload', - - 'data-flow-profile' => [ - 'index' => 'Data Flow Profile', - 'add-profile' => 'Add Profile', - 'grid' => 'Profile Grid', - 'name' => 'Name', - - 'data-grid' => [ - 'created-at' => 'Created At' - ] - ], - - 'run-profile' => [ - 'index' => 'Run Profile', - 'select-file' => 'Select File', - 'please-select' => 'Please Select', - 'run' => 'Run', - 'profile-execution' => 'Starting profile execution, please wait...', - 'error-count' => 'Number of errors while product uploading', - 'error-in-product' => 'Error while product uploading', - 'warning' => 'Warning: Please do not close the window during importing data', - 'products-uploaded' => 'Products Uploaded', - 'finish' => 'Finished Profile Execution', - ], - - 'upload-files' => [ - 'index' => 'Upload Files', - 'download-sample' => 'Download Samples', - 'download' => 'Download', - 'csv-file' => 'Sample :filetype CSV File', - 'xls-file' => 'Sample :filetype XLS File', - 'import-products' => 'Import Products', - 'is-downloadable' => 'Is downloadable have files', - 'sample-links' => 'Is Links have samples', - 'sample-available' => 'Is Samples available', - 'upload-link-files' => 'Upload Link Files', - 'upload-link-sample-files' => 'Upload Link Sample Files', - 'upload-sample-files' => 'Upload Sample Files', - 'file' => 'CSV/XLS/XLSX file', - 'image' => 'Image Zip file', - 'save' => 'Save' - ], - - 'messages' => [ - 'profile-saved' => 'Profile added successfully', - 'profile-deleted' => 'Profile deleted successfully', - 'file-format-error' => 'Invalid File Extension', - 'update-profile' => 'Profile updated successfully', - 'data-profile-not-selected' => 'Data Flow Profile not selected', - ] - ], - ], -]; \ No newline at end of file diff --git a/src/Resources/lang/nl/app.php b/src/Resources/lang/nl/app.php deleted file mode 100644 index 0e030c6..0000000 --- a/src/Resources/lang/nl/app.php +++ /dev/null @@ -1,60 +0,0 @@ - [ - 'bulk-upload' => [ - 'index' => 'Bulkupload', - 'manage-bulk-upload' => 'Manage Bulk Upload', - - 'data-flow-profile' => [ - 'index' => 'Data Flow Profile', - 'add-profile' => 'Add Profile', - 'grid' => 'Profile Grid', - 'name' => 'Name', - - 'data-grid' => [ - 'created-at' => 'Created At' - ] - ], - - 'run-profile' => [ - 'index' => 'Run Profile', - 'select-file' => 'Select File', - 'please-select' => 'Please Select', - 'run' => 'Run', - 'profile-execution' => 'Starting profile execution, please wait...', - 'error-count' => 'Number of errors while product uploading', - 'error-in-product' => 'Error while product uploading', - 'warning' => 'Warning: Please do not close the window during importing data', - 'products-uploaded' => 'Products Uploaded', - 'finish' => 'Finished Profile Execution', - ], - - 'upload-files' => [ - 'index' => 'Upload Files', - 'download-sample' => 'Download Samples', - 'download' => 'Download', - 'csv-file' => 'Sample :filetype CSV File', - 'xls-file' => 'Sample :filetype XLS File', - 'import-products' => 'Import Products', - 'is-downloadable' => 'Is downloadable have files', - 'sample-links' => 'Is Links have samples', - 'sample-available' => 'Is Samples available', - 'upload-link-files' => 'Upload Link Files', - 'upload-link-sample-files' => 'Upload Link Sample Files', - 'upload-sample-files' => 'Upload Sample Files', - 'file' => 'CSV/XLS/XLSX file', - 'image' => 'Image Zip file', - 'save' => 'Save' - ], - - 'messages' => [ - 'profile-saved' => 'Profile added successfully', - 'profile-deleted' => 'Profile deleted successfully', - 'file-format-error' => 'Invalid File Extension', - 'update-profile' => 'Profile updated successfully', - 'data-profile-not-selected' => 'Data Flow Profile not selected', - ] - ], - ], -]; \ No newline at end of file diff --git a/src/Resources/lang/pt_BR/app.php b/src/Resources/lang/pt_BR/app.php deleted file mode 100644 index 0e030c6..0000000 --- a/src/Resources/lang/pt_BR/app.php +++ /dev/null @@ -1,60 +0,0 @@ - [ - 'bulk-upload' => [ - 'index' => 'Bulkupload', - 'manage-bulk-upload' => 'Manage Bulk Upload', - - 'data-flow-profile' => [ - 'index' => 'Data Flow Profile', - 'add-profile' => 'Add Profile', - 'grid' => 'Profile Grid', - 'name' => 'Name', - - 'data-grid' => [ - 'created-at' => 'Created At' - ] - ], - - 'run-profile' => [ - 'index' => 'Run Profile', - 'select-file' => 'Select File', - 'please-select' => 'Please Select', - 'run' => 'Run', - 'profile-execution' => 'Starting profile execution, please wait...', - 'error-count' => 'Number of errors while product uploading', - 'error-in-product' => 'Error while product uploading', - 'warning' => 'Warning: Please do not close the window during importing data', - 'products-uploaded' => 'Products Uploaded', - 'finish' => 'Finished Profile Execution', - ], - - 'upload-files' => [ - 'index' => 'Upload Files', - 'download-sample' => 'Download Samples', - 'download' => 'Download', - 'csv-file' => 'Sample :filetype CSV File', - 'xls-file' => 'Sample :filetype XLS File', - 'import-products' => 'Import Products', - 'is-downloadable' => 'Is downloadable have files', - 'sample-links' => 'Is Links have samples', - 'sample-available' => 'Is Samples available', - 'upload-link-files' => 'Upload Link Files', - 'upload-link-sample-files' => 'Upload Link Sample Files', - 'upload-sample-files' => 'Upload Sample Files', - 'file' => 'CSV/XLS/XLSX file', - 'image' => 'Image Zip file', - 'save' => 'Save' - ], - - 'messages' => [ - 'profile-saved' => 'Profile added successfully', - 'profile-deleted' => 'Profile deleted successfully', - 'file-format-error' => 'Invalid File Extension', - 'update-profile' => 'Profile updated successfully', - 'data-profile-not-selected' => 'Data Flow Profile not selected', - ] - ], - ], -]; \ No newline at end of file diff --git a/src/Resources/views/admin/bulk-upload/bulk-product-importer/edit.blade.php b/src/Resources/views/admin/bulk-upload/bulk-product-importer/edit.blade.php new file mode 100644 index 0000000..ba873e8 --- /dev/null +++ b/src/Resources/views/admin/bulk-upload/bulk-product-importer/edit.blade.php @@ -0,0 +1,85 @@ +@extends('admin::layouts.content') + +@section('page_title') + {{ __('bulkupload::app.admin.bulk-upload.bulk-product-importer.edit-profile') }} +@endsection + +@section('content') + +@endsection diff --git a/src/Resources/views/admin/bulk-upload/data-flow-profile/index.blade.php b/src/Resources/views/admin/bulk-upload/bulk-product-importer/index.blade.php similarity index 50% rename from src/Resources/views/admin/bulk-upload/data-flow-profile/index.blade.php rename to src/Resources/views/admin/bulk-upload/bulk-product-importer/index.blade.php index d3d96fd..c140f9e 100644 --- a/src/Resources/views/admin/bulk-upload/data-flow-profile/index.blade.php +++ b/src/Resources/views/admin/bulk-upload/bulk-product-importer/index.blade.php @@ -1,7 +1,7 @@ @extends('admin::layouts.content') @section('page_title') - {{ __('bulkupload::app.admin.bulk-upload.data-flow-profile.index') }} + {{ __('bulkupload::app.admin.bulk-upload.bulk-product-importer.index') }} @stop @push('css') @@ -14,55 +14,69 @@ @section('content') -
-

{{ __('bulkupload::app.admin.bulk-upload.data-flow-profile.add-profile') }}

+

{{ __('bulkupload::app.admin.bulk-upload.bulk-product-importer.add-profile') }}

-
+ @csrf + input('family') ?> -
- - - {{ $errors->first('name') }} +
+ + + + + @{{ errors.first('name') }}
-
- +
+ - @foreach ($families as $family) - + @endforeach @if ($familyId) - + @endif - {{ $errors->first('attribute_family') }} + @{{ errors.first('attribute_family_id') }}
- + + @{{ errors.first('locale_code') }}
@@ -74,10 +88,10 @@
- +
- {!! app('Webkul\Bulkupload\DataGrids\Admin\ProfileDataGrid')->render() !!} +
diff --git a/src/Resources/views/admin/bulk-upload/data-flow-profile/edit.blade.php b/src/Resources/views/admin/bulk-upload/data-flow-profile/edit.blade.php deleted file mode 100644 index 65ac3af..0000000 --- a/src/Resources/views/admin/bulk-upload/data-flow-profile/edit.blade.php +++ /dev/null @@ -1,54 +0,0 @@ -@extends('admin::layouts.content') - -@section('page_title') -{{ __('bulkupload::app.admin.bulk-upload.bulk-upload-dataflow-profile') }} -@endsection - -@section('content') - -@endsection diff --git a/src/Resources/views/admin/bulk-upload/run-profile/index.blade.php b/src/Resources/views/admin/bulk-upload/run-profile/index.blade.php index 33929b2..109b8e6 100644 --- a/src/Resources/views/admin/bulk-upload/run-profile/index.blade.php +++ b/src/Resources/views/admin/bulk-upload/run-profile/index.blade.php @@ -4,6 +4,39 @@ {{ __('bulkupload::app.admin.bulk-upload.run-profile.index') }} @stop +@push('css') + +@endpush + @section('content') @@ -20,86 +53,126 @@ @push('scripts') - + -@endpush \ No newline at end of file +@endpush diff --git a/src/Resources/views/admin/bulk-upload/style.blade.php b/src/Resources/views/admin/bulk-upload/style.blade.php index 3230861..9c38839 100644 --- a/src/Resources/views/admin/bulk-upload/style.blade.php +++ b/src/Resources/views/admin/bulk-upload/style.blade.php @@ -1 +1 @@ - \ No newline at end of file + diff --git a/src/Resources/views/admin/bulk-upload/upload-files/index.blade.php b/src/Resources/views/admin/bulk-upload/upload-files/index.blade.php index 5252ba8..c6cd29b 100644 --- a/src/Resources/views/admin/bulk-upload/upload-files/index.blade.php +++ b/src/Resources/views/admin/bulk-upload/upload-files/index.blade.php @@ -8,34 +8,46 @@