зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 5 changesets (bug 1866802) for causing failures at test_TopSitesFeed.js. CLOSED TREE
Backed out changeset af9fbbc9ae50 (bug 1866802) Backed out changeset 81d5b7de7178 (bug 1866802) Backed out changeset e4d0863ed222 (bug 1866802) Backed out changeset c0deb681b193 (bug 1866802) Backed out changeset dda3e5e39f8c (bug 1866802)
This commit is contained in:
Родитель
d433a7d264
Коммит
8582db0ea5
|
@ -233,7 +233,6 @@ module.exports = {
|
|||
"browser/components/Browser*",
|
||||
"browser/components/aboutlogins/**",
|
||||
"browser/components/aboutwelcome/**",
|
||||
"browser/components/asrouter/**",
|
||||
"browser/components/attribution/**",
|
||||
"browser/components/customizableui/**",
|
||||
"browser/components/downloads/**",
|
||||
|
@ -499,7 +498,6 @@ module.exports = {
|
|||
extends: ["plugin:react-hooks/recommended"],
|
||||
files: [
|
||||
"browser/components/aboutwelcome/**",
|
||||
"browser/components/asrouter/**",
|
||||
"browser/components/newtab/**",
|
||||
"browser/components/pocket/**",
|
||||
"devtools/**",
|
||||
|
|
|
@ -56,20 +56,12 @@ security/manager/.nss.checkout
|
|||
# gecko.log is generated by various test harnesses
|
||||
/gecko.log
|
||||
|
||||
# Ignore all node_modules directories
|
||||
node_modules/
|
||||
# ...but allow ones under third_party
|
||||
!/third_party/**/node_modules/
|
||||
|
||||
# Ignore newtab component build assets
|
||||
browser/components/newtab/logs/
|
||||
|
||||
# Ignore about:welcome component build assets
|
||||
browser/components/aboutwelcome/logs/
|
||||
|
||||
# Ignore ASRouter component build assets
|
||||
browser/components/asrouter/logs/
|
||||
|
||||
# Ignore ASRouter generated test files
|
||||
browser/components/newtab/content-src/asrouter/schemas/corpus/CFRMessageProvider.messages.json
|
||||
browser/components/newtab/content-src/asrouter/schemas/corpus/OnboardingMessageProvider.messages.json
|
||||
|
|
|
@ -60,9 +60,6 @@ compile_commands\.json
|
|||
# Ignore about:welcome build assets
|
||||
^browser/components/aboutwelcome/logs/
|
||||
|
||||
# Ignore ASRouter component build assets
|
||||
^browser/components/asrouter/logs/
|
||||
|
||||
# Ignore ASRouter generated test files
|
||||
^browser/components/newtab/content-src/asrouter/schemas/corpus/CFRMessageProvider.messages.json
|
||||
^browser/components/newtab/content-src/asrouter/schemas/corpus/OnboardingMessageProvider.messages.json
|
||||
|
@ -201,7 +198,6 @@ _OPT\.OBJ/
|
|||
^node_modules/
|
||||
^tools/browsertime/node_modules/
|
||||
^tools/lint/eslint/eslint-plugin-mozilla/node_modules/
|
||||
^browser/components/asrouter/node_modules/
|
||||
^browser/components/newtab/node_modules/
|
||||
^browser/components/aboutwelcome/node_modules/
|
||||
^tools/esmify/node_modules/
|
||||
|
|
|
@ -1449,9 +1449,6 @@ xpcom/io/crc32c.c
|
|||
|
||||
.gradle/
|
||||
browser/components/aboutwelcome/content/aboutwelcome.bundle.js
|
||||
browser/components/asrouter/node_modules/
|
||||
browser/components/asrouter/content/asrouter-admin.bundle.js
|
||||
browser/components/asrouter/logs/
|
||||
browser/components/newtab/content-src/asrouter/schemas/BackgroundTaskMessagingExperiment.schema.json
|
||||
browser/components/newtab/content-src/asrouter/schemas/MessagingExperiment.schema.json
|
||||
browser/components/newtab/logs/
|
||||
|
|
|
@ -26,7 +26,6 @@ obj*/
|
|||
browser/components/pocket/content/panels/css/main.compiled.css
|
||||
browser/components/newtab/**/*.css
|
||||
browser/components/aboutwelcome/**/*.css
|
||||
browser/components/asrouter/**/*.css
|
||||
|
||||
# Note that the debugger has its own stylelint setup, but that currently
|
||||
# produces errors. Bug 1831302 tracks making this better
|
||||
|
|
|
@ -260,7 +260,6 @@ module.exports = {
|
|||
{
|
||||
files: [
|
||||
"browser/components/aboutwelcome/**",
|
||||
"browser/components/asrouter/**",
|
||||
"browser/components/newtab/**",
|
||||
],
|
||||
customSyntax: "postcss-scss",
|
||||
|
|
|
@ -581,7 +581,6 @@ let JSWINDOWACTORS = {
|
|||
includeChrome: true,
|
||||
allFrames: true,
|
||||
matches: [
|
||||
"about:asrouter",
|
||||
"about:home",
|
||||
"about:newtab",
|
||||
"about:welcome",
|
||||
|
@ -797,7 +796,6 @@ let JSWINDOWACTORS = {
|
|||
},
|
||||
},
|
||||
matches: [
|
||||
"about:asrouter*",
|
||||
"about:home*",
|
||||
"about:newtab*",
|
||||
"about:welcome*",
|
||||
|
|
|
@ -44,11 +44,6 @@ struct RedirEntry {
|
|||
browser/components/about/components.conf
|
||||
*/
|
||||
static const RedirEntry kRedirMap[] = {
|
||||
{"asrouter", "chrome://browser/content/asrouter/asrouter-admin.html",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS |
|
||||
nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT |
|
||||
nsIAboutModule::HIDE_FROM_ABOUTABOUT},
|
||||
{"blocked", "chrome://browser/content/blockedSite.xhtml",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::URI_CAN_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT |
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
pages = [
|
||||
'asrouter',
|
||||
'blocked',
|
||||
'certerror',
|
||||
'downloads',
|
||||
|
|
|
@ -1,169 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
module.exports = {
|
||||
// When adding items to this file please check for effects on sub-directories.
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
},
|
||||
plugins: ["import", "react", "jsx-a11y"],
|
||||
settings: {
|
||||
react: {
|
||||
version: "16.2.0",
|
||||
},
|
||||
},
|
||||
extends: ["plugin:jsx-a11y/recommended"],
|
||||
overrides: [
|
||||
{
|
||||
// Only mark the files as modules which are actually modules.
|
||||
files: ["content-src/**", "tests/unit/**"],
|
||||
parserOptions: {
|
||||
sourceType: "module",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["./*.js", "content-src/**", "tests/unit/**"],
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
// Use a configuration that's appropriate for modules, workers and
|
||||
// non-production files.
|
||||
files: ["tests/**"],
|
||||
rules: {
|
||||
"no-implicit-globals": "off",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["content-src/**", "tests/unit/**"],
|
||||
rules: {
|
||||
// Disallow commonjs in these directories.
|
||||
"import/no-commonjs": 2,
|
||||
// Allow JSX with arrow functions.
|
||||
"react/jsx-no-bind": 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
// These tests simulate the browser environment.
|
||||
files: "tests/unit/**",
|
||||
env: {
|
||||
browser: true,
|
||||
mocha: true,
|
||||
},
|
||||
globals: {
|
||||
assert: true,
|
||||
chai: true,
|
||||
sinon: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: "tests/**",
|
||||
rules: {
|
||||
"func-name-matching": 0,
|
||||
"lines-between-class-members": 0,
|
||||
"require-await": 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
rules: {
|
||||
"fetch-options/no-fetch-credentials": "error",
|
||||
|
||||
"react/jsx-boolean-value": ["error", "always"],
|
||||
"react/jsx-key": "error",
|
||||
"react/jsx-no-bind": "error",
|
||||
"react/jsx-no-comment-textnodes": "error",
|
||||
"react/jsx-no-duplicate-props": "error",
|
||||
"react/jsx-no-target-blank": "error",
|
||||
"react/jsx-no-undef": "error",
|
||||
"react/jsx-pascal-case": "error",
|
||||
"react/jsx-uses-react": "error",
|
||||
"react/jsx-uses-vars": "error",
|
||||
"react/no-access-state-in-setstate": "error",
|
||||
"react/no-danger": "error",
|
||||
"react/no-deprecated": "error",
|
||||
"react/no-did-mount-set-state": "error",
|
||||
"react/no-did-update-set-state": "error",
|
||||
"react/no-direct-mutation-state": "error",
|
||||
"react/no-is-mounted": "error",
|
||||
"react/no-unknown-property": "error",
|
||||
"react/require-render-return": "error",
|
||||
|
||||
"accessor-pairs": ["error", { setWithoutGet: true, getWithoutSet: false }],
|
||||
"array-callback-return": "error",
|
||||
"block-scoped-var": "error",
|
||||
"consistent-this": ["error", "use-bind"],
|
||||
eqeqeq: "error",
|
||||
"for-direction": "error",
|
||||
"func-name-matching": "error",
|
||||
"getter-return": "error",
|
||||
"guard-for-in": "error",
|
||||
"handle-callback-err": "error",
|
||||
"lines-between-class-members": "error",
|
||||
"max-depth": ["error", 4],
|
||||
"max-nested-callbacks": ["error", 4],
|
||||
"max-params": ["error", 6],
|
||||
"max-statements": ["error", 50],
|
||||
"max-statements-per-line": ["error", { max: 2 }],
|
||||
"new-cap": ["error", { newIsCap: true, capIsNew: false }],
|
||||
"no-alert": "error",
|
||||
"no-buffer-constructor": "error",
|
||||
"no-console": ["error", { allow: ["error"] }],
|
||||
"no-div-regex": "error",
|
||||
"no-duplicate-imports": "error",
|
||||
"no-eq-null": "error",
|
||||
"no-extend-native": "error",
|
||||
"no-extra-label": "error",
|
||||
"no-implicit-coercion": ["error", { allow: ["!!"] }],
|
||||
"no-implicit-globals": "error",
|
||||
"no-loop-func": "error",
|
||||
"no-mixed-requires": "error",
|
||||
"no-multi-assign": "error",
|
||||
"no-multi-str": "error",
|
||||
"no-new": "error",
|
||||
"no-new-func": "error",
|
||||
"no-new-require": "error",
|
||||
"no-octal-escape": "error",
|
||||
"no-param-reassign": "error",
|
||||
"no-path-concat": "error",
|
||||
"no-process-exit": "error",
|
||||
"no-proto": "error",
|
||||
"no-prototype-builtins": "error",
|
||||
"no-return-assign": ["error", "except-parens"],
|
||||
"no-script-url": "error",
|
||||
"no-shadow": "error",
|
||||
"no-template-curly-in-string": "error",
|
||||
"no-undef-init": "error",
|
||||
"no-unmodified-loop-condition": "error",
|
||||
"no-unused-expressions": "error",
|
||||
"no-use-before-define": "error",
|
||||
"no-useless-computed-key": "error",
|
||||
"no-useless-constructor": "error",
|
||||
"no-useless-rename": "error",
|
||||
"no-var": "error",
|
||||
"no-void": ["error", { allowAsStatement: true }],
|
||||
"one-var": ["error", "never"],
|
||||
"operator-assignment": ["error", "always"],
|
||||
"prefer-destructuring": [
|
||||
"error",
|
||||
{
|
||||
AssignmentExpression: { array: true },
|
||||
VariableDeclarator: { array: true, object: true },
|
||||
},
|
||||
],
|
||||
"prefer-numeric-literals": "error",
|
||||
"prefer-promise-reject-errors": "error",
|
||||
"prefer-rest-params": "error",
|
||||
"prefer-spread": "error",
|
||||
"prefer-template": "error",
|
||||
radix: ["error", "always"],
|
||||
"require-await": "error",
|
||||
"sort-vars": "error",
|
||||
"symbol-description": "error",
|
||||
"vars-on-top": "error",
|
||||
yoda: ["error", "never"],
|
||||
},
|
||||
};
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,38 +0,0 @@
|
|||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="default-src 'none'; object-src 'none'; script-src resource: chrome:;"
|
||||
/>
|
||||
<meta name="color-scheme" content="light dark" />
|
||||
<title>ASRouter Admin</title>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href="chrome://branding/content/icon32.png"
|
||||
/>
|
||||
<link rel="localization" href="branding/brand.ftl" />
|
||||
<link rel="localization" href="toolkit/branding/brandings.ftl" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="chrome://browser/content/asrouter/components/ASRouterAdmin/ASRouterAdmin.css"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="chrome://browser/content/contentTheme.js"></script>
|
||||
<script src="resource://activity-stream/vendor/react.js"></script>
|
||||
<script src="resource://activity-stream/vendor/react-dom.js"></script>
|
||||
<script src="resource://activity-stream/vendor/prop-types.js"></script>
|
||||
<script src="chrome://browser/content/asrouter/asrouter-admin.bundle.js"></script>
|
||||
|
||||
<!-- The render.js script is the main entrypoint for the page. -->
|
||||
<script src="chrome://browser/content/asrouter/render.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,546 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/* stylelint-disable max-nesting-depth */
|
||||
:root {
|
||||
--newtab-background-color: #F9F9FB;
|
||||
--newtab-background-color-secondary: #FFF;
|
||||
--newtab-text-primary-color: #15141a;
|
||||
--newtab-primary-action-background: #0061e0;
|
||||
--newtab-primary-action-background-pocket: #008078;
|
||||
--newtab-text-secondary-color: color-mix(in srgb, var(--newtab-text-primary-color) 70%, transparent);
|
||||
--newtab-element-hover-color: color-mix(in srgb, var(--newtab-background-color) 90%, #000);
|
||||
--newtab-element-active-color: color-mix(in srgb, var(--newtab-background-color) 80%, #000);
|
||||
--newtab-element-secondary-color: color-mix(in srgb, currentColor 5%, transparent);
|
||||
--newtab-element-secondary-hover-color: color-mix(in srgb, currentColor 12%, transparent);
|
||||
--newtab-element-secondary-active-color: color-mix(in srgb, currentColor 25%, transparent);
|
||||
--newtab-primary-element-hover-color: color-mix(in srgb, var(--newtab-primary-action-background) 90%, #000);
|
||||
--newtab-primary-element-hover-pocket-color: color-mix(in srgb, var(--newtab-primary-action-background-pocket) 90%, #000);
|
||||
--newtab-primary-element-active-color: color-mix(in srgb, var(--newtab-primary-action-background) 80%, #000);
|
||||
--newtab-primary-element-text-color: #FFF;
|
||||
--newtab-primary-action-background-dimmed: color-mix(in srgb, var(--newtab-primary-action-background) 25%, transparent);
|
||||
--newtab-primary-action-background-pocket-dimmed: color-mix(in srgb, var(--newtab-primary-action-background-pocket) 25%, transparent);
|
||||
--newtab-border-color: color-mix(in srgb, var(--newtab-background-color) 75%, #000);
|
||||
--newtab-wordmark-color: #20123A;
|
||||
--newtab-status-success: #058B00;
|
||||
--newtab-status-error: #D70022;
|
||||
--newtab-inner-box-shadow-color: rgba(0, 0, 0, 0.1);
|
||||
--newtab-overlay-color: color-mix(in srgb, var(--newtab-background-color) 85%, transparent);
|
||||
--newtab-textbox-focus-color: var(--newtab-primary-action-background);
|
||||
--newtab-textbox-focus-boxshadow: 0 0 0 1px var(--newtab-primary-action-background), 0 0 0 4px rgba(var(--newtab-primary-action-background), 0.3);
|
||||
--newtab-button-secondary-color: inherit;
|
||||
}
|
||||
:root[lwt-newtab-brighttext] {
|
||||
--newtab-background-color: #2B2A33;
|
||||
--newtab-background-color-secondary: #42414d;
|
||||
--newtab-text-primary-color: #fbfbfe;
|
||||
--newtab-primary-action-background: #00ddff;
|
||||
--newtab-primary-action-background-pocket: #00ddff;
|
||||
--newtab-primary-action-background-pocket-dimmed: color-mix(in srgb, var(--newtab-primary-action-background) 25%, transparent);
|
||||
--newtab-primary-element-hover-color: color-mix(in srgb, var(--newtab-primary-action-background) 55%, #FFF);
|
||||
--newtab-primary-element-hover-pocket-color: color-mix(in srgb, var(--newtab-primary-action-background-pocket) 55%, #FFF);
|
||||
--newtab-element-hover-color: color-mix(in srgb, var(--newtab-background-color) 80%, #FFF);
|
||||
--newtab-element-active-color: color-mix(in srgb, var(--newtab-background-color) 60%, #FFF);
|
||||
--newtab-element-secondary-color: color-mix(in srgb, currentColor 10%, transparent);
|
||||
--newtab-element-secondary-hover-color: color-mix(in srgb, currentColor 17%, transparent);
|
||||
--newtab-element-secondary-active-color: color-mix(in srgb, currentColor 30%, transparent);
|
||||
--newtab-border-color: color-mix(in srgb, var(--newtab-background-color) 75%, #FFF);
|
||||
--newtab-primary-element-text-color: #2b2a33;
|
||||
--newtab-wordmark-color: #fbfbfe;
|
||||
--newtab-status-success: #7C6;
|
||||
}
|
||||
|
||||
@media (prefers-contrast) {
|
||||
:root {
|
||||
--newtab-text-secondary-color: var(--newtab-text-primary-color);
|
||||
}
|
||||
}
|
||||
.icon {
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 16px;
|
||||
-moz-context-properties: fill;
|
||||
display: inline-block;
|
||||
color: var(--newtab-text-primary-color);
|
||||
fill: currentColor;
|
||||
height: 16px;
|
||||
vertical-align: middle;
|
||||
width: 16px;
|
||||
}
|
||||
.icon.icon-spacer {
|
||||
margin-inline-end: 8px;
|
||||
}
|
||||
.icon.icon-small-spacer {
|
||||
margin-inline-end: 6px;
|
||||
}
|
||||
.icon.icon-button-style {
|
||||
fill: var(--newtab-text-secondary-color);
|
||||
border: 0;
|
||||
}
|
||||
.icon.icon-button-style:focus, .icon.icon-button-style:hover {
|
||||
fill: var(--newtab-text-primary-color);
|
||||
}
|
||||
.icon.icon-bookmark-added {
|
||||
background-image: url("chrome://browser/skin/bookmark.svg");
|
||||
}
|
||||
.icon.icon-bookmark-hollow {
|
||||
background-image: url("chrome://browser/skin/bookmark-hollow.svg");
|
||||
}
|
||||
.icon.icon-clear-input {
|
||||
background-image: url("chrome://global/skin/icons/close-fill.svg");
|
||||
}
|
||||
.icon.icon-delete {
|
||||
background-image: url("chrome://global/skin/icons/delete.svg");
|
||||
}
|
||||
.icon.icon-search {
|
||||
background-image: url("chrome://global/skin/icons/search-glass.svg");
|
||||
}
|
||||
.icon.icon-modal-delete {
|
||||
flex-shrink: 0;
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-modal-delete-20.svg");
|
||||
background-size: 32px;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
}
|
||||
.icon.icon-mail {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-mail-16.svg");
|
||||
}
|
||||
.icon.icon-dismiss {
|
||||
background-image: url("chrome://global/skin/icons/close.svg");
|
||||
}
|
||||
.icon.icon-info {
|
||||
background-image: url("chrome://global/skin/icons/info.svg");
|
||||
}
|
||||
.icon.icon-new-window {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-newWindow-16.svg");
|
||||
}
|
||||
.icon.icon-new-window:dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
.icon.icon-new-window-private {
|
||||
background-image: url("chrome://browser/skin/privateBrowsing.svg");
|
||||
}
|
||||
.icon.icon-settings {
|
||||
background-image: url("chrome://global/skin/icons/settings.svg");
|
||||
}
|
||||
.icon.icon-pin {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-pin-16.svg");
|
||||
}
|
||||
.icon.icon-pin:dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
.icon.icon-unpin {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-unpin-16.svg");
|
||||
}
|
||||
.icon.icon-unpin:dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
.icon.icon-edit {
|
||||
background-image: url("chrome://global/skin/icons/edit.svg");
|
||||
}
|
||||
.icon.icon-pocket {
|
||||
background-image: url("chrome://global/skin/icons/pocket.svg");
|
||||
}
|
||||
.icon.icon-pocket-save {
|
||||
background-image: url("chrome://global/skin/icons/pocket.svg");
|
||||
fill: #FFF;
|
||||
}
|
||||
.icon.icon-pocket-delete {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-pocket-delete-16.svg");
|
||||
}
|
||||
.icon.icon-pocket-archive {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-pocket-archive-16.svg");
|
||||
}
|
||||
.icon.icon-history-item {
|
||||
background-image: url("chrome://browser/skin/history.svg");
|
||||
}
|
||||
.icon.icon-trending {
|
||||
background-image: url("chrome://browser/skin/trending.svg");
|
||||
transform: translateY(2px);
|
||||
}
|
||||
.icon.icon-now {
|
||||
background-image: url("chrome://browser/skin/history.svg");
|
||||
}
|
||||
.icon.icon-topsites {
|
||||
background-image: url("chrome://browser/skin/topsites.svg");
|
||||
}
|
||||
.icon.icon-pin-small {
|
||||
background-image: url("chrome://browser/skin/pin-12.svg");
|
||||
background-size: 12px;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
}
|
||||
.icon.icon-pin-small:dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
.icon.icon-check {
|
||||
background-image: url("chrome://global/skin/icons/check.svg");
|
||||
}
|
||||
.icon.icon-download {
|
||||
background-image: url("chrome://browser/skin/downloads/downloads.svg");
|
||||
}
|
||||
.icon.icon-copy {
|
||||
background-image: url("chrome://global/skin/icons/edit-copy.svg");
|
||||
}
|
||||
.icon.icon-open-file {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-open-file-16.svg");
|
||||
}
|
||||
.icon.icon-webextension {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-webextension-16.svg");
|
||||
}
|
||||
.icon.icon-highlights {
|
||||
background-image: url("chrome://global/skin/icons/highlights.svg");
|
||||
}
|
||||
.icon.icon-arrowhead-down {
|
||||
background-image: url("chrome://global/skin/icons/arrow-down.svg");
|
||||
}
|
||||
.icon.icon-arrowhead-down-small {
|
||||
background-image: url("chrome://global/skin/icons/arrow-down-12.svg");
|
||||
background-size: 12px;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
}
|
||||
.icon.icon-arrowhead-forward-small {
|
||||
background-image: url("chrome://global/skin/icons/arrow-right-12.svg");
|
||||
background-size: 12px;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
}
|
||||
.icon.icon-arrowhead-forward-small:dir(rtl) {
|
||||
background-image: url("chrome://global/skin/icons/arrow-left-12.svg");
|
||||
}
|
||||
.icon.icon-arrowhead-up {
|
||||
background-image: url("chrome://global/skin/icons/arrow-up.svg");
|
||||
}
|
||||
.icon.icon-add {
|
||||
background-image: url("chrome://global/skin/icons/plus.svg");
|
||||
}
|
||||
.icon.icon-minimize {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-minimize-16.svg");
|
||||
}
|
||||
.icon.icon-maximize {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/glyph-maximize-16.svg");
|
||||
}
|
||||
.icon.icon-arrow {
|
||||
background-image: url("chrome://global/skin/icons/arrow-right-12.svg");
|
||||
}
|
||||
|
||||
.ASRouterButton {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
border-radius: 2px;
|
||||
border: 0;
|
||||
font-family: inherit;
|
||||
padding: 8px 15px;
|
||||
margin-inline-start: 12px;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
}
|
||||
.tall .ASRouterButton {
|
||||
margin-inline-start: 20px;
|
||||
}
|
||||
.ASRouterButton.test-only {
|
||||
width: 0;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
visibility: hidden;
|
||||
}
|
||||
.ASRouterButton.primary {
|
||||
border: 1px solid var(--newtab-primary-action-background);
|
||||
background-color: var(--newtab-primary-action-background);
|
||||
color: var(--newtab-primary-element-text-color);
|
||||
}
|
||||
.ASRouterButton.primary:hover {
|
||||
background-color: var(--newtab-primary-element-hover-color);
|
||||
}
|
||||
.ASRouterButton.primary:active {
|
||||
background-color: var(--newtab-primary-element-active-color);
|
||||
}
|
||||
.ASRouterButton.slim {
|
||||
border: 1px solid var(--newtab-border-color);
|
||||
margin-inline-start: 0;
|
||||
font-size: 12px;
|
||||
padding: 6px 12px;
|
||||
}
|
||||
.ASRouterButton.slim:hover, .ASRouterButton.slim:focus {
|
||||
box-shadow: 0 0 0 5px var(--newtab-element-secondary-color);
|
||||
transition: box-shadow 150ms;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Ubuntu, "Helvetica Neue", sans-serif;
|
||||
}
|
||||
|
||||
/**
|
||||
* These styles are copied verbatim from _activity-stream.scss in order to maintain
|
||||
* a continuity of styling while also decoupling from the newtab code. This should
|
||||
* be removed when about:asrouter starts using the default in-content style sheets.
|
||||
*/
|
||||
.button,
|
||||
.actions button {
|
||||
background-color: var(--newtab-button-secondary-color);
|
||||
border: 1px solid var(--newtab-border-color);
|
||||
border-radius: 4px;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
margin-bottom: 15px;
|
||||
padding: 10px 30px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.button:hover:not(.dismiss), .button:focus:not(.dismiss),
|
||||
.actions button:hover:not(.dismiss),
|
||||
.actions button:focus:not(.dismiss) {
|
||||
box-shadow: 0 0 0 5px var(--newtab-element-secondary-color);
|
||||
transition: box-shadow 150ms;
|
||||
}
|
||||
.button.dismiss,
|
||||
.actions button.dismiss {
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.button.primary, .button.done,
|
||||
.actions button.primary,
|
||||
.actions button.done {
|
||||
background-color: var(--newtab-primary-action-background);
|
||||
border: solid 1px var(--newtab-primary-action-background);
|
||||
color: var(--newtab-primary-element-text-color);
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
|
||||
.asrouter-admin {
|
||||
max-width: 1300px;
|
||||
font-size: 14px;
|
||||
padding-inline-start: 240px;
|
||||
color: var(--newtab-text-primary-color);
|
||||
}
|
||||
.asrouter-admin.collapsed {
|
||||
display: none;
|
||||
}
|
||||
.asrouter-admin .sidebar {
|
||||
inset-inline-start: 0;
|
||||
position: fixed;
|
||||
width: 240px;
|
||||
}
|
||||
.asrouter-admin .sidebar ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.asrouter-admin .sidebar li a {
|
||||
padding: 10px 34px;
|
||||
display: block;
|
||||
color: var(--lwt-sidebar-text-color);
|
||||
}
|
||||
.asrouter-admin .sidebar li a:hover {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
}
|
||||
.asrouter-admin h1 {
|
||||
font-weight: 200;
|
||||
font-size: 32px;
|
||||
}
|
||||
.asrouter-admin h2 .button,
|
||||
.asrouter-admin p .button {
|
||||
font-size: 14px;
|
||||
padding: 6px 12px;
|
||||
margin-inline-start: 5px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.asrouter-admin .general-textarea {
|
||||
direction: ltr;
|
||||
width: 740px;
|
||||
height: 500px;
|
||||
overflow: auto;
|
||||
resize: none;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
}
|
||||
.asrouter-admin .wnp-textarea {
|
||||
direction: ltr;
|
||||
width: 740px;
|
||||
height: 500px;
|
||||
overflow: auto;
|
||||
resize: none;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
}
|
||||
.asrouter-admin .json-button {
|
||||
display: inline-flex;
|
||||
font-size: 10px;
|
||||
padding: 4px 10px;
|
||||
margin-bottom: 6px;
|
||||
margin-inline-end: 4px;
|
||||
}
|
||||
.asrouter-admin .json-button:hover {
|
||||
background-color: var(--newtab-element-hover-color);
|
||||
box-shadow: none;
|
||||
}
|
||||
.asrouter-admin table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.asrouter-admin table.minimal-table {
|
||||
border-collapse: collapse;
|
||||
border: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.asrouter-admin table.minimal-table td {
|
||||
padding: 8px;
|
||||
}
|
||||
.asrouter-admin table.minimal-table td:first-child {
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.asrouter-admin table.minimal-table td:not(:first-child) {
|
||||
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
|
||||
}
|
||||
.asrouter-admin table.errorReporting tr {
|
||||
border: 1px solid var(--newtab-background-color-secondary);
|
||||
}
|
||||
.asrouter-admin table.errorReporting td {
|
||||
padding: 4px;
|
||||
}
|
||||
.asrouter-admin table.errorReporting td[rowspan] {
|
||||
border: 1px solid var(--newtab-background-color-secondary);
|
||||
}
|
||||
.asrouter-admin .sourceLabel {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.asrouter-admin .sourceLabel.isDisabled {
|
||||
background: rgba(215, 0, 34, 0.3);
|
||||
color: var(--newtab-status-error);
|
||||
}
|
||||
.asrouter-admin .message-item:first-child td {
|
||||
border-top: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.asrouter-admin .message-item td {
|
||||
vertical-align: top;
|
||||
padding: 8px;
|
||||
border-bottom: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.asrouter-admin .message-item td.min {
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.asrouter-admin .message-item td.message-summary {
|
||||
width: 60%;
|
||||
}
|
||||
.asrouter-admin .message-item td.button-column {
|
||||
width: 15%;
|
||||
}
|
||||
.asrouter-admin .message-item td:first-child {
|
||||
border-inline-start: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.asrouter-admin .message-item td:last-child {
|
||||
border-inline-end: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.asrouter-admin .message-item.blocked .message-id,
|
||||
.asrouter-admin .message-item.blocked .message-summary {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.asrouter-admin .message-item.blocked .message-id {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.asrouter-admin .message-item .message-id {
|
||||
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
.asrouter-admin .providerUrl {
|
||||
font-size: 12px;
|
||||
}
|
||||
.asrouter-admin pre {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
font-size: 12px;
|
||||
max-width: 750px;
|
||||
overflow: auto;
|
||||
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
|
||||
}
|
||||
.asrouter-admin .errorState {
|
||||
border: 1px solid var(--newtab-status-error);
|
||||
}
|
||||
.asrouter-admin .helpLink {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
border-radius: 3px;
|
||||
align-items: center;
|
||||
}
|
||||
.asrouter-admin .helpLink a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.asrouter-admin .helpLink .icon {
|
||||
min-width: 18px;
|
||||
min-height: 18px;
|
||||
}
|
||||
.asrouter-admin .ds-component {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.asrouter-admin .modalOverlayInner {
|
||||
height: 80%;
|
||||
}
|
||||
.asrouter-admin .clearButton {
|
||||
border: 0;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
}
|
||||
.asrouter-admin .clearButton:hover {
|
||||
background: var(--newtab-element-hover-color);
|
||||
}
|
||||
.asrouter-admin .collapsed {
|
||||
display: none;
|
||||
}
|
||||
.asrouter-admin .icon {
|
||||
display: inline-table;
|
||||
cursor: pointer;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
.asrouter-admin .button:disabled, .asrouter-admin .button:disabled:active {
|
||||
opacity: 0.5;
|
||||
cursor: unset;
|
||||
box-shadow: none;
|
||||
}
|
||||
.asrouter-admin .impressions-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.asrouter-admin .impressions-section .impressions-item {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
padding: 8px;
|
||||
border: 1px solid var(--newtab-border-color);
|
||||
border-radius: 5px;
|
||||
}
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-inner-box {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
gap: 8px;
|
||||
}
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-category {
|
||||
font-size: 1.15em;
|
||||
white-space: nowrap;
|
||||
flex-grow: 0.1;
|
||||
}
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-buttons button {
|
||||
margin: 0;
|
||||
}
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-editor {
|
||||
display: flex;
|
||||
flex-grow: 1.5;
|
||||
}
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-editor .general-textarea {
|
||||
width: auto;
|
||||
flex-grow: 1;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
// exported by asrouter-admin.bundle.js
|
||||
window.ASRouterAdminRenderUtils.renderASRouterAdmin();
|
|
@ -1,9 +0,0 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
browser.jar:
|
||||
content/browser/asrouter/asrouter-admin.html (content/asrouter-admin.html)
|
||||
content/browser/asrouter/asrouter-admin.bundle.js (content/asrouter-admin.bundle.js)
|
||||
content/browser/asrouter/components/ASRouterAdmin/ASRouterAdmin.css (content/components/ASRouterAdmin/ASRouterAdmin.css)
|
||||
content/browser/asrouter/render.js (content/render.js)
|
|
@ -1,203 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const path = require("path");
|
||||
const webpack = require("webpack");
|
||||
const { ResourceUriPlugin } = require("../newtab/tools/resourceUriPlugin");
|
||||
|
||||
const PATHS = {
|
||||
// Where is the entry point for the unit tests?
|
||||
testEntryFile: path.resolve(__dirname, "./tests/unit/unit-entry.js"),
|
||||
|
||||
// A glob-style pattern matching all unit tests
|
||||
testFilesPattern: "./tests/unit/unit-entry.js",
|
||||
|
||||
// The base directory of all source files (used for path resolution in webpack importing)
|
||||
moduleResolveDirectory: __dirname,
|
||||
newtabResolveDirectory: "../newtab",
|
||||
|
||||
// a RegEx matching all Cu.import statements of local files
|
||||
resourcePathRegEx: /^resource:\/\/activity-stream\//,
|
||||
|
||||
coverageReportingPath: "logs/coverage/",
|
||||
};
|
||||
|
||||
// When tweaking here, be sure to review the docs about the execution ordering
|
||||
// semantics of the preprocessors array, as they are somewhat odd.
|
||||
const preprocessors = {};
|
||||
preprocessors[PATHS.testFilesPattern] = [
|
||||
"webpack", // require("karma-webpack")
|
||||
"sourcemap", // require("karma-sourcemap-loader")
|
||||
];
|
||||
|
||||
module.exports = function (config) {
|
||||
const isTDD = config.tdd;
|
||||
const browsers = isTDD ? ["Firefox"] : ["FirefoxHeadless"]; // require("karma-firefox-launcher")
|
||||
config.set({
|
||||
singleRun: !isTDD,
|
||||
browsers,
|
||||
customLaunchers: {
|
||||
FirefoxHeadless: {
|
||||
base: "Firefox",
|
||||
flags: ["--headless"],
|
||||
},
|
||||
},
|
||||
frameworks: [
|
||||
"chai", // require("chai") require("karma-chai")
|
||||
"mocha", // require("mocha") require("karma-mocha")
|
||||
"sinon", // require("sinon") require("karma-sinon")
|
||||
],
|
||||
reporters: [
|
||||
"coverage-istanbul", // require("karma-coverage")
|
||||
"mocha", // require("karma-mocha-reporter")
|
||||
|
||||
// for bin/try-runner.js to parse the output easily
|
||||
"json", // require("karma-json-reporter")
|
||||
],
|
||||
jsonReporter: {
|
||||
// So this doesn't get interleaved with other karma output
|
||||
stdout: false,
|
||||
outputFile: path.join("logs", "karma-run-results.json"),
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
reports: ["lcov", "text-summary"], // for some reason "lcov" reallys means "lcov" and "html"
|
||||
"report-config": {
|
||||
// so the full m-c path gets printed; needed for https://coverage.moz.tools/ integration
|
||||
lcov: {
|
||||
projectRoot: "../../..",
|
||||
},
|
||||
},
|
||||
dir: PATHS.coverageReportingPath,
|
||||
// This will make karma fail if coverage reporting is less than the minimums here
|
||||
thresholds: !isTDD && {
|
||||
each: {
|
||||
statements: 100,
|
||||
lines: 100,
|
||||
functions: 100,
|
||||
branches: 66,
|
||||
overrides: {
|
||||
"content-src/components/ASRouterAdmin/*.jsx": {
|
||||
statements: 0,
|
||||
lines: 0,
|
||||
functions: 0,
|
||||
branches: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
files: [PATHS.testEntryFile],
|
||||
preprocessors,
|
||||
webpack: {
|
||||
mode: "none",
|
||||
devtool: "inline-source-map",
|
||||
// This loader allows us to override required files in tests
|
||||
resolveLoader: {
|
||||
alias: {
|
||||
inject: path.join(__dirname, "../newtab/loaders/inject-loader"),
|
||||
},
|
||||
},
|
||||
// This resolve config allows us to import with paths relative to the root directory, e.g. "lib/ActivityStream.jsm"
|
||||
resolve: {
|
||||
extensions: [".js", ".jsx"],
|
||||
modules: [
|
||||
PATHS.moduleResolveDirectory,
|
||||
"node_modules",
|
||||
PATHS.newtabResolveDirectory,
|
||||
],
|
||||
fallback: {
|
||||
stream: require.resolve("stream-browserify"),
|
||||
buffer: require.resolve("buffer"),
|
||||
},
|
||||
alias: {
|
||||
newtab: path.join(__dirname, "../newtab"),
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
// The ResourceUriPlugin handles translating resource URIs in import
|
||||
// statements in .mjs files, in a similar way to what
|
||||
// babel-jsm-to-commonjs does for jsm files.
|
||||
new ResourceUriPlugin({
|
||||
resourcePathRegEx: PATHS.resourcePathRegEx,
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
"process.env.NODE_ENV": JSON.stringify("development"),
|
||||
}),
|
||||
],
|
||||
externals: {
|
||||
// enzyme needs these for backwards compatibility with 0.13.
|
||||
// see https://github.com/airbnb/enzyme/blob/master/docs/guides/webpack.md#using-enzyme-with-webpack
|
||||
"react/addons": true,
|
||||
"react/lib/ReactContext": true,
|
||||
"react/lib/ExecutionEnvironment": true,
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
// This rule rewrites importing/exporting in .jsm files to be compatible with esmodules
|
||||
{
|
||||
test: /\.jsm$/,
|
||||
exclude: [/node_modules/],
|
||||
use: [
|
||||
{
|
||||
loader: "babel-loader", // require("babel-core")
|
||||
options: {
|
||||
plugins: [
|
||||
// Converts .jsm files into common-js modules
|
||||
[
|
||||
"../newtab/tools/babel-jsm-to-commonjs.js",
|
||||
{
|
||||
basePath: PATHS.resourcePathRegEx,
|
||||
removeOtherImports: true,
|
||||
replace: true,
|
||||
},
|
||||
],
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator",
|
||||
"@babel/plugin-proposal-optional-chaining",
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: [/node_modules\/(?!@fluent\/).*/, /tests/],
|
||||
loader: "babel-loader",
|
||||
options: {
|
||||
// This is a workaround for bug 1787278. It can be removed once
|
||||
// that bug is fixed.
|
||||
plugins: ["@babel/plugin-proposal-optional-chaining"],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.jsx$/,
|
||||
exclude: /node_modules/,
|
||||
loader: "babel-loader",
|
||||
options: {
|
||||
presets: ["@babel/preset-react"],
|
||||
plugins: [
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator",
|
||||
"@babel/plugin-proposal-optional-chaining",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.md$/,
|
||||
use: "raw-loader",
|
||||
},
|
||||
{
|
||||
enforce: "post",
|
||||
test: /\.js[mx]?$/,
|
||||
loader: "@jsdevtools/coverage-istanbul-loader",
|
||||
options: { esModules: true },
|
||||
include: [path.resolve("content-src"), path.resolve("modules")],
|
||||
exclude: [path.resolve("tests"), path.resolve("../newtab")],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
// Silences some overly-verbose logging of individual module builds
|
||||
webpackMiddleware: { noInfo: true },
|
||||
});
|
||||
};
|
|
@ -1,10 +0,0 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
JAR_MANIFESTS += ["jar.mn"]
|
||||
|
||||
with Files("**"):
|
||||
BUG_COMPONENT = ("Firefox", "Messaging System")
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,83 +0,0 @@
|
|||
{
|
||||
"name": "ASRouter",
|
||||
"description": "Task running for ASRouter",
|
||||
"version": "1.0.0",
|
||||
"author": "Mozilla (https://mozilla.org/)",
|
||||
"dependencies": {
|
||||
"@fluent/bundle": "0.17.1",
|
||||
"@fluent/react": "0.15.0",
|
||||
"react": "16.13.1",
|
||||
"react-dom": "16.13.1",
|
||||
"react-redux": "7.2.6",
|
||||
"redux": "4.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-class-properties": "7.16.0",
|
||||
"@babel/plugin-proposal-optional-chaining": "7.16.0",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "7.16.0",
|
||||
"@babel/preset-react": "7.16.0",
|
||||
"@jsdevtools/coverage-istanbul-loader": "^3.0.5",
|
||||
"babel-loader": "8.2.3",
|
||||
"babel-plugin-jsm-to-esmodules": "0.6.0",
|
||||
"chai": "4.3.4",
|
||||
"chai-json-schema": "1.5.1",
|
||||
"enzyme": "3.11.0",
|
||||
"enzyme-adapter-react-16": "1.15.6",
|
||||
"karma": "6.3.8",
|
||||
"karma-chai": "0.1.0",
|
||||
"karma-coverage-istanbul-reporter": "3.0.3",
|
||||
"karma-firefox-launcher": "2.1.2",
|
||||
"karma-json-reporter": "1.2.1",
|
||||
"karma-mocha": "2.0.1",
|
||||
"karma-mocha-reporter": "2.2.5",
|
||||
"karma-sinon": "1.0.5",
|
||||
"karma-sourcemap-loader": "0.3.8",
|
||||
"karma-webpack": "5.0.0",
|
||||
"mocha": "9.1.3",
|
||||
"npm-run-all": "4.1.5",
|
||||
"sass": "1.43.4",
|
||||
"sinon": "12.0.1",
|
||||
"stream-browserify": "3.0.0",
|
||||
"webpack": "5.56.0",
|
||||
"webpack-cli": "4.9.1",
|
||||
"yamscripts": "0.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"firefox": ">=45.0 <=*",
|
||||
"//": "when changing node versions, also edit .nvmrc",
|
||||
"node": "16.19.*",
|
||||
"npm": "8.19.3"
|
||||
},
|
||||
"license": "MPL-2.0",
|
||||
"config": {
|
||||
"mc_root": "../../..",
|
||||
"asrouter_path": "browser/components/asrouter"
|
||||
},
|
||||
"scripts": {
|
||||
"bundle": "npm-run-all bundle:*",
|
||||
"bundle:admin": "webpack-cli --config webpack.asrouter-admin.config.js",
|
||||
"bundle:css": "sass content-src:content --no-source-map",
|
||||
"watchmc": "npm-run-all --parallel watchmc:*",
|
||||
"watchmc:bundle": "npm run bundle:admin -- --env development -w",
|
||||
"watchmc:css": "npm run bundle:css -- --source-map --embed-sources --embed-source-map -w",
|
||||
"testmc": "npm-run-all testmc:*",
|
||||
"testmc:lint": "npm run lint",
|
||||
"testmc:build": "npm run bundle:admin",
|
||||
"testmc:unit": "karma start karma.mc.config.js",
|
||||
"tddmc": "karma start karma.mc.config.js --tdd",
|
||||
"debugcoverage": "open logs/coverage/lcov-report/index.html",
|
||||
"lint": "npm-run-all lint:*",
|
||||
"lint:codespell": "(cd $npm_package_config_mc_root && ./mach lint -l codespell $npm_package_config_asrouter_path)",
|
||||
"lint:eslint": "(cd $npm_package_config_mc_root && ./mach lint -l eslint $npm_package_config_asrouter_path)",
|
||||
"lint:license": "(cd $npm_package_config_mc_root && ./mach lint -l license $npm_package_config_asrouter_path)",
|
||||
"lint:stylelint": "(cd $npm_package_config_mc_root && ./mach lint -l stylelint $npm_package_config_asrouter_path)",
|
||||
"test": "npm run testmc",
|
||||
"tdd": "npm run tddmc",
|
||||
"fix": "npm-run-all fix:*",
|
||||
"fix:eslint": "npm run lint:eslint -- --fix",
|
||||
"fix:stylelint": "npm run lint:stylelint -- --fix",
|
||||
"help": "yamscripts help",
|
||||
"yamscripts": "yamscripts compile",
|
||||
"__": "# NOTE: THESE SCRIPTS ARE COMPILED!!! EDIT yamscripts.yml instead!!!"
|
||||
}
|
||||
}
|
|
@ -1,720 +0,0 @@
|
|||
import {
|
||||
EventEmitter,
|
||||
FakePrefs,
|
||||
FakensIPrefService,
|
||||
GlobalOverrider,
|
||||
FakeConsoleAPI,
|
||||
FakeLogger,
|
||||
} from "newtab/test/unit/utils";
|
||||
import Adapter from "enzyme-adapter-react-16";
|
||||
import { chaiAssertions } from "newtab/test/schemas/pings";
|
||||
import chaiJsonSchema from "chai-json-schema";
|
||||
import enzyme from "enzyme";
|
||||
import FxMSCommonSchema from "newtab/content-src/asrouter/schemas/FxMSCommon.schema.json";
|
||||
|
||||
enzyme.configure({ adapter: new Adapter() });
|
||||
|
||||
// Cause React warnings to make tests that trigger them fail
|
||||
const origConsoleError = console.error;
|
||||
console.error = function (msg, ...args) {
|
||||
origConsoleError.apply(console, [msg, ...args]);
|
||||
|
||||
if (
|
||||
/(Invalid prop|Failed prop type|Check the render method|React Intl)/.test(
|
||||
msg
|
||||
)
|
||||
) {
|
||||
throw new Error(msg);
|
||||
}
|
||||
};
|
||||
|
||||
const req = require.context(".", true, /\.test\.jsx?$/);
|
||||
const files = req.keys();
|
||||
|
||||
// This exposes sinon assertions to chai.assert
|
||||
sinon.assert.expose(assert, { prefix: "" });
|
||||
|
||||
chai.use(chaiAssertions);
|
||||
chai.use(chaiJsonSchema);
|
||||
chai.tv4.addSchema("file:///FxMSCommon.schema.json", FxMSCommonSchema);
|
||||
|
||||
const overrider = new GlobalOverrider();
|
||||
|
||||
const RemoteSettings = name => ({
|
||||
get: () => {
|
||||
if (name === "attachment") {
|
||||
return Promise.resolve([{ attachment: {} }]);
|
||||
}
|
||||
return Promise.resolve([]);
|
||||
},
|
||||
on: () => {},
|
||||
off: () => {},
|
||||
});
|
||||
RemoteSettings.pollChanges = () => {};
|
||||
|
||||
class JSWindowActorParent {
|
||||
sendAsyncMessage(name, data) {
|
||||
return { name, data };
|
||||
}
|
||||
}
|
||||
|
||||
class JSWindowActorChild {
|
||||
sendAsyncMessage(name, data) {
|
||||
return { name, data };
|
||||
}
|
||||
|
||||
sendQuery(name, data) {
|
||||
return Promise.resolve({ name, data });
|
||||
}
|
||||
|
||||
get contentWindow() {
|
||||
return {
|
||||
Promise,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Detect plain object passed to lazy getter APIs, and set its prototype to
|
||||
// global object, and return the global object for further modification.
|
||||
// Returns the object if it's not plain object.
|
||||
//
|
||||
// This is a workaround to make the existing testharness and testcase keep
|
||||
// working even after lazy getters are moved to plain `lazy` object.
|
||||
const cachedPlainObject = new Set();
|
||||
function updateGlobalOrObject(object) {
|
||||
// Given this function modifies the prototype, and the following
|
||||
// condition doesn't meet on the second call, cache the result.
|
||||
if (cachedPlainObject.has(object)) {
|
||||
return global;
|
||||
}
|
||||
|
||||
if (Object.getPrototypeOf(object).constructor.name !== "Object") {
|
||||
return object;
|
||||
}
|
||||
|
||||
cachedPlainObject.add(object);
|
||||
Object.setPrototypeOf(object, global);
|
||||
return global;
|
||||
}
|
||||
|
||||
const TEST_GLOBAL = {
|
||||
JSWindowActorParent,
|
||||
JSWindowActorChild,
|
||||
AboutReaderParent: {
|
||||
addMessageListener: (messageName, listener) => {},
|
||||
removeMessageListener: (messageName, listener) => {},
|
||||
},
|
||||
AboutWelcomeTelemetry: class {
|
||||
submitGleanPingForPing() {}
|
||||
},
|
||||
AddonManager: {
|
||||
getActiveAddons() {
|
||||
return Promise.resolve({ addons: [], fullData: false });
|
||||
},
|
||||
},
|
||||
AppConstants: {
|
||||
MOZILLA_OFFICIAL: true,
|
||||
MOZ_APP_VERSION: "69.0a1",
|
||||
isChinaRepack() {
|
||||
return false;
|
||||
},
|
||||
isPlatformAndVersionAtMost() {
|
||||
return false;
|
||||
},
|
||||
platform: "win",
|
||||
},
|
||||
ASRouterPreferences: {
|
||||
console: new FakeConsoleAPI({
|
||||
maxLogLevel: "off", // set this to "debug" or "all" to get more ASRouter logging in tests
|
||||
prefix: "ASRouter",
|
||||
}),
|
||||
},
|
||||
AWScreenUtils: {
|
||||
evaluateTargetingAndRemoveScreens() {
|
||||
return true;
|
||||
},
|
||||
async removeScreens() {
|
||||
return true;
|
||||
},
|
||||
evaluateScreenTargeting() {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
BrowserUtils: {
|
||||
sendToDeviceEmailsSupported() {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
UpdateUtils: { getUpdateChannel() {} },
|
||||
BasePromiseWorker: class {
|
||||
constructor() {
|
||||
this.ExceptionHandlers = [];
|
||||
}
|
||||
post() {}
|
||||
},
|
||||
browserSearchRegion: "US",
|
||||
BrowserWindowTracker: { getTopWindow() {} },
|
||||
ChromeUtils: {
|
||||
defineModuleGetter: updateGlobalOrObject,
|
||||
defineESModuleGetters: updateGlobalOrObject,
|
||||
generateQI() {
|
||||
return {};
|
||||
},
|
||||
import() {
|
||||
return global;
|
||||
},
|
||||
importESModule() {
|
||||
return global;
|
||||
},
|
||||
},
|
||||
ClientEnvironment: {
|
||||
get userId() {
|
||||
return "foo123";
|
||||
},
|
||||
},
|
||||
Components: {
|
||||
Constructor(classId) {
|
||||
switch (classId) {
|
||||
case "@mozilla.org/referrer-info;1":
|
||||
return function (referrerPolicy, sendReferrer, originalReferrer) {
|
||||
this.referrerPolicy = referrerPolicy;
|
||||
this.sendReferrer = sendReferrer;
|
||||
this.originalReferrer = originalReferrer;
|
||||
};
|
||||
}
|
||||
return function () {};
|
||||
},
|
||||
isSuccessCode: () => true,
|
||||
},
|
||||
ConsoleAPI: FakeConsoleAPI,
|
||||
// NB: These are functions/constructors
|
||||
// eslint-disable-next-line object-shorthand
|
||||
ContentSearchUIController: function () {},
|
||||
// eslint-disable-next-line object-shorthand
|
||||
ContentSearchHandoffUIController: function () {},
|
||||
Cc: {
|
||||
"@mozilla.org/browser/nav-bookmarks-service;1": {
|
||||
addObserver() {},
|
||||
getService() {
|
||||
return this;
|
||||
},
|
||||
removeObserver() {},
|
||||
SOURCES: {},
|
||||
TYPE_BOOKMARK: {},
|
||||
},
|
||||
"@mozilla.org/browser/nav-history-service;1": {
|
||||
addObserver() {},
|
||||
executeQuery() {},
|
||||
getNewQuery() {},
|
||||
getNewQueryOptions() {},
|
||||
getService() {
|
||||
return this;
|
||||
},
|
||||
insert() {},
|
||||
markPageAsTyped() {},
|
||||
removeObserver() {},
|
||||
},
|
||||
"@mozilla.org/io/string-input-stream;1": {
|
||||
createInstance() {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
"@mozilla.org/security/hash;1": {
|
||||
createInstance() {
|
||||
return {
|
||||
init() {},
|
||||
updateFromStream() {},
|
||||
finish() {
|
||||
return "0";
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
"@mozilla.org/updates/update-checker;1": { createInstance() {} },
|
||||
"@mozilla.org/widget/useridleservice;1": {
|
||||
getService() {
|
||||
return {
|
||||
idleTime: 0,
|
||||
addIdleObserver() {},
|
||||
removeIdleObserver() {},
|
||||
};
|
||||
},
|
||||
},
|
||||
"@mozilla.org/streamConverters;1": {
|
||||
getService() {
|
||||
return this;
|
||||
},
|
||||
},
|
||||
"@mozilla.org/network/stream-loader;1": {
|
||||
createInstance() {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
},
|
||||
Ci: {
|
||||
nsICryptoHash: {},
|
||||
nsIReferrerInfo: { UNSAFE_URL: 5 },
|
||||
nsITimer: { TYPE_ONE_SHOT: 1 },
|
||||
nsIWebProgressListener: { LOCATION_CHANGE_SAME_DOCUMENT: 1 },
|
||||
nsIDOMWindow: Object,
|
||||
nsITrackingDBService: {
|
||||
TRACKERS_ID: 1,
|
||||
TRACKING_COOKIES_ID: 2,
|
||||
CRYPTOMINERS_ID: 3,
|
||||
FINGERPRINTERS_ID: 4,
|
||||
SOCIAL_ID: 5,
|
||||
},
|
||||
nsICookieBannerService: {
|
||||
MODE_DISABLED: 0,
|
||||
MODE_REJECT: 1,
|
||||
MODE_REJECT_OR_ACCEPT: 2,
|
||||
MODE_UNSET: 3,
|
||||
},
|
||||
},
|
||||
Cu: {
|
||||
importGlobalProperties() {},
|
||||
now: () => window.performance.now(),
|
||||
cloneInto: o => JSON.parse(JSON.stringify(o)),
|
||||
},
|
||||
console: {
|
||||
...console,
|
||||
error() {},
|
||||
},
|
||||
dump() {},
|
||||
EveryWindow: {
|
||||
registerCallback: (id, init, uninit) => {},
|
||||
unregisterCallback: id => {},
|
||||
},
|
||||
setTimeout: window.setTimeout.bind(window),
|
||||
clearTimeout: window.clearTimeout.bind(window),
|
||||
fetch() {},
|
||||
// eslint-disable-next-line object-shorthand
|
||||
Image: function () {}, // NB: This is a function/constructor
|
||||
IOUtils: {
|
||||
writeJSON() {
|
||||
return Promise.resolve(0);
|
||||
},
|
||||
readJSON() {
|
||||
return Promise.resolve({});
|
||||
},
|
||||
read() {
|
||||
return Promise.resolve(new Uint8Array());
|
||||
},
|
||||
makeDirectory() {
|
||||
return Promise.resolve(0);
|
||||
},
|
||||
write() {
|
||||
return Promise.resolve(0);
|
||||
},
|
||||
exists() {
|
||||
return Promise.resolve(0);
|
||||
},
|
||||
remove() {
|
||||
return Promise.resolve(0);
|
||||
},
|
||||
stat() {
|
||||
return Promise.resolve(0);
|
||||
},
|
||||
},
|
||||
NewTabUtils: {
|
||||
activityStreamProvider: {
|
||||
getTopFrecentSites: () => [],
|
||||
executePlacesQuery: async (sql, options) => ({ sql, options }),
|
||||
},
|
||||
},
|
||||
OS: {
|
||||
File: {
|
||||
writeAtomic() {},
|
||||
makeDir() {},
|
||||
stat() {},
|
||||
Error: {},
|
||||
read() {},
|
||||
exists() {},
|
||||
remove() {},
|
||||
removeEmptyDir() {},
|
||||
},
|
||||
Path: {
|
||||
join() {
|
||||
return "/";
|
||||
},
|
||||
},
|
||||
Constants: {
|
||||
Path: {
|
||||
localProfileDir: "/",
|
||||
},
|
||||
},
|
||||
},
|
||||
PathUtils: {
|
||||
join(...parts) {
|
||||
return parts[parts.length - 1];
|
||||
},
|
||||
joinRelative(...parts) {
|
||||
return parts[parts.length - 1];
|
||||
},
|
||||
getProfileDir() {
|
||||
return Promise.resolve("/");
|
||||
},
|
||||
getLocalProfileDir() {
|
||||
return Promise.resolve("/");
|
||||
},
|
||||
},
|
||||
PlacesUtils: {
|
||||
get bookmarks() {
|
||||
return TEST_GLOBAL.Cc["@mozilla.org/browser/nav-bookmarks-service;1"];
|
||||
},
|
||||
get history() {
|
||||
return TEST_GLOBAL.Cc["@mozilla.org/browser/nav-history-service;1"];
|
||||
},
|
||||
observers: {
|
||||
addListener() {},
|
||||
removeListener() {},
|
||||
},
|
||||
},
|
||||
Preferences: FakePrefs,
|
||||
PrivateBrowsingUtils: {
|
||||
isBrowserPrivate: () => false,
|
||||
isWindowPrivate: () => false,
|
||||
permanentPrivateBrowsing: false,
|
||||
},
|
||||
DownloadsViewUI: {
|
||||
getDisplayName: () => "filename.ext",
|
||||
getSizeWithUnits: () => "1.5 MB",
|
||||
},
|
||||
FileUtils: {
|
||||
// eslint-disable-next-line object-shorthand
|
||||
File: function () {}, // NB: This is a function/constructor
|
||||
},
|
||||
Region: {
|
||||
home: "US",
|
||||
REGION_TOPIC: "browser-region-updated",
|
||||
},
|
||||
Services: {
|
||||
dirsvc: {
|
||||
get: () => ({ parent: { parent: { path: "appPath" } } }),
|
||||
},
|
||||
env: {
|
||||
set: () => undefined,
|
||||
},
|
||||
locale: {
|
||||
get appLocaleAsBCP47() {
|
||||
return "en-US";
|
||||
},
|
||||
negotiateLanguages() {},
|
||||
},
|
||||
urlFormatter: { formatURL: str => str, formatURLPref: str => str },
|
||||
mm: {
|
||||
addMessageListener: (msg, cb) => this.receiveMessage(),
|
||||
removeMessageListener() {},
|
||||
},
|
||||
obs: {
|
||||
addObserver() {},
|
||||
removeObserver() {},
|
||||
notifyObservers() {},
|
||||
},
|
||||
telemetry: {
|
||||
setEventRecordingEnabled: () => {},
|
||||
recordEvent: eventDetails => {},
|
||||
scalarSet: () => {},
|
||||
keyedScalarAdd: () => {},
|
||||
},
|
||||
uuid: {
|
||||
generateUUID() {
|
||||
return "{foo-123-foo}";
|
||||
},
|
||||
},
|
||||
console: { logStringMessage: () => {} },
|
||||
prefs: new FakensIPrefService(),
|
||||
tm: {
|
||||
dispatchToMainThread: cb => cb(),
|
||||
idleDispatchToMainThread: cb => cb(),
|
||||
},
|
||||
eTLD: {
|
||||
getBaseDomain({ spec }) {
|
||||
return spec.match(/\/([^/]+)/)[1];
|
||||
},
|
||||
getBaseDomainFromHost(host) {
|
||||
return host.match(/.*?(\w+\.\w+)$/)[1];
|
||||
},
|
||||
getPublicSuffix() {},
|
||||
},
|
||||
io: {
|
||||
newURI: spec => ({
|
||||
mutate: () => ({
|
||||
setRef: ref => ({
|
||||
finalize: () => ({
|
||||
ref,
|
||||
spec,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
spec,
|
||||
}),
|
||||
},
|
||||
search: {
|
||||
init() {
|
||||
return Promise.resolve();
|
||||
},
|
||||
getVisibleEngines: () =>
|
||||
Promise.resolve([{ identifier: "google" }, { identifier: "bing" }]),
|
||||
defaultEngine: {
|
||||
identifier: "google",
|
||||
searchForm:
|
||||
"https://www.google.com/search?q=&ie=utf-8&oe=utf-8&client=firefox-b",
|
||||
aliases: ["@google"],
|
||||
},
|
||||
defaultPrivateEngine: {
|
||||
identifier: "bing",
|
||||
searchForm: "https://www.bing.com",
|
||||
aliases: ["@bing"],
|
||||
},
|
||||
getEngineByAlias: async () => null,
|
||||
},
|
||||
scriptSecurityManager: {
|
||||
createNullPrincipal() {},
|
||||
getSystemPrincipal() {},
|
||||
},
|
||||
wm: {
|
||||
getMostRecentWindow: () => window,
|
||||
getMostRecentBrowserWindow: () => window,
|
||||
getEnumerator: () => [],
|
||||
},
|
||||
ww: { registerNotification() {}, unregisterNotification() {} },
|
||||
appinfo: { appBuildID: "20180710100040", version: "69.0a1" },
|
||||
scriptloader: { loadSubScript: () => {} },
|
||||
startup: {
|
||||
getStartupInfo() {
|
||||
return {
|
||||
process: {
|
||||
getTime() {
|
||||
return 1588010448000;
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
XPCOMUtils: {
|
||||
defineLazyGetter(object, name, f) {
|
||||
updateGlobalOrObject(object)[name] = f();
|
||||
},
|
||||
defineLazyGlobalGetters: updateGlobalOrObject,
|
||||
defineLazyModuleGetters: updateGlobalOrObject,
|
||||
defineLazyServiceGetter: updateGlobalOrObject,
|
||||
defineLazyServiceGetters: updateGlobalOrObject,
|
||||
defineLazyPreferenceGetter(object, name) {
|
||||
updateGlobalOrObject(object)[name] = "";
|
||||
},
|
||||
generateQI() {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
EventEmitter,
|
||||
ShellService: {
|
||||
doesAppNeedPin: () => false,
|
||||
isDefaultBrowser: () => true,
|
||||
},
|
||||
FilterExpressions: {
|
||||
eval() {
|
||||
return Promise.resolve(false);
|
||||
},
|
||||
},
|
||||
RemoteSettings,
|
||||
Localization: class {
|
||||
async formatMessages(stringsIds) {
|
||||
return Promise.resolve(
|
||||
stringsIds.map(({ id, args }) => ({ value: { string_id: id, args } }))
|
||||
);
|
||||
}
|
||||
async formatValue(stringId) {
|
||||
return Promise.resolve(stringId);
|
||||
}
|
||||
},
|
||||
FxAccountsConfig: {
|
||||
promiseConnectAccountURI(id) {
|
||||
return Promise.resolve(id);
|
||||
},
|
||||
},
|
||||
FX_MONITOR_OAUTH_CLIENT_ID: "fake_client_id",
|
||||
ExperimentAPI: {
|
||||
getExperiment() {},
|
||||
getExperimentMetaData() {},
|
||||
getRolloutMetaData() {},
|
||||
},
|
||||
NimbusFeatures: {
|
||||
glean: {
|
||||
getVariable() {},
|
||||
},
|
||||
newtab: {
|
||||
getVariable() {},
|
||||
getAllVariables() {},
|
||||
onUpdate() {},
|
||||
offUpdate() {},
|
||||
},
|
||||
pocketNewtab: {
|
||||
getVariable() {},
|
||||
getAllVariables() {},
|
||||
onUpdate() {},
|
||||
offUpdate() {},
|
||||
},
|
||||
cookieBannerHandling: {
|
||||
getVariable() {},
|
||||
},
|
||||
},
|
||||
TelemetryEnvironment: {
|
||||
setExperimentActive() {},
|
||||
currentEnvironment: {
|
||||
profile: {
|
||||
creationDate: 16587,
|
||||
},
|
||||
settings: {},
|
||||
},
|
||||
},
|
||||
TelemetryStopwatch: {
|
||||
start: () => {},
|
||||
finish: () => {},
|
||||
},
|
||||
Sampling: {
|
||||
ratioSample(seed, ratios) {
|
||||
return Promise.resolve(0);
|
||||
},
|
||||
},
|
||||
BrowserHandler: {
|
||||
get kiosk() {
|
||||
return false;
|
||||
},
|
||||
},
|
||||
TelemetrySession: {
|
||||
getMetadata(reason) {
|
||||
return {
|
||||
reason,
|
||||
sessionId: "fake_session_id",
|
||||
};
|
||||
},
|
||||
},
|
||||
PageThumbs: {
|
||||
addExpirationFilter() {},
|
||||
removeExpirationFilter() {},
|
||||
},
|
||||
Logger: FakeLogger,
|
||||
getFxAccountsSingleton() {},
|
||||
AboutNewTab: {},
|
||||
Glean: {
|
||||
newtab: {
|
||||
opened: {
|
||||
record() {},
|
||||
},
|
||||
closed: {
|
||||
record() {},
|
||||
},
|
||||
locale: {
|
||||
set() {},
|
||||
},
|
||||
newtabCategory: {
|
||||
set() {},
|
||||
},
|
||||
homepageCategory: {
|
||||
set() {},
|
||||
},
|
||||
blockedSponsors: {
|
||||
set() {},
|
||||
},
|
||||
sovAllocation: {
|
||||
set() {},
|
||||
},
|
||||
},
|
||||
newtabSearch: {
|
||||
enabled: {
|
||||
set() {},
|
||||
},
|
||||
},
|
||||
pocket: {
|
||||
enabled: {
|
||||
set() {},
|
||||
},
|
||||
impression: {
|
||||
record() {},
|
||||
},
|
||||
isSignedIn: {
|
||||
set() {},
|
||||
},
|
||||
sponsoredStoriesEnabled: {
|
||||
set() {},
|
||||
},
|
||||
click: {
|
||||
record() {},
|
||||
},
|
||||
save: {
|
||||
record() {},
|
||||
},
|
||||
topicClick: {
|
||||
record() {},
|
||||
},
|
||||
},
|
||||
topsites: {
|
||||
enabled: {
|
||||
set() {},
|
||||
},
|
||||
sponsoredEnabled: {
|
||||
set() {},
|
||||
},
|
||||
impression: {
|
||||
record() {},
|
||||
},
|
||||
click: {
|
||||
record() {},
|
||||
},
|
||||
rows: {
|
||||
set() {},
|
||||
},
|
||||
showPrivacyClick: {
|
||||
record() {},
|
||||
},
|
||||
dismiss: {
|
||||
record() {},
|
||||
},
|
||||
prefChanged: {
|
||||
record() {},
|
||||
},
|
||||
},
|
||||
topSites: {
|
||||
pingType: {
|
||||
set() {},
|
||||
},
|
||||
position: {
|
||||
set() {},
|
||||
},
|
||||
source: {
|
||||
set() {},
|
||||
},
|
||||
tileId: {
|
||||
set() {},
|
||||
},
|
||||
reportingUrl: {
|
||||
set() {},
|
||||
},
|
||||
advertiser: {
|
||||
set() {},
|
||||
},
|
||||
contextId: {
|
||||
set() {},
|
||||
},
|
||||
},
|
||||
},
|
||||
GleanPings: {
|
||||
newtab: {
|
||||
submit() {},
|
||||
},
|
||||
topSites: {
|
||||
submit() {},
|
||||
},
|
||||
},
|
||||
Utils: {
|
||||
SERVER_URL: "bogus://foo",
|
||||
},
|
||||
};
|
||||
overrider.set(TEST_GLOBAL);
|
||||
|
||||
describe("asrouter", () => {
|
||||
after(() => overrider.restore());
|
||||
files.forEach(file => req(file));
|
||||
});
|
|
@ -1,34 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const path = require("path");
|
||||
const config = require("../newtab/webpack.system-addon.config.js");
|
||||
const webpack = require("webpack");
|
||||
const absolute = relPath => path.join(__dirname, relPath);
|
||||
const banner = `
|
||||
NOTE: This file is generated by webpack from ASRouterAdmin.jsx
|
||||
using the npm bundle task.
|
||||
`;
|
||||
module.exports = Object.assign({}, config(), {
|
||||
entry: absolute("content-src/components/ASRouterAdmin/ASRouterAdmin.jsx"),
|
||||
output: {
|
||||
path: absolute("content"),
|
||||
filename: "asrouter-admin.bundle.js",
|
||||
library: "ASRouterAdminRenderUtils",
|
||||
},
|
||||
externals: {
|
||||
"prop-types": "PropTypes",
|
||||
react: "React",
|
||||
"react-dom": "ReactDOM",
|
||||
},
|
||||
plugins: [new webpack.BannerPlugin(banner)],
|
||||
// This resolve config allows us to import with paths relative to the root directory, e.g. "lib/ActivityStream.jsm"
|
||||
resolve: {
|
||||
extensions: [".js", ".jsx"],
|
||||
alias: {
|
||||
newtab: absolute("../newtab"),
|
||||
common: absolute("../newtab/common"),
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,44 +0,0 @@
|
|||
# This file compiles to package.json scripts.
|
||||
# When you add or modify anything, you *MUST* run:
|
||||
# npm run yamscripts
|
||||
# to compile your changes.
|
||||
|
||||
scripts:
|
||||
# bundle: Build all assets for ASRouter
|
||||
bundle:
|
||||
admin: webpack-cli --config webpack.asrouter-admin.config.js
|
||||
css: sass content-src:content --no-source-map
|
||||
|
||||
# watchmc: Automatically rebuild when files are changed. NOTE: Includes sourcemaps, do not use for profiling/perf testing.
|
||||
watchmc:
|
||||
_parallel: true
|
||||
bundle: =>bundle:admin -- --env development -w
|
||||
css: =>bundle:css -- --source-map --embed-sources --embed-source-map -w
|
||||
|
||||
testmc:
|
||||
lint: =>lint
|
||||
build: =>bundle:admin
|
||||
unit: karma start karma.mc.config.js
|
||||
|
||||
tddmc: karma start karma.mc.config.js --tdd
|
||||
|
||||
debugcoverage: open logs/coverage/lcov-report/index.html
|
||||
|
||||
# lint: Run various linters with mach or local dev dependencies
|
||||
lint:
|
||||
codespell: (cd $npm_package_config_mc_root && ./mach lint -l codespell $npm_package_config_asrouter_path)
|
||||
eslint: (cd $npm_package_config_mc_root && ./mach lint -l eslint $npm_package_config_asrouter_path)
|
||||
license: (cd $npm_package_config_mc_root && ./mach lint -l license $npm_package_config_asrouter_path)
|
||||
stylelint: (cd $npm_package_config_mc_root && ./mach lint -l stylelint $npm_package_config_asrouter_path)
|
||||
|
||||
# test: Run all tests once
|
||||
test: =>testmc
|
||||
|
||||
# tdd: Run content tests continuously
|
||||
tdd: =>tddmc
|
||||
|
||||
fix:
|
||||
# Note that since we're currently running eslint-plugin-prettier,
|
||||
# running fix:eslint will also reformat changed JS files using prettier.
|
||||
eslint: =>lint:eslint -- --fix
|
||||
stylelint: =>lint:stylelint -- --fix
|
|
@ -30,7 +30,6 @@ DIRS += [
|
|||
"about",
|
||||
"aboutlogins",
|
||||
"aboutwelcome",
|
||||
"asrouter",
|
||||
"attribution",
|
||||
"contentanalysis",
|
||||
"contextualidentity",
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## How to enable ASRouter devtools
|
||||
- In `about:config`, set `browser.newtabpage.activity-stream.asrouter.devtoolsEnabled` to `true`
|
||||
- Visit `about:asrouter` to see the devtools.
|
||||
- Visit `about:newtab#asrouter` to see the devtools.
|
||||
|
||||
## Overview of ASRouter devtools
|
||||
|
||||
|
|
|
@ -2,9 +2,13 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import { ASRouterUtils } from "newtab/content-src/asrouter/asrouter-utils";
|
||||
import {
|
||||
actionCreators as ac,
|
||||
actionTypes as at,
|
||||
} from "common/Actions.sys.mjs";
|
||||
import { ASRouterUtils } from "../../asrouter/asrouter-utils";
|
||||
import { connect } from "react-redux";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { SimpleHashRouter } from "./SimpleHashRouter";
|
||||
import { CopyButton } from "./CopyButton";
|
||||
import { ImpressionsSection } from "./ImpressionsSection";
|
||||
|
@ -95,6 +99,316 @@ export class TogglePrefCheckbox extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
export class Personalization extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.togglePersonalization = this.togglePersonalization.bind(this);
|
||||
}
|
||||
|
||||
togglePersonalization() {
|
||||
this.props.dispatch(
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_PERSONALIZATION_TOGGLE,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { lastUpdated, initialized } = this.props.state.Personalization;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<table>
|
||||
<tbody>
|
||||
<Row>
|
||||
<td colSpan="2">
|
||||
<TogglePrefCheckbox
|
||||
checked={this.props.personalized}
|
||||
pref="personalized"
|
||||
onChange={this.togglePersonalization}
|
||||
/>
|
||||
</td>
|
||||
</Row>
|
||||
<Row>
|
||||
<td className="min">Personalization Last Updated</td>
|
||||
<td>{relativeTime(lastUpdated) || "(no data)"}</td>
|
||||
</Row>
|
||||
<Row>
|
||||
<td className="min">Personalization Initialized</td>
|
||||
<td>{initialized ? "true" : "false"}</td>
|
||||
</Row>
|
||||
</tbody>
|
||||
</table>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class DiscoveryStreamAdmin extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.restorePrefDefaults = this.restorePrefDefaults.bind(this);
|
||||
this.setConfigValue = this.setConfigValue.bind(this);
|
||||
this.expireCache = this.expireCache.bind(this);
|
||||
this.refreshCache = this.refreshCache.bind(this);
|
||||
this.idleDaily = this.idleDaily.bind(this);
|
||||
this.systemTick = this.systemTick.bind(this);
|
||||
this.syncRemoteSettings = this.syncRemoteSettings.bind(this);
|
||||
this.onStoryToggle = this.onStoryToggle.bind(this);
|
||||
this.state = {
|
||||
toggledStories: {},
|
||||
};
|
||||
}
|
||||
|
||||
setConfigValue(name, value) {
|
||||
this.props.dispatch(
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_CONFIG_SET_VALUE,
|
||||
data: { name, value },
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
restorePrefDefaults(event) {
|
||||
this.props.dispatch(
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
refreshCache() {
|
||||
const { config } = this.props.state.DiscoveryStream;
|
||||
this.props.dispatch(
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_CONFIG_CHANGE,
|
||||
data: config,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
dispatchSimpleAction(type) {
|
||||
this.props.dispatch(
|
||||
ac.OnlyToMain({
|
||||
type,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
systemTick() {
|
||||
this.dispatchSimpleAction(at.DISCOVERY_STREAM_DEV_SYSTEM_TICK);
|
||||
}
|
||||
|
||||
expireCache() {
|
||||
this.dispatchSimpleAction(at.DISCOVERY_STREAM_DEV_EXPIRE_CACHE);
|
||||
}
|
||||
|
||||
idleDaily() {
|
||||
this.dispatchSimpleAction(at.DISCOVERY_STREAM_DEV_IDLE_DAILY);
|
||||
}
|
||||
|
||||
syncRemoteSettings() {
|
||||
this.dispatchSimpleAction(at.DISCOVERY_STREAM_DEV_SYNC_RS);
|
||||
}
|
||||
|
||||
renderComponent(width, component) {
|
||||
return (
|
||||
<table>
|
||||
<tbody>
|
||||
<Row>
|
||||
<td className="min">Type</td>
|
||||
<td>{component.type}</td>
|
||||
</Row>
|
||||
<Row>
|
||||
<td className="min">Width</td>
|
||||
<td>{width}</td>
|
||||
</Row>
|
||||
{component.feed && this.renderFeed(component.feed)}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
|
||||
renderFeedData(url) {
|
||||
const { feeds } = this.props.state.DiscoveryStream;
|
||||
const feed = feeds.data[url].data;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<h4>Feed url: {url}</h4>
|
||||
<table>
|
||||
<tbody>
|
||||
{feed.recommendations?.map(story => this.renderStoryData(story))}
|
||||
</tbody>
|
||||
</table>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
renderFeedsData() {
|
||||
const { feeds } = this.props.state.DiscoveryStream;
|
||||
return (
|
||||
<React.Fragment>
|
||||
{Object.keys(feeds.data).map(url => this.renderFeedData(url))}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
renderSpocs() {
|
||||
const { spocs } = this.props.state.DiscoveryStream;
|
||||
let spocsData = [];
|
||||
if (spocs.data && spocs.data.spocs && spocs.data.spocs.items) {
|
||||
spocsData = spocs.data.spocs.items || [];
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<table>
|
||||
<tbody>
|
||||
<Row>
|
||||
<td className="min">spocs_endpoint</td>
|
||||
<td>{spocs.spocs_endpoint}</td>
|
||||
</Row>
|
||||
<Row>
|
||||
<td className="min">Data last fetched</td>
|
||||
<td>{relativeTime(spocs.lastUpdated)}</td>
|
||||
</Row>
|
||||
</tbody>
|
||||
</table>
|
||||
<h4>Spoc data</h4>
|
||||
<table>
|
||||
<tbody>{spocsData.map(spoc => this.renderStoryData(spoc))}</tbody>
|
||||
</table>
|
||||
<h4>Spoc frequency caps</h4>
|
||||
<table>
|
||||
<tbody>
|
||||
{spocs.frequency_caps.map(spoc => this.renderStoryData(spoc))}
|
||||
</tbody>
|
||||
</table>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
onStoryToggle(story) {
|
||||
const { toggledStories } = this.state;
|
||||
this.setState({
|
||||
toggledStories: {
|
||||
...toggledStories,
|
||||
[story.id]: !toggledStories[story.id],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
renderStoryData(story) {
|
||||
let storyData = "";
|
||||
if (this.state.toggledStories[story.id]) {
|
||||
storyData = JSON.stringify(story, null, 2);
|
||||
}
|
||||
return (
|
||||
<tr className="message-item" key={story.id}>
|
||||
<td className="message-id">
|
||||
<span>
|
||||
{story.id} <br />
|
||||
</span>
|
||||
<ToggleStoryButton story={story} onClick={this.onStoryToggle} />
|
||||
</td>
|
||||
<td className="message-summary">
|
||||
<pre>{storyData}</pre>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
renderFeed(feed) {
|
||||
const { feeds } = this.props.state.DiscoveryStream;
|
||||
if (!feed.url) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Row>
|
||||
<td className="min">Feed url</td>
|
||||
<td>{feed.url}</td>
|
||||
</Row>
|
||||
<Row>
|
||||
<td className="min">Data last fetched</td>
|
||||
<td>
|
||||
{relativeTime(
|
||||
feeds.data[feed.url] ? feeds.data[feed.url].lastUpdated : null
|
||||
) || "(no data)"}
|
||||
</td>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const prefToggles = "enabled collapsible".split(" ");
|
||||
const { config, layout } = this.props.state.DiscoveryStream;
|
||||
const personalized =
|
||||
this.props.otherPrefs["discoverystream.personalization.enabled"];
|
||||
return (
|
||||
<div>
|
||||
<button className="button" onClick={this.restorePrefDefaults}>
|
||||
Restore Pref Defaults
|
||||
</button>{" "}
|
||||
<button className="button" onClick={this.refreshCache}>
|
||||
Refresh Cache
|
||||
</button>
|
||||
<br />
|
||||
<button className="button" onClick={this.expireCache}>
|
||||
Expire Cache
|
||||
</button>{" "}
|
||||
<button className="button" onClick={this.systemTick}>
|
||||
Trigger System Tick
|
||||
</button>{" "}
|
||||
<button className="button" onClick={this.idleDaily}>
|
||||
Trigger Idle Daily
|
||||
</button>
|
||||
<br />
|
||||
<button className="button" onClick={this.syncRemoteSettings}>
|
||||
Sync Remote Settings
|
||||
</button>
|
||||
<table>
|
||||
<tbody>
|
||||
{prefToggles.map(pref => (
|
||||
<Row key={pref}>
|
||||
<td>
|
||||
<TogglePrefCheckbox
|
||||
checked={config[pref]}
|
||||
pref={pref}
|
||||
onChange={this.setConfigValue}
|
||||
/>
|
||||
</td>
|
||||
</Row>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Layout</h3>
|
||||
{layout.map((row, rowIndex) => (
|
||||
<div key={`row-${rowIndex}`}>
|
||||
{row.components.map((component, componentIndex) => (
|
||||
<div key={`component-${componentIndex}`} className="ds-component">
|
||||
{this.renderComponent(row.width, component)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
<h3>Personalization</h3>
|
||||
<Personalization
|
||||
personalized={personalized}
|
||||
dispatch={this.props.dispatch}
|
||||
state={{
|
||||
Personalization: this.props.state.Personalization,
|
||||
}}
|
||||
/>
|
||||
<h3>Spocs</h3>
|
||||
{this.renderSpocs()}
|
||||
<h3>Feeds Data</h3>
|
||||
{this.renderFeedsData()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class ASRouterAdminInner extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
@ -181,10 +495,6 @@ export class ASRouterAdminInner extends React.PureComponent {
|
|||
}).then(this.setStateFromParent);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
ASRouterUtils.removeListener(this.onMessageFromParent);
|
||||
}
|
||||
|
||||
handleBlock(msg) {
|
||||
return () => ASRouterUtils.blockById(msg.id);
|
||||
}
|
||||
|
@ -214,6 +524,9 @@ export class ASRouterAdminInner extends React.PureComponent {
|
|||
return () =>
|
||||
ASRouterUtils.overrideMessage(id).then(state => {
|
||||
this.setStateFromParent(state);
|
||||
this.props.notifyContent({
|
||||
message: state.message,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -598,6 +911,9 @@ export class ASRouterAdminInner extends React.PureComponent {
|
|||
);
|
||||
return ASRouterUtils.modifyMessageJson(message).then(state => {
|
||||
this.setStateFromParent(state);
|
||||
this.props.notifyContent({
|
||||
message: state.message,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1399,6 +1715,20 @@ export class ASRouterAdminInner extends React.PureComponent {
|
|||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
case "ds":
|
||||
return (
|
||||
<React.Fragment>
|
||||
<h2>Discovery Stream</h2>
|
||||
<DiscoveryStreamAdmin
|
||||
state={{
|
||||
DiscoveryStream: this.props.DiscoveryStream,
|
||||
Personalization: this.props.Personalization,
|
||||
}}
|
||||
otherPrefs={this.props.Prefs.values}
|
||||
dispatch={this.props.dispatch}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
case "errors":
|
||||
return (
|
||||
<React.Fragment>
|
||||
|
@ -1429,18 +1759,6 @@ export class ASRouterAdminInner extends React.PureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
if (!this.state.devtoolsEnabled) {
|
||||
return (
|
||||
<div className="asrouter-admin">
|
||||
You must enable the ASRouter Admin page by setting{" "}
|
||||
<code>
|
||||
browser.newtabpage.activity-stream.asrouter.devtoolsEnabled
|
||||
</code>{" "}
|
||||
to <code>true</code> and then reloading this page.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`asrouter-admin ${
|
||||
|
@ -1464,6 +1782,9 @@ export class ASRouterAdminInner extends React.PureComponent {
|
|||
<li>
|
||||
<a href="#devtools-impressions">Impressions</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#devtools-ds">Discovery Stream</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#devtools-errors">Errors</a>
|
||||
</li>
|
||||
|
@ -1492,12 +1813,83 @@ export class ASRouterAdminInner extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
export const ASRouterAdmin = props => (
|
||||
export class CollapseToggle extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onCollapseToggle = this.onCollapseToggle.bind(this);
|
||||
this.state = { collapsed: false };
|
||||
}
|
||||
|
||||
get renderAdmin() {
|
||||
const { props } = this;
|
||||
return (
|
||||
props.location.hash &&
|
||||
(props.location.hash.startsWith("#asrouter") ||
|
||||
props.location.hash.startsWith("#devtools"))
|
||||
);
|
||||
}
|
||||
|
||||
onCollapseToggle(e) {
|
||||
e.preventDefault();
|
||||
this.setState(state => ({ collapsed: !state.collapsed }));
|
||||
}
|
||||
|
||||
setBodyClass() {
|
||||
if (this.renderAdmin && !this.state.collapsed) {
|
||||
global.document.body.classList.add("no-scroll");
|
||||
} else {
|
||||
global.document.body.classList.remove("no-scroll");
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setBodyClass();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.setBodyClass();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
global.document.body.classList.remove("no-scroll");
|
||||
ASRouterUtils.removeListener(this.onMessageFromParent);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { props } = this;
|
||||
const { renderAdmin } = this;
|
||||
const isCollapsed = this.state.collapsed || !renderAdmin;
|
||||
const label = `${isCollapsed ? "Expand" : "Collapse"} devtools`;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<a
|
||||
href="#devtools"
|
||||
title={label}
|
||||
aria-label={label}
|
||||
className={`asrouter-toggle ${
|
||||
isCollapsed ? "collapsed" : "expanded"
|
||||
}`}
|
||||
onClick={this.renderAdmin ? this.onCollapseToggle : null}
|
||||
>
|
||||
<span className="icon icon-devtools" />
|
||||
</a>
|
||||
{renderAdmin ? (
|
||||
<ASRouterAdminInner {...props} collapsed={this.state.collapsed} />
|
||||
) : null}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const _ASRouterAdmin = props => (
|
||||
<SimpleHashRouter>
|
||||
<ASRouterAdminInner {...props} />
|
||||
<CollapseToggle {...props} />
|
||||
</SimpleHashRouter>
|
||||
);
|
||||
|
||||
export function renderASRouterAdmin() {
|
||||
ReactDOM.render(<ASRouterAdmin />, document.getElementById("root"));
|
||||
}
|
||||
export const ASRouterAdmin = connect(state => ({
|
||||
Sections: state.Sections,
|
||||
DiscoveryStream: state.DiscoveryStream,
|
||||
Personalization: state.Personalization,
|
||||
Prefs: state.Prefs,
|
||||
}))(_ASRouterAdmin);
|
|
@ -1,64 +1,46 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* stylelint-disable max-nesting-depth */
|
||||
|
||||
@import '../../../../newtab/content-src/styles/variables';
|
||||
@import '../../../../newtab/content-src/styles/theme';
|
||||
@import '../../../../newtab/content-src/styles/icons';
|
||||
@import '../../../../newtab/content-src/asrouter/components/Button/Button';
|
||||
.asrouter-toggle {
|
||||
position: fixed;
|
||||
top: 50px;
|
||||
inset-inline-end: 15px;
|
||||
border: 0;
|
||||
background: none;
|
||||
z-index: 1;
|
||||
border-radius: 2px;
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif;
|
||||
}
|
||||
|
||||
/**
|
||||
* These styles are copied verbatim from _activity-stream.scss in order to maintain
|
||||
* a continuity of styling while also decoupling from the newtab code. This should
|
||||
* be removed when about:asrouter starts using the default in-content style sheets.
|
||||
*/
|
||||
.button,
|
||||
.actions button {
|
||||
background-color: var(--newtab-button-secondary-color);
|
||||
border: $border-primary;
|
||||
border-radius: 4px;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
margin-bottom: 15px;
|
||||
padding: 10px 30px;
|
||||
white-space: nowrap;
|
||||
|
||||
&:hover:not(.dismiss),
|
||||
&:focus:not(.dismiss) {
|
||||
box-shadow: $shadow-primary;
|
||||
transition: box-shadow 150ms;
|
||||
.icon-devtools {
|
||||
background-image: url('chrome://global/skin/icons/developer.svg');
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
&.dismiss {
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
text-decoration: underline;
|
||||
&:dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
// Blue button
|
||||
&.primary,
|
||||
&.done {
|
||||
background-color: var(--newtab-primary-action-background);
|
||||
border: solid 1px var(--newtab-primary-action-background);
|
||||
color: var(--newtab-primary-element-text-color);
|
||||
margin-inline-start: auto;
|
||||
&:hover {
|
||||
background: var(--newtab-element-hover-color);
|
||||
}
|
||||
|
||||
&.expanded {
|
||||
background: $black-20;
|
||||
}
|
||||
}
|
||||
|
||||
.asrouter-admin {
|
||||
max-width: 1300px;
|
||||
$border-color: var(--newtab-border-color);
|
||||
$monospace: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Mono', 'Droid Sans Mono',
|
||||
'Source Code Pro', monospace;
|
||||
$sidebar-width: 240px;
|
||||
|
||||
position: fixed;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
width: 100%;
|
||||
background: var(--newtab-background-color);
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
margin: 0 auto;
|
||||
font-size: 14px;
|
||||
padding-inline-start: $sidebar-width;
|
||||
color: var(--newtab-text-primary-color);
|
||||
|
@ -71,6 +53,7 @@ body {
|
|||
inset-inline-start: 0;
|
||||
position: fixed;
|
||||
width: $sidebar-width;
|
||||
padding: 30px 20px;
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
|
@ -137,6 +120,7 @@ body {
|
|||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
|
||||
&.minimal-table {
|
||||
border-collapse: collapse;
|
|
@ -2,7 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import { ASRouterUtils } from "newtab/content-src/asrouter/asrouter-utils";
|
||||
import { ASRouterUtils } from "../../asrouter/asrouter-utils";
|
||||
import React, {
|
||||
useState,
|
||||
useMemo,
|
|
@ -6,7 +6,7 @@ import {
|
|||
actionCreators as ac,
|
||||
actionTypes as at,
|
||||
} from "common/Actions.sys.mjs";
|
||||
import { DiscoveryStreamAdmin } from "content-src/components/DiscoveryStreamAdmin/DiscoveryStreamAdmin";
|
||||
import { ASRouterAdmin } from "content-src/components/ASRouterAdmin/ASRouterAdmin";
|
||||
import { ConfirmDialog } from "content-src/components/ConfirmDialog/ConfirmDialog";
|
||||
import { connect } from "react-redux";
|
||||
import { DiscoveryStreamBase } from "content-src/components/DiscoveryStreamBase/DiscoveryStreamBase";
|
||||
|
@ -93,7 +93,7 @@ export class _Base extends React.PureComponent {
|
|||
<React.Fragment>
|
||||
<BaseContent {...this.props} adminContent={this.state} />
|
||||
{isDevtoolsEnabled ? (
|
||||
<DiscoveryStreamAdmin notifyContent={this.notifyContent} />
|
||||
<ASRouterAdmin notifyContent={this.notifyContent} />
|
||||
) : null}
|
||||
</React.Fragment>
|
||||
</ErrorBoundary>
|
||||
|
|
|
@ -1,506 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import {
|
||||
actionCreators as ac,
|
||||
actionTypes as at,
|
||||
} from "common/Actions.sys.mjs";
|
||||
import { connect } from "react-redux";
|
||||
import React from "react";
|
||||
import { SimpleHashRouter } from "./SimpleHashRouter";
|
||||
|
||||
const Row = props => (
|
||||
<tr className="message-item" {...props}>
|
||||
{props.children}
|
||||
</tr>
|
||||
);
|
||||
|
||||
function relativeTime(timestamp) {
|
||||
if (!timestamp) {
|
||||
return "";
|
||||
}
|
||||
const seconds = Math.floor((Date.now() - timestamp) / 1000);
|
||||
const minutes = Math.floor((Date.now() - timestamp) / 60000);
|
||||
if (seconds < 2) {
|
||||
return "just now";
|
||||
} else if (seconds < 60) {
|
||||
return `${seconds} seconds ago`;
|
||||
} else if (minutes === 1) {
|
||||
return "1 minute ago";
|
||||
} else if (minutes < 600) {
|
||||
return `${minutes} minutes ago`;
|
||||
}
|
||||
return new Date(timestamp).toLocaleString();
|
||||
}
|
||||
|
||||
export class ToggleStoryButton extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
}
|
||||
|
||||
handleClick() {
|
||||
this.props.onClick(this.props.story);
|
||||
}
|
||||
|
||||
render() {
|
||||
return <button onClick={this.handleClick}>collapse/open</button>;
|
||||
}
|
||||
}
|
||||
|
||||
export class TogglePrefCheckbox extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onChange = this.onChange.bind(this);
|
||||
}
|
||||
|
||||
onChange(event) {
|
||||
this.props.onChange(this.props.pref, event.target.checked);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={this.props.checked}
|
||||
onChange={this.onChange}
|
||||
disabled={this.props.disabled}
|
||||
/>{" "}
|
||||
{this.props.pref}{" "}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class Personalization extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.togglePersonalization = this.togglePersonalization.bind(this);
|
||||
}
|
||||
|
||||
togglePersonalization() {
|
||||
this.props.dispatch(
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_PERSONALIZATION_TOGGLE,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { lastUpdated, initialized } = this.props.state.Personalization;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<table>
|
||||
<tbody>
|
||||
<Row>
|
||||
<td colSpan="2">
|
||||
<TogglePrefCheckbox
|
||||
checked={this.props.personalized}
|
||||
pref="personalized"
|
||||
onChange={this.togglePersonalization}
|
||||
/>
|
||||
</td>
|
||||
</Row>
|
||||
<Row>
|
||||
<td className="min">Personalization Last Updated</td>
|
||||
<td>{relativeTime(lastUpdated) || "(no data)"}</td>
|
||||
</Row>
|
||||
<Row>
|
||||
<td className="min">Personalization Initialized</td>
|
||||
<td>{initialized ? "true" : "false"}</td>
|
||||
</Row>
|
||||
</tbody>
|
||||
</table>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class DiscoveryStreamAdminUI extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.restorePrefDefaults = this.restorePrefDefaults.bind(this);
|
||||
this.setConfigValue = this.setConfigValue.bind(this);
|
||||
this.expireCache = this.expireCache.bind(this);
|
||||
this.refreshCache = this.refreshCache.bind(this);
|
||||
this.idleDaily = this.idleDaily.bind(this);
|
||||
this.systemTick = this.systemTick.bind(this);
|
||||
this.syncRemoteSettings = this.syncRemoteSettings.bind(this);
|
||||
this.onStoryToggle = this.onStoryToggle.bind(this);
|
||||
this.state = {
|
||||
toggledStories: {},
|
||||
};
|
||||
}
|
||||
|
||||
setConfigValue(name, value) {
|
||||
this.props.dispatch(
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_CONFIG_SET_VALUE,
|
||||
data: { name, value },
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
restorePrefDefaults(event) {
|
||||
this.props.dispatch(
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
refreshCache() {
|
||||
const { config } = this.props.state.DiscoveryStream;
|
||||
this.props.dispatch(
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_CONFIG_CHANGE,
|
||||
data: config,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
dispatchSimpleAction(type) {
|
||||
this.props.dispatch(
|
||||
ac.OnlyToMain({
|
||||
type,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
systemTick() {
|
||||
this.dispatchSimpleAction(at.DISCOVERY_STREAM_DEV_SYSTEM_TICK);
|
||||
}
|
||||
|
||||
expireCache() {
|
||||
this.dispatchSimpleAction(at.DISCOVERY_STREAM_DEV_EXPIRE_CACHE);
|
||||
}
|
||||
|
||||
idleDaily() {
|
||||
this.dispatchSimpleAction(at.DISCOVERY_STREAM_DEV_IDLE_DAILY);
|
||||
}
|
||||
|
||||
syncRemoteSettings() {
|
||||
this.dispatchSimpleAction(at.DISCOVERY_STREAM_DEV_SYNC_RS);
|
||||
}
|
||||
|
||||
renderComponent(width, component) {
|
||||
return (
|
||||
<table>
|
||||
<tbody>
|
||||
<Row>
|
||||
<td className="min">Type</td>
|
||||
<td>{component.type}</td>
|
||||
</Row>
|
||||
<Row>
|
||||
<td className="min">Width</td>
|
||||
<td>{width}</td>
|
||||
</Row>
|
||||
{component.feed && this.renderFeed(component.feed)}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
|
||||
renderFeedData(url) {
|
||||
const { feeds } = this.props.state.DiscoveryStream;
|
||||
const feed = feeds.data[url].data;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<h4>Feed url: {url}</h4>
|
||||
<table>
|
||||
<tbody>
|
||||
{feed.recommendations?.map(story => this.renderStoryData(story))}
|
||||
</tbody>
|
||||
</table>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
renderFeedsData() {
|
||||
const { feeds } = this.props.state.DiscoveryStream;
|
||||
return (
|
||||
<React.Fragment>
|
||||
{Object.keys(feeds.data).map(url => this.renderFeedData(url))}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
renderSpocs() {
|
||||
const { spocs } = this.props.state.DiscoveryStream;
|
||||
let spocsData = [];
|
||||
if (spocs.data && spocs.data.spocs && spocs.data.spocs.items) {
|
||||
spocsData = spocs.data.spocs.items || [];
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<table>
|
||||
<tbody>
|
||||
<Row>
|
||||
<td className="min">spocs_endpoint</td>
|
||||
<td>{spocs.spocs_endpoint}</td>
|
||||
</Row>
|
||||
<Row>
|
||||
<td className="min">Data last fetched</td>
|
||||
<td>{relativeTime(spocs.lastUpdated)}</td>
|
||||
</Row>
|
||||
</tbody>
|
||||
</table>
|
||||
<h4>Spoc data</h4>
|
||||
<table>
|
||||
<tbody>{spocsData.map(spoc => this.renderStoryData(spoc))}</tbody>
|
||||
</table>
|
||||
<h4>Spoc frequency caps</h4>
|
||||
<table>
|
||||
<tbody>
|
||||
{spocs.frequency_caps.map(spoc => this.renderStoryData(spoc))}
|
||||
</tbody>
|
||||
</table>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
onStoryToggle(story) {
|
||||
const { toggledStories } = this.state;
|
||||
this.setState({
|
||||
toggledStories: {
|
||||
...toggledStories,
|
||||
[story.id]: !toggledStories[story.id],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
renderStoryData(story) {
|
||||
let storyData = "";
|
||||
if (this.state.toggledStories[story.id]) {
|
||||
storyData = JSON.stringify(story, null, 2);
|
||||
}
|
||||
return (
|
||||
<tr className="message-item" key={story.id}>
|
||||
<td className="message-id">
|
||||
<span>
|
||||
{story.id} <br />
|
||||
</span>
|
||||
<ToggleStoryButton story={story} onClick={this.onStoryToggle} />
|
||||
</td>
|
||||
<td className="message-summary">
|
||||
<pre>{storyData}</pre>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
renderFeed(feed) {
|
||||
const { feeds } = this.props.state.DiscoveryStream;
|
||||
if (!feed.url) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Row>
|
||||
<td className="min">Feed url</td>
|
||||
<td>{feed.url}</td>
|
||||
</Row>
|
||||
<Row>
|
||||
<td className="min">Data last fetched</td>
|
||||
<td>
|
||||
{relativeTime(
|
||||
feeds.data[feed.url] ? feeds.data[feed.url].lastUpdated : null
|
||||
) || "(no data)"}
|
||||
</td>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const prefToggles = "enabled collapsible".split(" ");
|
||||
const { config, layout } = this.props.state.DiscoveryStream;
|
||||
const personalized =
|
||||
this.props.otherPrefs["discoverystream.personalization.enabled"];
|
||||
return (
|
||||
<div>
|
||||
<button className="button" onClick={this.restorePrefDefaults}>
|
||||
Restore Pref Defaults
|
||||
</button>{" "}
|
||||
<button className="button" onClick={this.refreshCache}>
|
||||
Refresh Cache
|
||||
</button>
|
||||
<br />
|
||||
<button className="button" onClick={this.expireCache}>
|
||||
Expire Cache
|
||||
</button>{" "}
|
||||
<button className="button" onClick={this.systemTick}>
|
||||
Trigger System Tick
|
||||
</button>{" "}
|
||||
<button className="button" onClick={this.idleDaily}>
|
||||
Trigger Idle Daily
|
||||
</button>
|
||||
<br />
|
||||
<button className="button" onClick={this.syncRemoteSettings}>
|
||||
Sync Remote Settings
|
||||
</button>
|
||||
<table>
|
||||
<tbody>
|
||||
{prefToggles.map(pref => (
|
||||
<Row key={pref}>
|
||||
<td>
|
||||
<TogglePrefCheckbox
|
||||
checked={config[pref]}
|
||||
pref={pref}
|
||||
onChange={this.setConfigValue}
|
||||
/>
|
||||
</td>
|
||||
</Row>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Layout</h3>
|
||||
{layout.map((row, rowIndex) => (
|
||||
<div key={`row-${rowIndex}`}>
|
||||
{row.components.map((component, componentIndex) => (
|
||||
<div key={`component-${componentIndex}`} className="ds-component">
|
||||
{this.renderComponent(row.width, component)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
<h3>Personalization</h3>
|
||||
<Personalization
|
||||
personalized={personalized}
|
||||
dispatch={this.props.dispatch}
|
||||
state={{
|
||||
Personalization: this.props.state.Personalization,
|
||||
}}
|
||||
/>
|
||||
<h3>Spocs</h3>
|
||||
{this.renderSpocs()}
|
||||
<h3>Feeds Data</h3>
|
||||
{this.renderFeedsData()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class DiscoveryStreamAdminInner extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.setState = this.setState.bind(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
className={`discoverystream-admin ${
|
||||
this.props.collapsed ? "collapsed" : "expanded"
|
||||
}`}
|
||||
>
|
||||
<main className="main-panel">
|
||||
<h1>Discovery Stream Admin</h1>
|
||||
|
||||
<p className="helpLink">
|
||||
<span className="icon icon-small-spacer icon-info" />{" "}
|
||||
<span>
|
||||
Need to access the ASRouter Admin dev tools?{" "}
|
||||
<a target="blank" href="about:asrouter">
|
||||
Click here
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<React.Fragment>
|
||||
<DiscoveryStreamAdminUI
|
||||
state={{
|
||||
DiscoveryStream: this.props.DiscoveryStream,
|
||||
Personalization: this.props.Personalization,
|
||||
}}
|
||||
otherPrefs={this.props.Prefs.values}
|
||||
dispatch={this.props.dispatch}
|
||||
/>
|
||||
</React.Fragment>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class CollapseToggle extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onCollapseToggle = this.onCollapseToggle.bind(this);
|
||||
this.state = { collapsed: false };
|
||||
}
|
||||
|
||||
get renderAdmin() {
|
||||
const { props } = this;
|
||||
return props.location.hash && props.location.hash.startsWith("#devtools");
|
||||
}
|
||||
|
||||
onCollapseToggle(e) {
|
||||
e.preventDefault();
|
||||
this.setState(state => ({ collapsed: !state.collapsed }));
|
||||
}
|
||||
|
||||
setBodyClass() {
|
||||
if (this.renderAdmin && !this.state.collapsed) {
|
||||
global.document.body.classList.add("no-scroll");
|
||||
} else {
|
||||
global.document.body.classList.remove("no-scroll");
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setBodyClass();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.setBodyClass();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
global.document.body.classList.remove("no-scroll");
|
||||
}
|
||||
|
||||
render() {
|
||||
const { props } = this;
|
||||
const { renderAdmin } = this;
|
||||
const isCollapsed = this.state.collapsed || !renderAdmin;
|
||||
const label = `${isCollapsed ? "Expand" : "Collapse"} devtools`;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<a
|
||||
href="#devtools"
|
||||
title={label}
|
||||
aria-label={label}
|
||||
className={`discoverystream-admin-toggle ${
|
||||
isCollapsed ? "collapsed" : "expanded"
|
||||
}`}
|
||||
onClick={this.renderAdmin ? this.onCollapseToggle : null}
|
||||
>
|
||||
<span className="icon icon-devtools" />
|
||||
</a>
|
||||
{renderAdmin ? (
|
||||
<DiscoveryStreamAdminInner
|
||||
{...props}
|
||||
collapsed={this.state.collapsed}
|
||||
/>
|
||||
) : null}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const _DiscoveryStreamAdmin = props => (
|
||||
<SimpleHashRouter>
|
||||
<CollapseToggle {...props} />
|
||||
</SimpleHashRouter>
|
||||
);
|
||||
|
||||
export const DiscoveryStreamAdmin = connect(state => ({
|
||||
Sections: state.Sections,
|
||||
DiscoveryStream: state.DiscoveryStream,
|
||||
Personalization: state.Personalization,
|
||||
Prefs: state.Prefs,
|
||||
}))(_DiscoveryStreamAdmin);
|
|
@ -1,337 +0,0 @@
|
|||
/* stylelint-disable max-nesting-depth */
|
||||
|
||||
.discoverystream-admin-toggle {
|
||||
position: fixed;
|
||||
top: 50px;
|
||||
inset-inline-end: 15px;
|
||||
border: 0;
|
||||
background: none;
|
||||
z-index: 1;
|
||||
border-radius: 2px;
|
||||
|
||||
.icon-devtools {
|
||||
background-image: url('chrome://global/skin/icons/developer.svg');
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
&:dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--newtab-element-hover-color);
|
||||
}
|
||||
|
||||
&.expanded {
|
||||
background: $black-20;
|
||||
}
|
||||
}
|
||||
|
||||
.discoverystream-admin {
|
||||
$border-color: var(--newtab-border-color);
|
||||
$monospace: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Mono', 'Droid Sans Mono',
|
||||
'Source Code Pro', monospace;
|
||||
$sidebar-width: 240px;
|
||||
|
||||
position: fixed;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
width: 100%;
|
||||
background: var(--newtab-background-color);
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
margin: 0 auto;
|
||||
font-size: 14px;
|
||||
padding-inline-start: $sidebar-width;
|
||||
color: var(--newtab-text-primary-color);
|
||||
|
||||
&.collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
inset-inline-start: 0;
|
||||
position: fixed;
|
||||
width: $sidebar-width;
|
||||
padding: 30px 20px;
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
li a {
|
||||
padding: 10px 34px;
|
||||
display: block;
|
||||
color: var(--lwt-sidebar-text-color);
|
||||
|
||||
&:hover {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: 200;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
h2 .button,
|
||||
p .button {
|
||||
font-size: 14px;
|
||||
padding: 6px 12px;
|
||||
margin-inline-start: 5px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.general-textarea {
|
||||
direction: ltr;
|
||||
width: 740px;
|
||||
height: 500px;
|
||||
overflow: auto;
|
||||
resize: none;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.wnp-textarea {
|
||||
direction: ltr;
|
||||
width: 740px;
|
||||
height: 500px;
|
||||
overflow: auto;
|
||||
resize: none;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.json-button {
|
||||
display: inline-flex;
|
||||
font-size: 10px;
|
||||
padding: 4px 10px;
|
||||
margin-bottom: 6px;
|
||||
margin-inline-end: 4px;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--newtab-element-hover-color);
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
|
||||
&.minimal-table {
|
||||
border-collapse: collapse;
|
||||
border: 1px solid $border-color;
|
||||
|
||||
td {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
td:first-child {
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
td:not(:first-child) {
|
||||
font-family: $monospace;
|
||||
}
|
||||
}
|
||||
|
||||
&.errorReporting {
|
||||
tr {
|
||||
border: 1px solid var(--newtab-background-color-secondary);
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 4px;
|
||||
|
||||
&[rowspan] {
|
||||
border: 1px solid var(--newtab-background-color-secondary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sourceLabel {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
|
||||
&.isDisabled {
|
||||
background: $email-input-invalid;
|
||||
color: var(--newtab-status-error);
|
||||
}
|
||||
}
|
||||
|
||||
.message-item {
|
||||
&:first-child td {
|
||||
border-top: 1px solid $border-color;
|
||||
}
|
||||
|
||||
td {
|
||||
vertical-align: top;
|
||||
padding: 8px;
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
||||
&.min {
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&.message-summary {
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
&.button-column {
|
||||
width: 15%;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
border-inline-start: 1px solid $border-color;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-inline-end: 1px solid $border-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.blocked {
|
||||
.message-id,
|
||||
.message-summary {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.message-id {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.message-id {
|
||||
font-family: $monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.providerUrl {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
font-size: 12px;
|
||||
max-width: 750px;
|
||||
overflow: auto;
|
||||
font-family: $monospace;
|
||||
}
|
||||
|
||||
.errorState {
|
||||
border: $input-error-border;
|
||||
}
|
||||
|
||||
.helpLink {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
background: $black-10;
|
||||
border-radius: 3px;
|
||||
align-items: center;
|
||||
|
||||
a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.icon {
|
||||
min-width: 18px;
|
||||
min-height: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.ds-component {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.modalOverlayInner {
|
||||
height: 80%;
|
||||
}
|
||||
|
||||
.clearButton {
|
||||
border: 0;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
|
||||
&:hover {
|
||||
background: var(--newtab-element-hover-color);
|
||||
}
|
||||
}
|
||||
|
||||
.collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.icon {
|
||||
display: inline-table;
|
||||
cursor: pointer;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.button {
|
||||
&:disabled,
|
||||
&:disabled:active {
|
||||
opacity: 0.5;
|
||||
cursor: unset;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.impressions-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
|
||||
.impressions-item {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
padding: 8px;
|
||||
border: 1px solid $border-color;
|
||||
border-radius: 5px;
|
||||
|
||||
.impressions-inner-box {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.impressions-category {
|
||||
font-size: 1.15em;
|
||||
white-space: nowrap;
|
||||
flex-grow: 0.1;
|
||||
}
|
||||
|
||||
.impressions-buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
|
||||
button {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.impressions-editor {
|
||||
display: flex;
|
||||
flex-grow: 1.5;
|
||||
|
||||
.general-textarea {
|
||||
width: auto;
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import React from "react";
|
||||
|
||||
export class SimpleHashRouter extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onHashChange = this.onHashChange.bind(this);
|
||||
this.state = { hash: global.location.hash };
|
||||
}
|
||||
|
||||
onHashChange() {
|
||||
this.setState({ hash: global.location.hash });
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
global.addEventListener("hashchange", this.onHashChange);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
global.removeEventListener("hashchange", this.onHashChange);
|
||||
}
|
||||
|
||||
render() {
|
||||
const [, ...routes] = this.state.hash.split("-");
|
||||
return React.cloneElement(this.props.children, {
|
||||
location: {
|
||||
hash: this.state.hash,
|
||||
routes,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
|
@ -139,7 +139,7 @@ input {
|
|||
@import '../components/CustomizeMenu/CustomizeMenu';
|
||||
@import '../components/Card/Card';
|
||||
@import '../components/CollapsibleSection/CollapsibleSection';
|
||||
@import '../components/DiscoveryStreamAdmin/DiscoveryStreamAdmin';
|
||||
@import '../components/ASRouterAdmin/ASRouterAdmin';
|
||||
@import '../components/PocketLoggedInCta/PocketLoggedInCta';
|
||||
@import '../components/MoreRecommendations/MoreRecommendations';
|
||||
@import '../components/DiscoveryStreamBase/DiscoveryStreamBase';
|
||||
|
|
|
@ -2161,7 +2161,7 @@ main section {
|
|||
}
|
||||
|
||||
/* stylelint-disable max-nesting-depth */
|
||||
.discoverystream-admin-toggle {
|
||||
.asrouter-toggle {
|
||||
position: fixed;
|
||||
top: 50px;
|
||||
inset-inline-end: 15px;
|
||||
|
@ -2170,21 +2170,21 @@ main section {
|
|||
z-index: 1;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.discoverystream-admin-toggle .icon-devtools {
|
||||
.asrouter-toggle .icon-devtools {
|
||||
background-image: url("chrome://global/skin/icons/developer.svg");
|
||||
padding: 15px;
|
||||
}
|
||||
.discoverystream-admin-toggle:dir(rtl) {
|
||||
.asrouter-toggle:dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
.discoverystream-admin-toggle:hover {
|
||||
.asrouter-toggle:hover {
|
||||
background: var(--newtab-element-hover-color);
|
||||
}
|
||||
.discoverystream-admin-toggle.expanded {
|
||||
.asrouter-toggle.expanded {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.discoverystream-admin {
|
||||
.asrouter-admin {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
|
@ -2197,40 +2197,40 @@ main section {
|
|||
padding-inline-start: 240px;
|
||||
color: var(--newtab-text-primary-color);
|
||||
}
|
||||
.discoverystream-admin.collapsed {
|
||||
.asrouter-admin.collapsed {
|
||||
display: none;
|
||||
}
|
||||
.discoverystream-admin .sidebar {
|
||||
.asrouter-admin .sidebar {
|
||||
inset-inline-start: 0;
|
||||
position: fixed;
|
||||
width: 240px;
|
||||
padding: 30px 20px;
|
||||
}
|
||||
.discoverystream-admin .sidebar ul {
|
||||
.asrouter-admin .sidebar ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.discoverystream-admin .sidebar li a {
|
||||
.asrouter-admin .sidebar li a {
|
||||
padding: 10px 34px;
|
||||
display: block;
|
||||
color: var(--lwt-sidebar-text-color);
|
||||
}
|
||||
.discoverystream-admin .sidebar li a:hover {
|
||||
.asrouter-admin .sidebar li a:hover {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
}
|
||||
.discoverystream-admin h1 {
|
||||
.asrouter-admin h1 {
|
||||
font-weight: 200;
|
||||
font-size: 32px;
|
||||
}
|
||||
.discoverystream-admin h2 .button,
|
||||
.discoverystream-admin p .button {
|
||||
.asrouter-admin h2 .button,
|
||||
.asrouter-admin p .button {
|
||||
font-size: 14px;
|
||||
padding: 6px 12px;
|
||||
margin-inline-start: 5px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.discoverystream-admin .general-textarea {
|
||||
.asrouter-admin .general-textarea {
|
||||
direction: ltr;
|
||||
width: 740px;
|
||||
height: 500px;
|
||||
|
@ -2239,7 +2239,7 @@ main section {
|
|||
border-radius: 4px;
|
||||
display: flex;
|
||||
}
|
||||
.discoverystream-admin .wnp-textarea {
|
||||
.asrouter-admin .wnp-textarea {
|
||||
direction: ltr;
|
||||
width: 740px;
|
||||
height: 500px;
|
||||
|
@ -2248,92 +2248,92 @@ main section {
|
|||
border-radius: 4px;
|
||||
display: flex;
|
||||
}
|
||||
.discoverystream-admin .json-button {
|
||||
.asrouter-admin .json-button {
|
||||
display: inline-flex;
|
||||
font-size: 10px;
|
||||
padding: 4px 10px;
|
||||
margin-bottom: 6px;
|
||||
margin-inline-end: 4px;
|
||||
}
|
||||
.discoverystream-admin .json-button:hover {
|
||||
.asrouter-admin .json-button:hover {
|
||||
background-color: var(--newtab-element-hover-color);
|
||||
box-shadow: none;
|
||||
}
|
||||
.discoverystream-admin table {
|
||||
.asrouter-admin table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
.discoverystream-admin table.minimal-table {
|
||||
.asrouter-admin table.minimal-table {
|
||||
border-collapse: collapse;
|
||||
border: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.discoverystream-admin table.minimal-table td {
|
||||
.asrouter-admin table.minimal-table td {
|
||||
padding: 8px;
|
||||
}
|
||||
.discoverystream-admin table.minimal-table td:first-child {
|
||||
.asrouter-admin table.minimal-table td:first-child {
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.discoverystream-admin table.minimal-table td:not(:first-child) {
|
||||
.asrouter-admin table.minimal-table td:not(:first-child) {
|
||||
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
|
||||
}
|
||||
.discoverystream-admin table.errorReporting tr {
|
||||
.asrouter-admin table.errorReporting tr {
|
||||
border: 1px solid var(--newtab-background-color-secondary);
|
||||
}
|
||||
.discoverystream-admin table.errorReporting td {
|
||||
.asrouter-admin table.errorReporting td {
|
||||
padding: 4px;
|
||||
}
|
||||
.discoverystream-admin table.errorReporting td[rowspan] {
|
||||
.asrouter-admin table.errorReporting td[rowspan] {
|
||||
border: 1px solid var(--newtab-background-color-secondary);
|
||||
}
|
||||
.discoverystream-admin .sourceLabel {
|
||||
.asrouter-admin .sourceLabel {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.discoverystream-admin .sourceLabel.isDisabled {
|
||||
.asrouter-admin .sourceLabel.isDisabled {
|
||||
background: rgba(215, 0, 34, 0.3);
|
||||
color: var(--newtab-status-error);
|
||||
}
|
||||
.discoverystream-admin .message-item:first-child td {
|
||||
.asrouter-admin .message-item:first-child td {
|
||||
border-top: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.discoverystream-admin .message-item td {
|
||||
.asrouter-admin .message-item td {
|
||||
vertical-align: top;
|
||||
padding: 8px;
|
||||
border-bottom: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.discoverystream-admin .message-item td.min {
|
||||
.asrouter-admin .message-item td.min {
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.discoverystream-admin .message-item td.message-summary {
|
||||
.asrouter-admin .message-item td.message-summary {
|
||||
width: 60%;
|
||||
}
|
||||
.discoverystream-admin .message-item td.button-column {
|
||||
.asrouter-admin .message-item td.button-column {
|
||||
width: 15%;
|
||||
}
|
||||
.discoverystream-admin .message-item td:first-child {
|
||||
.asrouter-admin .message-item td:first-child {
|
||||
border-inline-start: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.discoverystream-admin .message-item td:last-child {
|
||||
.asrouter-admin .message-item td:last-child {
|
||||
border-inline-end: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.discoverystream-admin .message-item.blocked .message-id,
|
||||
.discoverystream-admin .message-item.blocked .message-summary {
|
||||
.asrouter-admin .message-item.blocked .message-id,
|
||||
.asrouter-admin .message-item.blocked .message-summary {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.discoverystream-admin .message-item.blocked .message-id {
|
||||
.asrouter-admin .message-item.blocked .message-id {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.discoverystream-admin .message-item .message-id {
|
||||
.asrouter-admin .message-item .message-id {
|
||||
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
.discoverystream-admin .providerUrl {
|
||||
.asrouter-admin .providerUrl {
|
||||
font-size: 12px;
|
||||
}
|
||||
.discoverystream-admin pre {
|
||||
.asrouter-admin pre {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
|
@ -2342,87 +2342,87 @@ main section {
|
|||
overflow: auto;
|
||||
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
|
||||
}
|
||||
.discoverystream-admin .errorState {
|
||||
.asrouter-admin .errorState {
|
||||
border: 1px solid var(--newtab-status-error);
|
||||
}
|
||||
.discoverystream-admin .helpLink {
|
||||
.asrouter-admin .helpLink {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
border-radius: 3px;
|
||||
align-items: center;
|
||||
}
|
||||
.discoverystream-admin .helpLink a {
|
||||
.asrouter-admin .helpLink a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.discoverystream-admin .helpLink .icon {
|
||||
.asrouter-admin .helpLink .icon {
|
||||
min-width: 18px;
|
||||
min-height: 18px;
|
||||
}
|
||||
.discoverystream-admin .ds-component {
|
||||
.asrouter-admin .ds-component {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.discoverystream-admin .modalOverlayInner {
|
||||
.asrouter-admin .modalOverlayInner {
|
||||
height: 80%;
|
||||
}
|
||||
.discoverystream-admin .clearButton {
|
||||
.asrouter-admin .clearButton {
|
||||
border: 0;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
}
|
||||
.discoverystream-admin .clearButton:hover {
|
||||
.asrouter-admin .clearButton:hover {
|
||||
background: var(--newtab-element-hover-color);
|
||||
}
|
||||
.discoverystream-admin .collapsed {
|
||||
.asrouter-admin .collapsed {
|
||||
display: none;
|
||||
}
|
||||
.discoverystream-admin .icon {
|
||||
.asrouter-admin .icon {
|
||||
display: inline-table;
|
||||
cursor: pointer;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
.discoverystream-admin .button:disabled, .discoverystream-admin .button:disabled:active {
|
||||
.asrouter-admin .button:disabled, .asrouter-admin .button:disabled:active {
|
||||
opacity: 0.5;
|
||||
cursor: unset;
|
||||
box-shadow: none;
|
||||
}
|
||||
.discoverystream-admin .impressions-section {
|
||||
.asrouter-admin .impressions-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item {
|
||||
.asrouter-admin .impressions-section .impressions-item {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
padding: 8px;
|
||||
border: 1px solid var(--newtab-border-color);
|
||||
border-radius: 5px;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item .impressions-inner-box {
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-inner-box {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
gap: 8px;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item .impressions-category {
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-category {
|
||||
font-size: 1.15em;
|
||||
white-space: nowrap;
|
||||
flex-grow: 0.1;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item .impressions-buttons {
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item .impressions-buttons button {
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-buttons button {
|
||||
margin: 0;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item .impressions-editor {
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-editor {
|
||||
display: flex;
|
||||
flex-grow: 1.5;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item .impressions-editor .general-textarea {
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-editor .general-textarea {
|
||||
width: auto;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
|
|
@ -2165,7 +2165,7 @@ main section {
|
|||
}
|
||||
|
||||
/* stylelint-disable max-nesting-depth */
|
||||
.discoverystream-admin-toggle {
|
||||
.asrouter-toggle {
|
||||
position: fixed;
|
||||
top: 50px;
|
||||
inset-inline-end: 15px;
|
||||
|
@ -2174,21 +2174,21 @@ main section {
|
|||
z-index: 1;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.discoverystream-admin-toggle .icon-devtools {
|
||||
.asrouter-toggle .icon-devtools {
|
||||
background-image: url("chrome://global/skin/icons/developer.svg");
|
||||
padding: 15px;
|
||||
}
|
||||
.discoverystream-admin-toggle:dir(rtl) {
|
||||
.asrouter-toggle:dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
.discoverystream-admin-toggle:hover {
|
||||
.asrouter-toggle:hover {
|
||||
background: var(--newtab-element-hover-color);
|
||||
}
|
||||
.discoverystream-admin-toggle.expanded {
|
||||
.asrouter-toggle.expanded {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.discoverystream-admin {
|
||||
.asrouter-admin {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
|
@ -2201,40 +2201,40 @@ main section {
|
|||
padding-inline-start: 240px;
|
||||
color: var(--newtab-text-primary-color);
|
||||
}
|
||||
.discoverystream-admin.collapsed {
|
||||
.asrouter-admin.collapsed {
|
||||
display: none;
|
||||
}
|
||||
.discoverystream-admin .sidebar {
|
||||
.asrouter-admin .sidebar {
|
||||
inset-inline-start: 0;
|
||||
position: fixed;
|
||||
width: 240px;
|
||||
padding: 30px 20px;
|
||||
}
|
||||
.discoverystream-admin .sidebar ul {
|
||||
.asrouter-admin .sidebar ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.discoverystream-admin .sidebar li a {
|
||||
.asrouter-admin .sidebar li a {
|
||||
padding: 10px 34px;
|
||||
display: block;
|
||||
color: var(--lwt-sidebar-text-color);
|
||||
}
|
||||
.discoverystream-admin .sidebar li a:hover {
|
||||
.asrouter-admin .sidebar li a:hover {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
}
|
||||
.discoverystream-admin h1 {
|
||||
.asrouter-admin h1 {
|
||||
font-weight: 200;
|
||||
font-size: 32px;
|
||||
}
|
||||
.discoverystream-admin h2 .button,
|
||||
.discoverystream-admin p .button {
|
||||
.asrouter-admin h2 .button,
|
||||
.asrouter-admin p .button {
|
||||
font-size: 14px;
|
||||
padding: 6px 12px;
|
||||
margin-inline-start: 5px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.discoverystream-admin .general-textarea {
|
||||
.asrouter-admin .general-textarea {
|
||||
direction: ltr;
|
||||
width: 740px;
|
||||
height: 500px;
|
||||
|
@ -2243,7 +2243,7 @@ main section {
|
|||
border-radius: 4px;
|
||||
display: flex;
|
||||
}
|
||||
.discoverystream-admin .wnp-textarea {
|
||||
.asrouter-admin .wnp-textarea {
|
||||
direction: ltr;
|
||||
width: 740px;
|
||||
height: 500px;
|
||||
|
@ -2252,92 +2252,92 @@ main section {
|
|||
border-radius: 4px;
|
||||
display: flex;
|
||||
}
|
||||
.discoverystream-admin .json-button {
|
||||
.asrouter-admin .json-button {
|
||||
display: inline-flex;
|
||||
font-size: 10px;
|
||||
padding: 4px 10px;
|
||||
margin-bottom: 6px;
|
||||
margin-inline-end: 4px;
|
||||
}
|
||||
.discoverystream-admin .json-button:hover {
|
||||
.asrouter-admin .json-button:hover {
|
||||
background-color: var(--newtab-element-hover-color);
|
||||
box-shadow: none;
|
||||
}
|
||||
.discoverystream-admin table {
|
||||
.asrouter-admin table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
.discoverystream-admin table.minimal-table {
|
||||
.asrouter-admin table.minimal-table {
|
||||
border-collapse: collapse;
|
||||
border: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.discoverystream-admin table.minimal-table td {
|
||||
.asrouter-admin table.minimal-table td {
|
||||
padding: 8px;
|
||||
}
|
||||
.discoverystream-admin table.minimal-table td:first-child {
|
||||
.asrouter-admin table.minimal-table td:first-child {
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.discoverystream-admin table.minimal-table td:not(:first-child) {
|
||||
.asrouter-admin table.minimal-table td:not(:first-child) {
|
||||
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
|
||||
}
|
||||
.discoverystream-admin table.errorReporting tr {
|
||||
.asrouter-admin table.errorReporting tr {
|
||||
border: 1px solid var(--newtab-background-color-secondary);
|
||||
}
|
||||
.discoverystream-admin table.errorReporting td {
|
||||
.asrouter-admin table.errorReporting td {
|
||||
padding: 4px;
|
||||
}
|
||||
.discoverystream-admin table.errorReporting td[rowspan] {
|
||||
.asrouter-admin table.errorReporting td[rowspan] {
|
||||
border: 1px solid var(--newtab-background-color-secondary);
|
||||
}
|
||||
.discoverystream-admin .sourceLabel {
|
||||
.asrouter-admin .sourceLabel {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.discoverystream-admin .sourceLabel.isDisabled {
|
||||
.asrouter-admin .sourceLabel.isDisabled {
|
||||
background: rgba(215, 0, 34, 0.3);
|
||||
color: var(--newtab-status-error);
|
||||
}
|
||||
.discoverystream-admin .message-item:first-child td {
|
||||
.asrouter-admin .message-item:first-child td {
|
||||
border-top: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.discoverystream-admin .message-item td {
|
||||
.asrouter-admin .message-item td {
|
||||
vertical-align: top;
|
||||
padding: 8px;
|
||||
border-bottom: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.discoverystream-admin .message-item td.min {
|
||||
.asrouter-admin .message-item td.min {
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.discoverystream-admin .message-item td.message-summary {
|
||||
.asrouter-admin .message-item td.message-summary {
|
||||
width: 60%;
|
||||
}
|
||||
.discoverystream-admin .message-item td.button-column {
|
||||
.asrouter-admin .message-item td.button-column {
|
||||
width: 15%;
|
||||
}
|
||||
.discoverystream-admin .message-item td:first-child {
|
||||
.asrouter-admin .message-item td:first-child {
|
||||
border-inline-start: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.discoverystream-admin .message-item td:last-child {
|
||||
.asrouter-admin .message-item td:last-child {
|
||||
border-inline-end: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.discoverystream-admin .message-item.blocked .message-id,
|
||||
.discoverystream-admin .message-item.blocked .message-summary {
|
||||
.asrouter-admin .message-item.blocked .message-id,
|
||||
.asrouter-admin .message-item.blocked .message-summary {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.discoverystream-admin .message-item.blocked .message-id {
|
||||
.asrouter-admin .message-item.blocked .message-id {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.discoverystream-admin .message-item .message-id {
|
||||
.asrouter-admin .message-item .message-id {
|
||||
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
.discoverystream-admin .providerUrl {
|
||||
.asrouter-admin .providerUrl {
|
||||
font-size: 12px;
|
||||
}
|
||||
.discoverystream-admin pre {
|
||||
.asrouter-admin pre {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
|
@ -2346,87 +2346,87 @@ main section {
|
|||
overflow: auto;
|
||||
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
|
||||
}
|
||||
.discoverystream-admin .errorState {
|
||||
.asrouter-admin .errorState {
|
||||
border: 1px solid var(--newtab-status-error);
|
||||
}
|
||||
.discoverystream-admin .helpLink {
|
||||
.asrouter-admin .helpLink {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
border-radius: 3px;
|
||||
align-items: center;
|
||||
}
|
||||
.discoverystream-admin .helpLink a {
|
||||
.asrouter-admin .helpLink a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.discoverystream-admin .helpLink .icon {
|
||||
.asrouter-admin .helpLink .icon {
|
||||
min-width: 18px;
|
||||
min-height: 18px;
|
||||
}
|
||||
.discoverystream-admin .ds-component {
|
||||
.asrouter-admin .ds-component {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.discoverystream-admin .modalOverlayInner {
|
||||
.asrouter-admin .modalOverlayInner {
|
||||
height: 80%;
|
||||
}
|
||||
.discoverystream-admin .clearButton {
|
||||
.asrouter-admin .clearButton {
|
||||
border: 0;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
}
|
||||
.discoverystream-admin .clearButton:hover {
|
||||
.asrouter-admin .clearButton:hover {
|
||||
background: var(--newtab-element-hover-color);
|
||||
}
|
||||
.discoverystream-admin .collapsed {
|
||||
.asrouter-admin .collapsed {
|
||||
display: none;
|
||||
}
|
||||
.discoverystream-admin .icon {
|
||||
.asrouter-admin .icon {
|
||||
display: inline-table;
|
||||
cursor: pointer;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
.discoverystream-admin .button:disabled, .discoverystream-admin .button:disabled:active {
|
||||
.asrouter-admin .button:disabled, .asrouter-admin .button:disabled:active {
|
||||
opacity: 0.5;
|
||||
cursor: unset;
|
||||
box-shadow: none;
|
||||
}
|
||||
.discoverystream-admin .impressions-section {
|
||||
.asrouter-admin .impressions-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item {
|
||||
.asrouter-admin .impressions-section .impressions-item {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
padding: 8px;
|
||||
border: 1px solid var(--newtab-border-color);
|
||||
border-radius: 5px;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item .impressions-inner-box {
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-inner-box {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
gap: 8px;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item .impressions-category {
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-category {
|
||||
font-size: 1.15em;
|
||||
white-space: nowrap;
|
||||
flex-grow: 0.1;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item .impressions-buttons {
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item .impressions-buttons button {
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-buttons button {
|
||||
margin: 0;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item .impressions-editor {
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-editor {
|
||||
display: flex;
|
||||
flex-grow: 1.5;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item .impressions-editor .general-textarea {
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-editor .general-textarea {
|
||||
width: auto;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
|
|
@ -2161,7 +2161,7 @@ main section {
|
|||
}
|
||||
|
||||
/* stylelint-disable max-nesting-depth */
|
||||
.discoverystream-admin-toggle {
|
||||
.asrouter-toggle {
|
||||
position: fixed;
|
||||
top: 50px;
|
||||
inset-inline-end: 15px;
|
||||
|
@ -2170,21 +2170,21 @@ main section {
|
|||
z-index: 1;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.discoverystream-admin-toggle .icon-devtools {
|
||||
.asrouter-toggle .icon-devtools {
|
||||
background-image: url("chrome://global/skin/icons/developer.svg");
|
||||
padding: 15px;
|
||||
}
|
||||
.discoverystream-admin-toggle:dir(rtl) {
|
||||
.asrouter-toggle:dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
.discoverystream-admin-toggle:hover {
|
||||
.asrouter-toggle:hover {
|
||||
background: var(--newtab-element-hover-color);
|
||||
}
|
||||
.discoverystream-admin-toggle.expanded {
|
||||
.asrouter-toggle.expanded {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.discoverystream-admin {
|
||||
.asrouter-admin {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
|
@ -2197,40 +2197,40 @@ main section {
|
|||
padding-inline-start: 240px;
|
||||
color: var(--newtab-text-primary-color);
|
||||
}
|
||||
.discoverystream-admin.collapsed {
|
||||
.asrouter-admin.collapsed {
|
||||
display: none;
|
||||
}
|
||||
.discoverystream-admin .sidebar {
|
||||
.asrouter-admin .sidebar {
|
||||
inset-inline-start: 0;
|
||||
position: fixed;
|
||||
width: 240px;
|
||||
padding: 30px 20px;
|
||||
}
|
||||
.discoverystream-admin .sidebar ul {
|
||||
.asrouter-admin .sidebar ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.discoverystream-admin .sidebar li a {
|
||||
.asrouter-admin .sidebar li a {
|
||||
padding: 10px 34px;
|
||||
display: block;
|
||||
color: var(--lwt-sidebar-text-color);
|
||||
}
|
||||
.discoverystream-admin .sidebar li a:hover {
|
||||
.asrouter-admin .sidebar li a:hover {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
}
|
||||
.discoverystream-admin h1 {
|
||||
.asrouter-admin h1 {
|
||||
font-weight: 200;
|
||||
font-size: 32px;
|
||||
}
|
||||
.discoverystream-admin h2 .button,
|
||||
.discoverystream-admin p .button {
|
||||
.asrouter-admin h2 .button,
|
||||
.asrouter-admin p .button {
|
||||
font-size: 14px;
|
||||
padding: 6px 12px;
|
||||
margin-inline-start: 5px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.discoverystream-admin .general-textarea {
|
||||
.asrouter-admin .general-textarea {
|
||||
direction: ltr;
|
||||
width: 740px;
|
||||
height: 500px;
|
||||
|
@ -2239,7 +2239,7 @@ main section {
|
|||
border-radius: 4px;
|
||||
display: flex;
|
||||
}
|
||||
.discoverystream-admin .wnp-textarea {
|
||||
.asrouter-admin .wnp-textarea {
|
||||
direction: ltr;
|
||||
width: 740px;
|
||||
height: 500px;
|
||||
|
@ -2248,92 +2248,92 @@ main section {
|
|||
border-radius: 4px;
|
||||
display: flex;
|
||||
}
|
||||
.discoverystream-admin .json-button {
|
||||
.asrouter-admin .json-button {
|
||||
display: inline-flex;
|
||||
font-size: 10px;
|
||||
padding: 4px 10px;
|
||||
margin-bottom: 6px;
|
||||
margin-inline-end: 4px;
|
||||
}
|
||||
.discoverystream-admin .json-button:hover {
|
||||
.asrouter-admin .json-button:hover {
|
||||
background-color: var(--newtab-element-hover-color);
|
||||
box-shadow: none;
|
||||
}
|
||||
.discoverystream-admin table {
|
||||
.asrouter-admin table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
.discoverystream-admin table.minimal-table {
|
||||
.asrouter-admin table.minimal-table {
|
||||
border-collapse: collapse;
|
||||
border: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.discoverystream-admin table.minimal-table td {
|
||||
.asrouter-admin table.minimal-table td {
|
||||
padding: 8px;
|
||||
}
|
||||
.discoverystream-admin table.minimal-table td:first-child {
|
||||
.asrouter-admin table.minimal-table td:first-child {
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.discoverystream-admin table.minimal-table td:not(:first-child) {
|
||||
.asrouter-admin table.minimal-table td:not(:first-child) {
|
||||
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
|
||||
}
|
||||
.discoverystream-admin table.errorReporting tr {
|
||||
.asrouter-admin table.errorReporting tr {
|
||||
border: 1px solid var(--newtab-background-color-secondary);
|
||||
}
|
||||
.discoverystream-admin table.errorReporting td {
|
||||
.asrouter-admin table.errorReporting td {
|
||||
padding: 4px;
|
||||
}
|
||||
.discoverystream-admin table.errorReporting td[rowspan] {
|
||||
.asrouter-admin table.errorReporting td[rowspan] {
|
||||
border: 1px solid var(--newtab-background-color-secondary);
|
||||
}
|
||||
.discoverystream-admin .sourceLabel {
|
||||
.asrouter-admin .sourceLabel {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.discoverystream-admin .sourceLabel.isDisabled {
|
||||
.asrouter-admin .sourceLabel.isDisabled {
|
||||
background: rgba(215, 0, 34, 0.3);
|
||||
color: var(--newtab-status-error);
|
||||
}
|
||||
.discoverystream-admin .message-item:first-child td {
|
||||
.asrouter-admin .message-item:first-child td {
|
||||
border-top: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.discoverystream-admin .message-item td {
|
||||
.asrouter-admin .message-item td {
|
||||
vertical-align: top;
|
||||
padding: 8px;
|
||||
border-bottom: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.discoverystream-admin .message-item td.min {
|
||||
.asrouter-admin .message-item td.min {
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.discoverystream-admin .message-item td.message-summary {
|
||||
.asrouter-admin .message-item td.message-summary {
|
||||
width: 60%;
|
||||
}
|
||||
.discoverystream-admin .message-item td.button-column {
|
||||
.asrouter-admin .message-item td.button-column {
|
||||
width: 15%;
|
||||
}
|
||||
.discoverystream-admin .message-item td:first-child {
|
||||
.asrouter-admin .message-item td:first-child {
|
||||
border-inline-start: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.discoverystream-admin .message-item td:last-child {
|
||||
.asrouter-admin .message-item td:last-child {
|
||||
border-inline-end: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.discoverystream-admin .message-item.blocked .message-id,
|
||||
.discoverystream-admin .message-item.blocked .message-summary {
|
||||
.asrouter-admin .message-item.blocked .message-id,
|
||||
.asrouter-admin .message-item.blocked .message-summary {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.discoverystream-admin .message-item.blocked .message-id {
|
||||
.asrouter-admin .message-item.blocked .message-id {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.discoverystream-admin .message-item .message-id {
|
||||
.asrouter-admin .message-item .message-id {
|
||||
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
.discoverystream-admin .providerUrl {
|
||||
.asrouter-admin .providerUrl {
|
||||
font-size: 12px;
|
||||
}
|
||||
.discoverystream-admin pre {
|
||||
.asrouter-admin pre {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
|
@ -2342,87 +2342,87 @@ main section {
|
|||
overflow: auto;
|
||||
font-family: "SF Mono", "Monaco", "Inconsolata", "Fira Mono", "Droid Sans Mono", "Source Code Pro", monospace;
|
||||
}
|
||||
.discoverystream-admin .errorState {
|
||||
.asrouter-admin .errorState {
|
||||
border: 1px solid var(--newtab-status-error);
|
||||
}
|
||||
.discoverystream-admin .helpLink {
|
||||
.asrouter-admin .helpLink {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
border-radius: 3px;
|
||||
align-items: center;
|
||||
}
|
||||
.discoverystream-admin .helpLink a {
|
||||
.asrouter-admin .helpLink a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.discoverystream-admin .helpLink .icon {
|
||||
.asrouter-admin .helpLink .icon {
|
||||
min-width: 18px;
|
||||
min-height: 18px;
|
||||
}
|
||||
.discoverystream-admin .ds-component {
|
||||
.asrouter-admin .ds-component {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.discoverystream-admin .modalOverlayInner {
|
||||
.asrouter-admin .modalOverlayInner {
|
||||
height: 80%;
|
||||
}
|
||||
.discoverystream-admin .clearButton {
|
||||
.asrouter-admin .clearButton {
|
||||
border: 0;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
}
|
||||
.discoverystream-admin .clearButton:hover {
|
||||
.asrouter-admin .clearButton:hover {
|
||||
background: var(--newtab-element-hover-color);
|
||||
}
|
||||
.discoverystream-admin .collapsed {
|
||||
.asrouter-admin .collapsed {
|
||||
display: none;
|
||||
}
|
||||
.discoverystream-admin .icon {
|
||||
.asrouter-admin .icon {
|
||||
display: inline-table;
|
||||
cursor: pointer;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
.discoverystream-admin .button:disabled, .discoverystream-admin .button:disabled:active {
|
||||
.asrouter-admin .button:disabled, .asrouter-admin .button:disabled:active {
|
||||
opacity: 0.5;
|
||||
cursor: unset;
|
||||
box-shadow: none;
|
||||
}
|
||||
.discoverystream-admin .impressions-section {
|
||||
.asrouter-admin .impressions-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item {
|
||||
.asrouter-admin .impressions-section .impressions-item {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
padding: 8px;
|
||||
border: 1px solid var(--newtab-border-color);
|
||||
border-radius: 5px;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item .impressions-inner-box {
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-inner-box {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
gap: 8px;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item .impressions-category {
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-category {
|
||||
font-size: 1.15em;
|
||||
white-space: nowrap;
|
||||
flex-grow: 0.1;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item .impressions-buttons {
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item .impressions-buttons button {
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-buttons button {
|
||||
margin: 0;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item .impressions-editor {
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-editor {
|
||||
display: flex;
|
||||
flex-grow: 1.5;
|
||||
}
|
||||
.discoverystream-admin .impressions-section .impressions-item .impressions-editor .general-textarea {
|
||||
.asrouter-admin .impressions-section .impressions-item .impressions-editor .general-textarea {
|
||||
width: auto;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -99,15 +99,6 @@ running
|
|||
./mach npm test --prefix=browser/components/newtab &&
|
||||
./mach npm run debugcoverage --prefix=browser/components/newtab
|
||||
|
||||
Discovery Stream Developer tools
|
||||
--------------------------------
|
||||
|
||||
You can access the developer tools for the Discovery Stream components of about:newtab by
|
||||
visiting `about:config` and setting `browser.newtabpage.activity-stream.asrouter.devtoolsEnabled`
|
||||
to `true`.
|
||||
|
||||
Then, go to any `about:newtab` page and click on the wrench icon in the top-right corner.
|
||||
|
||||
Detailed Docs
|
||||
-------------
|
||||
.. toctree::
|
||||
|
|
|
@ -97,8 +97,8 @@ module.exports = function (config) {
|
|||
"content-src/asrouter/asrouter-utils.js": {
|
||||
statements: 66,
|
||||
lines: 66,
|
||||
functions: 76,
|
||||
branches: 33,
|
||||
functions: 78,
|
||||
branches: 50,
|
||||
},
|
||||
"lib/TelemetryFeed.jsm": {
|
||||
statements: 98,
|
||||
|
@ -188,7 +188,7 @@ module.exports = function (config) {
|
|||
functions: 60,
|
||||
branches: 50,
|
||||
},
|
||||
"content-src/components/DiscoveryStreamAdmin/*.jsx": {
|
||||
"content-src/components/ASRouterAdmin/*.jsx": {
|
||||
statements: 0,
|
||||
lines: 0,
|
||||
functions: 0,
|
||||
|
|
|
@ -1116,7 +1116,6 @@ class _ASRouter {
|
|||
userPrefs: lazy.ASRouterPreferences.getAllUserPreferences(),
|
||||
targetingParameters,
|
||||
errors: this.errors,
|
||||
devtoolsEnabled: lazy.ASRouterPreferences.devtoolsEnabled,
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
@ -1594,7 +1594,6 @@ describe("ASRouter", () => {
|
|||
userPrefs: ASRouterPreferences.getAllUserPreferences(),
|
||||
targetingParameters: {},
|
||||
errors: Router.errors,
|
||||
devtoolsEnabled: ASRouterPreferences.devtoolsEnabled,
|
||||
});
|
||||
|
||||
assert.deepEqual(msg, expected);
|
||||
|
|
|
@ -1,4 +1,14 @@
|
|||
import { ASRouterAdminInner } from "content-src/components/ASRouterAdmin/ASRouterAdmin";
|
||||
import {
|
||||
actionCreators as ac,
|
||||
actionTypes as at,
|
||||
} from "common/Actions.sys.mjs";
|
||||
import {
|
||||
ASRouterAdminInner,
|
||||
CollapseToggle,
|
||||
DiscoveryStreamAdmin,
|
||||
Personalization,
|
||||
ToggleStoryButton,
|
||||
} from "content-src/components/ASRouterAdmin/ASRouterAdmin";
|
||||
import { ASRouterUtils } from "content-src/asrouter/asrouter-utils";
|
||||
import { GlobalOverrider } from "test/unit/utils";
|
||||
import React from "react";
|
||||
|
@ -36,8 +46,9 @@ describe("ASRouterAdmin", () => {
|
|||
ASRouterRemoveParentListener: sandbox.stub(),
|
||||
};
|
||||
globalOverrider.set(globals);
|
||||
wrapper = shallow(<ASRouterAdminInner location={{ routes: [""] }} />);
|
||||
wrapper.setState({ devtoolsEnabled: true });
|
||||
wrapper = shallow(
|
||||
<ASRouterAdminInner collapsed={false} location={{ routes: [""] }} />
|
||||
);
|
||||
});
|
||||
afterEach(() => {
|
||||
sandbox.restore();
|
||||
|
@ -53,6 +64,15 @@ describe("ASRouterAdmin", () => {
|
|||
data: { endpoint: "foo" },
|
||||
});
|
||||
});
|
||||
it("should set a .collapsed class on the outer div if props.collapsed is true", () => {
|
||||
wrapper.setProps({ collapsed: true });
|
||||
assert.isTrue(wrapper.find(".asrouter-admin").hasClass("collapsed"));
|
||||
});
|
||||
it("should set a .expanded class on the outer div if props.collapsed is false", () => {
|
||||
wrapper.setProps({ collapsed: false });
|
||||
assert.isTrue(wrapper.find(".asrouter-admin").hasClass("expanded"));
|
||||
assert.isFalse(wrapper.find(".asrouter-admin").hasClass("collapsed"));
|
||||
});
|
||||
describe("#getSection", () => {
|
||||
it("should render a message provider section by default", () => {
|
||||
assert.equal(wrapper.find("h2").at(1).text(), "Messages");
|
||||
|
@ -61,14 +81,22 @@ describe("ASRouterAdmin", () => {
|
|||
wrapper = shallow(
|
||||
<ASRouterAdminInner location={{ routes: ["targeting"] }} />
|
||||
);
|
||||
wrapper.setState({ devtoolsEnabled: true });
|
||||
assert.equal(wrapper.find("h2").at(0).text(), "Targeting Utilities");
|
||||
});
|
||||
it("should render a DS section for DS route", () => {
|
||||
wrapper = shallow(
|
||||
<ASRouterAdminInner
|
||||
location={{ routes: ["ds"] }}
|
||||
Sections={[]}
|
||||
Prefs={{}}
|
||||
/>
|
||||
);
|
||||
assert.equal(wrapper.find("h2").at(0).text(), "Discovery Stream");
|
||||
});
|
||||
it("should render two error messages", () => {
|
||||
wrapper = shallow(
|
||||
<ASRouterAdminInner location={{ routes: ["errors"] }} Sections={[]} />
|
||||
);
|
||||
wrapper.setState({ devtoolsEnabled: true });
|
||||
const firstError = {
|
||||
timestamp: Date.now() + 100,
|
||||
error: { message: "first" },
|
||||
|
@ -259,4 +287,229 @@ describe("ASRouterAdmin", () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
describe("#DiscoveryStream", () => {
|
||||
let state = {};
|
||||
let dispatch;
|
||||
beforeEach(() => {
|
||||
dispatch = sandbox.stub();
|
||||
state = {
|
||||
config: {
|
||||
enabled: true,
|
||||
},
|
||||
layout: [],
|
||||
spocs: {
|
||||
frequency_caps: [],
|
||||
},
|
||||
feeds: {
|
||||
data: {},
|
||||
},
|
||||
};
|
||||
wrapper = shallow(
|
||||
<DiscoveryStreamAdmin
|
||||
dispatch={dispatch}
|
||||
otherPrefs={{}}
|
||||
state={{
|
||||
DiscoveryStream: state,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
it("should render a DiscoveryStreamAdmin component", () => {
|
||||
assert.equal(wrapper.find("h3").at(0).text(), "Layout");
|
||||
});
|
||||
it("should render a spoc in DiscoveryStreamAdmin component", () => {
|
||||
state.spocs = {
|
||||
frequency_caps: [],
|
||||
data: {
|
||||
spocs: {
|
||||
items: [
|
||||
{
|
||||
id: 12345,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
wrapper = shallow(
|
||||
<DiscoveryStreamAdmin
|
||||
otherPrefs={{}}
|
||||
state={{ DiscoveryStream: state }}
|
||||
/>
|
||||
);
|
||||
wrapper.instance().onStoryToggle({ id: 12345 });
|
||||
const messageSummary = wrapper.find(".message-summary").at(0);
|
||||
const pre = messageSummary.find("pre").at(0);
|
||||
const spocText = pre.text();
|
||||
assert.equal(spocText, '{\n "id": 12345\n}');
|
||||
});
|
||||
it("should fire restorePrefDefaults with DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS", () => {
|
||||
wrapper.find("button").at(0).simulate("click");
|
||||
assert.calledWith(
|
||||
dispatch,
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS,
|
||||
})
|
||||
);
|
||||
});
|
||||
it("should fire config change with DISCOVERY_STREAM_CONFIG_CHANGE", () => {
|
||||
wrapper.find("button").at(1).simulate("click");
|
||||
assert.calledWith(
|
||||
dispatch,
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_CONFIG_CHANGE,
|
||||
data: { enabled: true },
|
||||
})
|
||||
);
|
||||
});
|
||||
it("should fire expireCache with DISCOVERY_STREAM_DEV_EXPIRE_CACHE", () => {
|
||||
wrapper.find("button").at(2).simulate("click");
|
||||
assert.calledWith(
|
||||
dispatch,
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_DEV_EXPIRE_CACHE,
|
||||
})
|
||||
);
|
||||
});
|
||||
it("should fire systemTick with DISCOVERY_STREAM_DEV_SYSTEM_TICK", () => {
|
||||
wrapper.find("button").at(3).simulate("click");
|
||||
assert.calledWith(
|
||||
dispatch,
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_DEV_SYSTEM_TICK,
|
||||
})
|
||||
);
|
||||
});
|
||||
it("should fire idleDaily with DISCOVERY_STREAM_DEV_IDLE_DAILY", () => {
|
||||
wrapper.find("button").at(4).simulate("click");
|
||||
assert.calledWith(
|
||||
dispatch,
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_DEV_IDLE_DAILY,
|
||||
})
|
||||
);
|
||||
});
|
||||
it("should fire syncRemoteSettings with DISCOVERY_STREAM_DEV_SYNC_RS", () => {
|
||||
wrapper.find("button").at(5).simulate("click");
|
||||
assert.calledWith(
|
||||
dispatch,
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_DEV_SYNC_RS,
|
||||
})
|
||||
);
|
||||
});
|
||||
it("should fire setConfigValue with DISCOVERY_STREAM_CONFIG_SET_VALUE", () => {
|
||||
const name = "name";
|
||||
const value = "value";
|
||||
wrapper.instance().setConfigValue(name, value);
|
||||
assert.calledWith(
|
||||
dispatch,
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_CONFIG_SET_VALUE,
|
||||
data: { name, value },
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#Personalization", () => {
|
||||
let dispatch;
|
||||
beforeEach(() => {
|
||||
dispatch = sandbox.stub();
|
||||
wrapper = shallow(
|
||||
<Personalization
|
||||
dispatch={dispatch}
|
||||
state={{
|
||||
Personalization: {
|
||||
lastUpdated: 1000,
|
||||
initialized: true,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
it("should render with pref checkbox, lastUpdated, and initialized", () => {
|
||||
assert.lengthOf(wrapper.find("TogglePrefCheckbox"), 1);
|
||||
assert.equal(
|
||||
wrapper.find("td").at(1).text(),
|
||||
"Personalization Last Updated"
|
||||
);
|
||||
assert.equal(
|
||||
wrapper.find("td").at(2).text(),
|
||||
new Date(1000).toLocaleString()
|
||||
);
|
||||
assert.equal(
|
||||
wrapper.find("td").at(3).text(),
|
||||
"Personalization Initialized"
|
||||
);
|
||||
assert.equal(wrapper.find("td").at(4).text(), "true");
|
||||
});
|
||||
it("should render with no data with no last updated", () => {
|
||||
wrapper = shallow(
|
||||
<Personalization
|
||||
dispatch={dispatch}
|
||||
state={{
|
||||
Personalization: {
|
||||
version: 2,
|
||||
lastUpdated: 0,
|
||||
initialized: true,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
assert.equal(wrapper.find("td").at(2).text(), "(no data)");
|
||||
});
|
||||
it("should dispatch DISCOVERY_STREAM_PERSONALIZATION_TOGGLE", () => {
|
||||
wrapper.instance().togglePersonalization();
|
||||
assert.calledWith(
|
||||
dispatch,
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_PERSONALIZATION_TOGGLE,
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#ToggleStoryButton", () => {
|
||||
it("should fire onClick in toggle button", async () => {
|
||||
let result = "";
|
||||
function onClick(spoc) {
|
||||
result = spoc;
|
||||
}
|
||||
|
||||
wrapper = shallow(<ToggleStoryButton story="spoc" onClick={onClick} />);
|
||||
wrapper.find("button").simulate("click");
|
||||
|
||||
assert.equal(result, "spoc");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("CollapseToggle", () => {
|
||||
let wrapper;
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(<CollapseToggle location={{ routes: [""] }} />);
|
||||
});
|
||||
|
||||
describe("rendering inner content", () => {
|
||||
it("should not render ASRouterAdminInner for about:newtab (no hash)", () => {
|
||||
wrapper.setProps({ location: { hash: "", routes: [""] } });
|
||||
assert.lengthOf(wrapper.find(ASRouterAdminInner), 0);
|
||||
});
|
||||
|
||||
it("should render ASRouterAdminInner for about:newtab#asrouter and subroutes", () => {
|
||||
wrapper.setProps({ location: { hash: "#asrouter", routes: [""] } });
|
||||
assert.lengthOf(wrapper.find(ASRouterAdminInner), 1);
|
||||
|
||||
wrapper.setProps({ location: { hash: "#asrouter-foo", routes: [""] } });
|
||||
assert.lengthOf(wrapper.find(ASRouterAdminInner), 1);
|
||||
});
|
||||
|
||||
it("should render ASRouterAdminInner for about:newtab#devtools and subroutes", () => {
|
||||
wrapper.setProps({ location: { hash: "#devtools", routes: [""] } });
|
||||
assert.lengthOf(wrapper.find(ASRouterAdminInner), 1);
|
||||
|
||||
wrapper.setProps({ location: { hash: "#devtools-foo", routes: [""] } });
|
||||
assert.lengthOf(wrapper.find(ASRouterAdminInner), 1);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -3,7 +3,7 @@ import {
|
|||
BaseContent,
|
||||
PrefsButton,
|
||||
} from "content-src/components/Base/Base";
|
||||
import { DiscoveryStreamAdmin } from "content-src/components/DiscoveryStreamAdmin/DiscoveryStreamAdmin";
|
||||
import { ASRouterAdmin } from "content-src/components/ASRouterAdmin/ASRouterAdmin";
|
||||
import { ErrorBoundary } from "content-src/components/ErrorBoundary/ErrorBoundary";
|
||||
import React from "react";
|
||||
import { Search } from "content-src/components/Search/Search";
|
||||
|
@ -47,24 +47,24 @@ describe("<Base>", () => {
|
|||
);
|
||||
});
|
||||
|
||||
it("should render an DiscoveryStreamAdmin if the devtools pref is true", () => {
|
||||
it("should render an ASRouterAdmin if the devtools pref is true", () => {
|
||||
const wrapper = shallow(
|
||||
<Base
|
||||
{...DEFAULT_PROPS}
|
||||
Prefs={{ values: { "asrouter.devtoolsEnabled": true } }}
|
||||
/>
|
||||
);
|
||||
assert.lengthOf(wrapper.find(DiscoveryStreamAdmin), 1);
|
||||
assert.lengthOf(wrapper.find(ASRouterAdmin), 1);
|
||||
});
|
||||
|
||||
it("should not render an DiscoveryStreamAdmin if the devtools pref is false", () => {
|
||||
it("should not render an ASRouterAdmin if the devtools pref is false", () => {
|
||||
const wrapper = shallow(
|
||||
<Base
|
||||
{...DEFAULT_PROPS}
|
||||
Prefs={{ values: { "asrouter.devtoolsEnabled": false } }}
|
||||
/>
|
||||
);
|
||||
assert.lengthOf(wrapper.find(DiscoveryStreamAdmin), 0);
|
||||
assert.lengthOf(wrapper.find(ASRouterAdmin), 0);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,267 +0,0 @@
|
|||
import {
|
||||
actionCreators as ac,
|
||||
actionTypes as at,
|
||||
} from "common/Actions.sys.mjs";
|
||||
import {
|
||||
DiscoveryStreamAdminInner,
|
||||
CollapseToggle,
|
||||
DiscoveryStreamAdminUI,
|
||||
Personalization,
|
||||
ToggleStoryButton,
|
||||
} from "content-src/components/DiscoveryStreamAdmin/DiscoveryStreamAdmin";
|
||||
import React from "react";
|
||||
import { shallow } from "enzyme";
|
||||
|
||||
describe("DiscoveryStreamAdmin", () => {
|
||||
let sandbox;
|
||||
let wrapper;
|
||||
|
||||
beforeEach(() => {
|
||||
sandbox = sinon.createSandbox();
|
||||
wrapper = shallow(
|
||||
<DiscoveryStreamAdminInner
|
||||
collapsed={false}
|
||||
location={{ routes: [""] }}
|
||||
Prefs={{}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
afterEach(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
it("should render DiscoveryStreamAdmin component", () => {
|
||||
assert.ok(wrapper.exists());
|
||||
});
|
||||
it("should set a .collapsed class on the outer div if props.collapsed is true", () => {
|
||||
wrapper.setProps({ collapsed: true });
|
||||
assert.isTrue(wrapper.find(".discoverystream-admin").hasClass("collapsed"));
|
||||
});
|
||||
it("should set a .expanded class on the outer div if props.collapsed is false", () => {
|
||||
wrapper.setProps({ collapsed: false });
|
||||
assert.isTrue(wrapper.find(".discoverystream-admin").hasClass("expanded"));
|
||||
assert.isFalse(
|
||||
wrapper.find(".discoverystream-admin").hasClass("collapsed")
|
||||
);
|
||||
});
|
||||
it("should render a DS section", () => {
|
||||
assert.equal(wrapper.find("h1").at(0).text(), "Discovery Stream Admin");
|
||||
});
|
||||
|
||||
describe("#DiscoveryStream", () => {
|
||||
let state = {};
|
||||
let dispatch;
|
||||
beforeEach(() => {
|
||||
dispatch = sandbox.stub();
|
||||
state = {
|
||||
config: {
|
||||
enabled: true,
|
||||
},
|
||||
layout: [],
|
||||
spocs: {
|
||||
frequency_caps: [],
|
||||
},
|
||||
feeds: {
|
||||
data: {},
|
||||
},
|
||||
};
|
||||
wrapper = shallow(
|
||||
<DiscoveryStreamAdminUI
|
||||
dispatch={dispatch}
|
||||
otherPrefs={{}}
|
||||
state={{
|
||||
DiscoveryStream: state,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
it("should render a DiscoveryStreamAdminUI component", () => {
|
||||
assert.equal(wrapper.find("h3").at(0).text(), "Layout");
|
||||
});
|
||||
it("should render a spoc in DiscoveryStreamAdminUI component", () => {
|
||||
state.spocs = {
|
||||
frequency_caps: [],
|
||||
data: {
|
||||
spocs: {
|
||||
items: [
|
||||
{
|
||||
id: 12345,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
wrapper = shallow(
|
||||
<DiscoveryStreamAdminUI
|
||||
otherPrefs={{}}
|
||||
state={{ DiscoveryStream: state }}
|
||||
/>
|
||||
);
|
||||
wrapper.instance().onStoryToggle({ id: 12345 });
|
||||
const messageSummary = wrapper.find(".message-summary").at(0);
|
||||
const pre = messageSummary.find("pre").at(0);
|
||||
const spocText = pre.text();
|
||||
assert.equal(spocText, '{\n "id": 12345\n}');
|
||||
});
|
||||
it("should fire restorePrefDefaults with DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS", () => {
|
||||
wrapper.find("button").at(0).simulate("click");
|
||||
assert.calledWith(
|
||||
dispatch,
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS,
|
||||
})
|
||||
);
|
||||
});
|
||||
it("should fire config change with DISCOVERY_STREAM_CONFIG_CHANGE", () => {
|
||||
wrapper.find("button").at(1).simulate("click");
|
||||
assert.calledWith(
|
||||
dispatch,
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_CONFIG_CHANGE,
|
||||
data: { enabled: true },
|
||||
})
|
||||
);
|
||||
});
|
||||
it("should fire expireCache with DISCOVERY_STREAM_DEV_EXPIRE_CACHE", () => {
|
||||
wrapper.find("button").at(2).simulate("click");
|
||||
assert.calledWith(
|
||||
dispatch,
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_DEV_EXPIRE_CACHE,
|
||||
})
|
||||
);
|
||||
});
|
||||
it("should fire systemTick with DISCOVERY_STREAM_DEV_SYSTEM_TICK", () => {
|
||||
wrapper.find("button").at(3).simulate("click");
|
||||
assert.calledWith(
|
||||
dispatch,
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_DEV_SYSTEM_TICK,
|
||||
})
|
||||
);
|
||||
});
|
||||
it("should fire idleDaily with DISCOVERY_STREAM_DEV_IDLE_DAILY", () => {
|
||||
wrapper.find("button").at(4).simulate("click");
|
||||
assert.calledWith(
|
||||
dispatch,
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_DEV_IDLE_DAILY,
|
||||
})
|
||||
);
|
||||
});
|
||||
it("should fire syncRemoteSettings with DISCOVERY_STREAM_DEV_SYNC_RS", () => {
|
||||
wrapper.find("button").at(5).simulate("click");
|
||||
assert.calledWith(
|
||||
dispatch,
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_DEV_SYNC_RS,
|
||||
})
|
||||
);
|
||||
});
|
||||
it("should fire setConfigValue with DISCOVERY_STREAM_CONFIG_SET_VALUE", () => {
|
||||
const name = "name";
|
||||
const value = "value";
|
||||
wrapper.instance().setConfigValue(name, value);
|
||||
assert.calledWith(
|
||||
dispatch,
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_CONFIG_SET_VALUE,
|
||||
data: { name, value },
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#Personalization", () => {
|
||||
let dispatch;
|
||||
beforeEach(() => {
|
||||
dispatch = sandbox.stub();
|
||||
wrapper = shallow(
|
||||
<Personalization
|
||||
dispatch={dispatch}
|
||||
state={{
|
||||
Personalization: {
|
||||
lastUpdated: 1000,
|
||||
initialized: true,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
it("should render with pref checkbox, lastUpdated, and initialized", () => {
|
||||
assert.lengthOf(wrapper.find("TogglePrefCheckbox"), 1);
|
||||
assert.equal(
|
||||
wrapper.find("td").at(1).text(),
|
||||
"Personalization Last Updated"
|
||||
);
|
||||
assert.equal(
|
||||
wrapper.find("td").at(2).text(),
|
||||
new Date(1000).toLocaleString()
|
||||
);
|
||||
assert.equal(
|
||||
wrapper.find("td").at(3).text(),
|
||||
"Personalization Initialized"
|
||||
);
|
||||
assert.equal(wrapper.find("td").at(4).text(), "true");
|
||||
});
|
||||
it("should render with no data with no last updated", () => {
|
||||
wrapper = shallow(
|
||||
<Personalization
|
||||
dispatch={dispatch}
|
||||
state={{
|
||||
Personalization: {
|
||||
version: 2,
|
||||
lastUpdated: 0,
|
||||
initialized: true,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
assert.equal(wrapper.find("td").at(2).text(), "(no data)");
|
||||
});
|
||||
it("should dispatch DISCOVERY_STREAM_PERSONALIZATION_TOGGLE", () => {
|
||||
wrapper.instance().togglePersonalization();
|
||||
assert.calledWith(
|
||||
dispatch,
|
||||
ac.OnlyToMain({
|
||||
type: at.DISCOVERY_STREAM_PERSONALIZATION_TOGGLE,
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#ToggleStoryButton", () => {
|
||||
it("should fire onClick in toggle button", async () => {
|
||||
let result = "";
|
||||
function onClick(spoc) {
|
||||
result = spoc;
|
||||
}
|
||||
|
||||
wrapper = shallow(<ToggleStoryButton story="spoc" onClick={onClick} />);
|
||||
wrapper.find("button").simulate("click");
|
||||
|
||||
assert.equal(result, "spoc");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("CollapseToggle", () => {
|
||||
let wrapper;
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(<CollapseToggle location={{ routes: [""] }} />);
|
||||
});
|
||||
|
||||
describe("rendering inner content", () => {
|
||||
it("should not render DiscoveryStreamAdminInner for about:newtab (no hash)", () => {
|
||||
wrapper.setProps({ location: { hash: "", routes: [""] } });
|
||||
assert.lengthOf(wrapper.find(DiscoveryStreamAdminInner), 0);
|
||||
});
|
||||
|
||||
it("should render DiscoveryStreamAdminInner for about:newtab#devtools and subroutes", () => {
|
||||
wrapper.setProps({ location: { hash: "#devtools", routes: [""] } });
|
||||
assert.lengthOf(wrapper.find(DiscoveryStreamAdminInner), 1);
|
||||
|
||||
wrapper.setProps({ location: { hash: "#devtools-foo", routes: [""] } });
|
||||
assert.lengthOf(wrapper.find(DiscoveryStreamAdminInner), 1);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -4,9 +4,6 @@ build/vs/vs2022.yaml
|
|||
browser/components/aboutwelcome/content/aboutwelcome.bundle.js
|
||||
browser/components/aboutwelcome/logs/
|
||||
browser/components/aboutwelcome/node_modules/
|
||||
browser/components/asrouter/node_modules/
|
||||
browser/components/asrouter/content/asrouter-admin.bundle.js
|
||||
browser/components/asrouter/logs/
|
||||
browser/components/newtab/content-src/asrouter/schemas/BackgroundTaskMessagingExperiment.schema.json
|
||||
browser/components/newtab/content-src/asrouter/schemas/MessagingExperiment.schema.json
|
||||
browser/components/newtab/logs/
|
||||
|
|
Загрузка…
Ссылка в новой задаче