Managing workflows with nodejs - google-workflows

I am trying to use nodejs to manage my workflows instead of using the console. The createWorkflow method returns a 200 code but I cannot find it in the console or when listing it. Any idea what is missing? the typescript typedef has too many partials to be useful on what is needed and what is not. In the code below the list method returns correctly the workflow names I created in the console which proves that I use the parent params correctly I guess. However when I call the create method with the name of a new workflow and some code, I get this this back and a return code of 200 which should mean it was successful but can't find it. Also trying to execute it returns a not found.
return value:
{
"_events": {},
"_eventsCount": 2,
"completeListeners": 0,
"hasActiveListeners": false,
"latestResponse": {
"name": "projects/xxxxx/locations/us-central1/operations/operation-1607572432499-5b6141fca342d-32b153bf-bfce0551",
"metadata": {
"type_url": "type.googleapis.com/google.cloud.workflows.v1beta.OperationMetadata",
"value": {
"type": "Buffer",
"data": [
10,
12,
8,
208,
183,
198,
254,
5,
16,
236,
212,
251,
180,
2,
26,
76,
112,
114,
111,
106,
101,
99,
116,
115,
47,
98,
117,
116,
116,
101,
114,
102,
108,
121,
45,
105,
116,
45,
55,
102,
55,
55,
98,
47,
108,
111,
99,
97,
116,
105,
111,
110,
115,
47,
117,
115,
45,
99,
101,
110,
116,
114,
97,
108,
49,
47,
119,
111,
114,
107,
102,
108,
111,
119,
115,
47,
116,
101,
115,
116,
95,
119,
111,
114,
107,
102,
108,
111,
119,
95,
118,
49,
34,
6,
99,
114,
101,
97,
116,
101,
42,
6,
118,
49,
98,
101,
116,
97
]
}
},
"done": false
},
"name": "projects/xxxxxxxxxxxx/locations/us-central1/operations/operation-1607572432499-5b6141fca342d-32b153bf-bfce0551",
"done": false,
"longrunningDescriptor": {
"operationsClient": {
"auth": {
"checkIsGCE": true,
"jsonContent": null,
"cachedCredential": {
"_events": {},
"_eventsCount": 0,
"transporter": {},
"credentials": {
"access_token": "ya29.c.KpcB6AdCAMGMr_FqY7veU-uQTAP2cenQDWOh3Msaw-CPjdodjeYKAEf7lw-m1joxmam06_4QgRJ5Atnlpcm7db37CAi0lz4LS5_KPkvaodE6oefkDChOly92BxyCfaJClrKqklcEbSt1yg-2iVwngXccgwtdko9sbM4UeUihNPYScdGY0bGT484x7Ai6e2vtAfZMC2r-DqGE-g",
"token_type": "Bearer",
"expiry_date": 1607573907456,
"refresh_token": "compute-placeholder"
},
"certificateCache": {},
"certificateExpiry": null,
"certificateCacheFormat": "PEM",
"refreshTokenPromises": {},
"eagerRefreshThresholdMillis": 300000,
"forceRefreshOnFailure": false,
"serviceAccountEmail": "default",
"scopes": [
"https://www.googleapis.com/auth/cloud-platform"
]
},
"_cachedProjectId": "xxxxxxxxxxxx",
"defaultScopes": [
"https://www.googleapis.com/auth/cloud-platform"
],
"_getDefaultProjectIdPromise": {}
},
"innerApiCalls": {},
"descriptor": {
"listOperations": {
"requestPageTokenField": "pageToken",
"responsePageTokenField": "nextPageToken",
"resourceField": "operations"
}
}
}
},
"result": null,
"metadata": {
"createTime": {
"seconds": "1607572432",
"nanos": 647948908
},
"target": "projects/xxxxxxxxxxxx/locations/us-central1/workflows/test_workflow_v1",
"verb": "create",
"apiVersion": "v1beta"
},
"backoffSettings": {
"initialRetryDelayMillis": 100,
"retryDelayMultiplier": 1.3,
"maxRetryDelayMillis": 60000,
"initialRpcTimeoutMillis": null,
"rpcTimeoutMultiplier": null,
"maxRpcTimeoutMillis": null,
"totalTimeoutMillis": null
},
"_callOptions": {
"timeout": 30000,
"retry": {
"retryCodes": [],
"backoffSettings": {
"initialRetryDelayMillis": 100,
"retryDelayMultiplier": 1.3,
"maxRetryDelayMillis": 60000,
"initialRpcTimeoutMillis": 60000,
"rpcTimeoutMultiplier": 1,
"maxRpcTimeoutMillis": 60000,
"totalTimeoutMillis": 600000
}
},
"autoPaginate": true,
"otherArgs": {
"headers": {
"x-goog-request-params": "parent=projects%2Fxxxxxxxxxxxx%2Flocations%2Fus-central1"
}
},
"bundleOptions": null,
"isBundling": true,
"apiName": "google.cloud.workflows.v1beta.Workflows"
}
}
** code: **
engine: ExecutionsClient;
builder: WorkflowsClient;
location = 'us-central1';
projectId: string;
constructor() {
this.engine = new ExecutionsClient();
this.builder = new WorkflowsClient();
this.projectId = serviceAccount.project_id;
}
async list(): Promise<any> {
console.log (`list workflows`);
const [ resp ] = await this.builder.listWorkflows({
parent: this.builder.locationPath(this.projectId, this.location),
});
console.log (`listWorkflow: ${JSON.stringify(resp)}`);
return resp;
}
async create(name: string, code: string): Promise<any> {
console.log (`creating workflow named: ${name}`);
const [ resp ] = await this.builder.createWorkflow({
parent: this.builder.locationPath(this.projectId, this.location),
workflow: {
sourceContents: code,
},
workflowId: name
});
console.log (`createWorkflow: ${JSON.stringify(resp)}`);
return resp;
}
async execute(name: string): Promise<any> {
const [resp] = await this.engine.createExecution({
parent: this.engine.workflowPath(this.projectId, this.location, name),
});
return resp;
}

After consulting the source for google-cloud/workflows I found where the problem was. createWorkflow is what they call a long operation and is actually 2 successive promises
const [operation] = await client.createWorkflow(request);
const [response] = await operation.promise();

Related

How to verify with Python (PyNaCl) a message signed by Solana wallet adapter (javascript)

I have signed a message using Solana's wallet adapter example:
import { useWallet } from '#solana/wallet-adapter-react';
import bs58 from 'bs58';
import React, { FC, useCallback } from 'react';
import { sign } from 'tweetnacl';
export const SignMessageButton: FC = () => {
const { publicKey, signMessage } = useWallet();
const onClick = useCallback(async () => {
try {
// `publicKey` will be null if the wallet isn't connected
if (!publicKey) throw new Error('Wallet not connected!');
// `signMessage` will be undefined if the wallet doesn't support it
if (!signMessage) throw new Error('Wallet does not support message signing!');
// Encode anything as bytes
const message = new TextEncoder().encode("hello");
// Sign the bytes using the wallet
const signature = await signMessage(message);
// Verify that the bytes were signed using the private key that matches the known public key
if (!sign.detached.verify(message, signature, publicKey.toBytes())) throw new Error('Invalid signature!');
alert(`Message signature: ${bs58.encode(signature)}`);
} catch (error: any) {
alert(`Signing failed: ${error?.message}`);
}
}, [publicKey, signMessage]);
return signMessage ? (<button onClick={onClick} disabled={!publicKey}>Sign Message</button>) : null;
};
Pubkey used: DKpHyR1WjWE23E3xizPUhefZKmpMrMXNBVfoxQ7WXCRR
Message signed: hello
Signature received: 3EWDdtU1w8pWkr6fg8faJvKn1wBZmNjgf5kUx4Pn5gw4HeBPYVDm7cTHNqpRVMami6yX36jdaeZacv9GXR19Jzye
But I am not being able to verify the signed message using Python 3.9 with PyNaCl and Solana-py. I have tried the following:
from nacl.signing import VerifyKey
from solana.publickey import PublicKey
import base58
pubkey = bytes(PublicKey("DKpHyR1WjWE23E3xizPUhefZKmpMrMXNBVfoxQ7WXCRR"))
msg = bytes("hello", 'utf8')
signed = bytes("3EWDdtU1w8pWkr6fg8faJvKn1wBZmNjgf5kUx4Pn5gw4HeBPYVDm7cTHNqpRVMami6yX36jdaeZacv9GXR19Jzye", 'utf8')
result = VerifyKey(
pubkey
).verify(
smessage=base58.b58decode(msg),
signature=base58.b58decode(signed)
)
But verification returns: nacl.exceptions.BadSignatureError: Signature was forged or corrupt.
Somebody knows what is wrong? Could it be an encoding problem? Seems like JS uses the following byte types:
pubkey: Uint8Array(32) [144, 188, 240, 167, 187, 75, 30, 17, 232, 175, 91, 222, 73, 68, 183, 218, 108, 56, 249, 64, 250, 61, 111, 168, 194, 233, 159, 2, 247, 5, 175, 124, buffer: ArrayBuffer(32), byteLength: 32, byteOffset: 0, length: 32]
message: Uint8Array(44) [57, 85, 65, 81, 76, 53, 81, 68, 67, 89, 122, 70, 112, 107, 119, 70, 88, 52, 88, 75, 53, 70, 119, 107, 66, 54, 67, 57, 116, 57, 116, 120, 65, 89, 52, 102, 102, 122, 69, 52, 114, 97, 113, 84, buffer: ArrayBuffer(44), byteLength: 44, byteOffset: 0, length: 44]
signed: Uint8Array(64) [111, 173, 219, 10, 169, 113, 163, 35, 30, 162, 250, 243, 191, 106, 195, 99, 238, 34, 49, 192, 19, 92, 111, 142, 57, 31, 158, 235, 65, 219, 146, 176, 174, 48, 30, 255, 160, 90, 174, 179, 219, 197, 252, 189, 150, 225, 160, 133, 163, 109, 159, 80, 56, 191, 11, 1, 91, 111, 196, 214, 231, 84, 11, 1, buffer: ArrayBuffer(64), byteLength: 64, byteOffset: 0, length: 64]
And in python:
pubkey: b'\xb7\x1e+\xef\xe19#y}\xa4L\xf2K\rK\xc3\xbby\x93\x1c\x00L\xe1<\x19g`-\x9d\xd5\xee\x94'
msg: b'Cn8eVZg'
signed: b'3EWDdtU1w8pWkr6fg8faJvKn1wBZmNjgf5kUx4Pn5gw4HeBPYVDm7cTHNqpRVMami6yX36jdaeZacv9GXR19Jzye'
Do I need to use some different encoding on Python?
Thanks for providing a concrete example on this, you're very close! The encoding is absolutely the issue here -- the pubkey is correctly encoded in Python as bytes. That first byte of \x90, encoded as two hex values, is 144 in JS, and you can check that in Python with: int('90', 16) = 144.
So to verify your key, you can instead use the base58 package https://github.com/keis/base58 and do:
from nacl.signing import VerifyKey
from solana.publickey import PublicKey
import base58
pubkey = bytes(PublicKey("DKpHyR1WjWE23E3xizPUhefZKmpMrMXNBVfoxQ7WXCRR"))
msg = bytes("hello", 'utf8')
signed = bytes("3EWDdtU1w8pWkr6fg8faJvKn1wBZmNjgf5kUx4Pn5gw4HeBPYVDm7cTHNqpRVMami6yX36jdaeZacv9GXR19Jzye", 'utf8')
result = VerifyKey(
pubkey
).verify(
smessage=msg,
signature=base58.b58decode(signed)
)
Note.- on smessage you don't need to use b58, because it was
encoded with new TextEncoder().encode("hello").
Second option: if you already have the UInt8Array from JS, you can do:
result = VerifyKey(bytes(PublicKey("HERE_THE_PUB_KEY"))
).verify(
smessage=bytes([byte1, byte2, byte3, ...])
signature=bytes([byte1, byte2, byte3, ...])
)

assert_noop! doesn't pass the test

This is my test:
assert_noop!(
TemplateModule::commit_vote(
Origin::signed(5),
count - 1,
0,
"2-Votinghash".as_bytes().to_vec()
),
Error::<Test>::AlreadyCommitUsed
);
When I add another error its fails as:
thread 'tests::commit_vote' panicked at 'assertion failed: `(left == right)`
left: `Err(DispatchError::Module { index: 1, error: 7, message: Some("AlreadyCommitUsed") })`,
right: `Err(DispatchError::Module { index: 1, error: 4, message: Some("DepartmentNotAssociated") })`', pallets/template/src/tests.rs:106:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Where as when I add AlreadyCommitUsed as error, it gives following strange inequality:
thread 'tests::commit_vote' panicked at 'assertion failed: `(left == right)`
left: `[218, 23, 247, 200, 228, 182, 117, 227, 150, 32, 248, 47, 209, 182, 207, 246, 198, 19, 20, 74, 185, 125, 35, 94, 74, 161, 128, 199, 114, 155, 238, 228]`,
right: `[128, 69, 23, 167, 50, 250, 133, 59, 10, 41, 100, 95, 141, 187, 236, 154, 67, 174, 251, 17, 219, 45, 146, 141, 204, 77, 245, 38, 95, 131, 122, 48]`', pallets/template/src/tests.rs:106:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
This is my commit_vote function:
#[weight = 10_000 + T::DbWeight::get().reads_writes(3,3)]
pub fn commit_vote(origin, departmentid:u128, voting_cycle:u128, vote_commit:Vec<u8>) -> dispatch::DispatchResult {
let who = ensure_signed(origin.clone())?;
Self::check_citizen_associated_department(who.clone(), departmentid)?;
let status = VoteStatus::get((departmentid, voting_cycle, vote_commit.clone()));
match status {
Some(value) => {
if value == true {
Err(Error::<T>::AlreadyCommitUsed.into())
} else {
Err(Error::<T>::VoteRevealed.into())
}
}
None => {
Self::add_vote(departmentid, voting_cycle, vote_commit)?;
Ok(())
}
}
}
This is my helper function:
// Helper functions
impl<T: Config> Module<T> {
fn check_citizen_associated_department(
who: T::AccountId,
departmentid: u128,
) -> dispatch::DispatchResult {
let approved_peer_dep = PeerDepartments::<T>::get(&who);
match approved_peer_dep.binary_search(&departmentid) {
Ok(_) => {
Self::deposit_event(RawEvent::PeerDepartment(departmentid, who));
Ok(())
}
Err(_) => Err(Error::<T>::DepartmentNotAssociated.into()),
}
}
}
Yes, the error is because of the helper function, the error disappers when deposit_event of check_citizen_associated_department is removed. Not sure if its right way to write helper function.
This error:
thread 'tests::commit_vote' panicked at 'assertion failed: `(left == right)`
left: `[218, 23, 247, 200, 228, 182, 117, 227, 150, 32, 248, 47, 209, 182, 207, 246, 198, 19, 20, 74, 185, 125, 35, 94, 74, 161, 128, 199, 114, 155, 238, 228]`,
right: `[128, 69, 23, 167, 50, 250, 133, 59, 10, 41, 100, 95, 141, 187, 236, 154, 67, 174, 251, 17, 219, 45, 146, 141, 204, 77, 245, 38, 95, 131, 122, 48]`', pallets/template/src/tests.rs:106:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Is telling you that your extrinsic resulted in an error, but you also changed the state of the runtime. This is against the rules of how you can use Substrate.
This is the purpose of the assert_noop! macro:
https://crates.parity.io/frame_support/macro.assert_noop.html
There is a policy that all extrinsics must be "Check First, Write Last", as in, by the time you actually go about modifying the runtime state, there should be no way for an error to occur.
The problem seems to be that you emit an event in check_citizen_associated_department, which modifies the state, but then can error in match status.
You will need to fix your logic such that an event is only emitted when you know everything else will succeed.

C3 Extent not working as expected

I'm creating a pretty simple line graph and want the initial load to be a section of all available data, so am setting extent on the x axis:
This is how I am setting the extent:
axis: {
"x": {
"type": "timeseries",
"tick": {
"format": "%d/%m/%Y"
},
"label": {
"text": "X Label",
"position": "outer-center"
},
"padding": {
"left": 0
},
"extent": ["2017-10-01", "2017-10-05"]
},
"y": {
"label": {
"text": "Y Label",
"position": "outer-middle"
}
}
},
But it is ignored. The chart just shows the full extent of the data.
Is this the correct way to show a subset of the data when the chart is generated?
This is the full code and here's a fiddle (I tried a code snippet but didn't work)
const columnData = [
["x", "2017-10-01", "2017-10-02", "2017-10-03", "2017-10-04", "2017-10-05", "2017-10-06", "2017-10-07", "2017-10-08", "2017-10-09", "2017-10-10", "2017-10-11", "2017-10-12", "2017-10-13", "2017-10-14", "2017-10-15", "2017-10-16"],
["data0", -55, -50, 11, -18, 39, 65, -84, -15, 14, 81, -79, 67, -48, 38, 99, -60],
["data1", 28, 14, -99, -33, 55, 71, 58, 66, 7, -88, 99, -37, -7, 59, -13, -57],
["data2", 14, 6, -9, 25, 42, -93, -6, 67, -35, 88, 36, 45, 42, 78, 51, -88],
["data3", 31, -73, -69, 45, 55, 15, -48, 41, -64, -12, -6, 14, -69, 16, -65, -73],
["data4", 98, 60, 82, 80, -62, -47, 55, 87, -65, 37, 22, 30, 93, -69, -88, 33],
["data5", -98, 57, 71, -25, -40, 13, 72, -90, 71, -71, -21, -9, -90, 73, -94, 100]
];
const generateChart = function() {
const chart = c3.generate({
data: {
"x": "x",
"columns": columnData,
"type": "line"
},
axis: {
"x": {
"type": "timeseries",
"tick": {
"format": "%d/%m/%Y"
},
"label": {
"text": "X Label",
"position": "outer-center"
},
"padding": {
"left": 0
},
"extent": ["2017-10-01", "2017-10-05"]
},
"y": {
"label": {
"text": "Y Label",
"position": "outer-middle"
}
}
},
zoom: {
enabled: true
},
transition: {
duration: 100
},
legend: {
show: false
},
subchart: {
show: true
},
size: {
height: 500
},
grid: {
x: {
show: true
},
y: {
show: true
}
}
});
};
generateChart();
As of 11th May 2018 it seems this is a bug: https://github.com/c3js/c3/issues/2357
I switched to earlier versions (see below) of C3 and D3 and it works as it should.
I am now using C3 version 0.4.10 and D3 version 3.5.0

How to change sparkline background color within Kendo UI

$("#spark-collector").kendoSparkline({
type: "line",
data: [
71, 70, 69, 68, 65, 60, 55, 55, 50, 52,
73, 72, 72, 71, 68, 63, 57, 58, 53, 55,
63, 59, 61, 64, 58, 53, 48, 48, 45, 45,
63, 64, 63, 67, 58, 56, 53, 59, 51, 54
],
valueAxis: {
min: 0,
max: 100
},
seriesColors: ["blue"],
tooltip: {
visible: true
}
});
How to change sparkline background color within Kendo UI?
I believe you can use PlotArea for that. Please refer to the documentation. You can set Background, border, margin, opacity and padding
https://www.telerik.com/kendo-angular-ui/components/charts/api/PlotArea/
You should use the property chartArea.background. Referring to your example:
$("#spark-collector").kendoSparkline({
type: "line",
charArea: {
background: "cyan"
},
data: [
71, 70, 69, 68, 65, 60, 55, 55, 50, 52,
73, 72, 72, 71, 68, 63, 57, 58, 53, 55,
63, 59, 61, 64, 58, 53, 48, 48, 45, 45,
63, 64, 63, 67, 58, 56, 53, 59, 51, 54
],
valueAxis: {
min: 0,
max: 100
},
seriesColors: ["blue"],
tooltip: {
visible: true
}
});
Check the documentation here
Following a code snippet...
$("#spark-collector").kendoSparkline({
type: "line",
chartArea: {
background: "cyan"
},
data: [
71, 70, 69, 68, 65, 60, 55, 55, 50, 52,
73, 72, 72, 71, 68, 63, 57, 58, 53, 55,
63, 59, 61, 64, 58, 53, 48, 48, 45, 45,
63, 64, 63, 67, 58, 56, 53, 59, 51, 54
],
valueAxis: {
min: 0,
max: 100
},
seriesColors: ["blue"],
tooltip: {
visible: true
}
});
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.1.221/styles/kendo.bootstrap-v4.min.css" />
<script src="https://kendo.cdn.telerik.com/2018.1.221/js/jquery.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2018.1.221/js/kendo.all.min.js"></script>
<div id="spark-collector"></div>

Set in kendogrid sparkline

I am going to use sparkline in the" usage" column, just in the way that the two sparkline chart cover each other
There is a problem because when I click on the button Edite "sparkline" disappears.
Or click on "usage column" think that happens.
Why tooltip as bad as it can be displayed tooltip not regular.
Why sparkline "usage column" in all rows, there is only one row
jsfiddle code
$(document).ready(function () {
//var ds = new kendo.data.DataSource({
// transport: {
// read: {
// url: '/api/clientssnapshot',
// dataType: 'json',
// type: 'get',
// cache: false
// },
// },
// batch: true,
// pageSize: 10,
// schema: {
// model: {
// fields: {
// Mac: { editable: false, nullable: true },
// RadioName: { type: "string", validation: { required: true } },
// ApName: { type: "string", validation: { required: true, min: 1 } },
// RemoteIp: { type: "boolean" },
// TX: { type: "number", validation: { min: 0, required: true } },
// RX: { type: "number", validation: { min: 0, required: true } },
// Signal: { type: "number", validation: { min: 0, required: true } },
// Uptime: { type: "number", validation: { min: 0, required: true } },
// }
// }
// }
//});
$('.table').kendoGrid({
dataSource: {
data: [{
"Mac": "D4:CA:6D:28:D1:05",
"RadioName": "D4CA6D28D105",
"ApName": "Om11",
"ApIp": "10.20.0.100",
"TX": 48,
"RX": 54,
"Signal": -64,
"Uptime": 797452,
"InRate": 0,
"OutRate": 0,
"AccountingId": 759,
"AccountingName": "فرشاد صفایی زاده",
"RemoteIp": "188.121.123.56",
"IsValidInScan": true,
"Comments": null,
"ApScanId": 26173,
"InRateHistory": "0, 0, 0, 0, 2, 0, 2, 16, 96, 16, 96, 16, 96, 113, 31, 113, 31, 113, 31, 0",
"OutRateHistory": "0, 5, 3, 5, 2, 5, 2, 35, 136, 35, 136, 35, 136, 164, 51, 164, 51, 164, 51, 4"
}, {
"Mac": "00:15:6D:BD:64:92",
"RadioName": "Behrooz Hoseyn",
"ApName": "Om11",
"ApIp": "10.20.0.100",
"TX": 48,
"RX": 18,
"Signal": -65,
"Uptime": 797446,
"InRate": 2,
"OutRate": 2,
"AccountingId": 750,
"AccountingName": "بهروز حسینی",
"RemoteIp": "188.121.123.48",
"IsValidInScan": true,
"Comments": null,
"ApScanId": 26173,
"InRateHistory": "0, 0, 0, 0, 2, 0, 2, 16, 96, 16, 96, 16, 96, 113, 31, 113, 31, 113, 31, 0",
"OutRateHistory": "0, 5, 3, 5, 2, 5, 2, 35, 136, 35, 136, 35, 136, 164, 51, 164, 51, 164, 51, 4"
}, {
"Mac": "00:15:6D:1E:B3:6C",
"RadioName": "UBNT",
"ApName": "Om11",
"ApIp": "10.20.0.100",
"TX": 54,
"RX": 24,
"Signal": -65,
"Uptime": 310336,
"InRate": 0,
"OutRate": 0,
"AccountingId": 820,
"AccountingName": "******",
"RemoteIp": "10.10.15.129",
"IsValidInScan": true,
"Comments": null,
"ApScanId": 26173,
"InRateHistory": "0, 0, 0, 0, 2, 0, 2, 16, 96, 16, 96, 16, 96, 113, 31, 113, 31, 113, 31, 0",
"OutRateHistory": "0, 5, 3, 5, 2, 5, 2, 35, 136, 35, 136, 35, 136, 164, 51, 164, 51, 164, 51, 4"
}, {
"Mac": "00:15:6D:1C:B1:89",
"RadioName": "Grous Tajhiz P",
"ApName": "Om11",
"ApIp": "10.20.0.100",
"TX": 48,
"RX": 6,
"Signal": -62,
"Uptime": 122116,
"InRate": 0,
"OutRate": 0,
"AccountingId": 595,
"AccountingName": "حمید شمس لواسانی",
"RemoteIp": "188.121.124.17",
"IsValidInScan": true,
"Comments": null,
"ApScanId": 26173,
"InRateHistory": "0, 0, 0, 0, 2, 0, 2, 16, 96, 16, 96, 16, 96, 113, 31, 113, 31, 113, 31, 0",
"OutRateHistory": "0, 5, 3, 5, 2, 5, 2, 35, 136, 35, 136, 35, 136, 164, 51, 164, 51, 164, 51, 4"
}, {
"Mac": "00:27:22:3E:91:12",
"RadioName": "Anbar Aminzade",
"ApName": "Om1",
"ApIp": "10.20.0.101",
"TX": 36,
"RX": 36,
"Signal": -68,
"Uptime": 1131461,
"InRate": 4,
"OutRate": 4,
"AccountingId": 977,
"AccountingName": "انبار شهید امین زاده ",
"RemoteIp": "188.121.123.31",
"IsValidInScan": true,
"Comments": null,
"ApScanId": 26173,
"InRateHistory": "0, 0, 0, 0, 2, 0, 2, 16, 96, 16, 96, 16, 96, 113, 31, 113, 31, 113, 31, 0",
"OutRateHistory": "0, 5, 3, 5, 2, 5, 2, 35, 136, 35, 136, 35, 136, 164, 51, 164, 51, 164, 51, 4"
}, {
"Mac": "00:15:6D:1A:59:D0",
"RadioName": "UBNT",
"ApName": "Om1",
"ApIp": "10.20.0.101",
"TX": 36,
"RX": 12,
"Signal": -73,
"Uptime": 734737,
"InRate": 2,
"OutRate": 2,
"AccountingId": 820,
"AccountingName": "******",
"RemoteIp": "10.10.15.76",
"IsValidInScan": true,
"Comments": null,
"ApScanId": 26173,
"InRateHistory": "0, 0, 0, 0, 2, 0, 2, 16, 96, 16, 96, 16, 96, 113, 31, 113, 31, 113, 31, 0",
"OutRateHistory": "0, 5, 3, 5, 2, 5, 2, 35, 136, 35, 136, 35, 136, 164, 51, 164, 51, 164, 51, 4"
}, {
"Mac": "00:15:6D:E2:2D:13",
"RadioName": "UBNT",
"ApName": "Om1",
"ApIp": "10.20.0.101",
"TX": 54,
"RX": 36,
"Signal": -72,
"Uptime": 848,
"InRate": 0,
"OutRate": 0,
"AccountingId": 820,
"AccountingName": "******",
"RemoteIp": "10.10.15.67",
"IsValidInScan": true,
"Comments": null,
"ApScanId": 26173,
"InRateHistory": "0, 0, 0, 0, 2, 0, 2, 16, 96, 16, 96, 16, 96, 113, 31, 113, 31, 113, 31, 0",
"OutRateHistory": "0, 5, 3, 5, 2, 5, 2, 35, 136, 35, 136, 35, 136, 164, 51, 164, 51, 164, 51, 4"
}, {
"Mac": "00:27:22:32:24:C9",
"RadioName": "UBNT",
"ApName": "Om7",
"ApIp": "10.20.0.100",
"TX": 36,
"RX": 24,
"Signal": -78,
"Uptime": 731588,
"InRate": 0,
"OutRate": 0,
"AccountingId": 820,
"AccountingName": "******",
"RemoteIp": "10.10.15.188",
"IsValidInScan": true,
"Comments": null,
"ApScanId": 26173,
"InRateHistory": "0, 0, 0, 0, 2, 0, 2, 16, 96, 16, 96, 16, 96, 113, 31, 113, 31, 113, 31, 0",
"OutRateHistory": "0, 5, 3, 5, 2, 5, 2, 35, 136, 35, 136, 35, 136, 164, 51, 164, 51, 164, 51, 4"
}, {
"Mac": "00:15:6D:FE:BB:E2",
"RadioName": "ketabforooshie",
"ApName": "Om7",
"ApIp": "10.20.0.100",
"TX": 54,
"RX": 36,
"Signal": -72,
"Uptime": 240361,
"InRate": 0,
"OutRate": 0,
"AccountingId": 533,
"AccountingName": "قاسم رضاپور",
"RemoteIp": "188.121.124.214",
"IsValidInScan": true,
"Comments": null,
"ApScanId": 26173,
"InRateHistory": "0, 0, 0, 0, 2, 0, 2, 16, 96, 16, 96, 16, 96, 113, 31, 113, 31, 113, 31, 0",
"OutRateHistory": "0, 5, 3, 5, 2, 5, 2, 35, 136, 35, 136, 35, 136, 164, 51, 164, 51, 164, 51, 4"
}, {
"Mac": "00:27:22:D2:86:56",
"RadioName": "UBNT",
"ApName": "Om7",
"ApIp": "10.20.0.100",
"TX": 48,
"RX": 12,
"Signal": -72,
"Uptime": 126430,
"InRate": 0,
"OutRate": 0,
"AccountingId": 1453,
"AccountingName": "حسن قربانی",
"RemoteIp": "188.121.123.154",
"IsValidInScan": true,
"Comments": null,
"ApScanId": 26173,
"InRateHistory": "0, 0, 0, 0, 2, 0, 2, 16, 96, 16, 96, 16, 96, 113, 31, 113, 31, 113, 31, 0",
"OutRateHistory": "0, 5, 3, 5, 2, 5, 2, 35, 136, 35, 136, 35, 136, 164, 51, 164, 51, 164, 51, 4"
}, {
"Mac": "00:27:22:78:A3:19",
"RadioName": "UBNT",
"ApName": "Om7",
"ApIp": "10.20.0.100",
"TX": 54,
"RX": 54,
"Signal": -56,
"Uptime": 58617,
"InRate": 0,
"OutRate": 0,
"AccountingId": 820,
"AccountingName": "******",
"RemoteIp": "10.10.15.39",
"IsValidInScan": true,
"Comments": null,
"ApScanId": 26173,
"InRateHistory": "0, 0, 0, 0, 2, 0, 2, 16, 96, 16, 96, 16, 96, 113, 31, 113, 31, 113, 31, 0",
"OutRateHistory": "0, 5, 3, 5, 2, 5, 2, 35, 136, 35, 136, 35, 136, 164, 51, 164, 51, 164, 51, 4"
}
]
},
sortable: true,
groupable: true,
selectable: true,
navigatable: true,
height: 500,
scrollable: true,
pageable: true,
columns: [{
field: "Mac",
title: "Mac",
width: 170
}, {
field: "RadioName",
title: "Radio",
width: 150
}, {
field: "ApName",
title: "Ap",
width: 80,
template: '#=ApName#'
}, {
field: "RemoteIp",
title: "Remote IP",
width: 160,
template: '#=RemoteIp#'
}, {
field: "AccountingName",
title: "Name",
width: 130,
template: ' #= AccountingName # '
}, {
field: "TX",
title: "TX",
width: 44
}, {
field: "RX",
title: "RX",
width: 50
}, {
field: "Signal",
title: "Signal",
width: 50
}, {
field: "Uptime",
title: "Uptime",
width: 78
}, {
field: "Usage",
title: "Usage",
template: '<span id="sparkline"></span>'
}, {
command: ["edit"],
title: " "
}],
editable: "popup",
});
$(".ref").click(function () {
$(".table").data("kendoGrid").dataSource.read();
});
$("#sparkline").kendoSparkline({
type: "area",
series: [{
name: "World",
data: [15.7, 16.7, 20, 23.5, 26.6, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5, 3.5],
}, {
name: 'New York',
data: [0.7, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5],
}],
categoryAxis: {
categories: [2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015]
}
});
<div class="span6 box gradient main_stting">
<div class="dataTables_filter" id="txtSearch">
<label>Search:
<input type="text" aria-controls="DataTables_Table_0">
</label>
</div>
<div class="title">
<button class="btn ref" type="submit">Refresh</button>
<h3></h3>
</div>
<div class="content">
<div class="table"></div>
</div>
thank you
After edit, the HTML elements are destroyed and recreated when the Grid updates. You will need to recreate your sparklines. It is basically the same as this issue.

Resources