Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closes #338, #228: Improvements to x-axis formatting #365

Closed
wants to merge 66 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
6100335
In docker-entrypoint ensure tables exist
Apr 12, 2017
018211b
upgrade node and npm in dockerfile
alison985 Aug 11, 2017
6d530c6
Update circle.yml for our workflow
robotblake Apr 19, 2017
4f395c3
add pyup config document
alison985 Jul 8, 2017
29b1b99
Pin PyAthena dependency to 1.2.0.
jezdez Oct 25, 2017
357a8d4
Switch to PyMySQL for MySQL 5.7 support
Sep 14, 2017
de4a5a1
upgrade to Celery 4.1.0
Jan 8, 2018
75228b2
Documentation links for data sources (re #6)
Nov 8, 2016
e6720e0
Don't execute query when changing data sources (fixes #29)
Feb 10, 2017
b4a8d5c
Retry fetching query result on failure (fixes #36)
Feb 16, 2017
a7b4f46
Use saved values for parameters in scheduled queries (re #43)
Feb 24, 2017
c5c9f14
delay schema filtering to improve responsiveness (fixes #45)
Mar 8, 2017
a8ff8f4
Add `schedule_until` field to queries, to allow expiry (re #15)
Mar 2, 2017
2a7c354
add compare query version support (re #7)
spasovski Feb 6, 2017
be89d48
accommodate '/' in dashboard tags (re #48)
Mar 24, 2017
13c37cd
reject non-list dashboard layouts (re #25)
Apr 26, 2017
d5304fe
Reject empty names for dashboards (re #76)
May 5, 2017
19343fb
allow unpublished queries to be used as alerts (re #97)
alison985 Jul 4, 2017
8c62d24
dashboard textbox edit close fix (re #111)
alison985 Jun 25, 2017
04b433f
works for filtering _v literally (re #31)
alison985 Jul 4, 2017
4a5f5f8
Expose data source version info in UI (re #89)
alison985 Jun 24, 2017
4f95077
give warning/error msg on inaccurate graph config (re #57)
alison985 Jun 22, 2017
0d329d2
adding activedata query_runner (re #83)
alison985 Jul 4, 2017
5a22ec5
Re-prompt for login if an unauthorized Google account is used (fixes …
Jul 21, 2017
55a3e90
add toggle_table_string (re #130)
alison985 Jul 24, 2017
ce9565f
add column type info to query runners (re #152, #23)
alison985 Jul 28, 2017
82373ce
make the enter button submit the form (re #172)
alison985 Jul 28, 2017
de46def
add hideParameters param (re #163)
alison985 Jul 28, 2017
d5a27be
add ability to add query to dashboard from query page (re #154)
alison985 Aug 8, 2017
5a66ed0
Add last_active_at column to users page (re #155)
alison985 Aug 12, 2017
0746ebf
add partition key marker to Athena and Presto columns (re #185)
Dec 9, 2017
5eaa966
make autocomplete for large schemas faster (re #232)
Dec 9, 2017
134f91a
hide query more menu if empty (re #208)
spasovski Aug 17, 2017
508a9b7
only show query versions when more than one exists (re #194)
spasovski Aug 16, 2017
ea7bcd0
sort query version select options (re #198)
spasovski Aug 16, 2017
3c4b910
change pie chart colors (re #240)
alison985 Aug 18, 2017
df97310
adds redash db size metrics to status page (re #247)
alison985 Sep 6, 2017
04b0571
Move events server side (re #245)
alison985 Sep 1, 2017
ba062d2
Run queries with no cached result in public dashboards (re #220)
Sep 6, 2017
3087822
allow x-axis label truncation (re #249)
alison985 Sep 11, 2017
8e1a325
secure cookies, add X-Content-Type-Options header (bug 1371613)
Sep 27, 2017
f41651a
Merge mozilla schema updates with schema from master
Dec 12, 2017
ea3525e
Add navigation for tags in dashboard list (re #259)
Dec 15, 2017
0604760
Toggle for query editor autocomplete (re #282)
Dec 19, 2017
cff65fe
merge upstream db changes
Feb 14, 2018
80d9ab6
Propagate query execution errors from Celery tasks properly (re #290)
Feb 27, 2018
0d579e9
Migration that needs to be rolled back before landing #339
Mar 6, 2018
e2b692f
fixup pie chart colors (fixes #345)
Mar 7, 2018
a56eeee
Support authentication for URL data source (re #330) (#336)
Mar 20, 2018
f45fac6
properly rollback failed db commits
Mar 21, 2018
cb90254
Install redash-stmo.
jezdez Feb 28, 2018
5f501f5
Extend the Remote User Auth backend with REMOTE_GROUPS ability (#311)
jezdez Mar 23, 2018
f2c80df
Unique names for query parameters (re #164)
Jan 16, 2018
4c17b26
Aggregate query results (re #35) (#339)
Mar 27, 2018
1f1117d
Filter versioned table names only (re #130) (re #356)
Apr 4, 2018
bd5e7f7
move autocomplete checkbox next to format button (re #282) (re #355)
Apr 5, 2018
595c1cf
Don't delete latest query results (re #363) (re #35)
Apr 9, 2018
7118fe3
Updates to docker-entrypoint for worker and scheduler (#364)
jasonthomas Apr 11, 2018
30be3e7
Update redash-stmo. (#360)
jezdez Apr 11, 2018
eb1b3cb
Closes #359: Truncate x-axis by default.
Apr 11, 2018
c151935
Closes #374: Truncating x-axis should be done to ticktext not x values.
Apr 19, 2018
7a2a3f2
Closes #387: Only truncate 'category' type labels.
Apr 30, 2018
fc5437f
Pad series text to be same length as x axis (re #391) (#392)
May 3, 2018
d7e413e
Closes #368: Wrap Autocomplete and checkbox in span and pad.
May 3, 2018
7fb937d
Closes #338: Allow dates formatted as YYYYMMDD to be displayed as dat…
Apr 11, 2018
6806277
Closes #228: Use Plotly's default xaxis type instead of datetime.
Apr 11, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .pyup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
schedule: "every day"
search: False
update: insecure
requirements:
- requirements.txt:
update: insecure
- requirements-newrelic.txt:
update: security
9 changes: 9 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ COPY requirements.txt requirements_dev.txt requirements_all_ds.txt ./
RUN pip install -r requirements.txt -r requirements_dev.txt -r requirements_all_ds.txt

COPY . ./

# Upgrade node to LTS 6.11.2
RUN cd ~
RUN wget https://nodejs.org/download/release/v6.11.2/node-v6.11.2-linux-x64.tar.gz
RUN sudo tar --strip-components 1 -xzvf node-v* -C /usr/local

# Upgrade npm
RUN npm upgrade npm

RUN npm install && npm run build && rm -rf node_modules
RUN chown -R redash /app
USER redash
Expand Down
19 changes: 19 additions & 0 deletions bin/deploy
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash

set -eo pipefail

[ ! -z $DOCKERHUB_REPO ] && [ $# -eq 1 ]

VERSION="$1"

printf '{"commit":"%s","version":"%s","source":"https://github.com/%s/%s","build":"%s"}\n' \
"$CIRCLE_SHA1" \
"$VERSION" \
"$CIRCLE_PROJECT_USERNAME" \
"$CIRCLE_PROJECT_REPONAME" \
"$CIRCLE_BUILD_URL" \
> version.json

docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
docker build -t $DOCKERHUB_REPO:$VERSION .
docker push $DOCKERHUB_REPO:$VERSION
13 changes: 11 additions & 2 deletions bin/docker-entrypoint
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,32 @@
set -e

worker() {
/app/manage.py db upgrade
WORKERS_COUNT=${WORKERS_COUNT:-2}
QUEUES=${QUEUES:-queries,scheduled_queries,celery}
MAX_MEMORY=$(($(/usr/bin/awk '/MemTotal/ {print $2}' /proc/meminfo)/4))

echo "Starting $WORKERS_COUNT workers for queues: $QUEUES..."
exec /usr/local/bin/celery worker --app=redash.worker -c$WORKERS_COUNT -Q$QUEUES -linfo --maxtasksperchild=10 -Ofair
exec /usr/local/bin/celery worker --app=redash.worker -c$WORKERS_COUNT -Q$QUEUES -linfo \
--max-tasks-per-child=10 \
--max-memory-per-child=$MAX_MEMORY \
-Ofair
}

scheduler() {
/app/manage.py db upgrade
WORKERS_COUNT=${WORKERS_COUNT:-1}
QUEUES=${QUEUES:-celery}

echo "Starting scheduler and $WORKERS_COUNT workers for queues: $QUEUES..."

exec /usr/local/bin/celery worker --app=redash.worker --beat -c$WORKERS_COUNT -Q$QUEUES -linfo --maxtasksperchild=10 -Ofair
exec /usr/local/bin/celery worker --app=redash.worker --beat -c$WORKERS_COUNT -Q$QUEUES -linfo \
--max-tasks-per-child=10 \
-Ofair
}

server() {
/app/manage.py db upgrade
exec /usr/local/bin/gunicorn -b 0.0.0.0:5000 --name redash -w${REDASH_WEB_WORKERS:-4} redash.wsgi:app
}

Expand Down
20 changes: 8 additions & 12 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,16 @@ test:
override:
- pytest --junitxml=$CIRCLE_TEST_REPORTS/junit.xml tests/
deployment:
tarball:
branch: [master, /release.*/]
latest:
branch: master
owner: mozilla
commands:
- bin/pack
docker:
tag: [/v[0-9]+(\.[0-9\-a-z]+)*/]
- ./bin/deploy "latest"
hub_releases:
tag: /^m[0-9]+(\.[0-9]+)?$/
owner: mozilla
commands:
- bin/pack
- docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
- docker build -t redash/redash:$(./manage.py version | sed -e "s/\+/./") .
- docker push redash/redash:$(./manage.py version | sed -e "s/\+/./")
notify:
webhooks:
- url: https://webhooks.gitter.im/e/895d09c3165a0913ac2f
- ./bin/deploy "$CIRCLE_TAG"
general:
branches:
ignore:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ <h4 class="modal-title">Dashboard name: {{$ctrl.dashboard.name}}</h4>
</div>
<div class="modal-body">
<p>
<input type="text" class="form-control" placeholder="Dashboard Name" ng-model="$ctrl.dashboard.name" autofocus>
<input type="text" class="form-control" placeholder="Dashboard Name" ng-model="$ctrl.dashboard.name" ng-keyup="$ctrl.saveDashboardOnEnter($event)" autofocus required>
</p>
</div>
<div class="modal-footer">
Expand Down
10 changes: 10 additions & 0 deletions client/app/components/dashboards/edit-dashboard-dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ const EditDashboardDialog = {
});
Events.record('create', 'dashboard');
};
this.saveDashboardOnEnter = ($event) => {
// keyCode 13 is the Enter key
if ($event.keyCode === 13) {
this.saveDashboard();
}
};
this.closeWithoutSave = () => {
this.dashboard.name = this.dashboard.existing_name;
this.dismiss();
};
},
};

Expand Down
4 changes: 2 additions & 2 deletions client/app/components/dashboards/widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ function DashboardWidgetCtrl($location, $uibModal, $window, Events, currentUser)
resolve: {
widget: this.widget,
},
backdrop: 'static',
keyboard: false,
});
};

Expand All @@ -68,8 +70,6 @@ function DashboardWidgetCtrl($location, $uibModal, $window, Events, currentUser)
return;
}

Events.record('delete', 'widget', this.widget.id);

this.widget.$delete((response) => {
this.dashboard.widgets = this.dashboard.widgets
.filter(widget => (widget.id !== undefined) && (widget.id !== this.widget.id));
Expand Down
1 change: 1 addition & 0 deletions client/app/components/dynamic-form.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<label ng-if="field.property.type !== 'checkbox'" class="control-label">{{field.property.title || field.name | capitalize}}</label>
<input name="input" type="{{field.property.type}}" class="form-control" ng-model="target.options[field.name]" ng-required="field.property.required"
ng-if="field.property.type !== 'file' && field.property.type !== 'checkbox'" accesskey="tab" placeholder="{{field.property.default}}">
<div class="mute-text"> {{ field.property.info }} </div>

<label ng-if="field.property.type=='checkbox'">
<input name="input" type="{{field.property.type}}" ng-model="target.options[field.name]" ng-required="field.property.required"
Expand Down
2 changes: 1 addition & 1 deletion client/app/components/parameters.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="parameter-container form-inline bg-white"
ng-if="parameters | notEmpty"
ng-if="hideParameters != 'true' && parameters | notEmpty"
ui-sortable="{ 'ui-floating': true, 'disabled': !editable }"
ng-model="parameters">
<div class="form-group m-r-10"
Expand Down
3 changes: 2 additions & 1 deletion client/app/components/parameters.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ function ParametersDirective($location, $uibModal) {
}
scope.parameters.forEach((param) => {
if (param.value !== null || param.value !== '') {
$location.search(`p_${param.name}`, param.value);
$location.search(`p_${param.name}_${param.queryId}`, param.value);
}
});
}, true);
Expand All @@ -145,6 +145,7 @@ function ParametersDirective($location, $uibModal) {
},
});
};
scope.hideParameters = $location.search().hideParameters;
},
};
}
Expand Down
54 changes: 37 additions & 17 deletions client/app/components/queries/query-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,57 +79,77 @@ function queryEditor(QuerySnippet, $timeout) {
editor.getSession().setMode(newMode);
});

$scope.$watch('schema', (newSchema, oldSchema) => {
$scope.$watch('autoCompleteSchema', (newSchema, oldSchema) => {
if (newSchema !== oldSchema) {
if (newSchema === undefined) {
return;
}
const tokensCount = newSchema.reduce((totalLength, table) => totalLength + table.columns.length, 0);
// If there are too many tokens we disable live autocomplete,
// as it makes typing slower.
if (tokensCount > 5000) {
const tokensCount =
newSchema.reduce((totalLength, table) => totalLength + table.columns.length, 0);
// If there are too many tokens or if it's requested via the UI
// we disable live autocomplete, as it makes typing slower.
if (tokensCount > 5000 || !$scope.$parent.autocompleteQuery) {
editor.setOption('enableLiveAutocompletion', false);
editor.setOption('enableBasicAutocompletion', false);
} else {
editor.setOption('enableLiveAutocompletion', true);
editor.setOption('enableBasicAutocompletion', true);
}
}
});

$scope.$parent.$on('angular-resizable.resizing', () => {
editor.resize();
});
$scope.$parent.$watch('autocompleteQuery', () => {
editor.setOption('enableLiveAutocompletion', $scope.$parent.autocompleteQuery);
editor.setOption('enableBasicAutocompletion', $scope.$parent.autocompleteQuery);
});

editor.focus();
},
};

const schemaCompleter = {
getCompletions(state, session, pos, prefix, callback) {
if (prefix.length === 0 || !$scope.schema) {
// make a variable for the auto completion in the query editor
$scope.autoCompleteSchema = $scope.schema; // removeExtraSchemaInfo(

if (prefix.length === 0 || !$scope.autoCompleteSchema) {
callback(null, []);
return;
}

if (!$scope.schema.keywords) {
if (!$scope.autoCompleteSchema.keywords) {
const keywords = {};

$scope.schema.forEach((table) => {
$scope.autoCompleteSchema.forEach((table) => {
keywords[table.name] = 'Table';

table.columns.forEach((c) => {
keywords[c] = 'Column';
table.columns.forEach((c) => { // autoCompleteColumns
if (c.charAt(c.length - 1) === ')') {
let parensStartAt = c.indexOf('(') - 1;
c = c.substring(0, parensStartAt);
parensStartAt = 1; // linter complains without this line
}
// remove '[P] ' for partition keys
if (c.charAt(0) === '[') {
c = c.substring(4, c.length);
}
// keywords[c] = 'Column'; // dups columns
keywords[`${table.name}.${c}`] = 'Column';
});
});

$scope.schema.keywords = map(keywords, (v, k) => ({
name: k,
value: k,
score: 0,
meta: v,
}));
$scope.autoCompleteSchema.keywords = map(keywords, (v, k) =>
({
name: k,
value: k,
score: 0,
meta: v,
}));
}
callback(null, $scope.schema.keywords);
callback(null, $scope.autoCompleteSchema.keywords);
},
};

Expand Down
7 changes: 7 additions & 0 deletions client/app/components/queries/schedule-dialog.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,11 @@ <h4 class="modal-title">Refresh Schedule</h4>
<query-time-picker refresh-type="$ctrl.refreshType" query="$ctrl.query" save-query="$ctrl.saveQuery"></query-time-picker>
</label>
</div>
<label>
Stop scheduling at date/time (format yyyy-MM-ddTHH:mm:ss, like 2016-12-28T14:57:00):
<schedule-until query="$ctrl.query" save-query="$ctrl.saveQuery"></schedule-until>
</label>
<label>
Number of query results to keep <schedule-keep-results query="$ctrl.query" save-query="$ctrl.saveQuery"></schedule-keep-results>
</label>
</div>
25 changes: 24 additions & 1 deletion client/app/components/queries/schedule-dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,32 @@ function queryRefreshSelect(clientConfig) {
};
}

function scheduleUntil() {
return {
restrict: 'E',
scope: {
query: '=',
saveQuery: '=',
},
template: '<input type="datetime-local" step="1" class="form-control" ng-model="query.scheduleUntil" ng-change="saveQuery()">',
};
}

function scheduleKeepResults() {
return {
restrict: 'E',
scope: {
query: '=',
saveQuery: '=',
},
template: '<input type="number" class="form-control" ng-model="query.schedule_resultset_size" ng-change="saveQuery()" ng-disabled="!query.schedule">',
};
}

const ScheduleForm = {
controller() {
this.query = this.resolve.query;
this.saveQuery = this.resolve.saveQuery;

if (this.query.hasDailySchedule()) {
this.refreshType = 'daily';
} else {
Expand All @@ -112,5 +133,7 @@ const ScheduleForm = {
export default function init(ngModule) {
ngModule.directive('queryTimePicker', queryTimePicker);
ngModule.directive('queryRefreshSelect', queryRefreshSelect);
ngModule.directive('scheduleUntil', scheduleUntil);
ngModule.directive('scheduleKeepResults', scheduleKeepResults);
ngModule.component('scheduleDialog', ScheduleForm);
}
14 changes: 12 additions & 2 deletions client/app/components/queries/schema-browser.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
<div class="schema-container" ng-if="$ctrl.schema">
<div class="schema-control">
<input type="text" placeholder="Search schema..." class="form-control" ng-model="$ctrl.schemaFilter" ng-disabled="$ctrl.isEmpty()">
<input type="text" placeholder="Search schema..." class="form-control" ng-model="$ctrl.schemaFilter" ng-model-options="{ debounce: 500 }" ng-disabled="$ctrl.isEmpty()">
<button class="btn btn-default"
title="Refresh Schema"
ng-click="$ctrl.onRefresh()">
<span class="zmdi zmdi-refresh"></span>
</button>

<button class="btn btn-default"
title="Toggle Versioned Tables"
ng-click="$ctrl.flipToggleVersionedTables($ctrl.versionToggle, $ctrl.tabletogglestring)"
ng-if="$ctrl.tabletogglestring && $ctrl.tabletogglestring != ''"
>
<span class="fa " ng-class="{'fa-toggle-on': $ctrl.versionToggle == true, 'fa-toggle-off': !$ctrl.versionToggle}">
<input type="checkbox" id="versioned-tables-toggle" ng-model="$ctrl.versionToggle" hidden/>
</span>
</button>
</div>

<div class="schema-browser" vs-repeat vs-size="$ctrl.getSize(table)">
<div ng-repeat="table in $ctrl.schema | filter:$ctrl.schemaFilter track by table.name">
<div ng-repeat="table in $ctrl.schema | filter:$ctrl.schemaFilter | filter: {name: '!'+$ctrl.versionFilter}">
<div class="table-name" ng-click="$ctrl.showTable(table)">
<i class="fa fa-table"></i>
<strong>
Expand Down
14 changes: 14 additions & 0 deletions client/app/components/queries/schema-browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import template from './schema-browser.html';
function SchemaBrowserCtrl($rootScope, $scope) {
'ngInject';

this.versionToggle = false;
this.versionFilter = 'abcdefghijklmnop';

this.showTable = (table) => {
table.collapsed = !table.collapsed;
$scope.$broadcast('vsRepeatTrigger');
Expand All @@ -21,6 +24,15 @@ function SchemaBrowserCtrl($rootScope, $scope) {
this.isEmpty = function isEmpty() {
return this.schema === undefined || this.schema.length === 0;
};
this.flipToggleVersionedTables = (versionToggle, toggleString) => {
if (versionToggle === false) {
this.versionToggle = true;
this.versionFilter = toggleString;
} else {
this.versionToggle = false;
this.versionFilter = 'abcdefghijklmnop';
}
};

this.itemSelected = ($event, hierarchy) => {
$rootScope.$broadcast('query-editor.paste', hierarchy.join('.'));
Expand All @@ -32,7 +44,9 @@ function SchemaBrowserCtrl($rootScope, $scope) {
const SchemaBrowser = {
bindings: {
schema: '<',
tabletogglestring: '<',
onRefresh: '&',
flipToggleVersionedTables: '&',
},
controller: SchemaBrowserCtrl,
template,
Expand Down
Loading