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 | +*/ | |
| 492 | + Polymer({ | |
| 493 | + | |
| 494 | + is: 'google-signin-aware', | |
| 495 | + | |
| 496 | + /** | |
| 497 | + * Fired when this scope has been authorized | |
| 498 | + * @param {Object} result Authorization result. | |
| 499 | + * @event google-signin-aware-success | |
| 500 | + */ | |
| 501 | + /** | |
| 502 | + * Fired when an offline authorization is successful. | |
| 503 | + * @param {Object} detail | |
| 504 | + * @param {string} detail.code The one-time authorization code from Google. | |
| 505 | + * Your application can exchange this for an `access_token` and `refresh_token` | |
| 506 | + * @event google-signin-offline-success | |
| 507 | + */ | |
| 508 | + /** | |
| 509 | + * Fired when this scope is not authorized | |
| 510 | + * @event google-signin-aware-signed-out | |
| 511 | + */ | |
| 512 | + properties: { | |
| 513 | + /** | |
| 514 | + * App package name for android over-the-air installs. | |
| 515 | + * See the relevant [docs](https://developers.google.com/+/web/signin/android-app-installs) | |
| 516 | + */ | |
| 517 | + appPackageName: { | |
| 518 | + type: String, | |
| 519 | + observer: '_appPackageNameChanged' | |
| 520 | + }, | |
| 521 | + /** | |
| 522 | + * a Google Developers clientId reference | |
| 523 | + */ | |
| 524 | + clientId: { | |
| 525 | + type: String, | |
| 526 | + observer: '_clientIdChanged' | |
| 527 | + }, | |
| 528 | + | |
| 529 | + /** | |
| 530 | + * The cookie policy defines what URIs have access to the session cookie | |
| 531 | + * remembering the user's sign-in state. | |
| 532 | + * See the relevant [docs](https://developers.google.com/+/web/signin/reference#determining_a_value_for_cookie_policy) for more information. | |
| 533 | + * @default 'single_host_origin' | |
| 534 | + */ | |
| 535 | + cookiePolicy: { | |
| 536 | + type: String, | |
| 537 | + observer: '_cookiePolicyChanged' | |
| 538 | + }, | |
| 539 | + | |
| 540 | + /** | |
| 541 | + * The app activity types you want to write on behalf of the user | |
| 542 | + * (e.g http://schemas.google.com/AddActivity) | |
| 543 | + * | |
| 544 | + */ | |
| 545 | + requestVisibleActions: { | |
| 546 | + type: String, | |
| 547 | + observer: '_requestVisibleActionsChanged' | |
| 548 | + }, | |
| 549 | + | |
| 550 | + /** | |
| 551 | + * The Google Apps domain to which users must belong to sign in. | |
| 552 | + * See the relevant [docs](https://developers.google.com/identity/sign-in/web/reference) for more information. | |
| 553 | + */ | |
| 554 | + hostedDomain: { | |
| 555 | + type: String, | |
| 556 | + observer: '_hostedDomainChanged' | |
| 557 | + }, | |
| 558 | + | |
| 559 | + /** | |
| 560 | + * Allows for offline `access_token` retrieval during the signin process. | |
| 561 | + * See also `offlineAlwaysPrompt`. You only need to set one of the two; if both | |
| 562 | + * are set, the behavior of `offlineAlwaysPrompt` will override `offline`. | |
| 563 | + */ | |
| 564 | + offline: { | |
| 565 | + type: Boolean, | |
| 566 | + value: false, | |
| 567 | + observer: '_offlineChanged' | |
| 568 | + }, | |
| 569 | + | |
| 570 | + /** | |
| 571 | + * Works the same as `offline` with the addition that it will always | |
| 572 | + * force a re-prompt to the user, guaranteeing that you will get a | |
| 573 | + * refresh_token even if the user has already granted offline access to | |
| 574 | + * this application. You only need to set one of `offline` or | |
| 575 | + * `offlineAlwaysPrompt`, not both. | |
| 576 | + */ | |
| 577 | + offlineAlwaysPrompt: { | |
| 578 | + type: Boolean, | |
| 579 | + value: false, | |
| 580 | + observer: '_offlineAlwaysPromptChanged' | |
| 581 | + }, | |
| 582 | + | |
| 583 | + /** | |
| 584 | + * The scopes to provide access to (e.g https://www.googleapis.com/auth/drive) | |
| 585 | + * and should be space-delimited. | |
| 586 | + */ | |
| 587 | + scopes: { | |
| 588 | + type: String, | |
| 589 | + value: 'profile', | |
| 590 | + observer: '_scopesChanged' | |
| 591 | + }, | |
| 592 | + | |
| 593 | + /** | |
| 594 | + * True if user is signed in | |
| 595 | + */ | |
| 596 | + signedIn: { | |
| 597 | + type: Boolean, | |
| 598 | + notify: true, | |
| 599 | + readOnly: true | |
| 600 | + }, | |
| 601 | + | |
| 602 | + /** | |
| 603 | + * True if authorizations for *this* element have been granted | |
| 604 | + */ | |
| 605 | + isAuthorized: { | |
| 606 | + type: Boolean, | |
| 607 | + notify: true, | |
| 608 | + readOnly: true, | |
| 609 | + value: false | |
| 610 | + }, | |
| 611 | + | |
| 612 | + /** | |
| 613 | + * True if additional authorizations for *any* element are required | |
| 614 | + */ | |
| 615 | + needAdditionalAuth: { | |
| 616 | + type: Boolean, | |
| 617 | + notify: true, | |
| 618 | + readOnly: true | |
| 619 | + }, | |
| 620 | + | |
| 621 | + /** | |
| 622 | + * True if *any* element has google+ scopes | |
| 623 | + */ | |
| 624 | + hasPlusScopes: { | |
| 625 | + type: Boolean, | |
| 626 | + value: false, | |
| 627 | + notify: true, | |
| 628 | + readOnly: true | |
| 629 | + } | |
| 630 | + }, | |
| 631 | + | |
| 632 | + attached: function() { | |
| 633 | + AuthEngine.attachSigninAware(this); | |
| 634 | + }, | |
| 635 | + | |
| 636 | + detached: function() { | |
| 637 | + AuthEngine.detachSigninAware(this); | |
| 638 | + }, | |
| 639 | + | |
| 640 | + /** pops up the authorization dialog */ | |
| 641 | + signIn: function() { | |
| 642 | + AuthEngine.signIn(); | |
| 643 | + }, | |
| 644 | + | |
| 645 | + /** signs user out */ | |
| 646 | + signOut: function() { | |
| 647 | + AuthEngine.signOut(); | |
| 648 | + }, | |
| 649 | + | |
| 650 | + _appPackageNameChanged: function(newName, oldName) { | |
| 651 | + AuthEngine.appPackageName = newName; | |
| 652 | + }, | |
| 653 | + | |
| 654 | + _clientIdChanged: function(newId, oldId) { | |
| 655 | + AuthEngine.clientId = newId; | |
| 656 | + }, | |
| 657 | + | |
| 658 | + _cookiePolicyChanged: function(newPolicy, oldPolicy) { | |
| 659 | + AuthEngine.cookiePolicy = newPolicy; | |
| 660 | + }, | |
| 661 | + | |
| 662 | + _requestVisibleActionsChanged: function(newVal, oldVal) { | |
| 663 | + AuthEngine.requestVisibleActions = newVal; | |
| 664 | + }, | |
| 665 | + | |
| 666 | + _hostedDomainChanged: function(newVal, oldVal) { | |
| 667 | + AuthEngine.hostedDomain = newVal; | |
| 668 | + }, | |
| 669 | + | |
| 670 | + _offlineChanged: function(newVal, oldVal) { | |
| 671 | + AuthEngine.offline = newVal; | |
| 672 | + }, | |
| 673 | + | |
| 674 | + _offlineAlwaysPromptChanged: function(newVal, oldVal) { | |
| 675 | + AuthEngine.offlineAlwaysPrompt = newVal; | |
| 676 | + }, | |
| 677 | + | |
| 678 | + _scopesChanged: function(newVal, oldVal) { | |
| 679 | + AuthEngine.requestScopes(newVal); | |
| 680 | + this._updateScopeStatus(); | |
| 681 | + }, | |
| 682 | + | |
| 683 | + _updateScopeStatus: function(user) { | |
| 684 | + var newAuthorized = this.signedIn && AuthEngine.hasGrantedScopes(this.scopes); | |
| 685 | + if (newAuthorized !== this.isAuthorized) { | |
| 686 | + this._setIsAuthorized(newAuthorized); | |
| 687 | + if (newAuthorized) { | |
| 688 | + this.fire('google-signin-aware-success', user); | |
| 689 | + } | |
| 690 | + else { | |
| 691 | + this.fire('google-signin-aware-signed-out', user); | |
| 692 | + } | |
| 693 | + } | |
| 694 | + }, | |
| 695 | + | |
| 696 | + _updateOfflineCode: function(code) { | |
| 697 | + if (code) { | |
| 698 | + this.fire('google-signin-offline-success', {code: code}); | |
| 699 | + } | |
| 700 | + } | |
| 701 | + }); | |
| 702 | + })(); | |
| 703 | +</script> | ... | ... |
bower_components/google-signin/google-signin.css
0 → 100644
| 1 | +:host { | |
| 2 | + display: inline-block; | |
| 3 | + position: relative; | |
| 4 | + box-sizing: border-box; | |
| 5 | + margin: 0 0.29em; | |
| 6 | + background: transparent; | |
| 7 | + text-align: center; | |
| 8 | + font: inherit; | |
| 9 | + outline: none; | |
| 10 | + border-radius: 3px; | |
| 11 | + -webkit-user-select: none; | |
| 12 | + user-select: none; | |
| 13 | + cursor: pointer; | |
| 14 | + z-index: 0; | |
| 15 | +} | |
| 16 | + | |
| 17 | +:host([disabled]) { | |
| 18 | + cursor: auto; | |
| 19 | + pointer-events: none; | |
| 20 | +} | |
| 21 | + | |
| 22 | +:host([disabled]) #button { | |
| 23 | + background: #eaeaea; | |
| 24 | + color: #a8a8a8; | |
| 25 | +} | |
| 26 | + | |
| 27 | +#button { | |
| 28 | + position: relative; | |
| 29 | + outline: none; | |
| 30 | + font-size: 14px; | |
| 31 | + font-weight: 400; | |
| 32 | + font-family: 'RobotoDraft','Roboto',arial,sans-serif; | |
| 33 | + white-space: nowrap; | |
| 34 | + border-radius: inherit; | |
| 35 | +} | |
| 36 | + | |
| 37 | +iron-icon { | |
| 38 | + width: 22px; | |
| 39 | + height: 22px; | |
| 40 | + margin: 6px; | |
| 41 | +} | |
| 42 | + | |
| 43 | +.icon { | |
| 44 | + display: inline-block; | |
| 45 | + vertical-align: middle; | |
| 46 | +} | |
| 47 | + | |
| 48 | +#shadow { | |
| 49 | + border-radius: inherit; | |
| 50 | +} | |
| 51 | + | |
| 52 | +#ripple { | |
| 53 | + pointer-events: none; | |
| 54 | +} | |
| 55 | + | |
| 56 | +.button-content { | |
| 57 | + outline: none; | |
| 58 | +} | |
| 59 | + | |
| 60 | +.buttonText { | |
| 61 | + display: inline-block; | |
| 62 | + vertical-align: middle; | |
| 63 | + padding-right: .8em; | |
| 64 | +} | |
| 65 | + | |
| 66 | +/* | |
| 67 | + * Dark Theme | |
| 68 | + */ | |
| 69 | +.theme-dark { | |
| 70 | + background: #da4336; | |
| 71 | + color: #ffffff; | |
| 72 | + border: 1px solid transparent; | |
| 73 | +} | |
| 74 | + | |
| 75 | +.theme-dark.signedIn-true.additionalAuth-false { | |
| 76 | + background: #999; | |
| 77 | + border: 1px solid #888; | |
| 78 | +} | |
| 79 | + | |
| 80 | +.theme-dark.signedIn-true.additionalAuth-false:hover, | |
| 81 | +.theme-dark.signedIn-true.additionalAuth-false:focus { | |
| 82 | + background: #aaa; | |
| 83 | +} | |
| 84 | + | |
| 85 | +:host([noink]) .theme-dark:hover, | |
| 86 | +:host([noink]) .theme-dark:focus { | |
| 87 | + background: #e74b37; | |
| 88 | +} | |
| 89 | + | |
| 90 | +:host([noink]) .theme-dark.signedIn-true.additionalAuth-false:hover, | |
| 91 | +:host([noink]) .theme-dark.signedIn-true.additionalAuth-false:focus { | |
| 92 | + background: #aaa; | |
| 93 | +} | |
| 94 | + | |
| 95 | +/* | |
| 96 | + * Light Theme | |
| 97 | + */ | |
| 98 | +.theme-light { | |
| 99 | + background: #fff; | |
| 100 | + color: #737373; | |
| 101 | + border: 1px solid #d9d9d9; | |
| 102 | +} | |
| 103 | + | |
| 104 | +.theme-light.signedIn-true.additionalAuth-false { | |
| 105 | + background: #c0c0c0; | |
| 106 | + color: #fff; | |
| 107 | + border: #888 1px solid; | |
| 108 | +} | |
| 109 | + | |
| 110 | +.theme-light.signedIn-true.additionalAuth-false:hover, | |
| 111 | +.theme-light.signedIn-true.additionalAuth-false:focus { | |
| 112 | + background: #aaa; | |
| 113 | +} | |
| 114 | + | |
| 115 | +:host([noink]) .theme-light .button-content:hover, | |
| 116 | +:host([noink]) .theme-light:focus { | |
| 117 | + border: 1px solid #c0c0c0; | |
| 118 | +} | |
| 119 | + | |
| 120 | +:host([noink]) .theme-light.signedIn-true.additionalAuth-false:hover, | |
| 121 | +:host([noink]) .theme-light.signedIn-true.additionalAuth-false:focus { | |
| 122 | + background: #aaa; | |
| 123 | +} | |
| 124 | + | |
| 125 | +/* | |
| 126 | + * Icon Only Width | |
| 127 | + */ | |
| 128 | +.width-iconOnly .buttonText { | |
| 129 | + display: none; | |
| 130 | +} | |
| 131 | + | |
| 132 | +/* | |
| 133 | + * Tall Height | |
| 134 | + */ | |
| 135 | +.height-tall .buttonText { | |
| 136 | + font-size: 15px; | |
| 137 | + font-weight: 700; | |
| 138 | +} | |
| 139 | + | |
| 140 | +.height-tall iron-icon { | |
| 141 | + width: 30px; | |
| 142 | + height: 30px; | |
| 143 | + margin: 8px; | |
| 144 | +} | |
| 145 | + | |
| 146 | +/* | |
| 147 | + * Short Height | |
| 148 | + */ | |
| 149 | +.height-short .buttonText { | |
| 150 | + font-size: 11px; | |
| 151 | +} | |
| 152 | + | |
| 153 | +.height-short iron-icon { | |
| 154 | + width: 16px; | |
| 155 | + height: 16px; | |
| 156 | + margin: 3px; | |
| 157 | +} | |
| 158 | + | |
| 159 | + | |
| 160 | +/* | |
| 161 | + * Branding | |
| 162 | + */ | |
| 163 | + | |
| 164 | +/* Google Scopes */ | |
| 165 | + | |
| 166 | +/* Dark Theme */ | |
| 167 | +.brand-google.theme-dark { | |
| 168 | + background: #4184F3; | |
| 169 | + color: #fff; | |
| 170 | + border: 1px solid #3266d5; | |
| 171 | +} | |
| 172 | + | |
| 173 | +.brand-google.theme-dark #ripple { | |
| 174 | + color: #1b39a8; | |
| 175 | +} | |
| 176 | + | |
| 177 | +:host([noink]) .brand-google.theme-dark:hover, | |
| 178 | +:host([noink]) .brand-google.theme-dark:focus { | |
| 179 | + background: #e74b37; | |
| 180 | +} | |
| 181 | + | |
| 182 | +.brand-google.theme-light .icon { | |
| 183 | + color: #4184F3; | |
| 184 | +} | |
| 185 | + | |
| 186 | +.brand-google.theme-light.signedIn-true.additionalAuth-false .icon { | |
| 187 | + color: #fff; | |
| 188 | +} | |
| 189 | + | |
| 190 | +.brand-google.theme-light #ripple { | |
| 191 | + color: #444; | |
| 192 | +} | |
| 193 | + | |
| 194 | +:host([noink]) .brand-google.theme-light:hover, | |
| 195 | +:host([noink]) .brand-google.theme-light:focus { | |
| 196 | + border: 1px solid #c0c0c0; | |
| 197 | +} | |
| 198 | + | |
| 199 | +.brand-google-plus.theme-dark { | |
| 200 | + background: #da4336; | |
| 201 | + color: #fff; | |
| 202 | + border: 1px solid transparent; | |
| 203 | +} | |
| 204 | + | |
| 205 | +.brand-google-plus.theme-dark #ripple { | |
| 206 | + color: #c43828; | |
| 207 | +} | |
| 208 | + | |
| 209 | +/* Light Theme */ | |
| 210 | +.brand-google-plus.theme-light { | |
| 211 | + background: #fff; | |
| 212 | + color: #737373; | |
| 213 | + border: 1px solid #d9d9d9; | |
| 214 | +} | |
| 215 | + | |
| 216 | +.brand-google-plus.theme-light .icon { | |
| 217 | + color: #e74b37; | |
| 218 | +} | |
| 219 | + | |
| 220 | +.brand-google-plus.theme-light.signedIn-true.additionalAuth-false .icon { | |
| 221 | + color: #fff; | |
| 222 | +} | |
| 223 | + | |
| 224 | +.brand-google-plus.theme-light #ripple { | |
| 225 | + color: #400; | |
| 226 | +} | |
| 227 | + | |
| 228 | +:host([noink]) .brand-google-plus.theme-light:hover, | |
| 229 | +:host([noink]) .brand-google-plus.theme-light:focus { | |
| 230 | + border: 1px solid #c0c0c0; | |
| 231 | +} | ... | ... |
bower_components/google-signin/google-signin.html
0 → 100644
| 1 | +<link rel="import" href="../polymer/polymer.html"> | |
| 2 | +<link rel="import" href="google-signin-aware.html"> | |
| 3 | +<link rel="import" href="../iron-icon/iron-icon.html"> | |
| 4 | +<link rel="import" href="../iron-icons/iron-icons.html"> | |
| 5 | +<link rel="import" href="../font-roboto/roboto.html"> | |
| 6 | +<link rel="import" href="../google-apis/google-js-api.html"> | |
| 7 | +<link rel="import" href="../paper-ripple/paper-ripple.html"> | |
| 8 | +<link rel="import" href="../paper-material/paper-material.html"> | |
| 9 | +<link rel="import" href="../iron-flex-layout/classes/iron-flex-layout.html"> | |
| 10 | +<link rel="import" href="google-icons.html"> | |
| 11 | + | |
| 12 | +<dom-module id="google-signin"> | |
| 13 | + <link rel="import" type="css" href="google-signin.css"> | |
| 14 | + <template> | |
| 15 | + <google-signin-aware id="aware" | |
| 16 | + app-package-name="{{appPackageName}}" | |
| 17 | + client-id="{{clientId}}" | |
| 18 | + cookie-policy="{{cookiePolicy}}" | |
| 19 | + request-visible-actions="{{requestVisibleActions}}" | |
| 20 | + hosted-domain="{{hostedDomain}}" | |
| 21 | + offline="{{offline}}" | |
| 22 | + offline-always-prompt="{{offlineAlwaysPrompt}}" | |
| 23 | + scopes="{{scopes}}" | |
| 24 | + signed-in="{{signedIn}}" | |
| 25 | + is-authorized="{{isAuthorized}}" | |
| 26 | + need-additional-auth="{{needAdditionalAuth}}" | |
| 27 | + has-plus-scopes="{{hasPlusScopes}}"></google-signin-aware> | |
| 28 | + <template is="dom-if" if="{{raised}}"> | |
| 29 | + <paper-material id="shadow" class="fit" elevation="2" animated></paper-material> | |
| 30 | + </template> | |
| 31 | + <div id="button" | |
| 32 | + class$="[[_computeButtonClass(height, width, theme, signedIn, _brand, needAdditionalAuth)]]"> | |
| 33 | + | |
| 34 | + <paper-ripple id="ripple" class="fit"></paper-ripple> | |
| 35 | + <!-- this div is needed to position the ripple behind text content --> | |
| 36 | + <div relative layout horizontal center-center> | |
| 37 | + <template is="dom-if" if="{{_computeButtonIsSignIn(signedIn, needAdditionalAuth)}}"> | |
| 38 | + <div class="button-content signIn" tabindex="0" | |
| 39 | + on-click="signIn" on-keydown="_signInKeyPress"> | |
| 40 | + <span class="icon"><iron-icon icon="[[_brandIcon]]"></iron-icon></span> | |
| 41 | + <span class="buttonText">{{_labelSignin}}</span> | |
| 42 | + </div> | |
| 43 | + </template> | |
| 44 | + <template is="dom-if" if="{{_computeButtonIsSignOut(signedIn, needAdditionalAuth) }}"> | |
| 45 | + <div class="button-content signOut" tabindex="0" | |
| 46 | + on-click="signOut" on-keydown="_signOutKeyPress"> | |
| 47 | + <span class="icon"><iron-icon icon="[[_brandIcon]]"></iron-icon></span> | |
| 48 | + <span class="buttonText">{{labelSignout}}</span> | |
| 49 | + </div> | |
| 50 | + </template> | |
| 51 | + <template is="dom-if" if="{{_computeButtonIsSignOutAddl(signedIn, needAdditionalAuth) }}"> | |
| 52 | + <div class="button-content signIn" tabindex="0" | |
| 53 | + on-click="signIn" on-keydown="_signInKeyPress"> | |
| 54 | + <span class="icon"><iron-icon icon="[[_brandIcon]]"></iron-icon></span> | |
| 55 | + <span class="buttonText">{{labelAdditional}}</span> | |
| 56 | + </div> | |
| 57 | + </template> | |
| 58 | + </div> | |
| 59 | + | |
| 60 | + </div> | |
| 61 | + </template> | |
| 62 | +</dom-module> | |
| 63 | +<script> | |
| 64 | + (function() { | |
| 65 | + | |
| 66 | + /** | |
| 67 | + * Enum brand values. | |
| 68 | + * @readonly | |
| 69 | + * @enum {string} | |
| 70 | + */ | |
| 71 | + var BrandValue = { | |
| 72 | + GOOGLE: 'google', | |
| 73 | + PLUS: 'google-plus' | |
| 74 | + }; | |
| 75 | + | |
| 76 | + /** | |
| 77 | + * Enum height values. | |
| 78 | + * @readonly | |
| 79 | + * @enum {string} | |
| 80 | + */ | |
| 81 | + var HeightValue = { | |
| 82 | + SHORT: 'short', | |
| 83 | + STANDARD: 'standard', | |
| 84 | + TALL: 'tall' | |
| 85 | + }; | |
| 86 | + | |
| 87 | + /** | |
| 88 | + * Enum button label default values. | |
| 89 | + * @readonly | |
| 90 | + * @enum {string} | |
| 91 | + */ | |
| 92 | + var LabelValue = { | |
| 93 | + STANDARD: 'Sign in', | |
| 94 | + WIDE: 'Sign in with Google', | |
| 95 | + WIDE_PLUS: 'Sign in with Google+' | |
| 96 | + }; | |
| 97 | + | |
| 98 | + /** | |
| 99 | + * Enum theme values. | |
| 100 | + * @readonly | |
| 101 | + * @enum {string} | |
| 102 | + */ | |
| 103 | + var ThemeValue = { | |
| 104 | + LIGHT: 'light', | |
| 105 | + DARK: 'dark' | |
| 106 | + }; | |
| 107 | + | |
| 108 | + /** | |
| 109 | + * Enum width values. | |
| 110 | + * @readonly | |
| 111 | + * @enum {string} | |
| 112 | + */ | |
| 113 | + var WidthValue = { | |
| 114 | + ICON_ONLY: 'iconOnly', | |
| 115 | + STANDARD: 'standard', | |
| 116 | + WIDE: 'wide' | |
| 117 | + }; | |
| 118 | + | |
| 119 | +/** | |
| 120 | +<google-signin> is used to authenticate with Google, allowing you to interact | |
| 121 | +with other Google APIs such as Drive and Google+. | |
| 122 | + | |
| 123 | +<img style="max-width:100%;" src="https://cloud.githubusercontent.com/assets/107076/6791176/5c868822-d16a-11e4-918c-ec9b84a2db45.png"/> | |
| 124 | + | |
| 125 | +If you do not need to show the button, use companion `<google-signin-aware>` element to declare scopes, check authentication state. | |
| 126 | + | |
| 127 | +#### Examples | |
| 128 | + | |
| 129 | + <google-signin client-id="..." scopes="https://www.googleapis.com/auth/drive"></google-signin> | |
| 130 | + | |
| 131 | + <google-signin label-signin="Sign-in" client-id="..." scopes="https://www.googleapis.com/auth/drive"></google-signin> | |
| 132 | + | |
| 133 | + <google-signin theme="dark" width="iconOnly" client-id="..." scopes="https://www.googleapis.com/auth/drive"></google-signin> | |
| 134 | + | |
| 135 | + | |
| 136 | +#### Notes | |
| 137 | + | |
| 138 | +The attribute `clientId` is provided in your Google Developers Console | |
| 139 | +(https://console.developers.google.com). | |
| 140 | + | |
| 141 | +The `scopes` attribute allows you to specify which scope permissions are required | |
| 142 | +(e.g do you want to allow interaction with the Google Drive API). Many APIs also | |
| 143 | +need to be enabled in the Google Developers Console before you can use them. | |
| 144 | + | |
| 145 | +The `requestVisibleActions` attribute is necessary if you want to write app | |
| 146 | +activities (https://developers.google.com/+/web/app-activities/) on behalf of | |
| 147 | +the user. Please note that this attribute is only valid in combination with the | |
| 148 | +plus.login scope (https://www.googleapis.com/auth/plus.login). | |
| 149 | + | |
| 150 | +The `offline` attribute allows you to get an auth code which your server can | |
| 151 | +redeem for an offline access token | |
| 152 | +(https://developers.google.com/identity/sign-in/web/server-side-flow). | |
| 153 | +You can also set `offline-always-prompt` instead of `offline` to ensure that your app | |
| 154 | +will re-prompt the user for offline access and generate a working `refresh_token` | |
| 155 | +even if they have already granted offline access to your app in the past. | |
| 156 | + | |
| 157 | +Use label properties to customize prompts. | |
| 158 | + | |
| 159 | +The button can be styled in using the `height`, `width`, and `theme` attributes. | |
| 160 | +These attributes help you follow the Google+ Sign-In button branding guidelines | |
| 161 | +(https://developers.google.com/+/branding-guidelines). | |
| 162 | + | |
| 163 | +The `google-signin-success` event is triggered when a user successfully authenticates | |
| 164 | +and `google-signed-out` is triggered when user signs out. | |
| 165 | +You can also use `isAuthorized` attribute to observe user's authentication state. | |
| 166 | + | |
| 167 | +Additional events, such as `google-signout-attempted` are | |
| 168 | +triggered when the user attempts to sign-out and successfully signs out. | |
| 169 | + | |
| 170 | +When requesting offline access, the `google-signin-offline-success` event is | |
| 171 | +triggered when the user successfully consents with offline support. | |
| 172 | + | |
| 173 | +The `google-signin-necessary` event is fired when scopes requested via | |
| 174 | +google-signin-aware elements require additional user permissions. | |
| 175 | + | |
| 176 | +#### Testing | |
| 177 | + | |
| 178 | +By default, the demo accompanying this element is setup to work on localhost with | |
| 179 | +port 8080. That said, you *should* update the `clientId` to your own one for | |
| 180 | +any apps you're building. See the Google Developers Console | |
| 181 | +(https://console.developers.google.com) for more info. | |
| 182 | + | |
| 183 | +@demo | |
| 184 | +*/ | |
| 185 | + | |
| 186 | + Polymer({ | |
| 187 | + | |
| 188 | + is: 'google-signin', | |
| 189 | + | |
| 190 | + /** | |
| 191 | + * Fired when user is signed in. | |
| 192 | + * You can use auth2 api to retrieve current user: `gapi.auth2.getAuthInstance().currentUser.get();` | |
| 193 | + * @event google-signin-success | |
| 194 | + */ | |
| 195 | + | |
| 196 | + /** | |
| 197 | + * Fired when the user is signed-out. | |
| 198 | + * @event google-signed-out | |
| 199 | + */ | |
| 200 | + | |
| 201 | + /** | |
| 202 | + * Fired if user requires additional authorization | |
| 203 | + * @event google-signin-necessary | |
| 204 | + */ | |
| 205 | + | |
| 206 | + /** | |
| 207 | + * Fired when signed in, and scope has been authorized | |
| 208 | + * @param {Object} result Authorization result. | |
| 209 | + * @event google-signin-aware-success | |
| 210 | + */ | |
| 211 | + | |
| 212 | + /** | |
| 213 | + * Fired when an offline authorization is successful. | |
| 214 | + * @event google-signin-offline-success | |
| 215 | + * @param {Object} detail | |
| 216 | + * @param {string} detail.code The one-time authorization code from Google. | |
| 217 | + * Your application can exchange this for an `access_token` and `refresh_token` | |
| 218 | + */ | |
| 219 | + | |
| 220 | + /** | |
| 221 | + * Fired when this scope is not authorized | |
| 222 | + * @event google-signin-aware-signed-out | |
| 223 | + */ | |
| 224 | + properties: { | |
| 225 | + /** | |
| 226 | + * App package name for android over-the-air installs. | |
| 227 | + * See the relevant [docs](https://developers.google.com/+/web/signin/android-app-installs) | |
| 228 | + */ | |
| 229 | + appPackageName: { | |
| 230 | + type: String, | |
| 231 | + value: '' | |
| 232 | + }, | |
| 233 | + | |
| 234 | + /** | |
| 235 | + * The brand being used for logo and styling. | |
| 236 | + * | |
| 237 | + * @default 'google' | |
| 238 | + */ | |
| 239 | + brand: { | |
| 240 | + type: String, | |
| 241 | + value: '' | |
| 242 | + }, | |
| 243 | + | |
| 244 | + /** @private */ | |
| 245 | + _brand: { | |
| 246 | + type: String, | |
| 247 | + computed: '_computeBrand(brand, hasPlusScopes)' | |
| 248 | + }, | |
| 249 | + | |
| 250 | + /** | |
| 251 | + * a Google Developers clientId reference | |
| 252 | + */ | |
| 253 | + clientId: { | |
| 254 | + type: String, | |
| 255 | + value: '' | |
| 256 | + }, | |
| 257 | + | |
| 258 | + /** | |
| 259 | + * The cookie policy defines what URIs have access to the session cookie | |
| 260 | + * remembering the user's sign-in state. | |
| 261 | + * See the relevant [docs](https://developers.google.com/+/web/signin/reference#determining_a_value_for_cookie_policy) for more information. | |
| 262 | + * | |
| 263 | + * @default 'single_host_origin' | |
| 264 | + */ | |
| 265 | + cookiePolicy: { | |
| 266 | + type: String, | |
| 267 | + value: '' | |
| 268 | + }, | |
| 269 | + | |
| 270 | + /** | |
| 271 | + * The height to use for the button. | |
| 272 | + * | |
| 273 | + * Available options: short, standard, tall. | |
| 274 | + * | |
| 275 | + * @type {HeightValue} | |
| 276 | + */ | |
| 277 | + height: { | |
| 278 | + type: String, | |
| 279 | + value: 'standard' | |
| 280 | + }, | |
| 281 | + | |
| 282 | + /** | |
| 283 | + * By default the ripple expands to fill the button. Set this to true to | |
| 284 | + * constrain the ripple to a circle within the button. | |
| 285 | + */ | |
| 286 | + fill: { | |
| 287 | + type: Boolean, | |
| 288 | + value: true | |
| 289 | + }, | |
| 290 | + | |
| 291 | + /** | |
| 292 | + * An optional label for the button for additional permissions. | |
| 293 | + */ | |
| 294 | + labelAdditional: { | |
| 295 | + type: String, | |
| 296 | + value: 'Additional permissions required' | |
| 297 | + }, | |
| 298 | + | |
| 299 | + /** | |
| 300 | + * An optional label for the sign-in button. | |
| 301 | + */ | |
| 302 | + labelSignin: { | |
| 303 | + type: String, | |
| 304 | + value: '' | |
| 305 | + }, | |
| 306 | + | |
| 307 | + _labelSignin: { | |
| 308 | + type: String, | |
| 309 | + computed: '_computeSigninLabel(labelSignin, width, _brand)' | |
| 310 | + }, | |
| 311 | + | |
| 312 | + /** | |
| 313 | + * An optional label for the sign-out button. | |
| 314 | + */ | |
| 315 | + labelSignout: { | |
| 316 | + type: String, | |
| 317 | + value: 'Sign out' | |
| 318 | + }, | |
| 319 | + | |
| 320 | + /** | |
| 321 | + * If true, the button will be styled with a shadow. | |
| 322 | + */ | |
| 323 | + raised: { | |
| 324 | + type: Boolean, | |
| 325 | + value: false | |
| 326 | + }, | |
| 327 | + | |
| 328 | + /** | |
| 329 | + * The app activity types you want to write on behalf of the user | |
| 330 | + * (e.g http://schemas.google.com/AddActivity) | |
| 331 | + */ | |
| 332 | + requestVisibleActions: { | |
| 333 | + type: String, | |
| 334 | + value: '' | |
| 335 | + }, | |
| 336 | + | |
| 337 | + /** | |
| 338 | + * The Google Apps domain to which users must belong to sign in. | |
| 339 | + * See the relevant [docs](https://developers.google.com/identity/sign-in/web/reference) for more information. | |
| 340 | + */ | |
| 341 | + hostedDomain: { | |
| 342 | + type: String, | |
| 343 | + value: '' | |
| 344 | + }, | |
| 345 | + | |
| 346 | + /** | |
| 347 | + * Allows for offline `access_token` retrieval during the signin process. | |
| 348 | + */ | |
| 349 | + offline: { | |
| 350 | + type: Boolean, | |
| 351 | + value: false | |
| 352 | + }, | |
| 353 | + | |
| 354 | + /** | |
| 355 | + * Forces a re-prompt, even if the user has already granted offline | |
| 356 | + * access to your application in the past. You only need one of | |
| 357 | + * `offline` and `offlineAlwaysPrompt`. | |
| 358 | + */ | |
| 359 | + offlineAlwaysPrompt: { | |
| 360 | + type: Boolean, | |
| 361 | + value: false | |
| 362 | + }, | |
| 363 | + | |
| 364 | + /** | |
| 365 | + * The scopes to provide access to (e.g https://www.googleapis.com/auth/drive) | |
| 366 | + * and should be space-delimited. | |
| 367 | + */ | |
| 368 | + scopes: { | |
| 369 | + type: String, | |
| 370 | + value: '' | |
| 371 | + }, | |
| 372 | + | |
| 373 | + /** | |
| 374 | + * The theme to use for the button. | |
| 375 | + * | |
| 376 | + * Available options: light, dark. | |
| 377 | + * | |
| 378 | + * @attribute theme | |
| 379 | + * @type {ThemeValue} | |
| 380 | + * @default 'dark' | |
| 381 | + */ | |
| 382 | + theme: { | |
| 383 | + type: String, | |
| 384 | + value: 'dark' | |
| 385 | + }, | |
| 386 | + | |
| 387 | + /** | |
| 388 | + * The width to use for the button. | |
| 389 | + * | |
| 390 | + * Available options: iconOnly, standard, wide. | |
| 391 | + * | |
| 392 | + * @type {WidthValue} | |
| 393 | + */ | |
| 394 | + width: { | |
| 395 | + type: String, | |
| 396 | + value: 'standard' | |
| 397 | + }, | |
| 398 | + | |
| 399 | + _brandIcon: { | |
| 400 | + type: String, | |
| 401 | + computed: '_computeIcon(_brand)' | |
| 402 | + }, | |
| 403 | + | |
| 404 | + /** | |
| 405 | + * True if *any* element has google+ scopes | |
| 406 | + */ | |
| 407 | + hasPlusScopes: { | |
| 408 | + type: Boolean, | |
| 409 | + notify: true, | |
| 410 | + value: false | |
| 411 | + }, | |
| 412 | + | |
| 413 | + /** | |
| 414 | + * True if additional authorization required globally | |
| 415 | + */ | |
| 416 | + needAdditionalAuth: { | |
| 417 | + type: Boolean, | |
| 418 | + value: false | |
| 419 | + }, | |
| 420 | + | |
| 421 | + /** | |
| 422 | + * Is user signed in? | |
| 423 | + */ | |
| 424 | + signedIn: { | |
| 425 | + type: Boolean, | |
| 426 | + notify: true, | |
| 427 | + value: false, | |
| 428 | + observer: '_observeSignedIn' | |
| 429 | + }, | |
| 430 | + | |
| 431 | + /** | |
| 432 | + * True if authorizations for *this* element have been granted | |
| 433 | + */ | |
| 434 | + isAuthorized: { | |
| 435 | + type: Boolean, | |
| 436 | + notify: true, | |
| 437 | + value: false | |
| 438 | + } | |
| 439 | + | |
| 440 | + }, | |
| 441 | + | |
| 442 | + _computeButtonClass: function(height, width, theme, signedIn, brand, needAdditionalAuth) { | |
| 443 | + return "height-" + height + " width-" + width + " theme-" + theme + " signedIn-" + signedIn + " brand-" + brand + " additionalAuth-" + needAdditionalAuth; | |
| 444 | + }, | |
| 445 | + | |
| 446 | + _computeIcon: function(brand) { | |
| 447 | + return "google:" + brand; | |
| 448 | + }, | |
| 449 | + | |
| 450 | + /* Button state computed */ | |
| 451 | + _computeButtonIsSignIn: function(signedIn, additionalAuth) { | |
| 452 | + return !signedIn; | |
| 453 | + }, | |
| 454 | + | |
| 455 | + _computeButtonIsSignOut: function(signedIn, additionalAuth) { | |
| 456 | + return signedIn && !additionalAuth; | |
| 457 | + }, | |
| 458 | + | |
| 459 | + _computeButtonIsSignOutAddl: function(signedIn, additionalAuth) { | |
| 460 | + return signedIn && additionalAuth; | |
| 461 | + }, | |
| 462 | + | |
| 463 | + _computeBrand: function(attrBrand, hasPlusScopes) { | |
| 464 | + var newBrand; | |
| 465 | + if (attrBrand) { | |
| 466 | + newBrand = attrBrand; | |
| 467 | + } else if (hasPlusScopes) { | |
| 468 | + newBrand = BrandValue.PLUS; | |
| 469 | + } else { | |
| 470 | + newBrand = BrandValue.GOOGLE; | |
| 471 | + }; | |
| 472 | + return newBrand; | |
| 473 | + }, | |
| 474 | + | |
| 475 | + _observeSignedIn: function(newVal, oldVal) { | |
| 476 | + if (newVal) { | |
| 477 | + if (this.needAdditionalAuth) | |
| 478 | + this.fire('google-signin-necessary'); | |
| 479 | + this.fire('google-signin-success'); | |
| 480 | + } | |
| 481 | + else | |
| 482 | + this.fire('google-signed-out'); | |
| 483 | + }, | |
| 484 | + | |
| 485 | + /** | |
| 486 | + * Determines the proper label based on the attributes. | |
| 487 | + */ | |
| 488 | + _computeSigninLabel: function(labelSignin, width, _brand) { | |
| 489 | + if (labelSignin) { | |
| 490 | + return labelSignin; | |
| 491 | + } else { | |
| 492 | + switch(width) { | |
| 493 | + | |
| 494 | + case WidthValue.WIDE: | |
| 495 | + return (_brand == BrandValue.PLUS) ? | |
| 496 | + LabelValue.WIDE_PLUS : LabelValue.WIDE; | |
| 497 | + | |
| 498 | + case WidthValue.STANDARD: | |
| 499 | + return LabelValue.STANDARD; | |
| 500 | + | |
| 501 | + case WidthValue.ICON_ONLY: | |
| 502 | + return ''; | |
| 503 | + | |
| 504 | + default: | |
| 505 | + console.warn("bad width value: ", width); | |
| 506 | + return LabelValue.STANDARD; | |
| 507 | + } | |
| 508 | + } | |
| 509 | + }, | |
| 510 | + | |
| 511 | + /** Sign in user. Opens the authorization dialog for signing in. | |
| 512 | + * The dialog will be blocked by a popup blocker unless called inside click handler. | |
| 513 | + */ | |
| 514 | + signIn: function () { | |
| 515 | + this.$.aware.signIn(); | |
| 516 | + }, | |
| 517 | + | |
| 518 | + _signInKeyPress: function (e) { | |
| 519 | + if (e.which == 13 || e.keyCode == 13 || e.which == 32 || e.keyCode == 32) { | |
| 520 | + e.preventDefault(); | |
| 521 | + this.signIn(); | |
| 522 | + } | |
| 523 | + }, | |
| 524 | + | |
| 525 | + /** Sign out the user */ | |
| 526 | + signOut: function () { | |
| 527 | + this.fire('google-signout-attempted'); | |
| 528 | + this.$.aware.signOut(); | |
| 529 | + }, | |
| 530 | + | |
| 531 | + _signOutKeyPress: function (e) { | |
| 532 | + if (e.which == 13 || e.keyCode == 13 || e.which == 32 || e.keyCode == 32) { | |
| 533 | + e.preventDefault(); | |
| 534 | + this.signOut(); | |
| 535 | + } | |
| 536 | + } | |
| 537 | + }); | |
| 538 | + }()); | |
| 539 | +</script> | ... | ... |
bower_components/google-signin/index.html
0 → 100644
| 1 | +<!doctype html> | |
| 2 | +<!-- Copyright (c) 2014 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> | ... | ... |
datalets/test-google-components/test.html
0 → 100644
| 1 | +<!DOCTYPE html> | |
| 2 | +<html lang="en"> | |
| 3 | +<head> | |
| 4 | + <meta charset="UTF-8"> | |
| 5 | + <title>Google spreadsheet and document test page</title> | |
| 6 | + | |
| 7 | + <script type="text/javascript" src="../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script> | |
| 8 | + <script type="text/javascript" src="../shared_js/jquery-1.11.2.min.js"></script> | |
| 9 | + | |
| 10 | + <link rel="import" href="../../bower_components/google-sheets/google-sheets.html"> | |
| 11 | + <link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout.html"> | |
| 12 | + <link rel="import" href="../../bower_components/iron-icons/iron-icons.html"> | |
| 13 | + <link rel="import" href="../../bower_components/paper-fab/paper-fab.html"> | |
| 14 | + <link rel="import" href="../linechart-datalet/linechart-datalet.html"> | |
| 15 | + | |
| 16 | + <style> | |
| 17 | + #sheet{ | |
| 18 | + height: 400px; | |
| 19 | + width: 40%; | |
| 20 | + margin: 40px; | |
| 21 | + } | |
| 22 | + | |
| 23 | + #showVisualization{ | |
| 24 | + background-color: #2196F3; | |
| 25 | + color: #ffffff; | |
| 26 | + margin-left: 50px; | |
| 27 | + } | |
| 28 | + | |
| 29 | + | |
| 30 | + #datalet_placeholder{ | |
| 31 | + height: 400px; | |
| 32 | + width: 40%; | |
| 33 | + margin: 40px;/ | |
| 34 | + } | |
| 35 | + | |
| 36 | + #doc{ | |
| 37 | + height: 400px; | |
| 38 | + width: 100%; | |
| 39 | + } | |
| 40 | + </style> | |
| 41 | + | |
| 42 | + <script> | |
| 43 | + | |
| 44 | + getData = function() | |
| 45 | + { | |
| 46 | + var sheet = document.querySelector('google-sheets'); | |
| 47 | + | |
| 48 | + sheet.addEventListener('google-sheet-data', function(e) | |
| 49 | + { | |
| 50 | + var data = []; | |
| 51 | + //get the keys | |
| 52 | + for(var key in this.rows[0]) { | |
| 53 | + if (key.match(/gsx\$*/)) { | |
| 54 | + data.push({name: key.replace("gsx$", ""), data: []}); | |
| 55 | + } | |
| 56 | + } | |
| 57 | + //fill the structure with values | |
| 58 | + for(var row in this.rows){ | |
| 59 | + var i = 0; | |
| 60 | + for(var key in this.rows[row]){ | |
| 61 | + if(key.match(/gsx\$*/)){ | |
| 62 | + data[i++].data.push(this.rows[row][key].$t.replace("'","")); | |
| 63 | + } | |
| 64 | + } | |
| 65 | + | |
| 66 | + } | |
| 67 | + | |
| 68 | + $("#datalet_placeholder").html('<linechart-datalet ' + | |
| 69 | + 'data-url="https://docs.google.com/spreadsheets/d/1EYJ88pOsbc0GkUTTdPhuReUjHewk1fhis9VZBXes_Ao" ' + | |
| 70 | + //'fields=\'[]\'' + | |
| 71 | + 'title="Google spreadsheet realtime data visualization"' + | |
| 72 | + 'data=\'' + JSON.stringify(data) + '\'>' + | |
| 73 | + '</linechart-datalet>'); | |
| 74 | + | |
| 75 | + $("#spreadsheet_url").html('<a href="' + this.openInGoogleDocsUrl + '" target="_blank">' + this.openInGoogleDocsUrl + '</a>'); | |
| 76 | + | |
| 77 | + }); | |
| 78 | + | |
| 79 | + sheet.addEventListener('error', function(e) { | |
| 80 | + // e.detail.response | |
| 81 | + }); | |
| 82 | + | |
| 83 | + } | |
| 84 | + | |
| 85 | + refresh = function(){ | |
| 86 | + $("#sheet-component").html('<google-sheets key="1EYJ88pOsbc0GkUTTdPhuReUjHewk1fhis9VZBXes_Ao" published></google-sheets>'); | |
| 87 | + getData(); | |
| 88 | + } | |
| 89 | + | |
| 90 | + $( document ).ready(function() { | |
| 91 | + getData(); | |
| 92 | + }); | |
| 93 | + | |
| 94 | + </script> | |
| 95 | + | |
| 96 | +</head> | |
| 97 | +<body is="dom-bind"> | |
| 98 | + <div class="layout vertical"> | |
| 99 | + <div class="layout vertical"> | |
| 100 | + <div class="layout horizontal" style="width: 100%;"> | |
| 101 | + <h1>Google Spreadsheet realtime visualization with Datalet</h1> | |
| 102 | + <paper-fab id="showVisualization" icon="refresh" onClick="refresh()"></paper-fab> | |
| 103 | + </div> | |
| 104 | + <div class="layout horizontal" style="width: 100%;"> | |
| 105 | + <h3 id="spreadsheet_url"></h3> | |
| 106 | + </div> | |
| 107 | + <div class="layout horizontal"> | |
| 108 | + <iframe id="sheet" src="https://docs.google.com/spreadsheets/d/1EYJ88pOsbc0GkUTTdPhuReUjHewk1fhis9VZBXes_Ao/edit?usp=sharing?embedded=true"></iframe> | |
| 109 | + <div id="datalet_placeholder"></div> | |
| 110 | + </div> | |
| 111 | + </div> | |
| 112 | + | |
| 113 | + <div class="layout vertical"> | |
| 114 | + <h1 style="width: 100%;margin-top: 100px;">Google Docs realtime visualization with Datalet</h1> | |
| 115 | + <iframe id="doc" src="https://docs.google.com/document/d/1IIfmqTGBpTkEMHPnuxJeoOJI3u-8wQu9dkf49X2T6SE/edit?usp=sharing?embedded=true"></iframe> | |
| 116 | + </div> | |
| 117 | + </div> | |
| 118 | + | |
| 119 | + <div id="sheet-component"> | |
| 120 | + <google-sheets key="1EYJ88pOsbc0GkUTTdPhuReUjHewk1fhis9VZBXes_Ao" published></google-sheets> | |
| 121 | + </div> | |
| 122 | + | |
| 123 | +</body> | |
| 124 | +</html> | |
| 0 | 125 | \ No newline at end of file | ... | ... |