marty 8.5.0 → 9.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.eslintignore +1 -0
- data/.eslintrc.js +26 -0
- data/.gitignore +3 -0
- data/.gitlab-ci.yml +7 -0
- data/.prettierignore +14 -0
- data/.rubocop_todo.yml +1 -1
- data/Dockerfile.dummy +3 -0
- data/Makefile +1 -0
- data/app/assets/javascripts/marty/cable.js +7 -3
- data/app/assets/javascripts/marty/extjs/extensions/datetime_field/component.js +401 -0
- data/app/assets/javascripts/marty/extjs/extensions/datetime_field/field.js +140 -0
- data/app/assets/javascripts/marty/extjs/extensions/marty.js +845 -781
- data/app/assets/stylesheets/marty/codemirror/codemirror.css +215 -77
- data/app/assets/stylesheets/marty/codemirror/delorean.css +2 -2
- data/app/assets/stylesheets/marty/dark_mode.css +13 -3
- data/app/components/marty/auth_app/client/auth_app.js +107 -102
- data/app/components/marty/base_rule_view/client/base_rule_view.js +10 -8
- data/app/components/marty/data_grid_view/client/data_grid_edit.js +534 -519
- data/app/components/marty/form/client/form.js +3 -3
- data/app/components/marty/grid/client/grid.js +110 -87
- data/app/components/marty/import_view/client/import_view.js +18 -18
- data/app/components/marty/live_search_grid_panel/client/live_search_grid_panel.js +14 -13
- data/app/components/marty/main_auth_app/client/main_auth_app.js +42 -42
- data/app/components/marty/mcfly_grid_panel/client/mcfly_grid_panel.js +27 -18
- data/app/components/marty/new_posting_form/client/new_posting_form.js +3 -3
- data/app/components/marty/panel/client/panel.js +3 -3
- data/app/components/marty/posting_grid/client/posting_grid.js +24 -18
- data/app/components/marty/promise_view/client/promise_view.css +12 -12
- data/app/components/marty/promise_view/client/promise_view.js +46 -38
- data/app/components/marty/report_form/client/report_form.js +30 -28
- data/app/components/marty/report_select/client/report_select.js +28 -23
- data/app/components/marty/reporting/client/reporting.js +3 -3
- data/app/components/marty/script_form/client/script_form.js +29 -23
- data/app/components/marty/script_tester/client/script_tester.js +4 -5
- data/app/components/marty/scripting/client/scripting.js +40 -36
- data/app/components/marty/simple_app/client/simple_app.js +33 -24
- data/app/components/marty/simple_app/client/statusbar_ext.js +1 -1
- data/app/controllers/marty/rpc_controller.rb +3 -0
- data/app/models/marty/promise.rb +10 -2
- data/app/services/marty/data_grid/constraint.rb +2 -1
- data/app/services/marty/jobs/schedule.rb +2 -2
- data/app/services/marty/promises/delorean/create.rb +9 -2
- data/app/services/marty/promises/ruby/create.rb +7 -2
- data/config/initializers/delayed_job_config.rb +1 -0
- data/delorean/blame_report.dl +50 -58
- data/delorean/enum_report.dl +2 -3
- data/delorean/{marty_fields.dl → fields.dl} +16 -0
- data/delorean/styles.dl +216 -0
- data/delorean/table_report.dl +4 -4
- data/lib/marty/monkey.rb +17 -0
- data/lib/marty/promise_job.rb +9 -0
- data/lib/marty/promise_ruby_job.rb +8 -0
- data/lib/marty/version.rb +1 -1
- data/make-lint.mk +19 -0
- data/package.json +16 -0
- data/prettier.config.js +6 -0
- data/spec/controllers/diagnostic/controller_spec.rb +0 -1
- data/spec/controllers/rpc_controller_spec.rb +21 -7
- data/spec/dummy/delorean/data_report.dl +4 -4
- data/spec/dummy/delorean/fields.dl +1 -0
- data/spec/features/data_grid_spec.rb +37 -1
- data/spec/job_helper.rb +6 -0
- data/spec/lib/data_blame_spec.rb +4 -4
- data/spec/lib/data_importer_spec.rb +6 -4
- data/spec/models/promise_spec.rb +31 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/support/download_helper.rb +53 -49
- data/spec/support/json_helper.rb +11 -0
- data/spec/support/shared_connection_db_helpers.rb +1 -0
- data/spec/support/suite.rb +20 -14
- data/yarn.lock +967 -0
- metadata +16 -4
- data/spec/dummy/delorean/marty_fields.dl +0 -1
@@ -1,82 +1,86 @@
|
|
1
|
-
{
|
2
|
-
netzkeOnSignIn
|
3
|
-
|
4
|
-
this.signinWin =
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
1
|
+
({
|
2
|
+
netzkeOnSignIn() {
|
3
|
+
const me = this;
|
4
|
+
this.signinWin =
|
5
|
+
this.signinWin ||
|
6
|
+
Ext.create("Ext.Window", {
|
7
|
+
modal: true,
|
8
|
+
layout: "fit",
|
9
|
+
|
10
|
+
submit() {
|
11
|
+
const form = this.items.first();
|
12
|
+
const values = form.getForm().getValues();
|
13
|
+
|
14
|
+
// calling the endpoint
|
15
|
+
me.server.signIn(values, function(res) {
|
16
|
+
if (res) {
|
17
|
+
if (!me.authSpecMode) {
|
18
|
+
this.signinWin.close();
|
19
|
+
}
|
20
|
+
Ext.Msg.show({
|
21
|
+
title: "Signed in",
|
22
|
+
msg: "Signed in successfully, reloading...",
|
23
|
+
icon: Ext.Msg.INFO,
|
24
|
+
closable: false
|
25
|
+
});
|
26
|
+
if (!me.authSpecMode) {
|
27
|
+
window.location.href = "/";
|
28
|
+
}
|
26
29
|
}
|
27
|
-
}
|
28
|
-
});
|
29
|
-
},
|
30
|
-
|
31
|
-
closeAction: 'hide',
|
32
|
-
title: "Sign in",
|
33
|
-
fbar: [{
|
34
|
-
text: 'OK',
|
35
|
-
name: 'signin_submit',
|
36
|
-
handler: function () {
|
37
|
-
this.up('window').submit();
|
38
|
-
},
|
30
|
+
});
|
39
31
|
},
|
40
|
-
{
|
41
|
-
text: 'Cancel',
|
42
|
-
handler: function () {
|
43
|
-
this.up('window').close();
|
44
|
-
},
|
45
|
-
},
|
46
|
-
],
|
47
32
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
field.up('window').submit();
|
57
|
-
}
|
33
|
+
closeAction: "hide",
|
34
|
+
title: "Sign in",
|
35
|
+
fbar: [
|
36
|
+
{
|
37
|
+
text: "OK",
|
38
|
+
name: "signin_submit",
|
39
|
+
handler() {
|
40
|
+
this.up("window").submit();
|
58
41
|
}
|
59
42
|
},
|
60
|
-
},
|
61
|
-
items: [{
|
62
|
-
fieldLabel: 'Login',
|
63
|
-
name: 'login',
|
64
|
-
},
|
65
43
|
{
|
66
|
-
|
67
|
-
|
68
|
-
|
44
|
+
text: "Cancel",
|
45
|
+
handler() {
|
46
|
+
this.up("window").close();
|
47
|
+
}
|
69
48
|
}
|
70
|
-
]
|
71
|
-
|
72
|
-
|
49
|
+
],
|
50
|
+
|
51
|
+
items: {
|
52
|
+
xtype: "form",
|
53
|
+
defaultType: "textfield",
|
54
|
+
bodyPadding: "15px 15px 0px 10px",
|
55
|
+
defaults: {
|
56
|
+
listeners: {
|
57
|
+
specialkey(field, event) {
|
58
|
+
if (event.getKey() == event.ENTER) {
|
59
|
+
field.up("window").submit();
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
},
|
64
|
+
items: [
|
65
|
+
{
|
66
|
+
fieldLabel: "Login",
|
67
|
+
name: "login"
|
68
|
+
},
|
69
|
+
{
|
70
|
+
fieldLabel: "Password",
|
71
|
+
name: "password",
|
72
|
+
inputType: "password"
|
73
|
+
}
|
74
|
+
]
|
75
|
+
}
|
76
|
+
});
|
73
77
|
|
74
78
|
this.signinWin.show();
|
75
|
-
this.signinWin.down(
|
79
|
+
this.signinWin.down("textfield").focus(false, 100);
|
76
80
|
},
|
77
81
|
|
78
|
-
netzkeOnSignOut
|
79
|
-
this.server.signOut(null, function
|
82
|
+
netzkeOnSignOut() {
|
83
|
+
this.server.signOut(null, function(success) {
|
80
84
|
if (success) {
|
81
85
|
Ext.Msg.show({
|
82
86
|
title: "Signed out",
|
@@ -86,63 +90,64 @@
|
|
86
90
|
});
|
87
91
|
window.location.href = "/";
|
88
92
|
}
|
89
|
-
})
|
93
|
+
});
|
90
94
|
},
|
91
95
|
|
92
|
-
netzkeOnToggleDarkMode
|
93
|
-
|
96
|
+
netzkeOnToggleDarkMode() {
|
97
|
+
this.server.toggleDarkMode(() => {
|
98
|
+
window.location.href = "/";
|
99
|
+
});
|
94
100
|
},
|
95
101
|
|
96
|
-
netzkeOnNotificationsWindow
|
102
|
+
netzkeOnNotificationsWindow() {
|
97
103
|
this.netzkeLoadComponent("notifications_window", {
|
98
|
-
callback
|
104
|
+
callback(w) {
|
99
105
|
w.show();
|
100
106
|
|
101
107
|
this.server.markWebNotificationsDelivered();
|
102
108
|
|
103
|
-
|
104
|
-
|
105
|
-
)
|
109
|
+
const notificationsButton = this.menuBar.items.items.find(function(
|
110
|
+
item
|
111
|
+
) {
|
112
|
+
return item.name === "notificationsWindow";
|
113
|
+
});
|
106
114
|
|
107
|
-
notificationsButton.setText(
|
108
|
-
}
|
115
|
+
notificationsButton.setText(""); // Remove the counter
|
116
|
+
}
|
109
117
|
});
|
110
118
|
},
|
111
119
|
|
112
|
-
netzkeInitComponentCallback
|
120
|
+
netzkeInitComponentCallback() {
|
113
121
|
try {
|
114
|
-
|
122
|
+
const subscription = RailsApp.cable.subscriptions.subscriptions.find(
|
115
123
|
(sub) => sub.identifier === '{"channel":"Marty::NotificationChannel"}'
|
116
|
-
)
|
124
|
+
);
|
117
125
|
|
118
126
|
// In case if component is initialized twice
|
119
127
|
if (subscription) {
|
120
|
-
return
|
128
|
+
return;
|
121
129
|
}
|
122
130
|
|
123
|
-
RailsApp.cable.subscriptions.create(
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
131
|
+
RailsApp.cable.subscriptions.create("Marty::NotificationChannel", {
|
132
|
+
received: (data) => {
|
133
|
+
const notificationsButton = this.menuBar.items.items.find(function(
|
134
|
+
item
|
135
|
+
) {
|
136
|
+
return item.name === "notificationsWindow";
|
137
|
+
});
|
138
|
+
|
139
|
+
if (data.unread_notifications_count > 0) {
|
140
|
+
notificationsButton.setText(
|
141
|
+
`<span class='notification-counter'>${data.unread_notifications_count}</span>`
|
129
142
|
);
|
130
|
-
|
131
|
-
|
132
|
-
notificationsButton.setText(
|
133
|
-
`<span class='notification-counter'>${data.unread_notifications_count}</span>`
|
134
|
-
);
|
135
|
-
} else {
|
136
|
-
notificationsButton.setText('');
|
137
|
-
}
|
143
|
+
} else {
|
144
|
+
notificationsButton.setText("");
|
138
145
|
}
|
139
146
|
}
|
140
|
-
);
|
141
|
-
}
|
142
|
-
|
143
|
-
console.log('ActionCable connection failed')
|
147
|
+
});
|
148
|
+
} catch (error) {
|
149
|
+
console.log("ActionCable connection failed");
|
144
150
|
console.error(error);
|
145
151
|
}
|
146
152
|
}
|
147
|
-
}
|
148
|
-
|
153
|
+
});
|
@@ -1,10 +1,12 @@
|
|
1
|
-
{
|
2
|
-
simpleGuardColumnRenderer
|
1
|
+
({
|
2
|
+
simpleGuardColumnRenderer(value, cell, obj) {
|
3
3
|
if (value === undefined || value === null) {
|
4
|
-
return value
|
4
|
+
return value;
|
5
5
|
}
|
6
6
|
|
7
|
-
if (
|
7
|
+
if (
|
8
|
+
!(cell && cell.column && cell.column.config && cell.column.config.name)
|
9
|
+
) {
|
8
10
|
return value;
|
9
11
|
}
|
10
12
|
|
@@ -12,13 +14,13 @@
|
|
12
14
|
return value;
|
13
15
|
}
|
14
16
|
|
15
|
-
column_name = cell.column.config.name;
|
16
|
-
with_not = obj.data[`${column_name}_not`];
|
17
|
+
const column_name = cell.column.config.name;
|
18
|
+
const with_not = obj.data[`${column_name}_not`];
|
17
19
|
|
18
20
|
if (with_not) {
|
19
|
-
return `NOT (${value})
|
21
|
+
return `NOT (${value})`;
|
20
22
|
}
|
21
23
|
|
22
24
|
return value;
|
23
25
|
}
|
24
|
-
}
|
26
|
+
});
|
@@ -1,550 +1,565 @@
|
|
1
|
-
{
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
}
|
1
|
+
({
|
2
|
+
createStoreAndColumns(data, hdim, vdim, hcol, vcol, extra_attrs) {
|
3
|
+
const fields = [];
|
4
|
+
const columns = [];
|
5
|
+
for (let i = 0; i < data[0].length; i++) {
|
6
|
+
fields.push("a" + i);
|
7
|
+
columns.push({
|
8
|
+
dataIndex: "a" + i,
|
9
|
+
text: i,
|
10
|
+
sortable: false,
|
11
|
+
editor: "textfield",
|
12
|
+
renderer(value, meta) {
|
13
|
+
const hlen = hdim.length,
|
14
|
+
vlen = vdim.length,
|
15
|
+
row = meta.rowIndex,
|
16
|
+
col = meta.column.fullColumnIndex;
|
17
|
+
if (extra_attrs[row][col]) {
|
18
|
+
meta.tdStyle = extra_attrs[row][col][0];
|
19
|
+
meta.tdAttr = Ext.String.format(
|
20
|
+
'data-qtip="{0}"',
|
21
|
+
extra_attrs[row][col][1]
|
22
|
+
);
|
23
|
+
}
|
24
|
+
if (row < hlen && col >= vlen) {
|
25
|
+
meta.tdStyle = hcol[row];
|
26
|
+
meta.tdAttr = Ext.String.format('data-qtip="{0}"', hdim[row]);
|
27
|
+
}
|
28
|
+
if (col < vlen && row >= hlen) {
|
29
|
+
meta.tdStyle = vcol[col];
|
30
|
+
meta.tdAttr = Ext.String.format('data-qtip="{0}"', vdim[col]);
|
31
|
+
}
|
33
32
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
33
|
+
return value;
|
34
|
+
},
|
35
|
+
autoSizeColumn: true
|
36
|
+
});
|
37
|
+
}
|
38
|
+
const thestore = Ext.create("Ext.data.ArrayStore", {
|
39
|
+
fields,
|
40
|
+
data
|
41
|
+
});
|
42
|
+
return [columns, thestore];
|
43
|
+
},
|
44
|
+
editGrid(record_id, hdim, vdim, data, title_str, permission) {
|
45
|
+
const colors = [
|
46
|
+
"background-color: #FFA1A1;",
|
47
|
+
"background-color: #FF9D5C;",
|
48
|
+
"background-color: #A1A1FF;",
|
49
|
+
"background-color: #FFFFA1;",
|
50
|
+
"background-color: #A1FFFF;",
|
51
|
+
"background-color: #FFA1FF;",
|
52
|
+
"background-color: #A1A187;",
|
53
|
+
"background-color: #D1FFD1;",
|
54
|
+
"background-color: #FFD1D1;",
|
55
|
+
"background-color: #FF9D7C;",
|
56
|
+
"background-color: #D1D1FF;",
|
57
|
+
"background-color: #FFFFD1;",
|
58
|
+
"background-color: #D1FFFF;",
|
59
|
+
"background-color: #FFD1FF;",
|
60
|
+
"background-color: #D1D1B7;"
|
61
|
+
];
|
62
|
+
const hcol = [];
|
63
|
+
const vcol = [];
|
47
64
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
'background-color: #FFA1FF;',
|
54
|
-
'background-color: #A1A187;',
|
55
|
-
'background-color: #D1FFD1;',
|
56
|
-
'background-color: #FFD1D1;',
|
57
|
-
'background-color: #FF9D7C;',
|
58
|
-
'background-color: #D1D1FF;',
|
59
|
-
'background-color: #FFFFD1;',
|
60
|
-
'background-color: #D1FFFF;',
|
61
|
-
'background-color: #FFD1FF;',
|
62
|
-
'background-color: #D1D1B7;',
|
63
|
-
];
|
64
|
-
var hcol = [];
|
65
|
-
var vcol = [];
|
66
|
-
|
67
|
-
var me = this;
|
68
|
-
// setup colors for hdims
|
69
|
-
for (var i=0; i<hdim.length; i++)
|
70
|
-
hcol[i] = colors.pop();
|
71
|
-
// setup colors for vdims
|
72
|
-
for (var i=0; i<vdim.length; i++)
|
73
|
-
vcol[i] = colors.pop();
|
74
|
-
var columns, thestore;
|
65
|
+
let me = this;
|
66
|
+
// setup colors for hdims
|
67
|
+
for (let i = 0; i < hdim.length; i++) hcol[i] = colors.pop();
|
68
|
+
// setup colors for vdims
|
69
|
+
for (let i = 0; i < vdim.length; i++) vcol[i] = colors.pop();
|
75
70
|
|
76
|
-
|
77
|
-
|
78
|
-
|
71
|
+
const createArray = function(length) {
|
72
|
+
const arr = new Array(length || 0);
|
73
|
+
let i = length;
|
79
74
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
75
|
+
if (arguments.length > 1) {
|
76
|
+
const args = Array.prototype.slice.call(arguments, 1);
|
77
|
+
while (i--) arr[length - 1 - i] = createArray.apply(this, args);
|
78
|
+
}
|
84
79
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
var extra_attrs = createArray(data.length, data[0].length);
|
80
|
+
return arr;
|
81
|
+
};
|
89
82
|
|
90
|
-
|
83
|
+
const extra_attrs = createArray(data.length, data[0].length);
|
91
84
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
85
|
+
const [columns, thestore] = this.createStoreAndColumns(
|
86
|
+
data,
|
87
|
+
hdim,
|
88
|
+
vdim,
|
89
|
+
hcol,
|
90
|
+
vcol,
|
91
|
+
extra_attrs
|
92
|
+
);
|
93
|
+
|
94
|
+
let dirty = false;
|
95
|
+
const setDirty = function() {
|
96
|
+
dirty = true;
|
97
|
+
};
|
98
|
+
const getDirty = function() {
|
99
|
+
return dirty;
|
100
|
+
};
|
101
|
+
|
102
|
+
me = this;
|
103
|
+
|
104
|
+
const dataUpdate = function(grid, modFunc) {
|
105
|
+
const store_data = grid.getStore().data.items;
|
106
|
+
const mod_data = [];
|
107
|
+
modFunc(store_data, mod_data);
|
108
|
+
const extra_attrs = createArray(mod_data.length, mod_data[0].length);
|
109
|
+
const [newcolumns, newstore] = me.createStoreAndColumns(
|
110
|
+
mod_data,
|
111
|
+
hdim,
|
112
|
+
vdim,
|
113
|
+
hcol,
|
114
|
+
vcol,
|
115
|
+
extra_attrs
|
116
|
+
);
|
117
|
+
grid.reconfigure(newstore, newcolumns);
|
118
|
+
Ext.each(grid.getColumns(), function(column) {
|
119
|
+
column.autoSize();
|
120
|
+
});
|
121
|
+
setDirty();
|
122
|
+
};
|
123
|
+
const insertRow = function(inData, outData, rowIdx, up) {
|
124
|
+
const width = inData[0].fields.length - 1;
|
125
|
+
const newa = Array.apply(null, Array(width)).map(function() {
|
126
|
+
return "";
|
127
|
+
});
|
128
|
+
const target = up ? rowIdx : rowIdx + 1;
|
129
|
+
for (let i = 0; i <= inData.length; ++i) {
|
130
|
+
if (i == target) {
|
131
|
+
outData.push(newa);
|
132
|
+
}
|
133
|
+
if (i < inData.length) {
|
134
|
+
const row = [];
|
135
|
+
for (const [key, value] of Object.entries(inData[i].data)) {
|
136
|
+
if (key != "id") row.push(value);
|
137
|
+
}
|
138
|
+
outData.push(row);
|
139
|
+
}
|
140
|
+
}
|
141
|
+
};
|
142
|
+
const insertCol = function(inData, outData, colIdx, left) {
|
143
|
+
const target = left ? colIdx : colIdx + 1;
|
144
|
+
const row_width = inData[0].fields.length;
|
145
|
+
for (let i = 0; i < inData.length; ++i) {
|
146
|
+
const row = [];
|
147
|
+
let idx = 0;
|
148
|
+
for (const [key, value] of Object.entries(inData[i].data)) {
|
149
|
+
if (idx == target) row.push(null);
|
150
|
+
if (key != "id") row.push(value);
|
151
|
+
++idx;
|
152
|
+
}
|
153
|
+
if (target == row_width) row.push(null);
|
154
|
+
outData.push(row);
|
155
|
+
}
|
156
|
+
};
|
157
|
+
const deleteRow = function(inData, outData, rowIdx) {
|
158
|
+
for (let i = 0; i < inData.length; ++i) {
|
159
|
+
if (i != rowIdx) {
|
160
|
+
const row = [];
|
161
|
+
for (const [key, value] of Object.entries(inData[i].data)) {
|
162
|
+
if (key != "id") row.push(value);
|
163
|
+
}
|
164
|
+
outData.push(row);
|
165
|
+
}
|
166
|
+
}
|
167
|
+
};
|
168
|
+
const deleteCol = function(inData, outData, colIdx) {
|
169
|
+
for (let i = 0; i < inData.length; ++i) {
|
170
|
+
const row = [];
|
171
|
+
let idx = 0;
|
172
|
+
for (const [key, value] of Object.entries(inData[i].data)) {
|
173
|
+
if (idx != colIdx && key != "id") row.push(value);
|
174
|
+
++idx;
|
175
|
+
}
|
176
|
+
outData.push(row);
|
177
|
+
}
|
178
|
+
};
|
179
|
+
const lookup_grid = function() {
|
180
|
+
return Ext.ComponentQuery.query("grid").find(function(v) {
|
181
|
+
return v.name == "data_grid_edit_grid";
|
182
|
+
});
|
183
|
+
};
|
184
|
+
const lookup_win = function() {
|
185
|
+
return Ext.ComponentQuery.query("window").find(function(v) {
|
186
|
+
return v.name == "data_grid_edit_window";
|
187
|
+
});
|
188
|
+
};
|
189
|
+
const insertRowAboveAction = Ext.create("Ext.Action", {
|
190
|
+
text: "Insert Row Above",
|
191
|
+
handler(widget, _event) {
|
192
|
+
const grid = lookup_grid();
|
193
|
+
dataUpdate(grid, function(data, mod_data) {
|
194
|
+
insertRow(data, mod_data, widget.position.row, true);
|
192
195
|
});
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
196
|
+
}
|
197
|
+
});
|
198
|
+
const insertRowBelowAction = Ext.create("Ext.Action", {
|
199
|
+
text: "Insert Row Below",
|
200
|
+
handler(widget, _event) {
|
201
|
+
const grid = lookup_grid();
|
202
|
+
dataUpdate(grid, function(data, mod_data) {
|
203
|
+
insertRow(data, mod_data, widget.position.row, false);
|
201
204
|
});
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
205
|
+
}
|
206
|
+
});
|
207
|
+
const insertColLeftAction = Ext.create("Ext.Action", {
|
208
|
+
text: "Insert Column Left",
|
209
|
+
handler(widget, _event) {
|
210
|
+
const grid = lookup_grid();
|
211
|
+
dataUpdate(grid, function(data, mod_data) {
|
212
|
+
insertCol(data, mod_data, widget.position.col, true);
|
210
213
|
});
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
214
|
+
}
|
215
|
+
});
|
216
|
+
const insertColRightAction = Ext.create("Ext.Action", {
|
217
|
+
text: "Insert Column Right",
|
218
|
+
handler(widget, _event) {
|
219
|
+
const grid = lookup_grid();
|
220
|
+
dataUpdate(grid, function(data, mod_data) {
|
221
|
+
insertCol(data, mod_data, widget.position.col, false);
|
219
222
|
});
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
223
|
+
}
|
224
|
+
});
|
225
|
+
const deleteRowAction = Ext.create("Ext.Action", {
|
226
|
+
text: "Delete Row",
|
227
|
+
handler(widget, _event) {
|
228
|
+
const grid = lookup_grid();
|
229
|
+
dataUpdate(grid, function(data, mod_data) {
|
230
|
+
deleteRow(data, mod_data, widget.position.row);
|
228
231
|
});
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
+
}
|
233
|
+
});
|
234
|
+
const deleteColAction = Ext.create("Ext.Action", {
|
235
|
+
text: "Delete Column",
|
236
|
+
handler(widget, _event) {
|
237
|
+
const grid = lookup_grid();
|
238
|
+
dataUpdate(grid, function(data, mod_data) {
|
239
|
+
deleteCol(data, mod_data, widget.position.col);
|
232
240
|
});
|
241
|
+
}
|
242
|
+
});
|
243
|
+
const itemContextMenu = Ext.create("Ext.menu.Menu", {
|
244
|
+
items: [
|
245
|
+
insertRowAboveAction,
|
246
|
+
insertRowBelowAction,
|
247
|
+
insertColLeftAction,
|
248
|
+
insertColRightAction,
|
249
|
+
deleteRowAction,
|
250
|
+
deleteColAction
|
251
|
+
]
|
252
|
+
});
|
233
253
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
254
|
+
// Selection Models
|
255
|
+
const spSel = Ext.create("Ext.grid.selection.SpreadsheetModel", {
|
256
|
+
cellSelect: true,
|
257
|
+
columnSelect: true,
|
258
|
+
rowSelect: false,
|
259
|
+
extensible: true,
|
260
|
+
mode: "MULTI"
|
261
|
+
});
|
242
262
|
|
243
|
-
|
244
|
-
|
245
|
-
|
263
|
+
const get_area = function(row, col) {
|
264
|
+
const row_hdim = row < hdim.length,
|
265
|
+
row_vdim = col < vdim.length;
|
246
266
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
else a = 'vdim_area';
|
255
|
-
return a;
|
256
|
-
};
|
267
|
+
let a;
|
268
|
+
if (row_hdim && row_vdim) a = "blank_area";
|
269
|
+
else if (!row_hdim && !row_vdim) a = "data_area";
|
270
|
+
else if (row_hdim && !row_vdim) a = "hdim_area";
|
271
|
+
else a = "vdim_area";
|
272
|
+
return a;
|
273
|
+
};
|
257
274
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
275
|
+
const can_edit = function(row, col) {
|
276
|
+
const area = get_area(row, col);
|
277
|
+
if (area == "blank_area") return false;
|
278
|
+
if (area == "data_area") return permission != "view";
|
279
|
+
if (area == "vdim_area" || area == "hdim_area")
|
280
|
+
return permission == "edit_all";
|
281
|
+
};
|
282
|
+
|
283
|
+
// Plugins
|
284
|
+
const cellEditor = Ext.create("Ext.grid.plugin.CellEditing", {
|
285
|
+
clicksToEdit: 2,
|
286
|
+
listeners: {
|
287
|
+
beforeedit(editor, context, _eOpts) {
|
288
|
+
if (!can_edit(context.rowIdx, context.colIdx)) return false;
|
289
|
+
},
|
290
|
+
afteredit() {
|
291
|
+
setDirty();
|
266
292
|
}
|
293
|
+
}
|
294
|
+
});
|
267
295
|
|
268
|
-
|
269
|
-
|
296
|
+
const context_disable_fn = function(menu, label, x, y, fn) {
|
297
|
+
const mi = menu.items.items.find(function(mi) {
|
298
|
+
return mi.text == label;
|
299
|
+
});
|
300
|
+
if (fn(x, y)) mi.enable();
|
301
|
+
else mi.disable();
|
302
|
+
};
|
303
|
+
// check to see if menu item should be enabled based on row, col
|
304
|
+
const row_menu_chk = function(row, col) {
|
305
|
+
const area = get_area(row, col);
|
306
|
+
if (vdim.length == 0) return false;
|
307
|
+
return (
|
308
|
+
(area == "vdim_area" || area == "data_area") && permission == "edit_all"
|
309
|
+
);
|
310
|
+
};
|
311
|
+
const col_menu_chk = function(row, col) {
|
312
|
+
const area = get_area(row, col);
|
313
|
+
if (hdim.length == 0) return false;
|
314
|
+
return (
|
315
|
+
(area == "hdim_area" || area == "data_area") && permission == "edit_all"
|
316
|
+
);
|
317
|
+
};
|
318
|
+
const disable_conds = [
|
319
|
+
["Insert Row Above", row_menu_chk],
|
320
|
+
["Insert Row Below", row_menu_chk],
|
321
|
+
["Delete Row", row_menu_chk],
|
322
|
+
["Insert Column Left", col_menu_chk],
|
323
|
+
["Insert Column Right", col_menu_chk],
|
324
|
+
["Delete Column", col_menu_chk]
|
325
|
+
];
|
326
|
+
Ext.define("DGEdit.grid.plugin.Clipboard", {
|
327
|
+
override: "Ext.grid.plugin.Clipboard",
|
328
|
+
beforepaste: Ext.emptyFn,
|
329
|
+
mixins: ["Ext.mixin.Observable"],
|
330
|
+
constructor(config) {
|
331
|
+
const me = this;
|
270
332
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
333
|
+
me.callParent([config]);
|
334
|
+
me.mixins.observable.constructor.call(me);
|
335
|
+
},
|
336
|
+
privates: {
|
337
|
+
onPaste(keyCode, event) {
|
338
|
+
const me = this,
|
339
|
+
sharedData = me.shared.data,
|
340
|
+
source = me.getSource(),
|
341
|
+
rowIdx = event.position.rowIdx,
|
342
|
+
colIdx = event.position.colIdx;
|
343
|
+
let i, n, s;
|
344
|
+
if (!can_edit(rowIdx, colIdx)) {
|
345
|
+
return;
|
346
|
+
}
|
347
|
+
if (me.fireEvent("beforepaste", keyCode, event, me.cmp) !== false) {
|
348
|
+
if (source) {
|
349
|
+
for (i = 0, n = source.length; i < n; ++i) {
|
350
|
+
s = source[i];
|
351
|
+
if (s === "system") {
|
352
|
+
// get the format used by the system clipboard.
|
353
|
+
s = me.getSystem();
|
354
|
+
me.pasteClipboardData(s);
|
355
|
+
break;
|
356
|
+
} else if (sharedData && s in sharedData) {
|
357
|
+
me.doPaste(s, sharedData[s]);
|
358
|
+
break;
|
279
359
|
}
|
360
|
+
}
|
280
361
|
}
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
362
|
+
}
|
363
|
+
}
|
364
|
+
}
|
365
|
+
});
|
366
|
+
Ext.define("DGEditController", {
|
367
|
+
extend: "Ext.app.ViewController",
|
368
|
+
alias: "controller.dataGridEdit",
|
369
|
+
onBeforePaste(_keyCode, _event, _grid) {
|
370
|
+
return false;
|
371
|
+
}
|
372
|
+
});
|
373
|
+
Ext.tip.Tip.prototype.minWidth = void 0;
|
374
|
+
Ext.tip.QuickTipManager.init();
|
375
|
+
const grid = {
|
376
|
+
xtype: "grid",
|
377
|
+
name: "data_grid_edit_grid",
|
378
|
+
border: false,
|
379
|
+
autoEncode: true,
|
380
|
+
controller: "dataGridEdit",
|
381
|
+
columns,
|
382
|
+
scrollable: true,
|
383
|
+
anchor: "100% 100%",
|
384
|
+
forceFit: true,
|
385
|
+
store: thestore,
|
386
|
+
hideHeaders: true,
|
387
|
+
columnLines: true,
|
388
|
+
plugins: [
|
389
|
+
cellEditor,
|
390
|
+
{
|
391
|
+
ptype: "clipboard",
|
392
|
+
system: "raw"
|
393
|
+
// listeners: {
|
394
|
+
// beforepaste: 'onBeforePaste'
|
395
|
+
// }
|
396
|
+
}
|
397
|
+
],
|
398
|
+
selModel: spSel,
|
399
|
+
listeners: {
|
400
|
+
containercontextmenu(view, e) {
|
401
|
+
e.preventDefault();
|
402
|
+
},
|
403
|
+
contextmenu(e, _element, _options) {
|
404
|
+
e.preventDefault();
|
405
|
+
},
|
406
|
+
itemcontextmenu(view, record, item, index, e) {
|
407
|
+
e.stopEvent();
|
408
|
+
const items = itemContextMenu.items.items;
|
409
|
+
const ctn = items.length;
|
410
|
+
const y = e.position.colIdx;
|
411
|
+
const x = e.position.rowIdx;
|
412
|
+
for (let i = 0; i < ctn; ++i) {
|
413
|
+
items[i].position = { col: y, row: x };
|
414
|
+
}
|
415
|
+
for (const [label, fn] of disable_conds) {
|
416
|
+
context_disable_fn(itemContextMenu, label, x, y, fn);
|
417
|
+
}
|
418
|
+
itemContextMenu.showAt(e.getXY());
|
419
|
+
}
|
420
|
+
}
|
421
|
+
};
|
422
|
+
const fbsave = {
|
423
|
+
text: "Save",
|
424
|
+
handler() {
|
425
|
+
this.up("window").submit();
|
426
|
+
}
|
427
|
+
};
|
428
|
+
const fbcancel = {
|
429
|
+
text: "Cancel",
|
430
|
+
handler() {
|
431
|
+
this.up("window").close();
|
432
|
+
}
|
433
|
+
};
|
434
|
+
const fbar = permission == "view" ? [fbcancel] : [fbsave, fbcancel];
|
323
435
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
// get the format used by the system clipboard.
|
344
|
-
s = me.getSystem();
|
345
|
-
me.pasteClipboardData(s);
|
346
|
-
break;
|
347
|
-
} else if (sharedData && (s in sharedData)) {
|
348
|
-
me.doPaste(s, sharedData[s]);
|
349
|
-
break;
|
350
|
-
}
|
351
|
-
}
|
352
|
-
}
|
353
|
-
}
|
354
|
-
}
|
355
|
-
}
|
356
|
-
});
|
357
|
-
Ext.define('DGEditController', {
|
358
|
-
extend : 'Ext.app.ViewController',
|
359
|
-
alias: 'controller.dataGridEdit',
|
360
|
-
onBeforePaste:function(keyCode,event,grid){
|
361
|
-
return false;
|
362
|
-
}
|
436
|
+
Ext.create("Ext.Window", {
|
437
|
+
name: "data_grid_edit_window",
|
438
|
+
height: "90%",
|
439
|
+
width: "90%",
|
440
|
+
x: 100,
|
441
|
+
y: 100,
|
442
|
+
autoWidth: true,
|
443
|
+
modal: true,
|
444
|
+
autoScroll: true,
|
445
|
+
title: title_str,
|
446
|
+
layout: "anchor",
|
447
|
+
items: grid,
|
448
|
+
submit() {
|
449
|
+
Ext.getBody()
|
450
|
+
.mask("Saving data...")
|
451
|
+
.setZIndex(99999)
|
452
|
+
.setStyle("cursor", "wait");
|
453
|
+
const grid = Ext.ComponentQuery.query("grid").find(function(v) {
|
454
|
+
return v.name == "data_grid_edit_grid";
|
363
455
|
});
|
364
|
-
|
365
|
-
Ext.tip.QuickTipManager.init();
|
366
|
-
var grid = {
|
367
|
-
xtype: 'grid',
|
368
|
-
name: 'data_grid_edit_grid',
|
369
|
-
border: false,
|
370
|
-
hideHeaders: false,
|
371
|
-
autoEncode: true,
|
372
|
-
controller: 'dataGridEdit',
|
373
|
-
columns: columns,
|
374
|
-
scrollable: true,
|
375
|
-
anchor: '100% 100%',
|
376
|
-
forceFit: true,
|
377
|
-
store: thestore,
|
378
|
-
hideHeaders: true,
|
379
|
-
columnLines: true,
|
380
|
-
plugins: [cellEditor,
|
381
|
-
{
|
382
|
-
ptype: 'clipboard',
|
383
|
-
system: 'raw',
|
384
|
-
// listeners: {
|
385
|
-
// beforepaste: 'onBeforePaste'
|
386
|
-
// }
|
387
|
-
}],
|
388
|
-
selModel: spSel,
|
389
|
-
listeners: {
|
390
|
-
containercontextmenu: function(view, e) {
|
391
|
-
e.preventDefault();
|
392
|
-
},
|
393
|
-
contextmenu: function(e, element, options) {
|
394
|
-
e.preventDefault();
|
395
|
-
},
|
396
|
-
itemcontextmenu: function(view, record, item, index, e) {
|
397
|
-
e.stopEvent();
|
398
|
-
var items = itemContextMenu.items.items;
|
399
|
-
var ctn = items.length;
|
400
|
-
var y = e.position.colIdx;
|
401
|
-
var x = e.position.rowIdx;
|
402
|
-
for (var i=0; i<ctn; ++i) {
|
403
|
-
items[i].position = {col: y, row: x};
|
404
|
-
}
|
405
|
-
for (const [label, fn] of disable_conds) {
|
406
|
-
context_disable_fn(itemContextMenu, label, x, y, fn);
|
407
|
-
}
|
408
|
-
itemContextMenu.showAt(e.getXY());
|
409
|
-
},
|
410
|
-
|
411
|
-
}
|
412
|
-
};
|
413
|
-
var fbsave = {
|
414
|
-
text: 'Save',
|
415
|
-
handler: function () {
|
416
|
-
this.up('window').submit();
|
417
|
-
}};
|
418
|
-
var fbcancel = {
|
419
|
-
text: 'Cancel',
|
420
|
-
handler: function () {
|
421
|
-
this.up('window').close();
|
422
|
-
}};
|
423
|
-
var fbar = permission == 'view' ?
|
424
|
-
[fbcancel] : [fbsave, fbcancel];
|
425
|
-
|
426
|
-
Ext.create('Ext.Window', {
|
427
|
-
name: 'data_grid_edit_window',
|
428
|
-
height: "90%",
|
429
|
-
width: "90%",
|
430
|
-
x: 100,
|
431
|
-
y: 100,
|
432
|
-
autoWidth: true,
|
433
|
-
modal: true,
|
434
|
-
autoScroll: true,
|
435
|
-
title: title_str,
|
436
|
-
layout: 'anchor',
|
437
|
-
items: grid,
|
438
|
-
submit: function() {
|
439
|
-
Ext.getBody().mask('Saving data...').setZIndex(99999).setStyle('cursor', 'wait');
|
440
|
-
var grid = Ext.ComponentQuery.query('grid').find(function(v) {
|
441
|
-
return v.name=='data_grid_edit_grid'
|
442
|
-
});
|
443
|
-
var server = me.server;
|
456
|
+
const server = me.server;
|
444
457
|
|
445
|
-
|
446
|
-
|
447
|
-
|
458
|
+
if (getDirty() || grid.getStore().getModifiedRecords().length > 0) {
|
459
|
+
const store = grid.getStore().data.items;
|
460
|
+
const ret = [];
|
448
461
|
|
449
|
-
|
450
|
-
|
462
|
+
for (let i = 0; i < store.length; ++i) {
|
463
|
+
const row = {};
|
451
464
|
|
452
|
-
|
465
|
+
let col_idx = 0;
|
453
466
|
|
454
|
-
|
455
|
-
|
467
|
+
// or remove label fields we added in top left
|
468
|
+
const col_null = i < hdim.length ? vdim.length : 0;
|
456
469
|
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
{
|
496
|
-
var win = lookup_win();
|
497
|
-
win.destroy();
|
498
|
-
}
|
499
|
-
Ext.getBody().unmask();
|
500
|
-
});
|
501
|
-
}
|
502
|
-
else
|
503
|
-
{
|
504
|
-
Ext.getBody().unmask();
|
505
|
-
Ext.MessageBox.show({
|
506
|
-
title:'Nothing to Save',
|
507
|
-
msg: 'No changes made',
|
508
|
-
buttons: Ext.Msg.OK
|
509
|
-
});
|
470
|
+
for (const [key, value] of Object.entries(store[i].data)) {
|
471
|
+
if (key != "id") {
|
472
|
+
if (col_idx < col_null) row[key] = "";
|
473
|
+
else row[key] = value;
|
474
|
+
}
|
475
|
+
// const col0_skip = false;
|
476
|
+
col_idx++;
|
477
|
+
}
|
478
|
+
ret.push(row);
|
479
|
+
}
|
480
|
+
server.saveGrid({ record_id, data: ret }, function(res) {
|
481
|
+
if (res) {
|
482
|
+
if (res["errorMessage"]) {
|
483
|
+
Ext.MessageBox.show({
|
484
|
+
title: "Error in data",
|
485
|
+
msg: "error: " + res["errorMessage"],
|
486
|
+
buttons: Ext.Msg.OK
|
487
|
+
});
|
488
|
+
} else if (res["problemArray"]) {
|
489
|
+
Ext.MessageBox.show({
|
490
|
+
title: "Error in data",
|
491
|
+
msg:
|
492
|
+
"error: some entries failed constraint or data type check",
|
493
|
+
buttons: Ext.Msg.OK
|
494
|
+
});
|
495
|
+
for (const [type, x, y] of res["problemArray"]) {
|
496
|
+
const real_x = vdim.length + x,
|
497
|
+
real_y = hdim.length + y;
|
498
|
+
if (type == "constraint")
|
499
|
+
extra_attrs[real_y][real_x] = [
|
500
|
+
"background-color: #FF8181;",
|
501
|
+
"failed constraint check"
|
502
|
+
];
|
503
|
+
else if (type == "type")
|
504
|
+
extra_attrs[real_y][real_x] = [
|
505
|
+
"background-color: #FFB181;",
|
506
|
+
"failed type check"
|
507
|
+
];
|
510
508
|
}
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
509
|
+
grid.getView().refresh();
|
510
|
+
}
|
511
|
+
} else {
|
512
|
+
const win = lookup_win();
|
513
|
+
win.destroy();
|
514
|
+
}
|
515
|
+
Ext.getBody().unmask();
|
516
|
+
});
|
517
|
+
} else {
|
518
|
+
Ext.getBody().unmask();
|
519
|
+
Ext.MessageBox.show({
|
520
|
+
title: "Nothing to Save",
|
521
|
+
msg: "No changes made",
|
522
|
+
buttons: Ext.Msg.OK
|
523
|
+
});
|
524
|
+
}
|
525
|
+
},
|
526
|
+
closeAction: "destroy",
|
527
|
+
listeners: {
|
528
|
+
beforeclose(win) {
|
529
|
+
const grid = lookup_grid();
|
530
|
+
if (win.closeMe) {
|
531
|
+
win.closeMe = false;
|
532
|
+
grid.destroy();
|
533
|
+
return true;
|
534
|
+
}
|
535
|
+
if (getDirty() || grid.getStore().getModifiedRecords().length > 0) {
|
536
|
+
Ext.MessageBox.show({
|
537
|
+
title: "Discard Changes?",
|
538
|
+
msg:
|
539
|
+
"You are closing a window that has unsaved changes. Are you sure?",
|
540
|
+
buttons: Ext.Msg.YESNO,
|
541
|
+
icon: Ext.Msg.QUESTION,
|
542
|
+
callback(btn) {
|
543
|
+
if ("yes" === btn) {
|
544
|
+
win.closeMe = true;
|
545
|
+
win.close();
|
538
546
|
}
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
547
|
+
}
|
548
|
+
});
|
549
|
+
return false;
|
550
|
+
}
|
551
|
+
grid.destroy();
|
552
|
+
return true;
|
553
|
+
}
|
554
|
+
},
|
555
|
+
fbar
|
556
|
+
}).show();
|
557
|
+
const gridobj = Ext.ComponentQuery.query("grid").find(function(v) {
|
558
|
+
return v.name == "data_grid_edit_grid";
|
559
|
+
});
|
560
|
+
Ext.each(gridobj.getColumns(), function(column) {
|
561
|
+
column.autoSize();
|
562
|
+
column.setWidth(column.getWidth() + 20);
|
563
|
+
});
|
564
|
+
}
|
565
|
+
});
|