mirror of
https://github.com/valitydev/redash.git
synced 2024-11-08 18:03:54 +00:00
272 lines
13 KiB
HTML
272 lines
13 KiB
HTML
<div class="container">
|
|
<overlay ng-if="canCreateQuery === false && query.isNew()">
|
|
You don't have permission to create new queries on any of the data sources available to you. You can either <a
|
|
href="queries">browse existing queries</a>, or ask for additional permissions from your Redash admin.
|
|
</overlay>
|
|
<overlay ng-if="noDataSources && currentUser.isAdmin">
|
|
Looks like no data sources were created yet (or none of them available to the group(s) you're member of). Please
|
|
create one first, and then start querying.
|
|
<br/>
|
|
<a href="data_sources/new" class="btn btn-primary">Create Data Source</a> <a href="groups" class="btn btn-default">Manage
|
|
Group Permissions</a>
|
|
</overlay>
|
|
<overlay ng-if="noDataSources && !currentUser.isAdmin">
|
|
Looks like no data sources were created yet (or none of them available to the group(s) you're member of). Please ask
|
|
your Redash admin to create one first.
|
|
</overlay>
|
|
|
|
<alert-unsaved-changes ng-if="canEdit" is-dirty="isDirty"></alert-unsaved-changes>
|
|
|
|
<div class="row bg-white p-10 m-b-10">
|
|
<div class="col-sm-9">
|
|
<h3>
|
|
<edit-in-place editable="canEdit" done="saveName" ignore-blanks="true" value="query.name"></edit-in-place>
|
|
<span class="label label-default" ng-if="query.is_draft && !query.is_archived">Unpublished</span>
|
|
<span class="label label-warning" ng-if="query.is_archived" uib-popover="This query is archived and can't be used in dashboards, and won't appear in search results." popover-placement="right" popover-trigger="'mouseenter'">Archived</span>
|
|
</h3>
|
|
<p>
|
|
<em>
|
|
<edit-in-place editable="canEdit"
|
|
done="saveDescription"
|
|
editor="textarea"
|
|
placeholder="No description"
|
|
ignore-blanks='false'
|
|
value="query.description"
|
|
markdown="true">
|
|
</edit-in-place>
|
|
</em>
|
|
|
|
<ul class="list-inline m-t-20">
|
|
<li>
|
|
<span class="zmdi zmdi-account"></span>
|
|
<span class="text-muted">Created By </span>
|
|
<strong>{{query.user.name}}</strong>
|
|
</li>
|
|
<li ng-if="query.last_modified_by && query.user.id != query.last_modified_by.id">
|
|
<span class="zmdi zmdi-account"></span>
|
|
<span class="text-muted">Last Modified By </span>
|
|
<strong>{{query.last_modified_by.name}}</strong>
|
|
</li>
|
|
<li>
|
|
<span class="zmdi zmdi-time"></span>
|
|
<span class="text-muted">Updated at </span>
|
|
<strong>
|
|
<rd-time-ago value="query.updated_at"></rd-time-ago>
|
|
</strong>
|
|
</li>
|
|
<li>
|
|
<span class="zmdi zmdi-time"></span>
|
|
<span class="text-muted">Created at </span>
|
|
<strong>
|
|
<rd-time-ago value="query.created_at"></rd-time-ago>
|
|
</strong>
|
|
</li>
|
|
</ul>
|
|
</p>
|
|
</div>
|
|
<div class="col-sm-3 text-right">
|
|
<h3>
|
|
<span ng-show="query.id && canViewSource">
|
|
<a ng-show="!sourceMode"
|
|
ng-href="{{query.getUrl(true, selectedTab)}}" class="btn btn-default">Show Source
|
|
</a>
|
|
<a ng-show="sourceMode"
|
|
ng-href="{{query.getUrl(false, selectedTab)}}" class="btn btn-default">Hide Source
|
|
</a>
|
|
</span>
|
|
</h3>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- editor -->
|
|
<div class="container">
|
|
<div class="row bg-white p-b-5" ng-if="sourceMode" resizable r-directions="['bottom']" r-height="300" style="min-height:100px;">
|
|
<schema-browser class="col-md-3 hidden-sm hidden-xs schema-container"
|
|
schema="schema"
|
|
on-refresh="refreshSchema()"
|
|
ng-show="hasSchema">
|
|
</schema-browser>
|
|
|
|
<div ng-class="editorSize" style="height:100%;">
|
|
<div class="p-5">
|
|
<button type="button" class="btn btn-primary btn-s" ng-disabled="queryExecuting || !canExecuteQuery()"
|
|
ng-click="executeQuery()">
|
|
<span class="zmdi zmdi-play"></span> Execute
|
|
</button>
|
|
|
|
<button type="button" class="btn btn-default btn-s" ng-click="formatQuery()">
|
|
<span class="zmdi zmdi-format-indent-increase"></span> Format Query
|
|
</button>
|
|
|
|
<i class="fa fa-database"></i>
|
|
<span class="text-muted">Data Source</span>
|
|
<select ng-disabled="!isQueryOwner" ng-model="query.data_source_id" ng-change="updateDataSource()"
|
|
ng-options="ds.id as ds.name for ds in dataSources"></select>
|
|
|
|
<div class="pull-right">
|
|
<button class="btn btn-s btn-default" ng-click="togglePublished()" ng-if="query.is_draft && query.id != undefined && (isQueryOwner || currentUser.hasPermission('admin'))">
|
|
<span class="fa fa-paper-plane"></span> Publish
|
|
</button>
|
|
<button class="btn btn-s btn-default" ng-click="duplicateQuery()" ng-disabled="query.id === undefined">
|
|
<span class="zmdi zmdi-arrow-split"></span> Fork
|
|
</button>
|
|
<button class="btn btn-default" ng-show="canEdit" ng-click="saveQuery()">
|
|
<span class="fa fa-floppy-o"> </span> Save<span
|
|
ng-show="isDirty">*</span>
|
|
</button>
|
|
<div class="btn-group" role="group" uib-dropdown>
|
|
<button class="btn btn-default btn-sm dropdown-toggle" uib-dropdown-toggle>
|
|
<span class="zmdi zmdi-more"></span>
|
|
</button>
|
|
<ul class="dropdown-menu pull-right" uib-dropdown-menu>
|
|
<li ng-if="!query.is_archived && query.id != undefined && (isQueryOwner || currentUser.hasPermission('admin'))"><a ng-click="archiveQuery()">Archive Query</a></li>
|
|
<li ng-if="!query.is_archived && query.id != undefined && (isQueryOwner || currentUser.hasPermission('admin')) && showPermissionsControl"><a ng-click="showManagePermissionsModal()">Manage Permissions</a></li>
|
|
<li ng-if="!query.is_draft && query.id != undefined && (isQueryOwner || currentUser.hasPermission('admin'))"><a ng-click="togglePublished()">Unpublish Query</a></li>
|
|
<li ng-if="query.id != undefined"><a ng-click="showApiKey()">Show API Key</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<p style="height:calc(100% - 40px);">
|
|
<query-editor query="query"
|
|
schema="schema"
|
|
syntax="dataSource.syntax"></query-editor>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- end of editor -->
|
|
|
|
<!-- Query Details-->
|
|
<div class="container m-b-5 p-t-5 bg-ace" ng-if="sourceMode">
|
|
</div>
|
|
<!-- End of Query Details-->
|
|
|
|
<div class="tile">
|
|
<div class="t-header bg-ace">
|
|
<div class="pull-right">
|
|
<button class="btn btn-sm btn-default" ng-click="executeQuery()"
|
|
ng-disabled="queryExecuting || !canExecuteQuery()" title="Refresh Dataset"
|
|
ng-if="!sourceMode"><span
|
|
class="zmdi zmdi-refresh"></span></button>
|
|
<div class="btn-group" uib-dropdown>
|
|
<button type="button" class="btn btn-default btn-sm dropdown-toggle"
|
|
ng-disabled="queryExecuting || !queryResult.getData()" aria-haspopup="true"
|
|
uib-dropdown-toggle aria-expanded="false">
|
|
Download Dataset <span class="caret"></span>
|
|
</button>
|
|
<ul class="dropdown-menu pull-right" uib-dropdown-menu>
|
|
<li>
|
|
<a query-result-link target="_self">
|
|
<span class="fa fa-file-o"></span> Download as CSV File
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a query-result-link file-type="xlsx" target="_self">
|
|
<span class="fa fa-file-excel-o"></span> Download as Excel File
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<ul class="list-inline">
|
|
<li>
|
|
<!-- runtime -->
|
|
<span class="zmdi zmdi-timer"></span>
|
|
<span class="text-muted">Runtime </span>
|
|
<strong ng-show="!queryExecuting">{{queryResult.getRuntime() | durationHumanize}}</strong>
|
|
<span ng-show="queryExecuting">Running…</span>
|
|
</li>
|
|
<li>
|
|
<!-- rows -->
|
|
<span class="zmdi zmdi-format-align-justify"></span>
|
|
<span class="text-muted">Rows </span><strong>{{queryResult.getData().length}}</strong>
|
|
</li>
|
|
<li>
|
|
<!-- refresh schedule -->
|
|
<span class="zmdi zmdi-refresh"></span>
|
|
<span class="text-muted">Refresh Schedule</span>
|
|
<a ng-click="openScheduleForm()" ng-if="!query.isNew()">{{query.schedule | scheduleHumanize}}</a>
|
|
<span ng-if="query.isNew()">Never</span>
|
|
</li>
|
|
<li>
|
|
<!-- last update -->
|
|
<span class="zmdi zmdi-time"></span>
|
|
<span class="text-muted">Last update </span>
|
|
<strong>
|
|
<rd-time-ago value="queryResult.query_result.retrieved_at"></rd-time-ago>
|
|
</strong>
|
|
</li>
|
|
</ul>
|
|
|
|
</div>
|
|
<div class="t-body">
|
|
<div class="row">
|
|
<div class="col-lg-12">
|
|
<parameters parameters="query.getParametersDefs()" sync-values="!query.isNew()" editable="sourceMode && canEdit"></parameters>
|
|
<!-- Query Execution Status -->
|
|
<div class="alert alert-info" ng-show="queryResult.getStatus() == 'processing'">
|
|
Executing query…
|
|
<rd-timer timestamp="queryResult.getUpdatedAt()"></rd-timer>
|
|
<button type="button" class="btn btn-warning btn-xs pull-right" ng-disabled="cancelling"
|
|
ng-click="cancelExecution()">Cancel
|
|
</button>
|
|
</div>
|
|
<div class="alert alert-info" ng-show="queryResult.getStatus() == 'waiting'">
|
|
Query in queue…
|
|
<rd-timer timestamp="queryResult.getUpdatedAt()"></rd-timer>
|
|
<button type="button" class="btn btn-warning btn-xs pull-right" ng-disabled="cancelling"
|
|
ng-click="cancelExecution()">Cancel
|
|
</button>
|
|
</div>
|
|
<div class="alert alert-danger" ng-show="queryResult.getError()">Error running query: <strong>{{queryResult.getError()}}</strong>
|
|
</div>
|
|
<!-- End of Query Execution Status -->
|
|
|
|
<!-- tabs and data -->
|
|
<div ng-if="showDataset">
|
|
<div class="row p-10" ng-show="showLog">
|
|
<div class="col-lg-12">
|
|
<p>Log Information:</p>
|
|
<p ng-repeat="l in queryResult.getLog()">{{l}}</p>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-lg-12">
|
|
<ul class="tab-nav">
|
|
<rd-tab tab-id="table" name="Table" base-path="query.getUrl(sourceMode)"></rd-tab>
|
|
<rd-tab tab-id="{{vis.id}}" name="{{vis.name}}" ng-if="vis.type!='TABLE'" base-path="query.getUrl(sourceMode)"
|
|
ng-repeat="vis in query.visualizations">
|
|
<span class="remove" ng-click="deleteVisualization($event, vis)"
|
|
ng-show="canEdit"> ×</span>
|
|
</rd-tab>
|
|
<li class="rd-tab"><a ng-click="openVisualizationEditor()" ng-if="sourceMode && canEdit">+ New Visualization</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-lg-12">
|
|
<div ng-show="selectedTab == 'table'">
|
|
<filters filters="filters"></filters>
|
|
<grid-renderer query-result="queryResult" items-per-page="50"></grid-renderer>
|
|
<!-- the ng-repeat is a lame hack to find the table visualization... -->
|
|
<div class="bg-ace p-5" ng-repeat="vis in query.visualizations" ng-if="vis.type == 'TABLE'">
|
|
<button class="btn btn-default" ng-if="!query.isNew()" ng-click="showEmbedDialog(query, vis)"><i class="zmdi zmdi-code"></i> Embed</button>
|
|
</div>
|
|
</div>
|
|
<div ng-if="selectedTab == vis.id" ng-repeat="vis in query.visualizations">
|
|
<visualization-renderer visualization="vis" query-result="queryResult"></visualization-renderer>
|
|
<div class="bg-ace p-5">
|
|
<button class="btn btn-default" ng-click="openVisualizationEditor(vis)" ng-if="canEdit">Edit</button>
|
|
<button class="btn btn-default" ng-click="showEmbedDialog(query, vis)"><i class="zmdi zmdi-code"></i> Embed</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|