Skip to content

Commit 9258372

Browse files
authored
Merge pull request #116 from BuildFire/ai-seeder
feat: Added AI state seeder to the plugin
2 parents 1b869ac + 468e12c commit 9258372

8 files changed

Lines changed: 290 additions & 129 deletions

File tree

control/content/app.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,22 @@
4848
});
4949
}
5050
});
51+
// fix google places autocomplete dropdown position
52+
setTimeout(() => {
53+
const target = document.querySelector('.pac-container');
54+
if (target) {
55+
const observer = new MutationObserver(() => {
56+
document.querySelectorAll('.pac-item span, .pac-item')
57+
.forEach((n) => n.classList.add('needsclick'));
58+
const autocompleteBoundaries = document.getElementById('googleMapAutocomplete').getBoundingClientRect();
59+
target.style.top = (autocompleteBoundaries.top + autocompleteBoundaries.height )+ 'px';
60+
});
61+
observer.observe(target, { childList: true, attributes: true,
62+
characterData: true,
63+
});
64+
}
65+
console.log('observer target :', target);
66+
}, 2000);
5167
}
5268
};
5369
})

control/content/app.services.js

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,4 +158,219 @@
158158
}
159159
}
160160
}])
161+
.factory('DefaultInfo', ['LAYOUTS', function(LAYOUTS) {
162+
return {
163+
content: {
164+
carouselImages: [],
165+
description: '<p>&nbsp;<br></p>',
166+
addressTitle: '',
167+
address: {
168+
type:'',
169+
location:'',
170+
location_coordinates: [],
171+
},
172+
links: [],
173+
showMap: false
174+
},
175+
design: {
176+
listLayout: LAYOUTS.listLayouts[0].name,
177+
backgroundImage: ''
178+
}
179+
}
180+
}])
181+
.factory('AIStateSeeder', ['DefaultInfo', 'DataStore', 'TAG_NAMES', '$rootScope', function(DefaultInfo, DataStore, TAG_NAMES, $rootScope ) {
182+
let stateSeederInstance;
183+
let ContactInfo = DefaultInfo;
184+
const jsonTemplate = {
185+
imagesURLs: [],
186+
description: '',
187+
phoneNumber: '',
188+
email: '',
189+
location: '',
190+
}
191+
192+
const getAddress = function(location) {
193+
return new Promise((resolve) => {
194+
if (location) {
195+
const geocoder = new google.maps.Geocoder();
196+
geocoder.geocode({'address': location}, function(result, status) {
197+
if (status == google.maps.GeocoderStatus.OK) {
198+
resolve(
199+
{
200+
type: 'Location',
201+
location: result[0].formatted_address || location,
202+
location_coordinates: [result[0].geometry.location.lng(), result[0].geometry.location.lat()]
203+
});
204+
} else {
205+
resolve({
206+
type: 'Location',
207+
location: location,
208+
location_coordinates: []
209+
});
210+
};
211+
});
212+
} else {
213+
resolve(null);
214+
};
215+
});
216+
};
217+
218+
const parseImageURL = function(url) {
219+
const optimizedURL = url.replace('1080x720', '100x100');
220+
return new Promise((resolve) => {
221+
if (url.includes("http")){
222+
const xhr = new XMLHttpRequest();
223+
xhr.open("GET", optimizedURL);
224+
xhr.onerror = (error) => {
225+
console.warn('provided URL is not a valid image', error);
226+
resolve('');
227+
}
228+
xhr.onload = () => {
229+
if (xhr.responseURL.includes('source-404') || xhr.status == 404) {
230+
return resolve('');
231+
} else {
232+
return resolve(xhr.responseURL.replace('h=100', 'h=720').replace('w=100', 'w=1080'));
233+
}
234+
};
235+
xhr.send();
236+
} else resolve('');
237+
});
238+
}
239+
240+
const getCurrentUser = function () {
241+
return new Promise((resolve, reject) => {
242+
buildfire.auth.getCurrentUser((err, currentUser) => {
243+
if (err) reject(err);
244+
resolve(currentUser);
245+
});
246+
});
247+
}
248+
249+
const _applyDefaults = function (data) {
250+
// create HTML div element for the description, to avoid breaking the WYSIWYG
251+
const descriptionElement = document.createElement('div');
252+
descriptionElement.innerHTML = data.description || '';
253+
// default address in case there was no address provided
254+
let address = {
255+
type: 'Location',
256+
location: '501 Pacific Hwy, San Diego, CA 92101, USA',
257+
location_coordinates: [-117.17096400000003,32.7100444]
258+
}
259+
if (data.address) {
260+
address = data.address;
261+
}
262+
if (data.imagesURLs && data.imagesURLs.length) {
263+
for (let i = 0; i < data.imagesURLs.length; i++) {
264+
data.imagesURLs[i] = {
265+
action: 'noAction',
266+
iconUrl: data.imagesURLs[i],
267+
title: 'image'
268+
}
269+
}
270+
} else {
271+
data.imagesURLs = [];
272+
}
273+
274+
// add links based on the contact info provided
275+
let links = [];
276+
const emailRegex = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/;
277+
if (data.email && data.email.match(emailRegex)) {
278+
links.push({
279+
title: 'Email',
280+
action:'sendEmail',
281+
email: data.email,
282+
subject: 'Contact US',
283+
});
284+
}
285+
if (data.phoneNumber) {
286+
links.push({
287+
title:'Call',
288+
action:'callNumber',
289+
phoneNumber: data.phoneNumber
290+
});
291+
}
292+
return {
293+
showMap: true,
294+
carouselImages: data.imagesURLs,
295+
description : descriptionElement.outerHTML,
296+
addressTitle: 'Navigate to Location',
297+
address: address,
298+
links: links,
299+
}
300+
}
301+
302+
const handleAIReq = function(err, response) {
303+
if (
304+
err ||
305+
!response ||
306+
typeof response !== 'object' ||
307+
!Object.keys(response).length || !response.data
308+
) {
309+
return buildfire.dialog.toast({
310+
message: 'Bad AI request, please try changing your request.',
311+
type: 'danger',
312+
});
313+
}
314+
315+
let optimizedURLs = [];
316+
let promises = response.data.imagesURLs.map(url => {
317+
return parseImageURL(url)
318+
});
319+
320+
Promise.allSettled(promises).then(parsingResults => {
321+
parsingResults.forEach(parsingResult => {
322+
if (parsingResult.status == 'fulfilled' && parsingResult.value) {
323+
optimizedURLs.push(parsingResult.value);
324+
}
325+
})
326+
response.data.imagesURLs = optimizedURLs;
327+
DataStore.get(TAG_NAMES.CONTACT_INFO).then(info => {
328+
if (info && info.data && Object.keys(info.data).length) {
329+
ContactInfo = info.data;
330+
}
331+
getAddress(response.data.location).then(locationResult => {
332+
response.data.address = locationResult;
333+
ContactInfo.content = _applyDefaults(response.data);
334+
DataStore.save(ContactInfo, TAG_NAMES.CONTACT_INFO).then(() => {
335+
stateSeederInstance?.requestResult?.complete();
336+
$rootScope.initContentHome();
337+
}).catch(err => {
338+
stateSeederInstance?.requestResult?.complete();
339+
console.warn('error saving data to datastore', err);
340+
return buildfire.dialog.toast({
341+
message: 'Something went wrong, try again later.',
342+
type: 'danger',
343+
});
344+
});
345+
});
346+
}).catch(err => {
347+
stateSeederInstance?.requestResult?.complete();
348+
console.warn('error getting data from datastore', err);
349+
return buildfire.dialog.toast({
350+
message: 'Something went wrong, try again later.',
351+
type: 'danger',
352+
});
353+
});
354+
});
355+
};
356+
357+
return {
358+
initStateSeeder: function() {
359+
getCurrentUser().then(user => {
360+
stateSeederInstance = new buildfire.components.aiStateSeeder({
361+
generateOptions: {
362+
userMessage: `Generate a contact us information related to [business-type] located in [target-region].\nFor phone number use [+1 555 555-1234].\nFor email use [${user?.email || ''}].`,
363+
maxRecords: 5,
364+
systemMessage:
365+
'images are two 1080x720 images URLs related to location, use source.unsplash.com for images, URL should not have premium_photo or source.unsplash.com/random. return description as HTML',
366+
jsonTemplate: jsonTemplate,
367+
callback: handleAIReq.bind(this),
368+
hintText: 'Replace values between brackets to match your requirements.',
369+
},
370+
}).smartShowEmptyState();
371+
});
372+
return true;
373+
},
374+
}
375+
}])
161376
})(window.angular, window.buildfire);

control/content/controllers/content.home.controller.js

Lines changed: 10 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,61 +3,13 @@
33
(function (angular) {
44
angular
55
.module('contactUsPluginContent')
6-
.controller('ContentHomeCtrl', ['$scope', 'Buildfire', 'LAYOUTS', 'DataStore', 'TAG_NAMES', 'STATUS_CODE', 'ADDRESS_TYPE', 'Utils', '$timeout',
7-
function ($scope, Buildfire, LAYOUTS, DataStore, TAG_NAMES, STATUS_CODE, ADDRESS_TYPE, Utils, $timeout) {
8-
var _data = {
9-
"content": {
10-
"carouselImages": [],
11-
"description": '<p>&nbsp;<br></p>',
12-
"addressTitle": "",
13-
"address": {
14-
type:"",
15-
location:"",
16-
location_coordinates:[]
17-
},
18-
"links": [],
19-
"showMap": false
20-
},
21-
"design": {
22-
"listLayout": LAYOUTS.listLayouts[0].name,
23-
"backgroundImage": ""
24-
}
25-
};
26-
27-
// var initDummyFlag=true;
28-
29-
//init dummy data
30-
var _dummyData= {
31-
content: {
32-
showMap:true,
33-
carouselImages: [{
34-
action: "noAction",
35-
iconUrl: "http://buildfire.imgix.net/1462345835888-04866688400506973/6ac49110-11c7-11e6-92ea-27ed66023d52.jpeg?fit=crop&w=342&h=193",
36-
title: "image"
37-
},
38-
{
39-
action: "noAction",
40-
iconUrl: "http://buildfire.imgix.net/1462345835888-04866688400506973/6bf3c240-11c7-11e6-ad08-375cc71b6ca7.jpg?fit=crop&w=342&h=193",
41-
title: "image"
42-
}],
43-
description : "<p>With the wysiwyg, you can include text and lists, embed images, embed videos, and link to webpages, emails, phone numbers and more. Check out the tutorial on the wysiwyg for detailed information.</p>",
44-
addressTitle:"",
45-
address:{
46-
type:"Location",
47-
location:"501 Pacific Hwy, San Diego, CA 92101, USA",
48-
location_coordinates:[-117.17096400000003,32.7100444]
49-
},
50-
links:[{"title":"Call","action":"callNumber","phoneNumber":"6195551234"},{"title":"Email","action":"sendEmail"}]
51-
},
52-
design:{
53-
listLayout:"Layout_1",
54-
backgroundImage:""
55-
},
56-
default : true
57-
};
6+
.controller('ContentHomeCtrl', ['$scope', 'Buildfire', 'DataStore', 'TAG_NAMES', 'STATUS_CODE', 'ADDRESS_TYPE', 'Utils', '$timeout', 'DefaultInfo', 'AIStateSeeder', '$rootScope',
7+
function ($scope, Buildfire, DataStore, TAG_NAMES, STATUS_CODE, ADDRESS_TYPE, Utils, $timeout, DefaultInfo, AIStateSeeder, $rootScope) {
8+
AIStateSeeder.initStateSeeder();
9+
$rootScope.initContentHome = () => {init()};
10+
var _data = DefaultInfo;
5811
var ContentHome = this;
59-
ContentHome.masterData = _dummyData;
60-
// ContentHome.data = angular.copy(_data);
12+
ContentHome.data = angular.copy(_data);
6113
ContentHome.validCoordinatesFailure = false;
6214

6315
// create a new instance of the buildfire carousel editor
@@ -103,7 +55,7 @@
10355
$scope.$digest();
10456
};
10557

106-
updateMasterItem(_dummyData);
58+
updateMasterItem(_data);
10759

10860
ContentHome.bodyWYSIWYGOptions = {
10961
plugins: 'advlist autolink link image lists charmap print preview',
@@ -126,7 +78,6 @@
12678
var init = function () {
12779
var success = function (result) {
12880
if (result && result.id && result.data) {
129-
// initDummyFlag=false;
13081
console.info('init success result:', result);
13182
ContentHome.data = result.data;
13283
if(!ContentHome.data) {
@@ -155,9 +106,9 @@
155106
updateMasterItem(ContentHome.data);
156107
if (tmrDelay)clearTimeout(tmrDelay);
157108
}else{
158-
//initDummyFlag=true;
159-
ContentHome.data=_dummyData;
160-
// $scope.$digest();
109+
110+
ContentHome.data= _data;
111+
161112
if (ContentHome.data.content) {
162113
if (!ContentHome.data.content.carouselImages)
163114
editor.loadItems([]);

control/content/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<script src="../../../../scripts/jquery/jquery-ui.min.js"></script>
1717
<script src="../../../../scripts/angular/angular-ui-sortable.js"></script>
1818
<script src="../../../../scripts/buildfire/components/carousel/carousel.js"></script>
19+
<script src="../../../../scripts/buildfire/components/aiStateSeeder/aiStateSeeder.js"></script>
1920
<script src="../../../../scripts/tinymce/tinymce.min.js"></script>
2021
<script src="../../../../scripts/tinymce/ui-tinymce.js"></script>
2122
<script src="../../../../scripts/angular/ui-bootstrap.min.js"></script>

control/design/app.services.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,24 @@
4141
}
4242
}
4343
}])
44+
.factory('DefaultInfo', ['LAYOUTS', function(LAYOUTS) {
45+
return {
46+
content: {
47+
carouselImages: [],
48+
description: '<p>&nbsp;<br></p>',
49+
addressTitle: '',
50+
address: {
51+
type:'',
52+
location:'',
53+
location_coordinates: [],
54+
},
55+
links: [],
56+
showMap: false
57+
},
58+
design: {
59+
listLayout: LAYOUTS.listLayouts[0].name,
60+
backgroundImage: ''
61+
}
62+
}
63+
}])
4464
})(window.angular, window.buildfire);

0 commit comments

Comments
 (0)