Skip to content
This repository has been archived by the owner on Jul 9, 2024. It is now read-only.

Commit

Permalink
feat(export-table): Cancel export requests.
Browse files Browse the repository at this point in the history
- Reverts logic on tableicious handling turning off
  loading spinner to prevent complications.
- Download happens programatically through restangular.
  Abort process/UI incoming
- Defaults to no dialogue if the browser doesn't support
  createObjectURL

Closes #277
  • Loading branch information
Matthew Schranz authored and Shane Wilson committed Feb 17, 2015
1 parent c542196 commit f0f8e2f
Show file tree
Hide file tree
Showing 14 changed files with 156 additions and 29 deletions.
4 changes: 2 additions & 2 deletions app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@
<a href="#skip" tabindex="1" class="skip-to-content" data-translate>Skip to Main Content</a>

<div id="wrapper" aria-busy="true" aria-live="assertive" tabindex="0">
<div data-ng-if="!loaded" class="app-loading">
<i class="fa fa-spinner fa-spin fa-5x"></i>
<div data-ng-if="!loaded || !modelLoaded" class="app-loading">
<i class="fa fa-spinner fa-spin fa-5x" data-ng-click="cancelRequest()"></i>
</div>

<div id="header">
Expand Down
18 changes: 16 additions & 2 deletions app/scripts/annotations/annotations.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module ngApp.annotations.services {
import IAnnotations = ngApp.annotations.models.IAnnotations;
import ILocationService = ngApp.components.location.services.ILocationService;
import ICoreService = ngApp.core.services.ICoreService;
import IRootScope = ngApp.IRootScope;

export interface IAnnotationsService {
getAnnotation(id: string, params?: Object): ng.IPromise<IAnnotation>;
Expand All @@ -14,7 +15,8 @@ module ngApp.annotations.services {

/* @ngInject */
constructor(Restangular: restangular.IService, private LocationService: ILocationService,
private CoreService: ICoreService) {
private CoreService: ICoreService, private $rootScope: IRootScope,
private $q: ng.IQService) {
this.ds = Restangular.all("annotations");
}

Expand Down Expand Up @@ -54,10 +56,22 @@ module ngApp.annotations.services {

this.CoreService.setSearchModelState(false);

return this.ds.get("", angular.extend(defaults, params)).then((response): IAnnotations => {
var abort = this.$q.defer();
var prom: ng.IPromise<IAnnotations> = this.ds.withHttpConfig({
timeout: abort.promise
})
.get("", angular.extend(defaults, params)).then((response): IAnnotations => {
this.CoreService.setSearchModelState(true);
return response["data"];
});

var eventCancel = this.$rootScope.$on("gdc-cancel-request", () => {
abort.resolve();
eventCancel();
this.CoreService.setSearchModelState(true);
});

return prom;
}
}

Expand Down
3 changes: 0 additions & 3 deletions app/scripts/annotations/templates/annotations.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ <h3 class="panel-title pull-left">Facets</h3>
</div>

<div class="col-lg-9 col-md-8">
<div data-ng-if="!modelLoaded" class="app-loading table-loader">
<i class="fa fa-spinner fa-spin fa-5x"></i>
</div>

<div class="alert alert-info clearfix">
<span data-ng-if="!cfc.currentFilters.length">
Expand Down
3 changes: 1 addition & 2 deletions app/scripts/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ declare module ngApp {
modelLoaded: boolean;
config: IGDCConfig;
undoClicked(action: string): void;
cancelRequest(): void;
}
}

Expand Down Expand Up @@ -47,8 +48,6 @@ function appRun(gettextCatalog: any, Restangular: restangular.IProvider,
UserService: IUserService) {
gettextCatalog.debug = true;

//debugger;

$rootScope.config = config;
Restangular.setErrorInterceptor((response) => {
CoreService.xhrDone();
Expand Down
5 changes: 5 additions & 0 deletions app/scripts/components/location/location.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module ngApp.components.location.services {
pagination(): any;
setPaging(pagination: any): ng.ILocationService;
setHref(href: string): void;
getHref(href: string): string;
}

class LocationService implements ILocationService {
Expand Down Expand Up @@ -110,6 +111,10 @@ module ngApp.components.location.services {
this.$window.location.href = href;
}

getHref(href: string): string {
return this.$window.location.href;
}

}

angular
Expand Down
74 changes: 67 additions & 7 deletions app/scripts/components/tables/tables.controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ module ngApp.components.tables.controllers {
import ILocationService = ngApp.components.location.services.ILocationService;
import ITableColumn = ngApp.components.tables.models.ITableColumn;
import IPagination = ngApp.components.tables.pagination.models.IPagination;
import IGDCConfig = ngApp.IGDCConfig;

interface ITableSortController {
updateSorting(): void;
Expand Down Expand Up @@ -110,22 +109,83 @@ module ngApp.components.tables.controllers {
class ExportTableController implements IExportTableController {

/* @ngInject */
constructor(private $scope: IExportScope, private LocationService: ILocationService, private config: IGDCConfig) {}
constructor(private $scope: IExportScope, private LocationService: ILocationService, private config: IGDCConfig,
private $modal: any, private $q: ng.IQService, private Restangular: restangular.IProvider,
private $window: ng.IWindowService) {}

exportTable(fileType: string): void {
var filters: Object = this.LocationService.filters();
this.LocationService.setHref(this.config.api + "/" +
this.$scope.endpoint +
"?attachment=true&format=" + fileType +
"&size=" + this.$scope.size +
"&filters=" + JSON.stringify(filters));
var url = this.LocationService.getHref();
var abort = this.$q.defer();
var modalInstance = this.$modal.open({
templateUrl: "components/tables/templates/export-modal.html",
controller: "ExportTableModalController as etmc",
backdrop: 'static'
});

if (this.$window.URL && this.$window.URL.createObjectURL) {
abort = this.$q.defer();
this.Restangular.all(this.$scope.endpoint)
.withHttpConfig({
timeout: abort.promise,
responseType: "blob"
})
.get('', {
filters: filters,
attachment: true,
format: fileType,
size: this.$scope.size
}).then((file) => {
var url = this.$window.URL.createObjectURL(file);
var a = this.$window.document.createElement("a");
a.setAttribute("href", url);
a.setAttribute("download", this.$scope.endpoint + "." +
this.$window.moment().format() + "." +
fileType.toLowerCase());
this.$window.document.body.appendChild(a);

_.defer(() => {
a.click();
modalInstance.close();
this.$window.document.body.removeChild(a);
});
});
} else {
this.LocationService.setHref(this.config.api + "/" +
this.$scope.endpoint +
"?attachment=true&format=" + fileType +
"&size=" + this.$scope.size +
"&filters=" + JSON.stringify(filters));
}

modalInstance.result.then((data) => {
if (data.cancel) {
if (abort) {
abort.resolve();
} else {
this.LocationService.setHref(url);
}
}
});
}

}

class ExportTableModalController {

/* @ngInject */
constructor(private $modalInstance) {}
cancel(): void {
this.$modalInstance.close({
cancel: true
});
}
}

angular.module("tables.controllers", ["location.services"])
.controller("TableSortController", TableSortController)
.controller("GDCTableController", GDCTableController)
.controller("ExportTableModalController", ExportTableModalController)
.controller("ExportTableController", ExportTableController);
}

8 changes: 8 additions & 0 deletions app/scripts/components/tables/templates/export-modal.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div class="modal-body">
<h4>Generating File ...</h4>
</div>
<div class="modal-footer">
<button class="btn btn-warning" ng-click="etmc.cancel()" data-translate>
Cancel the Download
</button>
</div>
6 changes: 5 additions & 1 deletion app/scripts/core/core.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ module ngApp.core.controllers {

this.$rootScope.undoClicked = (action: string): void => {
this.$rootScope.$broadcast("undo", action);
}
};

this.$rootScope.cancelRequest = (): void => {
this.$rootScope.$broadcast("gdc-cancel-request");
};

}

Expand Down
18 changes: 16 additions & 2 deletions app/scripts/files/files.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module ngApp.files.services {
import IFile = ngApp.files.models.IFile;
import ILocationService = ngApp.components.location.services.ILocationService;
import IUserService = ngApp.components.user.services.IUserService;
import IRootScope = ngApp.IRootScope;

export interface IFilesService {
getFile(id: string, params: Object): ng.IPromise<IFile>;
Expand All @@ -15,7 +16,8 @@ module ngApp.files.services {

/* @ngInject */
constructor(Restangular: restangular.IService, private LocationService: ILocationService,
private UserService: IUserService, private CoreService: ICoreService) {
private UserService: IUserService, private CoreService: ICoreService,
private $rootScope: IRootScope, private $q: ng.IQService) {
this.ds = Restangular.all("files");
}

Expand Down Expand Up @@ -57,10 +59,22 @@ module ngApp.files.services {
defaults.filters = this.UserService.addMyProjectsFilter(defaults.filters, "participants.admin.disease_code");
this.CoreService.setSearchModelState(false);

return this.ds.get("", angular.extend(defaults, params)).then((response): IFiles => {
var abort = this.$q.defer();
var prom: ng.IPromise<IFiles> = this.ds.withHttpConfig({
timeout: abort.promise
})
.get("", angular.extend(defaults, params)).then((response): IFiles => {
this.CoreService.setSearchModelState(true);
return response["data"];
});

var eventCancel = this.$rootScope.$on("gdc-cancel-request", () => {
abort.resolve();
eventCancel();
this.CoreService.setSearchModelState(true);
});

return prom;
}
}

Expand Down
18 changes: 16 additions & 2 deletions app/scripts/participant/participants.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module ngApp.participants.services {
import IParticipant = ngApp.participants.models.IParticipant;
import ILocationService = ngApp.components.location.services.ILocationService;
import IUserService = ngApp.components.user.services.IUserService;
import IRootScope = ngApp.IRootScope;

export interface IParticipantsService {
getParticipant(id: string, params: Object): ng.IPromise<IParticipant>;
Expand All @@ -15,7 +16,8 @@ module ngApp.participants.services {

/* @ngInject */
constructor(Restangular: restangular.IService, private LocationService: ILocationService,
private UserService: IUserService, private CoreService: ICoreService) {
private UserService: IUserService, private CoreService: ICoreService,
private $rootScope: IRootScope, private $q: ng.IQService) {
this.ds = Restangular.all("participants");
}

Expand Down Expand Up @@ -56,10 +58,22 @@ module ngApp.participants.services {
defaults.filters = this.UserService.addMyProjectsFilter(defaults.filters, "participants.admin.disease_code");
this.CoreService.setSearchModelState(false);

return this.ds.get("", angular.extend(defaults, params)).then((response): IParticipants => {
var abort = this.$q.defer();
var prom: ng.IPromise<IParticipants> = this.ds.withHttpConfig({
timeout: abort.promise
})
.get("", angular.extend(defaults, params)).then((response): IParticipants => {
this.CoreService.setSearchModelState(true);
return response["data"];
});

var eventCancel = this.$rootScope.$on("gdc-cancel-request", () => {
abort.resolve();
eventCancel();
this.CoreService.setSearchModelState(true);
});

return prom;
}
}

Expand Down
21 changes: 19 additions & 2 deletions app/scripts/projects/projects.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ module ngApp.projects.services {
import IProjects = ngApp.projects.models.IProjects;
import ILocationService = ngApp.components.location.services.ILocationService;
import IUserService = ngApp.components.user.services.IUserService;
import ICoreService = ngApp.core.services.ICoreService;
import IRootScope = ngApp.IRootScope;

export interface IProjectsService {
getProject(id: string, params?: Object): ng.IPromise<IProject>;
Expand All @@ -14,7 +16,8 @@ module ngApp.projects.services {

/* @ngInject */
constructor(Restangular: restangular.IService, private LocationService: ILocationService,
private UserService: IUserService) {
private UserService: IUserService, private CoreService: ICoreService,
private $rootScope: IRootScope, private $q: ng.IQService) {
this.ds = Restangular.all("projects");
}

Expand Down Expand Up @@ -70,14 +73,28 @@ module ngApp.projects.services {
};

defaults.filters = this.UserService.addMyProjectsFilter(defaults.filters, "project_code");
this.CoreService.setSearchModelState(false);

return this.ds.get("", angular.extend(defaults, params)).then((response): IProjects => {
var abort = this.$q.defer();
var prom: ng.IPromise<IProjects> = this.ds.withHttpConfig({
timeout: abort.promise
})
.get("", angular.extend(defaults, params)).then((response): IFiles => {
var outer_class = this;
_.forEach(response["data"]["hits"], function(hit) {
hit = outer_class.crunch_summary(hit);
});
this.CoreService.setSearchModelState(true);
return response["data"];
});

var eventCancel = this.$rootScope.$on("gdc-cancel-request", () => {
abort.resolve();
eventCancel();
this.CoreService.setSearchModelState(true);
});

return prom;
}
}

Expand Down
3 changes: 0 additions & 3 deletions app/scripts/query/templates/query.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
<div class="container-fluid full-page">
<div class="row search-panel">
<div class="col-lg-12">
<div data-ng-if="!modelLoaded" class="app-loading table-loader">
<i class="fa fa-spinner fa-spin fa-5x"></i>
</div>

<search-bar></search-bar>

Expand Down
3 changes: 0 additions & 3 deletions app/scripts/search/templates/search.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@
</tabset>
</div>
<div class="col-lg-9 col-md-8">
<div data-ng-if="!modelLoaded" class="app-loading table-loader">
<i class="fa fa-spinner fa-spin fa-5x"></i>
</div>

<div class="alert alert-info clearfix">
<div class="col-lg-10 col-md-10">
Expand Down
1 change: 1 addition & 0 deletions app/styles/utils.less
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
vertical-align: bottom;
height: 100px;
width: 100px;
cursor: pointer;
}

&.ng-enter,
Expand Down

0 comments on commit f0f8e2f

Please sign in to comment.