mirror of
https://github.com/collinbarrett/FilterLists.git
synced 2026-03-11 09:04:27 +00:00
refactor api
This commit is contained in:
parent
3a8a01f4bc
commit
be67e4cccb
29 changed files with 505 additions and 369 deletions
|
|
@ -1,7 +1,4 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:s="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml"
|
||||
xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=6B3E6765_002D5B8B_002D4A23_002DAD12_002D7E2BC5F4D2E6_002Fd_003Awwwroot_002Fd_003Adist/@EntryIndexedValue">ExplicitlyExcluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/GeneratedCode/GeneratedFileMasks/=_002A_002EDesigner_002Ecs/@EntryIndexedValue"></s:String>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/GeneratedCode/GeneratedFileMasks/=_002A_002EDesigner_002Ecs/@EntryIndexRemoved">True</s:Boolean>
|
||||
|
|
@ -59,7 +56,7 @@
|
|||
</Entry.SortBy>
|
||||
</Entry>
|
||||
<Entry DisplayName="All other members" />
|
||||
<Entry DisplayName="Test Methods" Priority="100">
|
||||
<Entry Priority="100" DisplayName="Test Methods">
|
||||
<Entry.Match>
|
||||
<And>
|
||||
<Kind Is="Method" />
|
||||
|
|
@ -92,7 +89,7 @@
|
|||
</Entry.Match>
|
||||
</Entry>
|
||||
<Entry DisplayName="All other members" />
|
||||
<Entry DisplayName="Test Methods" Priority="100">
|
||||
<Entry Priority="100" DisplayName="Test Methods">
|
||||
<Entry.Match>
|
||||
<And>
|
||||
<Kind Is="Method" />
|
||||
|
|
@ -105,7 +102,7 @@
|
|||
</Entry>
|
||||
</TypePattern>
|
||||
<TypePattern DisplayName="Default Pattern">
|
||||
<Entry DisplayName="Public Delegates" Priority="100">
|
||||
<Entry Priority="100" DisplayName="Public Delegates">
|
||||
<Entry.Match>
|
||||
<And>
|
||||
<Access Is="Public" />
|
||||
|
|
@ -116,7 +113,7 @@
|
|||
<Name />
|
||||
</Entry.SortBy>
|
||||
</Entry>
|
||||
<Entry DisplayName="Public Enums" Priority="100">
|
||||
<Entry Priority="100" DisplayName="Public Enums">
|
||||
<Entry.Match>
|
||||
<And>
|
||||
<Access Is="Public" />
|
||||
|
|
@ -174,7 +171,7 @@
|
|||
<Access />
|
||||
</Entry.SortBy>
|
||||
</Entry>
|
||||
<Entry DisplayName="Interface Implementations" Priority="100">
|
||||
<Entry Priority="100" DisplayName="Interface Implementations">
|
||||
<Entry.Match>
|
||||
<And>
|
||||
<Kind Is="Member" />
|
||||
|
|
@ -195,6 +192,10 @@
|
|||
</Patterns></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAlwaysTreatStructAsNotReorderableMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=appsettings/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Wayback/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Waybacks/@EntryIndexedValue">True</s:Boolean>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
namespace FilterLists.Api.V1.Controllers
|
||||
{
|
||||
[ApiVersion("1.0")]
|
||||
[ApiVersion("1")]
|
||||
//TODO: use versioning without needing to manually specify in swagger-ui (https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/370)
|
||||
[Route("v{version:apiVersion}/[controller]")]
|
||||
[ResponseCache(Duration = 86400)]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { BrowserRouter } from "react-router-dom";
|
|||
import * as RoutesModule from "./Routes";
|
||||
let routes = RoutesModule.Routes;
|
||||
|
||||
function renderApp() {
|
||||
const renderApp = () => {
|
||||
const baseUrl = document.getElementsByTagName("base")[0].getAttribute("href")!;
|
||||
ReactDOM.render(
|
||||
<AppContainer>
|
||||
|
|
@ -13,7 +13,7 @@ function renderApp() {
|
|||
</AppContainer>,
|
||||
document.getElementById("react-app")
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderApp();
|
||||
|
||||
|
|
|
|||
|
|
@ -6,58 +6,51 @@ interface IProps {
|
|||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const Layout = (props: IProps) => {
|
||||
return <div className="container">
|
||||
<Header/>
|
||||
<div className="row">
|
||||
<div className="w-100">
|
||||
{ props.children }
|
||||
</div>
|
||||
</div>
|
||||
<Footer/>
|
||||
</div>;
|
||||
};
|
||||
export const Layout = (props: IProps) =>
|
||||
<div className="container">
|
||||
<Header/>
|
||||
<div className="row">
|
||||
<div className="w-100">
|
||||
{ props.children }
|
||||
</div>
|
||||
</div>
|
||||
<Footer/>
|
||||
</div>;
|
||||
|
||||
const Header = () => {
|
||||
return <header className="row">
|
||||
<h1>
|
||||
<a href="./">
|
||||
<img src="logo_filterlists.png" alt="FilterLists" className="img-fluid"/>
|
||||
</a>
|
||||
</h1>
|
||||
</header>;
|
||||
};
|
||||
const Header = () =>
|
||||
<header className="row">
|
||||
<h1>
|
||||
<a href="./">
|
||||
<img src="logo_filterlists.png" alt="FilterLists" className="img-fluid"/>
|
||||
</a>
|
||||
</h1>
|
||||
</header>;
|
||||
|
||||
const Footer = () => {
|
||||
return <footer className="row justify-content-center">
|
||||
<p className="mt-2 ml-1 mr-1">
|
||||
<ApiLink/> | <GitHubLink/> | <DonateLink/> | By <OwnerLink/>
|
||||
</p>
|
||||
</footer>;
|
||||
};
|
||||
const Footer = () =>
|
||||
<footer className="row justify-content-center">
|
||||
<p className="mt-2 ml-1 mr-1">
|
||||
<ApiLink/> | <GitHubLink/> | <DonateLink/> | By <OwnerLink/>
|
||||
</p>
|
||||
</footer>;
|
||||
|
||||
const ApiLink = () => {
|
||||
return <a href="https://filterlists.com/api/docs/index.html"
|
||||
title="API Swagger Docs">
|
||||
API
|
||||
</a>;
|
||||
};
|
||||
const ApiLink = () =>
|
||||
<a href="https://filterlists.com/api/docs/index.html"
|
||||
title="API Swagger Docs">
|
||||
API
|
||||
</a>;
|
||||
|
||||
const GitHubLink = () => {
|
||||
return <a href="https://github.com/collinbarrett/FilterLists">
|
||||
GitHub
|
||||
</a>;
|
||||
};
|
||||
const GitHubLink = () =>
|
||||
<a href="https://github.com/collinbarrett/FilterLists">
|
||||
GitHub
|
||||
</a>;
|
||||
|
||||
const DonateLink = () => {
|
||||
return <a href="https://beerpay.io/collinbarrett/FilterLists"
|
||||
title="Support with Beerpay">
|
||||
Donate
|
||||
</a>;
|
||||
};
|
||||
const DonateLink = () =>
|
||||
<a href="https://beerpay.io/collinbarrett/FilterLists"
|
||||
title="Support with Beerpay">
|
||||
Donate
|
||||
</a>;
|
||||
|
||||
const OwnerLink = () => {
|
||||
return <a href="https://collinmbarrett.com/">
|
||||
Collin M. Barrett
|
||||
</a>;
|
||||
};
|
||||
const OwnerLink = () =>
|
||||
<a href="https://collinmbarrett.com/">
|
||||
Collin M. Barrett
|
||||
</a>;
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import * as React from "react";
|
||||
import { IListDto, ISoftwareDto, ILanguageDto } from "./interfaces";
|
||||
import { Tagline, ListsTable, IColumnVisibility } from "./components";
|
||||
import { IColumnVisibility, ILanguage, IList, ISoftware, ITag } from "./interfaces";
|
||||
import { Tagline, ListsTable } from "./components";
|
||||
|
||||
const columnVisibilityDefaults = [
|
||||
const columnVisibilityDefaults: IColumnVisibility[] = [
|
||||
{ column: "Software", visible: true },
|
||||
{ column: "Tags", visible: true },
|
||||
{ column: "Languages", visible: true },
|
||||
|
|
@ -10,16 +10,17 @@ const columnVisibilityDefaults = [
|
|||
];
|
||||
|
||||
interface IProps {
|
||||
languages: ILanguageDto[];
|
||||
lists: IListDto[];
|
||||
languages: ILanguage[];
|
||||
lists: IList[];
|
||||
ruleCount: number;
|
||||
software: ISoftwareDto[];
|
||||
}
|
||||
software: ISoftware[];
|
||||
tags: ITag[];
|
||||
};
|
||||
|
||||
interface IState {
|
||||
columnVisibility: IColumnVisibility[];
|
||||
pageSize: number;
|
||||
}
|
||||
};
|
||||
|
||||
export class Home extends React.Component<IProps, IState> {
|
||||
constructor(props: IProps) {
|
||||
|
|
@ -33,32 +34,32 @@ export class Home extends React.Component<IProps, IState> {
|
|||
|
||||
componentDidMount() {
|
||||
this.updatePageSize();
|
||||
}
|
||||
|
||||
render() {
|
||||
return this.props.lists
|
||||
? <div>
|
||||
<Tagline listCount={this.props.lists.length} ruleCount={this.props.ruleCount}/>
|
||||
<ListsTable {...this.props} {...this.state}/>
|
||||
{this.renderColumnVisibilityCheckboxes()}
|
||||
</div>
|
||||
: null;
|
||||
}
|
||||
};
|
||||
|
||||
updatePageSize() {
|
||||
this.setState({
|
||||
pageSize: Math.max(Math.floor((window.innerHeight - 386) / 52), 5)
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
private renderColumnVisibilityCheckboxes() {
|
||||
return <div className="d-none d-md-block text-right">
|
||||
Visible: {this.state.columnVisibility.map(
|
||||
(c: IColumnVisibility, i) => this.renderColumnVisibilityCheckbox(c, i))}
|
||||
render() {
|
||||
return <div>
|
||||
<Tagline listCount={this.props.lists.length} ruleCount={this.props.ruleCount}/>
|
||||
<ListsTable {...this.props} {...this.state}/>
|
||||
{this.renderColumnVisibilityCheckboxes()}
|
||||
</div>;
|
||||
};
|
||||
|
||||
private renderColumnVisibilityCheckbox(props: IColumnVisibility, key: number) {
|
||||
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;
|
||||
};
|
||||
|
||||
renderColumnVisibilityCheckbox(props: IColumnVisibility, key: number) {
|
||||
return <div className="form-check form-check-inline" key={key}>
|
||||
<input className="form-check-input"
|
||||
type="checkbox"
|
||||
|
|
@ -70,21 +71,21 @@ export class Home extends React.Component<IProps, IState> {
|
|||
{props.column}
|
||||
</label>
|
||||
</div>;
|
||||
}
|
||||
};
|
||||
|
||||
private checkColumn(props: IColumnVisibility) {
|
||||
checkColumn(props: IColumnVisibility) {
|
||||
const columnVisibility = this.state.columnVisibility;
|
||||
const index = this.findWithAttr(columnVisibility, "column", props.column);
|
||||
columnVisibility[index].visible = !columnVisibility[index].visible;
|
||||
this.forceUpdate();
|
||||
}
|
||||
};
|
||||
|
||||
private findWithAttr(array: any, attr: string, value: string) {
|
||||
findWithAttr(array: any, attr: string, value: string) {
|
||||
for (let i = 0; i < array.length; i += 1) {
|
||||
if (array[i][attr] === value) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
@ -1,64 +1,67 @@
|
|||
import * as React from "react";
|
||||
import "isomorphic-fetch";
|
||||
import { ILanguageDto, IListDto, ISoftwareDto } from "./interfaces";
|
||||
import "../../utils/loader.css";
|
||||
import { ILanguage, IList, ISoftware, ITag } from "./interfaces";
|
||||
import { Home } from "./Home";
|
||||
|
||||
interface IState {
|
||||
languages: ILanguageDto[];
|
||||
lists: IListDto[];
|
||||
languages: ILanguage[];
|
||||
lists: IList[];
|
||||
ruleCount: number;
|
||||
software: ISoftwareDto[];
|
||||
}
|
||||
software: ISoftware[];
|
||||
tags: ITag[];
|
||||
};
|
||||
|
||||
export class HomeContainer extends React.Component<{}, IState> {
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
this.state = {
|
||||
lists: [],
|
||||
languages: [],
|
||||
lists: [],
|
||||
ruleCount: 0,
|
||||
software: []
|
||||
software: [],
|
||||
tags: []
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
fetch("https://filterlists.com/api/v1/lists")
|
||||
.then(r => r.json() as Promise<IListDto[]>)
|
||||
.then(d => {
|
||||
this.setState({
|
||||
lists: d
|
||||
});
|
||||
});
|
||||
this.fetchLists();
|
||||
this.fetchSoftware();
|
||||
this.fetchTags();
|
||||
this.fetchLanguages();
|
||||
this.fetchRuleCount();
|
||||
};
|
||||
|
||||
fetchLists() {
|
||||
fetch("https://filterlists.com/api/v1/lists/alpha")
|
||||
.then(r => r.json() as Promise<IList[]>)
|
||||
.then(d => { this.setState({ lists: d }); });
|
||||
};
|
||||
|
||||
fetchSoftware() {
|
||||
fetch("https://filterlists.com/api/v1/software")
|
||||
.then(r => r.json() as Promise<ISoftware[]>)
|
||||
.then(d => { this.setState({ software: d }); });
|
||||
};
|
||||
|
||||
fetchTags() {
|
||||
fetch("https://filterlists.com/api/v1/tags")
|
||||
.then(r => r.json() as Promise<ITag[]>)
|
||||
.then(d => { this.setState({ tags: d }); });
|
||||
};
|
||||
|
||||
fetchLanguages() {
|
||||
fetch("https://filterlists.com/api/v1/languages")
|
||||
.then(r => r.json() as Promise<ILanguage[]>)
|
||||
.then(d => { this.setState({ languages: d }); });
|
||||
};
|
||||
|
||||
fetchRuleCount() {
|
||||
fetch("https://filterlists.com/api/v1/rules")
|
||||
.then(r => r.json() as Promise<number>)
|
||||
.then(d => {
|
||||
this.setState({
|
||||
ruleCount: d
|
||||
});
|
||||
});
|
||||
fetch("https://filterlists.com/api/v1/software")
|
||||
.then(r => r.json() as Promise<ISoftwareDto[]>)
|
||||
.then(d => {
|
||||
this.setState({
|
||||
software: d
|
||||
});
|
||||
});
|
||||
fetch("https://filterlists.com/api/v1/languages")
|
||||
.then(r => r.json() as Promise<ILanguageDto[]>)
|
||||
.then(d => {
|
||||
this.setState({
|
||||
languages: d
|
||||
});
|
||||
});
|
||||
}
|
||||
.then(d => { this.setState({ ruleCount: d }); });
|
||||
};
|
||||
|
||||
render() {
|
||||
return this.state.lists.length === 0 ||
|
||||
this.state.ruleCount === 0 ||
|
||||
this.state.software.length === 0 ||
|
||||
this.state.languages.length === 0
|
||||
? <div className="loader">Loading...</div>
|
||||
: <Home {...this.state}/>;
|
||||
}
|
||||
}
|
||||
return <Home {...this.state}/>;
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
import * as React from "react";
|
||||
import { ITag } from "../interfaces";
|
||||
import { getContrast } from "../../../utils";
|
||||
|
||||
export const Tag = (props: ITag) => {
|
||||
const hexColor = kelly_colors_hex[props.id % kelly_colors_hex.length];
|
||||
return <span className="badge"
|
||||
style={{
|
||||
backgroundColor: `#${hexColor}`,
|
||||
color: getContrast(hexColor)
|
||||
}}
|
||||
title={props.description}>
|
||||
{props.name}
|
||||
</span>;
|
||||
};
|
||||
|
||||
//https://stackoverflow.com/a/4382138/2343739
|
||||
const kelly_colors_hex = [
|
||||
"FFB300", // Vivid Yellow
|
||||
"803E75", // Strong Purple
|
||||
"FF6800", // Vivid Orange
|
||||
"A6BDD7", // Very Light Blue
|
||||
"C10020", // Vivid Red
|
||||
"CEA262", // Grayish Yellow
|
||||
"817066", // Medium Gray
|
||||
"007D34", // Vivid Green
|
||||
"F6768E", // Strong Purplish Pink
|
||||
"00538A", // Strong Blue
|
||||
"FF7A5C", // Strong Yellowish Pink
|
||||
"53377A", // Strong Violet
|
||||
"FF8E00", // Vivid Orange Yellow
|
||||
"B32851", // Strong Purplish Red
|
||||
"F4C800", // Vivid Greenish Yellow
|
||||
"7F180D", // Strong Reddish Brown
|
||||
"93AA00", // Vivid Yellowish Green
|
||||
"593315", // Deep Yellowish Brown
|
||||
"F13A13", // Vivid Reddish Orange
|
||||
"232C16" // Dark Olive Green
|
||||
];
|
||||
|
|
@ -2,14 +2,16 @@
|
|||
|
||||
interface IProps {
|
||||
listCount: number;
|
||||
ruleCount: number,
|
||||
}
|
||||
ruleCount: number;
|
||||
};
|
||||
|
||||
export const Tagline = (props: IProps) => {
|
||||
return <p className="ml-2 mr-2">
|
||||
The independent, comprehensive directory of <strong>{props.ruleCount.toLocaleString()
|
||||
}</strong> unique rules across <strong>{
|
||||
props.listCount.toLocaleString()
|
||||
}</strong> filter and host lists for advertisements, trackers, malware, and annoyances.
|
||||
</p>;
|
||||
};
|
||||
export const Tagline = (props: IProps) =>
|
||||
props.listCount > 0 && props.ruleCount > 0
|
||||
? <p className="ml-2 mr-2">
|
||||
The independent, comprehensive directory of <strong>{props.ruleCount.toLocaleString()
|
||||
}</strong> unique rules across <strong>{props.listCount.toLocaleString()
|
||||
}</strong> filter and host lists for advertisements, trackers, malware, and annoyances.
|
||||
</p>
|
||||
: <p className="ml-2 mr-2">
|
||||
The independent, comprehensive directory of filter and host lists for advertisements, trackers, malware, and annoyances.
|
||||
</p>;
|
||||
|
|
@ -1,11 +1,9 @@
|
|||
import { DetailsExpander } from "./detailsExpander";
|
||||
import { ListsTable } from "./listsTable";
|
||||
import { IColumnVisibility } from "./listsTable";
|
||||
import { Tagline } from "./Tagline";
|
||||
|
||||
export {
|
||||
DetailsExpander,
|
||||
ListsTable,
|
||||
IColumnVisibility,
|
||||
Tagline
|
||||
};
|
||||
|
|
@ -1,183 +1,35 @@
|
|||
import * as React from "react";
|
||||
import { IListDto, ISoftwareDto, ILanguageDto } from "../../interfaces";
|
||||
import { IColumnVisibility, ILanguage, IList, ISoftware, ITag } from "../../interfaces";
|
||||
import "../../../../utils/loader.css";
|
||||
import ReactTable from "react-table"
|
||||
import "react-table/react-table.css"
|
||||
import "./listsTable.css";
|
||||
import { SoftwareIcon } from "../softwareIcon";
|
||||
import { getContrast } from "../../../../utils";
|
||||
import * as moment from "moment";
|
||||
import { DetailsButton, Languages, Name, Software, Tags, UpdatedDate } from "./columns";
|
||||
import { DetailsExpander } from "../../components";
|
||||
|
||||
export interface IColumnVisibility {
|
||||
column: string;
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
interface IProps {
|
||||
languages: ILanguageDto[];
|
||||
lists: IListDto[];
|
||||
software: ISoftwareDto[];
|
||||
languages: ILanguage[];
|
||||
lists: IList[];
|
||||
software: ISoftware[];
|
||||
tags: ITag[];
|
||||
columnVisibility: IColumnVisibility[];
|
||||
pageSize: number;
|
||||
}
|
||||
};
|
||||
|
||||
export const ListsTable = (props: IProps) => {
|
||||
return <ReactTable
|
||||
data={props.lists}
|
||||
key={props.pageSize}
|
||||
defaultPageSize={props.pageSize}
|
||||
showPageSizeOptions={false}
|
||||
columns={[
|
||||
{
|
||||
Header: "Name",
|
||||
accessor: "name",
|
||||
filterable: true,
|
||||
filterMethod: (f: any, r: any) =>
|
||||
r[f.id].toUpperCase().includes(f.value.toUpperCase()),
|
||||
sortMethod: (a: any, b: any) => a.toUpperCase() > b.toUpperCase() ? 1 : -1,
|
||||
Cell: (c: any) => <h2 className="mb-0">{c.value}</h2>
|
||||
},
|
||||
{
|
||||
Header: "Software",
|
||||
accessor: "softwareIds",
|
||||
filterable: true,
|
||||
filterMethod: (f: any, r: any) =>
|
||||
f.value === "any" || r[f.id].join(",").split(",").includes(f.value),
|
||||
Filter: ({ filter, onChange }) =>
|
||||
<select
|
||||
onChange={(event: any) => onChange(event.target.value)}
|
||||
style={{ width: "100%" }}
|
||||
value={filter ? filter.value : "any"}>
|
||||
<option value="any">Any</option>
|
||||
{props.software.map(
|
||||
(s: ISoftwareDto, i: number) => <option value={s.id} key={i}>{s.name}</option>)}
|
||||
</select>,
|
||||
sortable: false,
|
||||
Cell: (c: any) => c.value
|
||||
? c.value.map((s: number, i: number) => <SoftwareIcon id={s} key={i}/>)
|
||||
: null,
|
||||
width: 155,
|
||||
headerClassName: "d-none d-md-block",
|
||||
className: "d-none d-md-block",
|
||||
show: props.columnVisibility.filter(
|
||||
(c: IColumnVisibility) => { return c.column === "Software"; })[0].visible
|
||||
},
|
||||
{
|
||||
Header: "Tags",
|
||||
accessor: "tags",
|
||||
filterable: true,
|
||||
filterMethod: (f: any, r: any) =>
|
||||
(r[f.id]
|
||||
? r[f.id].map((e: any) => e.name).join().toUpperCase().includes(f.value.toUpperCase())
|
||||
: null),
|
||||
sortMethod: (a: any, b: any) => a
|
||||
? b
|
||||
? a.length === b.length
|
||||
? a[0].name > b[0].name
|
||||
? -1
|
||||
: 1
|
||||
: a.length > b.length
|
||||
? 1
|
||||
: -1
|
||||
: 1
|
||||
: -1,
|
||||
Cell: (c: any) => c.value
|
||||
? <div className="fl-tag-container">
|
||||
{c.value.map((e: any, i: number) =>
|
||||
<span className="badge"
|
||||
style={{
|
||||
backgroundColor: `#${e.colorHex}`,
|
||||
color: getContrast(`${e.colorHex}`)
|
||||
}}
|
||||
title={e.description}
|
||||
key={i}>
|
||||
{e.name}
|
||||
</span>)}
|
||||
</div>
|
||||
: null,
|
||||
width: 215,
|
||||
headerClassName: "d-none d-md-block",
|
||||
className: "d-none d-md-block",
|
||||
show: props.columnVisibility.filter(
|
||||
(c: IColumnVisibility) => { return c.column === "Tags"; })[0].visible
|
||||
},
|
||||
{
|
||||
Header: "Languages",
|
||||
accessor: "languages",
|
||||
filterable: true,
|
||||
filterMethod: (f: any, r: any) =>
|
||||
f.value === "any" ||
|
||||
(r[f.id]
|
||||
? r[f.id].map((x: any) => x.iso6391).includes(f.value)
|
||||
: false),
|
||||
Filter: ({ filter, onChange }) =>
|
||||
<select
|
||||
onChange={(event: any) => onChange(event.target.value)}
|
||||
style={{ width: "100%" }}
|
||||
value={filter ? filter.value : "any"}>
|
||||
<option value="any">Any</option>
|
||||
{props.languages
|
||||
? props.languages.map((l: ILanguageDto, i: number) =>
|
||||
<option value={l.iso6391} key={i}>{l.name}</option>)
|
||||
: null}
|
||||
</select>,
|
||||
sortable: false,
|
||||
Cell: (c: any) => c.value
|
||||
? <div className="fl-tag-container">
|
||||
{c.value.map((e: ILanguageDto, i: number) =>
|
||||
<span className="badge badge-secondary"
|
||||
title={e.name}
|
||||
key={i}>
|
||||
{e.iso6391}
|
||||
</span>)}
|
||||
</div>
|
||||
: null,
|
||||
style: { whiteSpace: "inherit" },
|
||||
width: 95,
|
||||
headerClassName: "d-none d-md-block",
|
||||
className: "d-none d-md-block",
|
||||
show: props.columnVisibility.filter(
|
||||
(c: IColumnVisibility) => { return c.column === "Languages"; })[0].visible
|
||||
},
|
||||
{
|
||||
Header: "Updated",
|
||||
accessor: "updatedDate",
|
||||
filterable: false,
|
||||
filterMethod: (f: any, r: any) => r[f.id].includes(f.value),
|
||||
sortMethod: (a: any, b: any) =>
|
||||
moment(a).isValid() ? (moment(b).isValid() ? (moment(a).isBefore(b) ? -1 : 1) : 1) : -1,
|
||||
Cell: (c: any) =>
|
||||
<div>
|
||||
{moment(c.value).isValid() ? moment(c.value).format("l") : "N/A"}
|
||||
</div>,
|
||||
style: { whiteSpace: "inherit" },
|
||||
width: 100,
|
||||
headerClassName: "d-none d-md-block",
|
||||
className: "d-none d-md-block",
|
||||
show: props.columnVisibility.filter(
|
||||
(c: IColumnVisibility) => { return c.column === "Updated Date"; })[0].visible
|
||||
},
|
||||
{
|
||||
Header: "Details",
|
||||
accessor: "id",
|
||||
sortable: false,
|
||||
expander: true,
|
||||
Expander: ({ isExpanded, row }) =>
|
||||
<div>
|
||||
{isExpanded
|
||||
? <button className="btn btn-primary btn-block active"
|
||||
title={`Collapse details about ${row.name}.`}>
|
||||
Details
|
||||
</button>
|
||||
: <button className="btn btn-primary btn-block"
|
||||
title={`Learn more about ${row.name}.`}>
|
||||
Details
|
||||
</button>}
|
||||
</div>,
|
||||
style: { textAlign: "center" },
|
||||
width: 90
|
||||
}
|
||||
]}
|
||||
SubComponent={(r: any) => <DetailsExpander listId={r.original.id}/>}
|
||||
className="-striped -highlight"/>;
|
||||
};
|
||||
export const ListsTable = (props: IProps) =>
|
||||
props.lists.length > 0 && props.languages.length > 0 && props.software.length > 0
|
||||
? <ReactTable
|
||||
data={props.lists}
|
||||
defaultPageSize={props.pageSize}
|
||||
showPageSizeOptions={false}
|
||||
columns={[
|
||||
Name,
|
||||
Software(props.columnVisibility, props.software),
|
||||
Tags(props.columnVisibility, props.tags),
|
||||
Languages(props.columnVisibility, props.languages),
|
||||
UpdatedDate(props.columnVisibility),
|
||||
DetailsButton
|
||||
]}
|
||||
SubComponent={(r: any) => <DetailsExpander listId={r.original.id}/>}
|
||||
className="-striped -highlight"/>
|
||||
: <div className="loader">Loading...</div>;
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import * as React from "react";
|
||||
import { Column, RowRenderProps } from "react-table";
|
||||
|
||||
export const DetailsButton = {
|
||||
Header: "Details",
|
||||
accessor: "id",
|
||||
sortable: false,
|
||||
expander: true,
|
||||
Expander: ({ isExpanded, row }: RowRenderProps) => Expander({ isExpanded, row }),
|
||||
style: { textAlign: "center" },
|
||||
width: 90
|
||||
} as Column;
|
||||
|
||||
const Expander = (props: RowRenderProps) =>
|
||||
<div>
|
||||
{props.isExpanded
|
||||
? <button className="btn btn-primary btn-block active"
|
||||
title={`Collapse details about ${props.row.name}.`}>
|
||||
Details
|
||||
</button>
|
||||
: <button className="btn btn-primary btn-block"
|
||||
title={`Learn more about ${props.row.name}.`}>
|
||||
Details
|
||||
</button>}
|
||||
</div>;
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
import * as React from "react";
|
||||
import { Column, Filter } from "react-table";
|
||||
import { IColumnVisibility, ILanguage } from "../../../interfaces";
|
||||
|
||||
export const Languages = (columnVisibility: IColumnVisibility[], languages: ILanguage[]) => {
|
||||
return {
|
||||
Header: "Languages",
|
||||
accessor: "languageIds",
|
||||
filterable: true,
|
||||
filterMethod: (f: Filter, r: any[]) => filterMethod(f, r),
|
||||
Filter: ({ onChange, filter }: any) => Filter({ onChange, filter }, languages),
|
||||
sortable: false,
|
||||
Cell: (c: any) => Cell(c.value, languages),
|
||||
style: { whiteSpace: "inherit" },
|
||||
width: 95,
|
||||
headerClassName: "d-none d-md-block",
|
||||
className: "d-none d-md-block",
|
||||
show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Languages")[0].visible
|
||||
} as Column;
|
||||
};
|
||||
|
||||
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)
|
||||
: false);
|
||||
};
|
||||
|
||||
const Filter = (props: any, languages: ILanguage[]) =>
|
||||
<select onChange={(event: any) => props.onChange(event.target.value)}
|
||||
style={{ width: "100%" }}
|
||||
value={props.filter ? props.filter.value : "any"}>
|
||||
<option value="any">Any</option>
|
||||
{languages.length > 0
|
||||
? languages.map((l: ILanguage, i: number) => <option value={l.id} key={i}>{l.name}</option>)
|
||||
: null}
|
||||
</select>;
|
||||
|
||||
const Cell = (languageIds: number[], languages: ILanguage[]) =>
|
||||
languageIds
|
||||
? <div className="fl-tag-container">
|
||||
{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;
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import * as React from "react";
|
||||
import { Column, Filter } from "react-table";
|
||||
|
||||
export const Name = {
|
||||
Header: "Name",
|
||||
accessor: "name",
|
||||
filterable: true,
|
||||
filterMethod: (f: Filter, r: any[]) => filterMethod(f, r),
|
||||
sortMethod: (a: string, b: string) => sortMethod(a, b),
|
||||
Cell: (c: any) => Cell(c.value)
|
||||
} as Column;
|
||||
|
||||
const filterMethod = (f: Filter, r: any[]): boolean =>
|
||||
r[f.id as any].toUpperCase().includes(f.value.toUpperCase());
|
||||
|
||||
const sortMethod = (a: string, b: string) =>
|
||||
a.toUpperCase() > b.toUpperCase() ? 1 : -1;
|
||||
|
||||
const Cell = (name: string) =>
|
||||
name
|
||||
? <h2 className="mb-0">{name}</h2>
|
||||
: null;
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import * as React from "react";
|
||||
import { Column, Filter } from "react-table";
|
||||
import { IColumnVisibility, ISoftware } from "../../../interfaces";
|
||||
import { SoftwareIcon } from "../../softwareIcon";
|
||||
|
||||
export const Software = (columnVisibility: IColumnVisibility[], software: ISoftware[]) => {
|
||||
return {
|
||||
Header: "Software",
|
||||
accessor: "syntaxId",
|
||||
filterable: true,
|
||||
filterMethod: (f: Filter, r: any[]) => filterMethod(f, r, software),
|
||||
Filter: ({ filter, onChange }: any) => Filter({ onChange, filter }, software),
|
||||
sortable: false,
|
||||
Cell: (c: any) => Cell(c.value, software),
|
||||
width: 155,
|
||||
headerClassName: "d-none d-md-block",
|
||||
className: "d-none d-md-block",
|
||||
show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Software")[0].visible
|
||||
} as Column;
|
||||
};
|
||||
|
||||
const filterMethod = (f: Filter, r: any[], software: ISoftware[]): boolean => {
|
||||
const isAny = f.value === "any";
|
||||
const softwareFiltered = isAny ? software : software.filter((s: ISoftware) => s.id === parseInt(f.value));
|
||||
const listSyntaxId: number = r[f.id as any];
|
||||
const isMatch = softwareFiltered[0].syntaxIds ? softwareFiltered[0].syntaxIds.indexOf(listSyntaxId) > -1 : false;
|
||||
return isAny || (listSyntaxId ? isMatch : false);
|
||||
};
|
||||
|
||||
const Filter = (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}
|
||||
</select>;
|
||||
|
||||
const Cell = (listSyntaxId: number, software: ISoftware[]) =>
|
||||
listSyntaxId
|
||||
? software.filter((s: ISoftware) => s.syntaxIds.indexOf(listSyntaxId) > -1)
|
||||
.map((s: ISoftware, i: number) => <SoftwareIcon id={s.id} key={i}/>)
|
||||
: null;
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
import * as React from "react";
|
||||
import { Column, Filter } from "react-table";
|
||||
import { Tag } from "../../Tag"
|
||||
import { IColumnVisibility, ITag } from "../../../interfaces";
|
||||
|
||||
export const Tags = (columnVisibility: IColumnVisibility[], tags: ITag[]) => {
|
||||
return {
|
||||
Header: "Tags",
|
||||
accessor: "tagIds",
|
||||
filterable: true,
|
||||
filterMethod: (f: Filter, r: any[]) => filterMethod(f, r, tags),
|
||||
sortMethod: (a: number[], b: number[]) => sortMethod(a, b),
|
||||
Cell: (c: any) => Cell(c.value, tags),
|
||||
width: 215,
|
||||
headerClassName: "d-none d-md-block",
|
||||
className: "d-none d-md-block",
|
||||
show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Tags")[0].visible
|
||||
} as Column;
|
||||
};
|
||||
|
||||
const filterMethod = (f: Filter, r: any[], tags: ITag[]): boolean => {
|
||||
const listTagIds = r[f.id as any];
|
||||
if (f.value.length > 0 && listTagIds && listTagIds.length > 0) {
|
||||
const listTags = tags.filter((t: ITag) => listTagIds.includes(t.id));
|
||||
const listTagNames = listTags.map((t: ITag) => t.name.toLowerCase()).join(",").split(",");
|
||||
return listTagNames.filter((l: string) => l.indexOf(f.value.toLowerCase()) > -1).length > 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const sortMethod = (a: number[], b: number[]): any =>
|
||||
a
|
||||
? b
|
||||
? a.length > b.length
|
||||
? 1
|
||||
: -1
|
||||
: 1
|
||||
: -1;
|
||||
|
||||
const Cell = (tagIds: number[], tags: ITag[]) =>
|
||||
tagIds
|
||||
? <div className="fl-tag-container">
|
||||
{tagIds.map((tid: number, i: number) => {
|
||||
const tag = tags.filter((t: ITag) => t.id === tid)[0];
|
||||
return <Tag {...tag} key={i}/>;
|
||||
})}
|
||||
</div>
|
||||
: null;
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
import * as React from "react";
|
||||
import { Column } from "react-table";
|
||||
import * as moment from "moment";
|
||||
import { IColumnVisibility } from "../../../interfaces";
|
||||
|
||||
export const UpdatedDate = (columnVisibility: IColumnVisibility[]) => {
|
||||
return {
|
||||
Header: "Updated",
|
||||
accessor: "updatedDate",
|
||||
sortMethod: (a: string, b: string) => sortMethod(a, b),
|
||||
Cell: (c: any) => Cell(c.value),
|
||||
style: { whiteSpace: "inherit" },
|
||||
width: 100,
|
||||
headerClassName: "d-none d-md-block",
|
||||
className: "d-none d-md-block",
|
||||
show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Updated Date")[0].visible
|
||||
} as Column;
|
||||
};
|
||||
|
||||
const sortMethod = (a: string, b: string) =>
|
||||
moment(a).isValid()
|
||||
? (moment(b).isValid()
|
||||
? (moment(a).isBefore(b)
|
||||
? -1
|
||||
: 1)
|
||||
: 1)
|
||||
: -1;
|
||||
|
||||
const Cell = (updatedDate: string) =>
|
||||
<div>
|
||||
{moment(updatedDate).isValid()
|
||||
? moment(updatedDate).format("l")
|
||||
: null}
|
||||
</div>;
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import { DetailsButton } from "./DetailsButton";
|
||||
import { Languages } from "./Languages";
|
||||
import { Name } from "./Name";
|
||||
import { Software } from "./Software";
|
||||
import { Tags } from "./Tags";
|
||||
import { UpdatedDate } from "./UpdatedDate";
|
||||
|
||||
export {
|
||||
DetailsButton,
|
||||
Languages,
|
||||
Name,
|
||||
Software,
|
||||
Tags,
|
||||
UpdatedDate
|
||||
};
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
import { ListsTable, IColumnVisibility } from "./ListsTable";
|
||||
import { ListsTable } from "./ListsTable";
|
||||
|
||||
export {
|
||||
ListsTable,
|
||||
IColumnVisibility
|
||||
};
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
export interface IColumnVisibility {
|
||||
column: string;
|
||||
visible: boolean;
|
||||
};
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
export interface ILanguage {
|
||||
id: number;
|
||||
iso6391: string;
|
||||
name: string;
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
export interface ILanguageDto {
|
||||
iso6391: string;
|
||||
name: string;
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
export interface IList {
|
||||
id: number;
|
||||
languageIds: number[];
|
||||
name: string;
|
||||
syntaxId: number;
|
||||
tagIds: number[];
|
||||
updatedDate: string;
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
export interface IListDto {
|
||||
id: number;
|
||||
languages: IListLanguageDto[];
|
||||
name: string;
|
||||
softwareIds: number[];
|
||||
tags: IListTagDto[];
|
||||
updatedDate: string;
|
||||
}
|
||||
|
||||
interface IListLanguageDto {
|
||||
name: string;
|
||||
iso6391: string;
|
||||
}
|
||||
|
||||
interface IListTagDto {
|
||||
name: string;
|
||||
colorHex: string;
|
||||
description: string;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
export interface ISoftware {
|
||||
id: number;
|
||||
name: string;
|
||||
syntaxIds: number[];
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
export interface ISoftwareDto {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
export interface ITag {
|
||||
id: number;
|
||||
description: string;
|
||||
name: string;
|
||||
}
|
||||
|
|
@ -1,9 +1,14 @@
|
|||
import { ILanguageDto } from "./ILanguageDto";
|
||||
import { IListDto } from "./IListDto";
|
||||
import { ISoftwareDto } from "./ISoftwareDto";
|
||||
import { IColumnVisibility } from "./IColumnVisibility";
|
||||
import { ILanguage } from "./ILanguage";
|
||||
import { IList } from "./IList";
|
||||
import { ISoftware } from "./ISoftware";
|
||||
import { ITag } from "./ITag";
|
||||
|
||||
|
||||
export {
|
||||
ILanguageDto,
|
||||
IListDto,
|
||||
ISoftwareDto
|
||||
IColumnVisibility,
|
||||
ILanguage,
|
||||
IList,
|
||||
ISoftware,
|
||||
ITag
|
||||
};
|
||||
|
|
@ -5,4 +5,4 @@ export const getContrast = (hexcolor: string) => {
|
|||
const b = parseInt(hexcolor.substr(4, 2), 16);
|
||||
const yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
|
||||
return (yiq >= 128) ? "black" : "white";
|
||||
}
|
||||
};
|
||||
26
src/FilterLists.Web/npm-shrinkwrap.json
generated
26
src/FilterLists.Web/npm-shrinkwrap.json
generated
|
|
@ -85,7 +85,7 @@
|
|||
"@types/webpack-env": {
|
||||
"version": "1.13.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.13.6.tgz",
|
||||
"integrity": "sha1-Eo0WhafDTTHtFwEPyH1qEsHeaXY=",
|
||||
"integrity": "sha512-5Th3OsZ4gTRdr9Mho83BQ23cex4sRhOR4XTG+m+cJc0FhtUBK9Vn62hBJ+pnQYnSxoPOsKoAPOx6FcphxBC8ng==",
|
||||
"dev": true
|
||||
},
|
||||
"acorn": {
|
||||
|
|
@ -496,7 +496,7 @@
|
|||
"bootstrap": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.1.3.tgz",
|
||||
"integrity": "sha1-DrNxryyESOjCEEEdDLgkpkCaEr4=",
|
||||
"integrity": "sha512-rDFIzgXcof0jDyjNosjv4Sno77X4KuPeFxG2XZZv1/Kc8DRVGVADdoQyyOVDwPqL36DDmtCQbrpMCqvpPLJQ0w==",
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
|
|
@ -1735,7 +1735,7 @@
|
|||
"extract-text-webpack-plugin": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz",
|
||||
"integrity": "sha1-XwQ+qgL5dQqSWLeMCm4NwUCPsvc=",
|
||||
"integrity": "sha512-bt/LZ4m5Rqt/Crl2HiKuAl/oqg0psx1tsTLkvWbJen1CtD+fftkZhMaQ9HOtY2gWsl2Wq+sABmMVi9z3DhKWQQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async": "^2.4.1",
|
||||
|
|
@ -2892,7 +2892,7 @@
|
|||
"history": {
|
||||
"version": "4.7.2",
|
||||
"resolved": "https://registry.npmjs.org/history/-/history-4.7.2.tgz",
|
||||
"integrity": "sha1-IrXH8xYzxbgCHH9KipVKwTnujVs=",
|
||||
"integrity": "sha512-1zkBRWW6XweO0NBcjiphtVJVsIQ+SXF29z9DVkceeaSLVMFXHool+fdCZD4spDCfZJCILPILc3bm7Bc+HRi0nA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"invariant": "^2.2.1",
|
||||
|
|
@ -2927,7 +2927,7 @@
|
|||
"hoist-non-react-statics": {
|
||||
"version": "2.5.5",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
|
||||
"integrity": "sha1-xZA89AnA39kI84jmGdhrnBF0y0c=",
|
||||
"integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==",
|
||||
"dev": true
|
||||
},
|
||||
"hosted-git-info": {
|
||||
|
|
@ -3059,7 +3059,7 @@
|
|||
"invariant": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
||||
"integrity": "sha1-YQ88ksk1nOHbYW5TgAjSP/NRWOY=",
|
||||
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.0.0"
|
||||
|
|
@ -3297,7 +3297,7 @@
|
|||
"jquery": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz",
|
||||
"integrity": "sha1-lYzinoHJeQ8xvneS311NlfxX+8o=",
|
||||
"integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==",
|
||||
"dev": true
|
||||
},
|
||||
"js-base64": {
|
||||
|
|
@ -3331,7 +3331,7 @@
|
|||
"json-loader": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz",
|
||||
"integrity": "sha1-3KFKcCNf+C8KyaOr62DTN6NlGF0=",
|
||||
"integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==",
|
||||
"dev": true
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
|
|
@ -4829,7 +4829,7 @@
|
|||
"react-router": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz",
|
||||
"integrity": "sha1-qtpK7xTICcsuaGsFzuR0IjRQbE4=",
|
||||
"integrity": "sha512-yrvL8AogDh2X42Dt9iknk4wF4V8bWREPirFfS9gLU1huk6qK41sg7Z/1S81jjTrGHxa3B8R3J6xIkDAA6CVarg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"history": "^4.7.2",
|
||||
|
|
@ -4844,7 +4844,7 @@
|
|||
"react-router-dom": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-4.3.1.tgz",
|
||||
"integrity": "sha1-TCYZ/CTE+ofJ/Rj0+0pD/mP71cY=",
|
||||
"integrity": "sha512-c/MlywfxDdCp7EnB7YfPMOfMD3tOtIjrQlj/CKfNMBxdmpJP8xcz5P/UAFn3JbnQCNUxsHyVVqllF9LhgVyFCA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"history": "^4.7.2",
|
||||
|
|
@ -5021,7 +5021,7 @@
|
|||
"resolve-pathname": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.2.0.tgz",
|
||||
"integrity": "sha1-fpriHtgV/WOrGJre7mTcgx7vqHk=",
|
||||
"integrity": "sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg==",
|
||||
"dev": true
|
||||
},
|
||||
"resolve-url": {
|
||||
|
|
@ -6123,7 +6123,7 @@
|
|||
"value-equal": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/value-equal/-/value-equal-0.4.0.tgz",
|
||||
"integrity": "sha1-xb3S9U7gk8BIOdcc4uR1imiQq8c=",
|
||||
"integrity": "sha512-x+cYdNnaA3CxvMaTX0INdTCN8m8aF2uY9BvEqmxuYp8bL09cs/kWVQPVGcA35fMktdOsP69IgU7wFj/61dJHEw==",
|
||||
"dev": true
|
||||
},
|
||||
"vendors": {
|
||||
|
|
@ -6144,7 +6144,7 @@
|
|||
"warning": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.1.tgz",
|
||||
"integrity": "sha1-Zs43a3+/6KiHwivfDnNJ1z05d0U=",
|
||||
"integrity": "sha512-rAVtTNZw+cQPjvGp1ox0XC5Q2IBFyqoqh+QII4J/oguyu83Bax1apbo2eqB8bHRS+fqYUBagys6lqUoVwKSmXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.0.0"
|
||||
|
|
|
|||
Loading…
Reference in a new issue