This commit is contained in:
Yangguang Li 2019-04-22 16:50:11 -07:00
Родитель 5505dc51b4
Коммит 5b83d1c40b
6 изменённых файлов: 541 добавлений и 7 удалений

Просмотреть файл

@ -5,7 +5,8 @@
"es6": true
},
"parserOptions": {
"ecmaVersion": 8
"ecmaVersion": 8,
"sourceType": "module"
},
"rules": {
"no-warning-comments": "off",
@ -14,7 +15,11 @@
"args": "after-used",
"argsIgnorePattern": "^var_args$"
}],
"indent": ["error", 2, { "outerIIFEBody": 0, "SwitchCase": 1 }],
"indent": [
"error",
2,
{ "outerIIFEBody": 0, "SwitchCase": 1, "ignoredNodes": ["TemplateLiteral > *"] }
],
"require-jsdoc": 0,
"no-var": 1,
"arrow-parens": 0,

Просмотреть файл

@ -0,0 +1,29 @@
import {LitElement, html} from 'https://unpkg.com/@polymer/lit-element@latest/lit-element.js?module';
const CYAN = 120;
const DEFAULT_MAX = 7;
class ChromedashColorStatus extends LitElement {
static get properties() {
return {
max: {type: Number}, // From parent
value: {type: Number}, // From parent
};
}
constructor() {
super();
this.max = DEFAULT_MAX;
}
render() {
const color = `hsl(${Math.round(CYAN - this.value * CYAN / this.max)}, 100%, 50%)`;
return html`
<link rel="stylesheet" href="/static/css/elements/chromedash-color-status.css">
<span id="status" style="background-color: ${color}"></span>
`;
}
}
customElements.define('chromedash-color-status', ChromedashColorStatus);

Просмотреть файл

@ -0,0 +1,498 @@
import {LitElement, html} from 'https://unpkg.com/@polymer/lit-element@latest/lit-element.js?module';
// import 'https://unpkg.com/@polymer/iron-icon/iron-icon.js?module';
// import 'https://unpkg.com/@polymer/paper-styles/color.js?module';
import {urlize} from './urlize.js';
import './chromedash-color-status.js';
class ChromedashMultiLinks extends LitElement {
static get properties() {
return {
title: {type: String}, // From parent
links: {type: Array}, // From parent
};
}
constructor() {
super();
this.title = 'Link';
this.links = [];
}
render() {
return html`
<link rel="stylesheet" href="/static/css/shared.css">
${this.links.map((link, index) => html`
<a href="${link}" target="_blank"
class="${index < this.links.length - 1 ? 'comma' : ''}"
>${this.title} ${index + 1}</a>
`)}
`;
}
}
customElements.define('chromedash-multi-links', ChromedashMultiLinks);
const MAX_STANDARDS_VAL = 6;
const MAX_VENDOR_VIEW = 7;
const MAX_WEBDEV_VIEW = 6;
const MAX_RISK = MAX_VENDOR_VIEW + MAX_WEBDEV_VIEW + MAX_STANDARDS_VAL;
const IS_PUSH_NOTIFIER_ENABLED = window.PushNotifier.GRANTED_ACCESS;
const IS_PUSH_NOTIFIER_SUPPORTED =
window.PushNotifier && window.PushNotifier.SUPPORTS_NOTIFICATIONS;
class ChromedashFeature extends LitElement {
static get properties() {
return {
feature: {type: Object}, // From parent
whitelisted: {type: Boolean}, // From parent
open: {type: Boolean, reflect: true}, // Attribute for styling
// Values used in the template
interopRisk: {type: Number, attribute: false},
isDeprecated: {type: Boolean, attribute: false},
hasDocLinks: {type: Boolean, attribute: false},
hasSampleLinks: {type: Boolean, attribute: false},
commentHtml: {type: String, attribute: false},
crBugNumber: {type: String, attribute: false},
newBugUrl: {type: String, attribute: false},
receivePush: {type: Boolean, attribute: false},
};
}
constructor() {
super();
this.whitelisted = false;
}
// Initialize values after receiving `this.feature`.
firstUpdated() {
this.open = this.feature.open;
this.receivePush = this.feature.receivePush;
this.crBugNumber = this._computeCrBugNumber();
this.newBugUrl = this._computeNewBugUrl();
this.interopRisk = this._computeInteropRisk();
this.isDeprecated = this._computeIsDeprecated();
this.hasDocLinks = this._computeHasDocLinks();
this.hasSampleLinks = this._computeHasSampleLinks();
this.commentHtml = this._computeCommentHtml();
}
_computeCrBugNumber() {
const link = this.feature.browsers.chrome.bug;
if (!link) {
return '';
}
/* Get the number id from a url.
* Url has two formats: "http://crbug.com/111111", and
* "https://bugs.chromium.org/p/chromium/issues/detail?id=111111" */
const matches = link.match(/(id=|crbug.com\/)([0-9]+)/);
if (matches) {
return matches[2];
}
return '';
}
_computeNewBugUrl() {
const url = 'https://bugs.chromium.org/p/chromium/issues/entry';
const params = [
`components=${this.feature.browsers.chrome.blink_components[0] ||
'Blink'}`];
const PRE_LAUNCH_STATUSES = [
'No active development',
'Proposed',
'In development',
'Behind a flag',
'Origin trial',
];
if (this.crBugNumber &&
PRE_LAUNCH_STATUSES.includes(
this.feature.browsers.chrome.status.text)) {
params.push(`blocking=${this.crBugNumber}`);
}
const owners = this.feature.browsers.chrome.owners;
if (owners && owners.length) {
params.push(`cc=${owners.map(encodeURIComponent)}`);
}
return `${url}?${params.join('&')}`;
}
_computeInteropRisk() {
const vendors = (this.feature.browsers.ff.view.val +
this.feature.browsers.edge.view.val +
this.feature.browsers.safari.view.val) / 3;
const webdevs = this.feature.browsers.webdev.view.val;
const standards = this.feature.standards.status.val;
return vendors + webdevs + standards;
}
_computeIsDeprecated() {
const DEPRECATED_STATUSES = ['Deprecated', 'No longer pursuing'];
return DEPRECATED_STATUSES.includes(
this.feature.browsers.chrome.status.text);
}
_computeHasDocLinks() {
return this.feature.resources.docs &&
this.feature.resources.docs.length > 0;
}
_computeHasSampleLinks() {
return this.feature.resources.samples &&
this.feature.resources.samples.length > 0;
}
_computeCommentHtml() {
return urlize(this.feature.comments,
{target: '_blank', trim: 'www', autoescape: true});
}
_fireEvent(eventName, detail) {
let event = new CustomEvent(eventName, {detail});
this.dispatchEvent(event);
}
toggle(e) {
// Don't toggle panel if tooltip or link is being clicked.
const target = e.currentTarget;
if (target.classList.contains('tooltip') || 'tooltip' in target.dataset ||
target.tagName == 'A' || target.tagName == 'CHROMEDASH-MULTI-LINKS') {
return;
}
this.open = !this.open;
// Handled in `chromedash-featurelist`
this._fireEvent('feature-toggled', {
feature: this.feature,
open: this.open,
});
}
categoryFilter(e) {
e.stopPropagation();
e.preventDefault();
// Directly listened in `templates/features.html`
this._fireEvent('filter-category', {val: e.currentTarget.textContent});
}
filterByOwner(e) {
e.stopPropagation();
e.preventDefault();
// Directly listened in `templates/features.html`
this._fireEvent('filter-owner', {val: e.currentTarget.textContent});
}
filterByComponent(e) {
e.stopPropagation();
e.preventDefault();
// Directly listened in `templates/features.html`
this._fireEvent('filter-component', {val: e.currentTarget.textContent});
}
subscribeToFeature(e) {
e.preventDefault();
e.stopPropagation();
const featureId = this.feature.id;
if (!featureId) {
return;
}
this.receivePush = !this.receivePush;
if (this.receivePush) {
PushNotifications.subscribeToFeature(featureId);
} else {
PushNotifications.unsubscribeFromFeature(featureId);
}
}
render() {
return html`
<link rel="stylesheet" href="/static/css/elements/chromedash-feature.css">
<div class="main-content-area" @click="${this.toggle}">
<hgroup>
<chromedash-color-status class="tooltip corner"
title="Interoperability risk: perceived interest from browser
vendors and web developers"
.value="${this.interopRisk}"
.max="${MAX_RISK}"></chromedash-color-status>
<h2>${this.feature.name}
${this.whitelisted ? `
<span class="tooltip" title="Edit this feature">
<a href="/admin/features/edit/${this.feature.id}" data-tooltip>
<iron-icon icon="chromestatus:create"></iron-icon>
</a>
</span>
`: ''}
</h2>
<div class="iconrow
${IS_PUSH_NOTIFIER_SUPPORTED ?
'supports-push-notifications' : ''}">
<span class="tooltip"
title="Filter by category ${this.feature.category}">
<button class="category"
@click="${this.categoryFilter}">
${this.feature.category}</button>
</span>
<div class="topcorner">
${this.feature.browsers.chrome.status.text === 'Removed' ? `
<span class="tooltip" title="Removed feature">
<iron-icon icon="chromestatus:cancel"
class="remove" data-tooltip></iron-icon>
</span>
` : ''}
${this.isDeprecated ? `
<span class="tooltip" title="Deprecated feature">
<iron-icon icon="chromestatus:warning"
class="deprecated" data-tooltip></iron-icon>
</span>
` : ''}
${this.feature.browsers.chrome.flag ? `
<span class="tooltip"
title="Experimental feature behind a flag">
<iron-icon icon="chromestatus:flag"
class="experimental"></iron-icon>
</span>
` : ''}
${this.feature.browsers.chrome.origintrial ? `
<span class="tooltip" title="Origin trial">
<iron-icon icon="chromestatus:extension"
class="experimental"></iron-icon>
</span>
` : ''}
${this.feature.browsers.chrome.intervention ? `
<span class="tooltip" title="Browser intervention">
<iron-icon icon="chromestatus:pan-tool"
class="intervention" data-tooltip></iron-icon>
</span>
` : ''}
<span class="tooltip no-push-notifications"
title="Receive a push notification when there are updates">
<button @click="${this.subscribeToFeature}" data-tooltip>
<iron-icon icon="${this.receivePush ?
'chromestatus:notifications' :
'chromestatus:notifications-off'}"
class="pushicon ${IS_PUSH_NOTIFIER_ENABLED ?
'' : 'disabled'}"></iron-icon>
</button>
</span>
<span class="tooltip" title="File a bug against this feature">
<a href="${this.newBugUrl}" data-tooltip>
<iron-icon icon="chromestatus:bug-report"></iron-icon>
</a>
</span>
<span class="tooltip" title="View on a standalone page">
<a href="/feature/${this.feature.id}" target="_blank">
<iron-icon icon="chromestatus:open-in-new"></iron-icon>
</a>
</span>
</div>
</div>
</hgroup>
<section class="desc">
<summary>
<p><span>${this.feature.summary}</span></p>
<p><span>${this.feature.motivation}</span></p>
</summary>
</section>
${this.open ? `
<section class="sidebyside">
<div class="flex">
<h3>Chromium status</h3>
<div class="impl_status">
<span class="chromium_status">
<label>${this.feature.browsers.chrome.status.text}</label>
</span>
${this.feature.browsers.chrome.desktop ? `
<span>
<label class="impl_status_label">
<span class="impl_status_icons">
<span class="chrome_icon"></span>
</span>
<span>Chrome desktop</span>
</label>
<span>${this.feature.browsers.chrome.desktop}</span>
</span>
` : ''}
${this.feature.browsers.chrome.android ? `
<span>
<label class="impl_status_label">
<span class="impl_status_icons">
<span class="chrome_icon"></span>
<iron-icon icon="chromestatus:android"
class="android"></iron-icon>
</span>
<span>Chrome for Android</span>
</label>
<span>${this.feature.browsers.chrome.android}</span>
</span>
` : ''}
${this.feature.browsers.chrome.webview ? `
<span>
<label class="impl_status_label">
<span class="impl_status_icons">
<iron-icon icon="chromestatus:android"
class="android"></iron-icon>
</span>
<span>Android Webview</span>
</label>
<span>${this.feature.browsers.chrome.webview}</span>
</span>
` : ''}
${this.feature.browsers.chrome.prefixed ? `
<span><label>Prefixed</label><span>Yes</span></span>
` : ''}
${this.feature.browsers.chrome.bug ? `
<span>
<span>Tracking bug</span>
<a href="${this.feature.browsers.chrome.bug}"
target="_blank">${this.crBugNumber ?
`#${this.crBugNumber}` :
this.feature.browsers.chrome.bug}</a>
</span>
` : ''}
${this.feature.browsers.chrome.blink_components &&
this.feature.browsers.chrome.blink_components.length ? `
<span>
<label>Blink component</label>
<span class="tooltip"
title="Filter by component
${this.feature.browsers.chrome.blink_components}">
<button @click="${this.filterByComponent}">
${this.feature.browsers.chrome.blink_components}
</button>
</span>
</span>
` : ''}
${this.feature.browsers.chrome.owners &&
this.feature.browsers.chrome.owners.length ? `
<span class="owner">
<label>Owner(s)</label>
<span class="owner-list">
${this.feature.browsers.chrome.owners.map((owner) => `
<span class="tooltip" title="Filter by owner ${owner}">
<button @click="${this.filterByOwner}">
${owner}
</button>
</span>
`)}
</span>
</span>
` : ''}
</div>
</div>
<div class="flex">
<h3>Consensus &amp; standardization</h3>
<div class="views">
<span title="${this.feature.browsers.ff.view.text}"
class="view tooltip">
<chromedash-color-status class="bottom"
.value="${this.feature.browsers.ff.view.val}"
.max="${MAX_VENDOR_VIEW}"></chromedash-color-status>
${this.feature.browsers.ff.view.url ? `
<a href="${this.feature.browsers.ff.view.url}"
target="_blank">
<span class="vendor-view ff-view"></span>
</a>
` : ''}
${this.feature.browsers.ff.view.url ?
'<span class="vendor-view ff-view"></span>' : ''}
</span>
<span title="${this.feature.browsers.edge.view.text}"
class="view tooltip">
<chromedash-color-status class="bottom"
.value="${this.feature.browsers.edge.view.val}"
.max="${MAX_VENDOR_VIEW}"></chromedash-color-status>
${this.feature.browsers.edge.view.url ? `
<a href="${this.feature.browsers.edge.view.url}"
target="_blank">
<span class="vendor-view edge-view"></span>
</a>
` : ''}
${this.feature.browsers.edge.view.url ?
'<span class="vendor-view edge-view"></span>' : ''}
</span>
<span title="${this.feature.browsers.safari.view.text}"
class="view tooltip">
<chromedash-color-status class="bottom"
.value="${this.feature.browsers.safari.view.val}"
.max="${MAX_VENDOR_VIEW}"></chromedash-color-status>
${this.feature.browsers.safari.view.url ? `
<a href="${this.feature.browsers.safari.view.url}"
target="_blank">
<span class="vendor-view safari-view"></span>
</a>
` : ''}
${this.feature.browsers.safari.view.url ?
'<span class="vendor-view safari-view"></span>' : ''}
</span>
<span title="Web developers:
${this.feature.browsers.webdev.view.text}"
class="view webdev-view tooltip">
<chromedash-color-status class="bottom"
.value="${this.feature.browsers.webdev.view.val}"
.max="${MAX_WEBDEV_VIEW}"></chromedash-color-status>
<iron-icon icon="chromestatus:accessibility"></iron-icon>
</span>
<span class="standardization view">
<chromedash-color-status class="bottom"
.value="${this.feature.standards.status.val}"
.max="${MAX_STANDARDS_VAL}"></chromedash-color-status>
${this.feature.standards.spec ? `
<a href="${this.feature.standards.spec}"
target="_blank">${this.feature.standards.status.text}</a>
` : ''}
${this.feature.standards.spec ?
`<label>${this.feature.standards.status.text}</label>` :
''}
</span>
</div>
<div style="font-size:smaller">
After a feature ships in Chrome, the values listed here are not
guaranteed to be up to date.
</div>
</div>
</section>
${this.hasDocLinks || this.hasSampleLinks ? `
<section>
<h3>Developer resources</h3>
<div class="resources">
<label>Documentation/samples:</label>
${this.hasDocLinks ? `
<div class="doc_links">
<chromedash-multi-links
.links="${this.feature.resources.docs}"
title="Link"></chromedash-multi-links>
</div>
` : ''}
${this.hasDocLinks && this.hasSampleLinks ?
'<span>,</span>' : ''}
${this.hasSampleLinks ? `
<div class="sample_links">
<chromedash-multi-links title="Sample"
.links="${this.feature.resources.samples}"
></chromedash-multi-links>
</div>
` : ''}
</div>
</section>
` : ''}
${this.feature.comments ? `
<section>
<h3>Comments</h3>
<summary class="comments">${this.commentHtml}</summary>
</section>
` : ''}
` : ''}
</div>
`;
}
}
customElements.define('chromedash-feature', ChromedashFeature);

Просмотреть файл

@ -1,7 +1,8 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="chromedash-feature.html">
<link rel="import" href="../bower_components/iron-list/iron-list.html">
<!-- <link rel="import" href="../bower_components/iron-flex-layout/iron-flex-layout.html"> -->
<link rel="import" href="../bower_components/iron-list/iron-list.html">
<!-- <link rel="import" href="chromedash-feature.html"> -->
<script type="module" src="/static/elements/chromedash-feature.js"></script>
<dom-module id="chromedash-featurelist">
<link rel="import" type="css" href="../css/elements/chromedash-featurelist.css">

Просмотреть файл

@ -1,6 +1,7 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="chromedash-color-status.html">
<!-- <link rel="import" href="chromedash-color-status.html"> -->
<script type="module" src="/static/elements/chromedash-color-status.js"></script>
<dom-module id="chromedash-legend">
<link rel="import" type="css" href="../css/elements/chromedash-legend.css">

Просмотреть файл

@ -1,4 +1,4 @@
var urlize = (function () {
export const urlize = (function () {
// From http://blog.stevenlevithan.com/archives/cross-browser-split
// modified to not add itself to String.prototype.