-
Notifications
You must be signed in to change notification settings - Fork 194
/
app.js
248 lines (214 loc) · 8.91 KB
/
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
'use strict';
var addAnalytics = require('./ga');
var getApiUrl = require('./get-api-url');
var serviceConfig = require('./service-config');
require('../shared/polyfills');
var raven;
// Read settings rendered into sidebar app HTML by service/extension.
var settings = require('../shared/settings').jsonConfigsFrom(document);
if (settings.raven) {
// Initialize Raven. This is required at the top of this file
// so that it happens early in the app's startup flow
raven = require('./raven');
raven.init(settings.raven);
}
var hostPageConfig = require('./host-config');
Object.assign(settings, hostPageConfig(window));
settings.apiUrl = getApiUrl(settings);
// Disable Angular features that are not compatible with CSP.
//
// See https://docs.angularjs.org/api/ng/directive/ngCsp
//
// The `ng-csp` attribute must be set on some HTML element in the document
// _before_ Angular is require'd for the first time.
document.body.setAttribute('ng-csp', '');
var angular = require('angular');
// autofill-event relies on the existence of window.angular so
// it must be require'd after angular is first require'd
require('autofill-event');
// Setup Angular integration for Raven
if (settings.raven) {
raven.angularModule(angular);
} else {
angular.module('ngRaven', []);
}
if(settings.googleAnalytics){
addAnalytics(settings.googleAnalytics);
}
// Fetch external state that the app needs before it can run. This includes the
// authenticated user state, the API endpoint URLs and WebSocket connection.
var resolve = {
// @ngInject
sessionState: function (session) {
return session.load();
},
};
// @ngInject
function configureLocation($locationProvider) {
// Use HTML5 history
return $locationProvider.html5Mode(true);
}
// @ngInject
function configureRoutes($routeProvider) {
// The `vm.{auth,search}` properties used in these templates come from the
// `<hypothesis-app>` component which hosts the router's container element.
$routeProvider.when('/a/:id',
{
template: '<annotation-viewer-content search="vm.search"></annotation-viewer-content>',
reloadOnSearch: false,
resolve: resolve,
});
$routeProvider.when('/stream',
{
template: '<stream-content search="vm.search"></stream-content>',
reloadOnSearch: false,
resolve: resolve,
});
$routeProvider.otherwise({
template: '<sidebar-content search="vm.search" auth="vm.auth"></sidebar-content>',
reloadOnSearch: false,
resolve: resolve,
});
}
// @ngInject
function configureToastr(toastrConfig) {
angular.extend(toastrConfig, {
preventOpenDuplicates: true,
});
}
// @ngInject
function configureHttp($httpProvider) {
// Use the Pyramid XSRF header name
$httpProvider.defaults.xsrfHeaderName = 'X-CSRF-Token';
}
// @ngInject
function setupHttp($http, streamer) {
$http.defaults.headers.common['X-Client-Id'] = streamer.clientId;
}
function processAppOpts() {
if (settings.liveReloadServer) {
require('./live-reload-client').connect(settings.liveReloadServer);
}
}
function shouldUseOAuth() {
if (serviceConfig(settings)) {
return true;
}
return settings.oauthClientId && settings.oauthEnabled;
}
var authService;
if (shouldUseOAuth()) {
authService = require('./oauth-auth');
} else {
authService = require('./auth');
}
module.exports = angular.module('h', [
// Angular addons which export the Angular module name
// via module.exports
require('angular-jwt'),
require('angular-resource'),
require('angular-route'),
require('angular-sanitize'),
require('angular-toastr'),
// Angular addons which do not export the Angular module
// name via module.exports
['angulartics', require('angulartics')][0],
['angulartics.google.analytics', require('angulartics/src/angulartics-ga')][0],
['ngTagsInput', require('ng-tags-input')][0],
['ui.bootstrap', require('./vendor/ui-bootstrap-custom-tpls-0.13.4')][0],
// Local addons
'ngRaven',
])
// The root component for the application
.component('hypothesisApp', require('./components/hypothesis-app'))
// UI components
.component('annotation', require('./components/annotation'))
.component('annotationHeader', require('./components/annotation-header'))
.component('annotationActionButton', require('./components/annotation-action-button'))
.component('annotationShareDialog', require('./components/annotation-share-dialog'))
.component('annotationThread', require('./components/annotation-thread'))
.component('annotationViewerContent', require('./components/annotation-viewer-content'))
.component('dropdownMenuBtn', require('./components/dropdown-menu-btn'))
.component('excerpt', require('./components/excerpt'))
.component('groupList', require('./components/group-list'))
.component('helpLink', require('./components/help-link'))
.component('helpPanel', require('./components/help-panel'))
.component('loggedoutMessage', require('./components/loggedout-message'))
.component('loginControl', require('./components/login-control'))
.component('loginForm', require('./components/login-form'))
.component('markdown', require('./components/markdown'))
.component('moderationBanner', require('./components/moderation-banner'))
.component('publishAnnotationBtn', require('./components/publish-annotation-btn'))
.component('searchInput', require('./components/search-input'))
.component('searchStatusBar', require('./components/search-status-bar'))
.component('selectionTabs', require('./components/selection-tabs'))
.component('sidebarContent', require('./components/sidebar-content'))
.component('sidebarTutorial', require('./components/sidebar-tutorial'))
.component('shareDialog', require('./components/share-dialog'))
.component('sortDropdown', require('./components/sort-dropdown'))
.component('streamContent', require('./components/stream-content'))
.component('svgIcon', require('./components/svg-icon'))
.component('tagEditor', require('./components/tag-editor'))
.component('threadList', require('./components/thread-list'))
.component('timestamp', require('./components/timestamp'))
.component('topBar', require('./components/top-bar'))
.directive('formInput', require('./directive/form-input'))
.directive('formValidate', require('./directive/form-validate'))
.directive('hAutofocus', require('./directive/h-autofocus'))
.directive('hBranding', require('./directive/h-branding'))
.directive('hOnTouch', require('./directive/h-on-touch'))
.directive('hTooltip', require('./directive/h-tooltip'))
.directive('spinner', require('./directive/spinner'))
.directive('statusButton', require('./directive/status-button'))
.directive('windowScroll', require('./directive/window-scroll'))
.service('analytics', require('./analytics'))
.service('annotationMapper', require('./annotation-mapper'))
.service('annotationUI', require('./annotation-ui'))
.service('auth', authService)
.service('bridge', require('../shared/bridge'))
.service('drafts', require('./drafts'))
.service('features', require('./features'))
.service('flash', require('./flash'))
.service('formRespond', require('./form-respond'))
.service('frameSync', require('./frame-sync').default)
.service('groups', require('./groups'))
.service('localStorage', require('./local-storage'))
.service('permissions', require('./permissions'))
.service('queryParser', require('./query-parser'))
.service('rootThread', require('./root-thread'))
.service('searchFilter', require('./search-filter'))
.service('serviceUrl', require('./service-url'))
.service('session', require('./session'))
.service('streamer', require('./streamer'))
.service('streamFilter', require('./stream-filter'))
.service('tags', require('./tags'))
.service('unicode', require('./unicode'))
.service('viewFilter', require('./view-filter'))
.factory('store', require('./store'))
.value('Discovery', require('../shared/discovery'))
.value('ExcerptOverflowMonitor', require('./util/excerpt-overflow-monitor'))
.value('VirtualThreadList', require('./virtual-thread-list'))
.value('random', require('./util/random'))
.value('raven', require('./raven'))
.value('serviceConfig', serviceConfig)
.value('settings', settings)
.value('time', require('./time'))
.value('urlEncodeFilter', require('./filter/url').encode)
.config(configureHttp)
.config(configureLocation)
.config(configureRoutes)
.config(configureToastr)
.run(setupHttp);
processAppOpts();
// Work around a check in Angular's $sniffer service that causes it to
// incorrectly determine that Firefox extensions are Chrome Packaged Apps which
// do not support the HTML 5 History API. This results Angular redirecting the
// browser on startup and thus the app fails to load.
// See https://github.com/angular/angular.js/blob/a03b75c6a812fcc2f616fc05c0f1710e03fca8e9/src/ng/sniffer.js#L30
if (window.chrome && !window.chrome.app) {
window.chrome.app = {
dummyAddedByHypothesisClient: true,
};
}
var appEl = document.querySelector('hypothesis-app');
angular.bootstrap(appEl, ['h'], {strictDi: true});