diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx
index fb2e3d3ed..73523b53e 100644
--- a/src/FilterLists.Web.V2/src/App.tsx
+++ b/src/FilterLists.Web.V2/src/App.tsx
@@ -1,13 +1,13 @@
import { Layout, Menu } from 'antd';
import React from 'react';
-import { BrowserRouter, Route, RouteComponentProps, Switch } from 'react-router-dom';
+import { BrowserRouter as Router, Route, RouteComponentProps, Switch } from 'react-router-dom';
-import { AllListsTable } from './components';
+import { ListsTable } from './components';
const { Header, Content, Footer } = Layout;
export const App: React.FC = () =>
-
+
@@ -16,7 +16,7 @@ export const App: React.FC = () =>
-
+
@@ -25,7 +25,7 @@ export const App: React.FC = () =>
| | | |
- ;
+ ;
const Logo = (): JSX.Element =>
+ ;
\ No newline at end of file
diff --git a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx
new file mode 100644
index 000000000..92ce66130
--- /dev/null
+++ b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx
@@ -0,0 +1,19 @@
+import { Drawer } from 'antd';
+import React from 'react';
+import { RouteComponentProps } from 'react-router-dom';
+
+import { List } from '../interfaces/List';
+import { Description } from './Description';
+import { SubscribeButton } from './subscribeButton';
+
+interface Props {
+ list: List;
+};
+
+export const ListDetailsDrawer = (props: RouteComponentProps & Props) =>
+ props.history.push("/")}>
+
+
+ ;
\ No newline at end of file
diff --git a/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx
deleted file mode 100644
index 36c927aab..000000000
--- a/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx
+++ /dev/null
@@ -1,159 +0,0 @@
-import { Table } from 'antd';
-import React from 'react';
-
-import { Description, LanguageCloud, ListDetails, TagCloud } from '..';
-import { Language } from '../../interfaces/Language';
-import { List } from '../../interfaces/List';
-import { Tag } from '../../interfaces/Tag';
-import { nameof } from '../../utils';
-import styles from './AllListsTable.module.css';
-
-interface State {
- lists: List[];
- languages: Language[];
- tags: Tag[];
- pageSize: number;
- pageSizeOptions: string[];
- isNarrowWindow: boolean;
-}
-
-export class AllListsTable extends React.Component<{}, State> {
- constructor(props: any) {
- super(props);
- this.state = {
- lists: [],
- languages: [],
- tags: [],
- pageSize: 0,
- pageSizeOptions: [],
- isNarrowWindow: false
- };
- this.updatePageSize = this.updatePageSize.bind(this);
- }
-
- componentDidMount() {
- this.fetchData();
- this.updatePageSize();
- window.addEventListener('resize', this.updatePageSize);
- }
-
- private fetchData() {
- fetch("/api/v1/lists")
- .then(response => response.json())
- .then(json => (json as List[]).sort((a, b) => a.name.localeCompare(b.name)))
- .then(lists => { this.setState({ lists: lists }); })
-
- fetch("/api/v1/languages")
- .then(response => response.json())
- .then(json => (json as Language[]).sort((a, b) => a.name.localeCompare(b.name)))
- .then(languages => { this.setState({ languages: languages }); })
-
- fetch("/api/v1/tags")
- .then(response => response.json())
- .then(json => (json as Tag[]).sort((a, b) => a.name.localeCompare(b.name)))
- .then(tags => { this.setState({ tags: tags }); })
- }
-
- private updatePageSize() {
- const pageSize = Math.floor((window.innerHeight - 211.5) / 56);
- this.setState({
- pageSize: pageSize,
- pageSizeOptions: [pageSize, 200, 2000].sort((a, b) => a - b).map(String),
- isNarrowWindow: window.innerWidth < 576 ? true : false
- });
- }
-
- render() {
- return (
-
- dataSource={this.state.lists}
- rowKey={record => record.id.toString()}
- loading={this.state.lists.length ? false : true}
- size="small"
- pagination={{
- size: "small",
- pageSize: this.state.pageSize,
- showSizeChanger: true,
- pageSizeOptions: this.state.pageSizeOptions
- }}
- scroll={{ x: this.state.isNarrowWindow ? undefined : 1200 }}>
-
- title="Name"
- dataIndex={nameof("name")}
- sorter={(a, b) => a.name.localeCompare(b.name)}
- defaultSortOrder={"ascend"}
- width={this.state.isNarrowWindow ? undefined : 200}
- className={styles.nogrow}
- fixed="left"
- render={(text: string) => {text}
} />
- {this.state.isNarrowWindow
- ? null
- :
- title="Description"
- dataIndex={nameof("description")}
- className={styles.nogrow}
- render={(_text: string, record: List) => } />}
- {this.state.isNarrowWindow
- ? null
- :
- title="Software"
- dataIndex={nameof("syntaxId")}
- className={styles.nogrow}
- render={(text: string) => {text}
} />}
- {this.state.isNarrowWindow
- ? null
- :
- title="Languages"
- dataIndex={nameof("languageIds")}
- sorter={(a, b) => arraySorter(a.languageIds, b.languageIds, this.state.languages)}
- width={125}
- className={styles.nogrow}
- render={(languageIds: number[]) =>
- languageIds
- ? languageIds.includes(l.id))} />
- : null} />}
- {this.state.isNarrowWindow
- ? null
- :
- title="Tags"
- dataIndex={nameof("tagIds")}
- sorter={(a, b) => arraySorter(a.tagIds, b.tagIds, this.state.tags)}
- width={275}
- className={styles.nogrow}
- render={(tagIds: number[]) =>
- tagIds
- ? tagIds.includes(t.id))} />
- : null} />}
-
- title="Details"
- dataIndex={nameof("viewUrl")}
- className={styles.nogrow}
- fixed="right"
- render={(_text: string, record: List) => } />
-
- );
- }
-
- componentWillUnmount() {
- window.removeEventListener('resize', this.updatePageSize);
- }
-}
-
-interface ArraySortableEntity {
- id: number;
- name: string;
-}
-
-const arraySorter = (a: number[], b: number[], entities: ArraySortableEntity[]): number =>
- a && a.length
- ? b && b.length
- ? a.length === b.length
- ? entities.filter((e: ArraySortableEntity) => a.indexOf(e.id) > -1).map((e: ArraySortableEntity) => e.name).join().toLowerCase()
- > entities.filter((e: ArraySortableEntity) => b.indexOf(e.id) > -1).map((e: ArraySortableEntity) => e.name).join().toLowerCase()
- ? 1
- : -1
- : a.length > b.length
- ? -1
- : 1
- : -1
- : 1;
\ No newline at end of file
diff --git a/src/FilterLists.Web.V2/src/components/allListsTable/index.ts b/src/FilterLists.Web.V2/src/components/allListsTable/index.ts
deleted file mode 100644
index 35e7597f6..000000000
--- a/src/FilterLists.Web.V2/src/components/allListsTable/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import { AllListsTable } from './AllListsTable';
-
-export { AllListsTable }
\ No newline at end of file
diff --git a/src/FilterLists.Web.V2/src/components/buttons/index.ts b/src/FilterLists.Web.V2/src/components/buttons/index.ts
deleted file mode 100644
index a551734b5..000000000
--- a/src/FilterLists.Web.V2/src/components/buttons/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import { SubscribeButton } from './subscribe';
-
-export { SubscribeButton }
\ No newline at end of file
diff --git a/src/FilterLists.Web.V2/src/components/index.ts b/src/FilterLists.Web.V2/src/components/index.ts
index a14e1b807..654f34a7d 100644
--- a/src/FilterLists.Web.V2/src/components/index.ts
+++ b/src/FilterLists.Web.V2/src/components/index.ts
@@ -1,8 +1,3 @@
-import { AllListsTable } from './allListsTable';
-import { SubscribeButton } from './buttons';
-import { Description } from './Description';
-import { LanguageCloud } from './languageCloud';
-import { ListDetails } from './listDetails';
-import { TagCloud } from './tagCloud';
+import { ListsTable } from './listsTable';
-export { SubscribeButton, Description, LanguageCloud, TagCloud, AllListsTable, ListDetails };
+export { ListsTable };
diff --git a/src/FilterLists.Web.V2/src/components/listDetails/ListDetails.tsx b/src/FilterLists.Web.V2/src/components/listDetails/ListDetails.tsx
deleted file mode 100644
index 7a1bb5131..000000000
--- a/src/FilterLists.Web.V2/src/components/listDetails/ListDetails.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-import { Button, Drawer } from 'antd';
-import React from 'react';
-
-import { Description } from '..';
-import { List } from '../../interfaces/List';
-import { SubscribeButton } from '../buttons';
-
-interface State {
- visible: boolean;
-}
-
-interface Props {
- list: List;
-};
-
-export class ListDetails extends React.Component {
- constructor(props: any) {
- super(props);
- this.state = {
- visible: false
- };
- }
-
- render() {
- return (
-
-
- this.setState({ visible: false, })}>
-
-
-
-
- )
- }
-}
\ No newline at end of file
diff --git a/src/FilterLists.Web.V2/src/components/listDetails/index.ts b/src/FilterLists.Web.V2/src/components/listDetails/index.ts
deleted file mode 100644
index d1f027755..000000000
--- a/src/FilterLists.Web.V2/src/components/listDetails/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import { ListDetails } from './ListDetails';
-
-export { ListDetails };
diff --git a/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.module.css b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.module.css
similarity index 100%
rename from src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.module.css
rename to src/FilterLists.Web.V2/src/components/listsTable/ListsTable.module.css
diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx
new file mode 100644
index 000000000..d55644291
--- /dev/null
+++ b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx
@@ -0,0 +1,172 @@
+import { Table } from 'antd';
+import React from 'react';
+import { Route, RouteComponentProps } from 'react-router-dom';
+
+import { Language } from '../../interfaces/Language';
+import { List } from '../../interfaces/List';
+import { Tag } from '../../interfaces/Tag';
+import { nameof } from '../../utils';
+import { Description } from '../Description';
+import { LanguageCloud } from '../languageCloud';
+import { ListDetailsButton } from '../ListDetailsButton';
+import { ListDetailsDrawer } from '../ListDetailsDrawer';
+import { TagCloud } from '../tagCloud';
+import styles from './ListsTable.module.css';
+
+interface State {
+ lists: List[];
+ languages: Language[];
+ tags: Tag[];
+ pageSize: number;
+ pageSizeOptions: string[];
+ isNarrowWindow: boolean;
+}
+
+export class ListsTable extends React.Component {
+ constructor(props: any) {
+ super(props);
+ this.state = {
+ lists: [],
+ languages: [],
+ tags: [],
+ pageSize: 0,
+ pageSizeOptions: [],
+ isNarrowWindow: false
+ };
+ this.updatePageSize = this.updatePageSize.bind(this);
+ }
+
+ componentDidMount() {
+ this.fetchData();
+ this.updatePageSize();
+ window.addEventListener('resize', this.updatePageSize);
+ }
+
+ private fetchData() {
+ fetch("/api/v1/lists")
+ .then(response => response.json())
+ .then(json => (json as List[]).sort((a, b) => a.name.localeCompare(b.name)))
+ .then(lists => { this.setState({ lists: lists }); })
+
+ fetch("/api/v1/languages")
+ .then(response => response.json())
+ .then(json => (json as Language[]).sort((a, b) => a.name.localeCompare(b.name)))
+ .then(languages => { this.setState({ languages: languages }); })
+
+ fetch("/api/v1/tags")
+ .then(response => response.json())
+ .then(json => (json as Tag[]).sort((a, b) => a.name.localeCompare(b.name)))
+ .then(tags => { this.setState({ tags: tags }); })
+ }
+
+ private updatePageSize() {
+ const pageSize = Math.floor((window.innerHeight - 211.5) / 56);
+ this.setState({
+ pageSize: pageSize,
+ pageSizeOptions: [pageSize, 200, 2000].sort((a, b) => a - b).map(String),
+ isNarrowWindow: window.innerWidth < 576 ? true : false
+ });
+ }
+
+ render() {
+ return (
+
+
+ dataSource={this.state.lists}
+ rowKey={record => record.id.toString()}
+ loading={this.state.lists.length ? false : true}
+ size="small"
+ pagination={{
+ size: "small",
+ pageSize: this.state.pageSize,
+ showSizeChanger: true,
+ pageSizeOptions: this.state.pageSizeOptions
+ }}
+ scroll={{ x: this.state.isNarrowWindow ? undefined : 1200 }}>
+
+ title="Name"
+ dataIndex={nameof("name")}
+ sorter={(a, b) => a.name.localeCompare(b.name)}
+ defaultSortOrder={"ascend"}
+ width={this.state.isNarrowWindow ? undefined : 200}
+ className={styles.nogrow}
+ fixed="left"
+ render={(text: string) => {text}
} />
+ {this.state.isNarrowWindow
+ ? null
+ :
+ title="Description"
+ dataIndex={nameof("description")}
+ className={styles.nogrow}
+ render={(_text: string, record: List) => } />}
+ {this.state.isNarrowWindow
+ ? null
+ :
+ title="Software"
+ dataIndex={nameof("syntaxId")}
+ className={styles.nogrow}
+ render={(text: string) => {text}
} />}
+ {this.state.isNarrowWindow
+ ? null
+ :
+ title="Languages"
+ dataIndex={nameof("languageIds")}
+ sorter={(a, b) => arraySorter(a.languageIds, b.languageIds, this.state.languages)}
+ width={125}
+ className={styles.nogrow}
+ render={(languageIds: number[]) =>
+ languageIds
+ ? languageIds.includes(l.id))} />
+ : null} />}
+ {this.state.isNarrowWindow
+ ? null
+ :
+ title="Tags"
+ dataIndex={nameof("tagIds")}
+ sorter={(a, b) => arraySorter(a.tagIds, b.tagIds, this.state.tags)}
+ width={275}
+ className={styles.nogrow}
+ render={(tagIds: number[]) =>
+ tagIds
+ ? tagIds.includes(t.id))} />
+ : null} />}
+
+ title="Details"
+ dataIndex={nameof("viewUrl")}
+ className={styles.nogrow}
+ fixed="right"
+ render={(_text: string, record: List) => } />
+
+ {
+ const list = this.state.lists.find(l => l.id === +props.match.params.id);
+ return list
+ ?
+ : null //TODO: redirect or 404 for invalid list id
+ }} />
+
+ );
+ }
+
+ componentWillUnmount() {
+ window.removeEventListener('resize', this.updatePageSize);
+ }
+}
+
+interface ArraySortableEntity {
+ id: number;
+ name: string;
+}
+
+const arraySorter = (a: number[], b: number[], entities: ArraySortableEntity[]): number =>
+ a && a.length
+ ? b && b.length
+ ? a.length === b.length
+ ? entities.filter((e: ArraySortableEntity) => a.indexOf(e.id) > -1).map((e: ArraySortableEntity) => e.name).join().toLowerCase()
+ > entities.filter((e: ArraySortableEntity) => b.indexOf(e.id) > -1).map((e: ArraySortableEntity) => e.name).join().toLowerCase()
+ ? 1
+ : -1
+ : a.length > b.length
+ ? -1
+ : 1
+ : -1
+ : 1;
\ No newline at end of file
diff --git a/src/FilterLists.Web.V2/src/components/listsTable/index.ts b/src/FilterLists.Web.V2/src/components/listsTable/index.ts
new file mode 100644
index 000000000..ad67ef839
--- /dev/null
+++ b/src/FilterLists.Web.V2/src/components/listsTable/index.ts
@@ -0,0 +1,3 @@
+import { ListsTable } from './ListsTable';
+
+export { ListsTable }
\ No newline at end of file
diff --git a/src/FilterLists.Web.V2/src/components/buttons/subscribe/SubscribeButton.module.css b/src/FilterLists.Web.V2/src/components/subscribeButton/SubscribeButton.module.css
similarity index 100%
rename from src/FilterLists.Web.V2/src/components/buttons/subscribe/SubscribeButton.module.css
rename to src/FilterLists.Web.V2/src/components/subscribeButton/SubscribeButton.module.css
diff --git a/src/FilterLists.Web.V2/src/components/buttons/subscribe/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/components/subscribeButton/SubscribeButton.tsx
similarity index 100%
rename from src/FilterLists.Web.V2/src/components/buttons/subscribe/SubscribeButton.tsx
rename to src/FilterLists.Web.V2/src/components/subscribeButton/SubscribeButton.tsx
diff --git a/src/FilterLists.Web.V2/src/components/buttons/subscribe/index.ts b/src/FilterLists.Web.V2/src/components/subscribeButton/index.ts
similarity index 100%
rename from src/FilterLists.Web.V2/src/components/buttons/subscribe/index.ts
rename to src/FilterLists.Web.V2/src/components/subscribeButton/index.ts