Skip to content

Commit

Permalink
Merge pull request #33 from TID-Lab/batch-mode
Browse files Browse the repository at this point in the history
Batch mode
  • Loading branch information
codelastnight authored Sep 3, 2024
2 parents 03d5bd3 + 6dbd8e3 commit 1131e0c
Show file tree
Hide file tree
Showing 53 changed files with 1,470 additions and 883 deletions.
4 changes: 2 additions & 2 deletions backend/api/controllers/reportController.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,13 @@ exports.reports_irrelevant_update = (req, res) => {
let remaining = reports.length;
reports.forEach((report) => {
// Mark each report as escalated to catch it in model
report.setIrrelevant(req.body.irrelevant);
report.setIrrelevant(req.body.irrelevance);
report.save((err) => {
if (err) {
if (!res.headersSent) res.status(err.status).send(err.message)
return;
}
writelog.writeReport(req, report, 'escalatedReport');
writelog.writeReport(req, report, 'irreleventReport');
if (--remaining === 0) return res.sendStatus(200);
});
});
Expand Down
2 changes: 1 addition & 1 deletion backend/api/routes/reportRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ router.patch('/_read', User.can('edit data'), reportController.reports_read_upda
router.patch('/_escalated', User.can('edit data'), reportController.reports_escalated_update);

// Update reports escalation
router.patch('/_irrelevant', User.can('edit data'), reportController.reports_irrelevant_update);
router.patch('/_irrelevance', User.can('edit data'), reportController.reports_irrelevant_update);

// Add reports group
router.patch('/_group', User.can('edit data'), reportController.reports_group_update);
Expand Down
2 changes: 1 addition & 1 deletion backend/models/report.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ let schema = new Schema({
notes: { type: String },
escalated: { type: Boolean, default: false, required: true, index: true },
content_lang: { type: String },
irrelevant: { type: Boolean, default: false, required: false }
irrelevant: { type: String, default: 'false', required: false, enum: ['false', 'true', 'maybe'] }
});

schema.index({ 'metadata.ct_tag': 1 }, { background: true });
Expand Down
37 changes: 37 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
"react-scripts": "^5.0.1",
"react-tagcloud": "^2.2.0",
"react-twitter-widgets": "^1.10.0",
"react-youtube": "^10.1.0",
"readline-sync": "^1.4.10",
"recharts": "^2.1.9",
"reparse": "^0.1.2",
Expand Down
23 changes: 12 additions & 11 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import React, { useEffect, useState } from "react";
import "./App.css";
import "@yaireo/tagify/dist/tagify.css";
import AggieNavbar from "./components/AggieNavbar";
import AlertService, { AlertContent } from "./components/AlertService";
import {
Navigate,
Route,
Routes,
useLocation,
useNavigate,
} from "react-router-dom";
import AggieNavbar from "./components/AggieNavbar";
import AlertService, { AlertContent } from "./components/AlertService";
import { Modal } from "react-bootstrap";
import { getSession } from "./api/session";

import type { AxiosError } from "axios";
import type { Session } from "./objectTypes";

import "./App.css";
import "@yaireo/tagify/dist/tagify.css";

import ReportsIndex from "./pages/report/ReportsIndex";
import ReportDetails from "./pages/report/ReportDetails";
import GroupsIndex from "./pages/group/GroupsIndex";
Expand All @@ -25,20 +32,15 @@ import Login from "./pages/Login";
import Analysis from "./pages/Analysis";
import NotFound from "./pages/NotFound";
import ResetPassword from "./pages/ResetPassword";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { getSession } from "./api/session";
import { Axios, AxiosError } from "axios";
import { Session } from "./objectTypes";
import RelevantReportsIndex from "./pages/report/RelevantReportsIndex";
import { getAllGroups } from "./api/groups";
import { Button, Modal } from "react-bootstrap";
import Incidents from "./pages/incidents";
import Incident from "./pages/incidents/Incident";
import Reports from "./pages/Reports";
import Report from "./pages/Reports/Report";
import NewIncident from "./pages/incidents/NewIncident";
import FetchIndicator from "./components/FetchIndicator";

// im currently working on this
//TODO: BIG TODO is to correctly type all of react-query usage. Its not critical for function, but it is good for clarity in development.
//TODO: Also BIG TODO is to ensure EVERY API call has a way of surfacing an error message. I want readble UI alerts but at least console.errors.
const isSafari = () =>
Expand Down Expand Up @@ -98,7 +100,6 @@ const PrivateRoutes = ({ sessionData, setGlobalAlert }: IPrivateRouteProps) => {
);
};
const App = () => {
const queryClient = useQueryClient();
const [isLoggedIn, setIsLoggedIn] = useState(true);
const [userData, setUserData] = useState<Session | undefined>(undefined);

Expand Down
22 changes: 15 additions & 7 deletions src/api/enums.ts → src/api/common.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
export interface hasId {
_id: string;
}

export const VERACITY_OPTIONS = [
"Unconfirmed",
"Confirmed False",
"Confirmed True",
] as const;
export type VeracityOptions = (typeof VERACITY_OPTIONS)[number];

export const ESCALATED_OPTIONS = ["true", "false"] as const;
export type EscalatedOptions = (typeof ESCALATED_OPTIONS)[number];

export const CLOSED_OPTIONS = ["true", "false"] as const;
export type ClosedOptions = (typeof CLOSED_OPTIONS)[number];

export const MEDIA_OPTIONS = [
"twitter",
"tiktok",
"instagram",
"RSS",
"elmo",
"SMS GH",
"youtube",
"facebook",
];
] as const;
export type MediaOptions = (typeof MEDIA_OPTIONS)[number];

export const ESCALATED_OPTIONS = ["true", "false"] as const;
export type EscalatedOptions = (typeof ESCALATED_OPTIONS)[number];

export const CLOSED_OPTIONS = ["true", "false"] as const;
export type ClosedOptions = (typeof CLOSED_OPTIONS)[number];

export const IRRELEVANCE_OPTIONS = ["true", "maybe", "false"] as const;
export type IrrelevanceOptions = (typeof IRRELEVANCE_OPTIONS)[number];
6 changes: 3 additions & 3 deletions src/api/groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import {
Groups,
GroupSearchState,
GroupQueryState,
hasId,
Reports,
} from "../objectTypes";
import { VeracityOptions } from "./enums";

import type { Reports } from "./reports/types";
import { hasId, VeracityOptions } from "./common";

export const getGroups = async (
searchState: GroupQueryState = {},
Expand Down
31 changes: 23 additions & 8 deletions src/api/reports.ts → src/api/reports/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import axios from "axios";
import {
hasId,
Report,
ReportQueryState,
import type { Report, ReportQueryState, Reports } from "./types";
import type {
ReportQueryState_old,
Reports,
} from "../objectTypes";
import { VeracityOptions } from "./enums";
Report as Report_old,
} from "../../objectTypes";
import type { hasId, IrrelevanceOptions, VeracityOptions } from "../common";

export const getReports = async (
searchState: ReportQueryState,
Expand Down Expand Up @@ -60,8 +58,14 @@ export const editReport = async (report: Report) => {
return data;
};

//TODO: deprecate, same thing using old types
export const editReport_old = async (report: Report_old) => {
const { data } = await axios.put("/api/report/" + report._id, report);
return data;
};

export const getBatch = async () => {
const { data } = await axios.get("/api/report/batch");
const { data } = await axios.get<Reports>("/api/report/batch");
return data;
};

Expand Down Expand Up @@ -94,6 +98,17 @@ export const setSelectedVeracity = async (
return data;
};

export const setSelectedIrrelevance = async (
reportIds: string[],
irrelevance: IrrelevanceOptions | string
) => {
const { data } = await axios.patch("/api/report/_irrelevance", {
ids: reportIds,
irrelevance: irrelevance,
});
return data;
};

export const setSelectedNotes = async (reportIds: string[], notes: string) => {
const { data } = await axios.patch("/api/report/_notes", {
ids: reportIds,
Expand Down
62 changes: 58 additions & 4 deletions src/types/metadata.ts → src/api/reports/types.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,55 @@
interface RawApiResponse {
id: string;
type: string;
attributes: unknown;
import type {
hasId,
VeracityOptions,
MediaOptions,
IrrelevanceOptions,
} from "../common";

export interface Report extends hasId {
veracity: VeracityOptions;
tags: string[];
smtcTags: string[];
hasSMTCTags: boolean;
read: boolean;
_sources: string[];
_media: MediaOptions[];
_sourceNicknames: string[];
escalated: boolean;
_group?: string;
authoredAt: string;
fetchedAt: string;
content: string;
author: string;
metadata: BaseMetadata;
url: string;
storedAt: string;
commentTo: string;
notes: string;
originalPost: string;
irrelevant?: IrrelevanceOptions;
__v: number;
}

export interface Reports {
total: number;
results: Report[];
}

export interface ReportQueryState {
keywords?: string;
author?: string;
groupId?: string;
media?: string;
sourceId?: string;
list?: string;
before?: Date | string;
after?: Date | string;
tags?: string[];
page?: number;
batch?: boolean;
}

// metadata typed
export interface BaseMetadata {
imageText: any;
junkipediaId: number;
Expand All @@ -15,6 +61,14 @@ export interface BaseMetadata {
rawAPIResponse: RawApiResponse;
testingFlagForPotentialDeletion: boolean;
}

interface RawApiResponse {
id: string;
type: string;
attributes: unknown;
[key: string]: any;
}
// i need to redo this...
export interface Statistics
extends TwitterStatistics,
TiktokStatistics,
Expand Down
15 changes: 12 additions & 3 deletions src/components/AggieButton.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { faSpinner } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";

const defaultCSS =
"disabled:pointer-events-none disabled:opacity-50 inline-flex gap-1 items-center text-nowrap focus-theme";
"disabled:pointer-events-none disabled:opacity-50 inline-flex gap-1 items-center text-nowrap focus-theme font-medium";

const variantCSS = {
primary:
"bg-green-800 text-slate-100 hover:bg-green-700 rounded-lg px-2 py-1 font-medium",
"bg-green-800 text-slate-100 hover:bg-green-700 rounded-lg px-2 py-1 ",
secondary:
"bg-slate-100 px-2 py-1 hover:bg-slate-200 border border-slate-200 rounded-lg",
outline: "",
Expand All @@ -13,12 +16,15 @@ interface IProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
className?: string;
override?: boolean;
variant?: keyof typeof variantCSS;
loading?: boolean;
}

const AggieButton = ({
className,
override = false,
loading = false,
variant,
children,
...props
}: IProps) => {
return (
Expand All @@ -29,7 +35,10 @@ const AggieButton = ({
: `${defaultCSS} ${className} ${variant ? variantCSS[variant] : ""}`
}
{...props}
/>
>
{loading && <FontAwesomeIcon icon={faSpinner} className='animate-spin' />}
{children}
</button>
);
};

Expand Down
Loading

0 comments on commit 1131e0c

Please sign in to comment.