How to configure everything into one or multiple configure files - json

I haven't used this since 2 years ago. I'm trying to figure out how to put everything into one json or it has to be mulitple jsons.
Using v11.9.46. The documentation is not clear as it references things that are for one version or another.
I'm moving items from ADOorg1 to ADOorg2. In this order I was going to setup the json
Areas and Iterations
Team setup
Shared Queries
Work Items (using a query to find select area)
This is what I had so far as I tried to figure out how to put it into one:
{
"ChangeSetMappingFile": null,
// "Endpoints": {
// "TfsTeamSettingsEndpoints": [
// {
// "Name": "TeamSettingsSource",
// "AccessToken": "",
// "Query": {
// "Query": "SELECT [System.Id], [System.Tags] FROM WorkItems WHERE [System.TeamProject] = #TeamProject AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan') ORDER BY [System.ChangedDate] desc"
// },
// "Organisation": "https://dev.azure.com/test1/",
// "Project": "test1",
// "ReflectedWorkItemIdField": "ReflectedWorkItemId",
// "AuthenticationMode": "AccessToken",
// "AllowCrossProjectLinking": false,
// "LanguageMaps": {
// "AreaPath": "Area",
// "IterationPath": "Iteration"
// }
// },
// {
// "Name": "TeamSettingsTarget",
// "AccessToken": "",
// "Query": {
// "Query": "SELECT [System.Id], [System.Tags] FROM WorkItems WHERE [System.TeamProject] = #TeamProject AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan') ORDER BY [System.ChangedDate] desc"
// },
// "Organisation": "https://dev.azure.com/test2/",
// "Project": "test2",
// "ReflectedWorkItemIdField": "ReflectedWorkItemId",
// "AuthenticationMode": "AccessToken",
// "AllowCrossProjectLinking": false,
// "LanguageMaps": {
// "AreaPath": "Area",
// "IterationPath": "Iteration"
// }
// }
// ]
// },
"Source": {
"$type": "TfsTeamProjectConfig",
"Collection": "https://dev.azure.com/test1/",
"Project": "test1",
"ReflectedWorkItemIDFieldName": "ReflectedWorkItemId",
"AllowCrossProjectLinking": false,
"AuthenticationMode": "Prompt",
"PersonalAccessToken": "",
"LanguageMaps": {
"AreaPath": "Area",
"IterationPath": "Iteration"
}
},
"Target": {
"$type": "TfsTeamProjectConfig",
"Collection": "https://dev.azure.com/test2/",
"Project": "Test2",
"ReflectedWorkItemIDFieldName": "ReflectedWorkItemId",
"AllowCrossProjectLinking": false,
"AuthenticationMode": "Prompt",
"PersonalAccessToken": "",
"LanguageMaps": {
"AreaPath": "Area",
"IterationPath": "Iteration"
}
},
"Endpoints": {
"InMemoryWorkItemEndpoints": [
{
"Name": "Source",
"EndpointEnrichers": null
},
{
"Name": "Target",
"EndpointEnrichers": null
}
]
},
"GitRepoMapping": null,
"LogLevel": "Information",
"Processors": [
{
"$type": "TfsAreaAndIterationProcessorOptions",
"Enabled": true,
"PrefixProjectToNodes": false,
"NodeBasePaths": null,
"ProcessorEnrichers": null,
"SourceName": "Source",
"TargetName": "Target"
},
{
"$type": "TfsTeamSettingsProcessorOptions",
"Enabled": false,
"MigrateTeamSettings": true,
"UpdateTeamSettings": true,
"PrefixProjectToNodes": false,
"Teams": null,
"ProcessorEnrichers": null,
"SourceName": "Source",
"TargetName": "Target"
},
{
"$type": "WorkItemMigrationConfig",
"Enabled": false,
"ReplayRevisions": true,
"PrefixProjectToNodes": false,
"UpdateCreatedDate": true,
"UpdateCreatedBy": true,
"BuildFieldTable": false,
"AppendMigrationToolSignatureFooter": false,
"WIQLQueryBit": "AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')",
"WIQLOrderBit": "[System.ChangedDate] desc",
"LinkMigration": true,
"AttachmentMigration": true,
"AttachmentWorkingPath": "E:\\temp\\WorkItemAttachmentWorkingFolder\\",
"FixHtmlAttachmentLinks": false,
"SkipToFinalRevisedWorkItemType": true,
"WorkItemCreateRetryLimit": 5,
"FilterWorkItemsThatAlreadyExistInTarget": true,
"PauseAfterEachWorkItem": false,
"AttachmentMaxSize": 480000000,
"CollapseRevisions": false,
"LinkMigrationSaveEachAsAdded": false,
"GenerateMigrationComment": true,
"NodeBasePaths": [
"Product\\Area\\Path1",
"Product\\Area\\Path2"
],
"WorkItemIDs": null
}
],
"Version": "0.0",
"workaroundForQuerySOAPBugEnabled": false,
"WorkItemTypeDefinition": {
"sourceWorkItemTypeName": "targetWorkItemTypeName"
}
// "Endpoints": {
// "InMemoryWorkItemEndpoints": [
// {
// "Name": "Source",
// "EndpointEnrichers": null
// },
// {
// "Name": "Target",
// "EndpointEnrichers": null
// }
// ]
// }
}

If you use this Azure DevOps Migration Tools, it can migrate Work Items, TestPlans & Suits, Teams, Shared Queries, & Pipelines from one Organization to another. You could refer to Processors: TfsAreaAndIterationProcessor, TfsTeamSettingsProcessor, TfsSharedQueryProcessor and Work Item Tracking Processor to create corresponding configuration Json files one by one.

Related

How to Change the defaults in Great Expectations DataDoc HTML Report?

Great Expectations provides the ability to produce Html reports using DataDocs as shown in the folloiwng example:
I would like the change the following defaults in the header - see image
The report is generated using the following
validation_results_stg = ge_stg_update.validate(expectation_suite='stg_expectations.html', only_return_failures=False)
I believe I can make changes because if I run the code validatation_results_stg
I get the following output
{
"evaluation_parameters": {},
"meta": {
"great_expectations_version": "0.13.38",
"expectation_suite_name": "default",
"run_id": {
"run_time": "2021-11-18T14:59:49.831733+00:00",
"run_name": null
},
"batch_kwargs": {
"ge_batch_id": "2c157d12-4880-11ec-8b5e-000d3ad66fea"
},
"batch_markers": {},
"batch_parameters": {},
"validation_time": "20211118T145949.831530Z",
"expectation_suite_meta": {
"great_expectations_version": "0.13.38"
}
},
"results": [
{
"result": {
"element_count": 14539,
"missing_count": 0,
"missing_percent": 0.0,
"unexpected_count": 0,
"unexpected_percent": 0.0,
"unexpected_percent_total": 0.0,
"unexpected_percent_nonmissing": 0.0,
"partial_unexpected_list": []
},
"exception_info": {
"raised_exception": false,
"exception_message": null,
"exception_traceback": null
},
"meta": {},
"success": true,
"expectation_config": {
"kwargs": {
"column": "SERVICE",
"value_set": [
"CMC",
"Divorce",
"Probate",
"SSCS"
]
},
"expectation_type": "expect_column_values_to_be_in_set",
"meta": {},
"ge_cloud_id": null
}
},
{
"result": {
"observed_value": 14539
},
"exception_info": {
"raised_exception": false,
"exception_message": null,
"exception_traceback": null
},
"meta": {},
"success": true,
"expectation_config": {
"kwargs": {
"value": 14539
},
"expectation_type": "expect_table_row_count_to_equal",
"meta": {},
"ge_cloud_id": null
}
}
],
"success": true,
"statistics": {
"evaluated_expectations": 2,
"successful_expectations": 2,
"unsuccessful_expectations": 0,
"success_percent": 100.0
}
}
As you can see the defaults are loaded e.g. you will notice "expectation_suite_name": "default",
Can someone show me how you can the default to something else?

Iterate over objects and print select values

Question: I would like to know how I can iterate over an object to print out the name of each subnet and its cidr range in the subnets object.
I know how I can print out the vnet name and cidr range:
jq '.[] | select(.vnet) | {name: .vnet.name, cidr: .vnet.address_space[0]}'
I have looked online and found that you can convert the object to an array, but I am unsure how I can look through that array to print out the values:
jq '.[] | to_entries | map_values(.value)'
Essentially the desired OUTPUT should look something like this:
{
"name": "asdf1",
"cidr": "10....."
},
{
"name": "asdf2",
"cidr": "10....."
}
//...and so forth
Sample INPUT:
{
"route_tables": {
"asdf": {
"disable_bgp_route_propagation": true,
"name": "az_afw",
"resource_group_name": "vnet-spoke",
"route_entries": {
"re1": {
"name": "rt-rfc-10-8",
"next_hop_in_ip_address": "10.0.0.0",
"next_hop_type": "VirtualAppliance",
"prefix": "10.0.0.0/8"
},
"re2": {
"name": "rt-rfc-172-12",
"next_hop_in_ip_address": "10.0.0.0",
"next_hop_type": "VirtualAppliance",
"prefix": "172.16.0.0/12"
}
}
}
},
"vnet_peering_settings": {
"peer1": {
"peer_to_source": {
"allow_forwarded_traffic": true,
"allow_gateway_transit": false,
"allow_virtual_network_access": true,
"use_remote_gateways": true
},
"source_to_peer": {
"allow_forwarded_traffic": true,
"allow_gateway_transit": true,
"allow_virtual_network_access": true,
"use_remote_gateways": false
}
}
},
"vnet_spoke_object": {
"specialsubnets": {},
"subnets": {
"objectAsdf1": {
"cidr": "10.0.0.1/24",
"enforce_private_link_endpoint_network_policies": false,
"enforce_private_link_service_network_policies": false,
"name": "asdf1",
"nsg_creation": true,
"nsg_inbound": [],
"nsg_outbound": [],
"route": null,
"service_endpoints": []
},
"objectAsdf2": {
"cidr": "10.0.0.1/24",
"enforce_private_link_endpoint_network_policies": false,
"enforce_private_link_service_network_policies": false,
"name": "asdf2",
"nsg_creation": true,
"nsg_inbound": [],
"nsg_outbound": [],
"route": "asdf",
"service_endpoints": [
"Microsoft.EventHub"
]
},
"objectAsdf3": {
"cidr": "10.0.0.1/24",
"enforce_private_link_endpoint_network_policies": false,
"enforce_private_link_service_network_policies": false,
"name": "asdf3",
"nsg_creation": true,
"nsg_inbound": [],
"nsg_outbound": [],
"route": "asdf",
"service_endpoints": []
},
"objectAsdf4": {
"cidr": "10.0.0.1/24",
"enforce_private_link_endpoint_network_policies": false,
"enforce_private_link_service_network_policies": false,
"name": "asdf4",
"nsg_creation": true,
"nsg_inbound": [],
"nsg_outbound": [],
"route": "asdf",
"service_endpoints": []
}
},
"vnet": {
"address_space": [
"10.0.0.0/16"
],
"ddos_id": "placeholder",
"dns": [
"10.0.0.1",
"10.0.0.1"
],
"enable_ddos_std": false,
"name": "asdf"
}
}
}
Start with the root path and traverse down and use to_entries to get past the varying key names and use the .value field only
jq '.vnet_spoke_object.subnets | to_entries[].value | { name, cidr }'
or collect it as an array of objects
jq '.vnet_spoke_object.subnets | to_entries | map(.value | { name, cidr })'
jqplay - Demo

Looping and updating data in React

So quite new to React here (mostly backend and devops engineer). I need to fix a bug as the person usually responsible is not available currently.
One of the REST endpoint is formatting dates incorrectly while sending the data to the backend. The data expected from the endpoint for a PUT is
"items": [
{
"uuid": "abc7aba1-47ad-46d1-a3a5-d26ff55e4cf8",
"item_id": "21626227",
"item_description": "Test",
"item_schedule": {
"uuid": "37f8ca4c-6469-4bfb-822e-acfbc02e502e",
"start_date": "2018-12-04",
"end_date": "2018-12-06",
"interval": 3,
"unit": "days",
"occurrence": 1
"schedule_dates": [
{
"uuid": "d5b73ac5-be77-40c5-b11b-45034f70f81f",
"planned_date": "2018-12-04",
"custom": true
}
]
}
},
{
"uuid": "7abca4f4-1717-4136-aec6-3a37b4971c81",
"item_id": "21626229",
"item_description": "Test 2",
"maintenance_plan": "31001827",
"item_schedule": {
"uuid": "5de45d6e-81e8-4c86-9eb2-31c71089c876",
"start_date": null,
"end_date": null,
"interval": null,
"unit": "",
"occurrence": null,
"schedule_dates": [
{
"uuid": "da7ed2e4-053e-4f1d-80ca-2d6d258e8a08",
"planned_date": "2018-12-13",
"custom": true
}
]
}
}
]
Instead what we get for all the dates, i.e. start_date, end_date and planned_dates is (skipping all the right stuff here..)
"end_date": "2018-12-05T13:00:00.000Z",
"start_date": "2018-12-03T13:00:00.000Z"
"planned_date" : "2018-12-03T13:00:00.000Z"
When creating a new schedule for a new item, the old schedule data is incorrectly formatted.
I have tried to loop over all the items and the relevant schedule and dates and correctly format them , but doesn't seem to work.
Do I need to use map here instead of foreach?
const mapDispatchToProps = (dispatch, props) => ({
save: (value, notes) => dispatch(ItemDetailAction.saveLocal(
props.value.merge(
Map(Object.assign(
{
notes: notes.setIn([0, 'created'], undefined),
uuid: props.value.get('uuid'),
},
props.value.getIn(['item', 'type']) === 'P' && {
items: props.value
.get('items').forEach((item) => {
console.log(item.get('item_schedule'));
const start_date = item.get('item_schedule').get('start_date');
if (start_date !== '') {
const formatted_date = moment(start_date).format('YYYY-MM-DD');
//not updating the date-format below in the same array.
item.get('item_schedule').set('start_date',formatted_date);
item.setIn(['item_schedule', 'start_date'],formatted_date);
// this still prints the wrong date-format
console.log(item.get('item_schedule').get('start_date'));
}
}),
},
)),
),
true,
{
then: () => {
props.onCancel();
dispatch(actions.getItemListTable(FilterMaintenance.asParams(props.filters)));
},
}, )), });

Set next step for the waterfall dialogue in Microsoft BotBuilder NodeJS SDK

I am using Microsoft Bot Framework for my facebook messenger bot. I want to load the dialog data from json files instead of hard coding in the js file. I would like to configure the next step in the dialog, based on result from the "current" step, which is part of the json file configuration, something like this.
{
"name": "welcome",
"type": "waterfall",
"steps": [
{
"id": 0,
"data": [
{
"type": "text",
"value": "Hey, It's nice to meet you."
},
{
"type": "quickReplies",
"value": "What do you want to do next?",
"options": [
{
"text": "some option 1",
"value": "option1"
},
{
"text": "some option 2",
"value": "option2"
}
]
}
],
"next": [
{
"result": "option1",
"action": "goto step 2"
},
{
"result": "option2",
"action": "goto step 5"
}
]
}
]
}
I would like to process all the incoming messages and respond with correct dialog or correct step in the dialog for the user.
I am trying something like this;
handleMessage = function (session) {
var step = session.dialogData["BotBuilder.Data.WaterfallStep"] || 0;
// check response data from previou step and identify the next step.
// set the waterfall step id
session.dialogData["BotBuilder.Data.WaterfallStep"] = 2;
session.send("Hello");
}
var bot = new builder.UniversalBot(connector, function (session) {
handleMessage(session);
})
.set('storage',tableStorage);
With this code, I am always getting step as zero for session.dialogData["BotBuilder.Data.WaterfallStep"] even after setting this to a different number.
Also, as soon as I set the waterfall step number, all other state data that is stored in my table storage for this conversation is gone.
Storage data before setting waterfall step:
{
"BotBuilder.Data.SessionState": {
"callstack": [
{
"id": "*:/",
"state": {
"BotBuilder.Data.WaterfallStep": 0
}
},
{
"id": "*:welcome",
"state": {
"BotBuilder.Data.WaterfallStep": 1
}
},
{
"id": "BotBuilder:prompt-text",
"state": {
"options": {
"prompt": {
"type": "message",
"agent": "botbuilder",
"source": "facebook",
"address": {
"id": "mid.$cAAAlr-0LRH9niO21L1hV6hs83GuJ",
"channelId": "facebook",
"user": {
"id": "XXXX",
"name": "XXXX"
},
"conversation": {
"isGroup": false,
"id": "XX"
},
"bot": {
"id": "XXX",
"name": "XXX"
},
"serviceUrl": "https://facebook.botframework.com"
},
"text": "what do you want to next"
//ignored for simplicity
},
"promptAfterAction": true,
"libraryNamespace": "*"
},
"turns": 0,
"lastTurn": 1517594116372,
"isReprompt": false
}
}
],
"lastAccess": 1517594112740,
"version": 0
}
}
After I set the waterfall step:
{
"BotBuilder.Data.SessionState": {
"callstack": [
{
"id": "*:/",
"state": {
"BotBuilder.Data.WaterfallStep": 2
}
}
],
"lastAccess": 1517602122416,
"version": 0
}
}
Interestingly the step number is saved to the database (but in session state) but my "session" variable do not have this value anywhere. Also, even after configuring custom state service, the serviceUrl is still https://facebook.botframework.com which I thought is the default state service used if there is no state service set for the bot.
Per your code, as your bot actually contains only one waterfall step: handleMessage(session);, which raised your issue. You can consider to create multiple dialogs from json configration instead of complex waterfall steps.
Here is my quick test, for your information:
const json = `
[{
"name": "welcome",
"type": "waterfall",
"steps": [
{
"id": 0,
"data": [
{
"type": "text",
"value": "Hey, It's nice to meet you."
},
{
"type": "quickReplies",
"value": "What do you want to do next?",
"options": [
{
"text": "some option 1",
"value": "option1"
},
{
"text": "some option 2",
"value": "option2"
}
]
}
],
"next": [
{
"result": "option1",
"action": "dialog2"
},
{
"result": "option2",
"action": "dialog3"
}
]
}
]
},{
"name":"dialog2",
"type": "waterfall",
"steps": [
{
"data": [
{
"type": "text",
"value": "Hey, this is dialig2."
}]
}
]
},{
"name":"dialog3",
"type": "waterfall",
"steps": [
{
"data": [
{
"type": "text",
"value": "Hey, this is dialig3."
}]
}
]
}]
`;
const generateSignleStep = (step) => {
return (session, args, next) => {
step.forEach(sentence => {
switch (sentence.type) {
case 'quickReplies':
let choices = sentence.options.map(item => {
return item.value
});
let card = new builder.ThumbnailCard(session)
.text(sentence.value)
.buttons(sentence.options.map(choice => new builder.CardAction.imBack(session, choice.value, choice.text)))
let message = new builder.Message(session).addAttachment(card);
builder.Prompts.choice(session, message, choices);
break;
case 'text':
default:
session.send(sentence.value)
break;
}
})
}
}
const generatenextAction = (actions) => {
return (session, args, next) => {
const response = args.response;
actions.map(action => {
if (action.result == response.entity) {
session.beginDialog(action.action);
}
})
}
}
const generateWaterfallSteps = (steps) => {
let waterfall = [];
steps.forEach(step => {
waterfall.push(generateSignleStep(step.data));
if (step.next) {
waterfall.push(generatenextAction(step.next));
}
});
return waterfall;
}
var bot = new builder.UniversalBot(connector);
const jsonobj = JSON.parse(json);
jsonobj.forEach(dialog => {
bot.dialog(dialog.name, generateWaterfallSteps(dialog.steps))
.triggerAction({
matches: new RegExp(dialog.name, "g")
})
});
The result is:

jqgrid - json - getting wrong value

I have the following JSON:
{
"wrapper": {
"table": {
"rows": [
{
"cells": [
{
"fname": "Jack",
"label": "fname",
"editable": false
},
{
"lname": "Kalra",
"label": "lname",
"editable": true,
"details": [
{
"industry": "music"
},
{
"industry": "media"
}
]
}
]
},
{
"cells": [
{
"fname": "Steven",
"editable": true,
"label": "fname"
},
{
"lname": "Martini",
"editable": true,
"label": "lname"
}
]
},
{
"cells": [
{
"fname": "Andrea",
"editable": true,
"label": "fname"
},
{
"lname": "Dmello",
"editable": true,
"label": "lname",
"details": [
{
"industry": "finance"
},
{
"industry": "HR"
},
{
"industry": "media"
}
]
}
]
},
{
"cells": [
{
"fname": "James",
"label": "fname",
"editable": false
},
{
"label": "lname",
"lname": "Diamond",
"editable": true,
"details": [
{
"industry": "music"
},
{
"industry": "media"
}
]
}
]
},
{
"cells": [
{
"fname": "Aba",
"label": "fname",
"editable": true
},
{
"label": "lanme",
"lname": "Duck",
"editable": true,
"details": [
{
"industry": "finance"
},
{
"industry": "technology"
},
{
"industry": "media"
}
]
}
]
},
{
"cells": [
{
"fname": "Henry",
"label": "fname",
"editable": true
},
{
"label": "lname",
"lname": "Hebert",
"editable": true,
"details": [
{
"industry": "finance"
},
{
"industry": "HR"
},
{
"industry": "media"
},
{
"industry": "IT"
}
]
}
]
}
]
}
}
}
All cells are editable.
I'm trying to loop through each row and then each cell to find out the number of properties in "details". In inline editing mode, it should be a text field and the value of text field should be the corresponding number of properties.
Example - for Marc Kalra, the details cell will be a text field with a value of 2.
Here's my code
loadComplete: function(data){
var x, y, cellProp;
for (x = 0; x < data.wrapper.table.rows.length; x++) {
var cellCount = data.wrapper.table.rows[x].cells.length;
for (y = 0; y < cellCount; y += 1) {
cellProp = data.wrapper.table.rows[x].cells[y];
var prop, listCount, cellLabel;
listCount = data.wrapper.table.rows[x].cells[y].details.length;
cellLabel = data.wrapper.table.rows[x].cells[y].label;
function gridCustomEdit (value, options){
var el = document.createElement("input");
el.type="text";
el.value = listCount;
return el;
}
for (prop in cellProp) { if (prop === "details"){
$("#jqgrid").setColProp(cellLabel, {
editable: true,
edittype: "custom",
editoptions: {
custom_element: gridCustomEdit
}
});
}
}
}
}
PROBLEM - is that el.value = listCount; in the above code always returns 4 as the number of properties for each row/cell.
Can someone point me my mistake?
UPDATED
loadComplete: function(data){
var x, y, cellProp;
for (x = 0; x < data.wrapper.table.rows.length; x++) {
var cellCount = data.wrapper.table.rows[x].cells.length;
for (y = 0; y < cellCount; y += 1) {
cellProp = data.wrapper.table.rows[x].cells[y];
var isEditable = cellProp.editable;
if (isEditable === false) {
$("#jqgrid").setColProp(cellProp.label, {
editable: false
});
}else {
var listCount, cellLabel;
listCount = data.wrapper.table.rows[x].cells[y].details.length;
cellLabel = data.form.summary.rows[x].cells[y].label;
$("#jqgrid").setColProp(cellLabel, {
editable: true,
editoptions: {
dataInit: function(elem){
$(elem).myPlugin({listCount: listCount})
}
}
})
}
}
}
}
PLUGIN CODE
(function( $ ){
$.fn.extend({
myPlugin: function(options){
var defaults = {
listCount: 0
};
var options = $.extend(defaults, options);
var o = options;
alert(o.listCount);
if (o.listCount === 3){
$(elem).html("<input type='text' value='" + o.listCount + "'>")
} else {
$(elem).html("<select>") **// this should be a dropdown with values = properties of `details`**
}
}
})
})
GRID CODE
$("#jqgrid").jqGrid({
datatype: "json",
colNames:['fname','lname'],
colModel:[
{name:'fname',index:'fname'},
{name:'lname',index:'lname'},
],
jsonReader: {
root: "wrapper.table.rows",
repeatitems: false
},
onSelectRow: function(id){
$(this).jqGrid('editRow',id);
},
})
If details exist + number of properties in details = 3, then lname is displayed as a text field in inline editing mode.
If details exist + number of properties in details > 3, then lname is displayed as a select field in inline editing mode.
The method setColProp set property for the column and not for the cell in the column. So if you set in the loop setColProp for the same column many times only the last setting will be applied. Because the last row (for "Love Hebert") in your data has 4 items in the details array only the value will be used.
The next error is that you define gridCustomEdit function which has reference to external variable listCount. In the case there are only one instance of the function with the last value of the variable. If you need to have many function instances with different values you should use closure.
In your case it seems to me you can implement all what you need even without the usage of closure and without custom editing (edittype:'custom' with custom_element and custom_value).
I suppose that all what you need to do is to set setColProp inside of onSelectRow (or before the call of editRow) and not inside of loadComplete. See the answer for more information. If you need to change the edittype of the column you can do this in the same way. So you can for example dynamically set edittype: "text" and set editoptions with dataInit which change the value of the element.
If it is needed you can even dynamically switch the edittype between edittype: "text" and edittype: "select" and set all editoptions which are required.
In the way you will receive simple and flexible code which don't use custom editing at all.