From 81e0c18de92126b1b2bfff7a9106617a1149dde6 Mon Sep 17 00:00:00 2001 From: Abdalla Dimes <60352784+abdalladimes@users.noreply.github.com> Date: Wed, 6 Sep 2023 18:25:03 +0300 Subject: [PATCH 1/5] feat: Init AI state seeder --- control/content/controllers/aiStateSeeder.js | 225 ++++++++++++++++++ .../controllers/content.home.controller.js | 26 +- control/content/index.html | 4 +- 3 files changed, 251 insertions(+), 4 deletions(-) create mode 100644 control/content/controllers/aiStateSeeder.js diff --git a/control/content/controllers/aiStateSeeder.js b/control/content/controllers/aiStateSeeder.js new file mode 100644 index 0000000..59633a3 --- /dev/null +++ b/control/content/controllers/aiStateSeeder.js @@ -0,0 +1,225 @@ +class StateSeeder { + tagNames; + datastore; + reloadCoupons; + itemsList; + + jsonTemplate = { + items: [ + { + title: "", + summary: "", + listImage: "", + }, + ], + }; + + constructor(TAG_NAMES, Datastore, reloadCoupons) { + this.tagNames = TAG_NAMES; + this.datastore = Datastore; + this.reloadCoupons = reloadCoupons; + this.initStateSeeder(); + } + + async initStateSeeder() { + this.stateSeederInstance = new buildfire.components.aiStateSeeder({ + generateOptions: { + userMessage: `List a sample coupons for a [business-type]`, + maxRecords: 5, + systemMessage: + "title is the coupon title, summary is a brief summary, listImage is an image URL related to title and the list type, use source.unsplash.com for images URL image should be 1080x720, URL should not have premium_photo or source.unsplash.com/random.", + jsonTemplate: this.jsonTemplate, + callback: await this.handleAIReq.bind(this), + hintText: 'Replace values between brackets to match your requirements.', + }, + importOptions: { + jsonTemplate: this.jsonTemplate, + sampleCSV: "Flights, Save 20% on Flights, Get 20% off on flight bookings with this exclusive coupon, https://source.unsplash.com/1080x720/?travel\nHotel, 50% Off Hotel Bookings, Enjoy a 50% discount on hotel reservations using this limited-time coupon, https://source.unsplash.com/1080x720/?hotel", + maxRecords: 5, + hintText: '', + systemMessage: `each row has a coupon title and listImage URL`, + callback: await this.handleAIReq.bind(this), + }, + }).smartShowEmptyState(); + } + + async handleAIReq(err, data) { + if ( + err || + !data || + typeof data !== "object" || + !Object.keys(data).length || !data.data || !data.data.items || !data.data.items.length + ) { + return buildfire.dialog.toast({ + message: "Bad AI request, please try changing your request.", + type: "danger", + }); + } + + this.itemsList = data.data.items; + //Check image URLs + let coupons = this.itemsList.map(item => { + return new Promise((resolve, reject) => { + this.elimanateNotFoundImages(item.listImage).then(res => { + if (res.isValid) { + item.listImage = res.newURL; + resolve(item); + } else { + reject('image URL not valid'); + } + }) + }) + }) + + // Check image URLs and apply defaults + Promise.allSettled(coupons).then(results => { + this.itemsList = []; + results.forEach(res => { + if(res.status == 'fulfilled') { + const coupon = res.value; + if (coupon) { + this.itemsList.push(coupon); + } + } + }) + + if (!this.itemsList.length) { + return buildfire.dialog.toast({ + message: "Bad AI request, please try changing your request.", + type: "danger", + }); + } + + // reset old data + this.getOldCoupons().then(oldCouponsList => { + if (this.stateSeederInstance.requestResult.resetData){ + this.deleteAll(oldCouponsList) + } + // save new data + this.itemsList.forEach(item => { + item = this._applyDefaults(item); + buildfire.datastore.insert(item, this.tagNames.COUPON_ITEMS, (err, res)=> { + if (res) { + item.deepLinkId = res.id, + item.deepLinkUrl = buildfire.deeplink.createLink({ id: res.id }) + buildfire.datastore.update(res.id, item, this.tagNames.COUPON_ITEMS, (err, res) => { + if (res) + buildfire.messaging.sendMessageToWidget({ type: "ImportCSV", importing: false }); + this.reloadCoupons(); + }) + } + }) + }) + }) + }) + this.stateSeederInstance.requestResult.complete(); + } + + // UTILITIES + _applyDefaults(item) { + if (item.title) { + return { + title: item.title, + summary: item.summary || "N/A", + listImage: item.listImage || "", + startOn: Date.now(), + expiresOn: Math.trunc(Date.now() + Math.random() * 8640000000), + links: [], + preRedemptionText: "Redeem Now", + postRedemptionText: "Coupon Redeemed", + carouselImages: [ + { + "action": "noAction", + "iconUrl": item.listImage, + "title": "image" + } + ], + rank: 30, + addressTitle: "", + location: { + addressTitle: "", + coordinates: { + lat: "", + lng: "" + } + }, + Categories: [], + reuseAfterInMinutes: -1, + dateCreated: Date.now(), + deepLinkUrl: '', // must have an id from datatore + deepLinkId: '', //same as item id + SelectedCategories: [], + } + } + return null + } + + elimanateNotFoundImages = (url) => { + const optimisedURL = url.replace('1080x720', '100x100'); + return new Promise((resolve) => { + if (url.includes("http")){ + const xhr = new XMLHttpRequest(); + xhr.open("GET", optimisedURL); + xhr.onerror = (error) => { + console.warn('provided URL is not a valid image', error); + resolve({isValid: false, newURL: null}); + } + xhr.onload = () => { + if (xhr.responseURL.includes('source-404') || xhr.status == 404) { + return resolve({isValid: false ,newURL: null}); + } else { + return resolve({isValid: true, newURL: xhr.responseURL.replace('h=100', 'h=720').replace('w=100', 'w=1080') }); + } + }; + xhr.send(); + } else resolve(false); + }); + }; + + async getCurrentUser() { + return new Promise((resolve, reject) => { + buildfire.auth.getCurrentUser((err, currentUser) => { + if (!currentUser) { + buildfire.auth.login({ allowCancel: false }, (err, user) => { + if (!user) { + this.getCurrentUser(); + } else { + resolve(user); + } + }); + } else { + resolve(currentUser); + } + }); + }); + } + + getOldCoupons() { + return new Promise((resolve, reject) => { + buildfire.datastore.search( + {}, + this.tagNames.COUPON_ITEMS, + (err, results) => { + if (err) reject(err); + resolve(results); + } + ); + }); + } + + deleteAll(oldCouponsList) { + const promises = oldCouponsList.map((coupon) => + this.deleteCoupon(coupon.id, this.tagNames.COUPON_ITEMS) + ); + return Promise.all(promises); + } + + deleteCoupon(taskId, tag) { + return new Promise((resolve, reject) => { + buildfire.datastore.delete(taskId, tag, (err, res) => { + if (err) reject(err); + resolve(res); + }); + }); + } + } \ No newline at end of file diff --git a/control/content/controllers/content.home.controller.js b/control/content/controllers/content.home.controller.js index bbb1e77..72e378c 100644 --- a/control/content/controllers/content.home.controller.js +++ b/control/content/controllers/content.home.controller.js @@ -5,7 +5,6 @@ .module('couponPluginContent') .controller('ContentHomeCtrl', ['$scope', '$timeout', 'TAG_NAMES', 'SORT', 'SORT_FILTER', 'STATUS_CODE', 'DataStore', 'LAYOUTS', 'Buildfire', 'Modals', 'RankOfLastFilter', 'RankOfLastItem', '$csv', 'Utils', '$rootScope', 'PluginEvents', function ($scope, $timeout, TAG_NAMES, SORT, SORT_FILTER, STATUS_CODE, DataStore, LAYOUTS, Buildfire, Modals, RankOfLastFilter, RankOfLastItem, $csv, Utils, $rootScope, PluginEvents) { - var ContentHome = this; ContentHome.searchValue = ""; ContentHome.filter = null; @@ -799,9 +798,26 @@ "limit": "50" }; - ContentHome.loadMoreItems = function (str) { - console.log("------------------>>>>>>>>>>>>>>>>>>>>", str) + ContentHome.reloadCoupons = function () { + Buildfire.datastore.search(ContentHome.searchOptionsForItems, TAG_NAMES.COUPON_ITEMS, function (err, result) { + if (err) { + Buildfire.spinner.hide(); + return console.error('-----------err in getting list-------------', err); + } + if (result.length <= SORT._limit) {// to indicate there are more + ContentHome.noMore = true; + Buildfire.spinner.hide(); + } else { + result.pop(); + ContentHome.searchOptionsForItems.skip = ContentHome.searchOptionsForItems.skip + SORT._limit; + ContentHome.noMore = false; + } + ContentHome.items = result; + $scope.$digest(); + }) + } + ContentHome.loadMoreItems = function (str) { Buildfire.spinner.show(); if (ContentHome.busy) { return; @@ -868,6 +884,9 @@ ContentHome.busy = false; ContentHome.isBusy = false; console.log("-------------------llll", ContentHome.items) + if (!ContentHome.items || !ContentHome.items.length) { + new StateSeeder(TAG_NAMES, DataStore, ContentHome.reloadCoupons); + } Buildfire.spinner.hide(); $scope.$digest(); }); @@ -1323,6 +1342,7 @@ * Go pull any previously saved data * */ var init = function () { + console.log('$scope ====================>', $scope) var success = function (result) { console.info('Init success result:', result); ContentHome.data = result.data; diff --git a/control/content/index.html b/control/content/index.html index 36f2eed..bceb0c2 100755 --- a/control/content/index.html +++ b/control/content/index.html @@ -10,9 +10,10 @@ + + - @@ -36,6 +37,7 @@ + From ffa960ca3ecf40ac1ea090bc3d939a355251a7b2 Mon Sep 17 00:00:00 2001 From: Abdalla Dimes Date: Thu, 7 Sep 2023 04:11:29 +0300 Subject: [PATCH 2/5] fix: Applied code review changes --- control/content/app.services.js | 202 +++++++++++++++- control/content/controllers/aiStateSeeder.js | 225 ------------------ .../controllers/content.home.controller.js | 9 +- control/content/index.html | 1 - widget/controllers/widget.home.controller.js | 2 +- 5 files changed, 205 insertions(+), 234 deletions(-) delete mode 100644 control/content/controllers/aiStateSeeder.js diff --git a/control/content/app.services.js b/control/content/app.services.js index a54a1ac..8ac0b24 100644 --- a/control/content/app.services.js +++ b/control/content/app.services.js @@ -247,5 +247,205 @@ buildfire.analytics.unregisterEvent('coupon_item_view_' + key); } }; - }]);; + }]).factory('StateSeeder', ['TAG_NAMES' ,function(TAG_NAMES) { + // let reloadCoupons; + let itemsList; + let stateSeederInstance; + let reloadCoupons; + let jsonTemplate = { + items: [ + { + title: "", + summary: "", + listImage: "", + }, + ], + }; + let handleAIReq = function(err, data) { + if ( + err || + !data || + typeof data !== "object" || + !Object.keys(data).length || !data.data || !data.data.items || !data.data.items.length + ) { + return buildfire.dialog.toast({ + message: "Bad AI request, please try changing your request.", + type: "danger", + }); + } + + itemsList = data.data.items; + //Check image URLs + let coupons = itemsList.map(item => { + return new Promise((resolve, reject) => { + elimanateNotFoundImages(item.listImage).then(res => { + if (res.isValid) { + item.listImage = res.newURL; + resolve(item); + } else { + reject('image URL not valid'); + } + }) + }) + }) + + // Check image URLs and apply defaults + Promise.allSettled(coupons).then(results => { + itemsList = []; + results.forEach(res => { + if(res.status == 'fulfilled') { + const coupon = res.value; + if (coupon) { + itemsList.push(coupon); + } + } + }) + if (!itemsList.length) { + stateSeederInstance.requestResult.complete(); + return buildfire.dialog.toast({ + message: "Bad AI request, please try changing your request.", + type: "danger", + }); + } + + // reset old data + getOldCoupons().then(oldCouponsList => { + if (stateSeederInstance.requestResult.resetData){ + deleteAll(oldCouponsList) + } + // save new data + itemsList.forEach(item => { + item = _applyDefaults(item); + buildfire.datastore.insert(item, TAG_NAMES.COUPON_ITEMS, (err, res)=> { + if (res) { + item.deepLinkId = res.id, + item.deepLinkUrl = buildfire.deeplink.createLink({ id: res.id }) + buildfire.datastore.update(res.id, item, TAG_NAMES.COUPON_ITEMS, (err, res) => { + if (res) + buildfire.messaging.sendMessageToWidget({ type: "ImportCSV", importing: false }); + reloadCoupons(); + }) + } + }) + }) + }) + stateSeederInstance.requestResult.complete(); + }) + } + + // UTILITIES + let _applyDefaults = function(item) { + if (item.title) { + return { + title: item.title, + summary: item.summary || "N/A", + listImage: item.listImage || "", + startOn: Date.now(), + expiresOn: Math.trunc(Date.now() + Math.random() * 8640000000), + links: [], + preRedemptionText: "Redeem Now", + postRedemptionText: "Coupon Redeemed", + carouselImages: [ + { + "action": "noAction", + "iconUrl": item.listImage, + "title": "image" + } + ], + rank: 30, + addressTitle: "", + location: { + addressTitle: "", + coordinates: { + lat: "", + lng: "" + } + }, + Categories: [], + reuseAfterInMinutes: -1, + dateCreated: Date.now(), + deepLinkUrl: '', // must have an id from datatore + deepLinkId: '', //same as item id + SelectedCategories: [], + } + } + return null + } + + let elimanateNotFoundImages = function(url) { + const optimisedURL = url.replace('1080x720', '100x100'); + return new Promise((resolve) => { + if (url.includes("http")){ + const xhr = new XMLHttpRequest(); + xhr.open("GET", optimisedURL); + xhr.onerror = (error) => { + console.warn('provided URL is not a valid image', error); + resolve({isValid: false, newURL: null}); + } + xhr.onload = () => { + if (xhr.responseURL.includes('source-404') || xhr.status == 404) { + return resolve({isValid: false ,newURL: null}); + } else { + return resolve({isValid: true, newURL: xhr.responseURL.replace('h=100', 'h=720').replace('w=100', 'w=1080') }); + } + }; + xhr.send(); + } else resolve(false); + }); + }; + + + let getOldCoupons = function() { + return new Promise((resolve, reject) => { + buildfire.datastore.search( + {}, + TAG_NAMES.COUPON_ITEMS, + (err, results) => { + if (err) reject(err); + resolve(results); + } + ); + }); + } + + let deleteAll = function(oldCouponsList) { + const promises = oldCouponsList.map((coupon) => + deleteCoupon(coupon.id, TAG_NAMES.COUPON_ITEMS) + ); + return Promise.all(promises); + } + + let deleteCoupon = function(taskId, tag) { + return new Promise((resolve, reject) => { + buildfire.datastore.delete(taskId, tag, (err, res) => { + if (err) reject(err); + resolve(res); + }); + }); + } + return { + initStateSeeder: function(callback) { + reloadCoupons = callback; + stateSeederInstance = new buildfire.components.aiStateSeeder({ + generateOptions: { + userMessage: `List sample coupons for a new [business-type]`, + maxRecords: 5, + systemMessage: + "title is the coupon title, summary is a brief summary, listImage is an image URL related to title and the list type, use source.unsplash.com for images URL image should be 1080x720, URL should not have premium_photo or source.unsplash.com/random.", + jsonTemplate: jsonTemplate, + callback: handleAIReq.bind(this), + hintText: 'Replace values between brackets to match your requirements.', + }, + importOptions: { + jsonTemplate: jsonTemplate, + sampleCSV: "Save 20% on Flights, Get 20% off on flight bookings with this exclusive coupon, https://source.unsplash.com/1080x720/?travel\n50% Off Hotel Bookings, Enjoy a 50% discount on hotel reservations using this limited-time coupon, https://source.unsplash.com/1080x720/?hotel\nCar Rental Special Offer, Rent a car for 7 days and pay for only 5 days with this coupon code, https://source.unsplash.com/1080x720/?car\nAdventure Tour Promo, Book an adventure tour and receive a free equipment rental worth $50 using this coupon, https://source.unsplash.com/1080x720/?adventure", + maxRecords: 5, + hintText: '', + systemMessage: `each row has a coupon title and listImage URL`, + callback: handleAIReq.bind(this), + }, + }).smartShowEmptyState(); + }, + } + }]) })(window.angular, window.buildfire); \ No newline at end of file diff --git a/control/content/controllers/aiStateSeeder.js b/control/content/controllers/aiStateSeeder.js deleted file mode 100644 index 59633a3..0000000 --- a/control/content/controllers/aiStateSeeder.js +++ /dev/null @@ -1,225 +0,0 @@ -class StateSeeder { - tagNames; - datastore; - reloadCoupons; - itemsList; - - jsonTemplate = { - items: [ - { - title: "", - summary: "", - listImage: "", - }, - ], - }; - - constructor(TAG_NAMES, Datastore, reloadCoupons) { - this.tagNames = TAG_NAMES; - this.datastore = Datastore; - this.reloadCoupons = reloadCoupons; - this.initStateSeeder(); - } - - async initStateSeeder() { - this.stateSeederInstance = new buildfire.components.aiStateSeeder({ - generateOptions: { - userMessage: `List a sample coupons for a [business-type]`, - maxRecords: 5, - systemMessage: - "title is the coupon title, summary is a brief summary, listImage is an image URL related to title and the list type, use source.unsplash.com for images URL image should be 1080x720, URL should not have premium_photo or source.unsplash.com/random.", - jsonTemplate: this.jsonTemplate, - callback: await this.handleAIReq.bind(this), - hintText: 'Replace values between brackets to match your requirements.', - }, - importOptions: { - jsonTemplate: this.jsonTemplate, - sampleCSV: "Flights, Save 20% on Flights, Get 20% off on flight bookings with this exclusive coupon, https://source.unsplash.com/1080x720/?travel\nHotel, 50% Off Hotel Bookings, Enjoy a 50% discount on hotel reservations using this limited-time coupon, https://source.unsplash.com/1080x720/?hotel", - maxRecords: 5, - hintText: '', - systemMessage: `each row has a coupon title and listImage URL`, - callback: await this.handleAIReq.bind(this), - }, - }).smartShowEmptyState(); - } - - async handleAIReq(err, data) { - if ( - err || - !data || - typeof data !== "object" || - !Object.keys(data).length || !data.data || !data.data.items || !data.data.items.length - ) { - return buildfire.dialog.toast({ - message: "Bad AI request, please try changing your request.", - type: "danger", - }); - } - - this.itemsList = data.data.items; - //Check image URLs - let coupons = this.itemsList.map(item => { - return new Promise((resolve, reject) => { - this.elimanateNotFoundImages(item.listImage).then(res => { - if (res.isValid) { - item.listImage = res.newURL; - resolve(item); - } else { - reject('image URL not valid'); - } - }) - }) - }) - - // Check image URLs and apply defaults - Promise.allSettled(coupons).then(results => { - this.itemsList = []; - results.forEach(res => { - if(res.status == 'fulfilled') { - const coupon = res.value; - if (coupon) { - this.itemsList.push(coupon); - } - } - }) - - if (!this.itemsList.length) { - return buildfire.dialog.toast({ - message: "Bad AI request, please try changing your request.", - type: "danger", - }); - } - - // reset old data - this.getOldCoupons().then(oldCouponsList => { - if (this.stateSeederInstance.requestResult.resetData){ - this.deleteAll(oldCouponsList) - } - // save new data - this.itemsList.forEach(item => { - item = this._applyDefaults(item); - buildfire.datastore.insert(item, this.tagNames.COUPON_ITEMS, (err, res)=> { - if (res) { - item.deepLinkId = res.id, - item.deepLinkUrl = buildfire.deeplink.createLink({ id: res.id }) - buildfire.datastore.update(res.id, item, this.tagNames.COUPON_ITEMS, (err, res) => { - if (res) - buildfire.messaging.sendMessageToWidget({ type: "ImportCSV", importing: false }); - this.reloadCoupons(); - }) - } - }) - }) - }) - }) - this.stateSeederInstance.requestResult.complete(); - } - - // UTILITIES - _applyDefaults(item) { - if (item.title) { - return { - title: item.title, - summary: item.summary || "N/A", - listImage: item.listImage || "", - startOn: Date.now(), - expiresOn: Math.trunc(Date.now() + Math.random() * 8640000000), - links: [], - preRedemptionText: "Redeem Now", - postRedemptionText: "Coupon Redeemed", - carouselImages: [ - { - "action": "noAction", - "iconUrl": item.listImage, - "title": "image" - } - ], - rank: 30, - addressTitle: "", - location: { - addressTitle: "", - coordinates: { - lat: "", - lng: "" - } - }, - Categories: [], - reuseAfterInMinutes: -1, - dateCreated: Date.now(), - deepLinkUrl: '', // must have an id from datatore - deepLinkId: '', //same as item id - SelectedCategories: [], - } - } - return null - } - - elimanateNotFoundImages = (url) => { - const optimisedURL = url.replace('1080x720', '100x100'); - return new Promise((resolve) => { - if (url.includes("http")){ - const xhr = new XMLHttpRequest(); - xhr.open("GET", optimisedURL); - xhr.onerror = (error) => { - console.warn('provided URL is not a valid image', error); - resolve({isValid: false, newURL: null}); - } - xhr.onload = () => { - if (xhr.responseURL.includes('source-404') || xhr.status == 404) { - return resolve({isValid: false ,newURL: null}); - } else { - return resolve({isValid: true, newURL: xhr.responseURL.replace('h=100', 'h=720').replace('w=100', 'w=1080') }); - } - }; - xhr.send(); - } else resolve(false); - }); - }; - - async getCurrentUser() { - return new Promise((resolve, reject) => { - buildfire.auth.getCurrentUser((err, currentUser) => { - if (!currentUser) { - buildfire.auth.login({ allowCancel: false }, (err, user) => { - if (!user) { - this.getCurrentUser(); - } else { - resolve(user); - } - }); - } else { - resolve(currentUser); - } - }); - }); - } - - getOldCoupons() { - return new Promise((resolve, reject) => { - buildfire.datastore.search( - {}, - this.tagNames.COUPON_ITEMS, - (err, results) => { - if (err) reject(err); - resolve(results); - } - ); - }); - } - - deleteAll(oldCouponsList) { - const promises = oldCouponsList.map((coupon) => - this.deleteCoupon(coupon.id, this.tagNames.COUPON_ITEMS) - ); - return Promise.all(promises); - } - - deleteCoupon(taskId, tag) { - return new Promise((resolve, reject) => { - buildfire.datastore.delete(taskId, tag, (err, res) => { - if (err) reject(err); - resolve(res); - }); - }); - } - } \ No newline at end of file diff --git a/control/content/controllers/content.home.controller.js b/control/content/controllers/content.home.controller.js index 72e378c..3143687 100644 --- a/control/content/controllers/content.home.controller.js +++ b/control/content/controllers/content.home.controller.js @@ -3,8 +3,8 @@ (function (angular, buildfire) { angular .module('couponPluginContent') - .controller('ContentHomeCtrl', ['$scope', '$timeout', 'TAG_NAMES', 'SORT', 'SORT_FILTER', 'STATUS_CODE', 'DataStore', 'LAYOUTS', 'Buildfire', 'Modals', 'RankOfLastFilter', 'RankOfLastItem', '$csv', 'Utils', '$rootScope', 'PluginEvents', - function ($scope, $timeout, TAG_NAMES, SORT, SORT_FILTER, STATUS_CODE, DataStore, LAYOUTS, Buildfire, Modals, RankOfLastFilter, RankOfLastItem, $csv, Utils, $rootScope, PluginEvents) { + .controller('ContentHomeCtrl', ['$scope', '$timeout', 'TAG_NAMES', 'SORT', 'SORT_FILTER', 'STATUS_CODE', 'DataStore', 'LAYOUTS', 'Buildfire', 'Modals', 'RankOfLastFilter', 'RankOfLastItem', '$csv', 'Utils', '$rootScope', 'PluginEvents', 'StateSeeder', + function ($scope, $timeout, TAG_NAMES, SORT, SORT_FILTER, STATUS_CODE, DataStore, LAYOUTS, Buildfire, Modals, RankOfLastFilter, RankOfLastItem, $csv, Utils, $rootScope, PluginEvents, StateSeeder) { var ContentHome = this; ContentHome.searchValue = ""; ContentHome.filter = null; @@ -816,6 +816,7 @@ $scope.$digest(); }) } + let aiStateSeeder = StateSeeder.initStateSeeder(ContentHome.reloadCoupons); ContentHome.loadMoreItems = function (str) { Buildfire.spinner.show(); @@ -884,9 +885,6 @@ ContentHome.busy = false; ContentHome.isBusy = false; console.log("-------------------llll", ContentHome.items) - if (!ContentHome.items || !ContentHome.items.length) { - new StateSeeder(TAG_NAMES, DataStore, ContentHome.reloadCoupons); - } Buildfire.spinner.hide(); $scope.$digest(); }); @@ -1407,6 +1405,5 @@ return ContentHome.filter; }, updateItemsWithDelay, true); - }]); })(window.angular, window.buildfire); diff --git a/control/content/index.html b/control/content/index.html index bceb0c2..957238f 100755 --- a/control/content/index.html +++ b/control/content/index.html @@ -37,7 +37,6 @@ - diff --git a/widget/controllers/widget.home.controller.js b/widget/controllers/widget.home.controller.js index be20095..b91ade1 100644 --- a/widget/controllers/widget.home.controller.js +++ b/widget/controllers/widget.home.controller.js @@ -146,7 +146,6 @@ }; WidgetHome.init = function (cb) { - Buildfire.spinner.show(); var success = function (result) { Buildfire.spinner.hide(); if (result && result.data) { @@ -339,6 +338,7 @@ WidgetHome.getItems = function (filter) { Buildfire.spinner.show(); var successAll = function (resultAll) { + Buildfire.spinner.hide(); Buildfire.spinner.hide(); if (resultAll) { resultAll.forEach(function (_item) { From 966940621814fd0ef85ae121456acf35279f749c Mon Sep 17 00:00:00 2001 From: Abdalla Dimes Date: Mon, 11 Sep 2023 16:05:29 +0300 Subject: [PATCH 3/5] fix: Used the DataStore service instead of buildfire.datastore --- control/content/app.services.js | 93 ++++++++----------- .../controllers/content.home.controller.js | 13 ++- widget/controllers/widget.home.controller.js | 1 - 3 files changed, 48 insertions(+), 59 deletions(-) diff --git a/control/content/app.services.js b/control/content/app.services.js index 8ac0b24..781b65b 100644 --- a/control/content/app.services.js +++ b/control/content/app.services.js @@ -247,8 +247,7 @@ buildfire.analytics.unregisterEvent('coupon_item_view_' + key); } }; - }]).factory('StateSeeder', ['TAG_NAMES' ,function(TAG_NAMES) { - // let reloadCoupons; + }]).factory('StateSeeder', ['TAG_NAMES', 'DataStore' ,function(TAG_NAMES, DataStore) { let itemsList; let stateSeederInstance; let reloadCoupons; @@ -289,7 +288,7 @@ }) }) - // Check image URLs and apply defaults + // Check image URLs Promise.allSettled(coupons).then(results => { itemsList = []; results.forEach(res => { @@ -308,27 +307,26 @@ }); } - // reset old data - getOldCoupons().then(oldCouponsList => { - if (stateSeederInstance.requestResult.resetData){ - deleteAll(oldCouponsList) - } + // reset old data + checkOldData().then(() => { // save new data - itemsList.forEach(item => { - item = _applyDefaults(item); - buildfire.datastore.insert(item, TAG_NAMES.COUPON_ITEMS, (err, res)=> { - if (res) { - item.deepLinkId = res.id, - item.deepLinkUrl = buildfire.deeplink.createLink({ id: res.id }) - buildfire.datastore.update(res.id, item, TAG_NAMES.COUPON_ITEMS, (err, res) => { - if (res) - buildfire.messaging.sendMessageToWidget({ type: "ImportCSV", importing: false }); - reloadCoupons(); - }) - } - }) + buildfire.messaging.sendMessageToWidget({ type: "ImportCSV", importing: true }); + itemsList.forEach((item, i)=> { + item = _applyDefaults(item); + DataStore.insert(item, TAG_NAMES.COUPON_ITEMS).then((res)=> { + if (res) { + item.deepLinkId = res.id, + item.deepLinkUrl = buildfire.deeplink.createLink({ id: res.id }) + DataStore.update(res.id, item, TAG_NAMES.COUPON_ITEMS).then((res) => { + }) + if(i == (itemsList.length - 1)) { + buildfire.messaging.sendMessageToWidget({ type: "ImportCSV", importing: false }); + reloadCoupons(); + } + } + }) }) - }) + }) stateSeederInstance.requestResult.complete(); }) } @@ -392,46 +390,29 @@ xhr.send(); } else resolve(false); }); - }; - - - let getOldCoupons = function() { - return new Promise((resolve, reject) => { - buildfire.datastore.search( - {}, - TAG_NAMES.COUPON_ITEMS, - (err, results) => { - if (err) reject(err); - resolve(results); - } - ); - }); - } + };`` - let deleteAll = function(oldCouponsList) { - const promises = oldCouponsList.map((coupon) => - deleteCoupon(coupon.id, TAG_NAMES.COUPON_ITEMS) - ); - return Promise.all(promises); - } - - let deleteCoupon = function(taskId, tag) { - return new Promise((resolve, reject) => { - buildfire.datastore.delete(taskId, tag, (err, res) => { - if (err) reject(err); - resolve(res); - }); - }); + let checkOldData = function() { + return new Promise(resolve => { + if (stateSeederInstance.requestResult.resetData){ + DataStore.save([], TAG_NAMES.COUPON_ITEMS).then(() => { + resolve(); + }) + } else { + resolve(); + } + }) } + return { - initStateSeeder: function(callback) { - reloadCoupons = callback; + initStateSeeder: function(onDataChange) { + reloadCoupons = onDataChange; stateSeederInstance = new buildfire.components.aiStateSeeder({ generateOptions: { userMessage: `List sample coupons for a new [business-type]`, maxRecords: 5, systemMessage: - "title is the coupon title, summary is a brief summary, listImage is an image URL related to title and the list type, use source.unsplash.com for images URL image should be 1080x720, URL should not have premium_photo or source.unsplash.com/random.", + "listImage is an 1080x720 image URL related to title and the list type, use source.unsplash.com for images, URL should not have premium_photo or source.unsplash.com/random.", jsonTemplate: jsonTemplate, callback: handleAIReq.bind(this), hintText: 'Replace values between brackets to match your requirements.', @@ -441,9 +422,9 @@ sampleCSV: "Save 20% on Flights, Get 20% off on flight bookings with this exclusive coupon, https://source.unsplash.com/1080x720/?travel\n50% Off Hotel Bookings, Enjoy a 50% discount on hotel reservations using this limited-time coupon, https://source.unsplash.com/1080x720/?hotel\nCar Rental Special Offer, Rent a car for 7 days and pay for only 5 days with this coupon code, https://source.unsplash.com/1080x720/?car\nAdventure Tour Promo, Book an adventure tour and receive a free equipment rental worth $50 using this coupon, https://source.unsplash.com/1080x720/?adventure", maxRecords: 5, hintText: '', - systemMessage: `each row has a coupon title and listImage URL`, + systemMessage: '', callback: handleAIReq.bind(this), - }, + }, }).smartShowEmptyState(); }, } diff --git a/control/content/controllers/content.home.controller.js b/control/content/controllers/content.home.controller.js index 3143687..ad43d7f 100644 --- a/control/content/controllers/content.home.controller.js +++ b/control/content/controllers/content.home.controller.js @@ -6,6 +6,12 @@ .controller('ContentHomeCtrl', ['$scope', '$timeout', 'TAG_NAMES', 'SORT', 'SORT_FILTER', 'STATUS_CODE', 'DataStore', 'LAYOUTS', 'Buildfire', 'Modals', 'RankOfLastFilter', 'RankOfLastItem', '$csv', 'Utils', '$rootScope', 'PluginEvents', 'StateSeeder', function ($scope, $timeout, TAG_NAMES, SORT, SORT_FILTER, STATUS_CODE, DataStore, LAYOUTS, Buildfire, Modals, RankOfLastFilter, RankOfLastItem, $csv, Utils, $rootScope, PluginEvents, StateSeeder) { var ContentHome = this; + let stateSeeder; + $rootScope.$watch('showEmptyState', function(newValue, oldValue) { + if (typeof newValue === 'undefined' || newValue == true) { + stateSeeder = StateSeeder.initStateSeeder(() => {ContentHome.reloadCoupons()}); + } + }) ContentHome.searchValue = ""; ContentHome.filter = null; ContentHome.isBusy = true; @@ -816,7 +822,6 @@ $scope.$digest(); }) } - let aiStateSeeder = StateSeeder.initStateSeeder(ContentHome.reloadCoupons); ContentHome.loadMoreItems = function (str) { Buildfire.spinner.show(); @@ -862,7 +867,11 @@ ContentHome.items = ContentHome.items ? ContentHome.items.concat(result) : result; Buildfire.datastore.search(searchOptionsFilterForItemList, TAG_NAMES.COUPON_CATEGORIES, function (err, resultFilter) { - + if (!ContentHome.items.length) { + $rootScope.showEmptyState = true; + } else { + $rootScope.showEmptyState = false; + } if (err) { Buildfire.spinner.hide(); return console.error('-----------err in getting list-------------', err); diff --git a/widget/controllers/widget.home.controller.js b/widget/controllers/widget.home.controller.js index b91ade1..8349525 100644 --- a/widget/controllers/widget.home.controller.js +++ b/widget/controllers/widget.home.controller.js @@ -338,7 +338,6 @@ WidgetHome.getItems = function (filter) { Buildfire.spinner.show(); var successAll = function (resultAll) { - Buildfire.spinner.hide(); Buildfire.spinner.hide(); if (resultAll) { resultAll.forEach(function (_item) { From a72fd63e56e8016cccc60c9ea9b0b5c6f590f1ae Mon Sep 17 00:00:00 2001 From: Abdalla Dimes Date: Mon, 11 Sep 2023 17:42:03 +0300 Subject: [PATCH 4/5] fix: Hotfixes --- control/content/app.services.js | 32 ++++++++++--------- .../controllers/content.home.controller.js | 7 +++- widget/app.js | 2 +- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/control/content/app.services.js b/control/content/app.services.js index 781b65b..25e4227 100644 --- a/control/content/app.services.js +++ b/control/content/app.services.js @@ -311,22 +311,23 @@ checkOldData().then(() => { // save new data buildfire.messaging.sendMessageToWidget({ type: "ImportCSV", importing: true }); - itemsList.forEach((item, i)=> { - item = _applyDefaults(item); - DataStore.insert(item, TAG_NAMES.COUPON_ITEMS).then((res)=> { - if (res) { - item.deepLinkId = res.id, - item.deepLinkUrl = buildfire.deeplink.createLink({ id: res.id }) - DataStore.update(res.id, item, TAG_NAMES.COUPON_ITEMS).then((res) => { - }) - if(i == (itemsList.length - 1)) { - buildfire.messaging.sendMessageToWidget({ type: "ImportCSV", importing: false }); - reloadCoupons(); + for (let i = 0; i < itemsList.length; i++) { + itemsList[i] = _applyDefaults(itemsList[i]); + DataStore.insert(itemsList[i], TAG_NAMES.COUPON_ITEMS).then((res)=> { + if (res) { + itemsList[i].deepLinkId = res.id, + itemsList[i].deepLinkUrl = buildfire.deeplink.createLink({ id: res.id }) + DataStore.update(res.id, itemsList[i], TAG_NAMES.COUPON_ITEMS).then((res) => { + }) + if(i == (itemsList.length - 1)) { + buildfire.messaging.sendMessageToWidget({ type: "ImportCSV", importing: false }); + reloadCoupons(); + } } - } - }) - }) - }) + }) + + } + }) stateSeederInstance.requestResult.complete(); }) } @@ -426,6 +427,7 @@ callback: handleAIReq.bind(this), }, }).smartShowEmptyState(); + return true; }, } }]) diff --git a/control/content/controllers/content.home.controller.js b/control/content/controllers/content.home.controller.js index ad43d7f..23cb9bf 100644 --- a/control/content/controllers/content.home.controller.js +++ b/control/content/controllers/content.home.controller.js @@ -8,7 +8,7 @@ var ContentHome = this; let stateSeeder; $rootScope.$watch('showEmptyState', function(newValue, oldValue) { - if (typeof newValue === 'undefined' || newValue == true) { + if ((typeof newValue === 'undefined' || newValue == true) && !stateSeeder) { stateSeeder = StateSeeder.initStateSeeder(() => {ContentHome.reloadCoupons()}); } }) @@ -819,6 +819,11 @@ ContentHome.noMore = false; } ContentHome.items = result; + if (!ContentHome.items.length) { + $rootScope.showEmptyState = true; + } else { + $rootScope.showEmptyState = false; + } $scope.$digest(); }) } diff --git a/widget/app.js b/widget/app.js index b91aebb..b6da87b 100644 --- a/widget/app.js +++ b/widget/app.js @@ -327,7 +327,7 @@ break; case 'ImportCSV': msg.importing ? $rootScope.importingCSV = true : $rootScope.importingCSV = false; - if(!$rootScope.importingCSV) window.location.reload(); + if(!$rootScope.importingCSV) window.location.href = window.location.href; default: ViewStack.popAllViews(true); } From 62adff145886416a2539573bc489772de1fb43ff Mon Sep 17 00:00:00 2001 From: Abdalla Dimes Date: Mon, 18 Sep 2023 19:33:04 +0300 Subject: [PATCH 5/5] fix: Applied latest changes --- control/content/app.services.js | 141 ++++++++++-------- control/content/assets/css/jquery-ui.css | 3 +- control/content/assets/css/sortable.css | 12 +- .../controllers/content.home.controller.js | 17 ++- .../controllers/content.item.controller.js | 3 +- control/content/templates/home.html | 32 ++-- 6 files changed, 122 insertions(+), 86 deletions(-) diff --git a/control/content/app.services.js b/control/content/app.services.js index 25e4227..1afe593 100644 --- a/control/content/app.services.js +++ b/control/content/app.services.js @@ -247,10 +247,10 @@ buildfire.analytics.unregisterEvent('coupon_item_view_' + key); } }; - }]).factory('StateSeeder', ['TAG_NAMES', 'DataStore' ,function(TAG_NAMES, DataStore) { + }]).factory('StateSeeder', ['TAG_NAMES', 'DataStore', 'RankOfLastItem', '$rootScope', '$timeout' ,function(TAG_NAMES, DataStore, RankOfLastItem, $rootScope, $timeout) { let itemsList; let stateSeederInstance; - let reloadCoupons; + $rootScope.oldCouponsIds = []; let jsonTemplate = { items: [ { @@ -260,7 +260,7 @@ }, ], }; - let handleAIReq = function(err, data) { + let handleAIReq = function(isImport, err, data) { if ( err || !data || @@ -272,63 +272,81 @@ type: "danger", }); } - itemsList = data.data.items; //Check image URLs let coupons = itemsList.map(item => { - return new Promise((resolve, reject) => { - elimanateNotFoundImages(item.listImage).then(res => { - if (res.isValid) { - item.listImage = res.newURL; - resolve(item); - } else { - reject('image URL not valid'); - } + return new Promise((resolve, reject) => { + checkNotFoundImages(item.listImage ?? "", isImport).then(res => { + if (res.isValid) { + item.listImage = res.newURL; + resolve(item); + } else { + reject('image URL not valid'); + } + }) }) - }) }) - + // Check image URLs Promise.allSettled(coupons).then(results => { - itemsList = []; - results.forEach(res => { - if(res.status == 'fulfilled') { - const coupon = res.value; - if (coupon) { - itemsList.push(coupon); - } + itemsList = []; + results.forEach(res => { + if(res.status == 'fulfilled') { + const coupon = res.value; + if (coupon) { + itemsList.push(coupon); + } + } + }) + if (!itemsList.length) { + stateSeederInstance?.requestResult?.complete(); + return buildfire.dialog.toast({ + message: "Bad AI request, please try changing your request.", + type: "danger", + }); } - }) - if (!itemsList.length) { - stateSeederInstance.requestResult.complete(); - return buildfire.dialog.toast({ - message: "Bad AI request, please try changing your request.", - type: "danger", - }); - } - + // reset old data checkOldData().then(() => { - // save new data + // save new data buildfire.messaging.sendMessageToWidget({ type: "ImportCSV", importing: true }); - for (let i = 0; i < itemsList.length; i++) { - itemsList[i] = _applyDefaults(itemsList[i]); - DataStore.insert(itemsList[i], TAG_NAMES.COUPON_ITEMS).then((res)=> { - if (res) { - itemsList[i].deepLinkId = res.id, - itemsList[i].deepLinkUrl = buildfire.deeplink.createLink({ id: res.id }) - DataStore.update(res.id, itemsList[i], TAG_NAMES.COUPON_ITEMS).then((res) => { - }) - if(i == (itemsList.length - 1)) { - buildfire.messaging.sendMessageToWidget({ type: "ImportCSV", importing: false }); - reloadCoupons(); + let promises = itemsList.map((item, i) => { + return new Promise((resolve, reject) => { + itemsList[i] = _applyDefaults(itemsList[i]); + RankOfLastItem.setRank(itemsList[i].rank); + DataStore.insert(itemsList[i], TAG_NAMES.COUPON_ITEMS).then((res)=> { + if (res) { + $rootScope.oldCouponsIds.push(res.id); + itemsList[i].deepLinkId = res.id, + itemsList[i].deepLinkUrl = buildfire.deeplink.createLink({ id: res.id }) + new Deeplink({ + deeplinkId: res.id, + name: res.data.title, + imageUrl: res.data.listImage ? res.data.listImage : null, + deeplinkData: { + id: res.id, + } + }).save((err, deepLinkData) => { + itemsList[i].deepLinkId = deepLinkData.deeplinkId; + DataStore.update(res.id, itemsList[i], TAG_NAMES.COUPON_ITEMS).then(() => { + }) + resolve(); + }); } - } + }) + + }); + }) + Promise.allSettled(promises).then(() => { + $timeout(()=> { + buildfire.messaging.sendMessageToWidget({ type: "ImportCSV", importing: false }); + $rootScope.reloadCoupons = true; }) + $rootScope.reloadCoupons = true; + }).catch(err => console.warn('error while saving data: ', err)) - } }) - stateSeederInstance.requestResult.complete(); + stateSeederInstance?.requestResult?.complete(); }) } @@ -337,21 +355,21 @@ if (item.title) { return { title: item.title, - summary: item.summary || "N/A", + summary: item.summary || "", listImage: item.listImage || "", startOn: Date.now(), expiresOn: Math.trunc(Date.now() + Math.random() * 8640000000), links: [], preRedemptionText: "Redeem Now", postRedemptionText: "Coupon Redeemed", - carouselImages: [ + carouselImages: item.listImage ? [ { "action": "noAction", "iconUrl": item.listImage, "title": "image" } - ], - rank: 30, + ] : [], + rank: RankOfLastItem.getRank() ? RankOfLastItem.getRank() + 10: 10, addressTitle: "", location: { addressTitle: "", @@ -371,7 +389,7 @@ return null } - let elimanateNotFoundImages = function(url) { + let checkNotFoundImages = function(url, isImport) { const optimisedURL = url.replace('1080x720', '100x100'); return new Promise((resolve) => { if (url.includes("http")){ @@ -379,23 +397,27 @@ xhr.open("GET", optimisedURL); xhr.onerror = (error) => { console.warn('provided URL is not a valid image', error); - resolve({isValid: false, newURL: null}); + resolve({isValid: true, newURL: isImport ? null : 'https://dummyimage.com/300x300/d7dbde/ffffff.png'}); } xhr.onload = () => { if (xhr.responseURL.includes('source-404') || xhr.status == 404) { - return resolve({isValid: false ,newURL: null}); + return resolve({isValid: true ,newURL: isImport ? null : 'https://dummyimage.com/300x300/d7dbde/ffffff.png'}); } else { return resolve({isValid: true, newURL: xhr.responseURL.replace('h=100', 'h=720').replace('w=100', 'w=1080') }); } }; xhr.send(); - } else resolve(false); + } else resolve({isValid: true ,newURL: isImport ? null : 'https://dummyimage.com/300x300/d7dbde/ffffff.png'}); }); };`` let checkOldData = function() { return new Promise(resolve => { if (stateSeederInstance.requestResult.resetData){ + $rootScope.oldCouponsIds.forEach(id => { + Deeplink.deleteById(id); + }) + $rootScope.oldCouponsIds = []; DataStore.save([], TAG_NAMES.COUPON_ITEMS).then(() => { resolve(); }) @@ -406,25 +428,24 @@ } return { - initStateSeeder: function(onDataChange) { - reloadCoupons = onDataChange; + initStateSeeder: function() { stateSeederInstance = new buildfire.components.aiStateSeeder({ generateOptions: { - userMessage: `List sample coupons for a new [business-type]`, + userMessage: `List sample coupons for a new [Optics Shop]`, maxRecords: 5, systemMessage: "listImage is an 1080x720 image URL related to title and the list type, use source.unsplash.com for images, URL should not have premium_photo or source.unsplash.com/random.", jsonTemplate: jsonTemplate, - callback: handleAIReq.bind(this), + callback: handleAIReq.bind(this, false), hintText: 'Replace values between brackets to match your requirements.', }, importOptions: { jsonTemplate: jsonTemplate, sampleCSV: "Save 20% on Flights, Get 20% off on flight bookings with this exclusive coupon, https://source.unsplash.com/1080x720/?travel\n50% Off Hotel Bookings, Enjoy a 50% discount on hotel reservations using this limited-time coupon, https://source.unsplash.com/1080x720/?hotel\nCar Rental Special Offer, Rent a car for 7 days and pay for only 5 days with this coupon code, https://source.unsplash.com/1080x720/?car\nAdventure Tour Promo, Book an adventure tour and receive a free equipment rental worth $50 using this coupon, https://source.unsplash.com/1080x720/?adventure", maxRecords: 5, - hintText: '', - systemMessage: '', - callback: handleAIReq.bind(this), + hintText: 'Each row should start with a Coupon title, Summary, and Image URL', + systemMessage: 'listImage is an image URL, summary and listImage are optional', + callback: handleAIReq.bind(this, true), }, }).smartShowEmptyState(); return true; diff --git a/control/content/assets/css/jquery-ui.css b/control/content/assets/css/jquery-ui.css index e827fb1..b254cad 100644 --- a/control/content/assets/css/jquery-ui.css +++ b/control/content/assets/css/jquery-ui.css @@ -1273,5 +1273,6 @@ body .ui-tooltip { } .draggable-list-view.wide-list{ - overflow: visible !important; + /* overflow: visible !important; */ + overflow-y: scroll; } \ No newline at end of file diff --git a/control/content/assets/css/sortable.css b/control/content/assets/css/sortable.css index 49456b6..4b9c30b 100644 --- a/control/content/assets/css/sortable.css +++ b/control/content/assets/css/sortable.css @@ -10,9 +10,7 @@ .draggable-list-view .d-item.square-icon .media-holder{ margin-right: .5rem; object-fit: cover; -} -.draggable-list-view .d-item.square-icon .media-holder { - object-fit: cover; + min-width: 50px; } .draggable-list-view.no-media .d-item .copy{ display: flex; @@ -91,6 +89,7 @@ html[buildfire] .d-item .btn-edit-icon:hover::after{ .media-holder.pull-left > img { object-fit: cover !important; + min-width: 50px; } .draggable-list-view.carousel-items .d-item span.title { @@ -103,6 +102,13 @@ html[buildfire] .d-item .btn-edit-icon:hover::after{ top: 3px } +.draggable-list-view .d-item.double-line .copy .delete-icon-cont { + display: flex; +} +.draggable-list-view .d-item.double-line .overflow-hidden { + overflow: hidden; +} + a.text-primary.text { top: -15px !important } diff --git a/control/content/controllers/content.home.controller.js b/control/content/controllers/content.home.controller.js index 23cb9bf..36fd2f7 100644 --- a/control/content/controllers/content.home.controller.js +++ b/control/content/controllers/content.home.controller.js @@ -3,13 +3,13 @@ (function (angular, buildfire) { angular .module('couponPluginContent') - .controller('ContentHomeCtrl', ['$scope', '$timeout', 'TAG_NAMES', 'SORT', 'SORT_FILTER', 'STATUS_CODE', 'DataStore', 'LAYOUTS', 'Buildfire', 'Modals', 'RankOfLastFilter', 'RankOfLastItem', '$csv', 'Utils', '$rootScope', 'PluginEvents', 'StateSeeder', - function ($scope, $timeout, TAG_NAMES, SORT, SORT_FILTER, STATUS_CODE, DataStore, LAYOUTS, Buildfire, Modals, RankOfLastFilter, RankOfLastItem, $csv, Utils, $rootScope, PluginEvents, StateSeeder) { + .controller('ContentHomeCtrl', ['$scope', '$timeout', 'TAG_NAMES', 'SORT', 'SORT_FILTER', 'STATUS_CODE', 'DataStore', 'LAYOUTS', 'Buildfire', 'Modals', 'RankOfLastFilter', 'RankOfLastItem', '$csv', 'Utils', '$rootScope', 'PluginEvents', 'StateSeeder', '$filter', + function ($scope, $timeout, TAG_NAMES, SORT, SORT_FILTER, STATUS_CODE, DataStore, LAYOUTS, Buildfire, Modals, RankOfLastFilter, RankOfLastItem, $csv, Utils, $rootScope, PluginEvents, StateSeeder, $filter) { var ContentHome = this; let stateSeeder; $rootScope.$watch('showEmptyState', function(newValue, oldValue) { if ((typeof newValue === 'undefined' || newValue == true) && !stateSeeder) { - stateSeeder = StateSeeder.initStateSeeder(() => {ContentHome.reloadCoupons()}); + stateSeeder = StateSeeder.initStateSeeder(); } }) ContentHome.searchValue = ""; @@ -805,6 +805,7 @@ }; ContentHome.reloadCoupons = function () { + ContentHome.isBusy = true; Buildfire.datastore.search(ContentHome.searchOptionsForItems, TAG_NAMES.COUPON_ITEMS, function (err, result) { if (err) { Buildfire.spinner.hide(); @@ -819,12 +820,14 @@ ContentHome.noMore = false; } ContentHome.items = result; + ContentHome.isBusy = false; + $rootScope.reloadCoupons = false; + $scope.$digest(); if (!ContentHome.items.length) { $rootScope.showEmptyState = true; } else { $rootScope.showEmptyState = false; } - $scope.$digest(); }) } @@ -1419,5 +1422,11 @@ return ContentHome.filter; }, updateItemsWithDelay, true); + $rootScope.$watch('reloadCoupons', function(newValue, oldValue) { + if (newValue) { + ContentHome.reloadCoupons(); + } + }) }]); + })(window.angular, window.buildfire); diff --git a/control/content/controllers/content.item.controller.js b/control/content/controllers/content.item.controller.js index bffb053..b292ccd 100644 --- a/control/content/controllers/content.item.controller.js +++ b/control/content/controllers/content.item.controller.js @@ -495,8 +495,9 @@ } //# + $rootScope.showEmptyState = false; buildfire.messaging.sendMessageToWidget({}); - Location.goToHome(); + $location.path('home'); }; ContentItem.setLocation = function (data) { console.log( diff --git a/control/content/templates/home.html b/control/content/templates/home.html index d1e98ef..61227c3 100644 --- a/control/content/templates/home.html +++ b/control/content/templates/home.html @@ -138,35 +138,33 @@

Coupons

Loading...

+
-
- +
-
-
- {{item.data.title}} - {{item.data.summary}} -
- -
+
+ {{item.data.title}} + {{item.data.summary}} +
+ +
Expires On
{{item.data.expiresOn | date :'mediumDate'}}
+ class="title pull-left ellipsis" ng-show="item.data.expiresOn!=''" ng-class="{'expired-item' : (ContentHome.currentDateTimestamp - item.data.expiresOn) > 1}">Expires On
{{item.data.expiresOn | date :'mediumDate'}} Expires On
No Expiration
+ class="title pull-left ellipsis" ng-hide="item.data.expiresOn!=''">Expires On
No Expiration
-
+
-
+