marty 8.5.0 → 9.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ });