using decorators to write AngularJS in nearly identical syntax to Angular 2
This commit is contained in:
parent
8e863b8cf5
commit
c60ce4a696
19 changed files with 559 additions and 488 deletions
|
@ -1,16 +1,15 @@
|
|||
import * as angular from 'angular';
|
||||
import { quayConfig } from './quay.config';
|
||||
import quayPages from './quay-pages.module';
|
||||
import quayRun from './quay.run';
|
||||
import { ViewArrayImpl } from './services/view-array/view-array.impl';
|
||||
import NAME_PATTERNS from './constants/name-patterns.constant';
|
||||
import { routeConfig } from './quay.routes';
|
||||
import { INJECTED_CONFIG, INJECTED_FEATURES, INJECTED_ENDPOINTS } from './constants/injected-values.constant';
|
||||
import * as angular from "angular";
|
||||
import * as Raven from "raven-js";
|
||||
import { ViewArrayImpl } from "./services/view-array/view-array.impl";
|
||||
import { NAME_PATTERNS } from "./constants/name-patterns.constant";
|
||||
import { INJECTED_CONFIG, INJECTED_FEATURES, INJECTED_ENDPOINTS } from "./constants/injected-values.constant";
|
||||
import { RegexMatchViewComponent } from "./directives/ui/regex-match-view/regex-match-view.component";
|
||||
import { NgModule } from "angular-ts-decorators";
|
||||
import { QuayRoutes } from "./quay-routes.module";
|
||||
|
||||
|
||||
var quayDependencies: string[] = [
|
||||
quayPages,
|
||||
'ngRoute',
|
||||
var quayDependencies: any[] = [
|
||||
QuayRoutes,
|
||||
'chieffancypants.loadingBar',
|
||||
'cfp.hotkeys',
|
||||
'angular-tour',
|
||||
|
@ -46,14 +45,198 @@ if (INJECTED_CONFIG && INJECTED_CONFIG.RECAPTCHA_SITE_KEY) {
|
|||
quayDependencies.push('vcRecaptcha');
|
||||
}
|
||||
|
||||
export default angular
|
||||
.module('quay', quayDependencies)
|
||||
.config(quayConfig)
|
||||
.config(routeConfig)
|
||||
|
||||
/**
|
||||
* Main application module.
|
||||
*/
|
||||
@NgModule({
|
||||
imports: quayDependencies,
|
||||
declarations: [
|
||||
RegexMatchViewComponent,
|
||||
],
|
||||
providers: [
|
||||
ViewArrayImpl,
|
||||
],
|
||||
})
|
||||
export class quay {
|
||||
|
||||
public config($provide: ng.auto.IProvideService,
|
||||
$injector: ng.auto.IInjectorService,
|
||||
INJECTED_CONFIG: any,
|
||||
cfpLoadingBarProvider: any,
|
||||
$tooltipProvider: any,
|
||||
$compileProvider: ng.ICompileProvider,
|
||||
RestangularProvider: any): void {
|
||||
cfpLoadingBarProvider.includeSpinner = false;
|
||||
|
||||
// decorate the tooltip getter
|
||||
var tooltipFactory: any = $tooltipProvider.$get[$tooltipProvider.$get.length - 1];
|
||||
$tooltipProvider.$get[$tooltipProvider.$get.length - 1] = function($window: ng.IWindowService) {
|
||||
if ('ontouchstart' in $window) {
|
||||
var existing: any = tooltipFactory.apply(this, arguments);
|
||||
return function(element) {
|
||||
// Note: We only disable bs-tooltip's themselves. $tooltip is used for other things
|
||||
// (such as the datepicker), so we need to be specific when canceling it.
|
||||
if (element !== undefined && element.attr('bs-tooltip') == null) {
|
||||
return existing.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return tooltipFactory.apply(this, arguments);
|
||||
};
|
||||
|
||||
if (!INJECTED_CONFIG['DEBUG']) {
|
||||
$compileProvider.debugInfoEnabled(false);
|
||||
}
|
||||
|
||||
// Configure compile provider to add additional URL prefixes to the sanitization list. We use
|
||||
// these on the Contact page.
|
||||
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|irc):/);
|
||||
|
||||
// Configure the API provider.
|
||||
RestangularProvider.setBaseUrl('/api/v1/');
|
||||
|
||||
// Configure analytics.
|
||||
if (INJECTED_CONFIG && INJECTED_CONFIG.MIXPANEL_KEY) {
|
||||
let $analyticsProvider: any = $injector.get('$analyticsProvider');
|
||||
$analyticsProvider.virtualPageviews(true);
|
||||
}
|
||||
|
||||
// Configure sentry.
|
||||
if (INJECTED_CONFIG && INJECTED_CONFIG.SENTRY_PUBLIC_DSN) {
|
||||
$provide.decorator("$exceptionHandler", function($delegate) {
|
||||
return function(ex, cause) {
|
||||
$delegate(ex, cause);
|
||||
Raven.captureException(ex, {extra: {cause: cause}});
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public run($rootScope: QuayRunScope,
|
||||
Restangular: any,
|
||||
PlanService: any,
|
||||
$http: ng.IHttpService,
|
||||
CookieService: any,
|
||||
Features: any,
|
||||
$anchorScroll: ng.IAnchorScrollService,
|
||||
MetaService: any,
|
||||
INJECTED_CONFIG: any): void {
|
||||
var defaultTitle = INJECTED_CONFIG['REGISTRY_TITLE'] || 'Quay Container Registry';
|
||||
|
||||
// Handle session security.
|
||||
Restangular.setDefaultRequestParams(['post', 'put', 'remove', 'delete'],
|
||||
{'_csrf_token': (<any>window).__token || ''});
|
||||
|
||||
// Handle session expiration.
|
||||
Restangular.setErrorInterceptor(function(response) {
|
||||
if (response !== undefined && response.status == 503) {
|
||||
(<any>$('#cannotContactService')).modal({});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response !== undefined && response.status == 500) {
|
||||
window.location.href = '/500';
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response !== undefined && !response.data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var invalid_token = response.data['title'] == 'invalid_token' || response.data['error_type'] == 'invalid_token';
|
||||
if (response !== undefined && response.status == 401 &&
|
||||
invalid_token &&
|
||||
response.data['session_required'] !== false) {
|
||||
(<any>$('#sessionexpiredModal')).modal({});
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// Check if we need to redirect based on a previously chosen plan.
|
||||
var result = PlanService.handleNotedPlan();
|
||||
|
||||
// Check to see if we need to show a redirection page.
|
||||
var redirectUrl = CookieService.get('quay.redirectAfterLoad');
|
||||
CookieService.clear('quay.redirectAfterLoad');
|
||||
|
||||
if (!result && redirectUrl && redirectUrl.indexOf((<any>window).location.href) == 0) {
|
||||
(<any>window).location = redirectUrl;
|
||||
return;
|
||||
}
|
||||
|
||||
$rootScope.$watch('description', function(description: string) {
|
||||
if (!description) {
|
||||
description = `Hosted private docker repositories. Includes full user management and history.
|
||||
Free for public repositories.`;
|
||||
}
|
||||
|
||||
// Note: We set the content of the description tag manually here rather than using Angular binding
|
||||
// because we need the <meta> tag to have a default description that is not of the form "{{ description }}",
|
||||
// we read by tools that do not properly invoke the Angular code.
|
||||
$('#descriptionTag').attr('content', description);
|
||||
});
|
||||
|
||||
// Listen for scope changes and update the title and description accordingly.
|
||||
$rootScope.$watch(function() {
|
||||
var title = MetaService.getTitle($rootScope.currentPage) || defaultTitle;
|
||||
$rootScope.title = title;
|
||||
|
||||
var description = MetaService.getDescription($rootScope.currentPage) || '';
|
||||
if ($rootScope.description != description) {
|
||||
$rootScope.description = description;
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.$on('$routeChangeSuccess', function (event, current, previous) {
|
||||
$rootScope.current = current.$$route;
|
||||
$rootScope.currentPage = current;
|
||||
$rootScope.pageClass = '';
|
||||
|
||||
if (!current.$$route) { return; }
|
||||
|
||||
var pageClass = current.$$route.pageClass || '';
|
||||
if (typeof pageClass != 'string') {
|
||||
pageClass = pageClass(Features);
|
||||
}
|
||||
|
||||
$rootScope.pageClass = pageClass;
|
||||
$rootScope.newLayout = !!current.$$route.newLayout;
|
||||
$rootScope.fixFooter = !!current.$$route.fixFooter;
|
||||
|
||||
$anchorScroll();
|
||||
});
|
||||
|
||||
var initallyChecked: boolean = false;
|
||||
(<any>window).__isLoading = function() {
|
||||
if (!initallyChecked) {
|
||||
initallyChecked = true;
|
||||
return true;
|
||||
}
|
||||
return $http.pendingRequests.length > 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface QuayRunScope extends ng.IRootScopeService {
|
||||
currentPage: any;
|
||||
current: any;
|
||||
title: any;
|
||||
description: string,
|
||||
pageClass: any;
|
||||
newLayout: any;
|
||||
fixFooter: any;
|
||||
}
|
||||
|
||||
|
||||
// TODO: Move component registration to @NgModule and remove this.
|
||||
angular
|
||||
.module(quay.name)
|
||||
.constant('NAME_PATTERNS', NAME_PATTERNS)
|
||||
.constant('INJECTED_CONFIG', INJECTED_CONFIG)
|
||||
.constant('INJECTED_FEATURES', INJECTED_FEATURES)
|
||||
.constant('INJECTED_ENDPOINTS', INJECTED_ENDPOINTS)
|
||||
.service('ViewArray', ViewArrayImpl)
|
||||
.run(quayRun)
|
||||
.name;
|
||||
.constant('INJECTED_ENDPOINTS', INJECTED_ENDPOINTS);
|
||||
|
|
Reference in a new issue