mirror of
https://github.com/collinbarrett/FilterLists.git
synced 2026-03-11 09:04:27 +00:00
resolve dependency issues
This commit is contained in:
parent
410004fa8a
commit
03153cd595
32 changed files with 454 additions and 399 deletions
BIN
src/web/package-lock.json
generated
BIN
src/web/package-lock.json
generated
Binary file not shown.
|
|
@ -7,9 +7,19 @@
|
|||
"@types/node": "12.6.8",
|
||||
"@types/react": "16.8.23",
|
||||
"@types/react-dom": "16.8.5",
|
||||
"@types/react-router-dom": "^4.3.4",
|
||||
"@types/react-table": "^6.8.5",
|
||||
"bootstrap": "^4.3.1",
|
||||
"es6-promise": "^4.2.8",
|
||||
"isomorphic-fetch": "^2.2.1",
|
||||
"jquery": "^3.4.1",
|
||||
"moment": "^2.24.0",
|
||||
"popper.js": "^1.15.0",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6",
|
||||
"react-router-dom": "^5.0.1",
|
||||
"react-scripts": "3.0.1",
|
||||
"react-table": "^6.10.0",
|
||||
"typescript": "3.5.3"
|
||||
},
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -1,33 +1,3 @@
|
|||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
animation: App-logo-spin infinite 20s linear;
|
||||
height: 40vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.App-header {
|
||||
background-color: #282c34;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.App-link {
|
||||
color: #61dafb;
|
||||
}
|
||||
|
||||
@keyframes App-logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
body, h2, h3, h4, h5, blockquote { font-size: 16px; }
|
||||
.container{ max-width:98vw!important;padding-left:7px!important }
|
||||
.w-100{ padding-left:7px!important }
|
||||
|
|
|
|||
|
|
@ -1,25 +1,12 @@
|
|||
import React from 'react';
|
||||
import logo from './logo.svg';
|
||||
import './App.css';
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import * as RoutesModule from "./Routes";
|
||||
|
||||
const App: React.FC = () => {
|
||||
// const baseUrl = document.getElementsByTagName("base")[0].getAttribute("href")!;
|
||||
return (
|
||||
<div className="App">
|
||||
<header className="App-header">
|
||||
<img src={logo} className="App-logo" alt="logo" />
|
||||
<p>
|
||||
Edit <code>src/App.tsx</code> and save to reload.
|
||||
</p>
|
||||
<a
|
||||
className="App-link"
|
||||
href="https://reactjs.org"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Learn React
|
||||
</a>
|
||||
</header>
|
||||
</div>
|
||||
<BrowserRouter children={RoutesModule.Routes} />
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
61
src/web/src/Layout.tsx
Normal file
61
src/web/src/Layout.tsx
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import * as React from "react";
|
||||
import "bootstrap";
|
||||
|
||||
interface IProps {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
export const Layout = (props: IProps) =>
|
||||
<div className="container">
|
||||
<Header/>
|
||||
<div className="row">
|
||||
<div className="w-100">
|
||||
{ props.children }
|
||||
</div>
|
||||
</div>
|
||||
<Footer/>
|
||||
</div>;
|
||||
|
||||
const Header = () =>
|
||||
<header className="row">
|
||||
<h1>
|
||||
<a href="./">
|
||||
<img src="logo_filterlists.png" alt="FilterLists" className="img-fluid"/>
|
||||
</a>
|
||||
</h1>
|
||||
</header>;
|
||||
|
||||
const Footer = () =>
|
||||
<footer className="row justify-content-center">
|
||||
<p className="mt-2 ml-1 mr-1">
|
||||
<HubLink/> | <GitHubLink/> | <ApiLink/> | <DonateLink/> | By <OwnerLink/>
|
||||
</p>
|
||||
</footer>;
|
||||
|
||||
const HubLink = () =>
|
||||
<a href="https://hub.filterlists.com"
|
||||
title="Discourse community forum">
|
||||
Hub
|
||||
</a>;
|
||||
|
||||
const GitHubLink = () =>
|
||||
<a href="https://github.com/collinbarrett/FilterLists">
|
||||
GitHub
|
||||
</a>;
|
||||
|
||||
const ApiLink = () =>
|
||||
<a href="/api/v1/lists"
|
||||
title="API lists endpoint">
|
||||
API
|
||||
</a>;
|
||||
|
||||
const DonateLink = () =>
|
||||
<a href="https://beerpay.io/collinbarrett/FilterLists"
|
||||
title="Support with Beerpay">
|
||||
Donate
|
||||
</a>;
|
||||
|
||||
const OwnerLink = () =>
|
||||
<a href="https://collinmbarrett.com/">
|
||||
Collin M. Barrett
|
||||
</a>;
|
||||
13
src/web/src/Routes.tsx
Normal file
13
src/web/src/Routes.tsx
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import * as React from "react";
|
||||
import { Layout } from "./Layout";
|
||||
import { Route, Redirect, Switch } from "react-router-dom";
|
||||
import { Home } from "./modules";
|
||||
|
||||
export const Routes = <Layout>
|
||||
<Switch>
|
||||
<Route exact path="/" component={Home}/>
|
||||
<Route>
|
||||
<Redirect to="/"/>
|
||||
</Route>
|
||||
</Switch>
|
||||
</Layout>;
|
||||
|
|
@ -1,5 +1,12 @@
|
|||
import * as React from "react";
|
||||
import { IColumnVisibility, ILanguage, ILicense, IList, IMaintainer, ISoftware, ISyntax, ITag } from "./interfaces";
|
||||
import { IColumnVisibility } from "./interfaces/IColumnVisibility";
|
||||
import { ILanguage } from "./interfaces/ILanguage";
|
||||
import { ILicense } from "./interfaces/ILicense";
|
||||
import { IList } from "./interfaces/IList";
|
||||
import { IMaintainer } from "./interfaces/IMaintainer";
|
||||
import { ISoftware } from "./interfaces/ISoftware";
|
||||
import { ISyntax } from "./interfaces/ISyntax";
|
||||
import { ITag } from "./interfaces/ITag";
|
||||
import { ListsTable, Oneliner } from "./components";
|
||||
|
||||
const columnVisibilityDefaults: IColumnVisibility[] = [
|
||||
|
|
@ -60,33 +67,33 @@ export class Home extends React.Component<IProps, IState> {
|
|||
|
||||
render() {
|
||||
return <div>
|
||||
<Oneliner listCount={this.props.lists.length}/* ruleCount={this.props.ruleCount}*//>
|
||||
<ListsTable {...this.props} {...this.state}/>
|
||||
{this.renderColumnVisibilityCheckboxes()}
|
||||
</div>;
|
||||
<Oneliner listCount={this.props.lists.length}/* ruleCount={this.props.ruleCount}*/ />
|
||||
<ListsTable {...this.props} {...this.state} />
|
||||
{this.renderColumnVisibilityCheckboxes()}
|
||||
</div>;
|
||||
};
|
||||
|
||||
renderColumnVisibilityCheckboxes() {
|
||||
return this.props.lists.length > 0
|
||||
? <div className="d-none d-md-block text-right">
|
||||
Visible: {this.state.columnVisibility.map(
|
||||
(c: IColumnVisibility, i: number) => this.renderColumnVisibilityCheckbox(c, i))}
|
||||
</div>
|
||||
: null;
|
||||
? <div className="d-none d-md-block text-right">
|
||||
Visible: {this.state.columnVisibility.map(
|
||||
(c: IColumnVisibility, i: number) => this.renderColumnVisibilityCheckbox(c, i))}
|
||||
</div>
|
||||
: null;
|
||||
};
|
||||
|
||||
renderColumnVisibilityCheckbox(props: IColumnVisibility, key: number) {
|
||||
return <div className="form-check form-check-inline" key={key}>
|
||||
<input className="form-check-input"
|
||||
type="checkbox"
|
||||
id={`checkbox${props.column.replace(/\s+/g, "")}`}
|
||||
defaultChecked={props.visible}
|
||||
onChange={() => this.checkColumn(props)}/>
|
||||
<label className="form-check-label"
|
||||
htmlFor={`checkbox${props.column.replace(/\s+/g, "")}`}>
|
||||
{props.column}
|
||||
</label>
|
||||
</div>;
|
||||
<input className="form-check-input"
|
||||
type="checkbox"
|
||||
id={`checkbox${props.column.replace(/\s+/g, "")}`}
|
||||
defaultChecked={props.visible}
|
||||
onChange={() => this.checkColumn(props)} />
|
||||
<label className="form-check-label"
|
||||
htmlFor={`checkbox${props.column.replace(/\s+/g, "")}`}>
|
||||
{props.column}
|
||||
</label>
|
||||
</div>;
|
||||
};
|
||||
|
||||
checkColumn(props: IColumnVisibility) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
import * as React from "react";
|
||||
import "isomorphic-fetch";
|
||||
import { ILanguage, ILicense, IList, IMaintainer, ISoftware, ISyntax, ITag } from "./interfaces";
|
||||
import { ILanguage } from "./interfaces/ILanguage";
|
||||
import { ILicense } from "./interfaces/ILicense";
|
||||
import { IList } from "./interfaces/IList";
|
||||
import { IMaintainer } from "./interfaces/IMaintainer";
|
||||
import { ISoftware } from "./interfaces/ISoftware";
|
||||
import { ISyntax } from "./interfaces/ISyntax";
|
||||
import { ITag } from "./interfaces/ITag";
|
||||
import { Home } from "./Home";
|
||||
|
||||
interface IState {
|
||||
|
|
@ -89,6 +95,6 @@ export class HomeContainer extends React.Component<{}, IState> {
|
|||
};
|
||||
|
||||
render() {
|
||||
return <Home {...this.state}/>;
|
||||
return <Home {...this.state} />;
|
||||
};
|
||||
};
|
||||
|
|
@ -1,4 +1,8 @@
|
|||
import { ILanguage, ILicense, IMaintainer, ISyntax, ITag } from "../../interfaces";
|
||||
import { ILanguage } from "../interfaces/ILanguage";
|
||||
import { ILicense } from "../interfaces/ILicense";
|
||||
import { IMaintainer } from "../interfaces/IMaintainer";
|
||||
import { ISyntax } from "../interfaces/ISyntax";
|
||||
import { ITag } from "../interfaces/ITag";
|
||||
|
||||
export interface IListDetails {
|
||||
id: number;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { ITag } from "../interfaces";
|
||||
import { ITag } from "../interfaces/ITag";
|
||||
import { getContrast } from "../../../utils";
|
||||
|
||||
interface IProps {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import * as React from "react";
|
||||
import { IColumnVisibility, ISoftware } from "../../interfaces";
|
||||
import { IListDetails } from "./IListDetails";
|
||||
import { ISoftware } from "../../interfaces/ISoftware";
|
||||
import { IColumnVisibility } from "../../interfaces/IColumnVisibility";
|
||||
import { IListDetails } from "../IListDetails";
|
||||
import { InfoCard } from "./infoCard";
|
||||
import { LinkButtonGroup } from "./LinkButtonGroup";
|
||||
import { MaintainersInfoCard } from "./maintainersInfoCard";
|
||||
|
|
@ -16,11 +17,11 @@ export const DetailsExpander = (props: IProps) =>
|
|||
<div className="card-body p-2">
|
||||
<div className="container m-0">
|
||||
<div className="row">
|
||||
<InfoCard columnVisibility={props.columnVisibility} software={props.software} {...props.list}/>
|
||||
<LinkButtonGroup {...props.list}/>
|
||||
<InfoCard columnVisibility={props.columnVisibility} software={props.software} {...props.list} />
|
||||
<LinkButtonGroup {...props.list} />
|
||||
</div>
|
||||
<div className="row">
|
||||
<MaintainersInfoCard maintainers={props.list.maintainers}/>
|
||||
<MaintainersInfoCard maintainers={props.list.maintainers} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
import { DetailsExpander } from "./DetailsExpander";
|
||||
import { IListDetails } from "./IListDetails";
|
||||
|
||||
export {
|
||||
DetailsExpander,
|
||||
IListDetails
|
||||
};
|
||||
DetailsExpander
|
||||
};
|
||||
|
|
@ -1,15 +1,19 @@
|
|||
import * as React from "react";
|
||||
import { IColumnVisibility } from "../../../interfaces";
|
||||
import { ILanguage, ILicense, ISoftware, ISyntax, ITag } from "../../../interfaces";
|
||||
import { IColumnVisibility } from "../../../interfaces/IColumnVisibility";
|
||||
import { ILanguage } from "../../../interfaces/ILanguage";
|
||||
import { ILicense, } from "../../../interfaces/ILicense";
|
||||
import { ISoftware, } from "../../../interfaces/ISoftware";
|
||||
import { ISyntax, } from "../../../interfaces/ISyntax";
|
||||
import { ITag } from "../../../interfaces/ITag";
|
||||
import { Description } from "./Description";
|
||||
import { Languages } from "./Languages";
|
||||
import { License } from "./License";
|
||||
import { PublishedDate } from "./PublishedDate";
|
||||
import { RuleCount } from "./RuleCount";
|
||||
// import { RuleCount } from "./RuleCount";
|
||||
import { SoftwareIcon } from "../../softwareIcon";
|
||||
import { Syntax } from "./Syntax";
|
||||
import { TagGroup } from "../../TagGroup"
|
||||
import { UpdatedDate } from "./UpdatedDate";
|
||||
// import { UpdatedDate } from "./UpdatedDate";
|
||||
|
||||
interface IProps {
|
||||
columnVisibility: IColumnVisibility[];
|
||||
|
|
@ -29,26 +33,26 @@ interface IProps {
|
|||
export const InfoCard = (props: IProps) =>
|
||||
<div className="col-9">
|
||||
{props.columnVisibility.filter((c: IColumnVisibility) => c.column === "Tags")[0].visible
|
||||
? null
|
||||
: <TagGroup tags={props.tags}/>}
|
||||
? null
|
||||
: <TagGroup tags={props.tags} />}
|
||||
<div>
|
||||
{props.columnVisibility.filter((c: IColumnVisibility) => c.column === "Software")[0].visible
|
||||
? null
|
||||
: props.syntax
|
||||
? props.software.filter((s: ISoftware) => s.syntaxIds.indexOf(props.syntax.id) > -1)
|
||||
.map((s: ISoftware, i: number) => <SoftwareIcon id={s.id} key={i}/>)
|
||||
: null}
|
||||
? null
|
||||
: props.syntax
|
||||
? props.software.filter((s: ISoftware) => s.syntaxIds.indexOf(props.syntax.id) > -1)
|
||||
.map((s: ISoftware, i: number) => <SoftwareIcon id={s.id} key={i} />)
|
||||
: null}
|
||||
</div>
|
||||
<Description {...props} url={props.descriptionSourceUrl}/>
|
||||
<Description {...props} url={props.descriptionSourceUrl} />
|
||||
<ul className="list-group list-group-flush">
|
||||
<Languages {...props}/>
|
||||
<Languages {...props} />
|
||||
{/*{props.columnVisibility.filter((c: IColumnVisibility) => c.column === "Rules")[0].visible
|
||||
? null
|
||||
: <RuleCount {...props}/>}
|
||||
{props.columnVisibility.filter((c: IColumnVisibility) => c.column === "Updated")[0].visible
|
||||
? null
|
||||
: <UpdatedDate {...props}/>}*/}
|
||||
<PublishedDate date={props.publishedDate}/>
|
||||
<PublishedDate date={props.publishedDate} />
|
||||
<Syntax {...props} />
|
||||
{props.columnVisibility.filter((c: IColumnVisibility) => c.column === "License")[0].visible
|
||||
? null
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { ILanguage } from "../../../interfaces";
|
||||
import { ILanguage } from "../../../interfaces/ILanguage";
|
||||
|
||||
interface IProps {
|
||||
languages: ILanguage[];
|
||||
|
|
@ -7,14 +7,14 @@ interface IProps {
|
|||
|
||||
export const Languages = (props: IProps) =>
|
||||
props.languages && props.languages.length > 0
|
||||
? props.languages.length > 1
|
||||
? <li className="list-group-item">
|
||||
<p className="m-0">Languages:</p>
|
||||
<ul>
|
||||
{props.languages.map((language: ILanguage, i: number) => <li key={i}>{language.name}</li>)}
|
||||
</ul>
|
||||
</li>
|
||||
: <li className="list-group-item">
|
||||
<p>Language: {props.languages[0].name}</p>
|
||||
</li>
|
||||
: null;
|
||||
? props.languages.length > 1
|
||||
? <li className="list-group-item">
|
||||
<p className="m-0">Languages:</p>
|
||||
<ul>
|
||||
{props.languages.map((language: ILanguage, i: number) => <li key={i}>{language.name}</li>)}
|
||||
</ul>
|
||||
</li>
|
||||
: <li className="list-group-item">
|
||||
<p>Language: {props.languages[0].name}</p>
|
||||
</li>
|
||||
: null;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { ILicense } from "../../../interfaces";
|
||||
import { ILicense } from "../../../interfaces/ILicense";
|
||||
|
||||
interface IProps {
|
||||
license: ILicense;
|
||||
|
|
@ -7,11 +7,11 @@ interface IProps {
|
|||
|
||||
export const License = (props: IProps) =>
|
||||
props.license.name
|
||||
? (props.license.descriptionUrl
|
||||
? <li className="list-group-item">
|
||||
<p>License: <a href={props.license.descriptionUrl}>{props.license.name}</a></p>
|
||||
</li>
|
||||
: <li className="list-group-item">
|
||||
<p>License: {props.license.name}</p>
|
||||
</li>)
|
||||
: null;
|
||||
? (props.license.descriptionUrl
|
||||
? <li className="list-group-item">
|
||||
<p>License: <a href={props.license.descriptionUrl}>{props.license.name}</a></p>
|
||||
</li>
|
||||
: <li className="list-group-item">
|
||||
<p>License: {props.license.name}</p>
|
||||
</li>)
|
||||
: null;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from "react";
|
||||
import * as moment from "moment";
|
||||
import moment from 'moment';
|
||||
|
||||
interface IProps {
|
||||
date: string;
|
||||
|
|
@ -7,7 +7,7 @@ interface IProps {
|
|||
|
||||
export const PublishedDate = (props: IProps) =>
|
||||
props.date
|
||||
? <li className="list-group-item">
|
||||
<p>Published: {moment(props.date).format("l")}</p>
|
||||
</li>
|
||||
: null;
|
||||
? <li className="list-group-item">
|
||||
<p>Published: {moment(props.date).format("l")}</p>
|
||||
</li>
|
||||
: null;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { ISyntax } from "../../../interfaces";
|
||||
import { ISyntax } from "../../../interfaces/ISyntax";
|
||||
|
||||
interface IProps {
|
||||
syntax: ISyntax;
|
||||
|
|
@ -7,11 +7,11 @@ interface IProps {
|
|||
|
||||
export const Syntax = (props: IProps) =>
|
||||
props.syntax
|
||||
? (props.syntax.definitionUrl
|
||||
? <li className="list-group-item">
|
||||
<p>Syntax: <a href={props.syntax.definitionUrl}>{props.syntax.name}</a></p>
|
||||
</li>
|
||||
: <li className="list-group-item">
|
||||
<p>Syntax: {props.syntax.name}</p>
|
||||
</li>)
|
||||
: null;
|
||||
? (props.syntax.definitionUrl
|
||||
? <li className="list-group-item">
|
||||
<p>Syntax: <a href={props.syntax.definitionUrl}>{props.syntax.name}</a></p>
|
||||
</li>
|
||||
: <li className="list-group-item">
|
||||
<p>Syntax: {props.syntax.name}</p>
|
||||
</li>)
|
||||
: null;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from "react";
|
||||
import * as moment from "moment";
|
||||
import moment from 'moment';
|
||||
|
||||
interface IProps {
|
||||
updatedDate: string;
|
||||
|
|
@ -7,9 +7,9 @@ interface IProps {
|
|||
|
||||
export const UpdatedDate = (props: IProps) =>
|
||||
props.updatedDate
|
||||
? <li className="list-group-item">
|
||||
<p>Updated: {moment(props.updatedDate).isValid()
|
||||
? moment(props.updatedDate).format("l")
|
||||
: "N/A"}</p>
|
||||
</li>
|
||||
: null;
|
||||
? <li className="list-group-item">
|
||||
<p>Updated: {moment(props.updatedDate).isValid()
|
||||
? moment(props.updatedDate).format("l")
|
||||
: "N/A"}</p>
|
||||
</li>
|
||||
: null;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { IMaintainer } from "../../../interfaces";
|
||||
import { IMaintainer } from "../../../interfaces/IMaintainer";
|
||||
import { MaintainerAdditionalLists } from "./MaintainerAdditionalLists";
|
||||
import { MaintainerLinkButtonGroup } from "./MaintainerLinkButtonGroup";
|
||||
|
||||
|
|
@ -9,15 +9,15 @@ interface IProps {
|
|||
|
||||
export const MaintainerInfoCard = (props: IProps) =>
|
||||
props.maintainer.name
|
||||
? <div className="card">
|
||||
<div className="card-body">
|
||||
<h3 className="card-header">Maintained by {props.maintainer.name}</h3>
|
||||
<div className="container pt-1">
|
||||
<div className="row">
|
||||
<MaintainerAdditionalLists/>
|
||||
<MaintainerLinkButtonGroup {...props.maintainer}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
: null;
|
||||
? <div className="card">
|
||||
<div className="card-body">
|
||||
<h3 className="card-header">Maintained by {props.maintainer.name}</h3>
|
||||
<div className="container pt-1">
|
||||
<div className="row">
|
||||
<MaintainerAdditionalLists />
|
||||
<MaintainerLinkButtonGroup {...props.maintainer} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
: null;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { IMaintainer } from "../../../interfaces";
|
||||
import { IMaintainer } from "../../../interfaces/IMaintainer";
|
||||
import { MaintainerInfoCard } from "./MaintainerInfoCard";
|
||||
|
||||
interface IProps {
|
||||
|
|
@ -8,7 +8,7 @@ interface IProps {
|
|||
|
||||
export const MaintainersInfoCard = (props: IProps) =>
|
||||
props.maintainers && props.maintainers.length > 0
|
||||
? <div className="w-100">
|
||||
{props.maintainers.map((m: IMaintainer, i: number) => <MaintainerInfoCard maintainer={m} key={i}/>)}
|
||||
</div>
|
||||
: null;
|
||||
? <div className="w-100">
|
||||
{props.maintainers.map((m: IMaintainer, i: number) => <MaintainerInfoCard maintainer={m} key={i} />)}
|
||||
</div>
|
||||
: null;
|
||||
|
|
@ -50,7 +50,7 @@ if (props.url.indexOf(".tpl") > 0)
|
|||
{
|
||||
title = `${titlePrefix}Subscribe to ${props.name} with Little Snitch's rule group subscription feature.`;
|
||||
} else {
|
||||
title = `${titlePrefix}Subscribe to ${props.name} with a browser extension supporting the \"abp:\" protocol (e.g. uBlock Origin, Adblock Plus).`;
|
||||
title = `${titlePrefix}Subscribe to ${props.name} with a browser extension supporting the "abp:" protocol (e.g. uBlock Origin, Adblock Plus).`;
|
||||
};
|
||||
|
||||
return props.url
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
import * as React from "react";
|
||||
import { IColumnVisibility, ILanguage, ILicense, IList, IMaintainer, ISoftware, ISyntax, ITag } from "../../interfaces";
|
||||
import { IColumnVisibility } from "../../interfaces/IColumnVisibility";
|
||||
import { ILanguage } from "../../interfaces/ILanguage";
|
||||
import { ILicense } from "../../interfaces/ILicense";
|
||||
import { IList } from "../../interfaces/IList";
|
||||
import { IMaintainer } from "../../interfaces/IMaintainer";
|
||||
import { ISoftware } from "../../interfaces/ISoftware";
|
||||
import { ISyntax } from "../../interfaces/ISyntax";
|
||||
import { ITag } from "../../interfaces/ITag";
|
||||
import "../../../../utils/loader.css";
|
||||
import ReactTable from "react-table";
|
||||
import "react-table/react-table.css";
|
||||
|
|
@ -16,7 +23,7 @@ import {
|
|||
Tags,
|
||||
//UpdatedDate
|
||||
} from "./columns";
|
||||
import { IListDetails } from "../../components/detailsExpander";
|
||||
import { IListDetails } from "../IListDetails";
|
||||
import { DetailsExpander } from "../../components";
|
||||
|
||||
interface IProps {
|
||||
|
|
@ -33,36 +40,36 @@ interface IProps {
|
|||
|
||||
export const ListsTable = (props: IProps) =>
|
||||
props.languages.length > 0 && props.lists.length > 0 && props.software.length > 0 && props.tags.length > 0
|
||||
? <ReactTable
|
||||
data={props.lists}
|
||||
defaultPageSize={props.pageSize}
|
||||
showPageSizeOptions={false}
|
||||
columns={[
|
||||
Name,
|
||||
Software(props.columnVisibility, props.software),
|
||||
Languages(props.columnVisibility, props.languages),
|
||||
Tags(props.columnVisibility, props.tags),
|
||||
//UpdatedDate(props.columnVisibility),
|
||||
//RuleCount(props.columnVisibility),
|
||||
License(props.columnVisibility, props.licenses),
|
||||
Maintainers(props.columnVisibility, props.maintainers),
|
||||
SubscribeButton(props.columnVisibility),
|
||||
DetailsButton
|
||||
]}
|
||||
defaultSorted={[{ id: "name" }]}
|
||||
SubComponent={(r: any) =>
|
||||
<DetailsExpander columnVisibility={props.columnVisibility}
|
||||
list={mapListDetails(({
|
||||
list: r.original,
|
||||
languages: props.languages,
|
||||
licenses: props.licenses,
|
||||
maintainers: props.maintainers,
|
||||
syntaxes: props.syntaxes,
|
||||
tags: props.tags
|
||||
} as ICreateListDtoProps))}
|
||||
software={props.software}/>}
|
||||
className="-striped -highlight"/>
|
||||
: <div className="loader">Loading...</div>;
|
||||
? <ReactTable
|
||||
data={props.lists}
|
||||
defaultPageSize={props.pageSize}
|
||||
showPageSizeOptions={false}
|
||||
columns={[
|
||||
Name,
|
||||
Software(props.columnVisibility, props.software),
|
||||
Languages(props.columnVisibility, props.languages),
|
||||
Tags(props.columnVisibility, props.tags),
|
||||
//UpdatedDate(props.columnVisibility),
|
||||
//RuleCount(props.columnVisibility),
|
||||
License(props.columnVisibility, props.licenses),
|
||||
Maintainers(props.columnVisibility, props.maintainers),
|
||||
SubscribeButton(props.columnVisibility),
|
||||
DetailsButton
|
||||
]}
|
||||
defaultSorted={[{ id: "name", desc: false }]}
|
||||
SubComponent={(r: any) =>
|
||||
<DetailsExpander columnVisibility={props.columnVisibility}
|
||||
list={mapListDetails(({
|
||||
list: r.original,
|
||||
languages: props.languages,
|
||||
licenses: props.licenses,
|
||||
maintainers: props.maintainers,
|
||||
syntaxes: props.syntaxes,
|
||||
tags: props.tags
|
||||
} as ICreateListDtoProps))}
|
||||
software={props.software} />}
|
||||
className="-striped -highlight" />
|
||||
: <div className="loader">Loading...</div>;
|
||||
|
||||
interface ICreateListDtoProps {
|
||||
list: IList;
|
||||
|
|
@ -74,31 +81,31 @@ interface ICreateListDtoProps {
|
|||
};
|
||||
|
||||
const mapListDetails = (props: ICreateListDtoProps): IListDetails =>
|
||||
({
|
||||
id: props.list.id,
|
||||
chatUrl: props.list.chatUrl,
|
||||
description: props.list.description,
|
||||
descriptionSourceUrl: props.list.descriptionSourceUrl,
|
||||
donateUrl: props.list.donateUrl,
|
||||
emailAddress: props.list.emailAddress,
|
||||
forumUrl: props.list.forumUrl,
|
||||
homeUrl: props.list.homeUrl,
|
||||
issuesUrl: props.list.issuesUrl,
|
||||
languages: props.list.languageIds
|
||||
? props.languages.filter((l: ILanguage) => props.list.languageIds.indexOf(l.id) > -1)
|
||||
: undefined,
|
||||
license: props.licenses.filter((l: ILicense) => props.list.licenseId === l.id)[0],
|
||||
maintainers: props.list.maintainerIds
|
||||
? props.maintainers.filter((m: IMaintainer) => props.list.maintainerIds.indexOf(m.id) > -1)
|
||||
: undefined,
|
||||
name: props.list.name,
|
||||
policyUrl: props.list.policyUrl,
|
||||
publishedDate: props.list.publishedDate,
|
||||
//ruleCount: props.list.ruleCount,
|
||||
submissionUrl: props.list.submissionUrl,
|
||||
syntax: props.syntaxes.filter((s: ISyntax) => props.list.syntaxId === s.id)[0],
|
||||
tags: props.list.tagIds ? props.tags.filter((t: ITag) => props.list.tagIds.indexOf(t.id) > -1) : undefined,
|
||||
//updatedDate: props.list.updatedDate,
|
||||
viewUrl: props.list.viewUrl,
|
||||
viewUrlMirrors: props.list.viewUrlMirrors
|
||||
} as IListDetails);
|
||||
({
|
||||
id: props.list.id,
|
||||
chatUrl: props.list.chatUrl,
|
||||
description: props.list.description,
|
||||
descriptionSourceUrl: props.list.descriptionSourceUrl,
|
||||
donateUrl: props.list.donateUrl,
|
||||
emailAddress: props.list.emailAddress,
|
||||
forumUrl: props.list.forumUrl,
|
||||
homeUrl: props.list.homeUrl,
|
||||
issuesUrl: props.list.issuesUrl,
|
||||
languages: props.list.languageIds
|
||||
? props.languages.filter((l: ILanguage) => props.list.languageIds.indexOf(l.id) > -1)
|
||||
: undefined,
|
||||
license: props.licenses.filter((l: ILicense) => props.list.licenseId === l.id)[0],
|
||||
maintainers: props.list.maintainerIds
|
||||
? props.maintainers.filter((m: IMaintainer) => props.list.maintainerIds.indexOf(m.id) > -1)
|
||||
: undefined,
|
||||
name: props.list.name,
|
||||
policyUrl: props.list.policyUrl,
|
||||
publishedDate: props.list.publishedDate,
|
||||
//ruleCount: props.list.ruleCount,
|
||||
submissionUrl: props.list.submissionUrl,
|
||||
syntax: props.syntaxes.filter((s: ISyntax) => props.list.syntaxId === s.id)[0],
|
||||
tags: props.list.tagIds ? props.tags.filter((t: ITag) => props.list.tagIds.indexOf(t.id) > -1) : undefined,
|
||||
//updatedDate: props.list.updatedDate,
|
||||
viewUrl: props.list.viewUrl,
|
||||
viewUrlMirrors: props.list.viewUrlMirrors
|
||||
} as IListDetails);
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import * as React from "react";
|
||||
import { Column, Filter } from "react-table";
|
||||
import { IColumnVisibility, ILanguage } from "../../../interfaces";
|
||||
import { IColumnVisibility } from "../../../interfaces/IColumnVisibility";
|
||||
import { ILanguage } from "../../../interfaces/ILanguage";
|
||||
|
||||
export const Languages = (columnVisibility: IColumnVisibility[], languages: ILanguage[]) => {
|
||||
const languagesSorted = languages.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
|
@ -9,7 +10,7 @@ export const Languages = (columnVisibility: IColumnVisibility[], languages: ILan
|
|||
accessor: "languageIds",
|
||||
filterable: true,
|
||||
filterMethod: (f: Filter, r: any[]) => filterMethod(f, r),
|
||||
Filter: ({ onChange, filter }: any) => Filter({ onChange, filter }, languagesSorted),
|
||||
Filter: ({ onChange, filter }: any) => filterLanguages({ onChange, filter }, languagesSorted),
|
||||
sortMethod: (a: number[], b: number[]) => sortMethod(a, b, languagesSorted),
|
||||
Cell: (c: any) => Cell(c.value, languagesSorted),
|
||||
style: { whiteSpace: "inherit" },
|
||||
|
|
@ -21,23 +22,23 @@ export const Languages = (columnVisibility: IColumnVisibility[], languages: ILan
|
|||
const filterMethod = (f: Filter, r: any[]): boolean => {
|
||||
const listLanguageIds = r[f.id as any];
|
||||
return f.value === "any" ||
|
||||
(listLanguageIds
|
||||
? listLanguageIds.join(",").split(",").includes(f.value)
|
||||
: f.value === "none");
|
||||
(listLanguageIds
|
||||
? listLanguageIds.join(",").split(",").includes(f.value)
|
||||
: f.value === "none");
|
||||
};
|
||||
|
||||
const Filter = (props: any, languages: ILanguage[]) =>
|
||||
const filterLanguages = (props: any, languages: ILanguage[]) =>
|
||||
<select onChange={(event: any) => props.onChange(event.target.value)}
|
||||
style={{ width: "100%" }}
|
||||
value={props.filter ? props.filter.value : "any"}>
|
||||
style={{ width: "100%" }}
|
||||
value={props.filter ? props.filter.value : "any"}>
|
||||
<option value="any">Any</option>
|
||||
<option value="none">None</option>
|
||||
{languages.length > 0
|
||||
? languages.map((l: ILanguage, i: number) =>
|
||||
<option value={l.id} key={i}>
|
||||
{l.name} ({l.filterListIds ? l.filterListIds.length : 0})
|
||||
? languages.map((l: ILanguage, i: number) =>
|
||||
<option value={l.id} key={i}>
|
||||
{l.name} ({l.filterListIds ? l.filterListIds.length : 0})
|
||||
</option>)
|
||||
: null}
|
||||
: null}
|
||||
</select>;
|
||||
|
||||
const sortMethod = (a: number[], b: number[], languages: ILanguage[]) => {
|
||||
|
|
@ -58,14 +59,14 @@ const sortMethod = (a: number[], b: number[], languages: ILanguage[]) => {
|
|||
|
||||
const Cell = (languageIds: number[], languages: ILanguage[]) =>
|
||||
languageIds
|
||||
? <div className="fl-wrap-cell">
|
||||
{languageIds.map((id: number, i: number) => {
|
||||
const language = languages.filter((l: ILanguage) => l.id === id)[0];
|
||||
return <span className="badge badge-secondary"
|
||||
title={language.name}
|
||||
key={i}>
|
||||
{language.iso6391}
|
||||
</span>;
|
||||
})}
|
||||
</div>
|
||||
: null;
|
||||
? <div className="fl-wrap-cell">
|
||||
{languageIds.map((id: number, i: number) => {
|
||||
const language = languages.filter((l: ILanguage) => l.id === id)[0];
|
||||
return <span className="badge badge-secondary"
|
||||
title={language.name}
|
||||
key={i}>
|
||||
{language.iso6391}
|
||||
</span>;
|
||||
})}
|
||||
</div>
|
||||
: null;
|
||||
|
|
@ -1,19 +1,20 @@
|
|||
import * as React from "react";
|
||||
import { Column, Filter } from "react-table";
|
||||
import { IColumnVisibility, ILicense } from "../../../interfaces";
|
||||
import { IColumnVisibility } from "../../../interfaces/IColumnVisibility";
|
||||
import { ILicense } from "../../../interfaces/ILicense";
|
||||
|
||||
export const License = (columnVisibility: IColumnVisibility[], licenses: ILicense[]) =>
|
||||
({
|
||||
Header: <span title="A legal document governing the use or redistribution of a FilterList.">License</span>,
|
||||
accessor: "licenseId",
|
||||
filterable: true,
|
||||
filterMethod: (f: Filter, r: any[]) => filterMethod(f, r, licenses),
|
||||
Filter: ({ filter, onChange }: any) => Filter({ onChange, filter }, licenses),
|
||||
sortMethod: (a: number, b: number) => sortMethod(a, b, licenses),
|
||||
Cell: (c: any) => Cell(c.value, licenses),
|
||||
width: 75,
|
||||
show: columnVisibility.filter((c: IColumnVisibility) => c.column === "License")[0].visible
|
||||
} as Column);
|
||||
({
|
||||
Header: <span title="A legal document governing the use or redistribution of a FilterList.">License</span>,
|
||||
accessor: "licenseId",
|
||||
filterable: true,
|
||||
filterMethod: (f: Filter, r: any[]) => filterMethod(f, r, licenses),
|
||||
Filter: ({ filter, onChange }: any) => filterLicenses({ onChange, filter }, licenses),
|
||||
sortMethod: (a: number, b: number) => sortMethod(a, b, licenses),
|
||||
Cell: (c: any) => Cell(c.value, licenses),
|
||||
width: 75,
|
||||
show: columnVisibility.filter((c: IColumnVisibility) => c.column === "License")[0].visible
|
||||
} as Column);
|
||||
|
||||
const filterMethod = (f: Filter, r: any[], licenses: ILicense[]): boolean => {
|
||||
const listLicenseId: number = r[f.id as any];
|
||||
|
|
@ -27,19 +28,19 @@ const filterMethod = (f: Filter, r: any[], licenses: ILicense[]): boolean => {
|
|||
}
|
||||
};
|
||||
|
||||
const Filter = (props: any, licenses: ILicense[]) =>
|
||||
const filterLicenses = (props: any, licenses: ILicense[]) =>
|
||||
<select
|
||||
onChange={(event: any) => props.onChange(event.target.value)}
|
||||
style={{ width: "100%" }}
|
||||
value={props.filter ? props.filter.value : "any"}>
|
||||
<option value="any">Any</option>
|
||||
{licenses.length > 0
|
||||
? licenses.sort((a, b) => a.name.replace(/['"]+/g, "").localeCompare(b.name.replace(/['"]+/g, ""))).map(
|
||||
(l: ILicense, i: number) =>
|
||||
<option value={l.id} key={i}>
|
||||
{l.name} ({l.filterListIds ? l.filterListIds.length : 0})
|
||||
? licenses.sort((a, b) => a.name.replace(/['"]+/g, "").localeCompare(b.name.replace(/['"]+/g, ""))).map(
|
||||
(l: ILicense, i: number) =>
|
||||
<option value={l.id} key={i}>
|
||||
{l.name} ({l.filterListIds ? l.filterListIds.length : 0})
|
||||
</option>)
|
||||
: null}
|
||||
: null}
|
||||
</select>;
|
||||
|
||||
const sortMethod = (a: number, b: number, licenses: ILicense[]) => {
|
||||
|
|
@ -59,10 +60,10 @@ const sortMethod = (a: number, b: number, licenses: ILicense[]) => {
|
|||
const Cell = (licenseId: number, licenses: ILicense[]) => {
|
||||
const license = licenses.filter((l: ILicense) => licenseId === l.id)[0];
|
||||
return license
|
||||
? <div>
|
||||
<span title={license.name}>
|
||||
{license.descriptionUrl ? <a href={license.descriptionUrl}>{license.name}</a> : license.name}
|
||||
</span>
|
||||
</div>
|
||||
: null;
|
||||
? <div>
|
||||
<span title={license.name}>
|
||||
{license.descriptionUrl ? <a href={license.descriptionUrl}>{license.name}</a> : license.name}
|
||||
</span>
|
||||
</div>
|
||||
: null;
|
||||
};
|
||||
|
|
@ -1,31 +1,32 @@
|
|||
import * as React from "react";
|
||||
import { Column, Filter } from "react-table";
|
||||
import { IColumnVisibility, IMaintainer } from "../../../interfaces";
|
||||
import { IColumnVisibility } from "../../../interfaces/IColumnVisibility";
|
||||
import { IMaintainer } from "../../../interfaces/IMaintainer";
|
||||
|
||||
export const Maintainers = (columnVisibility: IColumnVisibility[], maintainers: IMaintainer[]) =>
|
||||
({
|
||||
Header: <span title="Individuals, groups, or organizations who maintain the FilterList.">Maintainers</span>,
|
||||
accessor: "maintainerIds",
|
||||
filterable: true,
|
||||
filterMethod: (f: Filter, r: any[]) => filterMethod(f, r, maintainers),
|
||||
Filter: ({ filter, onChange }: any) => Filter({ onChange, filter }, maintainers),
|
||||
sortMethod: (a: number[], b: number[]) => sortMethod(a, b, maintainers),
|
||||
Cell: (c: any) => Cell(c.value, maintainers),
|
||||
width: 140,
|
||||
show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Maintainers")[0].visible
|
||||
} as Column);
|
||||
({
|
||||
Header: <span title="Individuals, groups, or organizations who maintain the FilterList.">Maintainers</span>,
|
||||
accessor: "maintainerIds",
|
||||
filterable: true,
|
||||
filterMethod: (f: Filter, r: any[]) => filterMethod(f, r, maintainers),
|
||||
Filter: ({ filter, onChange }: any) => filterMaintainers({ onChange, filter }, maintainers),
|
||||
sortMethod: (a: number[], b: number[]) => sortMethod(a, b, maintainers),
|
||||
Cell: (c: any) => Cell(c.value, maintainers),
|
||||
width: 140,
|
||||
show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Maintainers")[0].visible
|
||||
} as Column);
|
||||
|
||||
const filterMethod = (f: Filter, r: any[], maintainers: IMaintainer[]): boolean => {
|
||||
const listMaintainerIds: number[] = r[f.id as any];
|
||||
return f.value === "any" ||
|
||||
(listMaintainerIds
|
||||
? f.value === "none"
|
||||
? false
|
||||
: listMaintainerIds.indexOf(maintainers.filter((m: IMaintainer) => m.id === parseInt(f.value))[0].id) > -1
|
||||
: f.value === "none");
|
||||
(listMaintainerIds
|
||||
? f.value === "none"
|
||||
? false
|
||||
: listMaintainerIds.indexOf(maintainers.filter((m: IMaintainer) => m.id === parseInt(f.value))[0].id) > -1
|
||||
: f.value === "none");
|
||||
};
|
||||
|
||||
const Filter = (props: any, maintainers: IMaintainer[]) =>
|
||||
const filterMaintainers = (props: any, maintainers: IMaintainer[]) =>
|
||||
<select
|
||||
onChange={(event: any) => props.onChange(event.target.value)}
|
||||
style={{ width: "100%" }}
|
||||
|
|
@ -33,12 +34,12 @@ const Filter = (props: any, maintainers: IMaintainer[]) =>
|
|||
<option value="any">Any</option>
|
||||
<option value="none">None</option>
|
||||
{maintainers.length > 0
|
||||
? maintainers.sort((a, b) => a.name.localeCompare(b.name))
|
||||
.map((m: IMaintainer, i: number) =>
|
||||
<option value={m.id} key={i}>
|
||||
{m.name} ({m.filterListIds ? m.filterListIds.length : 0})
|
||||
? maintainers.sort((a, b) => a.name.localeCompare(b.name))
|
||||
.map((m: IMaintainer, i: number) =>
|
||||
<option value={m.id} key={i}>
|
||||
{m.name} ({m.filterListIds ? m.filterListIds.length : 0})
|
||||
</option>)
|
||||
: null}
|
||||
: null}
|
||||
</select>;
|
||||
|
||||
const sortMethod = (a: number[], b: number[], maintainers: IMaintainer[]) => {
|
||||
|
|
@ -57,12 +58,12 @@ const sortMethod = (a: number[], b: number[], maintainers: IMaintainer[]) => {
|
|||
|
||||
const Cell = (maintainerIds: number[], maintainers: IMaintainer[]) =>
|
||||
maintainerIds
|
||||
? <div className="fl-wrap-cell">
|
||||
{maintainers.filter((m: IMaintainer) => maintainerIds.indexOf(m.id) > -1)
|
||||
.map((m: IMaintainer, i: number) => {
|
||||
return m.homeUrl
|
||||
? <a href={m.homeUrl} key={i}>{m.name}</a>
|
||||
: <span key={i}>{m.name}</span>;
|
||||
}).reduce(((prev: JSX.Element, curr: JSX.Element): any => [prev, ", ", curr]) as any)}
|
||||
</div>
|
||||
: null;
|
||||
? <div className="fl-wrap-cell">
|
||||
{maintainers.filter((m: IMaintainer) => maintainerIds.indexOf(m.id) > -1)
|
||||
.map((m: IMaintainer, i: number) => {
|
||||
return m.homeUrl
|
||||
? <a href={m.homeUrl} key={i}>{m.name}</a>
|
||||
: <span key={i}>{m.name}</span>;
|
||||
}).reduce(((prev: JSX.Element, curr: JSX.Element): any => [prev, ", ", curr]) as any)}
|
||||
</div>
|
||||
: null;
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import * as React from "react";
|
||||
import { Column } from "react-table";
|
||||
import { IColumnVisibility } from "../../../interfaces";
|
||||
import { IColumnVisibility } from "../../../interfaces/IColumnVisibility";
|
||||
|
||||
export const RuleCount = (columnVisibility: IColumnVisibility[]) =>
|
||||
({
|
||||
({
|
||||
Header: <span title="The number of rules in the FilterList.">Rules</span>,
|
||||
accessor: "ruleCount",
|
||||
sortMethod: (a: string, b: string) => sortMethod(a, b),
|
||||
|
|
@ -11,10 +11,10 @@ export const RuleCount = (columnVisibility: IColumnVisibility[]) =>
|
|||
style: { whiteSpace: "inherit" },
|
||||
width: 85,
|
||||
show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Rules")[0].visible
|
||||
} as Column);
|
||||
} as Column);
|
||||
|
||||
const sortMethod = (a: string, b: string) =>
|
||||
a
|
||||
a
|
||||
? b
|
||||
? a > b
|
||||
? -1
|
||||
|
|
@ -23,6 +23,6 @@ const sortMethod = (a: string, b: string) =>
|
|||
: 1;
|
||||
|
||||
const Cell = (ruleCount: number) =>
|
||||
ruleCount
|
||||
? <span>{ ruleCount.toLocaleString() }</span>
|
||||
ruleCount
|
||||
? <span>{ruleCount.toLocaleString()}</span>
|
||||
: null;
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import * as React from "react";
|
||||
import { Column, Filter } from "react-table";
|
||||
import { IColumnVisibility, ISoftware } from "../../../interfaces";
|
||||
import { IColumnVisibility } from "../../../interfaces/IColumnVisibility";
|
||||
import { ISoftware } from "../../../interfaces/ISoftware";
|
||||
import { SoftwareIcon } from "../../softwareIcon";
|
||||
|
||||
export const Software = (columnVisibility: IColumnVisibility[], software: ISoftware[]) => {
|
||||
|
|
@ -11,7 +12,7 @@ export const Software = (columnVisibility: IColumnVisibility[], software: ISoftw
|
|||
accessor: "syntaxId",
|
||||
filterable: true,
|
||||
filterMethod: (f: Filter, r: any[]) => filterMethod(f, r, softwareSorted),
|
||||
Filter: ({ filter, onChange }: any) => Filter({ onChange, filter }, softwareSorted),
|
||||
Filter: ({ filter, onChange }: any) => filterSoftware({ onChange, filter }, softwareSorted),
|
||||
sortMethod: (a: number, b: number) => sortMethod(a, b, softwareSorted),
|
||||
Cell: (c: any) => Cell(c.value, software),
|
||||
width: 155,
|
||||
|
|
@ -27,15 +28,15 @@ const filterMethod = (f: Filter, r: any[], software: ISoftware[]): boolean => {
|
|||
return isAny || (listSyntaxId ? isMatch : false);
|
||||
};
|
||||
|
||||
const Filter = (props: any, software: ISoftware[]) =>
|
||||
const filterSoftware = (props: any, software: ISoftware[]) =>
|
||||
<select
|
||||
onChange={(event: any) => props.onChange(event.target.value)}
|
||||
style={{ width: "100%" }}
|
||||
value={props.filter ? props.filter.value : "any"}>
|
||||
<option value="any">Any</option>
|
||||
{software.length > 0
|
||||
? software.map((s: ISoftware, i: number) => <option value={s.id} key={i}>{s.name}</option>)
|
||||
: null}
|
||||
? software.map((s: ISoftware, i: number) => <option value={s.id} key={i}>{s.name}</option>)
|
||||
: null}
|
||||
</select>;
|
||||
|
||||
const sortMethod = (a: number, b: number, software: ISoftware[]) => {
|
||||
|
|
@ -62,13 +63,13 @@ const sortMethod = (a: number, b: number, software: ISoftware[]) => {
|
|||
|
||||
const Cell = (listSyntaxId: number, software: ISoftware[]) =>
|
||||
listSyntaxId
|
||||
? <div className="fl-wrap-cell">
|
||||
{software.filter((s: ISoftware) => s.syntaxIds.indexOf(listSyntaxId) > -1)
|
||||
.map((s: ISoftware, i: number) =>
|
||||
s.homeUrl
|
||||
? <a href={s.homeUrl} key={i}>
|
||||
<SoftwareIcon id={s.id}/>
|
||||
</a>
|
||||
: <SoftwareIcon id={s.id} key={i}/>)}
|
||||
</div>
|
||||
: null;
|
||||
? <div className="fl-wrap-cell">
|
||||
{software.filter((s: ISoftware) => s.syntaxIds.indexOf(listSyntaxId) > -1)
|
||||
.map((s: ISoftware, i: number) =>
|
||||
s.homeUrl
|
||||
? <a href={s.homeUrl} key={i}>
|
||||
<SoftwareIcon id={s.id} />
|
||||
</a>
|
||||
: <SoftwareIcon id={s.id} key={i} />)}
|
||||
</div>
|
||||
: null;
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
import * as React from "react";
|
||||
import { Column, Filter } from "react-table";
|
||||
import { IColumnVisibility } from "../../../interfaces";
|
||||
import { IColumnVisibility } from "../../../interfaces/IColumnVisibility";
|
||||
import { SubscribeButtonGroup } from "../../linkButtons";
|
||||
|
||||
export const SubscribeButton = (columnVisibility: IColumnVisibility[]) => ({
|
||||
Header: <span title={`Subscribe to the list with a browser extension supporting the "abp:" protocol (e.g. uBlock Origin, Adblock Plus)`}>
|
||||
Subscribe
|
||||
Subscribe
|
||||
</span>,
|
||||
accessor: "viewUrl",
|
||||
filterable: true,
|
||||
filterMethod: (f: Filter, r: any[]) => filterMethod(f, r),
|
||||
sortMethod: (a: string, b: string) => sortMethod(a, b),
|
||||
Cell: (c: any) => <SubscribeButtonGroup name={c.row.name} url={c.value} urlMirrors={c.row.viewUrlMirrors}/>,
|
||||
Cell: (c: any) => <SubscribeButtonGroup name={c.row.name} url={c.value} urlMirrors={c.row.viewUrlMirrors} />,
|
||||
style: { textAlign: "center" },
|
||||
width: 110,
|
||||
show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Subscribe")[0].visible
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import * as React from "react";
|
||||
import { Column, Filter } from "react-table";
|
||||
import { IColumnVisibility, ISyntax } from "../../../interfaces";
|
||||
import { IColumnVisibility } from "../../../interfaces/IColumnVisibility";
|
||||
import { ISyntax } from "../../../interfaces/ISyntax";
|
||||
|
||||
//TODO: https://github.com/collinbarrett/FilterLists/issues/488
|
||||
export const Syntax = (columnVisibility: IColumnVisibility[], syntaxes: ISyntax[]) => ({
|
||||
|
|
@ -8,7 +9,7 @@ export const Syntax = (columnVisibility: IColumnVisibility[], syntaxes: ISyntax[
|
|||
accessor: "syntaxId",
|
||||
filterable: true,
|
||||
filterMethod: (f: Filter, r: any[]) => filterMethod(f, r, syntaxes),
|
||||
Filter: ({ filter, onChange }: any) => Filter({ onChange, filter }, syntaxes),
|
||||
Filter: ({ filter, onChange }: any) => filterSyntaxes({ onChange, filter }, syntaxes),
|
||||
Cell: (c: any) => Cell(c.value, syntaxes),
|
||||
width: 155,
|
||||
show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Syntax")[0].visible
|
||||
|
|
@ -21,26 +22,26 @@ const filterMethod = (f: Filter, r: any[], syntaxes: ISyntax[]): boolean => {
|
|||
} else if (listSyntaxId) {
|
||||
const syntaxFiltered = syntaxes.filter((s: ISyntax) => s.id === parseInt(f.value));
|
||||
return syntaxFiltered[0].id
|
||||
? syntaxFiltered[0].id === listSyntaxId
|
||||
: false;
|
||||
? syntaxFiltered[0].id === listSyntaxId
|
||||
: false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const Filter = (props: any, syntaxes: ISyntax[]) =>
|
||||
const filterSyntaxes = (props: any, syntaxes: ISyntax[]) =>
|
||||
<select
|
||||
onChange={(event: any) => props.onChange(event.target.value)}
|
||||
style={{ width: "100%" }}
|
||||
value={props.filter ? props.filter.value : "any"}>
|
||||
<option value="any">Any</option>
|
||||
{syntaxes.length > 0
|
||||
? syntaxes.sort((a, b) => a.name.localeCompare(b.name)).map(
|
||||
(s: ISyntax, i: number) => <option value={s.id} key={i}>{s.name}</option>)
|
||||
: null}
|
||||
? syntaxes.sort((a, b) => a.name.localeCompare(b.name)).map(
|
||||
(s: ISyntax, i: number) => <option value={s.id} key={i}>{s.name}</option>)
|
||||
: null}
|
||||
</select>;
|
||||
|
||||
const Cell = (listSyntaxId: number, syntaxes: ISyntax[]) =>
|
||||
listSyntaxId
|
||||
? syntaxes.filter((s: ISyntax) => s.id === listSyntaxId)[0].name
|
||||
: null;
|
||||
? syntaxes.filter((s: ISyntax) => s.id === listSyntaxId)[0].name
|
||||
: null;
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
import * as React from "react";
|
||||
import { Column, Filter } from "react-table";
|
||||
import { TagGroup } from "../../TagGroup";
|
||||
import { IColumnVisibility, ITag } from "../../../interfaces";
|
||||
import { IColumnVisibility } from "../../../interfaces/IColumnVisibility";
|
||||
import { ITag } from "../../../interfaces/ITag";
|
||||
|
||||
export const Tags = (columnVisibility: IColumnVisibility[], tags: ITag[]) => {
|
||||
const tagsSorted = tags.sort((a: ITag, b: ITag) => a.name.localeCompare(b.name));
|
||||
|
|
@ -11,7 +12,7 @@ export const Tags = (columnVisibility: IColumnVisibility[], tags: ITag[]) => {
|
|||
accessor: "tagIds",
|
||||
filterable: true,
|
||||
filterMethod: (f: Filter, r: any[]) => filterMethod(f, r),
|
||||
Filter: ({ onChange, filter }: any) => Filter({ onChange, filter }, tagsSorted),
|
||||
Filter: ({ onChange, filter }: any) => filterTags({ onChange, filter }, tagsSorted),
|
||||
sortMethod: (a: number[], b: number[]) => sortMethod(a, b, tagsSorted),
|
||||
Cell: (c: any) => Cell(c.value, tagsSorted),
|
||||
width: 260,
|
||||
|
|
@ -22,42 +23,42 @@ export const Tags = (columnVisibility: IColumnVisibility[], tags: ITag[]) => {
|
|||
const filterMethod = (f: Filter, r: any[]): boolean => {
|
||||
const listTagIds = r[f.id as any];
|
||||
return f.value === "any" ||
|
||||
(listTagIds
|
||||
? listTagIds.join(",").split(",").includes(f.value)
|
||||
: f.value === "none");
|
||||
(listTagIds
|
||||
? listTagIds.join(",").split(",").includes(f.value)
|
||||
: f.value === "none");
|
||||
};
|
||||
|
||||
const Filter = (props: any, tags: ITag[]) =>
|
||||
const filterTags = (props: any, tags: ITag[]) =>
|
||||
<select onChange={(event: any) => props.onChange(event.target.value)}
|
||||
style={{ width: "100%" }}
|
||||
value={props.filter ? props.filter.value : "any"}>
|
||||
style={{ width: "100%" }}
|
||||
value={props.filter ? props.filter.value : "any"}>
|
||||
<option value="any">Any</option>
|
||||
<option value="none">None</option>
|
||||
{tags.length > 0
|
||||
? tags.map((t: ITag, i: number) =>
|
||||
<option value={t.id} title={t.description} key={i}>
|
||||
{t.name} ({t.filterListIds ? t.filterListIds.length : 0})
|
||||
? tags.map((t: ITag, i: number) =>
|
||||
<option value={t.id} title={t.description} key={i}>
|
||||
{t.name} ({t.filterListIds ? t.filterListIds.length : 0})
|
||||
</option>)
|
||||
: null}
|
||||
: null}
|
||||
</select>;
|
||||
|
||||
const sortMethod = (a: number[], b: number[], tags: ITag[]): any => {
|
||||
return a
|
||||
? b
|
||||
? a.length === b.length
|
||||
? tags.filter((t: ITag) => a.indexOf(t.id) > -1).map((t: ITag) => t.name).join()
|
||||
.toLowerCase() >
|
||||
tags.filter((t: ITag) => b.indexOf(t.id) > -1).map((t: ITag) => t.name).join().toLowerCase()
|
||||
? 1
|
||||
: -1
|
||||
: a.length > b.length
|
||||
? -1
|
||||
: 1
|
||||
: -1
|
||||
: 1;
|
||||
? b
|
||||
? a.length === b.length
|
||||
? tags.filter((t: ITag) => a.indexOf(t.id) > -1).map((t: ITag) => t.name).join()
|
||||
.toLowerCase() >
|
||||
tags.filter((t: ITag) => b.indexOf(t.id) > -1).map((t: ITag) => t.name).join().toLowerCase()
|
||||
? 1
|
||||
: -1
|
||||
: a.length > b.length
|
||||
? -1
|
||||
: 1
|
||||
: -1
|
||||
: 1;
|
||||
};
|
||||
|
||||
const Cell = (tagIds: number[], tags: ITag[]) =>
|
||||
tagIds
|
||||
? <TagGroup tags={tags.filter((t: ITag) => tagIds.indexOf(t.id) > -1)}/>
|
||||
: null;
|
||||
? <TagGroup tags={tags.filter((t: ITag) => tagIds.indexOf(t.id) > -1)} />
|
||||
: null;
|
||||
|
|
@ -1,33 +1,33 @@
|
|||
import * as React from "react";
|
||||
import { Column } from "react-table";
|
||||
import * as moment from "moment";
|
||||
import { IColumnVisibility } from "../../../interfaces";
|
||||
import moment from 'moment';
|
||||
import { IColumnVisibility } from "../../../interfaces/IColumnVisibility";
|
||||
|
||||
export const UpdatedDate = (columnVisibility: IColumnVisibility[]) =>
|
||||
({
|
||||
Header: <span title="The estimated date that the FilterList was last updated by the maintainer.">Updated</span>,
|
||||
accessor: "updatedDate",
|
||||
sortMethod: (a: string, b: string) => sortMethod(a, b),
|
||||
Cell: (c: any) => Cell(c.value),
|
||||
style: { whiteSpace: "inherit" },
|
||||
width: 100,
|
||||
show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Updated")[0].visible
|
||||
} as Column);
|
||||
({
|
||||
Header: <span title="The estimated date that the FilterList was last updated by the maintainer.">Updated</span>,
|
||||
accessor: "updatedDate",
|
||||
sortMethod: (a: string, b: string) => sortMethod(a, b),
|
||||
Cell: (c: any) => Cell(c.value),
|
||||
style: { whiteSpace: "inherit" },
|
||||
width: 100,
|
||||
show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Updated")[0].visible
|
||||
} as Column);
|
||||
|
||||
const sortMethod = (a: string, b: string) =>
|
||||
a && moment(a).isValid()
|
||||
? (b && moment(b).isValid()
|
||||
? (moment(a).isBefore(b)
|
||||
? 1
|
||||
: -1)
|
||||
: -1)
|
||||
: 1;
|
||||
? (b && moment(b).isValid()
|
||||
? (moment(a).isBefore(b)
|
||||
? 1
|
||||
: -1)
|
||||
: -1)
|
||||
: 1;
|
||||
|
||||
const Cell = (updatedDate: string) =>
|
||||
updatedDate
|
||||
? <div>
|
||||
{moment(updatedDate).isValid()
|
||||
? moment(updatedDate).format("l")
|
||||
: null}
|
||||
</div>
|
||||
: null;
|
||||
? <div>
|
||||
{moment(updatedDate).isValid()
|
||||
? moment(updatedDate).format("l")
|
||||
: null}
|
||||
</div>
|
||||
: null;
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
import { IColumnVisibility } from "./IColumnVisibility";
|
||||
import { ILanguage } from "./ILanguage";
|
||||
import { ILicense } from "./ILicense";
|
||||
import { IList } from "./IList";
|
||||
import { IMaintainer } from "./IMaintainer";
|
||||
import { ISoftware } from "./ISoftware";
|
||||
import { ISyntax } from "./ISyntax";
|
||||
import { ITag } from "./ITag";
|
||||
|
||||
export {
|
||||
IColumnVisibility,
|
||||
ILanguage,
|
||||
ILicense,
|
||||
IList,
|
||||
IMaintainer,
|
||||
ISoftware,
|
||||
ISyntax,
|
||||
ITag
|
||||
};
|
||||
Loading…
Reference in a new issue