Update nested json data with underscore - javascript

I have a json looking like so:
{
"itemsList": [{
"id": 187994,
"contentName": "Content",
"contentItems": [{
"name": "nested 1",
"description": "<p>nested 1</p>\n"
}, {
"name": "nested 2 ",
"description": "<p>nested 2</p>\n"
}]
}]
}
And I am importing this data to an update form and trying to update the value for nested 1 when I submit the form but it keeps only the updated value, somehow it keeps only the updated value the other values get wiped out.
The function below updates the contentItems object but it keeps only the updated content:
$("#editResourceItemForm").submit(function (e) {
e.preventDefault();
$.getJSON(appDirLocation + "public/_data/resource_data.json", function (jsonData) {
console.log(jsonData.itemsList.contentItem);
//var contentItems = jsonData.itemsList.contentItems;
var resourceId = $("#editResourceItemForm input#resourceId").val(); // resource id
var updatedContentName = $("#appData").data("content-name");
var updatedContentItem = {
name: $("#editResourceItemForm input#contentItemName").val(),
description: CKEDITOR.instances.contentItemDescription.getData()
};
resourceId = Number(resourceId); // input filed is collected as string needs to make number
_.each(jsonData.itemsList, function (item) {
if (item.id === resourceId) {
item.contentName = updatedContentName;
item.contentItems = updatedContentItem ;
// queue here new items to update
}
}); // used underscore.js seems better for handling json data
var newJsonOutput = JSON.stringify(jsonData); //stringify new data
var jsonFile = new BCAPI.Models.FileSystem.File(appDirLocation + "public/_data/resource_data.json");
jsonFile.upload(newJsonOutput).done(function () {
$("#contentItemsList").html(""); //clear old data to load new
console.log("RESOURCE DATA UPDATED");
$('#editResourceItem').foundation('close'); //close reveal after created and saved file
renderResourceItems(resourceId);
}).fail(function (jqXHR) {
console.log("RESOURCES JSON FAILED UPDATE: " + jqXHR.responseText);
}); // END OF JSON CREATING
console.log(newJsonOutput);
}).done(function (dataprocessed) {
console.log(dataprocessed);
}).fail(function (jqXHR) {
console.log("Request failed." + "Error code: " + jqXHR.status + "Error text: " + jqXHR.statusText + "Response text: " + jqXHR.responseText);
});
});
Please let me know what I can do to pass the updated values to the existing contentItems without wiping out the rest of the data in the object.
This is the fiddle I used to create the data:
https://jsfiddle.net/RicardoAlves/zb5dprvv
Thanks

Related

How to display one Chrome notification at a time?

I'm creating a Chrome Extension right now, and I'm running into a problem where the same notification is created and displayed a bunch of times. I was wondering if there is a solution on how to check and make sure that if there is already a notification, to not create a new one. Here's my code on how the notifications are created:
async function alert() {
console.log("Alert getting created");
var result = await getExpiredIndices();
var numberOfExpiredTabs = result.expiredTabArray.length;
var id = uuidv4();
var msg = `Ta daa! Your tab(s) are ready.`;
chrome.notifications.create(
id,
{
type: "basic",
iconUrl: "assets/icons/pondr_128.png",
title: "Pondr",
message: msg,
priority: 2,
requireInteraction: true,
buttons: [
{
//get indexes from storage pop them when user re-opens tabs
title: "Open",
},
{
title: "Later",
//get indexes, shift all times, pop them since they are no longer in the outdated subarray
},
],
}
);
}
chrome.notifications.onButtonClicked.addListener(async function (
notifId,
btnIdx
) {
var result1 = await getExpiredIndices();
var result2 = await getAllTabsArray();
var expiredTabArray = await result1.expiredTabArray;
var allTabsArray = await result2.allTabsArray;
if (btnIdx === 0) {
//if yes open tabs
console.log("hit yes");
console.log("Before popping allTabsArray: ", allTabsArray);
console.log("Before popping expiredTabsArray: ", expiredTabArray);
openTabsNow(expiredTabArray, allTabsArray);
} else if (btnIdx === 1) {
console.log("hit later");
console.log("Before popping allTabsArray: ", allTabsArray);
console.log("Before popping expiredTabsArray: ", expiredTabArray);
openTabsLater(expiredTabArray, allTabsArray);
//if no reapply reminder-setting
//FOR TIME BEING: will be hardcoded to push all items 3 hrs forward
}
});

DevExtreme / Knockout.js implement JSON as datasource

I'm new to JavaScript and REST, and I need to implement JSON as datasource to devextreme using knockout.js.
My problem is, that I can fetch the json, but it is not added to the datasource. I used console.log() for testing and noticed that the json is correctly loaded, but the datasource is empty (see comments in code below). How can I achieve the usage of my json as datasource?
Note: I used DevExtreme load JSON as datasource using knockout as base for getting my JSON-contents.
I have a sample JSON-File looking like this:
{
"ID":"3",
"content":
{
"ProdId":"000176491264",
"ProdDesc":"Sample 1",
"Type":"A",
}
}
And my current viewmodel looks like this:
MyApp.overview = function (params) {
"use strict";
var getData = function () {
var deferred = $.Deferred();
var xmlhttp = new XMLHttpRequest(), json;
xmlhttp.onreadystatechange = function() {
if(xmlhttp.readyState === 4 && xmlhttp.status === 200) {
json = JSON.parse(xmlhttp.responseText);
// prints needed content:
console.log(json.content);
deferred.resolve(json.content);
}
};
xmlhttp.open('GET', 'http://localhost:56253/test/3?format=json', true);
xmlhttp.send();
return deferred.promise();
};
var viewModel = {
overviewDatagridOptions: {
dataSource: getData(),
selection: {
mode: "single"
},
columns: [{
dataField: "ProdId",
caption: "ID"
}, {
dataField: "ProdDesc",
caption: "Description"
}, {
dataField: "Type",
caption: "Type"
}],
rowAlternationEnabled: true
},
// Returns {}
console.log("Datasource: " + JSON.stringify(viewModel.overviewDatagridOptions.dataSource));
return viewModel;
};
Edit: I changed my datasource to this:
dataSource: {
load: function (loadOptions) {
var d = new $.Deferred();
var params = {};
//Getting filter options
if (loadOptions.filter) {
params.filter = JSON.stringify(loadOptions.filter);
}
//Getting sort options
if (loadOptions.sort) {
params.sort = JSON.stringify(loadOptions.sort);
}
//Getting dataField option
if (loadOptions.dataField) {
params.dataField = loadOptions.dataField;
}
//If the select expression is specified
if (loadOptions.select) {
params.select= JSON.stringify(loadOptions.select);
}
//Getting group options
if (loadOptions.group) {
params.group = JSON.stringify(loadOptions.group);
}
//skip and take are used for paging
params.skip = loadOptions.skip; //A number of records that should be skipped
params.take = loadOptions.take; //A number of records that should be taken
var obj;
$.getJSON('http://localhost:56253/test/3?format=json', params).done(function (data) {
d.resolve(data);
});
//return obj;
return d.promise();
}, [...]
Based on the demo found here: https://www.devexpress.com/Support/Center/Question/Details/KA18955
Now, the output from the datasource is no longer empty, and looks like this:
Object
- load:(loadOptions)
- arguments:(...)
- caller:(...)
- length:1
- name:"load"
- prototype:Object
- __proto__:()
- [[FunctionLocation]]
- [[Scopes]]:Scopes[1]
- totalCount:(loadOptions)
- arguments:(...)
- caller:(...)
- length:1
- name:"totalCount"
- prototype:Object
- __proto__:()
- [[FunctionLocation]]
- [[Scopes]]:Scopes[1]
- __proto__:Object

It is possible to show the edit page of the record by clicking the custom button in netsuite?

I want to show the edit page of the record by clicking the custom button instead of the "standard edit button"
My Code:
Script Version: Suite Script 2.0
User Event Script:
function beforeLoad(context) {
log.debug('Test', 'Before Load Event Initiated');
var frm = context.form;
frm.clientScriptFileId = 2250;
//Values from System/ScriptContext
var record = context.newRecord;
if (context.type == context.UserEventType.VIEW) {
frm.addButton({
id: 'custpage_cust_edit_btn',
label: 'Deactivate Record',
functionName: 'customRecordEditMode(' + record.id + ')'
});
}
}
Client Script:
function customRecordEditMode(recordID) {
debugger;
try {
window.location.href = "https://system.sandbox.netsuite.com/app/common/custom/custrecordentry.nl?rectype=194&id=" + recordID + "&e=T";
} catch (exception) {
alert("Error:", exception.message);
}
}
ERROR Message:
I'm Getting the Following Error Message:
but the url of the record is same as in when we click the standard "Edit" Button. (i,e) rectype=194&id=237&e=T
thanks in advance
I'm not exactly sure why you would be getting this error with the raw URL, but instead of using the raw URL, have you tried utilizing the N/url module?
require(['N/url', 'N/record'], function(url, r) {
var output = url.resolveRecord({
recordType: r.Type.SALES_ORDER,
recordId: 6,
isEditMode: true
});
});
or perhaps even better would be the N/redirect module:
require(['N/redirect', 'N/record'], function(redirect, r) {
redirect.toRecord({
"type": r.Type.TASK,
"id": 6,
"isEditMode": true
});
});

Parse Backgroundjob Matching

I'm currently programming a background job for my Parse Database.
The Database contains lots of users in the User class. All user have a 'location' column and an 'offer' and 'search' column. 'offer' and 'search' store an array of strings.
What it should do is the following:
The background job should go through all the users and check for users close to them and then check if these users match on specific skills. So if someone has "example" in 'search' and someone else has "example" in 'offer' these user match and both get a notification.
The location query does not choose users close to each other
If a user does not "offer" anything, but "searches" for something he does not get a notification
It should not constantly send push notifications when two users are close to each other (only once)
-
Parse.Cloud.job("backgroundJob", function(request, status) {
var queryAllUser = new Parse.Query(Parse.User);
Parse.Cloud.useMasterKey();
var targetList = []; //new Array();
queryAllUser.each(function(user) {
var queryMatch = new Parse.Query(Parse.User);
queryMatch.withinKilometers("location", user.get("location"), 0.1);
//if(user.get("search") != null){
queryMatch.containedIn("offer", user.get("search"));
// }
return queryMatch.first().then(function(firstUser) {
if (firstUser != null) {
console.error("THIS IS THE FIRST USER: " + firstUser.get("name"));
}
if (firstUser) {
targetList.push(user);
}
});
}).then(function() {
console.error("Length of TargetList: " + targetList.length);
if (targetList[0] != null && targetList.length != 1) {
var queryTarget = new Parse.Query(Parse.Installation);
queryTarget.containedIn('user', targetList);
return Parse.Push.send({
where: queryTarget,
data: {
alert: "Found a Match!",
badge: "Increment",
pushType: "1",
}
}, {
success: function() {
status.success("Send the Pushes!");
},
error: function(error) {
status.error(error);
}
});
}
status.success("did the job!");
},
function(error) {
status.error("error:" + error.message);
});
});

How to dynamically generate options for RichCombo in CKEDITOR?

There is a form on my page with textarea (CKEDITOR) and select field <select id="_photogalleries" multiple="multiple"></select>. I'd like options in RichCombo to depend on the options that are selected in select with id #_photogalleries. Is there any way to regenerate RichCombo dynamically?
Thanks in advance.
CKEDITOR.plugins.add('style_plugin', {
requires: ['richcombo'],
init: function(editor) {
var pluginName = 'style_plugin';
var config = editor.config,
lang = editor.lang.format;
editor.ui.addRichCombo('photogalleries', {
label: "Фоторепортаж",
title: "Фоторепортаж",
voiceLabel: "Фоторепортаж",
className: 'cke_format',
multiSelect: false,
icon: CKEDITOR.plugins.getPath('style_plugin') + 'photo-list-horizontal.png',
panel: {
css: [config.contentsCss, CKEDITOR.getUrl(editor.skinPath + 'editor.css')],
voiceLabel: lang.panelVoiceLabel
},
init: function () {
this.startGroup("Фоторепортаж");
var list=this;
$("#_photogalleries option:selected").each(function(index, value){
console.log(index, value);
list.add("#HORIZONTAL_GALLERY_"+ $(value).val()+"#", "(Г) " + $(value).text(), "(Г) " + $(value).text());
list.add("#VERTICAL_GALLERY_"+ $(value).val()+"#", "(В) " + $(value).text(), "(В) " + $(value).text());
});
},
onClick: function (value) {
editor.focus();
editor.fire('saveSnapshot');
editor.insertHtml(value);
editor.fire('saveSnapshot');
}
});
}
});
This works for me and you dont have to keep a global variable.
CKEDITOR.plugins.add('systemdata', {
init: function (editor) {
var fnData = editor.config.fnData;
if (!fnData || typeof (fnData) != 'function')
throw "You must provide a function to retrieve the list data.";
editor.ui.addRichCombo('systemDataCmb',
{
allowedContent: 'abbr[title]',
label: "System Data",
title: "System Data",
multiSelect: false,
init: function () {
var self = this;
var content = fnData();
$.each(content, function(index, value) {
// value, html, text
self.add(value.name, value.name, value.name)
});
}
}
Then to set the function to get the data put this somewhere where you setup the ckeditor
CKEDITOR.replaceAll(function(element, config) {
config.startupFocus = true;
config.fnData = function() {
var returnData = null;
$.ajax({
url: "/GetData",
async: false,
data: { id: 1 },
}).done(function(result) { returnData= result; });
return returnData;
};
});
It assumes you bring back a json response that has an array of items that have a value property, that can be easily changed though.
I guess I found a solution that worked for me. It was to keep a list object in a global variable and then modify it when onchange event fires in the external select.
I solved this trouble with a single line:
YOURCOMBO.createPanel(editor);
For example:
var comboTeam = editor.ui.get("team");
comboTeam.createPanel(editor);//This is important, if not, doesnt works
Now you can add items to the combo
comboTeam.add("name","name","name");
comboTeam.add("name2","name2","name2");
comboTeam.add("name3","name3","name3");

Categories

Resources