##// END OF EJS Templates
js: migrate to polymer 3.x
ergo -
r3173:b3d618e2 default
parent child Browse files
Show More
@@ -45,6 +45,16 b''
45 "style-loader": "^0.21.0",
45 "style-loader": "^0.21.0",
46 "webpack-uglify-js-plugin": "^1.1.9",
46 "webpack-uglify-js-plugin": "^1.1.9",
47 "raw-loader": "1.0.0-beta.0",
47 "raw-loader": "1.0.0-beta.0",
48 "ts-loader": "^1.3.3"
48 "ts-loader": "^1.3.3",
49 "@webcomponents/webcomponentsjs": "^2.0.0",
50 "@polymer/polymer": "^3.0.0",
51 "@polymer/paper-button": "^3.0.0",
52 "@polymer/paper-spinner": "^3.0.0",
53 "@polymer/paper-tooltip": "^3.0.0",
54 "@polymer/paper-toast": "^3.0.0",
55 "@polymer/paper-toggle-button": "^3.0.0",
56 "@polymer/iron-ajax": "^3.0.0",
57 "@polymer/iron-autogrow-textarea": "^3.0.0",
58 "@polymer/iron-a11y-keys": "^3.0.0"
49 }
59 }
50 }
60 }
@@ -4,6 +4,222 b''
4
4
5 let
5 let
6 sources = {
6 sources = {
7 "@polymer/font-roboto-3.0.2" = {
8 name = "_at_polymer_slash_font-roboto";
9 packageName = "@polymer/font-roboto";
10 version = "3.0.2";
11 src = fetchurl {
12 url = "https://registry.npmjs.org/@polymer/font-roboto/-/font-roboto-3.0.2.tgz";
13 sha512 = "tx5TauYSmzsIvmSqepUPDYbs4/Ejz2XbZ1IkD7JEGqkdNUJlh+9KU85G56Tfdk/xjEZ8zorFfN09OSwiMrIQWA==";
14 };
15 };
16 "@polymer/iron-a11y-announcer-3.0.1" = {
17 name = "_at_polymer_slash_iron-a11y-announcer";
18 packageName = "@polymer/iron-a11y-announcer";
19 version = "3.0.1";
20 src = fetchurl {
21 url = "https://registry.npmjs.org/@polymer/iron-a11y-announcer/-/iron-a11y-announcer-3.0.1.tgz";
22 sha512 = "Xiqmpz0AEEbMNGYPpbrXBIrcI/xaR4tn77pmSLfxVKGGwjEUR/YrRgyIwXp4EN7lvst1dFC8kyl2hLga0uDIVQ==";
23 };
24 };
25 "@polymer/iron-a11y-keys-3.0.1" = {
26 name = "_at_polymer_slash_iron-a11y-keys";
27 packageName = "@polymer/iron-a11y-keys";
28 version = "3.0.1";
29 src = fetchurl {
30 url = "https://registry.npmjs.org/@polymer/iron-a11y-keys/-/iron-a11y-keys-3.0.1.tgz";
31 sha512 = "zmTi8xHeY4ZMJLAitW2hAmW5zXZ35hVy/eHQUFadAlOccuBK3oRRmoPRQRaZgpyJrCVFDAQRXXzzJtUDil/0CA==";
32 };
33 };
34 "@polymer/iron-a11y-keys-behavior-3.0.1" = {
35 name = "_at_polymer_slash_iron-a11y-keys-behavior";
36 packageName = "@polymer/iron-a11y-keys-behavior";
37 version = "3.0.1";
38 src = fetchurl {
39 url = "https://registry.npmjs.org/@polymer/iron-a11y-keys-behavior/-/iron-a11y-keys-behavior-3.0.1.tgz";
40 sha512 = "lnrjKq3ysbBPT/74l0Fj0U9H9C35Tpw2C/tpJ8a+5g8Y3YJs1WSZYnEl1yOkw6sEyaxOq/1DkzH0+60gGu5/PQ==";
41 };
42 };
43 "@polymer/iron-ajax-3.0.1" = {
44 name = "_at_polymer_slash_iron-ajax";
45 packageName = "@polymer/iron-ajax";
46 version = "3.0.1";
47 src = fetchurl {
48 url = "https://registry.npmjs.org/@polymer/iron-ajax/-/iron-ajax-3.0.1.tgz";
49 sha512 = "7+TPEAfWsRdhj1Y8UeF1759ktpVu+c3sG16rJiUC3wF9+woQ9xI1zUm2d59i7Yc3aDEJrR/Q8Y262KlOvyGVNg==";
50 };
51 };
52 "@polymer/iron-autogrow-textarea-3.0.1" = {
53 name = "_at_polymer_slash_iron-autogrow-textarea";
54 packageName = "@polymer/iron-autogrow-textarea";
55 version = "3.0.1";
56 src = fetchurl {
57 url = "https://registry.npmjs.org/@polymer/iron-autogrow-textarea/-/iron-autogrow-textarea-3.0.1.tgz";
58 sha512 = "FgSL7APrOSL9Vu812sBCFlQ17hvnJsBAV2C2e1UAiaHhB+dyfLq8gGdGUpqVWuGJ50q4Y/49QwCNnLf85AdVYA==";
59 };
60 };
61 "@polymer/iron-behaviors-3.0.1" = {
62 name = "_at_polymer_slash_iron-behaviors";
63 packageName = "@polymer/iron-behaviors";
64 version = "3.0.1";
65 src = fetchurl {
66 url = "https://registry.npmjs.org/@polymer/iron-behaviors/-/iron-behaviors-3.0.1.tgz";
67 sha512 = "IMEwcv1lhf1HSQxuyWOUIL0lOBwmeaoSTpgCJeP9IBYnuB1SPQngmfRuHKgK6/m9LQ9F9miC7p3HeQQUdKAE0w==";
68 };
69 };
70 "@polymer/iron-checked-element-behavior-3.0.1" = {
71 name = "_at_polymer_slash_iron-checked-element-behavior";
72 packageName = "@polymer/iron-checked-element-behavior";
73 version = "3.0.1";
74 src = fetchurl {
75 url = "https://registry.npmjs.org/@polymer/iron-checked-element-behavior/-/iron-checked-element-behavior-3.0.1.tgz";
76 sha512 = "aDr0cbCNVq49q+pOqa6CZutFh+wWpwPMLpEth9swx+GkAj+gCURhuQkaUYhIo5f2egDbEioR1aeHMnPlU9dQZA==";
77 };
78 };
79 "@polymer/iron-fit-behavior-3.0.1" = {
80 name = "_at_polymer_slash_iron-fit-behavior";
81 packageName = "@polymer/iron-fit-behavior";
82 version = "3.0.1";
83 src = fetchurl {
84 url = "https://registry.npmjs.org/@polymer/iron-fit-behavior/-/iron-fit-behavior-3.0.1.tgz";
85 sha512 = "/M0B1L30k31vmwNBaGuZcxzUAhJSHoGccb/DF0CDKI/hT8UlkTvcyemaWdOpmHHLgY52ceKIkRwA3AeXrKyvaQ==";
86 };
87 };
88 "@polymer/iron-flex-layout-3.0.1" = {
89 name = "_at_polymer_slash_iron-flex-layout";
90 packageName = "@polymer/iron-flex-layout";
91 version = "3.0.1";
92 src = fetchurl {
93 url = "https://registry.npmjs.org/@polymer/iron-flex-layout/-/iron-flex-layout-3.0.1.tgz";
94 sha512 = "7gB869czArF+HZcPTVSgvA7tXYFze9EKckvM95NB7SqYF+NnsQyhoXgKnpFwGyo95lUjUW9TFDLUwDXnCYFtkw==";
95 };
96 };
97 "@polymer/iron-form-element-behavior-3.0.1" = {
98 name = "_at_polymer_slash_iron-form-element-behavior";
99 packageName = "@polymer/iron-form-element-behavior";
100 version = "3.0.1";
101 src = fetchurl {
102 url = "https://registry.npmjs.org/@polymer/iron-form-element-behavior/-/iron-form-element-behavior-3.0.1.tgz";
103 sha512 = "G/e2KXyL5AY7mMjmomHkGpgS0uAf4ovNpKhkuUTRnMuMJuf589bKqE85KN4ovE1Tzhv2hJoh/igyD6ekHiYU1A==";
104 };
105 };
106 "@polymer/iron-meta-3.0.1" = {
107 name = "_at_polymer_slash_iron-meta";
108 packageName = "@polymer/iron-meta";
109 version = "3.0.1";
110 src = fetchurl {
111 url = "https://registry.npmjs.org/@polymer/iron-meta/-/iron-meta-3.0.1.tgz";
112 sha512 = "pWguPugiLYmWFV9UWxLWzZ6gm4wBwQdDy4VULKwdHCqR7OP7u98h+XDdGZsSlDPv6qoryV/e3tGHlTIT0mbzJA==";
113 };
114 };
115 "@polymer/iron-overlay-behavior-3.0.2" = {
116 name = "_at_polymer_slash_iron-overlay-behavior";
117 packageName = "@polymer/iron-overlay-behavior";
118 version = "3.0.2";
119 src = fetchurl {
120 url = "https://registry.npmjs.org/@polymer/iron-overlay-behavior/-/iron-overlay-behavior-3.0.2.tgz";
121 sha512 = "j1qmt6mJHCwpe1mKOvqK5kcCUPQr5LSrlqpgRDbUuLgUfNJ/vGTipjrkBlfbEUagm5FEQdc1VLPLSQP6WVuP9g==";
122 };
123 };
124 "@polymer/iron-resizable-behavior-3.0.1" = {
125 name = "_at_polymer_slash_iron-resizable-behavior";
126 packageName = "@polymer/iron-resizable-behavior";
127 version = "3.0.1";
128 src = fetchurl {
129 url = "https://registry.npmjs.org/@polymer/iron-resizable-behavior/-/iron-resizable-behavior-3.0.1.tgz";
130 sha512 = "FyHxRxFspVoRaeZSWpT3y0C9awomb4tXXolIJcZ7RvXhMP632V5lez+ch5G5SwK0LpnAPkg35eB0LPMFv+YMMQ==";
131 };
132 };
133 "@polymer/iron-validatable-behavior-3.0.1" = {
134 name = "_at_polymer_slash_iron-validatable-behavior";
135 packageName = "@polymer/iron-validatable-behavior";
136 version = "3.0.1";
137 src = fetchurl {
138 url = "https://registry.npmjs.org/@polymer/iron-validatable-behavior/-/iron-validatable-behavior-3.0.1.tgz";
139 sha512 = "wwpYh6wOa4fNI+jH5EYKC7TVPYQ2OfgQqocWat7GsNWcsblKYhLYbwsvEY5nO0n2xKqNfZzDLrUom5INJN7msQ==";
140 };
141 };
142 "@polymer/paper-behaviors-3.0.1" = {
143 name = "_at_polymer_slash_paper-behaviors";
144 packageName = "@polymer/paper-behaviors";
145 version = "3.0.1";
146 src = fetchurl {
147 url = "https://registry.npmjs.org/@polymer/paper-behaviors/-/paper-behaviors-3.0.1.tgz";
148 sha512 = "6knhj69fPJejv8qR0kCSUY+Q0XjaUf0OSnkjRjmTJPAwSrRYtgqE+l6P1FfA+py1X/cUjgne9EF5rMZAKJIg1g==";
149 };
150 };
151 "@polymer/paper-button-3.0.1" = {
152 name = "_at_polymer_slash_paper-button";
153 packageName = "@polymer/paper-button";
154 version = "3.0.1";
155 src = fetchurl {
156 url = "https://registry.npmjs.org/@polymer/paper-button/-/paper-button-3.0.1.tgz";
157 sha512 = "JRNBc+Oj9EWnmyLr7FcCr8T1KAnEHPh6mosln9BUdkM+qYaYsudSICh3cjTIbnj6AuF5OJidoLkM1dlyj0j6Zg==";
158 };
159 };
160 "@polymer/paper-ripple-3.0.1" = {
161 name = "_at_polymer_slash_paper-ripple";
162 packageName = "@polymer/paper-ripple";
163 version = "3.0.1";
164 src = fetchurl {
165 url = "https://registry.npmjs.org/@polymer/paper-ripple/-/paper-ripple-3.0.1.tgz";
166 sha512 = "dgOe12GyCF1VZBLUQqnzGWlf3xb255FajNCVB1VFj/AtskYtoamnafa7m3a+1vs+C8qbg4Benn5KwgxVDSW4cg==";
167 };
168 };
169 "@polymer/paper-spinner-3.0.1" = {
170 name = "_at_polymer_slash_paper-spinner";
171 packageName = "@polymer/paper-spinner";
172 version = "3.0.1";
173 src = fetchurl {
174 url = "https://registry.npmjs.org/@polymer/paper-spinner/-/paper-spinner-3.0.1.tgz";
175 sha512 = "MYIU6qWZnhZ5yNFOBzROPgBteGfxKEnDZ6bCgjrvUtJkBuQEz0MQZzSE/zmZc0oaJ9u5QK5xAFuYdudsGv7+sQ==";
176 };
177 };
178 "@polymer/paper-styles-3.0.1" = {
179 name = "_at_polymer_slash_paper-styles";
180 packageName = "@polymer/paper-styles";
181 version = "3.0.1";
182 src = fetchurl {
183 url = "https://registry.npmjs.org/@polymer/paper-styles/-/paper-styles-3.0.1.tgz";
184 sha512 = "y6hmObLqlCx602TQiSBKHqjwkE7xmDiFkoxdYGaNjtv4xcysOTdVJsDR/R9UHwIaxJ7gHlthMSykir1nv78++g==";
185 };
186 };
187 "@polymer/paper-toast-3.0.1" = {
188 name = "_at_polymer_slash_paper-toast";
189 packageName = "@polymer/paper-toast";
190 version = "3.0.1";
191 src = fetchurl {
192 url = "https://registry.npmjs.org/@polymer/paper-toast/-/paper-toast-3.0.1.tgz";
193 sha512 = "pizuogzObniDdICUc6dSLrnDt2VzzoRne1gCmbD6sfOATVv5tc8UfrqhA2iHngbNBEbniBiciS3iogdp5KTVUQ==";
194 };
195 };
196 "@polymer/paper-toggle-button-3.0.1" = {
197 name = "_at_polymer_slash_paper-toggle-button";
198 packageName = "@polymer/paper-toggle-button";
199 version = "3.0.1";
200 src = fetchurl {
201 url = "https://registry.npmjs.org/@polymer/paper-toggle-button/-/paper-toggle-button-3.0.1.tgz";
202 sha512 = "jadZB60fycT7YnSAH0H23LYo6/2HYmMZTtNr9LpdSIRFPLX6mqqxewex92cFz019bMKaRJgORn308hRlJo2u6A==";
203 };
204 };
205 "@polymer/paper-tooltip-3.0.1" = {
206 name = "_at_polymer_slash_paper-tooltip";
207 packageName = "@polymer/paper-tooltip";
208 version = "3.0.1";
209 src = fetchurl {
210 url = "https://registry.npmjs.org/@polymer/paper-tooltip/-/paper-tooltip-3.0.1.tgz";
211 sha512 = "yiUk09opTEnE1lK+tb501ENb+yQBi4p++Ep0eGJAHesVYKVMPNgPphVKkIizkDaU+n0SE+zXfTsRbYyOMDYXSg==";
212 };
213 };
214 "@polymer/polymer-3.1.0" = {
215 name = "_at_polymer_slash_polymer";
216 packageName = "@polymer/polymer";
217 version = "3.1.0";
218 src = fetchurl {
219 url = "https://registry.npmjs.org/@polymer/polymer/-/polymer-3.1.0.tgz";
220 sha512 = "hwN8IMERsFATz/9dSMxYHL+84J9uBkPuuarxJWlTsppZ4CAYTZKnepBfNrKoyNsafBmA3yXBiiKPPf+fJtza7A==";
221 };
222 };
7 "@types/clone-0.1.30" = {
223 "@types/clone-0.1.30" = {
8 name = "_at_types_slash_clone";
224 name = "_at_types_slash_clone";
9 packageName = "@types/clone";
225 packageName = "@types/clone";
@@ -193,6 +409,24 b' let'
193 sha512 = "mJ3QKWtCchL1vhU/kZlJnLPuQZnlDOdZsyP0bbLWPGdYsQDnSBvyTLhzwBA3QAMlzEL9V4JHygEmK6/OTEyytA==";
409 sha512 = "mJ3QKWtCchL1vhU/kZlJnLPuQZnlDOdZsyP0bbLWPGdYsQDnSBvyTLhzwBA3QAMlzEL9V4JHygEmK6/OTEyytA==";
194 };
410 };
195 };
411 };
412 "@webcomponents/shadycss-1.5.2" = {
413 name = "_at_webcomponents_slash_shadycss";
414 packageName = "@webcomponents/shadycss";
415 version = "1.5.2";
416 src = fetchurl {
417 url = "https://registry.npmjs.org/@webcomponents/shadycss/-/shadycss-1.5.2.tgz";
418 sha512 = "0OyrmVc7S+INtzoqP2ofAo+OdVn2Nj0Qvq4wD9FEGN7nMmLRxaD2mzy6hD6EslzxUSuGH302CDU4KXiY66SEqg==";
419 };
420 };
421 "@webcomponents/webcomponentsjs-2.1.3" = {
422 name = "_at_webcomponents_slash_webcomponentsjs";
423 packageName = "@webcomponents/webcomponentsjs";
424 version = "2.1.3";
425 src = fetchurl {
426 url = "https://registry.npmjs.org/@webcomponents/webcomponentsjs/-/webcomponentsjs-2.1.3.tgz";
427 sha512 = "0UHJNY88lR3pnEYtBVT7F8cuuxOiITQGWJa0LxoELqkBSB7IabzJFOj5K99PajD3CGAsWpjB0CAeijfe376Y1w==";
428 };
429 };
196 "@xtuc/ieee754-1.2.0" = {
430 "@xtuc/ieee754-1.2.0" = {
197 name = "_at_xtuc_slash_ieee754";
431 name = "_at_xtuc_slash_ieee754";
198 packageName = "@xtuc/ieee754";
432 packageName = "@xtuc/ieee754";
@@ -1454,13 +1688,13 b' let'
1454 sha1 = "b534e7c734c4f81ec5fbe8aca2ad24354b962c6c";
1688 sha1 = "b534e7c734c4f81ec5fbe8aca2ad24354b962c6c";
1455 };
1689 };
1456 };
1690 };
1457 "caniuse-db-1.0.30000899" = {
1691 "caniuse-db-1.0.30000900" = {
1458 name = "caniuse-db";
1692 name = "caniuse-db";
1459 packageName = "caniuse-db";
1693 packageName = "caniuse-db";
1460 version = "1.0.30000899";
1694 version = "1.0.30000900";
1461 src = fetchurl {
1695 src = fetchurl {
1462 url = "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000899.tgz";
1696 url = "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000900.tgz";
1463 sha512 = "MSCUohyoLU4/PGapapw/PLQkmQ+sFgzX6e3tM6ue8HX9HW9rBD5gRiAYKhC8r0QkvUE0pWTA8Ze6f3jrzBizVg==";
1697 sha512 = "fvicVRDlhHIQpt/bmbLl3hDHKUZb5ZP8O2OuZLz2fSEPlUBbvwwbhhqhGS617ldN6bDoo9A3+MQKQyFq0p7UXA==";
1464 };
1698 };
1465 };
1699 };
1466 "caniuse-lite-1.0.30000899" = {
1700 "caniuse-lite-1.0.30000899" = {
@@ -7482,6 +7716,30 b' let'
7482 version = "1.0.0";
7716 version = "1.0.0";
7483 src = ./..;
7717 src = ./..;
7484 dependencies = [
7718 dependencies = [
7719 sources."@polymer/font-roboto-3.0.2"
7720 sources."@polymer/iron-a11y-announcer-3.0.1"
7721 sources."@polymer/iron-a11y-keys-3.0.1"
7722 sources."@polymer/iron-a11y-keys-behavior-3.0.1"
7723 sources."@polymer/iron-ajax-3.0.1"
7724 sources."@polymer/iron-autogrow-textarea-3.0.1"
7725 sources."@polymer/iron-behaviors-3.0.1"
7726 sources."@polymer/iron-checked-element-behavior-3.0.1"
7727 sources."@polymer/iron-fit-behavior-3.0.1"
7728 sources."@polymer/iron-flex-layout-3.0.1"
7729 sources."@polymer/iron-form-element-behavior-3.0.1"
7730 sources."@polymer/iron-meta-3.0.1"
7731 sources."@polymer/iron-overlay-behavior-3.0.2"
7732 sources."@polymer/iron-resizable-behavior-3.0.1"
7733 sources."@polymer/iron-validatable-behavior-3.0.1"
7734 sources."@polymer/paper-behaviors-3.0.1"
7735 sources."@polymer/paper-button-3.0.1"
7736 sources."@polymer/paper-ripple-3.0.1"
7737 sources."@polymer/paper-spinner-3.0.1"
7738 sources."@polymer/paper-styles-3.0.1"
7739 sources."@polymer/paper-toast-3.0.1"
7740 sources."@polymer/paper-toggle-button-3.0.1"
7741 sources."@polymer/paper-tooltip-3.0.1"
7742 sources."@polymer/polymer-3.1.0"
7485 sources."@types/clone-0.1.30"
7743 sources."@types/clone-0.1.30"
7486 sources."@types/node-6.14.0"
7744 sources."@types/node-6.14.0"
7487 sources."@types/parse5-2.2.34"
7745 sources."@types/parse5-2.2.34"
@@ -7503,6 +7761,8 b' let'
7503 sources."@webassemblyjs/wasm-parser-1.7.10"
7761 sources."@webassemblyjs/wasm-parser-1.7.10"
7504 sources."@webassemblyjs/wast-parser-1.7.10"
7762 sources."@webassemblyjs/wast-parser-1.7.10"
7505 sources."@webassemblyjs/wast-printer-1.7.10"
7763 sources."@webassemblyjs/wast-printer-1.7.10"
7764 sources."@webcomponents/shadycss-1.5.2"
7765 sources."@webcomponents/webcomponentsjs-2.1.3"
7506 sources."@xtuc/ieee754-1.2.0"
7766 sources."@xtuc/ieee754-1.2.0"
7507 sources."@xtuc/long-4.2.1"
7767 sources."@xtuc/long-4.2.1"
7508 sources."abbrev-1.1.1"
7768 sources."abbrev-1.1.1"
@@ -7716,7 +7976,7 b' let'
7716 sources."browserslist-1.7.7"
7976 sources."browserslist-1.7.7"
7717 ];
7977 ];
7718 })
7978 })
7719 sources."caniuse-db-1.0.30000899"
7979 sources."caniuse-db-1.0.30000900"
7720 sources."caniuse-lite-1.0.30000899"
7980 sources."caniuse-lite-1.0.30000899"
7721 sources."caseless-0.12.0"
7981 sources."caseless-0.12.0"
7722 sources."center-align-0.1.3"
7982 sources."center-align-0.1.3"
This diff has been collapsed as it changes many lines, (1003 lines changed) Show them Hide them
@@ -1,39 +1,8 b''
1 <link rel="import" href="../../../../../../bower_components/polymer/polymer.html">
1 import {Polymer, html} from '@polymer/polymer/polymer-legacy';
2 <link rel="import" href="../../../../../../bower_components/iron-ajax/iron-ajax.html">
2 import '@polymer/iron-ajax/iron-ajax.js';
3
4 <!--
5
6 `<channelstream-connection>` allows you to connect and interact with channelstream server
7 abstracting websocket/long-polling connections from you.
8
9 In typical use, just slap some `<channelstream-connection>` at the top of your body:
10
3
11 <body>
4 const elemTemplate = html`
12 <channelstream-connection
5 <iron-ajax
13 username="{{user.username}}"
14 connect-url="http://127.0.0.1:8000/demo/connect"
15 disconnect-url="http://127.0.0.1:8000/disconnect"
16 subscribe-url="http://127.0.0.1:8000/demo/subscribe"
17 message-url="http://127.0.0.1:8000/demo/message"
18 long-poll-url="http://127.0.0.1:8000/listen"
19 websocket-url="http://127.0.0.1:8000/ws"
20 channels-url='["channel1", "channel2"]' />
21
22 Then you can do `channelstreamElem.connect()` to kick off your connection.
23 This element also handles automatic reconnections.
24
25 ## Default handlers
26
27 By default element has a listener attached that will fire `startListening()` handler on `channelstream-connected` event.
28
29 By default element has a listener attached that will fire `retryConnection()` handler on `channelstream-connect-error` event,
30 this handler will forever try to re-establish connection to the server incrementing intervals between retries up to 1 minute.
31
32 -->
33 <dom-module id="channelstream-connection">
34 <template>
35
36 <iron-ajax
37 id="ajaxConnect"
6 id="ajaxConnect"
38 url=""
7 url=""
39 handle-as="json"
8 handle-as="json"
@@ -45,7 +14,7 b' this handler will forever try to re-esta'
45 on-error="_handleConnectError"
14 on-error="_handleConnectError"
46 debounce-duration="100"></iron-ajax>
15 debounce-duration="100"></iron-ajax>
47
16
48 <iron-ajax
17 <iron-ajax
49 id="ajaxDisconnect"
18 id="ajaxDisconnect"
50 url=""
19 url=""
51 handle-as="json"
20 handle-as="json"
@@ -56,7 +25,7 b' this handler will forever try to re-esta'
56 on-response="_handleDisconnect"
25 on-response="_handleDisconnect"
57 debounce-duration="100"></iron-ajax>
26 debounce-duration="100"></iron-ajax>
58
27
59 <iron-ajax
28 <iron-ajax
60 id="ajaxSubscribe"
29 id="ajaxSubscribe"
61 url=""
30 url=""
62 handle-as="json"
31 handle-as="json"
@@ -67,7 +36,7 b' this handler will forever try to re-esta'
67 on-response="_handleSubscribe"
36 on-response="_handleSubscribe"
68 debounce-duration="100"></iron-ajax>
37 debounce-duration="100"></iron-ajax>
69
38
70 <iron-ajax
39 <iron-ajax
71 id="ajaxUnsubscribe"
40 id="ajaxUnsubscribe"
72 url=""
41 url=""
73 handle-as="json"
42 handle-as="json"
@@ -78,7 +47,7 b' this handler will forever try to re-esta'
78 on-response="_handleUnsubscribe"
47 on-response="_handleUnsubscribe"
79 debounce-duration="100"></iron-ajax>
48 debounce-duration="100"></iron-ajax>
80
49
81 <iron-ajax
50 <iron-ajax
82 id="ajaxMessage"
51 id="ajaxMessage"
83 url=""
52 url=""
84 handle-as="json"
53 handle-as="json"
@@ -90,7 +59,7 b' this handler will forever try to re-esta'
90 on-error="_handleMessageError"
59 on-error="_handleMessageError"
91 debounce-duration="100"></iron-ajax>
60 debounce-duration="100"></iron-ajax>
92
61
93 <iron-ajax
62 <iron-ajax
94 id="ajaxListen"
63 id="ajaxListen"
95 url=""
64 url=""
96 handle-as="text"
65 handle-as="text"
@@ -100,511 +69,509 b' this handler will forever try to re-esta'
100 on-error="_handleListenError"
69 on-error="_handleListenError"
101 on-response="_handleListenMessageEvent"
70 on-response="_handleListenMessageEvent"
102 debounce-duration="100"></iron-ajax>
71 debounce-duration="100"></iron-ajax>
103
72 `
104 </template>
105 <script>
106 Polymer({
107 is: 'channelstream-connection',
108
73
109 /**
74 Polymer({
110 * Fired when `channels` array changes.
75 is: 'channelstream-connection',
111 *
112 * @event channelstream-channels-changed
113 */
114
76
115 /**
77 _template: elemTemplate,
116 * Fired when `connect()` method succeeds.
117 *
118 * @event channelstream-connected
119 */
120
78
121 /**
79 /**
122 * Fired when `connect` fails.
80 * Fired when `channels` array changes.
123 *
81 *
124 * @event channelstream-connect-error
82 * @event channelstream-channels-changed
125 */
83 */
126
127 /**
128 * Fired when `disconnect()` succeeds.
129 *
130 * @event channelstream-disconnected
131 */
132
84
133 /**
85 /**
134 * Fired when `message()` succeeds.
86 * Fired when `connect()` method succeeds.
135 *
87 *
136 * @event channelstream-message-sent
88 * @event channelstream-connected
137 */
89 */
138
139 /**
140 * Fired when `message()` fails.
141 *
142 * @event channelstream-message-error
143 */
144
90
145 /**
91 /**
146 * Fired when `subscribe()` succeeds.
92 * Fired when `connect` fails.
147 *
93 *
148 * @event channelstream-subscribed
94 * @event channelstream-connect-error
149 */
95 */
150
151 /**
152 * Fired when `subscribe()` fails.
153 *
154 * @event channelstream-subscribe-error
155 */
156
96
157 /**
97 /**
158 * Fired when `unsubscribe()` succeeds.
98 * Fired when `disconnect()` succeeds.
159 *
99 *
160 * @event channelstream-unsubscribed
100 * @event channelstream-disconnected
161 */
101 */
162
163 /**
164 * Fired when `unsubscribe()` fails.
165 *
166 * @event channelstream-unsubscribe-error
167 */
168
102
169 /**
103 /**
170 * Fired when listening connection receives a message.
104 * Fired when `message()` succeeds.
171 *
105 *
172 * @event channelstream-listen-message
106 * @event channelstream-message-sent
173 */
107 */
174
175 /**
176 * Fired when listening connection is opened.
177 *
178 * @event channelstream-listen-opened
179 */
180
108
181 /**
109 /**
182 * Fired when listening connection is closed.
110 * Fired when `message()` fails.
183 *
111 *
184 * @event channelstream-listen-closed
112 * @event channelstream-message-error
185 */
113 */
186
114
187 /**
115 /**
188 * Fired when listening connection suffers an error.
116 * Fired when `subscribe()` succeeds.
189 *
117 *
190 * @event channelstream-listen-error
118 * @event channelstream-subscribed
191 */
119 */
192
120
193 properties: {
121 /**
194 isReady: Boolean,
122 * Fired when `subscribe()` fails.
195 /** List of channels user should be subscribed to. */
123 *
196 channels: {
124 * @event channelstream-subscribe-error
197 type: Array,
125 */
198 value: function () {
126
199 return []
127 /**
200 },
128 * Fired when `unsubscribe()` succeeds.
201 notify: true
129 *
202 },
130 * @event channelstream-unsubscribed
203 /** Username of connecting user. */
131 */
204 username: {
132
205 type: String,
133 /**
206 value: 'Anonymous',
134 * Fired when `unsubscribe()` fails.
207 reflectToAttribute: true
135 *
208 },
136 * @event channelstream-unsubscribe-error
209 /** Connection identifier. */
137 */
210 connectionId: {
138
211 type: String,
139 /**
212 reflectToAttribute: true
140 * Fired when listening connection receives a message.
213 },
141 *
214 /** Websocket instance. */
142 * @event channelstream-listen-message
215 websocket: {
143 */
216 type: Object,
217 value: null
218 },
219 /** Websocket connection url. */
220 websocketUrl: {
221 type: String,
222 value: ''
223 },
224 /** URL used in `connect()`. */
225 connectUrl: {
226 type: String,
227 value: ''
228 },
229 /** URL used in `disconnect()`. */
230 disconnectUrl: {
231 type: String,
232 value: ''
233 },
234 /** URL used in `subscribe()`. */
235 subscribeUrl: {
236 type: String,
237 value: ''
238 },
239 /** URL used in `unsubscribe()`. */
240 unsubscribeUrl: {
241 type: String,
242 value: ''
243 },
244 /** URL used in `message()`. */
245 messageUrl: {
246 type: String,
247 value: ''
248 },
249 /** Long-polling connection url. */
250 longPollUrl: {
251 type: String,
252 value: ''
253 },
254 /** Long-polling connection url. */
255 shouldReconnect: {
256 type: Boolean,
257 value: true
258 },
259 /** Should send heartbeats. */
260 heartbeats: {
261 type: Boolean,
262 value: true
263 },
264 /** How much should every retry interval increase (in milliseconds) */
265 increaseBounceIv: {
266 type: Number,
267 value: 2000
268 },
269 _currentBounceIv: {
270 type: Number,
271 reflectToAttribute: true,
272 value: 0
273 },
274 /** Should use websockets or long-polling by default */
275 useWebsocket: {
276 type: Boolean,
277 reflectToAttribute: true,
278 value: true
279 },
280 connected: {
281 type: Boolean,
282 reflectToAttribute: true,
283 value: false
284 }
285 },
286
144
287 observers: [
145 /**
288 '_handleChannelsChange(channels.splices)'
146 * Fired when listening connection is opened.
289 ],
147 *
148 * @event channelstream-listen-opened
149 */
290
150
291 listeners: {
151 /**
292 'channelstream-connected': 'startListening',
152 * Fired when listening connection is closed.
293 'channelstream-connect-error': 'retryConnection',
153 *
294 },
154 * @event channelstream-listen-closed
155 */
295
156
296 /**
157 /**
297 * Mutators hold functions that you can set locally to change the data
158 * Fired when listening connection suffers an error.
298 * that the client is sending to all endpoints
159 *
299 * you can call it like `elem.mutators('connect', yourFunc())`
160 * @event channelstream-listen-error
300 * mutators will be executed in order they were pushed onto arrays
161 */
301 *
302 */
303 mutators: {
304 connect: function () {
305 return []
306 }(),
307 message: function () {
308 return []
309 }(),
310 subscribe: function () {
311 return []
312 }(),
313 unsubscribe: function () {
314 return []
315 }(),
316 disconnect: function () {
317 return []
318 }()
319 },
320 ready: function () {
321 this.isReady = true;
322 },
323
162
324 /**
163 properties: {
325 * Connects user and fetches connection id from the server.
164 isReady: Boolean,
326 *
165 /** List of channels user should be subscribed to. */
327 */
166 channels: {
328 connect: function () {
167 type: Array,
329 var request = this.$['ajaxConnect'];
168 value: function () {
330 request.url = this.connectUrl;
169 return []
331 request.body = {
332 username: this.username,
333 channels: this.channels
334 };
335 for (var i = 0; i < this.mutators.connect.length; i++) {
336 this.mutators.connect[i](request);
337 }
338 request.generateRequest()
339 },
340 /**
341 * Overwrite with custom function that will
342 */
343 addMutator: function (type, func) {
344 this.mutators[type].push(func);
345 },
170 },
346 /**
171 notify: true
347 * Subscribes user to channels.
172 },
348 *
173 /** Username of connecting user. */
349 */
174 username: {
350 subscribe: function (channels) {
175 type: String,
351 var request = this.$['ajaxSubscribe'];
176 value: 'Anonymous',
352 request.url = this.subscribeUrl;
177 reflectToAttribute: true
353 request.body = {
178 },
354 channels: channels,
179 /** Connection identifier. */
355 conn_id: this.connectionId
180 connectionId: {
356 };
181 type: String,
357 for (var i = 0; i < this.mutators.subscribe.length; i++) {
182 reflectToAttribute: true
358 this.mutators.subscribe[i](request);
183 },
359 }
184 /** Websocket instance. */
360 if (request.body.channels.length) {
185 websocket: {
361 request.generateRequest();
186 type: Object,
362 }
187 value: null
363 },
188 },
364 /**
189 /** Websocket connection url. */
365 * Unsubscribes user from channels.
190 websocketUrl: {
366 *
191 type: String,
367 */
192 value: ''
368 unsubscribe: function (unsubscribe) {
193 },
369 var request = this.$['ajaxUnsubscribe'];
194 /** URL used in `connect()`. */
195 connectUrl: {
196 type: String,
197 value: ''
198 },
199 /** URL used in `disconnect()`. */
200 disconnectUrl: {
201 type: String,
202 value: ''
203 },
204 /** URL used in `subscribe()`. */
205 subscribeUrl: {
206 type: String,
207 value: ''
208 },
209 /** URL used in `unsubscribe()`. */
210 unsubscribeUrl: {
211 type: String,
212 value: ''
213 },
214 /** URL used in `message()`. */
215 messageUrl: {
216 type: String,
217 value: ''
218 },
219 /** Long-polling connection url. */
220 longPollUrl: {
221 type: String,
222 value: ''
223 },
224 /** Long-polling connection url. */
225 shouldReconnect: {
226 type: Boolean,
227 value: true
228 },
229 /** Should send heartbeats. */
230 heartbeats: {
231 type: Boolean,
232 value: true
233 },
234 /** How much should every retry interval increase (in milliseconds) */
235 increaseBounceIv: {
236 type: Number,
237 value: 2000
238 },
239 _currentBounceIv: {
240 type: Number,
241 reflectToAttribute: true,
242 value: 0
243 },
244 /** Should use websockets or long-polling by default */
245 useWebsocket: {
246 type: Boolean,
247 reflectToAttribute: true,
248 value: true
249 },
250 connected: {
251 type: Boolean,
252 reflectToAttribute: true,
253 value: false
254 }
255 },
370
256
371 request.url = this.unsubscribeUrl;
257 observers: [
372 request.body = {
258 '_handleChannelsChange(channels.splices)'
373 channels: unsubscribe,
259 ],
374 conn_id: this.connectionId
375 };
376 for (var i = 0; i < this.mutators.unsubscribe.length; i++) {
377 this.mutators.unsubscribe[i](request);
378 }
379 request.generateRequest()
380 },
381
260
382 /**
261 listeners: {
383 * calculates list of channels we should add user to based on difference
262 'channelstream-connected': 'startListening',
384 * between channels property and passed channel list
263 'channelstream-connect-error': 'retryConnection',
385 */
264 },
386 calculateSubscribe: function (channels) {
265
387 var currentlySubscribed = this.channels;
266 /**
388 var toSubscribe = [];
267 * Mutators hold functions that you can set locally to change the data
389 for (var i = 0; i < channels.length; i++) {
268 * that the client is sending to all endpoints
390 if (currentlySubscribed.indexOf(channels[i]) === -1) {
269 * you can call it like `elem.mutators('connect', yourFunc())`
391 toSubscribe.push(channels[i]);
270 * mutators will be executed in order they were pushed onto arrays
392 }
271 *
393 }
272 */
394 return toSubscribe
273 mutators: {
395 },
274 connect: function () {
396 /**
275 return []
397 * calculates list of channels we should remove user from based difference
276 }(),
398 * between channels property and passed channel list
277 message: function () {
399 */
278 return []
400 calculateUnsubscribe: function (channels) {
279 }(),
401 var currentlySubscribed = this.channels;
280 subscribe: function () {
402 var toUnsubscribe = [];
281 return []
403 for (var i = 0; i < channels.length; i++) {
282 }(),
404 if (currentlySubscribed.indexOf(channels[i]) !== -1) {
283 unsubscribe: function () {
405 toUnsubscribe.push(channels[i]);
284 return []
406 }
285 }(),
407 }
286 disconnect: function () {
408 return toUnsubscribe
287 return []
409 },
288 }()
410 /**
289 },
411 * Marks the connection as expired.
290 ready: function () {
412 *
291 this.isReady = true;
413 */
292 },
414 disconnect: function () {
293
415 var request = this.$['ajaxDisconnect'];
294 /**
416 request.url = this.disconnectUrl;
295 * Connects user and fetches connection id from the server.
417 request.params = {
296 *
418 conn_id: this.connectionId
297 */
419 };
298 connect: function () {
420 for (var i = 0; i < this.mutators.disconnect.length; i++) {
299 var request = this.$['ajaxConnect'];
421 this.mutators.disconnect[i](request);
300 request.url = this.connectUrl;
422 }
301 request.body = {
423 // mark connection as expired
302 username: this.username,
424 request.generateRequest();
303 channels: this.channels
425 // disconnect existing connection
304 };
426 this.closeConnection();
305 for (var i = 0; i < this.mutators.connect.length; i++) {
427 },
306 this.mutators.connect[i](request);
307 }
308 request.generateRequest()
309 },
310 /**
311 * Overwrite with custom function that will
312 */
313 addMutator: function (type, func) {
314 this.mutators[type].push(func);
315 },
316 /**
317 * Subscribes user to channels.
318 *
319 */
320 subscribe: function (channels) {
321 var request = this.$['ajaxSubscribe'];
322 request.url = this.subscribeUrl;
323 request.body = {
324 channels: channels,
325 conn_id: this.connectionId
326 };
327 for (var i = 0; i < this.mutators.subscribe.length; i++) {
328 this.mutators.subscribe[i](request);
329 }
330 if (request.body.channels.length) {
331 request.generateRequest();
332 }
333 },
334 /**
335 * Unsubscribes user from channels.
336 *
337 */
338 unsubscribe: function (unsubscribe) {
339 var request = this.$['ajaxUnsubscribe'];
340
341 request.url = this.unsubscribeUrl;
342 request.body = {
343 channels: unsubscribe,
344 conn_id: this.connectionId
345 };
346 for (var i = 0; i < this.mutators.unsubscribe.length; i++) {
347 this.mutators.unsubscribe[i](request);
348 }
349 request.generateRequest()
350 },
428
351
429 /**
352 /**
430 * Sends a message to the server.
353 * calculates list of channels we should add user to based on difference
431 *
354 * between channels property and passed channel list
432 */
355 */
433 message: function (message) {
356 calculateSubscribe: function (channels) {
434 var request = this.$['ajaxMessage'];
357 var currentlySubscribed = this.channels;
435 request.url = this.messageUrl;
358 var toSubscribe = [];
436 request.body = message;
359 for (var i = 0; i < channels.length; i++) {
437 for (var i = 0; i < this.mutators.message.length; i++) {
360 if (currentlySubscribed.indexOf(channels[i]) === -1) {
438 this.mutators.message[i](request)
361 toSubscribe.push(channels[i]);
439 }
362 }
440 request.generateRequest();
363 }
441 },
364 return toSubscribe
442 /**
365 },
443 * Opens "long lived" (websocket/longpoll) connection to the channelstream server.
366 /**
444 *
367 * calculates list of channels we should remove user from based difference
445 */
368 * between channels property and passed channel list
446 startListening: function (event) {
369 */
447 this.fire('start-listening', {});
370 calculateUnsubscribe: function (channels) {
448 if (this.useWebsocket) {
371 var currentlySubscribed = this.channels;
449 this.useWebsocket = window.WebSocket ? true : false;
372 var toUnsubscribe = [];
450 }
373 for (var i = 0; i < channels.length; i++) {
451 if (this.useWebsocket) {
374 if (currentlySubscribed.indexOf(channels[i]) !== -1) {
452 this.openWebsocket();
375 toUnsubscribe.push(channels[i]);
453 }
376 }
454 else {
377 }
455 this.openLongPoll();
378 return toUnsubscribe
456 }
379 },
457 },
380 /**
458 /**
381 * Marks the connection as expired.
459 * Opens websocket connection.
382 *
460 *
383 */
461 */
384 disconnect: function () {
462 openWebsocket: function () {
385 var request = this.$['ajaxDisconnect'];
463 var url = this.websocketUrl + '?conn_id=' + this.connectionId;
386 request.url = this.disconnectUrl;
464 this.websocket = new WebSocket(url);
387 request.params = {
465 this.websocket.onopen = this._handleListenOpen.bind(this);
388 conn_id: this.connectionId
466 this.websocket.onclose = this._handleListenCloseEvent.bind(this);
389 };
467 this.websocket.onerror = this._handleListenErrorEvent.bind(this);
390 for (var i = 0; i < this.mutators.disconnect.length; i++) {
468 this.websocket.onmessage = this._handleListenMessageEvent.bind(this);
391 this.mutators.disconnect[i](request);
469 },
392 }
470 /**
393 // mark connection as expired
471 * Opens long-poll connection.
394 request.generateRequest();
472 *
395 // disconnect existing connection
473 */
396 this.closeConnection();
474 openLongPoll: function () {
397 },
475 var request = this.$['ajaxListen'];
476 request.url = this.longPollUrl + '?conn_id=' + this.connectionId;
477 request.generateRequest()
478 },
479 /**
480 * Retries `connect()` call while incrementing interval between tries up to 1 minute.
481 *
482 */
483 retryConnection: function () {
484 if (!this.shouldReconnect) {
485 return;
486 }
487 if (this._currentBounceIv < 60000) {
488 this._currentBounceIv = this._currentBounceIv + this.increaseBounceIv;
489 }
490 else {
491 this._currentBounceIv = 60000;
492 }
493 setTimeout(this.connect.bind(this), this._currentBounceIv);
494 },
495 /**
496 * Closes listening connection.
497 *
498 */
499 closeConnection: function () {
500 var request = this.$['ajaxListen'];
501 if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {
502 this.websocket.onclose = null;
503 this.websocket.onerror = null;
504 this.websocket.close();
505 }
506 if (request.loading) {
507 request.lastRequest.abort();
508 }
509 this.connected = false;
510 },
511
398
512 _handleChannelsChange: function (event) {
399 /**
513 // do not fire the event if set() didn't mutate anything
400 * Sends a message to the server.
514 // is this a reliable way to do it?
401 *
515 if (!this.isReady || event === undefined) {
402 */
516 return
403 message: function (message) {
517 }
404 var request = this.$['ajaxMessage'];
518 this.fire('channelstream-channels-changed', event)
405 request.url = this.messageUrl;
519 },
406 request.body = message;
520
407 for (var i = 0; i < this.mutators.message.length; i++) {
521 _handleListenOpen: function (event) {
408 this.mutators.message[i](request)
522 this.connected = true;
409 }
523 this.fire('channelstream-listen-opened', event);
410 request.generateRequest();
524 this.createHeartBeats();
411 },
525 },
412 /**
526
413 * Opens "long lived" (websocket/longpoll) connection to the channelstream server.
527 createHeartBeats: function () {
414 *
528 if (typeof self._heartbeat === 'undefined' && this.websocket !== null
415 */
529 && this.heartbeats) {
416 startListening: function (event) {
530 self._heartbeat = setInterval(this._sendHeartBeat.bind(this), 10000);
417 this.fire('start-listening', {});
531 }
418 if (this.useWebsocket) {
532 },
419 this.useWebsocket = window.WebSocket ? true : false;
533
420 }
534 _sendHeartBeat: function () {
421 if (this.useWebsocket) {
535 if (this.websocket.readyState === WebSocket.OPEN && this.heartbeats) {
422 this.openWebsocket();
536 this.websocket.send(JSON.stringify({type: 'heartbeat'}));
423 }
537 }
424 else {
538 },
425 this.openLongPoll();
539
426 }
540 _handleListenError: function (event) {
427 },
541 this.connected = false;
428 /**
542 this.retryConnection();
429 * Opens websocket connection.
543 },
430 *
544 _handleConnectError: function (event) {
431 */
545 this.connected = false;
432 openWebsocket: function () {
546 this.fire('channelstream-connect-error', event.detail);
433 var url = this.websocketUrl + '?conn_id=' + this.connectionId;
547 },
434 this.websocket = new WebSocket(url);
548
435 this.websocket.onopen = this._handleListenOpen.bind(this);
549 _handleListenMessageEvent: function (event) {
436 this.websocket.onclose = this._handleListenCloseEvent.bind(this);
550 var data = null;
437 this.websocket.onerror = this._handleListenErrorEvent.bind(this);
551 // comes from iron-ajax
438 this.websocket.onmessage = this._handleListenMessageEvent.bind(this);
552 if (event.detail) {
439 },
553 data = JSON.parse(event.detail.response)
440 /**
554 // comes from websocket
441 * Opens long-poll connection.
555 setTimeout(this.openLongPoll.bind(this), 0);
442 *
556 } else {
443 */
557 data = JSON.parse(event.data)
444 openLongPoll: function () {
558 }
445 var request = this.$['ajaxListen'];
559 this.fire('channelstream-listen-message', data);
446 request.url = this.longPollUrl + '?conn_id=' + this.connectionId;
447 request.generateRequest()
448 },
449 /**
450 * Retries `connect()` call while incrementing interval between tries up to 1 minute.
451 *
452 */
453 retryConnection: function () {
454 if (!this.shouldReconnect) {
455 return;
456 }
457 if (this._currentBounceIv < 60000) {
458 this._currentBounceIv = this._currentBounceIv + this.increaseBounceIv;
459 }
460 else {
461 this._currentBounceIv = 60000;
462 }
463 setTimeout(this.connect.bind(this), this._currentBounceIv);
464 },
465 /**
466 * Closes listening connection.
467 *
468 */
469 closeConnection: function () {
470 var request = this.$['ajaxListen'];
471 if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {
472 this.websocket.onclose = null;
473 this.websocket.onerror = null;
474 this.websocket.close();
475 }
476 if (request.loading) {
477 request.lastRequest.abort();
478 }
479 this.connected = false;
480 },
560
481
561 },
482 _handleChannelsChange: function (event) {
483 // do not fire the event if set() didn't mutate anything
484 // is this a reliable way to do it?
485 if (!this.isReady || event === undefined) {
486 return
487 }
488 this.fire('channelstream-channels-changed', event)
489 },
562
490
563 _handleListenCloseEvent: function (event) {
491 _handleListenOpen: function (event) {
564 this.connected = false;
492 this.connected = true;
565 this.fire('channelstream-listen-closed', event.detail);
493 this.fire('channelstream-listen-opened', event);
566 this.retryConnection();
494 this.createHeartBeats();
567 },
495 },
568
496
569 _handleListenErrorEvent: function (event) {
497 createHeartBeats: function () {
570 this.connected = false;
498 if (typeof self._heartbeat === 'undefined' && this.websocket !== null
571 this.fire('channelstream-listen-error', {})
499 && this.heartbeats) {
572 },
500 self._heartbeat = setInterval(this._sendHeartBeat.bind(this), 10000);
501 }
502 },
573
503
574 _handleConnect: function (event) {
504 _sendHeartBeat: function () {
575 this.currentBounceIv = 0;
505 if (this.websocket.readyState === WebSocket.OPEN && this.heartbeats) {
576 this.connectionId = event.detail.response.conn_id;
506 this.websocket.send(JSON.stringify({type: 'heartbeat'}));
577 this.fire('channelstream-connected', event.detail.response);
507 }
578 },
508 },
579
509
580 _handleDisconnect: function (event) {
510 _handleListenError: function (event) {
581 this.connected = false;
511 this.connected = false;
582 this.fire('channelstream-disconnected', {});
512 this.retryConnection();
583 },
513 },
514 _handleConnectError: function (event) {
515 this.connected = false;
516 this.fire('channelstream-connect-error', event.detail);
517 },
584
518
585 _handleMessage: function (event) {
519 _handleListenMessageEvent: function (event) {
586 this.fire('channelstream-message-sent', event.detail.response);
520 var data = null;
587 },
521 // comes from iron-ajax
588 _handleMessageError: function (event) {
522 if (event.detail) {
589 this.fire('channelstream-message-error', event.detail);
523 data = JSON.parse(event.detail.response)
590 },
524 // comes from websocket
525 setTimeout(this.openLongPoll.bind(this), 0);
526 } else {
527 data = JSON.parse(event.data)
528 }
529 this.fire('channelstream-listen-message', data);
591
530
592 _handleSubscribe: function (event) {
531 },
593 this.fire('channelstream-subscribed', event.detail.response);
532
594 },
533 _handleListenCloseEvent: function (event) {
534 this.connected = false;
535 this.fire('channelstream-listen-closed', event.detail);
536 this.retryConnection();
537 },
538
539 _handleListenErrorEvent: function (event) {
540 this.connected = false;
541 this.fire('channelstream-listen-error', {})
542 },
595
543
596 _handleSubscribeError: function (event) {
544 _handleConnect: function (event) {
597 this.fire('channelstream-subscribe-error', event.detail);
545 this.currentBounceIv = 0;
598 },
546 this.connectionId = event.detail.response.conn_id;
547 this.fire('channelstream-connected', event.detail.response);
548 },
599
549
600 _handleUnsubscribe: function (event) {
550 _handleDisconnect: function (event) {
601 this.fire('channelstream-unsubscribed', event.detail.response);
551 this.connected = false;
602 },
552 this.fire('channelstream-disconnected', {});
553 },
603
554
604 _handleUnsubscribeError: function (event) {
555 _handleMessage: function (event) {
605 this.fire('channelstream-unsubscribe-error', event.detail);
556 this.fire('channelstream-message-sent', event.detail.response);
606 }
557 },
607 });
558 _handleMessageError: function (event) {
559 this.fire('channelstream-message-error', event.detail);
560 },
561
562 _handleSubscribe: function (event) {
563 this.fire('channelstream-subscribed', event.detail.response);
564 },
608
565
609 </script>
566 _handleSubscribeError: function (event) {
610 </dom-module>
567 this.fire('channelstream-subscribe-error', event.detail);
568 },
569
570 _handleUnsubscribe: function (event) {
571 this.fire('channelstream-unsubscribed', event.detail.response);
572 },
573
574 _handleUnsubscribeError: function (event) {
575 this.fire('channelstream-unsubscribe-error', event.detail);
576 }
577 });
@@ -1,7 +1,7 b''
1 import '../../../../../bower_components/iron-ajax/iron-ajax.html';
1 import '@polymer/iron-ajax/iron-ajax.js';
2 import './root-styles.gen.html';
2 import './root-styles.gen.html';
3 import './channelstream-connection/channelstream-connection.html';
3 import './channelstream-connection/channelstream-connection.js';
4 import './rhodecode-toast/rhodecode-toast.html';
4 import './rhodecode-toast/rhodecode-toast.js';
5 import './rhodecode-toggle/rhodecode-toggle.html';
5 import './rhodecode-toggle/rhodecode-toggle.js';
6 import './rhodecode-unsafe-html/rhodecode-unsafe-html.html';
6 import './rhodecode-unsafe-html/rhodecode-unsafe-html.js';
7 import './rhodecode-app/rhodecode-app.html';
7 import './rhodecode-app/rhodecode-app.js';
@@ -1,10 +1,19 b''
1 <link rel="import" href="../../../../../../bower_components/polymer/polymer.html">
1 import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';
2 <link rel="import" href="../channelstream-connection/channelstream-connection.html">
2 import '../channelstream-connection/channelstream-connection.js';
3 <link rel="import" href="../rhodecode-toast/rhodecode-toast.html">
3 import '../rhodecode-toast/rhodecode-toast.js';
4 <link rel="import" href="../rhodecode-favicon/rhodecode-favicon.html">
4 import '../rhodecode-favicon/rhodecode-favicon.js';
5
6 var ccLog = Logger.get('RhodeCodeApp');
7 ccLog.setLevel(Logger.OFF);
5
8
6 <dom-module id="rhodecode-app">
9 export class RhodecodeApp extends PolymerElement {
7 <template>
10
11 static get is() {
12 return 'rhodecode-app';
13 }
14
15 static get template(){
16 return html`
8 <channelstream-connection
17 <channelstream-connection
9 id="channelstream-connection"
18 id="channelstream-connection"
10 on-channelstream-listen-message="receivedMessage"
19 on-channelstream-listen-message="receivedMessage"
@@ -12,184 +21,174 b''
12 on-channelstream-subscribed="handleSubscribed">
21 on-channelstream-subscribed="handleSubscribed">
13 </channelstream-connection>
22 </channelstream-connection>
14 <rhodecode-favicon></rhodecode-favicon>
23 <rhodecode-favicon></rhodecode-favicon>
15 </template>
24 `
16 <script>
25 }
17 var ccLog = Logger.get('RhodeCodeApp');
18 ccLog.setLevel(Logger.OFF);
19
20 class RhodecodeApp extends Polymer.Element {
21
22 static get is() {
23 return 'rhodecode-app';
24 }
25
26
26 connectedCallback() {
27 connectedCallback() {
27 super.connectedCallback();
28 super.connectedCallback();
28 ccLog.debug('rhodeCodeApp created');
29 ccLog.debug('rhodeCodeApp created');
29 $.Topic('/notifications').subscribe(this.handleNotifications.bind(this));
30 $.Topic('/notifications').subscribe(this.handleNotifications.bind(this));
30 $.Topic('/favicon/update').subscribe(this.faviconUpdate.bind(this));
31 $.Topic('/favicon/update').subscribe(this.faviconUpdate.bind(this));
31 $.Topic('/connection_controller/subscribe').subscribe(
32 $.Topic('/connection_controller/subscribe').subscribe(
32 this.subscribeToChannelTopic.bind(this));
33 this.subscribeToChannelTopic.bind(this));
33 // this event can be used to coordinate plugins to do their
34 // this event can be used to coordinate plugins to do their
34 // initialization before channelstream is kicked off
35 // initialization before channelstream is kicked off
35 $.Topic('/__MAIN_APP__').publish({});
36 $.Topic('/__MAIN_APP__').publish({});
36
37 for (var i = 0; i < alertMessagePayloads.length; i++) {
38 $.Topic('/notifications').publish(alertMessagePayloads[i]);
39 }
40 this.initPlugins();
41 // after rest of application loads and topics get fired, launch connection
42 $(document).ready(function () {
43 this.kickoffChannelstreamPlugin();
44 }.bind(this));
45 }
46
37
47 initPlugins() {
38 for (var i = 0; i < alertMessagePayloads.length; i++) {
48 for (var i = 0; i < window.APPLICATION_PLUGINS.length; i++) {
39 $.Topic('/notifications').publish(alertMessagePayloads[i]);
49 var pluginDef = window.APPLICATION_PLUGINS[i];
40 }
50 if (pluginDef.component) {
41 this.initPlugins();
51 var pluginElem = document.createElement(pluginDef.component);
42 // after rest of application loads and topics get fired, launch connection
52 this.shadowRoot.appendChild(pluginElem);
43 $(document).ready(function () {
53 if (typeof pluginElem.init !== 'undefined') {
44 this.kickoffChannelstreamPlugin();
54 pluginElem.init();
45 }.bind(this));
55 }
46 }
56 }
57 }
58 }
59
60 /** proxy to channelstream connection */
61 getChannelStreamConnection() {
62 return this.$['channelstream-connection'];
63 }
64
65 handleNotifications(data) {
66 var elem = document.getElementById('notifications');
67 if (elem) {
68 elem.handleNotification(data);
69 }
70
71 }
72
47
73 faviconUpdate(data) {
48 initPlugins() {
74 this.shadowRoot.querySelector('rhodecode-favicon').counter = data.count;
49 for (var i = 0; i < window.APPLICATION_PLUGINS.length; i++) {
75 }
50 var pluginDef = window.APPLICATION_PLUGINS[i];
76
51 if (pluginDef.component) {
77 /** opens connection to ws server */
52 var pluginElem = document.createElement(pluginDef.component);
78 kickoffChannelstreamPlugin(data) {
53 this.shadowRoot.appendChild(pluginElem);
79 ccLog.debug('kickoffChannelstreamPlugin');
54 if (typeof pluginElem.init !== 'undefined') {
80 var channels = ['broadcast'];
55 pluginElem.init();
81 var addChannels = this.checkViewChannels();
82 for (var i = 0; i < addChannels.length; i++) {
83 channels.push(addChannels[i]);
84 }
85 if (window.CHANNELSTREAM_SETTINGS && CHANNELSTREAM_SETTINGS.enabled) {
86 var channelstreamConnection = this.getChannelStreamConnection();
87 channelstreamConnection.connectUrl = CHANNELSTREAM_URLS.connect;
88 channelstreamConnection.subscribeUrl = CHANNELSTREAM_URLS.subscribe;
89 channelstreamConnection.websocketUrl = CHANNELSTREAM_URLS.ws + '/ws';
90 channelstreamConnection.longPollUrl = CHANNELSTREAM_URLS.longpoll + '/listen';
91 // some channels might already be registered by topic
92 for (var i = 0; i < channels.length; i++) {
93 channelstreamConnection.push('channels', channels[i]);
94 }
95 // append any additional channels registered in other plugins
96 $.Topic('/connection_controller/subscribe').processPrepared();
97 channelstreamConnection.connect();
98 }
56 }
99 }
57 }
58 }
59 }
100
60
101 checkViewChannels() {
61 /** proxy to channelstream connection */
102 // subscribe to different channels data is sent.
62 getChannelStreamConnection() {
63 return this.$['channelstream-connection'];
64 }
103
65
104 var channels = [];
66 handleNotifications(data) {
105 // subscribe to PR repo channel for PR's'
67 var elem = document.getElementById('notifications');
106 if (templateContext.pull_request_data.pull_request_id) {
68 if (elem) {
107 var channelName = '/repo$' + templateContext.repo_name + '$/pr/' +
69 elem.handleNotification(data);
108 String(templateContext.pull_request_data.pull_request_id);
70 }
109 channels.push(channelName);
110 }
111
71
112 if (templateContext.commit_data.commit_id) {
72 }
113 var channelName = '/repo$' + templateContext.repo_name + '$/commit/' +
73
114 String(templateContext.commit_data.commit_id);
74 faviconUpdate(data) {
115 channels.push(channelName);
75 this.shadowRoot.querySelector('rhodecode-favicon').counter = data.count;
116 }
76 }
117
77
118 return channels;
78 /** opens connection to ws server */
79 kickoffChannelstreamPlugin(data) {
80 ccLog.debug('kickoffChannelstreamPlugin');
81 var channels = ['broadcast'];
82 var addChannels = this.checkViewChannels();
83 for (var i = 0; i < addChannels.length; i++) {
84 channels.push(addChannels[i]);
85 }
86 if (window.CHANNELSTREAM_SETTINGS && CHANNELSTREAM_SETTINGS.enabled) {
87 var channelstreamConnection = this.getChannelStreamConnection();
88 channelstreamConnection.connectUrl = CHANNELSTREAM_URLS.connect;
89 channelstreamConnection.subscribeUrl = CHANNELSTREAM_URLS.subscribe;
90 channelstreamConnection.websocketUrl = CHANNELSTREAM_URLS.ws + '/ws';
91 channelstreamConnection.longPollUrl = CHANNELSTREAM_URLS.longpoll + '/listen';
92 // some channels might already be registered by topic
93 for (var i = 0; i < channels.length; i++) {
94 channelstreamConnection.push('channels', channels[i]);
119 }
95 }
96 // append any additional channels registered in other plugins
97 $.Topic('/connection_controller/subscribe').processPrepared();
98 channelstreamConnection.connect();
99 }
100 }
101
102 checkViewChannels() {
103 // subscribe to different channels data is sent.
120
104
121 /** subscribes users from channels in channelstream */
105 var channels = [];
122 subscribeToChannelTopic(channels) {
106 // subscribe to PR repo channel for PR's'
123 var channelstreamConnection = this.getChannelStreamConnection();
107 if (templateContext.pull_request_data.pull_request_id) {
124 var toSubscribe = channelstreamConnection.calculateSubscribe(channels);
108 var channelName = '/repo$' + templateContext.repo_name + '$/pr/' +
125 ccLog.debug('subscribeToChannelTopic', toSubscribe);
109 String(templateContext.pull_request_data.pull_request_id);
126 if (toSubscribe.length > 0) {
110 channels.push(channelName);
127 // if we are connected then subscribe
111 }
128 if (channelstreamConnection.connected) {
112
129 channelstreamConnection.subscribe(toSubscribe);
113 if (templateContext.commit_data.commit_id) {
130 }
114 var channelName = '/repo$' + templateContext.repo_name + '$/commit/' +
131 // not connected? just push channels onto the stack
115 String(templateContext.commit_data.commit_id);
132 else {
116 channels.push(channelName);
133 for (var i = 0; i < toSubscribe.length; i++) {
117 }
134 channelstreamConnection.push('channels', toSubscribe[i]);
118
135 }
119 return channels;
136 }
120 }
121
122 /** subscribes users from channels in channelstream */
123 subscribeToChannelTopic(channels) {
124 var channelstreamConnection = this.getChannelStreamConnection();
125 var toSubscribe = channelstreamConnection.calculateSubscribe(channels);
126 ccLog.debug('subscribeToChannelTopic', toSubscribe);
127 if (toSubscribe.length > 0) {
128 // if we are connected then subscribe
129 if (channelstreamConnection.connected) {
130 channelstreamConnection.subscribe(toSubscribe);
131 }
132 // not connected? just push channels onto the stack
133 else {
134 for (var i = 0; i < toSubscribe.length; i++) {
135 channelstreamConnection.push('channels', toSubscribe[i]);
137 }
136 }
138 }
137 }
138 }
139 }
139
140
140 /** publish received messages into correct topic */
141 /** publish received messages into correct topic */
141 receivedMessage(event) {
142 receivedMessage(event) {
142 for (var i = 0; i < event.detail.length; i++) {
143 for (var i = 0; i < event.detail.length; i++) {
143 var message = event.detail[i];
144 var message = event.detail[i];
144 if (message.message.topic) {
145 if (message.message.topic) {
145 ccLog.debug('publishing', message.message.topic);
146 ccLog.debug('publishing', message.message.topic);
146 $.Topic(message.message.topic).publish(message);
147 $.Topic(message.message.topic).publish(message);
147 }
148 }
148 else if (message.type === 'presence') {
149 else if (message.type === 'presence') {
149 $.Topic('/connection_controller/presence').publish(message);
150 $.Topic('/connection_controller/presence').publish(message);
150 }
151 else {
152 ccLog.warn('unhandled message', message);
153 }
154 }
155 }
151 }
152 else {
153 ccLog.warn('unhandled message', message);
154 }
155 }
156 }
156
157
157 handleConnected(event) {
158 handleConnected(event) {
158 var channelstreamConnection = this.getChannelStreamConnection();
159 var channelstreamConnection = this.getChannelStreamConnection();
159 channelstreamConnection.set('channelsState',
160 channelstreamConnection.set('channelsState',
160 event.detail.channels_info);
161 event.detail.channels_info);
161 channelstreamConnection.set('userState', event.detail.state);
162 channelstreamConnection.set('userState', event.detail.state);
162 channelstreamConnection.set('channels', event.detail.channels);
163 channelstreamConnection.set('channels', event.detail.channels);
163 this.propagageChannelsState();
164 this.propagageChannelsState();
164 }
165 }
165
166
166 handleSubscribed(event) {
167 handleSubscribed(event) {
167 var channelstreamConnection = this.getChannelStreamConnection();
168 var channelstreamConnection = this.getChannelStreamConnection();
168 var channelInfo = event.detail.channels_info;
169 var channelInfo = event.detail.channels_info;
169 var channelKeys = Object.keys(event.detail.channels_info);
170 var channelKeys = Object.keys(event.detail.channels_info);
170 for (var i = 0; i < channelKeys.length; i++) {
171 for (var i = 0; i < channelKeys.length; i++) {
171 var key = channelKeys[i];
172 var key = channelKeys[i];
172 channelstreamConnection.set(['channelsState', key], channelInfo[key]);
173 channelstreamConnection.set(['channelsState', key], channelInfo[key]);
173 }
174 }
174 channelstreamConnection.set('channels', event.detail.channels);
175 channelstreamConnection.set('channels', event.detail.channels);
175 this.propagageChannelsState();
176 this.propagageChannelsState();
176 }
177 }
177
178
178 /** propagates channel states on topics */
179 /** propagates channel states on topics */
179 propagageChannelsState(event) {
180 propagageChannelsState(event) {
180 var channelstreamConnection = this.getChannelStreamConnection();
181 var channelstreamConnection = this.getChannelStreamConnection();
181 var channel_data = channelstreamConnection.channelsState;
182 var channel_data = channelstreamConnection.channelsState;
182 var channels = channelstreamConnection.channels;
183 var channels = channelstreamConnection.channels;
183 for (var i = 0; i < channels.length; i++) {
184 for (var i = 0; i < channels.length; i++) {
184 var key = channels[i];
185 var key = channels[i];
185 $.Topic('/connection_controller/channel_update').publish(
186 $.Topic('/connection_controller/channel_update').publish(
186 {channel: key, state: channel_data[key]}
187 {channel: key, state: channel_data[key]}
187 );
188 );
188 }
189 }
189 }
190 }
190
191
191 }
192 }
192
193
193 customElements.define(RhodecodeApp.is, RhodecodeApp);
194 customElements.define(RhodecodeApp.is, RhodecodeApp);
194 </script>
195 </dom-module>
@@ -1,38 +1,33 b''
1 <link rel="import" href="../../../../../../bower_components/polymer/polymer.html">
1 import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';
2
2
3 <dom-module id="rhodecode-favicon">
3 export class RhodecodeFavicon extends PolymerElement {
4 <template>
5 </template>
6 <script>
7 class RhodecodeFavicon extends Polymer.Element {
8
4
9 static get is() { return 'rhodecode-favicon'; }
5 static get is() {
6 return 'rhodecode-favicon';
7 }
10
8
11 static get properties() {
9 static get properties() {
12 return {
10 return {
13 favicon: Object,
11 favicon: Object,
14 counter: {
12 counter: {
15 type: Number,
13 type: Number,
16 observer: '_handleCounter'
14 observer: '_handleCounter'
17 }
18 }
19 }
15 }
20
16 }
21 connectedCallback() {
17 }
22 super.connectedCallback();
23 this.favicon = new Favico({
24 type: 'rectangle',
25 animation: 'none'
26 });
27 }
28
18
29 _handleCounter(newVal, oldVal) {
19 connectedCallback() {
30 this.favicon.badge(this.counter);
20 super.connectedCallback();
31 }
21 this.favicon = new Favico({
22 type: 'rectangle',
23 animation: 'none'
24 });
25 }
32
26
33 }
27 _handleCounter(newVal, oldVal) {
34 customElements.define(RhodecodeFavicon.is, RhodecodeFavicon);
28 this.favicon.badge(this.counter);
29 }
35
30
31 }
36
32
37 </script>
33 customElements.define(RhodecodeFavicon.is, RhodecodeFavicon);
38 </dom-module>
@@ -1,9 +1,17 b''
1 <link rel="import" href="../../../../../../bower_components/paper-button/paper-button.html">
1 import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';
2 <link rel="import"
2 import '@polymer/paper-toggle-button/paper-toggle-button.js';
3 href="../../../../../../bower_components/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
3 import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';
4 <link rel="import" href="../rhodecode-unsafe-html/rhodecode-unsafe-html.html">
4 import {IronA11yKeysBehavior} from '@polymer/iron-a11y-keys-behavior/iron-a11y-keys-behavior.js';
5 <dom-module id="rhodecode-toast">
5 import '../rhodecode-unsafe-html/rhodecode-unsafe-html.js';
6 <template>
6
7 export class RhodecodeToast extends mixinBehaviors([IronA11yKeysBehavior], PolymerElement) {
8
9 static get is() {
10 return 'rhodecode-toast';
11 }
12
13 static get template(){
14 return html`
7 <style include="shared-styles">
15 <style include="shared-styles">
8 /* inset border for buttons - does not work in ie */
16 /* inset border for buttons - does not work in ie */
9 /* rounded borders */
17 /* rounded borders */
@@ -107,127 +115,117 b''
107 </template>
115 </template>
108 </div>
116 </div>
109 </template>
117 </template>
110 </template>
118 `
111
119 }
112 <script>
113
114 class RhodecodeToast extends Polymer.mixinBehaviors([Polymer.IronA11yKeysBehavior], Polymer.Element) {
115
116 static get is() {
117 return 'rhodecode-toast';
118 }
119
120
120 static get properties() {
121 static get properties() {
121 return {
122 return {
122 toasts: {
123 toasts: {
123 type: Array,
124 type: Array,
124 value() {
125 value() {
125 return []
126 return []
126 }
127 },
128 isFixed: {
129 type: Boolean,
130 value: false
131 },
132 hasToasts: {
133 type: Boolean,
134 computed: '_computeHasToasts(toasts.*)'
135 },
136 keyEventTarget: {
137 type: Object,
138 value() {
139 return document.body;
140 }
141 }
142 }
127 }
143 }
128 },
144
129 isFixed: {
145 get keyBindings() {
130 type: Boolean,
146 return {
131 value: false
147 'esc:keyup': '_hideOnEsc'
132 },
133 hasToasts: {
134 type: Boolean,
135 computed: '_computeHasToasts(toasts.*)'
136 },
137 keyEventTarget: {
138 type: Object,
139 value() {
140 return document.body;
148 }
141 }
149 }
142 }
143 }
144 }
150
145
151 static get observers() {
146 get keyBindings() {
152 return [
147 return {
153 '_changedToasts(toasts.splices)'
148 'esc:keyup': '_hideOnEsc'
154 ]
149 }
155 }
150 }
156
151
157 _hideOnEsc(event) {
152 static get observers() {
158 return this.dismissNotifications();
153 return [
159 }
154 '_changedToasts(toasts.splices)'
155 ]
156 }
160
157
161 _computeHasToasts() {
158 _hideOnEsc(event) {
162 return this.toasts.length > 0;
159 return this.dismissNotifications();
163 }
160 }
164
161
165 _debouncedCalc() {
162 _computeHasToasts() {
166 // calculate once in a while
163 return this.toasts.length > 0;
167 this.debounce('debouncedCalc', this.toastInWindow, 25);
164 }
168 }
169
165
170 conditionalClass() {
166 _debouncedCalc() {
171 return this.isFixed ? 'fixed' : '';
167 // calculate once in a while
172 }
168 this.debounce('debouncedCalc', this.toastInWindow, 25);
169 }
173
170
174 toastInWindow() {
171 conditionalClass() {
175 if (!this._headerNode) {
172 return this.isFixed ? 'fixed' : '';
176 return true
173 }
177 }
178 var headerHeight = this._headerNode.offsetHeight;
179 var scrollPosition = window.scrollY;
180
174
181 if (this.isFixed) {
175 toastInWindow() {
182 this.isFixed = 1 <= scrollPosition;
176 if (!this._headerNode) {
183 }
177 return true
184 else {
178 }
185 this.isFixed = headerHeight <= scrollPosition;
179 var headerHeight = this._headerNode.offsetHeight;
186 }
180 var scrollPosition = window.scrollY;
187 }
188
181
189 connectedCallback() {
182 if (this.isFixed) {
190 super.connectedCallback();
183 this.isFixed = 1 <= scrollPosition;
191 this._headerNode = document.querySelector('.header', document);
184 }
192 this.listen(window, 'scroll', '_debouncedCalc');
185 else {
193 this.listen(window, 'resize', '_debouncedCalc');
186 this.isFixed = headerHeight <= scrollPosition;
194 this._debouncedCalc();
187 }
195 }
188 }
196
189
197 _changedToasts(newValue, oldValue) {
190 connectedCallback() {
198 $.Topic('/favicon/update').publish({count: this.toasts.length});
191 super.connectedCallback();
199 }
192 this._headerNode = document.querySelector('.header', document);
193 this.listen(window, 'scroll', '_debouncedCalc');
194 this.listen(window, 'resize', '_debouncedCalc');
195 this._debouncedCalc();
196 }
200
197
201 dismissNotification(e) {
198 _changedToasts(newValue, oldValue) {
202 $.Topic('/favicon/update').publish({count: this.toasts.length - 1});
199 $.Topic('/favicon/update').publish({count: this.toasts.length});
203 var idx = e.target.parentNode.indexPos
200 }
204 this.splice('toasts', idx, 1);
205
201
206 }
202 dismissNotification(e) {
203 $.Topic('/favicon/update').publish({count: this.toasts.length - 1});
204 var idx = e.target.parentNode.indexPos
205 this.splice('toasts', idx, 1);
207
206
208 dismissNotifications() {
207 }
209 $.Topic('/favicon/update').publish({count: 0});
208
210 this.splice('toasts', 0);
209 dismissNotifications() {
211 }
210 $.Topic('/favicon/update').publish({count: 0});
211 this.splice('toasts', 0);
212 }
212
213
213 handleNotification(data) {
214 handleNotification(data) {
214 if (!templateContext.rhodecode_user.notification_status && !data.message.force) {
215 if (!templateContext.rhodecode_user.notification_status && !data.message.force) {
215 // do not act if notifications are disabled
216 // do not act if notifications are disabled
216 return
217 return
217 }
218 }
218 this.push('toasts', {
219 this.push('toasts', {
219 level: data.message.level,
220 level: data.message.level,
220 message: data.message.message
221 message: data.message.message
221 });
222 });
222 }
223 }
223
224
224 _gettext(x){
225 _gettext(x){
225 return _gettext(x)
226 return _gettext(x)
226 }
227 }
227
228
228 }
229 }
229
230
230 customElements.define(RhodecodeToast.is, RhodecodeToast);
231 customElements.define(RhodecodeToast.is, RhodecodeToast);
231
232 </script>
233 </dom-module>
@@ -1,61 +1,57 b''
1 <link rel="import"
1 import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';
2 href="../../../../../../bower_components/paper-toggle-button/paper-toggle-button.html">
2 import '@polymer/paper-toggle-button/paper-toggle-button.js';
3 <link rel="import" href="../../../../../../bower_components/paper-spinner/paper-spinner.html">
3 import '@polymer/paper-spinner/paper-spinner.js';
4 <link rel="import" href="../../../../../../bower_components/paper-tooltip/paper-tooltip.html">
4 import '@polymer/paper-tooltip/paper-tooltip.js';
5
5
6 <dom-module id="rhodecode-toggle">
6 export class RhodecodeToggle extends PolymerElement {
7
7
8 <style include="shared-styles">
8 static get is() {
9 .rc-toggle {
9 return 'rhodecode-toggle';
10 float: left;
10 }
11 position: relative;
12 }
13
11
14 .rc-toggle paper-spinner {
12 static get template() {
15 position: absolute;
13 return html`
16 top: 0;
14 <style include="shared-styles">
17 left: -30px;
15 .rc-toggle {
18 width: 20px;
16 float: left;
19 height: 20px;
17 position: relative;
20 }
18 }
21 </style>
19
22
20 .rc-toggle paper-spinner {
23 <template>
21 position: absolute;
22 top: 0;
23 left: -30px;
24 width: 20px;
25 height: 20px;
26 }
27 </style>
24 <div class="rc-toggle">
28 <div class="rc-toggle">
25 <paper-toggle-button checked={{checked}}>[[labelStatus(checked)]]</paper-toggle-button>
29 <paper-toggle-button checked={{checked}}>[[labelStatus(checked)]]
30 </paper-toggle-button>
26 <paper-tooltip>[[tooltipText]]</paper-tooltip>
31 <paper-tooltip>[[tooltipText]]</paper-tooltip>
27 <template is="dom-if" if="[[shouldShow(noSpinner)]]">
32 <template is="dom-if" if="[[shouldShow(noSpinner)]]">
28 <paper-spinner active=[[active]]></paper-spinner>
33 <paper-spinner active=[[active]]></paper-spinner>
29 </template>
34 </template>
30 </div>
35 </div>
31 </template>
36 `;
32
37 }
33 <script>
34
35 class RhodecodeToggle extends Polymer.Element {
36
37 static get is() {
38 return 'rhodecode-toggle';
39 }
40
38
41 static get properties() {
39 static get properties() {
42 return {
40 return {
43 noSpinner: {type: Boolean, value: false, reflectToAttribute: true},
41 noSpinner: {type: Boolean, value: false, reflectToAttribute: true},
44 tooltipText: {type: String, value: "Click to toggle", reflectToAttribute: true},
42 tooltipText: {type: String, value: "Click to toggle", reflectToAttribute: true},
45 checked: {type: Boolean, value: false, reflectToAttribute: true},
43 checked: {type: Boolean, value: false, reflectToAttribute: true},
46 active: {type: Boolean, value: false, reflectToAttribute: true, notify: true}
44 active: {type: Boolean, value: false, reflectToAttribute: true, notify: true}
47 }
45 }
48 }
46 }
49
47
50 shouldShow() {
48 shouldShow() {
51 return !this.noSpinner
49 return !this.noSpinner
52 }
50 }
53
51
54 labelStatus(isActive) {
52 labelStatus(isActive) {
55 return this.checked ? 'Enabled' : "Disabled"
53 return this.checked ? 'Enabled' : "Disabled"
56 }
54 }
57 }
55 }
58
56
59 customElements.define(RhodecodeToggle.is, RhodecodeToggle);
57 customElements.define(RhodecodeToggle.is, RhodecodeToggle);
60 </script>
61 </dom-module>
@@ -1,31 +1,30 b''
1 <link rel="import" href="../../../../../../bower_components/polymer/polymer-element.html">
1 import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';
2
3 export class RhodecodeUnsafeHtml extends PolymerElement {
2
4
3 <dom-module id="rhodecode-unsafe-html">
5 static get is() {
4 <template>
6 return 'rhodecode-unsafe-html';
7 }
8
9 static get template() {
10 return html`
5 <style include="shared-styles"></style>
11 <style include="shared-styles"></style>
6 <slot></slot>
12 <slot></slot>
7 </template>
13 `;
8 <script>
14 }
9 class RhodecodeUnsafeHtml extends Polymer.Element {
10
11 static get is() {
12 return 'rhodecode-unsafe-html';
13 }
14
15
15 static get properties() {
16 static get properties() {
16 return {
17 return {
17 text: {
18 text: {
18 type: String,
19 type: String,
19 observer: '_handleText'
20 observer: '_handleText'
20 }
21 }
22 }
23
24 _handleText(newVal, oldVal) {
25 this.innerHTML = this.text;
26 }
21 }
27 }
22 }
23 }
28
24
29 customElements.define(RhodecodeUnsafeHtml.is, RhodecodeUnsafeHtml);
25 _handleText(newVal, oldVal) {
30 </script>
26 this.innerHTML = this.text;
31 </dom-module>
27 }
28 }
29
30 customElements.define(RhodecodeUnsafeHtml.is, RhodecodeUnsafeHtml);
General Comments 0
You need to be logged in to leave comments. Login now