diff --git a/src/frontend/discussions-abusefilter-app/src/App.tsx b/src/frontend/discussions-abusefilter-app/src/App.tsx index 8af0c96..ac56797 100644 --- a/src/frontend/discussions-abusefilter-app/src/App.tsx +++ b/src/frontend/discussions-abusefilter-app/src/App.tsx @@ -25,6 +25,8 @@ import { ActionsProvider } from 'contexts/ActionsContext'; import { RulesProvider } from 'contexts/RulesContext'; import { TriggersProvider } from 'contexts/TriggersContext'; +// export const localMode = true; + export default function App() { const { token } = React.useContext(AuthContext); diff --git a/src/frontend/discussions-abusefilter-app/src/controllers/FilterController.ts b/src/frontend/discussions-abusefilter-app/src/controllers/FilterController.ts new file mode 100644 index 0000000..1d594a1 --- /dev/null +++ b/src/frontend/discussions-abusefilter-app/src/controllers/FilterController.ts @@ -0,0 +1,31 @@ +import type { Filter, FilterMetadata } from '@shared/filters'; +import type { BackendInterface } from '../interfaces/BackendInterface'; + +export class FilterController { + constructor(private readonly backendInterface: BackendInterface) {} + + getFilter(filterId: string) { + return this.backendInterface.getFilter(filterId); + } + + createFilter(filter: Filter, filterMetadata: FilterMetadata) { + this.backendInterface.createFilter(filter, filterMetadata); + } + + updateFilter(filter: Filter, filterMetadata: FilterMetadata) { + this.backendInterface.updateFilter(filter, filterMetadata); + } + + archiveFilter(filterId: string) { + this.backendInterface.archiveFilter(filterId); + } + + enableFilter(filterId: string) { + return this.backendInterface.enableFilter(filterId); + } + + disableFilter(filterId: string) { + return this.backendInterface.disableFilter(filterId); + } +} + diff --git a/src/frontend/discussions-abusefilter-app/src/controllers/FiltersController.ts b/src/frontend/discussions-abusefilter-app/src/controllers/FiltersController.ts new file mode 100644 index 0000000..63d726b --- /dev/null +++ b/src/frontend/discussions-abusefilter-app/src/controllers/FiltersController.ts @@ -0,0 +1,10 @@ +import type { BackendInterface } from '../interfaces/BackendInterface'; + +export class FiltersController { + constructor(private readonly backendInterface: BackendInterface) {} + + getFilters() { + return this.backendInterface.getFilters(); + } +} + diff --git a/src/frontend/discussions-abusefilter-app/src/interfaces/BackendInterface.ts b/src/frontend/discussions-abusefilter-app/src/interfaces/BackendInterface.ts new file mode 100644 index 0000000..3ad6ca7 --- /dev/null +++ b/src/frontend/discussions-abusefilter-app/src/interfaces/BackendInterface.ts @@ -0,0 +1,19 @@ +import type { Filter, FilterMetadata } from '@shared/filters'; + +export type Error = { + error: { + message: string + } +}; + +export const interfaceMode = 'local'; + +export interface BackendInterface { + getFilters: () => Promise, + getFilter: (filterId: string) => Promise<{ filterDetails: Filter, filterMetadata: FilterMetadata }> | Error, + createFilter: (filter: Filter, filterMetadata: FilterMetadata) => void, + updateFilter: (filter: Filter, filterMetadata: FilterMetadata) => void, + archiveFilter: (filterId: string) => void, + enableFilter: (filterId: string) => void, + disableFilter: (filterId: string) => void, +} diff --git a/src/frontend/discussions-abusefilter-app/src/interfaces/LocalBackendInterface.ts b/src/frontend/discussions-abusefilter-app/src/interfaces/LocalBackendInterface.ts new file mode 100644 index 0000000..71b6fa9 --- /dev/null +++ b/src/frontend/discussions-abusefilter-app/src/interfaces/LocalBackendInterface.ts @@ -0,0 +1,64 @@ +import type { Filter, FilterMetadata } from '@shared/filters'; +import type { BackendInterface, Error } from './BackendInterface'; + +export class LocalBackendInterface implements BackendInterface { + filters: Record; + filtersMetadata: Record; + archivedFilters: string[]; + private static instance: LocalBackendInterface; + + private constructor() { + this.filters = {}; + this.filtersMetadata = {}; + this.archivedFilters = []; + } + + getFilters(): Promise { + return Promise.resolve(Object.values(this.filtersMetadata)); + } + + getFilter(filterId: string): Promise<{ filterDetails: Filter, filterMetadata: FilterMetadata }> | Error { + return new Promise<{ filterDetails: Filter, filterMetadata: FilterMetadata}>((resolve, reject) => { + if (this.filters[filterId] != null && this.filtersMetadata[filterId] != null) { + resolve({ filterDetails: this.filters[filterId], filterMetadata: this.filtersMetadata[filterId] }); + } else { + reject({ + error: { + message: 'Filter ID does not exist', + }, + }); + } + }); + } + + createFilter(filter: Filter, filterMetadata: FilterMetadata) { + this.filters[filter.id] = filter; + this.filtersMetadata[filterMetadata.id] = filterMetadata; + } + + updateFilter(filter: Filter, filterMetadata: FilterMetadata) { + this.filters[filter.id] = filter; + this.filtersMetadata[filter.id] = filterMetadata; + } + + archiveFilter(filterId: string) { + this.archivedFilters.push(filterId); + delete this.filters[filterId]; + delete this.filtersMetadata[filterId]; + } + + enableFilter(filterId: string) { + this.filtersMetadata[filterId].enabled = true; + } + + disableFilter(filterId: string) { + this.filtersMetadata[filterId].enabled = false; + } + + static getInstance(): LocalBackendInterface { + if (!LocalBackendInterface.instance) { + LocalBackendInterface.instance = new LocalBackendInterface(); + } + return LocalBackendInterface.instance; + } +} diff --git a/src/frontend/discussions-abusefilter-app/src/interfaces/ProductionBackendInterface.ts b/src/frontend/discussions-abusefilter-app/src/interfaces/ProductionBackendInterface.ts new file mode 100644 index 0000000..51514f4 --- /dev/null +++ b/src/frontend/discussions-abusefilter-app/src/interfaces/ProductionBackendInterface.ts @@ -0,0 +1,70 @@ +import type { Filter, FilterMetadata } from '@shared/filters'; +import type { BackendInterface } from './BackendInterface'; + +const baseApiUrl = ''; + +export class ProductionBackendInterface implements BackendInterface { + userToken: string; + + constructor( userToken: string) { + this.userToken = userToken; + } + + getFilters(): Promise { + return fetch(`${baseApiUrl}/filters`, { + method: 'GET', + headers: { + token: this.userToken, + }, + }) + .then(res => res.json()) + .catch(e => console.log(e)); + } + + getFilter(filterId: string): Promise { + return fetch(`${baseApiUrl}/filter/${filterId}`, { + method: 'GET', + headers: { + token: this.userToken, + }, + }) + .then(res => res.json()) + .catch(e => console.log(e)); + } + + createFilter(filter: Filter, filterMetadata: FilterMetadata) { + console.log(filterMetadata); + return fetch(`${baseApiUrl}/filter/new`, { + method: 'POST', + headers: { + token: this.userToken, + }, + body: JSON.stringify(filter), + }) + .catch(e => console.log(e)); + } + + updateFilter(filter: Filter, filterMetadata: FilterMetadata) { + console.log(filterMetadata); + return fetch(`${baseApiUrl}/filter/${filter.id}`, { + method: 'POST', + headers: { + token: this.userToken, + }, + body: JSON.stringify(filter), + }) + .catch(e => console.log(e)); + } + + archiveFilter(filterId: string) { + return filterId; + } + + enableFilter(filterId: string) { + console.log(filterId); + } + + disableFilter(filterId: string) { + console.log(filterId); + } +} diff --git a/src/frontend/discussions-abusefilter-app/src/pages/Filter.tsx b/src/frontend/discussions-abusefilter-app/src/pages/Filter.tsx index 12e2e82..8353764 100644 --- a/src/frontend/discussions-abusefilter-app/src/pages/Filter.tsx +++ b/src/frontend/discussions-abusefilter-app/src/pages/Filter.tsx @@ -22,11 +22,16 @@ import TriggersContext from '../contexts/TriggersContext'; import Action from '../components/Action'; import ActionsContext from '../contexts/ActionsContext'; import RulesContext from '../contexts/RulesContext'; +import { LocalBackendInterface } from 'interfaces/LocalBackendInterface'; +import { ProductionBackendInterface } from 'interfaces/ProductionBackendInterface'; +import { interfaceMode } from 'interfaces/BackendInterface'; + +const filterController = interfaceMode === 'local' ? LocalBackendInterface.getInstance() : new ProductionBackendInterface('token'); export default function Filter() { const { filterId } = useParams(); - const [filterEnabled, setFilterEnabled] = React.useState(true); + const [filterEnabled, setFilterEnabled] = React.useState(false); const [name, setName] = React.useState(''); const [description, setDescription] = React.useState(''); const { filter } = React.useContext(FormContext); @@ -75,8 +80,29 @@ export default function Filter() { const handleSave = (event: { preventDefault: () => void }) => { event.preventDefault(); console.log(name, description, filter, triggers, actions, rules); - console.log(errors); + // console.log(errors); if (errors === 0) { + if (filterId === 'new') { + let wikiList: string[] = []; + triggers.forEach(trigger => wikiList = wikiList.concat(trigger.wikis)); + const newId = Math.floor(Math.random() * 999).toString(); + filterController.createFilter({ + id: newId, + triggers: triggers, + filter: filter, + actions: actions, + }, { + id: newId, + title: name, + description: description, + wikis: wikiList, + editedBy: '', + enabled: filterEnabled, + hits: 0, + }); + } else { + // + } console.log('firebase updated'); } else { console.log('there are errors'); @@ -96,7 +122,7 @@ export default function Filter() { } - label="Filter enabled" + label={filterEnabled ? 'Filter enabled' : 'Filter disabled'} /> @@ -227,7 +253,7 @@ export default function Filter() { diff --git a/src/frontend/discussions-abusefilter-app/src/pages/Filters.tsx b/src/frontend/discussions-abusefilter-app/src/pages/Filters.tsx index 9d49bdb..745b952 100644 --- a/src/frontend/discussions-abusefilter-app/src/pages/Filters.tsx +++ b/src/frontend/discussions-abusefilter-app/src/pages/Filters.tsx @@ -14,38 +14,60 @@ import { Stack, Link, Box, + Button, } from '@mui/material'; import { useTheme } from '@mui/material/styles'; import { fandomPurple } from 'themes/Theme'; +// import { localMode } from 'App'; +import { LocalBackendInterface } from 'interfaces/LocalBackendInterface'; +import { ProductionBackendInterface } from 'interfaces/ProductionBackendInterface'; +import { interfaceMode } from 'interfaces/BackendInterface'; +import type { FilterMetadata } from '@shared/filters'; -function createData(id: string, filterName: string, lastEdit: string, wikis: string[], hits: number) { - return { id, filterName, lastEdit, wikis, hits }; -} +// missing hits +// function createData(id: string, title: string, editedBy: string, wikis: string[], description: string) { +// return { id, title, editedBy, wikis, description }; +// } -const rows = [ - createData('1', 'test1', 'Noreplyz', ['community'], 5), - createData('2', 'test2', 'Noreplyz', ['community', 'noreply'], 10), - createData('3', 'test3', 'Noreplyz', ['avatar', 'noreply', 'noreply', 'noreply', 'noreply'], 10), -]; +// const rows: FilterMetadata[] = [ +// createData('1', 'test1', 'Noreplyz', ['community'], 5), +// createData('2', 'test2', 'Noreplyz', ['community', 'noreply'], 10), +// createData('3', 'test3', 'Noreplyz', ['avatar', 'noreply', 'noreply', 'noreply', 'noreply'], 10), +// ]; const headings = [ 'ID', 'Filter', + 'Description', 'Last edited by', 'Wikis', 'Hits', ]; +const filtersController = interfaceMode === 'local' ? LocalBackendInterface.getInstance() : new ProductionBackendInterface('token'); + export default function Filters() { - const [filterData] = React.useState(rows); + const [filterData, setFilterData] = React.useState([] as FilterMetadata[]); const theme = useTheme(); + React.useEffect(() => { + // eslint-disable-next-line no-constant-condition + if (true) { + filtersController.getFilters() + .then(res => setFilterData(res)); + } + filtersController.getFilters().then(res=>console.log(res)); + }, []); + return ( Filters - - {0} Enabled - {0} Disabled + + + {0} Enabled + {0} Disabled + + @@ -65,10 +87,11 @@ export default function Filters() { {row.id} - {row.filterName} + {row.title} - {row.lastEdit} + {row.description} + {row.editedBy}{row.wikis.length > 2 ? `${row.wikis[0]}, +${row.wikis.length - 1} more` : row.wikis.join(', ')}{row.hits} diff --git a/src/shared/filters.ts b/src/shared/filters.ts index 66d6af1..a8fa1ab 100644 --- a/src/shared/filters.ts +++ b/src/shared/filters.ts @@ -11,6 +11,10 @@ export type FilterMetadata = { wikis: string[], // Fandom username for the user who last edited the filter editedBy: string, + // Boolean flag that determines if the filter is enabled or disabled + enabled: boolean, + // Number of times the filter has been triggered + hits: number }; export type Filter = {