Commit 7002b595 authored by Laurent Wouters's avatar Laurent Wouters
Browse files

[feature] Implementing options page for the extension

parent aff0cd8e3d8f
/*******************************************************************************
* Copyright 2003-2018 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
* contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
*
* This file is part of CubicWeb.
*
* CubicWeb is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 2.1 of the License, or (at your option)
* any later version.
*
* CubicWeb is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
import React = require("react");
import { definition, application } from "@logilab/libview";
import {
ResourceData,
selectPrimaryTopic,
getSourcesFor,
DocumentSource
} from "../data";
import * as LANGUAGES from "../data.iso639.json";
export interface ConfigCurrentTabProps {
data: ResourceData;
registry: definition.ViewRegistry;
onPaneSources: () => void;
onTunOff: () => void;
onTabCommandAutomatic: (event: React.FormEvent<HTMLInputElement>) => void;
onTabCommandClearTopic: () => void;
onTabCommandSelectView: (event: React.FormEvent<HTMLSelectElement>) => void;
onTabCommandSelectLanguage: (
event: React.FormEvent<HTMLSelectElement>
) => void;
}
export class ConfigCurrentTab extends React.Component<
ConfigCurrentTabProps,
{}
> {
constructor(props: ConfigCurrentTabProps) {
super(props);
}
render() {
let isTopicOnAuto =
this.props.data.command.isAutomatic ||
this.props.data.command.selectedTopic == null;
let topic = selectPrimaryTopic(this.props.data);
return (
<div className="container-fluid">
<div className="row">
<div className="col-2">
<a
className="btn btn-outline-light"
onClick={this.props.onPaneSources}
title="Configuration"
>
<span style={{ fontSize: "20pt", cursor: "pointer" }}>
<img width="24px" src="../icons/settings.svg" />
</span>
</a>
</div>
<div className="col-2">
<a
className="btn btn-outline-light"
onClick={this.props.onTunOff}
title="Turn off on this tab"
>
<span style={{ fontSize: "20pt", cursor: "pointer" }}>
<img width="24px" src="../icons/off.svg" />
</span>
</a>
</div>
<div className="col-2" />
<div className="col-6">
<span style={{ fontSize: "17pt" }}>Current tab</span>
</div>
</div>
<hr />
<div className="row">
<div className="col-4">
<label>Auto config</label>
</div>
<div className="col-8">
<label className="switch">
<input
type="checkbox"
id="fiedAuto"
checked={this.props.data.command.isAutomatic}
onChange={this.props.onTabCommandAutomatic}
style={{ width: "250px" }}
/>
<span className="slider round" />
</label>
</div>
</div>
<div className="row">
<div className="col-4">
<label>Primary topic</label>
</div>
<div className="col-8">
{!isTopicOnAuto ? (
<div>
<a
className="btn btn-outline-light"
onClick={this.props.onTabCommandClearTopic}
title="Clear selected topic"
>
<span
style={{
fontSize: "10pt",
cursor: "pointer",
color: "red"
}}
>
clear
</span>
</a>
</div>
) : (
<div />
)}
<div>
{topic.uris.map((uri: string, index: number) => (
<div key={"topic-" + index}>
<a href={uri} title={uri}>
{uri}
</a>
</div>
))}
</div>
</div>
</div>
<div className="row">
<div className="col-4">
<label>View</label>
</div>
<div className="col-8">
<select
className="form-control"
id="fiedView"
disabled={this.props.data.command.isAutomatic}
onChange={this.props.onTabCommandSelectView}
value={this.props.data.command.selectedView}
style={{ width: "250px" }}
>
<option key={"view-default"} value="">
{"-- auto --"}
</option>
{Object.keys(this.props.registry.descriptors)
.map((key: string) => this.props.registry.descriptors[key])
.sort(
(
a: definition.ViewDescriptor,
b: definition.ViewDescriptor
): number => a.name.localeCompare(b.name)
)
.map((descriptor: definition.ViewDescriptor, index: number) => {
return (
<option key={"view-" + index} value={descriptor.identifier}>
{descriptor.name + " (" + descriptor.identifier + ")"}
</option>
);
})}
</select>
</div>
</div>
<div className="row">
<div className="col-4">
<label>Language</label>
</div>
<div className="col-8">
<select
className="form-control"
id="fieldLanguage"
disabled={this.props.data.command.isAutomatic}
onChange={this.props.onTabCommandSelectLanguage}
value={this.props.data.command.selectedLanguage.iso639_1}
style={{ width: "250px" }}
>
<option key={"view-default"} value="">
{"-- auto --"}
</option>
{LANGUAGES.sort(
(a: application.Language, b: application.Language) =>
a.name.localeCompare(b.name)
).map((language: application.Language, index: number) => {
return (
<option key={"language-" + index} value={language.iso639_1}>
{language.name + " (" + language.iso639_2 + ")"}
</option>
);
})}
</select>
</div>
</div>
<hr />
<div className="row">
<div className="col-12">Detected sources of data</div>
</div>
{getSourcesFor(this.props.data).map(
(series: DocumentSource[], index: number) => (
<div key={"series-" + index} style={{ marginTop: "10px" }}>
{series.map((source: DocumentSource, index: number) => (
<div key={"source-" + index} className="row">
<div className="col-12">
{index > 0 ? (
<span title="Fallback source">
{"\u00A0\u00A0\u00A0\u00A0\u21B3"}
</span>
) : (
<span title="Series head">{"\u25BA"}</span>
)}
{source.name}
</div>
</div>
))}
</div>
)
)}
<hr />
<div className="row">
<div className="col-12">Supplementary resources</div>
</div>
{this.props.data.supplements.map(
(supplement: application.Resource, index: number) => (
<div key={"supplement-" + index} style={{ marginTop: "10px" }}>
{supplement.uris.map((uri: string, index: number) => (
<div key={"uri-" + index} className="row">
<div className="col-12">
<a href={uri} title={uri}>
{uri}
</a>
</div>
</div>
))}
</div>
)
)}
</div>
);
}
}
/*******************************************************************************
* Copyright 2003-2018 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
* contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
*
* This file is part of CubicWeb.
*
* CubicWeb is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 2.1 of the License, or (at your option)
* any later version.
*
* CubicWeb is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
import React = require("react");
export class ConfigLoading extends React.Component {
render() {
return (
<div
style={{
width: "90%",
marginLeft: "5%",
marginTop: "5vh",
marginBottom: "5vh"
}}
>
<div className="alert alert-info" role="alert">
Loading
</div>
</div>
);
}
}
/*******************************************************************************
* Copyright 2003-2018 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
* contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
*
* This file is part of CubicWeb.
*
* CubicWeb is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 2.1 of the License, or (at your option)
* any later version.
*
* CubicWeb is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
import React = require("react");
import { definition } from "@logilab/libview";
interface State {
registryNewSourceName: string;
registryNewSourceURI: string;
}
export interface ConfigSourcesTabProps {
displayBackToTab: boolean;
registry: definition.ViewRegistry;
onPaneTab: () => void;
onPaneViews: () => void;
onButtonReloadRegistry: () => void;
onRegistryAddSource: (name: string, uri: string) => void;
onRegistryRemoveSource: (index: number) => void;
}
export class ConfigSourcesTab extends React.Component<
ConfigSourcesTabProps,
State
> {
state: State;
constructor(props: ConfigSourcesTabProps) {
super(props);
this.onRegistryUpdateNewSourceName = this.onRegistryUpdateNewSourceName.bind(
this
);
this.onRegistryUpdateNewSourceUri = this.onRegistryUpdateNewSourceUri.bind(
this
);
this.state = {
registryNewSourceName: "",
registryNewSourceURI: ""
};
}
onRegistryUpdateNewSourceName(event: React.FormEvent<HTMLInputElement>) {
this.state.registryNewSourceName = event.currentTarget.value;
this.setState(this.state);
}
onRegistryUpdateNewSourceUri(event: React.FormEvent<HTMLInputElement>) {
this.state.registryNewSourceURI = event.currentTarget.value;
this.setState(this.state);
}
render() {
return (
<div className="container-fluid">
<div className="row">
{this.props.displayBackToTab ? (
<div className="col-2">
<a
className="btn btn-outline-light"
onClick={this.props.onPaneTab}
title="Back"
>
<span style={{ fontSize: "20pt", cursor: "pointer" }}>
<img width="24px" src="../icons/back.svg" />
</span>
</a>
</div>
) : (
<span />
)}
<div className="col-2">
<a
className="btn btn-outline-light"
onClick={this.props.onPaneViews}
title="Available views"
>
<span style={{ fontSize: "20pt", cursor: "pointer" }}>
<img width="24px" src="../icons/view.svg" />
</span>
</a>
</div>
<div className="col-2">
<a
className="btn btn-outline-light"
onClick={this.props.onButtonReloadRegistry}
title="Reload registry"
>
<span style={{ fontSize: "20pt", cursor: "pointer" }}>
<img width="24px" src="../icons/refresh.svg" />
</span>
</a>
</div>
{this.props.displayBackToTab ? <span /> : <div className="col-2" />}
<div className="col-6">
<span style={{ fontSize: "17pt" }}>Registered sources</span>
</div>
</div>
<hr />
<div className="row">
<div className="col-4">New source name:</div>
<div className="col-8">
<input
className="form-control"
onChange={this.onRegistryUpdateNewSourceName}
value={this.state.registryNewSourceName}
/>
</div>
</div>
<div className="row">
<div className="col-4">New source URI:</div>
<div className="col-8">
<input
className="form-control"
onChange={this.onRegistryUpdateNewSourceUri}
value={this.state.registryNewSourceURI}
/>
</div>
</div>
<div className="row">
<div className="col-4" />
<div className="col-8">
<a
className="btn btn-primary"
onClick={() =>
this.props.onRegistryAddSource(
this.state.registryNewSourceName,
this.state.registryNewSourceURI
)
}
>
OK
</a>
</div>
</div>
<hr />
{this.props.registry.sources.map(
(source: definition.ViewRegistrySource, index: number) => {
return (
<div className="row" key={"source-" + index}>
<div className="col-2">
{source.kind != definition.ViewRegistrySourceKind.inline ? (
<a
className="btn btn-outline-light"
title="Remove this source"
>
<span
onClick={() => this.props.onRegistryRemoveSource(index)}
style={{ cursor: "pointer" }}
className="text-danger"
>
{"\u2716"}
</span>
</a>
) : (
<span />
)}
</div>
<div className="col-10">
<span>{source.name}</span>
{source.kind == definition.ViewRegistrySourceKind.remote ? (
<span>
{" : "}
<a
href={
(source as definition.ViewRegistrySourceRemote).uri
}
>
{(source as definition.ViewRegistrySourceRemote).uri}
</a>
</span>
) : (
<span />
)}
</div>
</div>
);
}
)}
</div>
);
}
}
/*******************************************************************************
* Copyright 2003-2018 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
* contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
*
* This file is part of CubicWeb.
*
* CubicWeb is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 2.1 of the License, or (at your option)
* any later version.
*
* CubicWeb is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
import React = require("react");
import { definition } from "@logilab/libview";
export interface ConfigViewsTabProps {
registry: definition.ViewRegistry;
onPaneSources: () => void;
onButtonReloadRegistry: () => void;
}
export class ConfigViewsTab extends React.Component<ConfigViewsTabProps, {}> {
constructor(props: ConfigViewsTabProps) {
super(props);
}
render() {
return (
<div className="container-fluid">
<div className="row">
<div className="col-2">
<a
className="btn btn-outline-light"
onClick={this.props.onPaneSources}
title="Back"
>
<span style={{ fontSize: "20pt", cursor: "pointer" }}>
<img width="24px" src="../icons/back.svg" />
</span>
</a>
</div>
<div className="col-2">
<a
className="btn btn-outline-light"
onClick={this.props.onButtonReloadRegistry}
title="Reload registry"
>
<span style={{ fontSize: "20pt", cursor: "pointer" }}>
<img width="24px" src="../icons/refresh.svg" />
</span>
</a>
</div>
<div className="col-2" />
<div className="col-6">
<span style={{ fontSize: "17pt" }}>Available views</span>
</div>
</div>
<hr />
{Object.keys(this.props.registry.descriptors)
.map((key: string) => this.props.registry.descriptors[key])
.sort(
(
a: definition.ViewDescriptor,
b: definition.ViewDescriptor
): number => a.identifier.localeCompare(b.identifier)
)
.map((descriptor: definition.ViewDescriptor, index: number) => {
return (
<div key={"descriptor-" + index} className="row">
<div className="col-6">
<span title={descriptor.description}>
{descriptor.identifier}
</span>
</div>
<div className="col-6">
<span title={descriptor.description}>{descriptor.name}</span>
</div>
</div>
);
})}
</div>
);
}
}
......@@ -27,13 +27,13 @@ import {
addViewSource,
removeViewSource
} from "../common/messages";
import { ConfigViewsTab } from "../common/config/ConfigViewsTab";