##// END OF EJS Templates
frontend: Use Polymer 2.0
ergo -
r2915:59bfd308 default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,17 +1,17 b''
1 1 {
2 2 "name": "rhodecode-elements",
3 3 "description": "User interface for elements for rhodecode",
4 4 "main": "index.html",
5 5 "dependencies": {
6 "webcomponentsjs": "^0.7.22",
7 "polymer": "Polymer/polymer#^1.6.1",
8 "paper-button": "PolymerElements/paper-button#^1.0.13",
9 "paper-spinner": "PolymerElements/paper-spinner#^1.2.0",
10 "paper-tooltip": "PolymerElements/paper-tooltip#^1.1.2",
11 "paper-toast": "PolymerElements/paper-toast#^1.3.0",
12 "paper-toggle-button": "PolymerElements/paper-toggle-button#^1.2.0",
13 "iron-ajax": "PolymerElements/iron-ajax#^1.4.4",
14 "iron-autogrow-textarea": "PolymerElements/iron-autogrow-textarea#^1.0.13",
15 "iron-a11y-keys": "PolymerElements/iron-a11y-keys#^1.0.6"
6 "webcomponentsjs": "^1.2.3",
7 "polymer": "Polymer/polymer#^2.6.0",
8 "paper-button": "PolymerElements/paper-button#^2.1.2",
9 "paper-spinner": "PolymerElements/paper-spinner#^2.1.0",
10 "paper-tooltip": "PolymerElements/paper-tooltip#^2.1.1",
11 "paper-toast": "PolymerElements/paper-toast#^2.1.2",
12 "paper-toggle-button": "PolymerElements/paper-toggle-button#^2.1.1",
13 "iron-ajax": "PolymerElements/iron-ajax#^2.1.3",
14 "iron-autogrow-textarea": "PolymerElements/iron-autogrow-textarea#^2.2.0",
15 "iron-a11y-keys": "PolymerElements/iron-a11y-keys#^2.1.2"
16 16 }
17 17 }
@@ -1,32 +1,32 b''
1 1 {
2 2 "name": "rhodecode-enterprise",
3 3 "version": "1.0.0",
4 4 "private": true,
5 5 "description" : "RhodeCode JS packaged",
6 6 "license": "SEE LICENSE IN LICENSE.txt",
7 7 "repository" : {
8 8 "type" : "hg",
9 9 "url" : "https://code.rhodecode.com/rhodecode-enterprise-ce"
10 10 },
11 11 "devDependencies": {
12 12 "grunt": "^0.4.5",
13 13 "grunt-contrib-copy": "^1.0.0",
14 14 "grunt-contrib-concat": "^0.5.1",
15 15 "grunt-contrib-jshint": "^0.12.0",
16 16 "grunt-contrib-less": "^1.1.0",
17 17 "grunt-contrib-watch": "^0.6.1",
18 "crisper": "^2.0.2",
19 "vulcanize": "^1.14.8",
18 "crisper": "^2.1.1",
19 "vulcanize": "^1.16.0",
20 20 "grunt-crisper": "^1.0.1",
21 21 "grunt-vulcanize": "^1.0.0",
22 22 "node2nix": "^1.0.0",
23 23 "jshint": "^2.9.1-rc3",
24 24 "bower": "^1.8.4",
25 25 "jquery": "1.11.3",
26 26 "favico.js": "^0.3.10",
27 27 "clipboard": "^1.7.1",
28 28 "moment": "^2.18.1",
29 29 "mousetrap": "^1.6.1",
30 30 "appenlight-client": "git+https://git@github.com/AppEnlight/appenlight-client-js.git#0.5.1"
31 31 }
32 32 }
@@ -1,150 +1,150 b''
1 1 ccLog = Logger.get('RhodeCodeApp');
2 2 ccLog.setLevel(Logger.OFF);
3 3
4 4 var rhodeCodeApp = Polymer({
5 5 is: 'rhodecode-app',
6 6 attached: function () {
7 7 ccLog.debug('rhodeCodeApp created');
8 8 $.Topic('/notifications').subscribe(this.handleNotifications.bind(this));
9 9 $.Topic('/favicon/update').subscribe(this.faviconUpdate.bind(this));
10 10 $.Topic('/connection_controller/subscribe').subscribe(
11 11 this.subscribeToChannelTopic.bind(this));
12 12 // this event can be used to coordinate plugins to do their
13 13 // initialization before channelstream is kicked off
14 14 $.Topic('/__MAIN_APP__').publish({});
15 15
16 16 for (var i = 0; i < alertMessagePayloads.length; i++) {
17 17 $.Topic('/notifications').publish(alertMessagePayloads[i]);
18 18 }
19 19 this.kickoffChannelstreamPlugin();
20 20 },
21 21
22 22 /** proxy to channelstream connection */
23 23 getChannelStreamConnection: function () {
24 24 return this.$['channelstream-connection'];
25 25 },
26 26
27 27 handleNotifications: function (data) {
28 28 var elem = document.getElementById('notifications');
29 29 if(elem){
30 30 elem.handleNotification(data);
31 31 }
32 32
33 33 },
34 34
35 35 faviconUpdate: function (data) {
36 this.$$('rhodecode-favicon').counter = data.count;
36 this.shadowRoot.querySelector('rhodecode-favicon').counter = data.count;
37 37 },
38 38
39 39 /** opens connection to ws server */
40 40 kickoffChannelstreamPlugin: function (data) {
41 41 ccLog.debug('kickoffChannelstreamPlugin');
42 42 var channels = ['broadcast'];
43 43 var addChannels = this.checkViewChannels();
44 44 for (var i = 0; i < addChannels.length; i++) {
45 45 channels.push(addChannels[i]);
46 46 }
47 47 if (window.CHANNELSTREAM_SETTINGS && CHANNELSTREAM_SETTINGS.enabled){
48 48 var channelstreamConnection = this.getChannelStreamConnection();
49 49 channelstreamConnection.connectUrl = CHANNELSTREAM_URLS.connect;
50 50 channelstreamConnection.subscribeUrl = CHANNELSTREAM_URLS.subscribe;
51 51 channelstreamConnection.websocketUrl = CHANNELSTREAM_URLS.ws + '/ws';
52 52 channelstreamConnection.longPollUrl = CHANNELSTREAM_URLS.longpoll + '/listen';
53 53 // some channels might already be registered by topic
54 54 for (var i = 0; i < channels.length; i++) {
55 55 channelstreamConnection.push('channels', channels[i]);
56 56 }
57 57 // append any additional channels registered in other plugins
58 58 $.Topic('/connection_controller/subscribe').processPrepared();
59 59 channelstreamConnection.connect();
60 60 }
61 61 },
62 62
63 63 checkViewChannels: function () {
64 64 // subscribe to different channels data is sent.
65 65
66 66 var channels = [];
67 67 // subscribe to PR repo channel for PR's'
68 68 if (templateContext.pull_request_data.pull_request_id) {
69 69 var channelName = '/repo$' + templateContext.repo_name + '$/pr/' +
70 70 String(templateContext.pull_request_data.pull_request_id);
71 71 channels.push(channelName);
72 72 }
73 73
74 74 if (templateContext.commit_data.commit_id) {
75 75 var channelName = '/repo$' + templateContext.repo_name + '$/commit/' +
76 76 String(templateContext.commit_data.commit_id);
77 77 channels.push(channelName);
78 78 }
79 79
80 80 return channels;
81 81 },
82 82
83 83 /** subscribes users from channels in channelstream */
84 84 subscribeToChannelTopic: function (channels) {
85 85 var channelstreamConnection = this.getChannelStreamConnection();
86 86 var toSubscribe = channelstreamConnection.calculateSubscribe(channels);
87 87 ccLog.debug('subscribeToChannelTopic', toSubscribe);
88 88 if (toSubscribe.length > 0) {
89 89 // if we are connected then subscribe
90 90 if (channelstreamConnection.connected) {
91 91 channelstreamConnection.subscribe(toSubscribe);
92 92 }
93 93 // not connected? just push channels onto the stack
94 94 else {
95 95 for (var i = 0; i < toSubscribe.length; i++) {
96 96 channelstreamConnection.push('channels', toSubscribe[i]);
97 97 }
98 98 }
99 99 }
100 100 },
101 101
102 102 /** publish received messages into correct topic */
103 103 receivedMessage: function (event) {
104 104 for (var i = 0; i < event.detail.length; i++) {
105 105 var message = event.detail[i];
106 106 if (message.message.topic) {
107 107 ccLog.debug('publishing', message.message.topic);
108 108 $.Topic(message.message.topic).publish(message);
109 109 }
110 110 else if (message.type === 'presence'){
111 111 $.Topic('/connection_controller/presence').publish(message);
112 112 }
113 113 else {
114 114 ccLog.warn('unhandled message', message);
115 115 }
116 116 }
117 117 },
118 118
119 119 handleConnected: function (event) {
120 120 var channelstreamConnection = this.getChannelStreamConnection();
121 121 channelstreamConnection.set('channelsState',
122 122 event.detail.channels_info);
123 123 channelstreamConnection.set('userState', event.detail.state);
124 124 channelstreamConnection.set('channels', event.detail.channels);
125 125 this.propagageChannelsState();
126 126 },
127 127 handleSubscribed: function (event) {
128 128 var channelstreamConnection = this.getChannelStreamConnection();
129 129 var channelInfo = event.detail.channels_info;
130 130 var channelKeys = Object.keys(event.detail.channels_info);
131 131 for (var i = 0; i < channelKeys.length; i++) {
132 132 var key = channelKeys[i];
133 133 channelstreamConnection.set(['channelsState', key], channelInfo[key]);
134 134 }
135 135 channelstreamConnection.set('channels', event.detail.channels);
136 136 this.propagageChannelsState();
137 137 },
138 138 /** propagates channel states on topics */
139 139 propagageChannelsState: function (event) {
140 140 var channelstreamConnection = this.getChannelStreamConnection();
141 141 var channel_data = channelstreamConnection.channelsState;
142 142 var channels = channelstreamConnection.channels;
143 143 for (var i = 0; i < channels.length; i++) {
144 144 var key = channels[i];
145 145 $.Topic('/connection_controller/channel_update').publish(
146 146 {channel: key, state: channel_data[key]}
147 147 );
148 148 }
149 149 }
150 150 });
@@ -1,24 +1,23 b''
1 1 <link rel="import" href="../../../../../../bower_components/paper-button/paper-button.html">
2 <link rel="import" href="../../../../../../bower_components/paper-toast/paper-toast.html">
3 2 <link rel="import" href="../../../../../../bower_components/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
4 3 <link rel="import" href="../rhodecode-unsafe-html/rhodecode-unsafe-html.html">
5 4 <dom-module id="rhodecode-toast">
6 5 <template>
7 6 <style include="shared-styles"></style>
8 7 <link rel="stylesheet" href="rhodecode-toast.css">
9 8 <template is="dom-if" if="[[hasToasts]]">
10 9 <div class$="container toast-message-holder [[conditionalClass(isFixed)]]">
11 10 <template is="dom-repeat" items="[[toasts]]">
12 11 <div class$="alert alert-[[item.level]]">
13 12 <div on-tap="dismissNotification" class="toast-close" index-pos="[[index]]">
14 13 <span>[[_gettext('Close')]]</span>
15 14 </div>
16 15 <rhodecode-unsafe-html text="[[item.message]]"></rhodecode-unsafe-html>
17 16 </div>
18 17 </template>
19 18 </div>
20 19 </template>
21 20 </template>
22 21
23 22 <script src="rhodecode-toast.js"></script>
24 23 </dom-module>
@@ -1,9 +1,9 b''
1 1 <link rel="import" href="../../../../../../bower_components/polymer/polymer.html">
2 2
3 3 <dom-module id="rhodecode-unsafe-html">
4 4 <template>
5 5 <style include="shared-styles"></style>
6 <content></content>
6 <slot></slot>
7 7 </template>
8 8 <script src="rhodecode-unsafe-html.js"></script>
9 9 </dom-module>
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,130 +1,133 b''
1 <template is="dom-bind" id="notificationsPage">
1 <dom-bind id="notificationsPage">
2 <template>
2 3 <iron-ajax id="toggleNotifications"
3 4 method="post"
4 5 url="${h.route_path('my_account_notifications_toggle_visibility')}"
5 6 content-type="application/json"
6 7 loading="{{changeNotificationsLoading}}"
7 8 on-response="handleNotifications"
8 9 handle-as="json">
9 10 </iron-ajax>
10 11
11 12 <iron-ajax id="sendTestNotification"
12 13 method="post"
13 14 url="${h.route_path('my_account_notifications_test_channelstream')}"
14 15 content-type="application/json"
15 16 on-response="handleTestNotification"
16 17 handle-as="json">
17 18 </iron-ajax>
18 19
19 20 <div class="panel panel-default">
20 21 <div class="panel-heading">
21 22 <h3 class="panel-title">${_('Your Live Notification Settings')}</h3>
22 23 </div>
23 24 <div class="panel-body">
24 25
25 26 <p><strong>IMPORTANT:</strong> This feature requires enabled channelstream websocket server to function correctly.</p>
26 27
27 28 <p class="hidden">Status of browser notifications permission: <strong id="browser-notification-status"></strong></p>
28 29
29 30 <div class="form">
30 31 <div class="fields">
31 32 <div class="field">
32 33 <div class="label">
33 34 <label for="new_email">${_('Notifications Status')}:</label>
34 35 </div>
35 36 <div class="checkboxes">
36 37 <rhodecode-toggle id="live-notifications" active="[[changeNotificationsLoading]]" on-change="toggleNotifications" ${'checked' if c.rhodecode_user.get_instance().user_data.get('notification_status') else ''}></rhodecode-toggle>
37 38 </div>
38 39 </div>
39 40 </div>
40 41 </div>
41 42 </div>
42 43 </div>
43 44
44 45 <div class="panel panel-default">
45 46 <div class="panel-heading">
46 47 <h3 class="panel-title">${_('Test Notifications')}</h3>
47 48 </div>
48 49 <div class="panel-body">
49 50
50 51
51 52 <div style="padding: 0px 0px 20px 0px">
52 53 <button class="btn" id="test-notification" on-tap="testNotifications">Test flash message</button>
53 54 <button class="btn" id="test-notification-live" on-tap="testNotificationsLive">Test live notification</button>
54 55 </div>
55 56 <h4 id="test-response"></h4>
56 57
57 58 </div>
58 59
59 60
60 61
61 62 </div>
62 63
64
65 </template>
66 </dom-bind>
67
63 68 <script type="text/javascript">
64 69 /** because im not creating a custom element for this page
65 70 * we need to push the function onto the dom-template
66 71 * ideally we turn this into notification-settings elements
67 72 * then it will be cleaner
68 73 */
69 74 var ctrlr = $('#notificationsPage')[0];
70 75 ctrlr.toggleNotifications = function(event){
71 76 var ajax = $('#toggleNotifications')[0];
72 77 ajax.headers = {"X-CSRF-Token": CSRF_TOKEN};
73 78 ajax.body = {notification_status:event.target.active};
74 79 ajax.generateRequest();
75 80 };
76 81 ctrlr.handleNotifications = function(event){
77 82 $('#live-notifications')[0].checked = event.detail.response;
78 83 };
79 84
80 85 ctrlr.testNotifications = function(event){
81 86 var levels = ['info', 'error', 'warning', 'success'];
82 87 var level = levels[Math.floor(Math.random()*levels.length)];
83 88 function getRandomArbitrary(min, max) {
84 return parseInt(Math.random() * (max - min) + min);
89 return parseInt(Math.random() * (max - min) + min);
85 90 }
86 91 function shuffle(a) {
87 92 var j, x, i;
88 93 for (i = a.length; i; i--) {
89 94 j = Math.floor(Math.random() * i);
90 95 x = a[i - 1];
91 96 a[i - 1] = a[j];
92 97 a[j] = x;
93 98 }
94 99 }
95 100 var wordDb = [
96 101 "Leela,", "Bender,", "we are", "going", "grave", "robbing.",
97 102 "Oh,", "I", "think", "we", "should", "just", "stay", "friends.",
98 103 "got", "to", "find", "a", "way", "to", "escape", "the", "horrible",
99 104 "ravages", "of", "youth.", "Suddenly,", "going", "to",
100 105 "the", "bathroom", "like", "clockwork,", "every", "three",
101 106 "hours.", "And", "those", "jerks", "at", "Social", "Security",
102 107 "stopped", "sending", "me", "checks.", "Now", "have", "to", "pay"
103 108 ];
104 109 shuffle(wordDb);
105 110 wordDb = wordDb.slice(0, getRandomArbitrary(3, wordDb.length));
106 111 var randomMessage = wordDb.join(" ");
107 112 var payload = {
108 113 message: {
109 114 message: randomMessage + " " + new Date(),
110 115 level: level,
111 116 force: true
112 117 }
113 118 };
114 119 $.Topic('/notifications').publish(payload);
115 120 };
116 121 ctrlr.testNotificationsLive = function(event){
117 122 var ajax = $('#sendTestNotification')[0];
118 123 ajax.headers = {"X-CSRF-Token": CSRF_TOKEN};
119 124 ajax.body = {test_msg: 'Hello !'};
120 125 ajax.generateRequest();
121 126 };
122 127 ctrlr.handleTestNotification = function(event){
123 128 var reply = event.detail.response.response;
124 129 reply = reply || 'no reply form server';
125 130 $('#test-response').html(reply);
126 131 };
127 132
128 133 </script>
129
130 </template>
@@ -1,188 +1,161 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <!DOCTYPE html>
3 3
4 4 <%
5 5 c.template_context['repo_name'] = getattr(c, 'repo_name', '')
6 6 go_import_header = ''
7 7 if hasattr(c, 'rhodecode_db_repo'):
8 8 c.template_context['repo_type'] = c.rhodecode_db_repo.repo_type
9 9 c.template_context['repo_landing_commit'] = c.rhodecode_db_repo.landing_rev[1]
10 10
11 11 if getattr(c, 'repo_group', None):
12 12 c.template_context['repo_group_id'] = c.repo_group.group_id
13 13
14 14 if getattr(c, 'rhodecode_user', None) and c.rhodecode_user.user_id:
15 15 c.template_context['rhodecode_user']['username'] = c.rhodecode_user.username
16 16 c.template_context['rhodecode_user']['email'] = c.rhodecode_user.email
17 17 c.template_context['rhodecode_user']['notification_status'] = c.rhodecode_user.get_instance().user_data.get('notification_status', True)
18 18 c.template_context['rhodecode_user']['first_name'] = c.rhodecode_user.first_name
19 19 c.template_context['rhodecode_user']['last_name'] = c.rhodecode_user.last_name
20 20
21 21 c.template_context['visual']['default_renderer'] = h.get_visual_attr(c, 'default_renderer')
22 22 c.template_context['default_user'] = {
23 23 'username': h.DEFAULT_USER,
24 24 'user_id': 1
25 25 }
26 26
27 27 %>
28 28 <html xmlns="http://www.w3.org/1999/xhtml">
29 29 <head>
30 <script src="${h.asset('js/vendors/webcomponentsjs/webcomponents-lite.min.js', ver=c.rhodecode_version_hash)}"></script>
30 <script src="${h.asset('js/vendors/webcomponentsjs/webcomponents-lite.js', ver=c.rhodecode_version_hash)}"></script>
31 31 <link rel="import" href="${h.asset('js/rhodecode-components.html', ver=c.rhodecode_version_hash)}">
32 32 <title>${self.title()}</title>
33 33 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
34 34
35 35 ${h.go_import_header(request, getattr(c, 'rhodecode_db_repo', None))}
36 36
37 37 % if 'safari' in (request.user_agent or '').lower():
38 38 <meta name="referrer" content="origin">
39 39 % else:
40 40 <meta name="referrer" content="origin-when-cross-origin">
41 41 % endif
42 42
43 43 <%def name="robots()">
44 44 <meta name="robots" content="index, nofollow"/>
45 45 </%def>
46 46 ${self.robots()}
47 47 <link rel="icon" href="${h.asset('images/favicon.ico', ver=c.rhodecode_version_hash)}" sizes="16x16 32x32" type="image/png" />
48 48
49 49 ## CSS definitions
50 50 <%def name="css()">
51 51 <link rel="stylesheet" type="text/css" href="${h.asset('css/style.css', ver=c.rhodecode_version_hash)}" media="screen"/>
52 52 <!--[if lt IE 9]>
53 53 <link rel="stylesheet" type="text/css" href="${h.asset('css/ie.css', ver=c.rhodecode_version_hash)}" media="screen"/>
54 54 <![endif]-->
55 55 ## EXTRA FOR CSS
56 56 ${self.css_extra()}
57 57 </%def>
58 58 ## CSS EXTRA - optionally inject some extra CSS stuff needed for specific websites
59 59 <%def name="css_extra()">
60 60 </%def>
61 61
62 62 ${self.css()}
63 63
64 64 ## JAVASCRIPT
65 65 <%def name="js()">
66 <script>
67 // setup Polymer options
68 window.Polymer = {lazyRegister: true, dom: 'shadow'};
69
70 // Load webcomponentsjs polyfill if browser does not support native Web Components
71 (function() {
72 'use strict';
73 var onload = function() {
74 // For native Imports, manually fire WebComponentsReady so user code
75 // can use the same code path for native and polyfill'd imports.
76 if (!window.HTMLImports) {
77 document.dispatchEvent(
78 new CustomEvent('WebComponentsReady', {bubbles: true})
79 );
80 }
81 };
82 var webComponentsSupported = (
83 'registerElement' in document
84 && 'import' in document.createElement('link')
85 && 'content' in document.createElement('template')
86 );
87 if (!webComponentsSupported) {
88 } else {
89 onload();
90 }
91 })();
92 </script>
93 66
94 67 <script src="${h.asset('js/rhodecode/i18n/%s.js' % c.language, ver=c.rhodecode_version_hash)}"></script>
95 68 <script type="text/javascript">
96 69 // register templateContext to pass template variables to JS
97 70 var templateContext = ${h.json.dumps(c.template_context)|n};
98 71
99 72 var APPLICATION_URL = "${h.route_path('home').rstrip('/')}";
100 73 var ASSET_URL = "${h.asset('')}";
101 74 var DEFAULT_RENDERER = "${h.get_visual_attr(c, 'default_renderer')}";
102 75 var CSRF_TOKEN = "${getattr(c, 'csrf_token', '')}";
103 76
104 77 var APPENLIGHT = {
105 78 enabled: ${'true' if getattr(c, 'appenlight_enabled', False) else 'false'},
106 79 key: '${getattr(c, "appenlight_api_public_key", "")}',
107 80 % if getattr(c, 'appenlight_server_url', None):
108 81 serverUrl: '${getattr(c, "appenlight_server_url", "")}',
109 82 % endif
110 83 requestInfo: {
111 84 % if getattr(c, 'rhodecode_user', None):
112 85 ip: '${c.rhodecode_user.ip_addr}',
113 86 username: '${c.rhodecode_user.username}'
114 87 % endif
115 88 },
116 89 tags: {
117 90 rhodecode_version: '${c.rhodecode_version}',
118 91 rhodecode_edition: '${c.rhodecode_edition}'
119 92 }
120 93 };
121 94
122 95 </script>
123 96 <%include file="/base/plugins_base.mako"/>
124 97 <!--[if lt IE 9]>
125 98 <script language="javascript" type="text/javascript" src="${h.asset('js/src/excanvas.min.js')}"></script>
126 99 <![endif]-->
127 100 <script language="javascript" type="text/javascript" src="${h.asset('js/rhodecode/routes.js', ver=c.rhodecode_version_hash)}"></script>
128 101 <script> var alertMessagePayloads = ${h.flash.json_alerts(request=request)|n}; </script>
129 102 ## avoide escaping the %N
130 103 <script language="javascript" type="text/javascript" src="${h.asset('js/rhodecode-components.js', ver=c.rhodecode_version_hash)}"></script>
131 104 <script>CodeMirror.modeURL = "${h.asset('') + 'js/mode/%N/%N.js?ver='+c.rhodecode_version_hash}";</script>
132 105
133 106
134 107 ## JAVASCRIPT EXTRA - optionally inject some extra JS for specificed templates
135 108 ${self.js_extra()}
136 109
137 110 <script type="text/javascript">
138 111 Rhodecode = (function() {
139 112 function _Rhodecode() {
140 113 this.comments = new CommentsController();
141 114 }
142 115 return new _Rhodecode();
143 116 })();
144 117
145 118 $(document).ready(function(){
146 119 show_more_event();
147 120 timeagoActivate();
148 121 clipboardActivate();
149 122 })
150 123 </script>
151 124
152 125 </%def>
153 126
154 127 ## JAVASCRIPT EXTRA - optionally inject some extra JS for specificed templates
155 128 <%def name="js_extra()"></%def>
156 129 ${self.js()}
157 130
158 131 <%def name="head_extra()"></%def>
159 132 ${self.head_extra()}
160 133 ## extra stuff
161 134 %if c.pre_code:
162 135 ${c.pre_code|n}
163 136 %endif
164 137 </head>
165 138 <body id="body">
166 139 <noscript>
167 140 <div class="noscript-error">
168 141 ${_('Please enable JavaScript to use RhodeCode Enterprise')}
169 142 </div>
170 143 </noscript>
171 144 ## IE hacks
172 145 <!--[if IE 7]>
173 146 <script>$(document.body).addClass('ie7')</script>
174 147 <![endif]-->
175 148 <!--[if IE 8]>
176 149 <script>$(document.body).addClass('ie8')</script>
177 150 <![endif]-->
178 151 <!--[if IE 9]>
179 152 <script>$(document.body).addClass('ie9')</script>
180 153 <![endif]-->
181 154
182 155 ${next.body()}
183 156 %if c.post_code:
184 157 ${c.post_code|n}
185 158 %endif
186 159 <rhodecode-app></rhodecode-app>
187 160 </body>
188 161 </html>
General Comments 0
You need to be logged in to leave comments. Login now