Skip to content

Commit

Permalink
Documentation links for data sources (re getredash#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
Allen Short committed Jul 25, 2018
1 parent fc63a3e commit 1a3f630
Show file tree
Hide file tree
Showing 36 changed files with 300 additions and 15 deletions.
2 changes: 2 additions & 0 deletions client/app/assets/less/redash/query.less
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@ a.label-tag {

.datasource-small {
visibility: hidden;
display: none !important;
}

.query-fullscreen .query-metadata__mobile {
Expand Down Expand Up @@ -599,6 +600,7 @@ nav .rg-bottom {

.datasource-small {
visibility: visible;
display: inline-block !important;
}

.query-fullscreen {
Expand Down
2 changes: 1 addition & 1 deletion client/app/pages/data-sources/list.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<div class="database-source">
<a class="visual-card" ng-href="data_sources/{{dataSource.id}}" ng-repeat="dataSource in $ctrl.dataSources" title="{{dataSource.name}}">
<img ng-src="/static/images/db-logos/{{dataSource.type}}.png" alt="{{dataSource.name}}">
<h3>{{dataSource.name}}</h3>
<h3>{{dataSource.name}}</h3> - {{dataSource.type_name}}
</a>
</div>
</div>
Expand Down
21 changes: 21 additions & 0 deletions client/app/pages/data-sources/show.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,32 @@ function DataSourceCtrl(
});
}

function getDataSourceVersion(callback) {
Events.record('test', 'data_source_version', $scope.dataSource.id);

DataSource.version({ id: $scope.dataSource.id }, (httpResponse) => {
if (httpResponse.ok) {
const versionNumber = httpResponse.message;
toastr.success(`Success. Version: ${versionNumber}`);
} else {
toastr.error(httpResponse.message, 'Version Test Failed:', { timeOut: 10000 });
}
callback();
}, (httpResponse) => {
logger('Failed to get data source version: ', httpResponse.status, httpResponse.statusText, httpResponse);
toastr.error('Unknown error occurred while performing data source version test. Please try again later.', 'Data Source Version Test Failed:', { timeOut: 10000 });
callback();
});
}

$scope.actions = [
{ name: 'Delete', class: 'btn-danger', callback: deleteDataSource },
{
name: 'Test Connection', class: 'btn-default pull-right', callback: testConnection, disableWhenDirty: true,
},
{
name: 'Test Data Source Version', class: 'btn-default', callback: getDataSourceVersion, disableWhenDirty: true,
},
];
}

Expand Down
19 changes: 19 additions & 0 deletions client/app/pages/queries/get-data-source-version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
function GetDataSourceVersionCtrl(Events, toastr, $scope, DataSource, $route) {
'ngInject';

this.getDataSourceVersion = DataSource.version({
id: $route.current.locals.query.data_source_id,
});
}

const GetDataSourceVersionInfo = {
bindings: {
onRefresh: '&',
},
controller: GetDataSourceVersionCtrl,
template: '<span ng-if=\'!$ctrl.getDataSourceVersion.message.includes("no")\'>{{ $ctrl.getDataSourceVersion.message }}</span><span ng-if=\'$ctrl.getDataSourceVersion.message.includes("no")\' class=\'fa fa-exclamation-circle\' data-toggle=\'tooltip\' data-placement=\'right\' tooltip title=\'{{ $ctrl.getDataSourceVersion.message }}\'></span>',
};

export default function (ngModule) {
ngModule.component('getDataSourceVersion', GetDataSourceVersionInfo);
}
11 changes: 8 additions & 3 deletions client/app/pages/queries/query.html
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ <h3>
{{ds.name}}
</ui-select-choices>
</ui-select>
<a ng-if="dataSource.options.doc_url != '' && dataSource.options.doc_url" ng-href={{dataSource.options.doc_url}}>{{dataSource.type_name}} documentation</a>
<span ng-if="dataSource.options.doc_url == '' || !dataSource.options.doc_url">{{ dataSource.type_name }} documentation</span>
<get-data-source-version id='data-source-version'></get-data-source-version>
</div>

<div class="editor__left__schema" ng-if="sourceMode">
Expand Down Expand Up @@ -154,8 +157,10 @@ <h3>
<div class="editor__control">
<div class="row form-inline">
<div class="col-xs-5 text-left">
<select class="form-control datasource-small" ng-disabled="!isQueryOwner || !sourceMode" ng-model="query.data_source_id"
ng-change="updateDataSource()" ng-options="ds.id as ds.name for ds in dataSources"></select>
<select class="form-control datasource-small" ng-disabled="!isQueryOwner || !sourceMode" ng-model="query.data_source_id" ng-change="updateDataSource()"
ng-options="ds.id as ds.name for ds in dataSources"></select>
<a ng-if="dataSource.options.doc_url != ''" ng-href={{dataSource.options.doc_url}}>{{dataSource.type_name}} documentation</a>
<span ng-if="dataSource.options.doc_url == ''">{{dataSource.type_name}}</span>
</div>

<div class="col-xs-7">
Expand Down Expand Up @@ -318,4 +323,4 @@ <h3>
</div>
</div>
</main>
</div>
</div>
1 change: 1 addition & 0 deletions client/app/pages/queries/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ function QueryViewCtrl(
}

$scope.dataSource = find($scope.dataSources, ds => ds.id === $scope.query.data_source_id);
document.getElementById('data-source-version').innerHTML = '<span class=\'fa fa-refresh\' data-toggle=\'tooltip\' data-placement=\'right\' tooltip title=\'It seems the data source was changed since the page loaded, refresh page to get version\'></span>';
getSchema();
$scope.executeQuery();
};
Expand Down
3 changes: 3 additions & 0 deletions client/app/services/data-source.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ function DataSource($q, $resource, $http) {
isArray: false,
url: 'api/data_sources/:id/test',
},
version: {
method: 'GET', cache: false, isArray: false, url: 'api/data_sources/:id/version',
},
};

const DataSourceResource = $resource('api/data_sources/:id', { id: '@id' }, actions);
Expand Down
24 changes: 24 additions & 0 deletions redash/cli/data_sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,30 @@ def test(name, organization='default'):
print("Couldn't find data source named: {}".format(name))
exit(1)

@manager.command()
@click.argument('name')
@click.option('--org', 'organization', default='default',
help="The organization the user belongs to "
"(leave blank for 'default').")
def get_data_source_version(name, organization='default'):
"""Get version of data source connection by issuing a trivial query."""
try:
org = models.Organization.get_by_slug(organization)
data_source = models.DataSource.query.filter(
models.DataSource.name == name,
models.DataSource.org == org).one()
print("Testing get connection data source version: {} (id={})".format(
name, data_source.id))
try:
info = data_source.query_runner.get_data_source_version()
except Exception as e:
print("Failure: {}".format(e))
exit(1)
else:
print(info)
except NoResultFound:
print("Couldn't find data source named: {}".format(name))
exit(1)

@manager.command()
@click.argument('name', default=None, required=False)
Expand Down
5 changes: 3 additions & 2 deletions redash/handlers/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from redash.handlers.base import org_scoped_rule
from redash.handlers.permissions import ObjectPermissionsListResource, CheckPermissionResource
from redash.handlers.alerts import AlertResource, AlertListResource, AlertSubscriptionListResource, AlertSubscriptionResource
from redash.handlers.dashboards import DashboardListResource, DashboardResource, DashboardShareResource, PublicDashboardResource
from redash.handlers.data_sources import DataSourceTypeListResource, DataSourceListResource, DataSourceSchemaResource, DataSourceResource, DataSourcePauseResource, DataSourceTestResource
from redash.handlers.dashboards import DashboardListResource, DashboardResource, DashboardShareResource, PublicDashboardResource
from redash.handlers.data_sources import DataSourceTypeListResource, DataSourceListResource, DataSourceSchemaResource, DataSourceResource, DataSourcePauseResource, DataSourceTestResource, DataSourceVersionResource
from redash.handlers.events import EventsResource
from redash.handlers.queries import QueryForkResource, QueryRefreshResource, QueryListResource, QueryRecentResource, QuerySearchResource, QueryResource, MyQueriesResource
from redash.handlers.query_results import QueryResultListResource, QueryResultResource, JobResource
Expand Down Expand Up @@ -58,6 +58,7 @@ def json_representation(data, code, headers=None):
api.add_org_resource(DataSourceSchemaResource, '/api/data_sources/<data_source_id>/schema')
api.add_org_resource(DataSourcePauseResource, '/api/data_sources/<data_source_id>/pause')
api.add_org_resource(DataSourceTestResource, '/api/data_sources/<data_source_id>/test')
api.add_org_resource(DataSourceVersionResource, '/api/data_sources/<data_source_id>/version')
api.add_org_resource(DataSourceResource, '/api/data_sources/<data_source_id>', endpoint='data_source')

api.add_org_resource(GroupListResource, '/api/groups', endpoint='groups')
Expand Down
13 changes: 13 additions & 0 deletions redash/handlers/data_sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,16 @@ def post(self, data_source_id):
return {"message": unicode(e), "ok": False}
else:
return {"message": "success", "ok": True}

class DataSourceVersionResource(BaseResource):
def get(self, data_source_id):
data_source = get_object_or_404(models.DataSource.get_by_id_and_org, data_source_id, self.current_org)
require_access(data_source.groups, self.current_user, view_only)
try:
version_info = data_source.query_runner.get_data_source_version()
except Exception as e:
return {"message": unicode(e), "ok": False}
else:
return {"message": version_info, "ok": True}


11 changes: 7 additions & 4 deletions redash/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -593,13 +593,14 @@ def to_dict(self, all=False, with_permissions_for=None):
'type': self.type,
'syntax': self.query_runner.syntax,
'paused': self.paused,
'pause_reason': self.pause_reason
'pause_reason': self.pause_reason,
'type_name': self.query_runner.name(),
}

schema = get_configuration_schema_for_query_runner_type(self.type)
self.options.set_schema(schema)
d['options'] = self.options.to_dict(mask_secrets=True)
if all:
schema = get_configuration_schema_for_query_runner_type(self.type)
self.options.set_schema(schema)
d['options'] = self.options.to_dict(mask_secrets=True)
d['queue_name'] = self.queue_name
d['scheduled_queue_name'] = self.scheduled_queue_name
d['groups'] = self.groups
Expand Down Expand Up @@ -683,6 +684,8 @@ def add_group(self, group, view_only=False):
db.session.add(dsg)
return dsg

setattr(self, 'data_source_groups', dsg)

def remove_group(self, group):
db.session.query(DataSourceGroup).filter(
DataSourceGroup.group == group,
Expand Down
24 changes: 24 additions & 0 deletions redash/query_runner/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class NotSupported(Exception):

class BaseQueryRunner(object):
noop_query = None
default_doc_url = None
data_source_version_query = None

def __init__(self, configuration):
self.syntax = 'sql'
Expand All @@ -76,6 +78,28 @@ def annotate_query(cls):
def configuration_schema(cls):
return {}

def get_data_source_version(self):
if self.data_source_version_query is None:
raise NotImplementedError
data, error = self.run_query(self.data_source_version_query, None)

if error is not None:
raise Exception(error)

try:
version = json.loads(data)['rows'][0]['version']
except KeyError as e:
raise Exception(e)

if self.data_source_version_post_process == "split by space take second":
version = version.split(" ")[1]
elif self.data_source_version_post_process == "split by space take last":
version = version.split(" ")[-1]
elif self.data_source_version_post_process == "none":
version = version

return version

def test_connection(self):
if self.noop_query is None:
raise NotImplementedError()
Expand Down
6 changes: 6 additions & 0 deletions redash/query_runner/big_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ def _get_query_results(jobs, project_id, job_id, start_index):

class BigQuery(BaseQueryRunner):
noop_query = "SELECT 1"
default_doc_url = "https://cloud.google.com/bigquery/docs/reference/legacy-sql"

@classmethod
def enabled(cls):
Expand Down Expand Up @@ -117,6 +118,11 @@ def configuration_schema(cls):
'maximumBillingTier': {
"type": "number",
"title": "Maximum Billing Tier"
},
"doc_url": {
"type": "string",
"title": "Documentation URL",
"default": cls.default_doc_url
}
},
'required': ['jsonKeyFile', 'projectId'],
Expand Down
6 changes: 6 additions & 0 deletions redash/query_runner/cass.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def default(self, o):

class Cassandra(BaseQueryRunner):
noop_query = "SELECT dateof(now()) FROM system.local"
default_doc_url = "http://cassandra.apache.org/doc/latest/cql/index.html"

@classmethod
def enabled(cls):
Expand Down Expand Up @@ -65,6 +66,11 @@ def configuration_schema(cls):
'type': 'number',
'title': 'Timeout',
'default': 10
},
"doc_url": {
"type": "string",
"title": "Documentation URL",
"default": cls.default_doc_url
}
},
'required': ['keyspace', 'host']
Expand Down
8 changes: 8 additions & 0 deletions redash/query_runner/dynamodb_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@


class DynamoDBSQL(BaseSQLQueryRunner):
noop_query = "SELECT 1"
default_doc_url = "https://dql.readthedocs.io/en/latest/"

@classmethod
def configuration_schema(cls):
return {
Expand All @@ -47,6 +50,11 @@ def configuration_schema(cls):
},
"secret_key": {
"type": "string",
},
"doc_url": {
"type": "string",
"title": "Documentation URL",
"default": cls.default_doc_url
}
},
"required": ["access_key", "secret_key"],
Expand Down
8 changes: 7 additions & 1 deletion redash/query_runner/elasticsearch.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@


class BaseElasticSearch(BaseQueryRunner):
DEBUG_ENABLED = False
DEBUG_ENABLED = True
default_doc_url = "https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html"

@classmethod
def configuration_schema(cls):
Expand All @@ -62,6 +63,11 @@ def configuration_schema(cls):
'basic_auth_password': {
'type': 'string',
'title': 'Basic Auth Password'
},
"doc_url": {
"type": "string",
"title": "Documentation URL",
"default": cls.default_doc_url
}
},
"secret": ["basic_auth_password"],
Expand Down
9 changes: 9 additions & 0 deletions redash/query_runner/google_spreadsheets.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ def parse_worksheet(worksheet):
columns.append({
'name': column_name,
'friendly_name': column_name,

'type': TYPE_STRING
})

Expand Down Expand Up @@ -138,6 +139,9 @@ def request(self, *args, **kwargs):


class GoogleSpreadsheet(BaseQueryRunner):
default_doc_url = ("http://redash.readthedocs.io/en/latest/"
"datasources.html#google-spreadsheets")

@classmethod
def annotate_query(cls):
return False
Expand All @@ -158,6 +162,11 @@ def configuration_schema(cls):
'jsonKeyFile': {
"type": "string",
'title': 'JSON Key File'
},
"doc_url": {
"type": "string",
"title": "Documentation URL",
"default": cls.default_doc_url
}
},
'required': ['jsonKeyFile'],
Expand Down
5 changes: 5 additions & 0 deletions redash/query_runner/graphite.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ def configuration_schema(cls):
'verify': {
'type': 'boolean',
'title': 'Verify SSL certificate'
},
"doc_url": {
"type": "string",
"title": "Documentation URL",
"default": cls.default_doc_url
}
},
'required': ['url'],
Expand Down
Loading

0 comments on commit 1a3f630

Please sign in to comment.