Bug 1566011 Create sub component for manifestItem (part 2), r=ladybenko,fluent-reviewers,flod

Differential Revision: https://phabricator.services.mozilla.com/D41909

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Ola Gasidlo 2019-08-21 08:39:11 +00:00
Родитель 1804529943
Коммит df494998bb
25 изменённых файлов: 737 добавлений и 49 удалений

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

@ -11,7 +11,8 @@
* Components
*/
@import "resource://devtools/client/application/src/components/App.css";
@import "resource://devtools/client/application/src/components/manifest/ManifestPage.css";
@import "resource://devtools/client/application/src/components/manifest/ManifestView.css";
@import "resource://devtools/client/application/src/components/routing/PageSwitcher.css";
@import "resource://devtools/client/application/src/components/service-workers/Worker.css";
@import "resource://devtools/client/application/src/components/service-workers/WorkerList.css";
@import "resource://devtools/client/application/src/components/service-workers/WorkerListEmpty.css";

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

@ -12,6 +12,8 @@
--body-20-font-size: 15px;
--body-20-font-weight: 400;
--body-20-font-weight-bold: 700;
--title-10-font-size: 13px;
--title-10-font-weight: 400;
--title-20-font-size: 17px;
--title-20-font-weight: 600;
--title-30-font-size: 22px;

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

@ -0,0 +1,36 @@
/* 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";
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { PureComponent } = require("devtools/client/shared/vendor/react");
const {
tr,
td,
th,
} = require("devtools/client/shared/vendor/react-dom-factories");
/**
* This component
*/
class ManifestItemIcon extends PureComponent {
static get propTypes() {
return {
icon: PropTypes.object.isRequired,
};
}
render() {
const { icon } = this.props;
return tr(
{ className: "manifest-view__row" },
th({ className: "manifest-view__col-label", scope: "row" }, icon.size),
td({ className: "manifest-view__col-value" }, icon.src)
);
}
}
// Exports
module.exports = ManifestItemIcon;

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

@ -0,0 +1,37 @@
/* 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";
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { PureComponent } = require("devtools/client/shared/vendor/react");
const {
tr,
td,
th,
} = require("devtools/client/shared/vendor/react-dom-factories");
/**
* This component
*/
class ManifestItemText extends PureComponent {
static get propTypes() {
return {
name: PropTypes.string.isRequired,
val: PropTypes.string.isRequired,
};
}
render() {
const { name, val } = this.props;
return tr(
{ className: "manifest-view__row" },
th({ className: "manifest-view__col-label", scope: "row" }, name),
td({ className: "manifest-view__col-value" }, val)
);
}
}
// Exports
module.exports = ManifestItemText;

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

@ -0,0 +1,43 @@
/* 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";
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { PureComponent } = require("devtools/client/shared/vendor/react");
const {
tr,
td,
th,
img,
} = require("devtools/client/shared/vendor/react-dom-factories");
/**
* This component
*/
class ManifestItemWarning extends PureComponent {
static get propTypes() {
return {
warning: PropTypes.object.isRequired,
};
}
render() {
const { warning } = this.props;
return tr(
{ className: "manifest-view__row manifest-view__row-error" },
th(
{ className: "manifest-view__col-label", scope: "row" },
img({
src: "chrome://global/skin/icons/warning.svg",
alt: "Warning icon",
})
),
td({ className: "manifest-view__col-value" }, warning.warn)
);
}
}
// Exports
module.exports = ManifestItemWarning;

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

@ -14,9 +14,46 @@ const {
const ManifestLoader = createFactory(require("../manifest/ManifestLoader"));
const ManifestView = createFactory(require("./ManifestView"));
const ManifestViewEmpty = createFactory(require("./ManifestViewEmpty"));
const { MANIFEST_DATA } = require("../../constants");
class ManifestPage extends PureComponent {
render() {
return section({ className: `manifest-page` }, ManifestLoader({}));
const isManifestViewEmpty = !MANIFEST_DATA;
// needs to be replaced with data from ManifestLoader
const data = {
warnings: MANIFEST_DATA.moz_validation,
icons: MANIFEST_DATA.icons,
identity: {
name: MANIFEST_DATA.name,
short_name: MANIFEST_DATA.short_name,
},
presentation: {
display: MANIFEST_DATA.display,
orientation: MANIFEST_DATA.orientation,
start_url: MANIFEST_DATA.start_url,
theme_color: MANIFEST_DATA.theme_color,
background_color: MANIFEST_DATA.background_color,
},
};
return section(
{
className: `app-page ${isManifestViewEmpty ? "app-page--empty" : ""}`,
},
ManifestLoader({}),
isManifestViewEmpty
? ManifestViewEmpty({})
: ManifestView({
identity: data.identity,
warnings: data.warnings,
icons: data.icons,
presentation: data.presentation,
})
);
}
}

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

@ -0,0 +1,41 @@
/* 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/. */
.manifest-view {
padding: calc(var(--base-unit) * 2) calc(var(--base-unit) * 4);
border-bottom: 1px solid var(--grey-20);
display: table;
width: 100%;
}
.manifest-view:last-child {
border-bottom: 0;
}
.manifest-view__title {
font-size: var(--title-10-font-size);
font-weight: var(--title-20-font-weight);
text-align: left;
padding: calc(var(--base-unit) * 2) 0;
}
.manifest-view__row {
vertical-align: top;
}
.manifest-view__col-label {
color: var(--grey-50);
font-weight: var(--title-30-font-weight);
width: calc(var(--base-unit) * 28);
text-align: right;
}
.manifest-view__col-value {
word-break: break-all;
}
.manifest-view__row-error .manifest-view__col-label {
width: calc(var(--base-unit) * 6);
text-align: left;
}

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

@ -0,0 +1,106 @@
/* 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";
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const {
createFactory,
PureComponent,
} = require("devtools/client/shared/vendor/react");
const {
article,
caption,
h1,
table,
tbody,
} = require("devtools/client/shared/vendor/react-dom-factories");
const FluentReact = require("devtools/client/shared/vendor/fluent-react");
const Localized = createFactory(FluentReact.Localized);
const ManifestItemIcon = createFactory(require("./ManifestItemIcon"));
const ManifestItemText = createFactory(require("./ManifestItemText"));
const ManifestItemWarning = createFactory(require("./ManifestItemWarning"));
/**
* This component
*/
class ManifestView extends PureComponent {
static get propTypes() {
return {
identity: PropTypes.object.isRequired,
warnings: PropTypes.array.isRequired,
icons: PropTypes.array.isRequired,
presentation: PropTypes.object.isRequired,
};
}
render() {
const { identity, warnings, icons, presentation } = this.props;
return article(
{},
Localized(
{
id: "manifest-view-header",
},
h1({ className: "app-page__title" })
),
table(
{ className: "manifest-view", key: "errors-and-warnings" },
Localized(
{ id: "manifest-item-warnings" },
caption({ className: "manifest-view__title" })
),
tbody(
{},
warnings.map((warning, index) =>
ManifestItemWarning({ warning, key: `warning-${index}` })
)
)
),
table(
{ className: "manifest-view", key: "identity" },
Localized(
{ id: "manifest-item-identity" },
caption({ className: "manifest-view__title" })
),
tbody(
{},
Object.entries(identity).map(([key, value]) =>
ManifestItemText({ name: key, val: value, key: `${key}` })
)
)
),
table(
{ className: "manifest-view", key: "presentation" },
Localized(
{ id: "manifest-item-presentation" },
caption({ className: "manifest-view__title" })
),
tbody(
{},
Object.entries(presentation).map(([key, value]) =>
ManifestItemText({ name: key, val: value, key: `${key}` })
)
)
),
table(
{ className: "manifest-view", key: "icons" },
Localized(
{ id: "manifest-item-icons" },
caption({ className: "manifest-view__title" })
),
tbody(
{},
icons.map((icon, index) =>
ManifestItemIcon({ icon, key: `warning-${index}` })
)
)
)
);
}
}
// Exports
module.exports = ManifestView;

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

@ -0,0 +1,40 @@
/* 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";
const {
createFactory,
PureComponent,
} = require("devtools/client/shared/vendor/react");
const {
article,
h1,
p,
} = require("devtools/client/shared/vendor/react-dom-factories");
const FluentReact = require("devtools/client/shared/vendor/fluent-react");
const Localized = createFactory(FluentReact.Localized);
/**
* This component displays help information when no manifest is found for the
* current target.
*/
class ManifestViewEmpty extends PureComponent {
render() {
return article(
{ className: "manifest-view-empty" },
Localized(
{
id: "manifest-view-header",
},
h1({ className: "app-page__title" })
),
Localized({ id: "manifest-empty-intro" }, p({}))
);
}
}
// Exports
module.exports = ManifestViewEmpty;

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

@ -3,7 +3,12 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
'ManifestItemIcon.js',
'ManifestItemText.js',
'ManifestItemWarning.js',
'ManifestLoader.js',
'ManifestPage.css',
'ManifestPage.js'
'ManifestPage.js',
'ManifestView.css',
'ManifestView.js',
'ManifestViewEmpty.js'
)

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

@ -2,15 +2,28 @@
* 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/. */
.manifest-page {
height: 100vh;
/*
* Page container for worker + manifest views
*/
.app-page {
height: 100vh;
padding: 0 2rem;
display: grid;
grid-template-rows: 1fr auto;
-moz-user-select: none;
}
/* slipt up in components in https://bugzilla.mozilla.org/show_bug.cgi?id=1566011 */
.app-page--empty {
align-items: center;
justify-content: center;
font-size: var(--title-10-font-size);
font-size: var(--body-10-font-size);
color: var(--theme-toolbar-color);
}
.app-page__title {
font-size: var(--title-30-font-size);
font-weight: var(--title-30-font-weight);
margin: 0;
}

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

@ -3,5 +3,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
'PageSwitcher.css',
'PageSwitcher.js',
)

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

@ -2,18 +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/. */
.worker-list-empty {
max-width: calc(var(--base-unit) * 179);
font-size: var(--body-10-font-size);
color: var(--theme-toolbar-color);
}
.worker-list-empty__title {
font-size: var(--title-20-font-size);
font-weight: var(--title-20-font-weight);
}
.worker-list-empty__title .external-link {
.app-page__title .external-link {
font-weight: var(--title-30-font-weight);
}

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

@ -12,6 +12,7 @@ const {
const {
a,
article,
h1,
li,
p,
ul,
@ -58,7 +59,7 @@ class WorkerListEmpty extends PureComponent {
onClick: () => this.openDocumentation(),
}),
},
p({ className: "worker-list-empty__title" })
h1({ className: "app-page__title" })
),
Localized({ id: "serviceworker-empty-suggestions" }, p({})),
ul(

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

@ -15,18 +15,3 @@
* | Link to about:debugging |
* +---------------------------------------------+
*/
.workers-page {
height: 100vh;
padding: 0 2rem;
display: grid;
-moz-user-select: none;
}
.workers-page--empty {
align-items: center;
justify-content: center;
}
.workers-page:not(.workers-page--empty) {
grid-template-rows: 1fr auto;
}

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

@ -38,9 +38,7 @@ class WorkersPage extends PureComponent {
return section(
{
className: `workers-page ${
isWorkerListEmpty ? "workers-page--empty" : ""
}`,
className: `app-page ${isWorkerListEmpty ? "app-page--empty" : ""}`,
},
isWorkerListEmpty
? WorkerListEmpty({})

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

@ -23,5 +23,51 @@ const PAGE_TYPES = {
const DEFAULT_PAGE = PAGE_TYPES.MANIFEST;
const MANIFEST_DATA = {
background_color: "#F9D",
dir: "auto",
display: "browser",
icons: [
{
src:
"https://design.firefox.com/icons/icons/desktop/default-browser-16.svg",
type: "type/png",
size: "16x16",
},
{
src:
"https://design.firefox.com/icons/icons/desktop/default-browser-16.svg",
type: "type/png",
size: "32x32",
},
{
src:
"https://design.firefox.com/icons/icons/desktop/default-browser-16.svg",
type: "type/png",
size: "64x64",
},
],
lang: "en-US",
moz_manifest_url: "",
moz_validation: [
{ warn: "Icons item at index 0 is invalid." },
{
warn:
"Icons item at index 2 is invalid. Icons item at index 2 is invalid. Icons item at index 2 is invalid. Icons item at index 2 is invalid.",
},
],
name:
"Name is a verrry long name and the name is longer tha you thinnk because it is loooooooooooooooooooooooooooooooooooooooooooooooong",
orientation: "landscape",
scope: "./",
short_name: "Na",
start_url: "root",
theme_color: "#345",
};
// flatten constants
module.exports = Object.assign({}, { DEFAULT_PAGE, PAGE_TYPES }, actionTypes);
module.exports = Object.assign(
{},
{ DEFAULT_PAGE, PAGE_TYPES, MANIFEST_DATA },
actionTypes
);

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

@ -2,8 +2,54 @@
exports[`ManifestPage renders the expected snapshot 1`] = `
<section
className="manifest-page"
className="app-page "
>
<Connect(ManifestLoader) />
<ManifestView
icons={
Array [
Object {
"size": "16x16",
"src": "https://design.firefox.com/icons/icons/desktop/default-browser-16.svg",
"type": "type/png",
},
Object {
"size": "32x32",
"src": "https://design.firefox.com/icons/icons/desktop/default-browser-16.svg",
"type": "type/png",
},
Object {
"size": "64x64",
"src": "https://design.firefox.com/icons/icons/desktop/default-browser-16.svg",
"type": "type/png",
},
]
}
identity={
Object {
"name": "Name is a verrry long name and the name is longer tha you thinnk because it is loooooooooooooooooooooooooooooooooooooooooooooooong",
"short_name": "Na",
}
}
presentation={
Object {
"background_color": "#F9D",
"display": "browser",
"orientation": "landscape",
"start_url": "root",
"theme_color": "#345",
}
}
warnings={
Array [
Object {
"warn": "Icons item at index 0 is invalid.",
},
Object {
"warn": "Icons item at index 2 is invalid. Icons item at index 2 is invalid. Icons item at index 2 is invalid. Icons item at index 2 is invalid.",
},
]
}
/>
</section>
`;

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

@ -0,0 +1,150 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ManifestView renders the expected snapshot 1`] = `
<article>
<Localized
id="manifest-view-header"
>
<h1
className="app-page__title"
/>
</Localized>
<table
className="manifest-view"
key="errors-and-warnings"
>
<Localized
id="manifest-item-warnings"
>
<caption
className="manifest-view__title"
/>
</Localized>
<tbody>
<ManifestItemWarning
key="warning-0"
warning={
Object {
"warn": "Icons item at index 0 is invalid.",
}
}
/>
<ManifestItemWarning
key="warning-1"
warning={
Object {
"warn": "Icons item at index 2 is invalid. Icons item at index 2 is invalid. Icons item at index 2 is invalid. Icons item at index 2 is invalid.",
}
}
/>
</tbody>
</table>
<table
className="manifest-view"
key="identity"
>
<Localized
id="manifest-item-identity"
>
<caption
className="manifest-view__title"
/>
</Localized>
<tbody>
<ManifestItemText
key="name"
name="name"
val="Name is a verrry long name and the name is longer tha you thinnk because it is loooooooooooooooooooooooooooooooooooooooooooooooong"
/>
<ManifestItemText
key="short_name"
name="short_name"
val="Na"
/>
</tbody>
</table>
<table
className="manifest-view"
key="presentation"
>
<Localized
id="manifest-item-presentation"
>
<caption
className="manifest-view__title"
/>
</Localized>
<tbody>
<ManifestItemText
key="display"
name="display"
val="browser"
/>
<ManifestItemText
key="orientation"
name="orientation"
val="landscape"
/>
<ManifestItemText
key="start_url"
name="start_url"
val="root"
/>
<ManifestItemText
key="theme_color"
name="theme_color"
val="#345"
/>
<ManifestItemText
key="background_color"
name="background_color"
val="#F9D"
/>
</tbody>
</table>
<table
className="manifest-view"
key="icons"
>
<Localized
id="manifest-item-icons"
>
<caption
className="manifest-view__title"
/>
</Localized>
<tbody>
<ManifestItemIcon
icon={
Object {
"size": "16x16",
"src": "https://design.firefox.com/icons/icons/desktop/default-browser-16.svg",
"type": "type/png",
}
}
key="warning-0"
/>
<ManifestItemIcon
icon={
Object {
"size": "32x32",
"src": "https://design.firefox.com/icons/icons/desktop/default-browser-16.svg",
"type": "type/png",
}
}
key="warning-1"
/>
<ManifestItemIcon
icon={
Object {
"size": "64x64",
"src": "https://design.firefox.com/icons/icons/desktop/default-browser-16.svg",
"type": "type/png",
}
}
key="warning-2"
/>
</tbody>
</table>
</article>
`;

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

@ -0,0 +1,20 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ManifestViewEmpty renders the expected snapshot 1`] = `
<article
className="manifest-view-empty"
>
<Localized
id="manifest-view-header"
>
<h1
className="app-page__title"
/>
</Localized>
<Localized
id="manifest-empty-intro"
>
<p />
</Localized>
</article>
`;

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

@ -0,0 +1,49 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Import libs
const { shallow } = require("enzyme");
const { createFactory } = require("react");
const ManifestView = createFactory(
require("devtools/client/application/src/components/manifest/ManifestView")
);
const { MANIFEST_DATA } = require("../../../src/constants");
// needs to move to reducer
const data = {
warnings: MANIFEST_DATA.moz_validation,
icons: MANIFEST_DATA.icons,
identity: {
name: MANIFEST_DATA.name,
short_name: MANIFEST_DATA.short_name,
},
presentation: {
display: MANIFEST_DATA.display,
orientation: MANIFEST_DATA.orientation,
start_url: MANIFEST_DATA.start_url,
theme_color: MANIFEST_DATA.theme_color,
background_color: MANIFEST_DATA.background_color,
},
};
/**
* Test for ManifestView.js component
*/
describe("ManifestView", () => {
it("renders the expected snapshot", () => {
const wrapper = shallow(
ManifestView({
identity: data.identity,
warnings: data.warnings,
icons: data.icons,
presentation: data.presentation,
})
);
expect(wrapper).toMatchSnapshot();
});
});

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

@ -0,0 +1,23 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Import libs
const { shallow } = require("enzyme");
const { createFactory } = require("react");
const ManifestViewEmpty = createFactory(
require("devtools/client/application/src/components/manifest/ManifestViewEmpty")
);
/**
* Test for ManifestPage.js component
*/
describe("ManifestViewEmpty", () => {
it("renders the expected snapshot", () => {
const wrapper = shallow(ManifestViewEmpty({}));
expect(wrapper).toMatchSnapshot();
});
});

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

@ -13,8 +13,8 @@ exports[`WorkerListEmpty renders the expected snapshot 1`] = `
}
id="serviceworker-empty-intro"
>
<p
className="worker-list-empty__title"
<h1
className="app-page__title"
/>
</Localized>
<Localized

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

@ -2,7 +2,7 @@
exports[`WorkersPage filters out workers from diferent domains 1`] = `
<section
className="workers-page "
className="app-page "
>
<WorkerList
canDebugWorkers={true}
@ -32,7 +32,7 @@ exports[`WorkersPage filters out workers from diferent domains 1`] = `
exports[`WorkersPage filters out workers from different domains and renders an empty list when there is none left 1`] = `
<section
className="workers-page workers-page--empty"
className="app-page app-page--empty"
>
<WorkerListEmpty />
</section>
@ -40,7 +40,7 @@ exports[`WorkersPage filters out workers from different domains and renders an e
exports[`WorkersPage it renders a list with a single element if there's just 1 worker 1`] = `
<section
className="workers-page "
className="app-page "
>
<WorkerList
canDebugWorkers={true}
@ -62,7 +62,7 @@ exports[`WorkersPage it renders a list with a single element if there's just 1 w
exports[`WorkersPage renders a list with multiple elements when there are multiple workers 1`] = `
<section
className="workers-page "
className="app-page "
>
<WorkerList
canDebugWorkers={true}
@ -100,7 +100,7 @@ exports[`WorkersPage renders a list with multiple elements when there are multip
exports[`WorkersPage renders an empty list if there are no workers 1`] = `
<section
className="workers-page workers-page--empty"
className="app-page app-page--empty"
>
<WorkerListEmpty />
</section>

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

@ -80,6 +80,24 @@ serviceworker-empty-suggestions-debugger = Step through your Service Worker regi
# Clicking on the link will open about:debugging in a new tab.
serviceworker-empty-suggestions-aboutdebugging = Inspect Service Workers from other domains. <a>Open about:debugging</a>
# Header for the view of Manifest displayed in the application panel for the current page.
manifest-view-header = App Manifest
# Header for the Errors and Warnings section of Manifest inspection displayed in the application panel.
manifest-item-warnings = Errors and Warnings
# Header for the Identity section of Manifest inspection displayed in the application panel.
manifest-item-identity = Identity
# Header for the Presentation section of Manifest inspection displayed in the application panel.
manifest-item-presentation = Presentation
# Header for the Icon section of Manifest inspection displayed in the application panel.
manifest-item-icons = Icons
# Text displayed when no manifest was found for the current page.
manifest-empty-intro = No manifest found to inspect.
# Text displayed while we are loading the manifest file
manifest-loading = Loading manifest…
@ -91,3 +109,4 @@ manifest-loaded-error = There was an error while loading the manifest:
# Text displayed when the page has no manifest available
manifest-non-existing = No manifest found to inspect.