Skip to content

Commit 2cd3d89

Browse files
committed
add a few graphs
1 parent c43edb9 commit 2cd3d89

8 files changed

Lines changed: 210 additions & 32 deletions

File tree

OpenFlow/src/DatabaseConnection.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,27 @@ export class DatabaseConnection {
156156
*/
157157
async MapReduce<T>(map: mapFunc, reduce: reduceFunc, finalize: finalizeFunc, query: any, out: string | any, collectionname: string, scope: any, jwt: string): Promise<T[]> {
158158
await this.connect();
159+
160+
if (query !== null && query !== undefined) {
161+
var json: any = query;
162+
if (typeof json !== 'string' && !(json instanceof String)) {
163+
json = JSON.stringify(json, (key, value) => {
164+
if (value instanceof RegExp)
165+
return ("__REGEXP " + value.toString());
166+
else
167+
return value;
168+
});
169+
}
170+
query = JSON.parse(json, (key, value) => {
171+
if (typeof value === 'string' && value.match(isoDatePattern)) {
172+
return new Date(value); // isostring, so cast to js date
173+
} else if (value.toString().indexOf("__REGEXP ") == 0) {
174+
var m = value.split("__REGEXP ")[1].match(/\/(.*)\/(.*)?/);
175+
return new RegExp(m[1], m[2] || "");
176+
} else
177+
return value; // leave any other value as-is
178+
});
179+
}
159180
var q: any = query;
160181
if (query !== null && query !== undefined) {
161182
q = { $and: [query, this.getbasequery(jwt, "_acl", [Rights.read])] };

OpenFlow/src/Logger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export class Logger {
4545
enumerateErrorFormat(),
4646
winston.format.json()
4747
),
48-
defaultMeta: { service: "openflownodered" },
48+
defaultMeta: { service: "openflow" },
4949
transports: [
5050
// new winston.transports.File(options.file),
5151
new winston.transports.Console(options.console)

OpenFlow/src/User.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,20 +56,29 @@ export class User extends Base {
5656
return result;
5757
}
5858
public static async FindByUsername(username: string): Promise<User> {
59-
var items: User[] = await Config.db.query<User>({ username: new RegExp(["^", username, "$"].join(""), "i") }, null, 1, 0, null, "users", TokenUser.rootToken());
59+
var byuser = { username: new RegExp(["^", username, "$"].join(""), "i") };
60+
//var byid = { federationids: { $elemMatch: new RegExp(["^", username, "$"].join(""), "i") } }
61+
var byid = { federationids: new RegExp(["^", username, "$"].join(""), "i") }
62+
var q = { $or: [byuser, byid] };
63+
var items: User[] = await Config.db.query<User>(q, null, 1, 0, null, "users", TokenUser.rootToken());
6064
if (items === null || items === undefined || items.length === 0) { return null; }
6165
var result: User = User.assign(items[0]);
6266
await result.DecorateWithRoles();
6367
return result;
6468
}
6569
public static async FindByUsernameOrFederationid(username: string): Promise<User> {
66-
var items: User[] = await Config.db.query<User>({
67-
$or:
68-
[
69-
{ username: new RegExp(["^", username, "$"].join(""), "i") },
70-
{ federationids: { $elemMatch: { id: new RegExp(["^", username, "$"].join(""), "i") } } }
71-
]
72-
}, null, 1, 0, null, "users", TokenUser.rootToken());
70+
var byuser = { username: new RegExp(["^", username, "$"].join(""), "i") };
71+
//var byid = { federationids: { $elemMatch: new RegExp(["^", username, "$"].join(""), "i") } }
72+
var byid = { federationids: new RegExp(["^", username, "$"].join(""), "i") }
73+
var q = { $or: [byuser, byid] };
74+
var items: User[] = await Config.db.query<User>(q, null, 1, 0, null, "users", TokenUser.rootToken());
75+
// var items: User[] = await Config.db.query<User>({
76+
// $or:
77+
// [
78+
// { username: new RegExp(["^", username, "$"].join(""), "i") },
79+
// { federationids: { $elemMatch: { id: new RegExp(["^", username, "$"].join(""), "i") } } }
80+
// ]
81+
// }, null, 1, 0, null, "users", TokenUser.rootToken());
7382
if (items === null || items === undefined || items.length === 0) { return null; }
7483
var result: User = User.assign(items[0]);
7584
await result.DecorateWithRoles();

OpenFlow/src/public/Controllers.ts

Lines changed: 135 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
module openflow {
22
"use strict";
33

4+
function treatAsUTC(date): number {
5+
var result = new Date(date);
6+
result.setMinutes(result.getMinutes() - result.getTimezoneOffset());
7+
return result as any;
8+
}
9+
10+
function daysBetween(startDate, endDate): number {
11+
var millisecondsPerDay = 24 * 60 * 60 * 1000;
12+
return (treatAsUTC(endDate) - treatAsUTC(startDate)) / millisecondsPerDay;
13+
}
414

515

616
export class WorkflowsCtrl extends entitiesCtrl<openflow.Base> {
@@ -30,36 +40,67 @@ module openflow {
3040
for (var i = 0; i < this.models.length; i++) {
3141
var workflow = this.models[i] as any;
3242
var d = new Date();
33-
//d.setMonth(d.getMonth() - 1);
34-
d.setDate(d.getDate() - 30);
43+
d.setMonth(d.getMonth() - 1);
44+
//d.setDate(d.getDate() - 30);
3545
console.log(d);
36-
// {$where : function() { return this.date.getMonth() == 11} }
37-
var q = { _type: "workflowinstance", WorkflowId: workflow._id, "_created": { "$gte": new Date(d.toISOString()) } };
38-
// var q = { _type: "workflowinstance", WorkflowId: workflow._id, "_created": { "$gte": new Date("2010-04-30T00:00:00.000Z") } };
3946

40-
workflow.instances = await this.api.Query("openrpa_instances", q, null, null, 100);
47+
48+
console.log("get mapreduce of instances");
49+
var stats = await this.api.MapReduce("openrpa_instances",
50+
function map() {
51+
var startDate = new Date(this._created);
52+
this.count = 1;
53+
emit(startDate.toISOString().split('T')[0], this);
54+
}, function reduce(key, values) {
55+
var reducedObject = { count: 0, value: 0, avg: 0, minrun: 0, maxrun: 0, run: 0, _acl: [] };
56+
values.forEach(function (value) {
57+
var startDate = new Date(value._created);
58+
var endDate = new Date(value._modified);
59+
var seconds = (endDate.getTime() - startDate.getTime()) / 1000;
60+
if (reducedObject.minrun == 0 && seconds > 0) reducedObject.minrun = seconds;
61+
if (reducedObject.minrun > seconds) reducedObject.minrun = seconds;
62+
if (reducedObject.maxrun < seconds) reducedObject.maxrun = seconds;
63+
reducedObject.run += seconds;
64+
reducedObject.count += value.count;
65+
reducedObject._acl = value._acl;
66+
});
67+
return reducedObject;
68+
}, function finalize(key, reducedValue) {
69+
if (reducedValue.count > 0) {
70+
reducedValue.avg = reducedValue.value / reducedValue.count;
71+
reducedValue.run = reducedValue.run / reducedValue.count;
72+
}
73+
return reducedValue;
74+
}, { _type: "workflowinstance", WorkflowId: workflow._id, "_created": { "$gte": new Date(d.toISOString()) } }, { inline: 1 }, null);
75+
76+
77+
78+
// // {$where : function() { return this.date.getMonth() == 11} }
79+
// var q = { _type: "workflowinstance", WorkflowId: workflow._id, "_created": { "$gte": new Date(d.toISOString()) } };
80+
// // var q = { _type: "workflowinstance", WorkflowId: workflow._id, "_created": { "$gte": new Date("2010-04-30T00:00:00.000Z") } };
81+
82+
// workflow.instances = await this.api.Query("openrpa_instances", q, null, null, 100);
4183

4284

4385
chart = new chartset();
44-
if (workflow == undefined) { chart.heading = "deleted workflow"; } else { chart.heading = workflow.name; }
4586
chart.charttype = "line"
4687
chart.data = [];
4788
var lastdate = "";
48-
console.log(workflow.instances);
49-
for (var i = 0; i < workflow.instances.length; i++) {
50-
var value = workflow.instances[i];
51-
var startDate = new Date(value._created);
52-
var endDate = new Date(value._modified);
53-
var seconds = (endDate.getTime() - startDate.getTime()) / 1000;
54-
55-
chart.data.push(seconds);
56-
if (lastdate != startDate.toISOString().split('T')[0]) {
57-
lastdate = startDate.toISOString().split('T')[0];
58-
chart.labels.push(startDate.toISOString().split('T')[0]);
89+
var days = daysBetween(d, new Date());
90+
console.log(stats);
91+
for (var y = 0; y < days; y++) {
92+
var startDate = new Date(d);
93+
startDate.setDate(d.getDate() + y);
94+
var datestring = startDate.toISOString().split('T')[0];
95+
var exists = stats.filter(m => m._id == datestring);
96+
if (exists.length > 0) {
97+
chart.data.push(exists[0].value.count);
5998
} else {
60-
chart.labels.push("");
99+
chart.data.push(0);
61100
}
62-
// chart.labels.push(startDate.toISOString().split('T')[0]);
101+
102+
103+
chart.labels.push(datestring);
63104
}
64105
workflow.chart = chart;
65106

@@ -492,7 +533,68 @@ module openflow {
492533
this.collection = "users";
493534
WebSocketClient.onSignedin((user: TokenUser) => {
494535
this.loadData();
536+
this._loadData();
495537
});
538+
539+
}
540+
async _loadData(): Promise<void> {
541+
this.loading = true;
542+
var chart: chartset = null;
543+
console.log("get users");
544+
this.models = await this.api.Query("users", { _type: "user" }, null, null);
545+
console.log(this.models);
546+
547+
for (var i = 0; i < this.models.length; i++) {
548+
var user = this.models[i] as any;
549+
var d = new Date();
550+
d.setMonth(d.getMonth() - 1);
551+
//d.setDate(d.getDate() - 30);
552+
console.log(d);
553+
554+
555+
console.log("get mapreduce for " + user.name);
556+
var stats = await this.api.MapReduce("audit",
557+
function map() {
558+
var startDate = new Date(this._created);
559+
this.count = 1;
560+
emit(startDate.toISOString().split('T')[0], this);
561+
}, function reduce(key, values) {
562+
var reducedObject = { count: 0, value: 0, avg: 0, minrun: 0, maxrun: 0, run: 0, _acl: [] };
563+
values.forEach(function (value) {
564+
reducedObject.count += value.count;
565+
reducedObject._acl = value._acl;
566+
});
567+
return reducedObject;
568+
}, function finalize(key, reducedValue) {
569+
if (reducedValue.count > 0) {
570+
reducedValue.avg = reducedValue.value / reducedValue.count;
571+
}
572+
return reducedValue;
573+
}, { userid: user._id, "_created": { "$gte": new Date(d.toISOString()) } }, { inline: 1 }, null);
574+
575+
chart = new chartset();
576+
chart.charttype = "line"
577+
chart.data = [];
578+
var days = daysBetween(d, new Date());
579+
console.log(stats);
580+
for (var y = 0; y < days; y++) {
581+
var startDate = new Date(d);
582+
startDate.setDate(d.getDate() + y);
583+
var datestring = startDate.toISOString().split('T')[0];
584+
var exists = stats.filter(m => m._id == datestring);
585+
if (exists.length > 0) {
586+
chart.data.push(exists[0].value.count);
587+
} else {
588+
chart.data.push(0);
589+
}
590+
//chart.labels.push(datestring);
591+
chart.labels.push("");
592+
}
593+
user.chart = chart;
594+
595+
}
596+
this.loading = false;
597+
if (!this.$scope.$$phase) { this.$scope.$apply(); }
496598
}
497599
async DeleteOne(model: any): Promise<any> {
498600
this.loading = true;
@@ -503,6 +605,7 @@ module openflow {
503605
}
504606
}
505607
export class UserCtrl extends entityCtrl<openflow.TokenUser> {
608+
public newid: string;
506609
constructor(
507610
public $scope: ng.IScope,
508611
public $location: ng.ILocationService,
@@ -527,6 +630,18 @@ module openflow {
527630

528631
});
529632
}
633+
deleteid(id) {
634+
if (this.model.federationids === null || this.model.federationids === undefined) {
635+
this.model.federationids = [];
636+
}
637+
this.model.federationids = this.model.federationids.filter(function (m: any): boolean { return m !== id; });
638+
}
639+
addid() {
640+
if (this.model.federationids === null || this.model.federationids === undefined) {
641+
this.model.federationids = [];
642+
}
643+
this.model.federationids.push(this.newid);
644+
}
530645
async submit(): Promise<void> {
531646
if (this.model._id) {
532647
await this.api.Update(this.collection, this.model);

OpenFlow/src/public/User.html

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,39 @@ <h1 class="pagetitle" translate lib="web">userdetails</h1>
4848
</div>
4949
</div>
5050

51+
<div class="form-group">
52+
<label class="col-sm-2 control-label" translate lib="web">providerids</label>
53+
<div class="col-sm-4">
54+
</div>
55+
</div>
56+
<div class="form-group" ng-repeat="id in ctrl.model.federationids">
57+
<label class="col-sm-2 control-label" translate lib="web"></label>
58+
<div class="col-sm-4">
59+
{{ id }}
60+
<button type="button" ng-disabled="ctrl.loading==true" class="btn btn-danger" ng-click="ctrl.deleteid(id)"
61+
translate lib="web">delete</button>
62+
</div>
63+
</div>
64+
65+
<div class="form-inline">
66+
<div class="form-group mb-2">
67+
<label class="sr-only" translate lib="web">AddFederationId</label>
68+
</div>
69+
<div class="form-group mx-sm-3 mb-2">
70+
<input ng-model="ctrl.newid" type="text" class="form-control" placeholder="New identity typically email"
71+
autocomplete="new-password">
72+
</div>
73+
<button type="button" class="btn btn-success mb-2" ng-disabled="ctrl.loading==true" ng-click="ctrl.addid()">add
74+
identity</button>
75+
</div>
76+
77+
78+
5179

5280
<div class="form-group">
5381
<div class="col-sm-offset-2 col-sm-10">
5482
<button type="submit" ng-disabled="ctrl.loading==true" class="btn btn-success" translate
55-
lib="web">Save</button>
83+
lib="web">save</button>
5684
</div>
5785
</div>
5886

OpenFlow/src/public/Users.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ <h1>Users</h1>
1313
<th ng-click="ctrl.ToggleOrder('lastseen')"><b translate lib="web">lastseen</b></th>
1414
<th></th>
1515
<th></th>
16+
<th></th>
1617
</tr>
1718
</thead>
1819
<tbody>
@@ -25,6 +26,11 @@ <h1>Users</h1>
2526
<td>
2627
<timesince ng-model="model.lastseen" />
2728
</td>
29+
<td class="btn-cell">
30+
<canvas id="bar" class="model.chart-base" chart-type="model.chart.charttype" chart-data="model.chart.data"
31+
chart-labels="model.chart.labels" chart-series="model.chart.series">
32+
</canvas>
33+
</td>
2834
<td class="btn-cell">
2935
<a ng-href="#/User/{{model._id}}">edit</a>
3036
</td>

OpenFlow/src/public/Workflows.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ <h1 translate lib="web">entities</h1>
2727
<canvas id="bar" class="model.chart-base" chart-type="model.chart.charttype" chart-data="model.chart.data"
2828
chart-labels="model.chart.labels" chart-series="model.chart.series">
2929
</canvas>
30-
3130
</td>
3231
<td class="btn-cell">
3332
<a href ng-click="ctrl.DeleteOne(model)" ng-disabled="ctrl.loading==true" translate lib="web">delete</a>

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.0.115
1+
0.0.117

0 commit comments

Comments
 (0)