From c6579396f745dd4a6c4d6d8672bbf0a969730bf6 Mon Sep 17 00:00:00 2001 From: alialaqrabawi3 Date: Tue, 2 Jul 2024 23:48:19 +0300 Subject: [PATCH 1/4] feat(mcd-melinda): handle setting tab , extract WYSIWYG content , handle search engine --- plugin.json | 2 +- src/control/content/index.html | 181 +++--------------- src/control/content/index.js | 153 +++++++++++++++ src/control/content/style.css | 15 ++ src/control/settings/index.html | 39 +++- src/control/settings/index.js | 56 ++++++ src/control/settings/style.css | 97 ++++++++++ src/control/shared/utils.js | 28 +++ src/widget/global/js/models/Setting.js | 19 ++ src/widget/global/js/repositories/Content.js | 16 ++ src/widget/global/js/repositories/Settings.js | 43 +++++ src/widget/global/js/services/searchEngine.js | 50 +++++ src/widget/widget.js | 9 +- webpack/build.config.js | 2 +- webpack/dev.config.js | 2 +- 15 files changed, 544 insertions(+), 168 deletions(-) create mode 100644 src/control/content/index.js create mode 100644 src/control/content/style.css create mode 100644 src/control/settings/index.js create mode 100644 src/control/settings/style.css create mode 100644 src/control/shared/utils.js create mode 100644 src/widget/global/js/models/Setting.js create mode 100644 src/widget/global/js/repositories/Content.js create mode 100644 src/widget/global/js/repositories/Settings.js create mode 100644 src/widget/global/js/services/searchEngine.js diff --git a/plugin.json b/plugin.json index 74cbf94..10adefe 100644 --- a/plugin.json +++ b/plugin.json @@ -15,7 +15,7 @@ "enabled":true } , "settings":{ - "enabled":false + "enabled":true } } ,"widget":{ diff --git a/src/control/content/index.html b/src/control/content/index.html index 37cd540..bb99d22 100644 --- a/src/control/content/index.html +++ b/src/control/content/index.html @@ -2,179 +2,46 @@ - + - + + - + + - + + + + + + + -
- -
-
-
- Text -
+
+ +
+
+
+ Content
-
-
-
- -
+
+
+
+
+
- - +
diff --git a/src/control/content/index.js b/src/control/content/index.js new file mode 100644 index 0000000..e994d3c --- /dev/null +++ b/src/control/content/index.js @@ -0,0 +1,153 @@ +let textPluginApp = angular.module('textPlugin', ['ui.tinymce']); + +textPluginApp.controller('textPluginCtrl', ['$scope', function ($scope) { + var datastoreInitialized = false; + + $scope.searchEngineIndexing = false; + + $scope.editorOptions = { + plugins: 'advlist autolink link image lists charmap print preview', + skin: 'lightgray', + trusted: true, + theme: 'modern', + format: 'html', + convert_urls: false, + relative_urls: false + + }; + + $scope.data = { + content: { + carouselImages: [], text: "

 

" + }, design: { + backgroundImage: null, backgroundBlur: 0, selectedLayout: 1 + } + }; + + // create a new instance of the buildfire carousel editor + var editor = new buildfire.components.carousel.editor("#carousel"); + + /* + * Go pull any previously saved data + * */ + buildfire.datastore.get(function (err, result) { + + if (!err) { + datastoreInitialized = true; + } else { + console.error("Error: ", err); + return; + } + + if (result && result.data && !angular.equals({}, result.data) && result.id) { + if (!result.data.design) result.data.design = $scope.data.design; + $scope.data = result.data; + $scope.id = result.id; + if ($scope.data.content && $scope.data.content.carouselImages) editor.loadItems($scope.data.content.carouselImages); + if (tmrDelay) clearTimeout(tmrDelay); + } else { + $scope.data = { + content: { + text: '

The WYSIWYG (which stands for What You See Is What You Get) allows you to do some really cool stuff. You can add images like this

\ +

\ +

You can even create links like these:
Link to web content like this
Link to a phone number like this 8005551234
Link to an email like this noreply@google.com

\ +

Want to add some super cool videos about this item? You can do that too!

\ +

\ +

You can create bulleted and numbered lists like this:

\ +
    \ +
  • This is an item in a list
  • \ +
  • This is another item in a list
  • \ +
  • This is a last item in a list
  • \ +
\ +

Want more info? Check out our tutorial by clicking the help button at the top of this page.

', + + carouselImages: [{ + "action": "noAction", + "iconUrl": "http://imageserver.prod.s3.amazonaws.com/b55ee984-a8e8-11e5-88d3-124798dea82d/5db61d30-0854-11e6-8963-f5d737bc276b.jpg", + "title": "image 1" + }, { + "action": "noAction", + "iconUrl": "http://imageserver.prod.s3.amazonaws.com/b55ee984-a8e8-11e5-88d3-124798dea82d/31c88a00-0854-11e6-8963-f5d737bc276b.jpeg", + "title": "image 2" + }] + }, design: { + backgroundImage: null, backgroundBlur: 0, selectedLayout: 1 + } + }; + editor.loadItems($scope.data.content.carouselImages); + } + + /* + * watch for changes in data and trigger the saveDataWithDelay function on change + * */ + $scope.$watch('data', saveDataWithDelay, true); + + if (!$scope.$$phase && !$scope.$root.$$phase) { + $scope.$apply(); + } + }); + + Settings.get().then((data) => $scope.searchEngineIndexing = data.searchEngineIndexing); + + + /* + * Call the datastore to save the data object + */ + var saveData = function (newObj) { + if (!datastoreInitialized) { + console.error("Error with datastore didn't get called"); + return; + } + if (newObj.content.text.indexOf("src=\"//") != -1) { + newObj.content.text = newObj.content.text.replace("src=\"//", "src=\"https://") + } + if (newObj == undefined) return; + + if ($scope.frmMain.$invalid) { + console.warn('invalid data, details will not be saved'); + return; + } + + if (!newObj.content || !newObj.design) return; + + buildfire.datastore.save(newObj, function (err, result) { + if (err || !result) { + console.error('Error saving the widget details: ', err); + } else { + console.info('Widget details saved'); + } + }); + }; + var saveSearchEngine = function (content) { + if (!$scope.searchEngineIndexing) return; + buildfire.dynamic.expressions.evaluate({expression: content}, (err, result) => { + if (err) return console.error(err); + const content = extractText(result.evaluatedExpression); + if (!content.title || !content.description) { + SearchEngineService.delete(); + return; + } + SearchEngineService.save(content.title, content.description); + }) + }; + /* + * create an artificial delay so api isnt called on every character entered + * */ + var tmrDelay = null; + + var saveDataWithDelay = function (newObj, oldObj) { + if (tmrDelay) clearTimeout(tmrDelay); + if (angular.equals(newObj, oldObj)) return; + tmrDelay = setTimeout(function () { + saveData(newObj); + saveSearchEngine(newObj.content.text); + + }, 500); + }; + + // this method will be called when a new item added to the list + editor.onAddItems = editor.onDeleteItem = editor.onItemChange = editor.onOrderChange = function () { + $scope.data.content.carouselImages = editor.items; + saveData($scope.data); + }; +}]); diff --git a/src/control/content/style.css b/src/control/content/style.css new file mode 100644 index 0000000..faa8093 --- /dev/null +++ b/src/control/content/style.css @@ -0,0 +1,15 @@ +#frMain { + height: 95vh; +} +.tinymce-editor{ + flex: 1; +} +.tinymce-editor .main { + height: 100%; +} + +/* This rule overrides the height of the TinyMCE editor */ +.tox.tox-tinymce { + min-height: 100% !important; +} + diff --git a/src/control/settings/index.html b/src/control/settings/index.html index 97a74b4..04fa83a 100644 --- a/src/control/settings/index.html +++ b/src/control/settings/index.html @@ -1,10 +1,39 @@ - + - + + + + + + + + + + + + + + + + - -no settings + +
+ +
+ + +

Please note: Any changes to the content will update automatically in + the search engine, but you still need to publish the app for users to see these updates.

+
+
- \ No newline at end of file + diff --git a/src/control/settings/index.js b/src/control/settings/index.js new file mode 100644 index 0000000..17c92da --- /dev/null +++ b/src/control/settings/index.js @@ -0,0 +1,56 @@ +let textPluginApp = angular.module('textSetting', []); + +textPluginApp.controller('textSettingCtrl', ['$scope', function ($scope) { + $scope.searchEngineIndexing = false; + + $scope.handleCheckboxClick = function () { + // initialSearchEngineIndexing to Save settings only if the searchEngineIndexing value has changed + let initialSearchEngineIndexing = $scope.searchEngineIndexing; + $scope.searchEngineIndexing = !$scope.searchEngineIndexing; + + if (!$scope.searchEngineIndexing) { + buildfire.dialog.confirm({ + title: "Disable Search Engine Indexing", + message: "Are you sure you want to disable search engine indexing? All indexed data from this Text WYSIWYG will be removed, and the content will no longer be searchable.", + confirmButton: {type: 'warning', text: 'Disable'}, + }, function (err, isConfirmed) { + $scope.searchEngineIndexing = !isConfirmed; + $scope.$apply(); + + if ($scope.searchEngineIndexing !== initialSearchEngineIndexing) { + Settings.save({searchEngineIndexing: $scope.searchEngineIndexing}); + Content.get().then(function (data) { + $scope.handleSearchEngine(data.data.content.text); + }); + } + }); + } else { + if ($scope.searchEngineIndexing !== initialSearchEngineIndexing) { + Settings.save({searchEngineIndexing: $scope.searchEngineIndexing}); + Content.get().then(function (data) { + $scope.handleSearchEngine(data.data.content.text); + }); + } + } + }; + + $scope.handleSearchEngine = function (content) { + buildfire.dynamic.expressions.evaluate({expression: content}, (err, result) => { + if (err) return console.error(err); + const content = extractText(result.evaluatedExpression); + if (!content.title || !content.description) { + return; + } + if (!$scope.searchEngineIndexing) { + SearchEngineService.delete(); + } else + SearchEngineService.save(content.title, content.description); + }) + }; + + Settings.get().then(function (data) { + $scope.searchEngineIndexing = data.searchEngineIndexing; + $scope.$apply(); + }); +} +]); diff --git a/src/control/settings/style.css b/src/control/settings/style.css new file mode 100644 index 0000000..b6a8a51 --- /dev/null +++ b/src/control/settings/style.css @@ -0,0 +1,97 @@ +/* tooltip */ +.tooltip-container { + display: flex; + align-items: center; + margin-right: 13px !important; + gap: 0.25rem; + flex: 1; +} +.tooltip-container .btn-info-icon { + display: flex; + align-items: center; + justify-content: center; + margin-left: 8px; + min-width: 16px; + min-height: 16px; + width: 16px; + height: 16px; + line-height: 16px; + color: #fff; + position: relative; +} +.tooltip-container .btn-info-icon:after { + content: 'i'; + font-weight: 400; + font-size: 12px; + font-style: normal; + left: 0; + top: auto !important; + height: 100%; +} +.tooltip-container .btn-info-icon .cp-tooltip { + pointer-events: none; + background-color: rgba(0, 0, 0, .80); + color: #fff; + padding: 8px; + border-radius: 4px; + position: absolute; + left: calc(100% + 12px); + top: 0px; + cursor: auto; + font-size: 12px; + text-align: left; + width: 200px; + opacity: 0; + transform: scale(.1); + transition: opacity ease .1s, transform ease .1s; + transform-origin: left; + z-index: 100; + font-weight: 400; + line-height: 18px; + font-family: 'Conv_apercu_regular','Helvetica','Sans-Serif','Arial'; + -webkit-text-stroke: 0; +} +.top-cp-tooltip { + top: 0; +} +.bottom-cp-tooltip { + bottom: 0; +} +.tooltip-container .btn-info-icon .cp-tooltip::before { + content: ""; + position: absolute; + top: 10%; + left: -5px; + transform: rotate(90deg) translate(-50%); + margin-left: -5px; + border-width: 5px; + border-style: solid; + border-color: rgba(0, 0, 0, .80) transparent transparent transparent; +} +.top-cp-tooltip::before { + top: 10px !important; +} +.bottom-cp-tooltip::before { + bottom: 0 !important; + top: unset !important; +} +.tooltip-container .btn-info-icon:hover .cp-tooltip { + opacity: 1; + transform: scale(1); +} + + +.referral-code-container{ + display: flex; + align-items: flex-start; +} + +.info-note { + color: var(--c-gray5); + background-color: var(--c-gray1); + font-family: 'Conv_apercu_regular', 'Helvetica', 'Sans-Serif', 'Arial'; +} + +.button-switch { + flex: 2.5; +} diff --git a/src/control/shared/utils.js b/src/control/shared/utils.js new file mode 100644 index 0000000..25b0d86 --- /dev/null +++ b/src/control/shared/utils.js @@ -0,0 +1,28 @@ +function extractText (el) { + let excludeTags = ["script", "style", "button"]; + let title = ""; + let description = ""; + + let tempDiv = document.createElement("div"); + tempDiv.innerHTML = el; + el = tempDiv; + function traverse(node) { + if (node.nodeType === Node.TEXT_NODE) { + description += node.textContent.trim() + " "; + } else if (node.nodeType === Node.ELEMENT_NODE && !excludeTags.includes(node.tagName.toLowerCase())) { + if (node.tagName.toLowerCase().startsWith("h") && !description.trim()) { + title = node.textContent.trim(); + } + node.childNodes.forEach(child => traverse(child)); + } + } + traverse(el); + + if (!title) { + title = description.substring(0, 40); + } + // remove extra spaces and rating characters + title = title.replace(/★/g, "").replace(/\s+/g, " ").trim(); + description = description.replace(/★/g, "").replace(/\s+/g, " ").trim(); + return { title, description }; +} diff --git a/src/widget/global/js/models/Setting.js b/src/widget/global/js/models/Setting.js new file mode 100644 index 0000000..1b1dc31 --- /dev/null +++ b/src/widget/global/js/models/Setting.js @@ -0,0 +1,19 @@ +// eslint-disable-next-line no-unused-vars +class Setting { + /** + * Create a setting model. + * @param {object} data - model value + */ + constructor(data = {}) { + this.searchEngineIndexing = data.searchEngineIndexing || false; + } + /** + * Convert the model to plain JSON + * @return {Setting} A Setting object. + */ + toJSON() { + return { + searchEngineIndexing: this.searchEngineIndexing, + }; + } +} diff --git a/src/widget/global/js/repositories/Content.js b/src/widget/global/js/repositories/Content.js new file mode 100644 index 0000000..c66cdd7 --- /dev/null +++ b/src/widget/global/js/repositories/Content.js @@ -0,0 +1,16 @@ +// eslint-disable-next-line no-unused-vars +class Content { + + /** + * get content data + * @returns {Promise} + */ + static get() { + return new Promise((resolve, reject) => { + buildfire.datastore.get( (err, res) => { + if (err) return reject(err); + resolve(res); + }); + }); + } +} diff --git a/src/widget/global/js/repositories/Settings.js b/src/widget/global/js/repositories/Settings.js new file mode 100644 index 0000000..e4b8107 --- /dev/null +++ b/src/widget/global/js/repositories/Settings.js @@ -0,0 +1,43 @@ +// eslint-disable-next-line no-unused-vars +class Settings { + /** + * Get database collection tag + * @returns {string} + */ + static get TAG() { + return "settings"; + } + + /** + * get settings data + * @returns {Promise} + */ + static get() { + return new Promise((resolve, reject) => { + buildfire.datastore.get(Settings.TAG, (err, res) => { + if (err) return reject(err); + if (!res || !res.data || !Object.keys(res.data).length) { + const data = new Setting().toJSON(); + resolve(data); + } else { + const data = new Setting(res.data).toJSON(); + resolve(data); + } + }); + }); + } + + /** + * set settings data + * @param {Object} data + * @returns {Promise} + */ + static save(data) { + return new Promise((resolve, reject) => { + buildfire.datastore.save(data, Settings.TAG, (err, res) => { + if (err) return reject(err); + return resolve(new Setting(res.data).toJSON()); + }); + }); + } +} diff --git a/src/widget/global/js/services/searchEngine.js b/src/widget/global/js/services/searchEngine.js new file mode 100644 index 0000000..f2bd7f5 --- /dev/null +++ b/src/widget/global/js/services/searchEngine.js @@ -0,0 +1,50 @@ +const instanceId = buildfire.getContext().instanceId; + +class SearchEngineService { + /** + * Get database collection tag + * @returns {string} + */ + static get TAG() { + return 'wysiwygContent'; + } + + /** + * Get database collection key + * @returns {string} + */ + + static get KEY() { + return `wysiwyg_${instanceId}`; + } + + /** + * save search engine data + * @returns {Promise} + */ + static save(title , description) { + return new Promise((resolve, reject) => { + buildfire.services.searchEngine.save({ + tag: SearchEngineService.TAG, key: SearchEngineService.KEY, title, description + }, (err, result) => { + if (err) return console.error(err); + },); + }); + } + /** + * delete search engine data + * @param {Object} data + * @returns {Promise} + */ + static delete() { + return new Promise((resolve, reject) => { + buildfire.services.searchEngine.delete({ + tag: SearchEngineService.TAG, key: SearchEngineService.KEY + }, + (err, result) => { + if (err) return console.error(err); + } + ); + }); + } +} diff --git a/src/widget/widget.js b/src/widget/widget.js index da91d57..70ff26b 100644 --- a/src/widget/widget.js +++ b/src/widget/widget.js @@ -60,9 +60,12 @@ function init() { // Keep state up to date with control changes buildfire.datastore.onUpdate((result) => { - state.data = result.data; - !state.data.design ? state.data.design = defaultData.design : null; - render(); + const isContentChanged = !!result.data.content + if (isContentChanged) { + state.data = result.data; + !state.data.design ? state.data.design = defaultData.design : null; + render(); + } }); } diff --git a/webpack/build.config.js b/webpack/build.config.js index cd1aa3c..5022648 100644 --- a/webpack/build.config.js +++ b/webpack/build.config.js @@ -66,7 +66,7 @@ const WebpackConfig = { to: path.join(__dirname, '../dist/plugin.json'), } ], { - ignore: ['*.js', '*.html', '*.md'] + ignore: [] }), new CopyWebpackPlugin([{ from: path.join(__dirname, '../src/control'), diff --git a/webpack/dev.config.js b/webpack/dev.config.js index c34a8b0..f6c7420 100644 --- a/webpack/dev.config.js +++ b/webpack/dev.config.js @@ -60,7 +60,7 @@ const WebpackConfig = { from: path.join(__dirname, '../src/resources'), to: path.join(__dirname, '../resources'), }], { - ignore: ['*.js', '*.html', '*.md'] + ignore: [] }), new CopyWebpackPlugin([{ from: path.join(__dirname, '../src/control'), From 243295dc2a1365a5c1d28a0b8f10c2d6ef2eccb2 Mon Sep 17 00:00:00 2001 From: alialaqrabawi3 Date: Wed, 3 Jul 2024 18:13:24 +0300 Subject: [PATCH 2/4] handle err in search engine , fix style --- src/control/content/index.html | 14 +++++------ src/control/content/index.js | 24 ++++++++++++------- src/control/content/style.css | 4 ++++ src/control/settings/index.html | 10 ++++---- src/control/settings/index.js | 18 +++++++++++--- src/control/settings/style.css | 7 +----- src/widget/global/js/models/Setting.js | 11 ++++++++- src/widget/global/js/repositories/Settings.js | 24 +++++++++++++++---- .../shared => widget/global/js}/utils.js | 2 +- src/widget/widget.js | 4 ++-- webpack/build.config.js | 7 ++++-- webpack/dev.config.js | 6 ++++- 12 files changed, 91 insertions(+), 40 deletions(-) rename src/{control/shared => widget/global/js}/utils.js (95%) diff --git a/src/control/content/index.html b/src/control/content/index.html index bb99d22..6dfc63e 100644 --- a/src/control/content/index.html +++ b/src/control/content/index.html @@ -3,11 +3,6 @@ - - - - - @@ -21,14 +16,19 @@ - + + + + + + -
+

diff --git a/src/control/content/index.js b/src/control/content/index.js index e994d3c..9b7e355 100644 --- a/src/control/content/index.js +++ b/src/control/content/index.js @@ -93,7 +93,7 @@ textPluginApp.controller('textPluginCtrl', ['$scope', function ($scope) { /* * Call the datastore to save the data object */ - var saveData = function (newObj) { + var saveData = function (newObj, callBack) { if (!datastoreInitialized) { console.error("Error with datastore didn't get called"); return; @@ -114,7 +114,7 @@ textPluginApp.controller('textPluginCtrl', ['$scope', function ($scope) { if (err || !result) { console.error('Error saving the widget details: ', err); } else { - console.info('Widget details saved'); + callBack(); } }); }; @@ -122,12 +122,22 @@ textPluginApp.controller('textPluginCtrl', ['$scope', function ($scope) { if (!$scope.searchEngineIndexing) return; buildfire.dynamic.expressions.evaluate({expression: content}, (err, result) => { if (err) return console.error(err); - const content = extractText(result.evaluatedExpression); + const content = prepareSearchEngineContent(result.evaluatedExpression); if (!content.title || !content.description) { - SearchEngineService.delete(); + SearchEngineService.delete().catch(()=>{ + buildfire.dialog.toast({ + message: 'Error indexing data.', + type:'danger' + }); + }); return; } - SearchEngineService.save(content.title, content.description); + SearchEngineService.save(content.title, content.description).catch(()=>{ + buildfire.dialog.toast({ + message: 'Error indexing data.', + type:'danger' + }); + }); }) }; /* @@ -139,9 +149,7 @@ textPluginApp.controller('textPluginCtrl', ['$scope', function ($scope) { if (tmrDelay) clearTimeout(tmrDelay); if (angular.equals(newObj, oldObj)) return; tmrDelay = setTimeout(function () { - saveData(newObj); - saveSearchEngine(newObj.content.text); - + saveData(newObj, function () {saveSearchEngine(newObj.content.text)}); }, 500); }; diff --git a/src/control/content/style.css b/src/control/content/style.css index faa8093..55a8022 100644 --- a/src/control/content/style.css +++ b/src/control/content/style.css @@ -1,5 +1,9 @@ +body { + font-family: 'Conv_apercu_regular','Helvetica','Sans-Serif','Arial'; +} #frMain { height: 95vh; + flex-direction: column; } .tinymce-editor{ flex: 1; diff --git a/src/control/settings/index.html b/src/control/settings/index.html index 04fa83a..2699fc3 100644 --- a/src/control/settings/index.html +++ b/src/control/settings/index.html @@ -3,10 +3,6 @@ - - - - @@ -14,9 +10,13 @@ - + + + + + diff --git a/src/control/settings/index.js b/src/control/settings/index.js index 17c92da..253e205 100644 --- a/src/control/settings/index.js +++ b/src/control/settings/index.js @@ -20,6 +20,7 @@ textPluginApp.controller('textSettingCtrl', ['$scope', function ($scope) { if ($scope.searchEngineIndexing !== initialSearchEngineIndexing) { Settings.save({searchEngineIndexing: $scope.searchEngineIndexing}); Content.get().then(function (data) { + if (data && data.data && data.data.content && data.data.content.text) $scope.handleSearchEngine(data.data.content.text); }); } @@ -28,6 +29,7 @@ textPluginApp.controller('textSettingCtrl', ['$scope', function ($scope) { if ($scope.searchEngineIndexing !== initialSearchEngineIndexing) { Settings.save({searchEngineIndexing: $scope.searchEngineIndexing}); Content.get().then(function (data) { + if (data && data.data && data.data.content && data.data.content.text) $scope.handleSearchEngine(data.data.content.text); }); } @@ -37,14 +39,24 @@ textPluginApp.controller('textSettingCtrl', ['$scope', function ($scope) { $scope.handleSearchEngine = function (content) { buildfire.dynamic.expressions.evaluate({expression: content}, (err, result) => { if (err) return console.error(err); - const content = extractText(result.evaluatedExpression); + const content = prepareSearchEngineContent(result.evaluatedExpression); if (!content.title || !content.description) { return; } if (!$scope.searchEngineIndexing) { - SearchEngineService.delete(); + SearchEngineService.delete().catch(()=>{ + buildfire.dialog.toast({ + message: 'Error indexing data.', + type:'danger' + }); + }); } else - SearchEngineService.save(content.title, content.description); + SearchEngineService.save(content.title, content.description).catch(()=>{ + buildfire.dialog.toast({ + message: 'Error indexing data.', + type:'danger' + }); + }); }) }; diff --git a/src/control/settings/style.css b/src/control/settings/style.css index b6a8a51..6aace95 100644 --- a/src/control/settings/style.css +++ b/src/control/settings/style.css @@ -81,12 +81,7 @@ } -.referral-code-container{ - display: flex; - align-items: flex-start; -} - -.info-note { +.button-switch p.info-note { color: var(--c-gray5); background-color: var(--c-gray1); font-family: 'Conv_apercu_regular', 'Helvetica', 'Sans-Serif', 'Arial'; diff --git a/src/widget/global/js/models/Setting.js b/src/widget/global/js/models/Setting.js index 1b1dc31..4c53f07 100644 --- a/src/widget/global/js/models/Setting.js +++ b/src/widget/global/js/models/Setting.js @@ -1,4 +1,3 @@ -// eslint-disable-next-line no-unused-vars class Setting { /** * Create a setting model. @@ -6,6 +5,11 @@ class Setting { */ constructor(data = {}) { this.searchEngineIndexing = data.searchEngineIndexing || false; + this.isActive = data.isActive || false; + this.createdOn = data.createdOn || new Date(); + this.createdBy = data.createdBy || ''; + this.lastUpdatedOn = data.lastUpdatedOn || new Date(); + this.lastUpdatedBy = data.lastUpdatedBy || ''; } /** * Convert the model to plain JSON @@ -14,6 +18,11 @@ class Setting { toJSON() { return { searchEngineIndexing: this.searchEngineIndexing, + isActive: this.isActive, + createdOn: this.createdOn, + createdBy: this.createdBy, + lastUpdatedOn: this.lastUpdatedOn, + lastUpdatedBy: this.lastUpdatedBy }; } } diff --git a/src/widget/global/js/repositories/Settings.js b/src/widget/global/js/repositories/Settings.js index e4b8107..2c6bc61 100644 --- a/src/widget/global/js/repositories/Settings.js +++ b/src/widget/global/js/repositories/Settings.js @@ -1,5 +1,7 @@ // eslint-disable-next-line no-unused-vars class Settings { + +static _settings = {} /** * Get database collection tag * @returns {string} @@ -18,9 +20,17 @@ class Settings { if (err) return reject(err); if (!res || !res.data || !Object.keys(res.data).length) { const data = new Setting().toJSON(); - resolve(data); + buildfire.auth.getCurrentUser((err, user) => { + if (err) return reject(); + data.createdBy = user._id ? user._id : ""; + Settings.save(data).then(()=>{ + this._settings = data; + resolve(data); + }) + }); } else { const data = new Setting(res.data).toJSON(); + this._settings = data; resolve(data); } }); @@ -34,9 +44,15 @@ class Settings { */ static save(data) { return new Promise((resolve, reject) => { - buildfire.datastore.save(data, Settings.TAG, (err, res) => { - if (err) return reject(err); - return resolve(new Setting(res.data).toJSON()); + buildfire.auth.getCurrentUser((err, user) => { + if (err) return reject(); + data.lastUpdatedBy = user._id? user._id : ""; + data.createdBy = data.createdBy || this._settings.createdBy; + data.createdOn = this._settings.createdOn || new Date(); + buildfire.datastore.save(new Setting(data).toJSON(), Settings.TAG, (err, res) => { + if (err) return reject(err); + return resolve(new Setting(res.data).toJSON()); + }); }); }); } diff --git a/src/control/shared/utils.js b/src/widget/global/js/utils.js similarity index 95% rename from src/control/shared/utils.js rename to src/widget/global/js/utils.js index 25b0d86..6de79e2 100644 --- a/src/control/shared/utils.js +++ b/src/widget/global/js/utils.js @@ -1,4 +1,4 @@ -function extractText (el) { +function prepareSearchEngineContent (el) { let excludeTags = ["script", "style", "button"]; let title = ""; let description = ""; diff --git a/src/widget/widget.js b/src/widget/widget.js index 70ff26b..daa7fd2 100644 --- a/src/widget/widget.js +++ b/src/widget/widget.js @@ -60,8 +60,8 @@ function init() { // Keep state up to date with control changes buildfire.datastore.onUpdate((result) => { - const isContentChanged = !!result.data.content - if (isContentChanged) { + const hasContentChanged = !!result.data.content + if (hasContentChanged) { state.data = result.data; !state.data.design ? state.data.design = defaultData.design : null; render(); diff --git a/webpack/build.config.js b/webpack/build.config.js index 5022648..0d8614f 100644 --- a/webpack/build.config.js +++ b/webpack/build.config.js @@ -66,12 +66,15 @@ const WebpackConfig = { to: path.join(__dirname, '../dist/plugin.json'), } ], { - ignore: [] - }), + ignore: ['*.js', '*.html', '*.md'] }), new CopyWebpackPlugin([{ from: path.join(__dirname, '../src/control'), to: path.join(__dirname, '../dist/control'), }]), + new CopyWebpackPlugin([{ + from: path.join(__dirname, '../src/widget'), + to: path.join(__dirname, '../dist/widget'), + }]), new ExtractTextPlugin('[name].css'), new ZipWebpackPlugin({ path: path.join(__dirname, '../'), diff --git a/webpack/dev.config.js b/webpack/dev.config.js index f6c7420..0f73d2c 100644 --- a/webpack/dev.config.js +++ b/webpack/dev.config.js @@ -60,8 +60,12 @@ const WebpackConfig = { from: path.join(__dirname, '../src/resources'), to: path.join(__dirname, '../resources'), }], { - ignore: [] + ignore: ['*.js', '*.html', '*.md'] }), + new CopyWebpackPlugin([{ + from: path.join(__dirname, '../src/widget'), + to: path.join(__dirname, '../dist/widget'), + }]), new CopyWebpackPlugin([{ from: path.join(__dirname, '../src/control'), to: path.join(__dirname, '../control'), From 90bae26d2fad7264f17d538a86e4c4f9e3052627 Mon Sep 17 00:00:00 2001 From: alialaqrabawi3 Date: Wed, 3 Jul 2024 20:25:45 +0300 Subject: [PATCH 3/4] enhance code quality --- src/control/content/index.html | 2 ++ src/control/content/index.js | 8 ++--- src/control/settings/index.html | 2 ++ src/control/settings/index.js | 8 +++-- src/widget/global/js/AppState.js | 4 +++ src/widget/global/js/models/Setting.js | 2 +- src/widget/global/js/repositories/Settings.js | 34 ++++++++----------- src/widget/global/js/services/AuthManager.js | 21 ++++++++++++ 8 files changed, 53 insertions(+), 28 deletions(-) create mode 100644 src/widget/global/js/AppState.js create mode 100644 src/widget/global/js/services/AuthManager.js diff --git a/src/control/content/index.html b/src/control/content/index.html index 6dfc63e..7eef3fa 100644 --- a/src/control/content/index.html +++ b/src/control/content/index.html @@ -14,6 +14,8 @@ + + diff --git a/src/control/content/index.js b/src/control/content/index.js index 9b7e355..a5b7df1 100644 --- a/src/control/content/index.js +++ b/src/control/content/index.js @@ -87,8 +87,9 @@ textPluginApp.controller('textPluginCtrl', ['$scope', function ($scope) { } }); - Settings.get().then((data) => $scope.searchEngineIndexing = data.searchEngineIndexing); - + AuthManager.refreshCurrentUser().then(function () { + Settings.get().then((data) => $scope.searchEngineIndexing = data.searchEngineIndexing); + }); /* * Call the datastore to save the data object @@ -113,9 +114,8 @@ textPluginApp.controller('textPluginCtrl', ['$scope', function ($scope) { buildfire.datastore.save(newObj, function (err, result) { if (err || !result) { console.error('Error saving the widget details: ', err); - } else { - callBack(); } + callBack(); }); }; var saveSearchEngine = function (content) { diff --git a/src/control/settings/index.html b/src/control/settings/index.html index 2699fc3..8932370 100644 --- a/src/control/settings/index.html +++ b/src/control/settings/index.html @@ -7,6 +7,8 @@ + + diff --git a/src/control/settings/index.js b/src/control/settings/index.js index 253e205..07837b0 100644 --- a/src/control/settings/index.js +++ b/src/control/settings/index.js @@ -60,9 +60,11 @@ textPluginApp.controller('textSettingCtrl', ['$scope', function ($scope) { }) }; - Settings.get().then(function (data) { - $scope.searchEngineIndexing = data.searchEngineIndexing; - $scope.$apply(); + AuthManager.refreshCurrentUser().then(function () { + Settings.get().then(function (data) { + $scope.searchEngineIndexing = data.searchEngineIndexing; + $scope.$apply(); + }); }); } ]); diff --git a/src/widget/global/js/AppState.js b/src/widget/global/js/AppState.js new file mode 100644 index 0000000..3eacb01 --- /dev/null +++ b/src/widget/global/js/AppState.js @@ -0,0 +1,4 @@ +// eslint-disable-next-line no-unused-vars +const AppState = { + settings: null, +}; diff --git a/src/widget/global/js/models/Setting.js b/src/widget/global/js/models/Setting.js index 4c53f07..8019a86 100644 --- a/src/widget/global/js/models/Setting.js +++ b/src/widget/global/js/models/Setting.js @@ -5,7 +5,7 @@ class Setting { */ constructor(data = {}) { this.searchEngineIndexing = data.searchEngineIndexing || false; - this.isActive = data.isActive || false; + this.isActive = data.isActive || true; this.createdOn = data.createdOn || new Date(); this.createdBy = data.createdBy || ''; this.lastUpdatedOn = data.lastUpdatedOn || new Date(); diff --git a/src/widget/global/js/repositories/Settings.js b/src/widget/global/js/repositories/Settings.js index 2c6bc61..e94d5f7 100644 --- a/src/widget/global/js/repositories/Settings.js +++ b/src/widget/global/js/repositories/Settings.js @@ -1,7 +1,5 @@ // eslint-disable-next-line no-unused-vars class Settings { - -static _settings = {} /** * Get database collection tag * @returns {string} @@ -19,18 +17,16 @@ static _settings = {} buildfire.datastore.get(Settings.TAG, (err, res) => { if (err) return reject(err); if (!res || !res.data || !Object.keys(res.data).length) { + const currentUser = AuthManager.currentUser; const data = new Setting().toJSON(); - buildfire.auth.getCurrentUser((err, user) => { - if (err) return reject(); - data.createdBy = user._id ? user._id : ""; - Settings.save(data).then(()=>{ - this._settings = data; - resolve(data); - }) - }); + data.createdBy = currentUser?._id ? currentUser._id : ""; + Settings.save(data).then(()=>{ + AppState.settings = data; + resolve(data); + }) } else { const data = new Setting(res.data).toJSON(); - this._settings = data; + AppState.settings = data; resolve(data); } }); @@ -44,15 +40,13 @@ static _settings = {} */ static save(data) { return new Promise((resolve, reject) => { - buildfire.auth.getCurrentUser((err, user) => { - if (err) return reject(); - data.lastUpdatedBy = user._id? user._id : ""; - data.createdBy = data.createdBy || this._settings.createdBy; - data.createdOn = this._settings.createdOn || new Date(); - buildfire.datastore.save(new Setting(data).toJSON(), Settings.TAG, (err, res) => { - if (err) return reject(err); - return resolve(new Setting(res.data).toJSON()); - }); + const currentUser = AuthManager.currentUser; + data.lastUpdatedBy = currentUser?._id ? currentUser._id : ""; + data.createdBy = data.createdBy || AppState.settings?.createdBy; + data.createdOn = AppState.settings?.createdOn || new Date(); + buildfire.datastore.save(new Setting(data).toJSON(), Settings.TAG, (err, res) => { + if (err) return reject(err); + return resolve(new Setting(res.data).toJSON()); }); }); } diff --git a/src/widget/global/js/services/AuthManager.js b/src/widget/global/js/services/AuthManager.js new file mode 100644 index 0000000..26c17ef --- /dev/null +++ b/src/widget/global/js/services/AuthManager.js @@ -0,0 +1,21 @@ +const AuthManager = { + _currentUser: {}, + get currentUser() { + return AuthManager._currentUser; + }, + set currentUser(user) { + AuthManager._currentUser = user; + }, + refreshCurrentUser() { + return new Promise((resolve) => { + buildfire.auth.getCurrentUser((err, user) => { + AuthManager.currentUser = err || !user ? null : user; + resolve(); + }); + }); + }, +}; + +buildfire.auth.onLogin((user) => { + AuthManager.currentUser = user; +}, true); From e2f001f4c4abb83e7a9f7d12bd1652c634efdc47 Mon Sep 17 00:00:00 2001 From: alialaqrabawi3 Date: Wed, 3 Jul 2024 21:14:11 +0300 Subject: [PATCH 4/4] move state file to control --- .../js/AppState.js => control/content/controlState.js} | 2 +- src/control/content/index.html | 2 +- src/control/settings/index.html | 2 +- src/widget/global/js/repositories/Settings.js | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) rename src/{widget/global/js/AppState.js => control/content/controlState.js} (74%) diff --git a/src/widget/global/js/AppState.js b/src/control/content/controlState.js similarity index 74% rename from src/widget/global/js/AppState.js rename to src/control/content/controlState.js index 3eacb01..a3224f0 100644 --- a/src/widget/global/js/AppState.js +++ b/src/control/content/controlState.js @@ -1,4 +1,4 @@ // eslint-disable-next-line no-unused-vars -const AppState = { +const ControlState = { settings: null, }; diff --git a/src/control/content/index.html b/src/control/content/index.html index 7eef3fa..3f7c7e9 100644 --- a/src/control/content/index.html +++ b/src/control/content/index.html @@ -14,8 +14,8 @@ + - diff --git a/src/control/settings/index.html b/src/control/settings/index.html index 8932370..65c089f 100644 --- a/src/control/settings/index.html +++ b/src/control/settings/index.html @@ -7,8 +7,8 @@ + - diff --git a/src/widget/global/js/repositories/Settings.js b/src/widget/global/js/repositories/Settings.js index e94d5f7..8340f26 100644 --- a/src/widget/global/js/repositories/Settings.js +++ b/src/widget/global/js/repositories/Settings.js @@ -21,12 +21,12 @@ class Settings { const data = new Setting().toJSON(); data.createdBy = currentUser?._id ? currentUser._id : ""; Settings.save(data).then(()=>{ - AppState.settings = data; + ControlState.settings = data; resolve(data); }) } else { const data = new Setting(res.data).toJSON(); - AppState.settings = data; + ControlState.settings = data; resolve(data); } }); @@ -42,8 +42,8 @@ class Settings { return new Promise((resolve, reject) => { const currentUser = AuthManager.currentUser; data.lastUpdatedBy = currentUser?._id ? currentUser._id : ""; - data.createdBy = data.createdBy || AppState.settings?.createdBy; - data.createdOn = AppState.settings?.createdOn || new Date(); + data.createdBy = data.createdBy || ControlState.settings?.createdBy; + data.createdOn = ControlState.settings?.createdOn || new Date(); buildfire.datastore.save(new Setting(data).toJSON(), Settings.TAG, (err, res) => { if (err) return reject(err); return resolve(new Setting(res.data).toJSON());