aleph_analytics 0.2.0 → 0.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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/README.md +1 -0
  4. data/app/assets/javascripts/angular/controllers/controllers.js.es6 +9 -2
  5. data/app/assets/javascripts/angular/directives/query/query_details_directive.js.es6 +54 -6
  6. data/app/assets/javascripts/angular/directives/query/query_version_sidebar_directive.js.es6 +8 -0
  7. data/app/assets/javascripts/angular/services/query/query.js.es6 +16 -5
  8. data/app/assets/javascripts/angular/services/query/query_request_transformers.js.es6 +1 -1
  9. data/app/assets/javascripts/angular/services/query/tags_roles_comparator.js.es6 +32 -0
  10. data/app/assets/javascripts/angular/services/services.js.es6 +1 -0
  11. data/app/assets/stylesheets/alert_bar.css.sass +3 -3
  12. data/app/assets/stylesheets/application.css.sass +1 -0
  13. data/app/assets/stylesheets/comments.css.sass +4 -0
  14. data/app/assets/stylesheets/queries.css.sass +12 -9
  15. data/app/assets/stylesheets/results.css.sass +0 -2
  16. data/app/assets/stylesheets/scheduled.css.sass +39 -0
  17. data/app/assets/stylesheets/shared.css.sass +67 -0
  18. data/app/assets/stylesheets/sidebar.css.sass +12 -0
  19. data/app/assets/stylesheets/variables.css.sass +1 -1
  20. data/app/mailers/alert_mailer.rb +1 -1
  21. data/app/mailers/query_mailer.rb +10 -0
  22. data/app/models/query.rb +21 -1
  23. data/app/models/result.rb +11 -4
  24. data/app/models/scheduled_query_execution.rb +23 -0
  25. data/app/serializers/query_serializer.rb +1 -1
  26. data/app/views/layouts/application.html.haml +3 -1
  27. data/app/views/queries/_comments.html.haml +9 -3
  28. data/app/views/queries/_index_item.html.haml +3 -3
  29. data/app/views/queries/_index_sort_bar.html.haml +3 -3
  30. data/app/views/queries/_query_details.html.haml +31 -21
  31. data/app/views/queries/_query_version_sidebar.html.haml +34 -16
  32. data/app/views/queries/_scheduled.html.haml +31 -0
  33. data/app/views/query_mailer/query_result_email.html.haml +7 -0
  34. data/config/environments/development.rb +3 -0
  35. data/config/example/{alerts.yml → email.yml} +0 -0
  36. data/config/initializers/01_internalize_configurations.rb +6 -6
  37. data/db/migrate/20190131003650_add_set_latest_result_to_queries.rb +5 -0
  38. data/db/migrate/20190205234108_add_query_scheduling_columns.rb +13 -0
  39. data/lib/aws_s3.rb +44 -3
  40. data/lib/clock.rb +1 -0
  41. data/lib/csv_helper/aws.rb +3 -18
  42. data/lib/interaction/query_interaction.rb +3 -0
  43. data/lib/interaction/query_update.rb +3 -0
  44. data/public/assets/.sprockets-manifest-331daedd75cbbd8f5318863713f13576.json +1 -0
  45. data/public/assets/angular/controllers/{controllers.js-45fce398a9c2c371df9ffc32e8dbed84.es6 → controllers.js-f00a5ac91d427dcb9694fc1849f5bbd1.es6} +9 -2
  46. data/public/assets/angular/directives/query/{query_details_directive.js-9ed5b4d1ee4b86889d0de38bc93bac26.es6 → query_details_directive.js-a6604f8ceb6af34a2e97360c6ed459f6.es6} +54 -6
  47. data/public/assets/angular/directives/query/{query_version_sidebar_directive.js-b19ba8a9bf4e66c5740e9b9f9495cee1.es6 → query_version_sidebar_directive.js-282fe948431cbd43335f8d99503fc87a.es6} +8 -0
  48. data/public/assets/angular/services/query/{query.js-7b6228d0a5c1a6ea76242f4aa49aafd0.es6 → query.js-0dd29232f8dbf0527a1324d509a8a74b.es6} +16 -5
  49. data/public/assets/angular/services/query/{query_request_transformers.js-522901477c7848324cd5c014005a85c8.es6 → query_request_transformers.js-110a99334386d4391d47d48df8b57ddf.es6} +1 -1
  50. data/public/assets/angular/services/query/tags_roles_comparator.js-d1e086bdbad13b7e1ed60fa24c660a71.es6 +32 -0
  51. data/public/assets/angular/services/{services.js-855551e8fa01a9a3c05115c4c9fdf7db.es6 → services.js-5230e6db8f737e8378ef2a17c2fc847e.es6} +1 -0
  52. data/public/assets/{application-8bc9d85ca89b3c85e03f7d06948d2e87.js → application-55739fd5c21580dfacbf85238f9e5575.js} +23 -23
  53. data/public/assets/{application-b3586e5b2749cef985bebb24246f95b6.css → application-a3b45a0034f70e5f423c4e0427ca5ccf.css} +1 -1
  54. data/public/assets/resque_web/{application-4218536633ae4c535133fe1455d54cbc.js → application-91fe987abb3becd4e530ec6a4a6a3da7.js} +4 -4
  55. metadata +23 -16
  56. data/lib/tasks/resque.rake +0 -22
  57. data/public/assets/.sprockets-manifest-61519c86aab355aa148c9e7c78293a9e.json +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2b835017996e863027ccbad3617742ffd680cfcd
4
- data.tar.gz: 567308aed9dec7a7ab5c34ef296f1ee6276d4503
3
+ metadata.gz: 9d4c390667cb9196104ad61049e9028d01b906ca
4
+ data.tar.gz: 5a4d2383a969bdb45929b8b696e491f61f42867c
5
5
  SHA512:
6
- metadata.gz: ee415ff8e6d34fd5275000d91564a19052156b7ea456a5af370cfbd546ef5d3a27760feeeb0e122fc1ea9251efb5fe5df7ed155beee3dcfff4c4a5e24e2db32f
7
- data.tar.gz: 723ef552f7f7661ae409e4d1a6d1dc6cee7188666584a78462bdd9d893cbd17ba5c9476895cc93c9e7653fb106119bb4ab3baa8b614607c814f8a2e96cf76a2e
6
+ metadata.gz: e88f4a7c419aa95cff8f1ded63c50c1da317022a82e3a8242458d55f4f66789d86ffe559ae2278b1c66e47f4e1a75ef44203af9e0a40a8bc4a3fca10f7f7faa9
7
+ data.tar.gz: f5e2da4929c25d8831812e452566e7f1ab68aeeed4dc95dde2d2ebcef7a5a682958a68be9ba121b1d2b36e6c41e6e618f9cb50381a3f4298cf1b12c3c5dc497c
data/CHANGELOG.md CHANGED
@@ -1,6 +1,14 @@
1
1
  # Change Log
2
2
  All notable changes to this project will be documented in this file using [Semantic Versioning](http://semver.org/).
3
3
 
4
+ ## [0.3.0] - 2010-02-26
5
+ ### Features
6
+ - [Scheduled Query Execution](https://github.com/lumoslabs/aleph/issues/42)
7
+ - Fixed s3 location for latest result (useful for GoogleSheet integration)
8
+
9
+ ### Fixed
10
+ - Fix roles and tag dirty aware comparators on the Query model
11
+
4
12
  ## [0.2.0] - 2017-09-12
5
13
  ### Features
6
14
  - [Surface Running Queries](https://github.com/lumoslabs/aleph/issues/45)
data/README.md CHANGED
@@ -134,6 +134,7 @@ You can manage your env variables in a .env file
134
134
 
135
135
  ## Links
136
136
 
137
+ - [Feature Notes](docs/FEATURES.md)
137
138
  - [Rubygem](https://rubygems.org/gems/aleph_analytics)
138
139
  - [aleph-user group](https://groups.google.com/forum/#!forum/aleph-user)
139
140
 
@@ -42,13 +42,20 @@
42
42
  function ($scope, $rootScope) {
43
43
  $scope.alerts = [];
44
44
 
45
+ function addAlert(alert) {
46
+ var latest = _.last($scope.alerts);
47
+ if ($scope.alerts.length == 0 || latest.message != alert.message || latest.type != alert.type) {
48
+ $scope.alerts.push(alert);
49
+ }
50
+ }
51
+
45
52
  $scope.dismiss = function dismiss() {
46
53
  $scope.alerts.length = 0;
47
54
  };
48
55
 
49
56
  $rootScope.$on('$routeChangeSuccess', () => {
50
57
  if ($scope.scheduledAlert) {
51
- $scope.alerts.push($scope.scheduledAlert);
58
+ addAlert($scope.scheduledAlert);
52
59
  $scope.scheduledAlert = null;
53
60
  } else {
54
61
  $scope.dismiss();
@@ -60,7 +67,7 @@
60
67
  });
61
68
 
62
69
  $rootScope.$on('setAlert', (event, alert) => {
63
- $scope.alerts.push(alert);
70
+ addAlert(alert);
64
71
  });
65
72
  }
66
73
  ]);
@@ -14,7 +14,7 @@
14
14
  this._Query = Query;
15
15
 
16
16
  RoleModel.initCollection();
17
- this._closeCommentDialog();
17
+ this._closeDialogBoxes();
18
18
  }
19
19
 
20
20
  openRepl() {
@@ -25,11 +25,34 @@
25
25
  .finally(this._closeCommentDialog.bind(this));
26
26
  }
27
27
 
28
- updateQuery() {
29
- this.query.save()
30
- .then(this._setPristine.bind(this))
31
- .then(this._handler.success.bind(this._handler, 'update', false))
32
- .finally(this._closeCommentDialog.bind(this));
28
+ updateTitle() {
29
+ if(this.query.isDirty()) {
30
+ this._updateQuery()
31
+ .then(this._setPristine.bind(this))
32
+ .finally(this._closeDialogBoxes.bind(this));
33
+ }
34
+ }
35
+
36
+ updateTagsAndRoles() {
37
+ if(this.query.isDirty()) {
38
+ this._updateQuery().finally(this._closeDialogBoxes.bind(this));
39
+ }
40
+ }
41
+
42
+ updateCommentDialogAndClose() {
43
+ if(this.query.isDirty()) {
44
+ this._updateQuery().finally(this._closeCommentDialog.bind(this));
45
+ } else {
46
+ this._closeCommentDialog();
47
+ }
48
+ }
49
+
50
+ updateScheduleDialogAndClose() {
51
+ if(this.query.isDirty()) {
52
+ this._updateQuery().finally(this._closeScheduleDialog.bind(this));
53
+ } else {
54
+ this._closeScheduleDialog();
55
+ }
33
56
  }
34
57
 
35
58
  runQuery() {
@@ -59,13 +82,38 @@
59
82
 
60
83
  toggleCommentDialog() {
61
84
  this.commentDialogOpen = !this.commentDialogOpen;
85
+ if(this.commentDialogOpen == true) {
86
+ this._closeScheduleDialog();
87
+ }
88
+ }
89
+
90
+ toggleScheduleDialog() {
91
+ this.scheduleDialogOpen = !this.scheduleDialogOpen;
92
+ if(this.scheduleDialogOpen == true) {
93
+ this._closeCommentDialog();
94
+ }
62
95
  }
63
96
 
64
97
  // private methods
98
+ _updateQuery() {
99
+ return this.query.save()
100
+ .then(this._internalizeQueryItem.bind(this))
101
+ .then(this._handler.success.bind(this._handler, 'update', false));
102
+ }
103
+
104
+ _closeDialogBoxes() {
105
+ this._closeScheduleDialog();
106
+ this._closeCommentDialog();
107
+ }
108
+
65
109
  _closeCommentDialog() {
66
110
  this.commentDialogOpen = false;
67
111
  }
68
112
 
113
+ _closeScheduleDialog() {
114
+ this.scheduleDialogOpen = false;
115
+ }
116
+
69
117
  _setPristine(query) {
70
118
  this.form.$setPristine();
71
119
  return query;
@@ -28,6 +28,14 @@
28
28
  }
29
29
  }
30
30
 
31
+ queryIsPersistedAsScheduled() {
32
+ return (this.query.isPristine() && this.query.item.scheduled_flag) || (this.query.isDirty() && !this.query.item.scheduled_flag);
33
+ }
34
+
35
+ alertResultLinkCopied() {
36
+ this._alertFlash.emitSuccess('S3 URL copied to clipboard!');
37
+ }
38
+
31
39
  loadQueryByVersion(queryVersionId) {
32
40
  this._$location.path('/queries/' + this.query.item.id + '/query_versions/' + queryVersionId);
33
41
  }
@@ -1,7 +1,7 @@
1
1
  !(angular => {
2
2
  'use strict';
3
3
 
4
- function QueryModelImports(QueryResource, ParameterMethods, StandardModel, $q) {
4
+ function QueryModelImports(QueryResource, ParameterMethods, StandardModel, TagsAndRolesComparator, $q) {
5
5
 
6
6
  return class Query extends StandardModel {
7
7
 
@@ -12,17 +12,28 @@
12
12
  {
13
13
  title: '',
14
14
  tags: [],
15
+ roles: [],
15
16
  version: {
16
17
  body: '',
18
+ comment: '',
17
19
  parameters: []
18
- }
20
+ },
21
+ scheduled_flag: false,
22
+ email: ''
19
23
  },
20
24
  [
21
25
  'title',
22
26
  'version.body',
27
+ 'version.comment',
23
28
  'roles',
24
- 'tags'
25
- ]
29
+ 'tags',
30
+ 'scheduled_flag',
31
+ 'email'
32
+ ],
33
+ {
34
+ tags: ((l, r) => TagsAndRolesComparator.compare(l, r)),
35
+ roles: ((l, r) => TagsAndRolesComparator.compare(l, r))
36
+ }
26
37
  );
27
38
  }
28
39
 
@@ -49,7 +60,7 @@
49
60
  };
50
61
  }
51
62
 
52
- QueryModelImports.$inject = ['QueryResource', 'ParameterMethods', 'StandardModel', '$q'];
63
+ QueryModelImports.$inject = ['QueryResource', 'ParameterMethods', 'StandardModel', 'TagsAndRolesComparator', '$q'];
53
64
  angular.module('alephServices.query', []).service('Query', QueryModelImports);
54
65
 
55
66
  }(angular));
@@ -2,7 +2,7 @@
2
2
  'use strict';
3
3
 
4
4
  function QueryRequestTransformers() {
5
- const saveFields = ['id', 'title', 'body', 'tags', 'result_id', 'version', 'roles'];
5
+ const saveFields = ['id', 'title', 'body', 'tags', 'result_id', 'version', 'roles', 'email', 'scheduled_flag'];
6
6
 
7
7
  // see https://github.com/mbenford/ngTagsInput
8
8
  function transformNgTagsInput(fieldName, query) {
@@ -0,0 +1,32 @@
1
+ !(angular => {
2
+ 'use strict';
3
+
4
+ class TagsAndRolesComparator {
5
+ compare(left, right) {
6
+ if(left === undefined && right === undefined) {
7
+ return true;
8
+ } else if(left === undefined) {
9
+ return false;
10
+ } else if(right === undefined) {
11
+ return false;
12
+ }
13
+
14
+ if(left.length != right.length) {
15
+ return false;
16
+ }
17
+
18
+ var unwrappedLeft = _.map(left, value => {
19
+ return _.isObject(value) ? value['text'] : value;
20
+ });
21
+
22
+ var unwrappedRight = _.map(right, value => {
23
+ return _.isObject(value) ? value['text'] : value;
24
+ });
25
+
26
+ return _.difference(unwrappedLeft, unwrappedRight).length == 0;
27
+ }
28
+ }
29
+
30
+ angular.module('alephServices.tagsAndRolesComparator', []).service('TagsAndRolesComparator', TagsAndRolesComparator);
31
+
32
+ }(angular));
@@ -13,6 +13,7 @@
13
13
  'alephServices.queryTab',
14
14
  'alephServices.query',
15
15
  'alephServices.queryLoader',
16
+ 'alephServices.tagsAndRolesComparator',
16
17
 
17
18
  // visualzations
18
19
  'alephServices.visualizationService',
@@ -4,10 +4,10 @@
4
4
 
5
5
  .alert-fade-out
6
6
  -webkit-animation-name: fade-out
7
- -webkit-animation-duration: 10s
7
+ -webkit-animation-duration: 6s
8
8
  animation-name: fade-out
9
- animation-duration: 10s
9
+ animation-duration: 6s
10
10
  animation-timing-function: ease-in
11
11
  margin: 0px
12
12
  padding: 0px
13
- border-radius: 0px 0px 15px 0px
13
+ border-radius: 0px 0px 0px 0px
@@ -25,6 +25,7 @@
25
25
  @import 'visualizations'
26
26
  @import 'sidebar'
27
27
  @import 'comments'
28
+ @import 'scheduled'
28
29
  @import 'shared'
29
30
  @import 'sort_bar'
30
31
  @import 'index_components'
@@ -5,3 +5,7 @@
5
5
  height: 150px
6
6
  font-size: small
7
7
 
8
+ .control-btn
9
+ font-size: x-small
10
+ padding-right: 5px
11
+ padding-bottom: 10px
@@ -24,6 +24,12 @@
24
24
  pre
25
25
  border-radius: 0px
26
26
 
27
+ .query-title-form
28
+ border: none
29
+ width: 100%
30
+ font-size: 2em
31
+ font-weight: bold
32
+
27
33
  .query-title-form.ng-dirty
28
34
  background-color: $gray-lighter
29
35
 
@@ -95,19 +101,16 @@ tags-input .tags .tag-item
95
101
  border: none
96
102
  box-shadow: none
97
103
 
98
- #query_title
99
- width: 100%
100
- font-size: 2em
101
- font-weight: bold
102
104
 
103
- #query-btns
104
- margin: 0 0 0
105
-
106
- #clone-btn
107
- margin-right: 15px
105
+ .white-btns
106
+ margin-left: 10px
107
+ color: $dark-slate-blue
108
108
 
109
109
  .white-background
110
110
  background-color: #FFFFFF
111
111
 
112
112
  .result-panel
113
113
  margin-bottom: 0px
114
+
115
+ .column-spacer
116
+ display: table-cell
@@ -21,5 +21,3 @@ result
21
21
 
22
22
  .high-row-count
23
23
  min-height: 300px
24
-
25
-
@@ -0,0 +1,39 @@
1
+ .scheduled
2
+ $schedule-box-width: 275px
3
+
4
+ .well-sized
5
+ min-width: 400px
6
+
7
+ .toggle-center
8
+ margin: auto
9
+ width: 60px
10
+
11
+ .pad1
12
+ padding: 1px
13
+
14
+ .control-btn
15
+ font-size: x-small
16
+ padding-right: 5px
17
+
18
+ .control-bar
19
+ width: $schedule-box-width
20
+ padding-top: 0px
21
+
22
+ .toggle-bar
23
+ width: $schedule-box-width
24
+ padding-top: 5px
25
+
26
+ .email-bar
27
+ width: $schedule-box-width
28
+ padding-top: 15px
29
+ padding-bottom: 20px
30
+
31
+ .email-label
32
+ padding: 2px
33
+
34
+ .email-label[disabled]
35
+ color: grey
36
+
37
+ .email-input-col
38
+ padding-left: 7px
39
+ padding-right: 6px
@@ -48,6 +48,9 @@ body
48
48
  .small-font
49
49
  font-size: small
50
50
 
51
+ .x-small-font
52
+ font-size: x-small
53
+
51
54
  .info-box
52
55
  background-color: $gray-lighter
53
56
  border: 1px solid $gray-light
@@ -159,6 +162,12 @@ a.navbar-text.active
159
162
  &:active
160
163
  opacity: $opacity-high
161
164
 
165
+ .subdued-clickable
166
+ color: $dark-slate-blue
167
+ cursor: pointer
168
+ &:hover
169
+ color: black
170
+
162
171
  // pulsating stuff
163
172
 
164
173
  // Chrome, Safari, Opera
@@ -200,3 +209,61 @@ a.navbar-text.active
200
209
  animation-duration: 3s
201
210
  animation-direction: alternate
202
211
  animation-iteration-count: 3
212
+
213
+
214
+ /* css for slider toggle switch */
215
+ .switch
216
+ position: relative
217
+ display: inline-block
218
+ width: 28px
219
+ height: 18px
220
+
221
+ $slider-checked: lighten($slate-blue, 5%) !default
222
+ $slider-bg: lighten(#ccc, 5%) !default
223
+
224
+ /* Hide default HTML checkbox */
225
+ .switch input
226
+ opacity: 0
227
+ width: 0
228
+ height: 0
229
+
230
+ /* The slider */
231
+ .slider
232
+ position: absolute
233
+ cursor: pointer
234
+ top: 0
235
+ left: 0
236
+ right: 0
237
+ bottom: 0
238
+ background-color: $slider-bg
239
+ -webkit-transition: .4s
240
+ transition: .4s
241
+
242
+ .slider:before
243
+ position: absolute
244
+ content: ""
245
+ height: 14px
246
+ width: 14px
247
+ left: 2px
248
+ bottom: 2px
249
+ background-color: white
250
+ -webkit-transition: .4s
251
+ transition: .4s
252
+
253
+ input:checked + .slider
254
+ background-color: $slider-checked
255
+
256
+ input:focus + .slider
257
+ box-shadow: 0 0 0px $slider-checked
258
+
259
+ input:checked + .slider:before
260
+ -webkit-transform: translateX(10px)
261
+ -ms-transform: translateX(10px)
262
+ transform: translateX(10px)
263
+
264
+ /* Rounded sliders */
265
+ .slider.round
266
+ border-radius: 5px
267
+
268
+ .slider.round:before
269
+ border-radius: 25%