Commit 525c13d8940ad0cb94ee66117553fe47ef6c4191
1 parent
ac237fdd
google component tests
Showing
24 changed files
with
2839 additions
and
0 deletions
bower_components/google-sheets/.bower.json
0 → 100644
1 | +{ | |
2 | + "name": "google-sheets", | |
3 | + "version": "1.0.5", | |
4 | + "homepage": "https://googlewebcomponents.github.io/google-sheets", | |
5 | + "description": "Web components to interact with Google Sheets", | |
6 | + "main": "google-sheets.html", | |
7 | + "authors": [ | |
8 | + "Eric Bidelman <ebidel@gmail.com>" | |
9 | + ], | |
10 | + "license": "Apache2", | |
11 | + "ignore": [ | |
12 | + "/.*", | |
13 | + "/test/" | |
14 | + ], | |
15 | + "keywords": [ | |
16 | + "web-component", | |
17 | + "web-components", | |
18 | + "polymer", | |
19 | + "spreadsheets", | |
20 | + "google" | |
21 | + ], | |
22 | + "dependencies": { | |
23 | + "polymer": "Polymer/polymer#^1.1.2", | |
24 | + "google-apis": "GoogleWebComponents/google-apis#^1.1.0", | |
25 | + "google-signin": "GoogleWebComponents/google-signin#^1.0.3", | |
26 | + "iron-ajax": "PolymerElements/iron-ajax#^1.0.0" | |
27 | + }, | |
28 | + "devDependencies": { | |
29 | + "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", | |
30 | + "google-map": "GoogleWebComponents/google-map#^1.1.0", | |
31 | + "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", | |
32 | + "web-component-tester": "*" | |
33 | + }, | |
34 | + "_release": "1.0.5", | |
35 | + "_resolution": { | |
36 | + "type": "version", | |
37 | + "tag": "1.0.5", | |
38 | + "commit": "1e87081a4abfdd31cf7cbf4ac970c7f9873c447d" | |
39 | + }, | |
40 | + "_source": "git://github.com/GoogleWebComponents/google-sheets.git", | |
41 | + "_target": "~1.0.5", | |
42 | + "_originalSource": "GoogleWebComponents/google-sheets", | |
43 | + "_direct": true | |
44 | +} | |
0 | 45 | \ No newline at end of file | ... | ... |
bower_components/google-sheets/LICENSE
0 → 100644
1 | +Copyright 2014 Google Inc | |
2 | + | |
3 | +Licensed under the Apache License, Version 2.0 (the "License"); | |
4 | +you may not use this file except in compliance with the License. | |
5 | +You may obtain a copy of the License at | |
6 | + | |
7 | + https://www.apache.org/licenses/LICENSE-2.0 | |
8 | + | |
9 | +Unless required by applicable law or agreed to in writing, software | |
10 | +distributed under the License is distributed on an "AS IS" BASIS, | |
11 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 | +See the License for the specific language governing permissions and | |
13 | +limitations under the License. | ... | ... |
bower_components/google-sheets/README.md
0 → 100755
bower_components/google-sheets/bower.json
0 → 100755
1 | +{ | |
2 | + "name": "google-sheets", | |
3 | + "version": "1.0.5", | |
4 | + "homepage": "https://googlewebcomponents.github.io/google-sheets", | |
5 | + "description": "Web components to interact with Google Sheets", | |
6 | + "main": "google-sheets.html", | |
7 | + "authors": [ | |
8 | + "Eric Bidelman <ebidel@gmail.com>" | |
9 | + ], | |
10 | + "license": "Apache2", | |
11 | + "ignore": [ | |
12 | + "/.*", | |
13 | + "/test/" | |
14 | + ], | |
15 | + "keywords": [ | |
16 | + "web-component", | |
17 | + "web-components", | |
18 | + "polymer", | |
19 | + "spreadsheets", | |
20 | + "google" | |
21 | + ], | |
22 | + "dependencies": { | |
23 | + "polymer": "Polymer/polymer#^1.1.2", | |
24 | + "google-apis": "GoogleWebComponents/google-apis#^1.1.0", | |
25 | + "google-signin": "GoogleWebComponents/google-signin#^1.0.3", | |
26 | + "iron-ajax": "PolymerElements/iron-ajax#^1.0.0" | |
27 | + }, | |
28 | + "devDependencies": { | |
29 | + "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", | |
30 | + "google-map": "GoogleWebComponents/google-map#^1.1.0", | |
31 | + "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", | |
32 | + "web-component-tester": "*" | |
33 | + } | |
34 | +} | ... | ... |
bower_components/google-sheets/demo/demo-private.html
0 → 100644
1 | +<!doctype html> | |
2 | +<!-- Copyright (c) 2015 Google Inc. All rights reserved. --> | |
3 | +<html> | |
4 | +<head> | |
5 | + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> | |
6 | + <title>google-sheets private data demo</title> | |
7 | + <script src="../../webcomponentsjs/webcomponents-lite.min.js"></script> | |
8 | + <link rel="import" href="../google-sheets.html"> | |
9 | + <link rel="import" href="../../google-map/google-map.html"> | |
10 | + <link rel="import" href="../../google-signin/google-signin.html"> | |
11 | + <style> | |
12 | + * { | |
13 | + box-sizing: border-box; | |
14 | + } | |
15 | + body { | |
16 | + margin: 2em; | |
17 | + font-family: 'Roboto', 'Helvetica Neue', Helvetica, Arial; | |
18 | + font-weight: 300; | |
19 | + background-color: #f1f1f3; | |
20 | + } | |
21 | + a { | |
22 | + text-decoration: none; | |
23 | + color: blue; | |
24 | + } | |
25 | + ul { | |
26 | + padding-left: 0; | |
27 | + } | |
28 | + ul, li { | |
29 | + list-style: none; | |
30 | + font-size: 14px; | |
31 | + } | |
32 | + section { | |
33 | + border-radius: 3px; | |
34 | + box-shadow: 1px 1px 3px #ccc; | |
35 | + padding: 1em 2em; | |
36 | + background-color: white; | |
37 | + width: 500px; | |
38 | + min-height: 500px; | |
39 | + } | |
40 | + main { | |
41 | + justify-content: space-around; | |
42 | + margin-top: 2em; | |
43 | + } | |
44 | + </style> | |
45 | +</head> | |
46 | +<body> | |
47 | + | |
48 | +<google-signin | |
49 | + client-id="1054047045356-j8pgqgls9vdef3rl09hapoicumbte0bo.apps.googleusercontent.com" | |
50 | + scopes="https://spreadsheets.google.com/feeds"> | |
51 | +</google-signin> | |
52 | + | |
53 | +<p>A <code><google-sheets></code> element returning data from a <b>private</b> Google Spreadsheet:</p> | |
54 | +<p><b>Note:</b> update the demo source to your clientId and private spreadsheet key for the demo to work.</p> | |
55 | + | |
56 | +<main class="layout horizontal"> | |
57 | + | |
58 | +<template id="spreadsheets" is="dom-bind"> | |
59 | + | |
60 | +<!-- Example: private spreadsheet --> | |
61 | +<google-sheets id="sheet" tab-id="1" | |
62 | + client-id="1054047045356-j8pgqgls9vdef3rl09hapoicumbte0bo.apps.googleusercontent.com" | |
63 | + key="1QMGizivw3UJ3-R9BFK7sfrXE0RL87dygk2C0RcuKoDY" | |
64 | + open-in-google-docs-url="{{openInGoogleDocsURL}}" | |
65 | + tab="{{tab}}" | |
66 | + spreadsheets="{{spreadsheets}}" | |
67 | + rows="{{rows}}"></google-sheets> | |
68 | + | |
69 | +<section> | |
70 | + | |
71 | + <heading> | |
72 | + <h3>List of spreadsheets</h3> | |
73 | + </heading> | |
74 | + | |
75 | + <ul> | |
76 | + <template is="dom-repeat" items="[[spreadsheets]]"> | |
77 | + <li>{{item.title.$t}}</li> | |
78 | + </template> | |
79 | + </ul> | |
80 | + | |
81 | +</section> | |
82 | + | |
83 | +<section> | |
84 | + | |
85 | + <heading> | |
86 | + <h3>Spreadsheet rows: | |
87 | + <a href="{{openInGoogleDocsURL}}" target="_blank" title="Open in Google Docs →"> | |
88 | + "<span>{{tab.title}}</span>" tab | |
89 | + </a> | |
90 | + </h3> | |
91 | + <h5>updated: <span>{{tab.updated}}</span>, by: <template is="dom-repeat" items="{{rows.authors}}"><span>{{item.name}}</span></template></h5> | |
92 | + </heading> | |
93 | + <ul> | |
94 | + <template is="dom-repeat" items="{{rows}}"> | |
95 | + <li>Name: <span>{{item.gsx$name.$t}}</span> ( lat: <span>{{item.gsx$lat.$t}}</span>, lng: <span>{{item.gsx$lng.$t}}</span> )</li> | |
96 | + </template> | |
97 | + </ul> | |
98 | + | |
99 | +</section> | |
100 | + | |
101 | +</template> | |
102 | + | |
103 | +</main> | |
104 | + | |
105 | +</body> | |
106 | +</html> | ... | ... |
bower_components/google-sheets/demo/index.html
0 → 100755
1 | +<!doctype html> | |
2 | +<!-- Copyright (c) 2015 Google Inc. All rights reserved. --> | |
3 | +<html> | |
4 | +<head> | |
5 | + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> | |
6 | + <title>google-sheets Demo</title> | |
7 | + <script src="../../webcomponentsjs/webcomponents-lite.min.js"></script> | |
8 | + <link rel="import" href="../../iron-flex-layout/classes/iron-flex-layout.html"> | |
9 | + <link rel="import" href="../google-sheets.html"> | |
10 | + <link rel="import" href="../../google-map/google-map.html"> | |
11 | + <style> | |
12 | + * { | |
13 | + box-sizing: border-box; | |
14 | + } | |
15 | + body { | |
16 | + margin: 2em; | |
17 | + font-family: 'Roboto', 'Helvetica Neue', Helvetica, Arial; | |
18 | + font-weight: 300; | |
19 | + background-color: #f1f1f3; | |
20 | + } | |
21 | + a { | |
22 | + text-decoration: none; | |
23 | + color: blue; | |
24 | + } | |
25 | + ul { | |
26 | + padding-left: 0; | |
27 | + } | |
28 | + ul, li { | |
29 | + list-style: none; | |
30 | + font-size: 14px; | |
31 | + } | |
32 | + section { | |
33 | + border-radius: 3px; | |
34 | + box-shadow: 1px 1px 3px #ccc; | |
35 | + padding: 1em 2em; | |
36 | + background-color: white; | |
37 | + width: 500px; | |
38 | + height: 500px; | |
39 | + } | |
40 | + google-map { | |
41 | + display: block; | |
42 | + height: 100%; | |
43 | + width: 100%; | |
44 | + } | |
45 | + main { | |
46 | + justify-content: space-around; | |
47 | + margin-top: 2em; | |
48 | + } | |
49 | + </style> | |
50 | +</head> | |
51 | +<body> | |
52 | + | |
53 | +<p>A <code><google-sheets></code> element returns data from a Google Spreadsheet:</p> | |
54 | + | |
55 | +<main class="layout horizontal"> | |
56 | + | |
57 | +<template id="container" is="dom-bind"> | |
58 | + | |
59 | + <section> | |
60 | + | |
61 | + <!-- Example: published spreadsheet --> | |
62 | + <google-sheets id="sheet" key="0Anye-JMjUkZZdDBkMVluMEhZMmFGeHpYdDJJV1FBRWc" tab-id="1" | |
63 | + published rows="{{rows}}" tab="{{tab}}" open-in-google-docs-url="{{openInGoogleDocsUrl}}"></google-sheets> | |
64 | + | |
65 | + <heading> | |
66 | + <h3>Spreadsheet rows: | |
67 | + <a href="{{openInGoogleDocsUrl}}" target="_blank" title="Open in Google Docs →"> | |
68 | + "<span>{{tab.title}}</span>" tab | |
69 | + </a> | |
70 | + </h3> | |
71 | + <h5>updated: <span>{{tab.updated}}</span>, by: <template is="dom-repeat" items="{{rows.authors}}">{{item.name}}</template></h5> | |
72 | + </heading> | |
73 | + <ul> | |
74 | + <template is="dom-repeat" items="[[rows]]"> | |
75 | + <li>Name: <span>{{item.gsx$name.$t}}</span> ( lat: <span>{{item.gsx$lat.$t}}</span>, lng: <span>{{item.gsx$lng.$t}}</span> )</li> | |
76 | + </template> | |
77 | + </ul> | |
78 | + | |
79 | + </section> | |
80 | + | |
81 | + <section style="padding: 0;"> | |
82 | + | |
83 | + <google-map disable-default-ui fit-to-markers> | |
84 | + <template is="dom-repeat" items="[[rows]]"> | |
85 | + <google-map-marker latitude="{{item.gsx$lat.$t}}" longitude="{{item.gsx$lng.$t}}"></google-map-marker> | |
86 | + </template> | |
87 | + </google-map> | |
88 | + | |
89 | + <button on-click="useTab" data-tabid="1">View tab 1 data</button> | |
90 | + <button on-click="useTab" data-tabid="2">View tab 2 data</button> | |
91 | + | |
92 | + </section> | |
93 | + | |
94 | +</template> | |
95 | +</main> | |
96 | + | |
97 | +<script> | |
98 | +var template = document.querySelector('#container'); | |
99 | + | |
100 | +template.useTab = function(e, detail, sender) { | |
101 | + document.querySelector('#sheet').tabId = Number(e.currentTarget.dataset.tabid); | |
102 | +}; | |
103 | +</script> | |
104 | +</body> | |
105 | +</html> | ... | ... |
bower_components/google-sheets/google-sheets.html
0 → 100755
1 | +<!-- Copyright (c) 2015 Google Inc. All rights reserved. --> | |
2 | + | |
3 | +<link rel="import" href="../polymer/polymer.html"> | |
4 | +<link rel="import" href="../iron-ajax/iron-ajax.html"> | |
5 | +<link rel="import" href="../google-signin/google-signin-aware.html"> | |
6 | + | |
7 | +<!-- | |
8 | +Element for interacting with Google Sheets. | |
9 | + | |
10 | +`<google-sheets>` pulls cell data from the Google Sheet specified by `key`. | |
11 | +A spreadsheet's key can be found in the URL when viewing it in google docs (e.g. `docs.google.com/spreadsheet/ccc?key=<KEY>#gid=12345`). | |
12 | + | |
13 | +Optionally, pass the `tab-id` attribute to specify a particular worksheet tab in the spreadsheet. For example, the first tab would be `tab-id="1"`. If `tab` is updated at a later time, the underlying data is also updated. **API calls are cached** as to not make extraneous calls. | |
14 | + | |
15 | +See [developers.google.com/google-apps/spreadsheets](https://developers.google.com/google-apps/spreadsheets) for full Spreadsheets API documentation. | |
16 | + | |
17 | +#### Example | |
18 | + | |
19 | + <google-sheets key="..." tab-id="1" client-id="..."></google-sheets> | |
20 | + | |
21 | + <script> | |
22 | + var sheet = document.querySelector('google-sheets'); | |
23 | + | |
24 | + sheet.addEventListener('google-sheet-data', function(e) { | |
25 | + // this.spreadsheets - list of the user's spreadsheets | |
26 | + // this.tab - information on the tab that was fetched | |
27 | + // this.rows - cell row information for the tab that was fetched | |
28 | + }); | |
29 | + | |
30 | + sheet.addEventListener('error', function(e) { | |
31 | + // e.detail.response | |
32 | + }); | |
33 | + </script> | |
34 | + | |
35 | +<b>Example</b> - `published` is a perf optimization and hints that the spreadsheet has been published (public): | |
36 | + | |
37 | + <google-sheets key="0Anye-JMjUkZZdDBkMVluMEhZMmFGeHpYdDJJV1FBRWc" published></google-sheets> | |
38 | + | |
39 | +<b>Example</b> - leaving off the `key` returns as list of the user's spreadsheets. | |
40 | + | |
41 | + <google-sheets client-id="..."></google-sheets> | |
42 | + | |
43 | +<b>Example</b> - show a list of Map markers, using data-binding features inside Polymer: | |
44 | + | |
45 | + <template is="dom-bind"> | |
46 | + <google-sheets | |
47 | + key="0Anye-JMjUkZZdDBkMVluMEhZMmFGeHpYdDJJV1FBRWc" tab-id="1" rows="{{rows}}" | |
48 | + client-id="..."> | |
49 | + </google-sheets> | |
50 | + <google-map> | |
51 | + <google-map-marker latitude="{{gsx$lat.$t}}" longitude="{{gsx$lng.$t}}"> | |
52 | + </google-map> | |
53 | + </template> | |
54 | + | |
55 | +<b>Example</b> - list a user's private spreadsheets. Authenticate with google-signin button. | |
56 | + | |
57 | + <google-signin | |
58 | + client-id="1054047045356-j8pgqgls9vdef3rl09hapoicumbte0bo.apps.googleusercontent.com" | |
59 | + scopes="https://spreadsheets.google.com/feeds"> | |
60 | + </google-signin> | |
61 | + | |
62 | + <template is="dom-bind"> | |
63 | + <google-sheets client-id="1054047045356-j8pgqgls9vdef3rl09hapoicumbte0bo.apps.googleusercontent.com" | |
64 | + key="1QMGizivw3UJ3-R9BFK7sfrXE0RL87dygk2C0RcuKoDY" tab-id="1" | |
65 | + spreadsheets="{{spreadsheets}}"></google-sheets> | |
66 | + <template is="dom-repeat" items="[[spreadsheets]]"> | |
67 | + <p>{{item.title.$t}}</p> | |
68 | + </template> | |
69 | + </template> | |
70 | + | |
71 | +@demo | |
72 | +--> | |
73 | + | |
74 | +<dom-module id="google-sheets"> | |
75 | + <template> | |
76 | + <template is="dom-if" if="{{!published}}"> | |
77 | + <google-signin-aware client-id="{{clientId}}" | |
78 | + scopes="https://spreadsheets.google.com/feeds" | |
79 | + on-google-signin-aware-success="_onSignInSuccess" | |
80 | + on-google-signin-aware-signed-out="_onSignInFail"></google-signin-aware> | |
81 | + </template> | |
82 | + | |
83 | + <iron-ajax id="publicajax" params='{"alt": "json"}' handle-as="json" | |
84 | + on-response="_onCellRows"></iron-ajax> | |
85 | + <iron-ajax id="listsheetsajax" params='{"alt": "json"}' handle-as="json" | |
86 | + on-response="_onSpreadsheetList"></iron-ajax> | |
87 | + <iron-ajax id="worksheetajax" params='{"alt": "json"}' handle-as="json" | |
88 | + on-response="_onWorksheet"></iron-ajax> | |
89 | + <iron-ajax id="cellrowsajax" params='{"alt": "json"}' handle-as="json" | |
90 | + on-response="_onCellRows"></iron-ajax> | |
91 | + | |
92 | + </template> | |
93 | +</dom-module> | |
94 | + | |
95 | +<script> | |
96 | +(function() { | |
97 | + var SCOPE_ = 'https://spreadsheets.google.com/feeds'; | |
98 | + | |
99 | + // Minimal cache for worksheet row data. Shared across instances so subsequent | |
100 | + // accesses are fast and API calls only happen once. | |
101 | + var rowDataCache_ = {}; | |
102 | + | |
103 | + function generateCacheKey_() { | |
104 | + return this._worksheetId + '_'+ this.tabId; | |
105 | + } | |
106 | + | |
107 | + function getLink_(rel, links) { | |
108 | + for (var i = 0, link; link = links[i]; ++i) { | |
109 | + if (link.rel === rel) { | |
110 | + return link; | |
111 | + } | |
112 | + } | |
113 | + return null; | |
114 | + } | |
115 | + | |
116 | + // Conversion of Worksheet Ids to GIDs and vice versa | |
117 | + // od4 > 2 | |
118 | + function wid_to_gid_(wid) { | |
119 | + return parseInt(String(wid), 36) ^ 31578; | |
120 | + } | |
121 | + // 2 > 0d4 | |
122 | + function gid_to_wid_(gid) { | |
123 | + // (gid xor 31578) encoded in base 36 | |
124 | + return parseInt((gid ^ 31578)).toString(36); | |
125 | + } | |
126 | + | |
127 | + window.GoogleSheets = Polymer({ | |
128 | + | |
129 | + is: 'google-sheets', | |
130 | + | |
131 | + /** | |
132 | + * Fired when the spreadsheet's cell information is available. | |
133 | + * | |
134 | + * @event google-sheet-data | |
135 | + * @param {Object} detail | |
136 | + * @param {Object} detail.data The data returned by the Spreadsheet API. | |
137 | + * @param {string} detail.type The type of data that was fetched. | |
138 | + * One of 'spreadsheets', 'tab', 'rows' * to correspond to the feed type. | |
139 | + */ | |
140 | + | |
141 | + hostAttributes: { | |
142 | + hidden: true | |
143 | + }, | |
144 | + | |
145 | + properties: { | |
146 | + /** | |
147 | + * A Google Developers client ID. Obtain from [console.developers.google.com](https://console.developers.google.com). Required for accessing a private spreadsheet. Optional if accessing a public spreadsheet. | |
148 | + */ | |
149 | + clientId: { | |
150 | + type: String, | |
151 | + value: '', | |
152 | + observer: '_configUpdate' | |
153 | + }, | |
154 | + | |
155 | + /** | |
156 | + * The key of the spreadsheet. This can be found in the URL when viewing | |
157 | + * the document is Google Docs (e.g. `docs.google.com/spreadsheet/ccc?key=<KEY>`). | |
158 | + * | |
159 | + * Leaving off this attribute still returns a list of the users spreadsheets in the `spreadsheets` property. | |
160 | + */ | |
161 | + key: { | |
162 | + type: String, | |
163 | + value: '', | |
164 | + observer: '_keyChanged' | |
165 | + }, | |
166 | + | |
167 | + /** | |
168 | + * Tab within a spreadsheet. For example, the first tab in a spreadsheet | |
169 | + * would be `tab-id="1"`. | |
170 | + */ | |
171 | + tabId: { | |
172 | + type: Number, | |
173 | + value: 1, | |
174 | + observer: '_configUpdate' | |
175 | + }, | |
176 | + | |
177 | + /** | |
178 | + * A hint that the spreadsheet is published publicly in Google Docs. Used as a performance optimization. | |
179 | + * Make sure the sheet is also publicly viewable by anyone in the Share settings. | |
180 | + * | |
181 | + * @attribute published | |
182 | + * @type boolean | |
183 | + * @default false | |
184 | + */ | |
185 | + published: { | |
186 | + type: Boolean, | |
187 | + value: false, | |
188 | + observer: '_configUpdate' | |
189 | + }, | |
190 | + | |
191 | + /** | |
192 | + * The fetched sheet corresponding to the `key` attribute. | |
193 | + */ | |
194 | + sheet: { | |
195 | + type: Object, | |
196 | + value: function() { return {}; }, | |
197 | + readOnly: true, | |
198 | + notify: true, | |
199 | + observer: '_sheetChanged' | |
200 | + }, | |
201 | + | |
202 | + /** | |
203 | + * Meta data about the particular tab that was retrieved for the spreadsheet. | |
204 | + */ | |
205 | + tab: { | |
206 | + type: Object, | |
207 | + value: function() { return {}; }, | |
208 | + readOnly: true, | |
209 | + notify: true, | |
210 | + observer: '_tabChanged' | |
211 | + }, | |
212 | + | |
213 | + /** | |
214 | + * If a spreadsheet `key` is specified, returns a list of cell row data. | |
215 | + */ | |
216 | + rows: { | |
217 | + type: Array, | |
218 | + value: function() { return []; }, | |
219 | + readOnly: true, | |
220 | + notify: true | |
221 | + }, | |
222 | + | |
223 | + /** | |
224 | + * List of the user's spreadsheets. Shared across instances. | |
225 | + */ | |
226 | + spreadsheets: { | |
227 | + type: Array, | |
228 | + readOnly: true, | |
229 | + notify: true, | |
230 | + value: function() { return []; } | |
231 | + }, | |
232 | + | |
233 | + /** | |
234 | + * The URL to open this spreadsheet in Google Sheets. | |
235 | + */ | |
236 | + openInGoogleDocsUrl: { | |
237 | + type: String, | |
238 | + computed: '_computeGoogleDocsUrl(key)', | |
239 | + notify: true | |
240 | + } | |
241 | + }, | |
242 | + | |
243 | + _worksheetId: null, | |
244 | + | |
245 | + _computeGoogleDocsUrl: function(key) { | |
246 | + var url = 'https://docs.google.com/spreadsheet/'; | |
247 | + if (key) { | |
248 | + url += 'ccc?key=' + key; | |
249 | + } | |
250 | + return url; | |
251 | + }, | |
252 | + | |
253 | + _configUpdate: function(key, published, tabId, clientId) { | |
254 | + this._tabIdChanged(); | |
255 | + }, | |
256 | + | |
257 | + _keyChanged: function(newValue, oldValue) { | |
258 | + // TODO(ericbidelman): need to better handle updates to the key attribute. | |
259 | + // Below doesn't account for private feeds. | |
260 | + if (this.published) { | |
261 | + var url = SCOPE_ + '/list/' + this.key + '/' + | |
262 | + this.tabId + '/public/values'; | |
263 | + this.$.publicajax.url = url; | |
264 | + this.$.publicajax.generateRequest(); | |
265 | + } | |
266 | + }, | |
267 | + | |
268 | + _tabIdChanged: function(newValue, oldValue) { | |
269 | + if (this._worksheetId) { | |
270 | + this._getCellRows(); | |
271 | + } else if (this.published) { | |
272 | + this._keyChanged(); | |
273 | + } | |
274 | + }, | |
275 | + | |
276 | + _sheetChanged: function(newValue, oldValue) { | |
277 | + if (!this.sheet.title) { | |
278 | + return; | |
279 | + } | |
280 | + | |
281 | + // Make metadata easily accessible on sheet object. | |
282 | + var authors = this.sheet.author && this.sheet.author.map(function(a) { | |
283 | + return {email: a.email.$t, name: a.name.$t}; | |
284 | + }); | |
285 | + | |
286 | + this.set('sheet.title', this.sheet.title.$t); | |
287 | + this.set('sheet.updated', new Date(this.sheet.updated.$t)); | |
288 | + this.set('sheet.authors', authors); | |
289 | + | |
290 | + this._worksheetId = this.sheet.id.$t.split('/').slice(-1)[0]; | |
291 | + this._getWorksheet(); | |
292 | + }, | |
293 | + | |
294 | + _tabChanged: function(newValue, oldValue) { | |
295 | + if (!this.tab.title) { | |
296 | + return; | |
297 | + } | |
298 | + | |
299 | + var authors = this.tab.authors = this.tab.author && this.tab.author.map(function(a) { | |
300 | + return {email: a.email.$t, name: a.name.$t}; | |
301 | + }); | |
302 | + | |
303 | + this.set('tab.title', this.tab.title.$t); | |
304 | + this.set('tab.updated', new Date(this.tab.updated.$t)); | |
305 | + this.set('tab.authors', authors); | |
306 | + | |
307 | + this.fire('google-sheet-data', { | |
308 | + type: 'tab', | |
309 | + data: this.tab | |
310 | + }); | |
311 | + }, | |
312 | + | |
313 | + _onSignInSuccess: function(e, detail) { | |
314 | + var oauthToken = gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse(); | |
315 | + | |
316 | + var headers = { | |
317 | + 'Authorization': 'Bearer ' + oauthToken.access_token | |
318 | + }; | |
319 | + | |
320 | + this.$.listsheetsajax.headers = headers; | |
321 | + this.$.worksheetajax.headers = headers; | |
322 | + this.$.cellrowsajax.headers = headers; | |
323 | + | |
324 | + // TODO(ericbidelman): don't make this call if this.spreadsheets is | |
325 | + // already populated from another instance. | |
326 | + this._listSpreadsheets(); | |
327 | + }, | |
328 | + | |
329 | + _onSignInFail: function(e, detail) { | |
330 | + // TODO(ericbidelman): handle this in some way. | |
331 | + console.log(e, e.type); | |
332 | + }, | |
333 | + | |
334 | + _listSpreadsheets: function() { | |
335 | + var url = SCOPE_ + '/spreadsheets/private/full'; | |
336 | + this.$.listsheetsajax.url = url; | |
337 | + this.$.listsheetsajax.generateRequest(); | |
338 | + }, | |
339 | + | |
340 | + _onSpreadsheetList: function(e) { | |
341 | + e.stopPropagation(); | |
342 | + | |
343 | + var feed = e.target.lastResponse.feed; | |
344 | + | |
345 | + this._setSpreadsheets(feed.entry); | |
346 | + | |
347 | + this.fire('google-sheet-data', { | |
348 | + type: 'spreadsheets', | |
349 | + data: this.spreadsheets | |
350 | + }); | |
351 | + | |
352 | + // Fetch worksheet feed if key was given and worksheet exists. | |
353 | + if (this.key) { | |
354 | + for (var i = 0, entry; entry = feed.entry[i]; ++i) { | |
355 | + var altLink = getLink_('alternate', entry.link); | |
356 | + if (altLink && altLink.href.indexOf(this.key) != -1) { | |
357 | + this._setSheet(entry); | |
358 | + break; | |
359 | + } | |
360 | + } | |
361 | + } | |
362 | + }, | |
363 | + | |
364 | + _getWorksheet: function() { | |
365 | + if (!this._worksheetId) { | |
366 | + throw new Error('workesheetId was not given.'); | |
367 | + } | |
368 | + | |
369 | + var url = SCOPE_ + '/worksheets/' + this._worksheetId + | |
370 | + '/private/full/' + this.tabId; | |
371 | + this.$.worksheetajax.url = url; | |
372 | + this.$.worksheetajax.generateRequest(); | |
373 | + }, | |
374 | + | |
375 | + _onWorksheet: function(e) { | |
376 | + e.stopPropagation(); | |
377 | + | |
378 | + // this.tab = e.target.lastResponse.entry; | |
379 | + this._setTab(e.target.lastResponse.entry); | |
380 | + this._getCellRows(); | |
381 | + }, | |
382 | + | |
383 | + _getCellRows: function() { | |
384 | + // Use cached data if available. | |
385 | + var key = generateCacheKey_.call(this); | |
386 | + if (key in rowDataCache_) { | |
387 | + this._onCellRows(null, null, rowDataCache_[key]); | |
388 | + | |
389 | + return; | |
390 | + } | |
391 | + | |
392 | + var url = SCOPE_ + '/list/' + | |
393 | + this._worksheetId + '/' + this.tabId + | |
394 | + '/private/full'; | |
395 | + this.$.cellrowsajax.url = url; | |
396 | + this.$.cellrowsajax.generateRequest(); | |
397 | + }, | |
398 | + | |
399 | + _onCellRows: function(e) { | |
400 | + e.stopPropagation(); | |
401 | + | |
402 | + var feed = e.target.lastResponse.feed; | |
403 | + | |
404 | + // Cache data if key doesn't exist. | |
405 | + var key = generateCacheKey_.call(this); | |
406 | + if (!(key in rowDataCache_)) { | |
407 | + rowDataCache_[key] = {response: {feed: feed}}; | |
408 | + } | |
409 | + | |
410 | + // this.rows = feed.entry; | |
411 | + this._setRows(feed.entry); | |
412 | + var authors = feed.author && feed.author.map(function(a) { | |
413 | + return {email: a.email.$t, name: a.name.$t}; | |
414 | + }); | |
415 | + this.set('rows.authors', authors); | |
416 | + | |
417 | + if (this.published) { | |
418 | + // this.tab = feed; | |
419 | + this._setTab(feed); | |
420 | + } | |
421 | + | |
422 | + this.fire('google-sheet-data', { | |
423 | + type: 'rows', | |
424 | + data: this.rows | |
425 | + }); | |
426 | + } | |
427 | + | |
428 | + }); | |
429 | + | |
430 | +})(); | |
431 | +</script> | ... | ... |
bower_components/google-sheets/index.html
0 → 100755
1 | +<!doctype html> | |
2 | +<!-- Copyright (c) 2015 Google Inc. All rights reserved. --> | |
3 | +<html> | |
4 | +<head> | |
5 | + | |
6 | + <script src="../webcomponentsjs/webcomponents-lite.js"></script> | |
7 | + <link rel="import" href="../iron-component-page/iron-component-page.html"> | |
8 | + | |
9 | +</head> | |
10 | +<body> | |
11 | + | |
12 | + <iron-component-page></iron-component-page> | |
13 | + | |
14 | +</body> | |
15 | +</html> | ... | ... |
bower_components/google-sheets/tests/google-sheet.html
0 → 100644
1 | +<!doctype html> | |
2 | +<!-- Copyright (c) 2015 Google Inc. All rights reserved. --> | |
3 | +<html> | |
4 | +<head> | |
5 | + <meta charset="utf-8"> | |
6 | + <title>google-sheet tests</title> | |
7 | + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> | |
8 | + | |
9 | + <script src="../../../platform/platform.js"></script> | |
10 | + <link rel="import" href="../../../polymer-test-tools/tools.html"> | |
11 | + <script src="../../../polymer-test-tools/htmltest.js"></script> | |
12 | + | |
13 | + <link rel="import" href="../google-sheets.html"> | |
14 | +</head> | |
15 | +<body> | |
16 | + | |
17 | +<google-sheets id="sheet1"></google-sheets> | |
18 | + | |
19 | +<script> | |
20 | +document.addEventListener('polymer-ready', function() { | |
21 | + | |
22 | + (function() { | |
23 | + var sheet = document.querySelector('#sheet1'); | |
24 | + var root = sheet.shadowRoot; | |
25 | + | |
26 | + // Check defaults. | |
27 | + assert.lengthOf(sheet.spreadsheets, 0, | |
28 | + '.spreadsheets length should default to 0'); | |
29 | + assert.lengthOf(sheet.rows, 0, '.rows length should default to 0'); | |
30 | + assert.isObject(sheet.sheet, '.sheet should default to {}'); | |
31 | + assert.isObject(sheet.tab, '.tab should default to {}'); | |
32 | + | |
33 | + assert.equal(sheet.key, '', ".key default is not ''"); | |
34 | + assert.equal(sheet.gid, 0, '.gid default is not 0'); | |
35 | + assert.isFalse(sheet.published, '.published does not default to false'); | |
36 | + assert.isNotNull(root.querySelector('google-signin-aware'), | |
37 | + 'google-signin-aware should be created for non-public sheet'); | |
38 | + | |
39 | + done(); | |
40 | + | |
41 | + })(); | |
42 | + | |
43 | +}); | |
44 | +</script> | |
45 | +</body> | |
46 | +</html> | ... | ... |
bower_components/google-sheets/tests/index.html
0 → 100644
1 | +<!doctype html> | |
2 | +<!-- Copyright (c) 2015 Google Inc. All rights reserved. --> | |
3 | +<html> | |
4 | + <head> | |
5 | + <meta charset="utf-8"> | |
6 | + <title>Runs all tests</title> | |
7 | + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> | |
8 | + <script src="../../platform/platform.js"></script> | |
9 | + <link rel="import" href="tests.html"> | |
10 | + </head> | |
11 | + <body> | |
12 | + <div id="mocha"></div> | |
13 | + </body> | |
14 | +</html> | ... | ... |
bower_components/google-sheets/tests/private.html
0 → 100644
1 | +<!doctype html> | |
2 | +<!-- Copyright (c) 2015 Google Inc. All rights reserved. --> | |
3 | +<html> | |
4 | +<head> | |
5 | + <meta charset="utf-8"> | |
6 | + <title>google-sheet tests</title> | |
7 | + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> | |
8 | + | |
9 | + <script src="../../../platform/platform.js"></script> | |
10 | + <link rel="import" href="../../../polymer-test-tools/tools.html"> | |
11 | + <script src="../../../polymer-test-tools/htmltest.js"></script> | |
12 | + | |
13 | + <link rel="import" href="../google-sheets.html"> | |
14 | +</head> | |
15 | +<body> | |
16 | + | |
17 | +<div> | |
18 | + <p>Tests live private spreadsheet data.</p> | |
19 | + <p>This test needs to be run manually, standalone in order to fetch an OAuth token.</p> | |
20 | + | |
21 | + <b>NOTES:</b><br> | |
22 | + <li>run manually off of localhost:3000/google-sheets/tests/private.html. Can also run from port 8080.</li> | |
23 | + <li>use the account: webcomponents.test@gmail.com</li> | |
24 | +</div> | |
25 | + | |
26 | +<google-sheets id="sheet" gid="1" | |
27 | + clientId="750497606405-1hq66meqmr4dp09dn54j9ggv85vbv0gp.apps.googleusercontent.com" | |
28 | + key="0AjqzxJ5RoRrWdGh2S0RRYURXTlNHdm9pQlFuM1ZwZWc"></google-sheets> | |
29 | + | |
30 | +<script> | |
31 | +document.addEventListener('polymer-ready', function() { | |
32 | + | |
33 | + (function() { | |
34 | + var sheet = document.querySelector('#sheet'); | |
35 | + var root = sheet.shadowRoot; | |
36 | + | |
37 | + // Test set attributes. | |
38 | + assert.equal(sheet.key, | |
39 | + '0AjqzxJ5RoRrWdGh2S0RRYURXTlNHdm9pQlFuM1ZwZWc', ".key was not updated"); | |
40 | + assert.equal(sheet.gid, 1, '.gid was not updated'); | |
41 | + assert.equal(sheet.clientId, | |
42 | + '750497606405-1hq66meqmr4dp09dn54j9ggv85vbv0gp.apps.googleusercontent.com', ".clientId was not set"); | |
43 | + | |
44 | + sheet.addEventListener('google-sheet-data', function(e) { | |
45 | + | |
46 | + switch (e.detail.type) { | |
47 | + case 'spreadsheets': | |
48 | + assert.isTrue(this.spreadsheets.length > 0, | |
49 | + '.spreadsheets should be populated for private feeds.'); | |
50 | + break; | |
51 | + case 'tab': | |
52 | + assert.equal(this.tab.title, 'SECONDTAB', '.tab.title is incorrect'); | |
53 | + break; | |
54 | + case 'rows': | |
55 | + assert.lengthOf(this.rows.authors, 1, '.rows.authors array'); | |
56 | + | |
57 | + var name = this.rows.authors[0].name; | |
58 | + var email = this.rows.authors[0].email | |
59 | + | |
60 | + assert.equal(email, 'webcomponents.test@gmail.com', 'author email not set correctly'); | |
61 | + assert.equal(name, 'webcomponents.test', 'author name not set correctly'); | |
62 | + | |
63 | + assert.equal(this.rows[0].title.$t, 'FIRST NAME', '"name" column was incorrect'); | |
64 | + assert.equal(this.rows[1].gsx$state.$t, 'OR', '"state" column was incorrect'); | |
65 | + | |
66 | + break; | |
67 | + default: | |
68 | + // Noop | |
69 | + } | |
70 | + | |
71 | + done(); | |
72 | + | |
73 | + }); | |
74 | + | |
75 | + })(); | |
76 | + | |
77 | +}); | |
78 | +</script> | |
79 | +</body> | |
80 | +</html> | |
81 | + | ... | ... |
bower_components/google-sheets/tests/published.html
0 → 100644
1 | +<!doctype html> | |
2 | +<!-- Copyright (c) 2015 Google Inc. All rights reserved. --> | |
3 | +<html> | |
4 | +<head> | |
5 | + <meta charset="utf-8"> | |
6 | + <title>google-sheet tests</title> | |
7 | + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> | |
8 | + | |
9 | + <script src="../../../platform/platform.js"></script> | |
10 | + <link rel="import" href="../../../polymer-test-tools/tools.html"> | |
11 | + <script src="../../../polymer-test-tools/htmltest.js"></script> | |
12 | + | |
13 | + <link rel="import" href="../google-sheets.html"> | |
14 | +</head> | |
15 | +<body> | |
16 | + | |
17 | +<google-sheets id="sheet" key="0Anye-JMjUkZZdDBkMVluMEhZMmFGeHpYdDJJV1FBRWc" | |
18 | + published></google-sheets> | |
19 | + | |
20 | +<script> | |
21 | +document.addEventListener('polymer-ready', function() { | |
22 | + | |
23 | + var sheet = document.querySelector('#sheet'); | |
24 | + var root = sheet.shadowRoot; | |
25 | + | |
26 | + assert.isTrue(sheet.published); | |
27 | + assert.isNull(root.querySelector('google-signin-aware'), | |
28 | + 'google-signin-aware should not be created for a published sheet'); | |
29 | + | |
30 | + sheet.addEventListener('google-sheet-data', function(e) { | |
31 | + | |
32 | + if (e.detail.type === 'tab') { | |
33 | + assert.equal(this.tab.title, 'Locations', | |
34 | + 'Published spreadsheet title is not correct.'); | |
35 | + assert.isNotNull(this.tab.updated, '.tab.updated was not set'); | |
36 | + assert.isTrue(this.tab.authors.length > 0, '.tab.authors was 0'); | |
37 | + } else if (e.detail.type === 'rows') { | |
38 | + assert.lengthOf(this.spreadsheets, 0, | |
39 | + '.spreadsheets length should be 0 since spreadsheet key was given'); | |
40 | + assert.isTrue(this.rows.length > 0, '.rows was not populated'); | |
41 | + } | |
42 | + | |
43 | + assert.equal(this.$.cellrowsajax.url, '', | |
44 | + '#cellrowsajax should not be invoked for a public spreadsheet'); | |
45 | + | |
46 | + done(); | |
47 | + }); | |
48 | +}); | |
49 | +</script> | |
50 | +</body> | |
51 | +</html> | ... | ... |
bower_components/google-sheets/tests/tests.html
0 → 100644
1 | +<!-- Copyright (c) 2015 Google Inc. All rights reserved. --> | |
2 | + | |
3 | +<link rel="import" href="../../polymer-test-tools/tools.html"> | |
4 | +<script src="../../polymer-test-tools/mocha-htmltest.js"></script> | |
5 | + | |
6 | +<script> | |
7 | +mocha.setup({ui: 'tdd', slow: 1000, timeout: 5000, htmlbase: ''}); | |
8 | + | |
9 | +htmlSuite('google-sheet', function() { | |
10 | + htmlTest('google-sheet.html'); | |
11 | + htmlTest('published.html'); | |
12 | + htmlTest('private.html'); | |
13 | +}); | |
14 | + | |
15 | +mocha.run(); | |
16 | +</script> | ... | ... |
bower_components/google-signin/.bower.json
0 → 100644
1 | +{ | |
2 | + "name": "google-signin", | |
3 | + "version": "1.2.0", | |
4 | + "description": "Web components to authenticate with Google services", | |
5 | + "homepage": "https://googlewebcomponents.github.io/google-signin", | |
6 | + "main": "google-signin.html", | |
7 | + "authors": [ | |
8 | + "Addy Osmani", | |
9 | + "Randy Merrill" | |
10 | + ], | |
11 | + "license": "Apache-2", | |
12 | + "ignore": [ | |
13 | + "/.*", | |
14 | + "/test/" | |
15 | + ], | |
16 | + "keywords": [ | |
17 | + "web-component", | |
18 | + "web-components", | |
19 | + "polymer", | |
20 | + "sign-in", | |
21 | + "google", | |
22 | + "authentication" | |
23 | + ], | |
24 | + "dependencies": { | |
25 | + "polymer": "Polymer/polymer#^1.0.0", | |
26 | + "font-roboto": "PolymerElements/font-roboto#^1.0.0", | |
27 | + "iron-icon": "PolymerElements/iron-icon#^1.0.0", | |
28 | + "iron-icons": "PolymerElements/iron-icons#^1.0.0", | |
29 | + "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", | |
30 | + "paper-ripple": "PolymerElements/paper-ripple#^1.0.0", | |
31 | + "paper-material": "PolymerElements/paper-material#^1.0.0", | |
32 | + "google-apis": "GoogleWebComponents/google-apis#^1.0.0" | |
33 | + }, | |
34 | + "devDependencies": { | |
35 | + "iron-component-page": "PolymerElements/iron-component-page#^1.0.2" | |
36 | + }, | |
37 | + "_release": "1.2.0", | |
38 | + "_resolution": { | |
39 | + "type": "version", | |
40 | + "tag": "v1.2.0", | |
41 | + "commit": "a1414b51b39e0a7dfe7031eb73a7733e2216579d" | |
42 | + }, | |
43 | + "_source": "git://github.com/GoogleWebComponents/google-signin.git", | |
44 | + "_target": "^1.0.3", | |
45 | + "_originalSource": "GoogleWebComponents/google-signin" | |
46 | +} | |
0 | 47 | \ No newline at end of file | ... | ... |
bower_components/google-signin/LICENSE
0 → 100644
1 | +Copyright 2014 Google Inc | |
2 | + | |
3 | +Licensed under the Apache License, Version 2.0 (the "License"); | |
4 | +you may not use this file except in compliance with the License. | |
5 | +You may obtain a copy of the License at | |
6 | + | |
7 | + https://www.apache.org/licenses/LICENSE-2.0 | |
8 | + | |
9 | +Unless required by applicable law or agreed to in writing, software | |
10 | +distributed under the License is distributed on an "AS IS" BASIS, | |
11 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 | +See the License for the specific language governing permissions and | |
13 | +limitations under the License. | ... | ... |
bower_components/google-signin/README.md
0 → 100644
bower_components/google-signin/bower.json
0 → 100644
1 | +{ | |
2 | + "name": "google-signin", | |
3 | + "version": "1.2.0", | |
4 | + "description": "Web components to authenticate with Google services", | |
5 | + "homepage": "https://googlewebcomponents.github.io/google-signin", | |
6 | + "main": "google-signin.html", | |
7 | + "authors": [ | |
8 | + "Addy Osmani", | |
9 | + "Randy Merrill" | |
10 | + ], | |
11 | + "license": "Apache-2", | |
12 | + "ignore": [ | |
13 | + "/.*", | |
14 | + "/test/" | |
15 | + ], | |
16 | + "keywords": [ | |
17 | + "web-component", | |
18 | + "web-components", | |
19 | + "polymer", | |
20 | + "sign-in", | |
21 | + "google", | |
22 | + "authentication" | |
23 | + ], | |
24 | + "dependencies": { | |
25 | + "polymer": "Polymer/polymer#^1.0.0", | |
26 | + "font-roboto": "PolymerElements/font-roboto#^1.0.0", | |
27 | + "iron-icon": "PolymerElements/iron-icon#^1.0.0", | |
28 | + "iron-icons": "PolymerElements/iron-icons#^1.0.0", | |
29 | + "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", | |
30 | + "paper-ripple": "PolymerElements/paper-ripple#^1.0.0", | |
31 | + "paper-material": "PolymerElements/paper-material#^1.0.0", | |
32 | + "google-apis": "GoogleWebComponents/google-apis#^1.0.0" | |
33 | + }, | |
34 | + "devDependencies": { | |
35 | + "iron-component-page": "PolymerElements/iron-component-page#^1.0.2" | |
36 | + } | |
37 | +} | ... | ... |
bower_components/google-signin/demo/index.html
0 → 100644
1 | +<!doctype html> | |
2 | +<!-- Copyright (c) 2014 Google Inc. All rights reserved. --> | |
3 | +<html> | |
4 | +<head> | |
5 | + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> | |
6 | + | |
7 | + <title>google-signin Demo</title> | |
8 | + | |
9 | + <script src="../../webcomponentsjs/webcomponents-lite.js"></script> | |
10 | + <link rel="import" href="../google-signin.html"> | |
11 | + <link rel="import" href="../google-signin-aware.html"> | |
12 | + | |
13 | + <!-- Demo only styles --> | |
14 | + <style> | |
15 | + body { | |
16 | + font-family: 'RobotoDraft', 'Roboto', sans-serif; | |
17 | + line-height:1.2; | |
18 | + vertical-align:middle; | |
19 | + background: rgba(204, 204, 204, 0.31); | |
20 | + } | |
21 | + | |
22 | + | |
23 | + .map { | |
24 | + background: whitesmoke; | |
25 | + margin: .5rem -1.5rem 0 -1.5rem; | |
26 | + padding: 0.5rem; | |
27 | + } | |
28 | + | |
29 | + h1 { | |
30 | + font-size: 2rem; | |
31 | + font-weight:200; | |
32 | + clear: both; | |
33 | + } | |
34 | + | |
35 | + h1 strong { | |
36 | + font-weight:300; | |
37 | + color:#539D00; | |
38 | + } | |
39 | + | |
40 | + h2 { | |
41 | + font-size:.9rem; | |
42 | + line-height:2.5; | |
43 | + color:gray; | |
44 | + font-weight:400; | |
45 | + clear: both; | |
46 | + } | |
47 | + | |
48 | + .showcase { | |
49 | + display: inline-block; | |
50 | + margin-right: 2rem; | |
51 | + float: left; | |
52 | + } | |
53 | + </style> | |
54 | + | |
55 | +</head> | |
56 | + | |
57 | +<body> | |
58 | + <p>A <code><google-signin></code> element looks like this button:</p> | |
59 | + | |
60 | + <p><google-signin brand="google" client-id="1054047045356-j8pgqgls9vdef3rl09hapoicumbte0bo.apps.googleusercontent.com"></google-signin> | |
61 | +or like this if plus scopes are present | |
62 | + <google-signin brand="google-plus"></google-signin> | |
63 | + </p> | |
64 | + <p>Signin button can vary its appearance:</p> | |
65 | + <p>Width: | |
66 | + <google-signin brand="google" width="wide"></google-signin> | |
67 | + <google-signin brand="google" width="iconOnly"></google-signin> | |
68 | + Height: | |
69 | + <google-signin brand="google" height="tall"></google-signin> | |
70 | + <google-signin brand="google" height="standard"></google-signin> | |
71 | + <google-signin brand="google" height="short"></google-signin> | |
72 | + </p> | |
73 | + <p> | |
74 | + Theme: | |
75 | + <google-signin brand="google" theme="dark"></google-signin> | |
76 | + <google-signin brand="google" theme="light"></google-signin> | |
77 | + <google-signin brand="google-plus" theme="light"></google-signin> | |
78 | + <google-signin brand="google-plus" theme="light" raised></google-signin> | |
79 | + </p> | |
80 | + <!-- Demo the ability to use the google-signin-aware element. --> | |
81 | + <p><code><google-signin-aware></code> is a companion element.</p> | |
82 | + <p>You can use it inside your components to request additional scopes.</p> | |
83 | + <p>Every signin button will request all the scopes present in the document, | |
84 | + and change its appearance to match</p> | |
85 | + <p>For example, here is a signin-aware scope. You can change its scopes via popup</p> | |
86 | + <template id="awareness" is="dom-bind"> | |
87 | + <div><code><google-signin-aware | |
88 | + <div>scope= | |
89 | + <select value="{{scope::change}}"> | |
90 | + <option value="">None</option> | |
91 | + <option value="https://www.googleapis.com/auth/analytics">Google Analytics</option> | |
92 | + <option value="https://www.googleapis.com/auth/plus.login">Google Plus view circles</option> | |
93 | + <option value="https://www.googleapis.com/auth/youtube">YouTube</option> | |
94 | + <option value="https://www.googleapis.com/auth/calendar">Calendar</option> | |
95 | + <option value="profile">Profile info</option> | |
96 | + </select> | |
97 | + </div> | |
98 | + <div>offline=<input type="checkbox" checked="{{offline::change}}"></div> | |
99 | + <div>signedIn="<span>{{signedIn}}</span>"</div> | |
100 | + <div>isAuthorized="<span>{{isAuthorized}}</span>"</div> | |
101 | + <div>needAdditionalAuth:"<span>{{needAdditionalAuth}}</span>"></div> | |
102 | + </code></div> | |
103 | + <p>Every new scope you select will be added to requested scopes.</p> | |
104 | + <p>When you select a Google Plus scope, button will turn red.</p> | |
105 | + <google-signin></google-signin> | |
106 | + </p> | |
107 | + <google-signin-aware | |
108 | + scopes="{{scope}}" | |
109 | + signed-in="{{signedIn}}" | |
110 | + offline="{{offline}}" | |
111 | + is-authorized="{{isAuthorized}}" | |
112 | + need-additional-auth="{{needAdditionalAuth}}" | |
113 | + on-google-signin-aware-success="handleSignIn" | |
114 | + on-google-signin-offline-success="handleOffline" | |
115 | + on-google-signin-aware-signed-out="handleSignOut"></google-signin-aware> | |
116 | + <p>User name:<span>{{userName}}</span></p> | |
117 | + <p>Testing <code>google-signin-aware</code> events: <span>{{status}}</span></p> | |
118 | + <p>Testing <code>google-signin-offline</code> events: <span>{{offlineCode}}</span></p> | |
119 | + <p><button on-click="disconnect">Disconnect to start over</button></p> | |
120 | + </template> | |
121 | + <script> | |
122 | + var aware = document.querySelector('#awareness'); | |
123 | + aware.status = 'Not granted'; | |
124 | + aware.offlineCode = 'No offline login.'; | |
125 | + aware.userName = 'N/A'; | |
126 | + aware.handleSignIn = function(response) { | |
127 | + this.status = 'Signin granted'; | |
128 | + // console.log('[Aware] Signin Response', response); | |
129 | + this.userName = gapi.auth2.getAuthInstance().currentUser.get().getBasicProfile().getName(); | |
130 | + }; | |
131 | + aware.handleOffline = function(response) { | |
132 | + this.offlineCode = response.detail.code; | |
133 | + }; | |
134 | + aware.handleSignOut = function(response) { | |
135 | + this.status = 'Signed out'; | |
136 | + // console.log('[Aware] Signout Response', response); | |
137 | + this.userName = 'N/A'; | |
138 | + }; | |
139 | + aware.disconnect = function() { | |
140 | + var b = document.querySelector('google-signin'); | |
141 | + var currentUser = gapi.auth2.getAuthInstance().currentUser.get(); | |
142 | + if (currentUser) { | |
143 | + currentUser.disconnect(); | |
144 | + } | |
145 | + gapi.auth2.getAuthInstance().signOut(); | |
146 | + }; | |
147 | + | |
148 | + </script> | |
149 | +</body> | |
150 | +</html> | ... | ... |
bower_components/google-signin/google-icons.html
0 → 100644
1 | +<!-- | |
2 | +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. | |
3 | +This code may only be used under the BSD style license found at https://polymer.github.io/LICENSE.txt | |
4 | +The complete set of authors may be found at https://polymer.github.io/AUTHORS.txt | |
5 | +The complete set of contributors may be found at https://polymer.github.io/CONTRIBUTORS.txt | |
6 | +Code distributed by Google as part of the polymer project is also | |
7 | +subject to an additional IP rights grant found at https://polymer.github.io/PATENTS.txt | |
8 | +--> | |
9 | + | |
10 | +<link rel="import" href="../iron-icon/iron-icon.html"> | |
11 | +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> | |
12 | +<iron-iconset-svg name="google" iconSize="24"> | |
13 | +<svg><defs> | |
14 | +<g id="google"><path d="M16.3,13.4l-1.1-0.8c-0.4-0.3-0.8-0.7-0.8-1.4c0-0.7,0.5-1.3,1-1.6c1.3-1,2.6-2.1,2.6-4.3c0-2.1-1.3-3.3-2-3.9h1.7L18.9,0h-6.2C8.3,0,6.1,2.8,6.1,5.8c0,2.3,1.8,4.8,5,4.8h0.8c-0.1,0.3-0.4,0.8-0.4,1.3c0,1,0.4,1.4,0.9,2c-1.4,0.1-4,0.4-5.9,1.6c-1.8,1.1-2.3,2.6-2.3,3.7c0,2.3,2.1,4.5,6.6,4.5c5.4,0,8-3,8-5.9C18.8,15.7,17.7,14.6,16.3,13.4z M8.7,4.3c0-2.2,1.3-3.2,2.7-3.2c2.6,0,4,3.5,4,5.5c0,2.6-2.1,3.1-2.9,3.1C10,9.7,8.7,6.6,8.7,4.3z M12.3,22.3c-3.3,0-5.4-1.5-5.4-3.7c0-2.2,2-2.9,2.6-3.2c1.3-0.4,3-0.5,3.3-0.5c0.3,0,0.5,0,0.7,0c2.4,1.7,3.4,2.4,3.4,4C16.9,20.8,15,22.3,12.3,22.3z"/></g> | |
15 | +<g id="google-plus"><path d="M21,10V7h-2v3h-3v2h3v3h2v-3h3v-2H21z M13.3,13.4l-1.1-0.8c-0.4-0.3-0.8-0.7-0.8-1.4c0-0.7,0.5-1.3,1-1.6c1.3-1,2.6-2.1,2.6-4.3c0-2.1-1.3-3.3-2-3.9h1.7L15.9,0H9.7C5.3,0,3.1,2.8,3.1,5.8c0,2.3,1.8,4.8,5,4.8h0.8c-0.1,0.3-0.4,0.8-0.4,1.3c0,1,0.4,1.4,0.9,2c-1.4,0.1-4,0.4-5.9,1.6c-1.8,1.1-2.3,2.6-2.3,3.7c0,2.3,2.1,4.5,6.6,4.5c5.4,0,8-3,8-5.9C15.8,15.7,14.7,14.6,13.3,13.4z M5.7,4.3c0-2.2,1.3-3.2,2.7-3.2c2.6,0,4,3.5,4,5.5c0,2.6-2.1,3.1-2.9,3.1C7,9.7,5.7,6.6,5.7,4.3z M9.3,22.3c-3.3,0-5.4-1.5-5.4-3.7c0-2.2,2-2.9,2.6-3.2c1.3-0.4,3-0.5,3.3-0.5c0.3,0,0.5,0,0.7,0c2.4,1.7,3.4,2.4,3.4,4C13.9,20.8,12,22.3,9.3,22.3z"/></g> | |
16 | +</defs></svg> | |
17 | +</iron-iconset-svg> | ... | ... |
bower_components/google-signin/google-signin-aware.html
0 → 100644
1 | +<link rel="import" href="../polymer/polymer.html"> | |
2 | +<link rel="import" href="../google-apis/google-js-api.html"> | |
3 | + | |
4 | +<script> | |
5 | + (function() { | |
6 | + | |
7 | + /** | |
8 | + * Enum of attributes to be passed through to the login API call. | |
9 | + * @readonly | |
10 | + * @enum {string} | |
11 | + */ | |
12 | + var ProxyLoginAttributes = { | |
13 | + 'appPackageName': 'apppackagename', | |
14 | + 'clientId': 'clientid', | |
15 | + 'cookiePolicy': 'cookiepolicy', | |
16 | + 'requestVisibleActions': 'requestvisibleactions', | |
17 | + 'hostedDomain': 'hostedDomain' | |
18 | + }; | |
19 | + | |
20 | + /** | |
21 | + * AuthEngine does all interactions with gapi.auth2 | |
22 | + * | |
23 | + * It is tightly coupled with <google-signin-aware> element | |
24 | + * The elements configure AuthEngine. | |
25 | + * AuthEngine propagates all authentication events to all google-signin-aware elements | |
26 | + * | |
27 | + * API used: https://developers.google.com/identity/sign-in/web/reference | |
28 | + * | |
29 | + */ | |
30 | + var AuthEngine = { | |
31 | + | |
32 | + /** | |
33 | + * oauth2 argument, set by google-signin-aware | |
34 | + */ | |
35 | + _clientId: null, | |
36 | + | |
37 | + get clientId() { | |
38 | + return this._clientId; | |
39 | + }, | |
40 | + | |
41 | + set clientId(val) { | |
42 | + if (this._clientId && val && val != this._clientId) { | |
43 | + throw new Error('clientId cannot change. Values do not match. New: ' + val + ' Old:' + this._clientId); | |
44 | + } | |
45 | + if (val) { | |
46 | + this._clientId = val; | |
47 | + this.initAuth2(); | |
48 | + } | |
49 | + }, | |
50 | + | |
51 | + /** | |
52 | + * oauth2 argument, set by google-signin-aware | |
53 | + */ | |
54 | + _cookiePolicy: 'single_host_origin', | |
55 | + | |
56 | + get cookiePolicy() { | |
57 | + return this._cookiePolicy; | |
58 | + }, | |
59 | + | |
60 | + set cookiePolicy(val) { | |
61 | + if (val) { | |
62 | + this._cookiePolicy = val; | |
63 | + } | |
64 | + }, | |
65 | + | |
66 | + /** | |
67 | + * oauth2 argument, set by google-signin-aware | |
68 | + */ | |
69 | + _appPackageName: '', | |
70 | + | |
71 | + get appPackageName() { | |
72 | + return this._appPackageName; | |
73 | + }, | |
74 | + | |
75 | + set appPackageName(val) { | |
76 | + if (this._appPackageName && val && val != this._appPackageName) { | |
77 | + throw new Error('appPackageName cannot change. Values do not match. New: ' + val + ' Old: ' + this._appPackageName); | |
78 | + } | |
79 | + if (val) { | |
80 | + this._appPackageName = val; | |
81 | + } | |
82 | + }, | |
83 | + | |
84 | + /** | |
85 | + * oauth2 argument, set by google-signin-aware | |
86 | + */ | |
87 | + _requestVisibleActions: '', | |
88 | + | |
89 | + get requestVisibleactions() { | |
90 | + return this._requestVisibleActions; | |
91 | + }, | |
92 | + | |
93 | + set requestVisibleactions(val) { | |
94 | + if (this._requestVisibleActions && val && val != this._requestVisibleActions) { | |
95 | + throw new Error('requestVisibleactions cannot change. Values do not match. New: ' + val + ' Old: ' + this._requestVisibleActions); | |
96 | + } | |
97 | + if (val) | |
98 | + this._requestVisibleActions = val; | |
99 | + }, | |
100 | + | |
101 | + /** | |
102 | + * oauth2 argument, set by google-signin-aware | |
103 | + */ | |
104 | + _hostedDomain: '', | |
105 | + | |
106 | + get hostedDomain() { | |
107 | + return this._hostedDomain; | |
108 | + }, | |
109 | + | |
110 | + set hostedDomain(val) { | |
111 | + if (this._hostedDomain && val && val != this._hostedDomain) { | |
112 | + throw new Error('hostedDomain cannot change. Values do not match. New: ' + val + ' Old: ' + this._hostedDomain); | |
113 | + } | |
114 | + if (val) | |
115 | + this._hostedDomain = val; | |
116 | + }, | |
117 | + | |
118 | + /** Is offline access currently enabled in the google-signin-aware element? */ | |
119 | + _offline: false, | |
120 | + | |
121 | + get offline() { | |
122 | + return this._offline; | |
123 | + }, | |
124 | + | |
125 | + set offline(val) { | |
126 | + this._offline = val; | |
127 | + this.updateAdditionalAuth(); | |
128 | + }, | |
129 | + | |
130 | + /** Should we force a re-prompt for offline access? */ | |
131 | + _offlineAlwaysPrompt: false, | |
132 | + | |
133 | + get offlineAlwaysPrompt() { | |
134 | + return this._offlineAlwaysPrompt; | |
135 | + }, | |
136 | + | |
137 | + set offlineAlwaysPrompt(val) { | |
138 | + this._offlineAlwaysPrompt = val; | |
139 | + this.updateAdditionalAuth(); | |
140 | + }, | |
141 | + | |
142 | + /** Have we already gotten offline access from Google during this session? */ | |
143 | + offlineGranted: false, | |
144 | + | |
145 | + /** <google-js-api> */ | |
146 | + _apiLoader: null, | |
147 | + | |
148 | + /** an array of wanted scopes. oauth2 argument */ | |
149 | + _requestedScopeArray: [], | |
150 | + | |
151 | + /** _requestedScopeArray as string */ | |
152 | + get requestedScopes() { | |
153 | + return this._requestedScopeArray.join(' '); | |
154 | + }, | |
155 | + | |
156 | + /** Is user signed in? */ | |
157 | + _signedIn: false, | |
158 | + | |
159 | + /** Currently granted scopes */ | |
160 | + _grantedScopeArray: [], | |
161 | + | |
162 | + /** True if additional authorization is required */ | |
163 | + _needAdditionalAuth: true, | |
164 | + | |
165 | + /** True if have google+ scopes */ | |
166 | + _hasPlusScopes: false, | |
167 | + | |
168 | + /** | |
169 | + * array of <google-signin-aware> | |
170 | + * state changes are broadcast to them | |
171 | + */ | |
172 | + signinAwares: [], | |
173 | + | |
174 | + init: function() { | |
175 | + this._apiLoader = document.createElement('google-js-api'); | |
176 | + this._apiLoader.addEventListener('js-api-load', this.loadAuth2.bind(this)); | |
177 | + }, | |
178 | + | |
179 | + loadAuth2: function() { | |
180 | + gapi.load('auth2', this.initAuth2.bind(this)); | |
181 | + }, | |
182 | + | |
183 | + initAuth2: function() { | |
184 | + if (!('gapi' in window) || !('auth2' in window.gapi) || !this.clientId) { | |
185 | + return; | |
186 | + } | |
187 | + var auth = gapi.auth2.init({ | |
188 | + 'client_id': this.clientId, | |
189 | + 'cookie_policy': this.cookiePolicy, | |
190 | + 'scope': this.requestedScopes, | |
191 | + 'hosted_domain': this.hostedDomain | |
192 | + }); | |
193 | + | |
194 | + auth.currentUser.listen(this.handleUserUpdate.bind(this)); | |
195 | + | |
196 | + auth.then( | |
197 | + function success() { | |
198 | + // Let the current user listener trigger the changes. | |
199 | + }, | |
200 | + function error(error) { | |
201 | + console.error(error); | |
202 | + } | |
203 | + ); | |
204 | + }, | |
205 | + | |
206 | + handleUserUpdate: function(newPrimaryUser) { | |
207 | + // update and broadcast currentUser | |
208 | + var isSignedIn = newPrimaryUser.isSignedIn(); | |
209 | + if (isSignedIn != this._signedIn) { | |
210 | + this._signedIn = isSignedIn; | |
211 | + for (var i=0; i<this.signinAwares.length; i++) { | |
212 | + this.signinAwares[i]._setSignedIn(isSignedIn); | |
213 | + } | |
214 | + } | |
215 | + | |
216 | + // update granted scopes | |
217 | + this._grantedScopeArray = this.strToScopeArray( | |
218 | + newPrimaryUser.getGrantedScopes()); | |
219 | + // console.log(this._grantedScopeArray); | |
220 | + this.updateAdditionalAuth(); | |
221 | + | |
222 | + var response = newPrimaryUser.getAuthResponse(); | |
223 | + for (var i=0; i<this.signinAwares.length; i++) { | |
224 | + this.signinAwares[i]._updateScopeStatus(response); | |
225 | + } | |
226 | + }, | |
227 | + | |
228 | + setOfflineCode: function(code) { | |
229 | + for (var i=0; i<this.signinAwares.length; i++) { | |
230 | + this.signinAwares[i]._updateOfflineCode(code); | |
231 | + } | |
232 | + }, | |
233 | + | |
234 | + /** convert scope string to scope array */ | |
235 | + strToScopeArray: function(str) { | |
236 | + if (!str) { | |
237 | + return []; | |
238 | + } | |
239 | + // remove extra spaces, then split | |
240 | + var scopes = str.replace(/\ +/g, ' ').trim().split(' '); | |
241 | + for (var i=0; i<scopes.length; i++) { | |
242 | + scopes[i] = scopes[i].toLowerCase(); | |
243 | + // Handle scopes that will be deprecated but are still returned with their old value | |
244 | + if (scopes[i] === 'https://www.googleapis.com/auth/userinfo.profile') { | |
245 | + scopes[i] = 'profile'; | |
246 | + } | |
247 | + if (scopes[i] === 'https://www.googleapis.com/auth/userinfo.email') { | |
248 | + scopes[i] = 'email'; | |
249 | + } | |
250 | + } | |
251 | + // return with duplicates filtered out | |
252 | + return scopes.filter( function(value, index, self) { | |
253 | + return self.indexOf(value) === index; | |
254 | + }); | |
255 | + }, | |
256 | + | |
257 | + /** true if scopes have google+ scopes */ | |
258 | + isPlusScope: function(scope) { | |
259 | + return (scope.indexOf('/auth/games') > -1) | |
260 | + || (scope.indexOf('auth/plus.') > -1 && scope.indexOf('auth/plus.me') < 0); | |
261 | + }, | |
262 | + | |
263 | + /** true if scopes have been granted */ | |
264 | + hasGrantedScopes: function(scopeStr) { | |
265 | + var scopes = this.strToScopeArray(scopeStr); | |
266 | + for (var i=0; i< scopes.length; i++) { | |
267 | + if (this._grantedScopeArray.indexOf(scopes[i]) === -1) | |
268 | + return false; | |
269 | + } | |
270 | + return true; | |
271 | + }, | |
272 | + | |
273 | + /** request additional scopes */ | |
274 | + requestScopes: function(newScopeStr) { | |
275 | + var newScopes = this.strToScopeArray(newScopeStr); | |
276 | + var scopesUpdated = false; | |
277 | + for (var i=0; i<newScopes.length; i++) { | |
278 | + if (this._requestedScopeArray.indexOf(newScopes[i]) === -1) { | |
279 | + this._requestedScopeArray.push(newScopes[i]); | |
280 | + scopesUpdated = true; | |
281 | + } | |
282 | + } | |
283 | + if (scopesUpdated) { | |
284 | + this.updateAdditionalAuth(); | |
285 | + this.updatePlusScopes(); | |
286 | + } | |
287 | + }, | |
288 | + | |
289 | + /** update status of _needAdditionalAuth */ | |
290 | + updateAdditionalAuth: function() { | |
291 | + var needMoreAuth = false; | |
292 | + if ((this.offlineAlwaysPrompt || this.offline ) && !this.offlineGranted) { | |
293 | + needMoreAuth = true; | |
294 | + } else { | |
295 | + for (var i=0; i<this._requestedScopeArray.length; i++) { | |
296 | + if (this._grantedScopeArray.indexOf(this._requestedScopeArray[i]) === -1) { | |
297 | + needMoreAuth = true; | |
298 | + break; | |
299 | + } | |
300 | + } | |
301 | + } | |
302 | + if (this._needAdditionalAuth != needMoreAuth) { | |
303 | + this._needAdditionalAuth = needMoreAuth; | |
304 | + // broadcast new value | |
305 | + for (var i=0; i<this.signinAwares.length; i++) { | |
306 | + this.signinAwares[i]._setNeedAdditionalAuth(needMoreAuth); | |
307 | + } | |
308 | + } | |
309 | + }, | |
310 | + | |
311 | + updatePlusScopes: function() { | |
312 | + var hasPlusScopes = false; | |
313 | + for (var i = 0; i < this._requestedScopeArray.length; i++) { | |
314 | + if (this.isPlusScope(this._requestedScopeArray[i])) { | |
315 | + hasPlusScopes = true; | |
316 | + break; | |
317 | + } | |
318 | + } | |
319 | + if (this._hasPlusScopes != hasPlusScopes) { | |
320 | + this._hasPlusScopes = hasPlusScopes; | |
321 | + for (var i=0; i<this.signinAwares.length; i++) { | |
322 | + this.signinAwares[i]._setHasPlusScopes(hasPlusScopes); | |
323 | + } | |
324 | + } | |
325 | + }, | |
326 | + /** | |
327 | + * attached <google-signin-aware> | |
328 | + * @param {<google-signin-aware>} aware element to add | |
329 | + */ | |
330 | + attachSigninAware: function(aware) { | |
331 | + if (this.signinAwares.indexOf(aware) == -1) { | |
332 | + this.signinAwares.push(aware); | |
333 | + // Initialize aware properties | |
334 | + aware._setNeedAdditionalAuth(this._needAdditionalAuth); | |
335 | + aware._setSignedIn(this._signedIn); | |
336 | + aware._setHasPlusScopes(this._hasPlusScopes); | |
337 | + } else { | |
338 | + console.warn('signinAware attached more than once', aware); | |
339 | + } | |
340 | + }, | |
341 | + | |
342 | + detachSigninAware: function(aware) { | |
343 | + var index = this.signinAwares.indexOf(aware); | |
344 | + if (index != -1) { | |
345 | + this.signinAwares.splice(index, 1); | |
346 | + } else { | |
347 | + console.warn('Trying to detach unattached signin-aware'); | |
348 | + } | |
349 | + }, | |
350 | + | |
351 | + /** returns scopes not granted */ | |
352 | + getMissingScopes: function() { | |
353 | + return this._requestedScopeArray.filter( function(scope) { | |
354 | + return this._grantedScopeArray.indexOf(scope) === -1; | |
355 | + }.bind(this)).join(' '); | |
356 | + }, | |
357 | + | |
358 | + assertAuthInitialized: function() { | |
359 | + if (!this.clientId) { | |
360 | + throw new Error("AuthEngine not initialized. clientId has not been configured."); | |
361 | + } | |
362 | + if (!('gapi' in window)) { | |
363 | + throw new Error("AuthEngine not initialized. gapi has not loaded."); | |
364 | + } | |
365 | + if (!('auth2' in window.gapi)) { | |
366 | + throw new Error("AuthEngine not initialized. auth2 not loaded."); | |
367 | + } | |
368 | + }, | |
369 | + | |
370 | + /** pops up sign-in dialog */ | |
371 | + signIn: function() { | |
372 | + this.assertAuthInitialized(); | |
373 | + var params = { | |
374 | + 'scope': this.getMissingScopes() | |
375 | + }; | |
376 | + | |
377 | + // Proxy specific attributes through to the signIn options. | |
378 | + Object.keys(ProxyLoginAttributes).forEach(function(key) { | |
379 | + if (this[key] && this[key] !== '') { | |
380 | + params[ProxyLoginAttributes[key]] = this[key]; | |
381 | + } | |
382 | + }, this); | |
383 | + | |
384 | + var promise; | |
385 | + var user = gapi.auth2.getAuthInstance().currentUser.get(); | |
386 | + if (!(this.offline || this.offlineAlwaysPrompt)) { | |
387 | + if (user.getGrantedScopes()) { | |
388 | + // additional auth, skip multiple account dialog | |
389 | + promise = user.grant(params); | |
390 | + } else { | |
391 | + // initial signin | |
392 | + promise = gapi.auth2.getAuthInstance().signIn(params); | |
393 | + } | |
394 | + } else { | |
395 | + params.redirect_uri = 'postmessage'; | |
396 | + if (this.offlineAlwaysPrompt) { | |
397 | + params.approval_prompt = 'force'; | |
398 | + } | |
399 | + | |
400 | + // Despite being documented at https://goo.gl/tiO0Bk | |
401 | + // It doesn't seem like user.grantOfflineAccess() actually exists in | |
402 | + // the current version of the Google Sign-In JS client we're using | |
403 | + // through GoogleWebComponents. So in the offline case, we will not | |
404 | + // distinguish between a first auth and an additional one. | |
405 | + promise = gapi.auth2.getAuthInstance().grantOfflineAccess(params); | |
406 | + } | |
407 | + promise.then( | |
408 | + function success(response) { | |
409 | + // If login was offline, response contains one string "code" | |
410 | + // Otherwise it contains the user object already | |
411 | + var newUser; | |
412 | + if (response.code) { | |
413 | + AuthEngine.offlineGranted = true; | |
414 | + newUser = gapi.auth2.getAuthInstance().currentUser.get(); | |
415 | + AuthEngine.setOfflineCode(response.code); | |
416 | + } else { | |
417 | + newUser = response; | |
418 | + } | |
419 | + | |
420 | + var authResponse = newUser.getAuthResponse(); | |
421 | + // Let the current user listener trigger the changes. | |
422 | + }, | |
423 | + function error(error) { | |
424 | + if ("Access denied." == error.reason) { | |
425 | + // Access denied is not an error, user hit cancel | |
426 | + return; | |
427 | + } else { | |
428 | + console.error(error); | |
429 | + } | |
430 | + } | |
431 | + ); | |
432 | + }, | |
433 | + | |
434 | + /** signs user out */ | |
435 | + signOut: function() { | |
436 | + this.assertAuthInitialized(); | |
437 | + gapi.auth2.getAuthInstance().signOut().then( | |
438 | + function success() { | |
439 | + // Let the current user listener trigger the changes. | |
440 | + }, | |
441 | + function error(error) { | |
442 | + console.error(error); | |
443 | + } | |
444 | + ); | |
445 | + } | |
446 | + }; | |
447 | + | |
448 | + AuthEngine.init(); | |
449 | + | |
450 | +/** | |
451 | +`google-signin-aware` is used to enable authentication in custom elements by | |
452 | +interacting with a google-signin element that needs to be present somewhere | |
453 | +on the page. | |
454 | + | |
455 | +The `scopes` attribute allows you to specify which scope permissions are required | |
456 | +(e.g do you want to allow interaction with the Google Drive API). | |
457 | + | |
458 | +The `google-signin-aware-success` event is triggered when a user successfully | |
459 | +authenticates. If either `offline` or `offlineAlwaysPrompt` is set to true, successful | |
460 | +authentication will also trigger the `google-signin-offline-success`event. | |
461 | +The `google-signin-aware-signed-out` event is triggered when a user explicitly | |
462 | +signs out via the google-signin element. | |
463 | + | |
464 | +You can bind to `isAuthorized` property to monitor authorization state. | |
465 | +##### Example | |
466 | + | |
467 | + <google-signin-aware scopes="https://www.googleapis.com/auth/drive"></google-signin-aware> | |
468 | + | |
469 | + | |
470 | +##### Example with offline | |
471 | + <template id="awareness" is="dom-bind"> | |
472 | + <google-signin-aware | |
473 | + scopes="https://www.googleapis.com/auth/drive" | |
474 | + offline | |
475 | + on-google-signin-aware-success="handleSignin" | |
476 | + on-google-signin-offline-success="handleOffline"></google-signin-aware> | |
477 | + <\/template> | |
478 | + <script> | |
479 | + var aware = document.querySelector('#awareness'); | |
480 | + aware.handleSignin = function(response) { | |
481 | + var user = gapi.auth2.getAuthInstance().currentUser.get(); | |
482 | + console.log('User name: ' + user.getBasicProfile().getName()); | |
483 | + }; | |
484 | + aware.handleOffline = function(response) { | |
485 | + console.log('Offline code received: ' + response.detail.code); | |
486 | + // Here you would POST response.detail.code to your webserver, which can | |
487 | + // exchange the authorization code for an access token. More info at: | |
488 | + // https://developers.google.com/identity/protocols/OAuth2WebServer | |
489 | + }; | |
490 | + <\/script> | |
491 | +*/ | |