marty 8.5.0 → 9.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintignore +1 -0
  3. data/.eslintrc.js +26 -0
  4. data/.gitignore +3 -0
  5. data/.gitlab-ci.yml +7 -0
  6. data/.prettierignore +14 -0
  7. data/.rubocop_todo.yml +1 -1
  8. data/Dockerfile.dummy +3 -0
  9. data/Makefile +1 -0
  10. data/app/assets/javascripts/marty/cable.js +7 -3
  11. data/app/assets/javascripts/marty/extjs/extensions/datetime_field/component.js +401 -0
  12. data/app/assets/javascripts/marty/extjs/extensions/datetime_field/field.js +140 -0
  13. data/app/assets/javascripts/marty/extjs/extensions/marty.js +845 -781
  14. data/app/assets/stylesheets/marty/codemirror/codemirror.css +215 -77
  15. data/app/assets/stylesheets/marty/codemirror/delorean.css +2 -2
  16. data/app/assets/stylesheets/marty/dark_mode.css +13 -3
  17. data/app/components/marty/auth_app/client/auth_app.js +107 -102
  18. data/app/components/marty/base_rule_view/client/base_rule_view.js +10 -8
  19. data/app/components/marty/data_grid_view/client/data_grid_edit.js +534 -519
  20. data/app/components/marty/form/client/form.js +3 -3
  21. data/app/components/marty/grid/client/grid.js +110 -87
  22. data/app/components/marty/import_view/client/import_view.js +18 -18
  23. data/app/components/marty/live_search_grid_panel/client/live_search_grid_panel.js +14 -13
  24. data/app/components/marty/main_auth_app/client/main_auth_app.js +42 -42
  25. data/app/components/marty/mcfly_grid_panel/client/mcfly_grid_panel.js +27 -18
  26. data/app/components/marty/new_posting_form/client/new_posting_form.js +3 -3
  27. data/app/components/marty/panel/client/panel.js +3 -3
  28. data/app/components/marty/posting_grid/client/posting_grid.js +24 -18
  29. data/app/components/marty/promise_view/client/promise_view.css +12 -12
  30. data/app/components/marty/promise_view/client/promise_view.js +46 -38
  31. data/app/components/marty/report_form/client/report_form.js +30 -28
  32. data/app/components/marty/report_select/client/report_select.js +28 -23
  33. data/app/components/marty/reporting/client/reporting.js +3 -3
  34. data/app/components/marty/script_form/client/script_form.js +29 -23
  35. data/app/components/marty/script_tester/client/script_tester.js +4 -5
  36. data/app/components/marty/scripting/client/scripting.js +40 -36
  37. data/app/components/marty/simple_app/client/simple_app.js +33 -24
  38. data/app/components/marty/simple_app/client/statusbar_ext.js +1 -1
  39. data/app/controllers/marty/rpc_controller.rb +3 -0
  40. data/app/models/marty/promise.rb +10 -2
  41. data/app/services/marty/data_grid/constraint.rb +2 -1
  42. data/app/services/marty/jobs/schedule.rb +2 -2
  43. data/app/services/marty/promises/delorean/create.rb +9 -2
  44. data/app/services/marty/promises/ruby/create.rb +7 -2
  45. data/config/initializers/delayed_job_config.rb +1 -0
  46. data/delorean/blame_report.dl +50 -58
  47. data/delorean/enum_report.dl +2 -3
  48. data/delorean/{marty_fields.dl → fields.dl} +16 -0
  49. data/delorean/styles.dl +216 -0
  50. data/delorean/table_report.dl +4 -4
  51. data/lib/marty/monkey.rb +17 -0
  52. data/lib/marty/promise_job.rb +9 -0
  53. data/lib/marty/promise_ruby_job.rb +8 -0
  54. data/lib/marty/version.rb +1 -1
  55. data/make-lint.mk +19 -0
  56. data/package.json +16 -0
  57. data/prettier.config.js +6 -0
  58. data/spec/controllers/diagnostic/controller_spec.rb +0 -1
  59. data/spec/controllers/rpc_controller_spec.rb +21 -7
  60. data/spec/dummy/delorean/data_report.dl +4 -4
  61. data/spec/dummy/delorean/fields.dl +1 -0
  62. data/spec/features/data_grid_spec.rb +37 -1
  63. data/spec/job_helper.rb +6 -0
  64. data/spec/lib/data_blame_spec.rb +4 -4
  65. data/spec/lib/data_importer_spec.rb +6 -4
  66. data/spec/models/promise_spec.rb +31 -0
  67. data/spec/spec_helper.rb +8 -0
  68. data/spec/support/download_helper.rb +53 -49
  69. data/spec/support/json_helper.rb +11 -0
  70. data/spec/support/shared_connection_db_helpers.rb +1 -0
  71. data/spec/support/suite.rb +20 -14
  72. data/yarn.lock +967 -0
  73. metadata +16 -4
  74. data/spec/dummy/delorean/marty_fields.dl +0 -1
@@ -1,82 +1,86 @@
1
- {
2
- netzkeOnSignIn: function () {
3
- var me = this;
4
- this.signinWin = this.signinWin || Ext.create('Ext.Window', {
5
- modal: true,
6
- layout: 'fit',
7
-
8
- submit: function () {
9
- var form = this.items.first();
10
- var values = form.getForm().getValues();
11
-
12
- // calling the endpoint
13
- me.server.signIn(values, function (res) {
14
- if (res) {
15
- if (!me.authSpecMode) {
16
- this.signinWin.close();
17
- }
18
- Ext.Msg.show({
19
- title: "Signed in",
20
- msg: "Signed in successfully, reloading...",
21
- icon: Ext.Msg.INFO,
22
- closable: false
23
- });
24
- if (!me.authSpecMode) {
25
- window.location.href = "/";
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
- items: {
49
- xtype: 'form',
50
- defaultType: 'textfield',
51
- bodyPadding: '15px 15px 0px 10px',
52
- defaults: {
53
- listeners: {
54
- specialkey: function (field, event) {
55
- if (event.getKey() == event.ENTER) {
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
- fieldLabel: 'Password',
67
- name: 'password',
68
- inputType: 'password',
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('textfield').focus(false, 100);
79
+ this.signinWin.down("textfield").focus(false, 100);
76
80
  },
77
81
 
78
- netzkeOnSignOut: function () {
79
- this.server.signOut(null, function (success) {
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: function() {
93
- this.server.toggleDarkMode(() => { window.location.href = "/" });
96
+ netzkeOnToggleDarkMode() {
97
+ this.server.toggleDarkMode(() => {
98
+ window.location.href = "/";
99
+ });
94
100
  },
95
101
 
96
- netzkeOnNotificationsWindow: function () {
102
+ netzkeOnNotificationsWindow() {
97
103
  this.netzkeLoadComponent("notifications_window", {
98
- callback: function (w) {
104
+ callback(w) {
99
105
  w.show();
100
106
 
101
107
  this.server.markWebNotificationsDelivered();
102
108
 
103
- var notificationsButton = this.menuBar.items.items.find(
104
- function(item) { return item.name === "notificationsWindow" }
105
- );
109
+ const notificationsButton = this.menuBar.items.items.find(function(
110
+ item
111
+ ) {
112
+ return item.name === "notificationsWindow";
113
+ });
106
114
 
107
- notificationsButton.setText(''); // Remove the counter
108
- },
115
+ notificationsButton.setText(""); // Remove the counter
116
+ }
109
117
  });
110
118
  },
111
119
 
112
- netzkeInitComponentCallback: function() {
120
+ netzkeInitComponentCallback() {
113
121
  try {
114
- var subscription = RailsApp.cable.subscriptions.subscriptions.find(
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
- 'Marty::NotificationChannel',
125
- {
126
- received: (data) => {
127
- var notificationsButton = this.menuBar.items.items.find(
128
- function(item) { return item.name === "notificationsWindow" }
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
- if (data.unread_notifications_count > 0) {
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
- catch(error) {
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: function(value, cell, obj) {
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 (!(cell && cell.column && cell.column.config && cell.column.config.name)) {
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
- createStoreAndColumns:
3
- function(data, hdim, vdim, hcol, vcol, extra_attrs) {
4
- var fields = [];
5
- var columns = [];
6
- for (var i=0; i< data[0].length; i++) {
7
- fields.push("a" + i);
8
- columns.push({dataIndex: "a" + i, text: i,
9
- sortable: false,
10
- editor: 'textfield',
11
- renderer: function(value, meta) {
12
- var hlen = hdim.length,
13
- vlen = vdim.length,
14
- row = meta.rowIndex,
15
- col = meta.column.fullColumnIndex;
16
- if (extra_attrs[row][col]) {
17
- meta.tdStyle = extra_attrs[row][col][0]
18
- meta.tdAttr = Ext.String.format('data-qtip="{0}"',
19
- extra_attrs[row][col][1]);
20
- }
21
- if (row < hlen && col >= vlen)
22
- {
23
- meta.tdStyle = hcol[row];
24
- meta.tdAttr = Ext.String.format('data-qtip="{0}"',
25
- hdim[row]);
26
- }
27
- if (col < vlen && row >= hlen)
28
- {
29
- meta.tdStyle = vcol[col];
30
- meta.tdAttr = Ext.String.format('data-qtip="{0}"',
31
- vdim[col]);
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
- return value;
35
- },
36
- autoSizeColumn: true});
37
- }
38
- var thestore = Ext.create('Ext.data.ArrayStore', {
39
- fields: fields,
40
- data: data,
41
- });
42
- return [columns, thestore];
43
- },
44
- editGrid:
45
- function(record_id, hdim, vdim, data, title_str, permission) {
46
- var colors = [
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
- 'background-color: #FFA1A1;',
49
- 'background-color: #FF9D5C;',
50
- 'background-color: #A1A1FF;',
51
- 'background-color: #FFFFA1;',
52
- 'background-color: #A1FFFF;',
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
- var createArray = function (length) {
77
- var arr = new Array(length || 0),
78
- i = length;
71
+ const createArray = function(length) {
72
+ const arr = new Array(length || 0);
73
+ let i = length;
79
74
 
80
- if (arguments.length > 1) {
81
- var args = Array.prototype.slice.call(arguments, 1);
82
- while(i--) arr[length-1 - i] = createArray.apply(this, args);
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
- return arr;
86
- };
87
-
88
- var extra_attrs = createArray(data.length, data[0].length);
80
+ return arr;
81
+ };
89
82
 
90
- [columns, thestore] = this.createStoreAndColumns(data, hdim, vdim, hcol, vcol, extra_attrs);
83
+ const extra_attrs = createArray(data.length, data[0].length);
91
84
 
92
- var dirty = false;
93
- var setDirty = function() { dirty = true; };
94
- var getDirty = function() { return dirty; };
95
- var me = this;
96
- var dataUpdate = function(grid, modFunc) {
97
- var store_data = grid.getStore().data.items;
98
- var newcolumns, newstore;
99
- var mod_data = [];
100
- modFunc(store_data, mod_data);
101
- var extra_attrs = createArray(mod_data.length, mod_data[0].length);
102
- [newcolumns, newstore] = me.createStoreAndColumns(mod_data, hdim, vdim, hcol, vcol, extra_attrs);
103
- grid.reconfigure(newstore, newcolumns);
104
- Ext.each(grid.getColumns(), function(column) {
105
- column.autoSize();
106
- });
107
- setDirty();
108
- };
109
- var insertRow = function(inData, outData, rowIdx, up) {
110
- var width = inData[0].fields.length -1
111
- var newa = Array.apply(null, Array(width)).map(function () { return ""; });
112
- var target = up ? rowIdx : rowIdx + 1;
113
- for (var i=0; i<= inData.length; ++i) {
114
- if (i == target) {
115
- outData.push(newa);
116
- }
117
- if (i < inData.length) {
118
- var row = [];
119
- for (const [key, value] of Object.entries(inData[i].data)) {
120
- if (key != 'id') row.push(value);
121
- }
122
- outData.push(row);
123
- }
124
- }
125
- };
126
- var insertCol = function(inData, outData, colIdx, left) {
127
- var target = left ? colIdx : colIdx + 1
128
- var row_width = inData[0].fields.length;
129
- for (var i=0; i< inData.length; ++i) {
130
- var row = [];
131
- var idx = 0;
132
- for (const [key, value] of Object.entries(inData[i].data)) {
133
- if (idx == target) row.push(null);
134
- if (key != 'id') row.push(value);
135
- ++idx;
136
- }
137
- if (target == row_width) row.push(null);
138
- outData.push(row);
139
- }
140
- };
141
- var deleteRow = function(inData, outData, rowIdx) {
142
- for (var i=0; i< inData.length; ++i) {
143
- if (i != rowIdx) {
144
- var row = [];
145
- for (const [key, value] of Object.entries(inData[i].data)) {
146
- if (key != 'id')
147
- row.push(value);
148
- }
149
- outData.push(row);
150
- }
151
- }
152
- };
153
- var deleteCol = function(inData, outData, colIdx) {
154
- for (var i=0; i< inData.length; ++i) {
155
- var row = [];
156
- var idx = 0;
157
- for (const [key, value] of Object.entries(inData[i].data)) {
158
- if (idx != colIdx && key != 'id')
159
- row.push(value);
160
- ++idx;
161
- }
162
- outData.push(row);
163
- }
164
- };
165
- var lookup_grid = function () {
166
- return Ext.ComponentQuery.query('grid').find(function(v) {
167
- return v.name=='data_grid_edit_grid'
168
- });
169
- };
170
- var lookup_win = function () {
171
- return Ext.ComponentQuery.query('window').find(function(v) {
172
- return v.name=='data_grid_edit_window'
173
- });
174
- };
175
- var insertRowAboveAction = Ext.create('Ext.Action', {
176
- text: 'Insert Row Above',
177
- handler: function(widget , event) {
178
- var grid = lookup_grid();
179
- dataUpdate(grid, function(data, mod_data) {
180
- insertRow(data, mod_data, widget.position.row, true);
181
- });
182
- }
183
- });
184
- var insertRowBelowAction = Ext.create('Ext.Action', {
185
- text: 'Insert Row Below',
186
- handler: function(widget , event) {
187
- var grid = lookup_grid();
188
- dataUpdate(grid, function(data, mod_data) {
189
- insertRow(data, mod_data, widget.position.row, false);
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
- var insertColLeftAction = Ext.create('Ext.Action', {
194
- text: 'Insert Column Left',
195
- handler: function(widget , event) {
196
- var grid = lookup_grid();
197
- dataUpdate(grid, function(data, mod_data) {
198
- insertCol(data, mod_data, widget.position.col, true);
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
- var insertColRightAction = Ext.create('Ext.Action', {
203
- text: 'Insert Column Right',
204
- handler: function(widget , event) {
205
- var grid = lookup_grid();
206
- dataUpdate(grid, function(data, mod_data) {
207
- insertCol(data, mod_data, widget.position.col, false);
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
- var deleteRowAction = Ext.create('Ext.Action', {
212
- text: 'Delete Row',
213
- handler: function(widget , event) {
214
- var grid = lookup_grid();
215
- dataUpdate(grid, function(data, mod_data) {
216
- deleteRow(data, mod_data, widget.position.row);
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
- var deleteColAction = Ext.create('Ext.Action', {
221
- text: 'Delete Column',
222
- handler: function(widget , event) {
223
- var grid = lookup_grid();
224
- dataUpdate(grid, function(data, mod_data) {
225
- deleteCol(data, mod_data, widget.position.col);
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
- var itemContextMenu = Ext.create('Ext.menu.Menu' , {
230
- items: [insertRowAboveAction, insertRowBelowAction, insertColLeftAction,
231
- insertColRightAction, deleteRowAction, deleteColAction]
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
- // Selection Models
235
- var spSel = Ext.create("Ext.grid.selection.SpreadsheetModel", {
236
- cellSelect: true,
237
- columnSelect: true,
238
- rowSelect: false,
239
- extensible: true,
240
- mode: "MULTI"
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
- var get_area = function(row, col) {
244
- var row_hdim = row < hdim.length,
245
- row_vdim = col < vdim.length;
263
+ const get_area = function(row, col) {
264
+ const row_hdim = row < hdim.length,
265
+ row_vdim = col < vdim.length;
246
266
 
247
- var a;
248
- if (row_hdim && row_vdim)
249
- a = 'blank_area';
250
- else if (!row_hdim && !row_vdim)
251
- a = 'data_area';
252
- else if (row_hdim && !row_vdim)
253
- a = 'hdim_area';
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
- var can_edit = function(row, col) {
259
- var area = get_area(row, col);
260
- if (area == 'blank_area')
261
- return false;
262
- if (area == 'data_area')
263
- return permission != 'view';
264
- if (area == 'vdim_area' || area == 'hdim_area')
265
- return permission == 'edit_all';
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
- // Plugins
269
- var cellEditor = Ext.create("Ext.grid.plugin.CellEditing", {
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
- clicksToEdit: 2,
272
- listeners: {
273
- beforeedit: function(editor, context, eOpts) {
274
- if (!can_edit(context.rowIdx, context.colIdx))
275
- return false;
276
- },
277
- afteredit: function() {
278
- setDirty();
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
- var context_disable_fn = function(menu, label, x, y, fn) {
284
- var mi = menu.items.items.find(function (mi) {
285
- return mi.text == label;
286
- });
287
- if (fn(x, y))
288
- mi.enable();
289
- else
290
- mi.disable();
291
- };
292
- // check to see if menu item should be enabled based on row, col
293
- var row_menu_chk = function (row, col) {
294
- var area = get_area(row, col);
295
- if (vdim.length == 0)
296
- return false;
297
- return (area == 'vdim_area' || area == 'data_area') &&
298
- permission == 'edit_all';
299
- };
300
- var col_menu_chk = function (row, col) {
301
- var area = get_area(row, col);
302
- if (hdim.length == 0)
303
- return false;
304
- return (area == 'hdim_area' || area == 'data_area') &&
305
- permission == 'edit_all';
306
- };
307
- var disable_conds = [
308
- ['Insert Row Above', row_menu_chk],
309
- ['Insert Row Below', row_menu_chk],
310
- ['Delete Row', row_menu_chk],
311
- ['Insert Column Left', col_menu_chk],
312
- ['Insert Column Right', col_menu_chk],
313
- ['Delete Column', col_menu_chk]
314
- ];
315
- Ext.define('DGEdit.grid.plugin.Clipboard',{
316
- override: 'Ext.grid.plugin.Clipboard',
317
- beforepaste: Ext.emptyFn,
318
- mixins: [
319
- 'Ext.mixin.Observable'
320
- ],
321
- constructor: function(config) {
322
- var me = this;
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
- me.callParent([config]);
325
- me.mixins.observable.constructor.call(me);
326
- },
327
- privates : {
328
- onPaste: function (keyCode, event) {
329
- var me = this,
330
- sharedData = me.shared.data,
331
- source = me.getSource(),
332
- i, n, s,
333
- rowIdx = event.position.rowIdx,
334
- colIdx = event.position.colIdx;
335
- if (!can_edit(rowIdx, colIdx)) {
336
- return;
337
- }
338
- if (me.fireEvent('beforepaste',keyCode,event,me.cmp) !== false) {
339
- if (source) {
340
- for (i = 0, n = source.length; i < n; ++i) {
341
- s = source[i];
342
- if (s === 'system') {
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
- Ext.tip.Tip.prototype.minWidth = void 0;
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
- if (getDirty() || grid.getStore().getModifiedRecords().length > 0) {
446
- var store = grid.getStore().data.items;
447
- var ret = [];
458
+ if (getDirty() || grid.getStore().getModifiedRecords().length > 0) {
459
+ const store = grid.getStore().data.items;
460
+ const ret = [];
448
461
 
449
- for (var i = 0; i < store.length; ++i) {
450
- var row = {};
462
+ for (let i = 0; i < store.length; ++i) {
463
+ const row = {};
451
464
 
452
- var col_idx = 0;
465
+ let col_idx = 0;
453
466
 
454
- // or remove label fields we added in top left
455
- var col_null = i < hdim.length ? vdim.length : 0;
467
+ // or remove label fields we added in top left
468
+ const col_null = i < hdim.length ? vdim.length : 0;
456
469
 
457
- for (const [key, value] of Object.entries(store[i].data)) {
458
- if (key != 'id') {
459
- if (col_idx < col_null)
460
- row[key] = "";
461
- else
462
- row[key] = value;
463
- }
464
- col0_skip = false;
465
- col_idx++;
466
- }
467
- ret.push(row);
468
- }
469
- server.saveGrid({record_id: record_id, data: ret}, function(res) {
470
- if (res) {
471
- if (res['errorMessage']) {
472
- Ext.MessageBox.show({
473
- title:'Error in data',
474
- msg: 'error: ' + res['errorMessage'],
475
- buttons: Ext.Msg.OK
476
- });
477
- } else if (res['problemArray']) {
478
- Ext.MessageBox.show({
479
- title:'Error in data',
480
- msg: 'error: some entries failed constraint or data type check',
481
- buttons: Ext.Msg.OK
482
- });
483
- for (const [type, x, y] of res['problemArray']) {
484
- var real_x = vdim.length + x,
485
- real_y = hdim.length + y;
486
- if (type == 'constraint')
487
- extra_attrs[real_y][real_x] = ['background-color: #FF8181;','failed constraint check'];
488
- else if (type == 'type')
489
- extra_attrs[real_y][real_x] = ['background-color: #FFB181;','failed type check'];
490
- }
491
- grid.getView().refresh();
492
- }
493
- }
494
- else
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
- closeAction: 'destroy',
513
- listeners: {
514
- beforeclose: function (win) {
515
- var grid = lookup_grid();
516
- if(win.closeMe) {
517
- win.closeMe = false;
518
- grid.destroy();
519
- return true;
520
- }
521
- if (getDirty() || grid.getStore().getModifiedRecords().length > 0) {
522
- Ext.MessageBox.show({
523
- title:'Discard Changes?',
524
- msg: 'You are closing a window that has unsaved changes. Are you sure?',
525
- buttons: Ext.Msg.YESNO,
526
- icon: Ext.Msg.QUESTION,
527
- callback: function(btn) {
528
- if('yes' === btn) {
529
- win.closeMe = true;
530
- win.close();
531
- }
532
- }
533
- });
534
- return false;
535
- }
536
- grid.destroy();
537
- return true;
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
- fbar: fbar
541
- }).show();
542
- var gridobj = Ext.ComponentQuery.query('grid').find(function(v) {
543
- return v.name=='data_grid_edit_grid'
544
- });
545
- Ext.each(gridobj.getColumns(), function(column) {
546
- column.autoSize();
547
- column.setWidth(column.getWidth()+20);
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
+ });