Added feature to remember last selected options to multiple screens. These are cleared on logout

Fixed JS_GEOLITE_ACCOUNT_ID undefined error
This commit is contained in:
CyferShepard
2024-10-03 21:48:21 +02:00
parent 33cdc00045
commit 57c028e23c
10 changed files with 192 additions and 79 deletions

View File

@@ -15,22 +15,39 @@ import LibraryFilterModal from "./components/library/library-filter-modal";
function Activity() {
const [data, setData] = useState();
const [config, setConfig] = useState(null);
const [streamTypeFilter, setStreamTypeFilter] = useState("All");
const [streamTypeFilter, setStreamTypeFilter] = useState(localStorage.getItem("PREF_ACTIVITY_StreamTypeFilter") ?? "All");
const [searchQuery, setSearchQuery] = useState("");
const [itemCount, setItemCount] = useState(10);
const [libraryFilters, setLibraryFilters] = useState([]);
const [itemCount, setItemCount] = useState(parseInt(localStorage.getItem("PREF_ACTIVITY_ItemCount") ?? "10"));
const [libraryFilters, setLibraryFilters] = useState(
localStorage.getItem("PREF_ACTIVITY_libraryFilters") != undefined
? JSON.parse(localStorage.getItem("PREF_ACTIVITY_libraryFilters"))
: []
);
const [libraries, setLibraries] = useState([]);
const [showLibraryFilters, setShowLibraryFilters] = useState(false);
function setItemLimit(limit) {
setItemCount(limit);
localStorage.setItem("PREF_ACTIVITY_ItemCount", limit);
}
function setTypeFilter(filter) {
setStreamTypeFilter(filter);
localStorage.setItem("PREF_ACTIVITY_StreamTypeFilter", filter);
}
const handleLibraryFilter = (selectedOptions) => {
setLibraryFilters(selectedOptions);
localStorage.setItem("PREF_ACTIVITY_libraryFilters", JSON.stringify(selectedOptions));
};
const toggleSelectAll = () => {
if (libraryFilters.length > 0) {
setLibraryFilters([]);
localStorage.setItem("PREF_ACTIVITY_libraryFilters", JSON.stringify([]));
} else {
setLibraryFilters(libraries.map((library) => library.Id));
localStorage.setItem("PREF_ACTIVITY_libraryFilters", JSON.stringify(libraries.map((library) => library.Id)));
}
};
@@ -73,15 +90,21 @@ function Activity() {
},
})
.then((data) => {
const libraryFilters = data.data.map((library) => {
const fetchedLibraryFilters = data.data.map((library) => {
return {
Name: library.Name,
Id: library.Id,
Archived: library.archived,
};
});
setLibraries(libraryFilters);
setLibraryFilters(libraryFilters.map((library) => library.Id));
setLibraries(fetchedLibraryFilters);
if (libraryFilters.length == 0) {
setLibraryFilters(fetchedLibraryFilters.map((library) => library.Id));
localStorage.setItem(
"PREF_ACTIVITY_libraryFilters",
JSON.stringify(fetchedLibraryFilters.map((library) => library.Id))
);
}
})
.catch((error) => {
console.log(error);
@@ -169,7 +192,7 @@ function Activity() {
</div>
<FormSelect
onChange={(event) => {
setStreamTypeFilter(event.target.value);
setTypeFilter(event.target.value);
}}
value={streamTypeFilter}
className="w-md-75 rounded-0 rounded-end"
@@ -192,7 +215,7 @@ function Activity() {
</div>
<FormSelect
onChange={(event) => {
setItemCount(event.target.value);
setItemLimit(event.target.value);
}}
value={itemCount}
className="w-md-75 rounded-0 rounded-end"

View File

@@ -15,8 +15,8 @@ import { Trans } from "react-i18next";
import PlaybackMethodStats from "./statCards/playback_method_stats";
function HomeStatisticCards() {
const [days, setDays] = useState(30);
const [input, setInput] = useState(30);
const [days, setDays] = useState(localStorage.getItem("PREF_HOME_STAT_DAYS") ?? 30);
const [input, setInput] = useState(localStorage.getItem("PREF_HOME_STAT_DAYS") ?? 30);
const handleKeyDown = (event) => {
if (event.key === "Enter") {
@@ -25,6 +25,7 @@ function HomeStatisticCards() {
setDays(0);
} else {
setDays(parseInt(input));
localStorage.setItem("PREF_HOME_STAT_DAYS", input);
}
console.log(days);

View File

@@ -155,7 +155,7 @@ export default function ActivityTable(props) {
row = row.original;
if (
isRemoteSession(row.RemoteEndPoint) &&
(window.env.JS_GEOLITE_ACCOUNT_ID ?? import.meta.env.JS_GEOLITE_ACCOUNT_ID)
(window.env?.JS_GEOLITE_ACCOUNT_ID ?? import.meta.env.JS_GEOLITE_ACCOUNT_ID) != undefined
) {
return (
<Link className="text-decoration-none" onClick={() => showIPDataModal(row.RemoteEndPoint)}>

View File

@@ -11,9 +11,19 @@ export default function Navbar() {
const handleLogout = () => {
localStorage.removeItem("token");
localStorage.removeItem("config");
deleteLibraryTabKeys();
window.location.reload();
};
const deleteLibraryTabKeys = () => {
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key.startsWith("PREF_")) {
localStorage.removeItem(key);
}
}
};
const location = useLocation();
return (

View File

@@ -19,10 +19,17 @@ import LibraryOptions from "./library/library-options";
function LibraryInfo() {
const { LibraryId } = useParams();
const [activeTab, setActiveTab] = useState("tabOverview");
const [activeTab, setActiveTab] = useState(
localStorage.getItem(`PREF_LIBRARY_TAB_LAST_SELECTED_${LibraryId}`) ?? "tabOverview"
);
const [data, setData] = useState();
const token = localStorage.getItem("token");
function setTab(tabName) {
setActiveTab(tabName);
localStorage.setItem(`PREF_LIBRARY_TAB_LAST_SELECTED_${LibraryId}`, tabName);
}
useEffect(() => {
const fetchData = async () => {
try {
@@ -64,23 +71,18 @@ function LibraryInfo() {
<p className="user-name">{data.Name}</p>
<ButtonGroup>
<Button
onClick={() => setActiveTab("tabOverview")}
onClick={() => setTab("tabOverview")}
active={activeTab === "tabOverview"}
variant="outline-primary"
type="button"
>
<Trans i18nKey="TAB_CONTROLS.OVERVIEW" />
</Button>
<Button
onClick={() => setActiveTab("tabItems")}
active={activeTab === "tabItems"}
variant="outline-primary"
type="button"
>
<Button onClick={() => setTab("tabItems")} active={activeTab === "tabItems"} variant="outline-primary" type="button">
<Trans i18nKey="MEDIA" />
</Button>
<Button
onClick={() => setActiveTab("tabActivity")}
onClick={() => setTab("tabActivity")}
active={activeTab === "tabActivity"}
variant="outline-primary"
type="button"
@@ -89,7 +91,7 @@ function LibraryInfo() {
</Button>
<Button
onClick={() => setActiveTab("tabOptions")}
onClick={() => setTab("tabOptions")}
active={activeTab === "tabOptions"}
variant="outline-primary"
type="button"
@@ -99,7 +101,7 @@ function LibraryInfo() {
</ButtonGroup>
</div>
</div>
<Tabs defaultActiveKey="tabOverview" activeKey={activeTab} variant="pills" className="hide-tab-titles">
<Tabs defaultActiveKey={activeTab} activeKey={activeTab} variant="pills" className="hide-tab-titles">
<Tab eventKey="tabOverview" title="Overview" className="bg-transparent">
<LibraryGlobalStats LibraryId={LibraryId} />

View File

@@ -9,9 +9,21 @@ import i18next from "i18next";
function LibraryActivity(props) {
const [data, setData] = useState();
const token = localStorage.getItem("token");
const [itemCount, setItemCount] = useState(10);
const [itemCount, setItemCount] = useState(parseInt(localStorage.getItem("PREF_LIBRARY_ACTIVITY_ItemCount") ?? "10"));
const [searchQuery, setSearchQuery] = useState("");
const [streamTypeFilter, setStreamTypeFilter] = useState("All");
const [streamTypeFilter, setStreamTypeFilter] = useState(
localStorage.getItem("PREF_LIBRARY_ACTIVITY_StreamTypeFilter") ?? "All"
);
function setItemLimit(limit) {
setItemCount(limit);
localStorage.setItem("PREF_LIBRARY_ACTIVITY_ItemCount", limit);
}
function setTypeFilter(filter) {
setStreamTypeFilter(filter);
localStorage.setItem("PREF_LIBRARY_ACTIVITY_StreamTypeFilter", filter);
}
useEffect(() => {
const fetchData = async () => {
@@ -72,7 +84,7 @@ function LibraryActivity(props) {
</div>
<FormSelect
onChange={(event) => {
setStreamTypeFilter(event.target.value);
setTypeFilter(event.target.value);
}}
value={streamTypeFilter}
className="w-md-75 rounded-0 rounded-end"
@@ -95,7 +107,7 @@ function LibraryActivity(props) {
</div>
<FormSelect
onChange={(event) => {
setItemCount(event.target.value);
setItemLimit(event.target.value);
}}
value={itemCount}
className="my-md-3 w-md-75 rounded-0 rounded-end"

View File

@@ -17,15 +17,19 @@ function LibraryItems(props) {
const [data, setData] = useState();
const [config, setConfig] = useState();
const [searchQuery, setSearchQuery] = useState("");
const [sortOrder, setSortOrder] = useState("Title");
const [sortAsc, setSortAsc] = useState("all");
const [sortOrder, setSortOrder] = useState(localStorage.getItem("PREF_sortOrder") ?? "Title");
const [sortAsc, setSortAsc] = useState(
localStorage.getItem("PREF_sortAsc") != undefined ? localStorage.getItem("PREF_sortAsc") == "true" : true
);
console.log(sortOrder);
const archive = {
all: "all",
archived: "true",
not_archived: "false",
};
const [showArchived, setShowArchived] = useState(archive.all);
const [showArchived, setShowArchived] = useState(localStorage.getItem("PREF_archiveFilterValue") ?? archive.all);
useEffect(() => {
const fetchConfig = async () => {
@@ -69,11 +73,26 @@ function LibraryItems(props) {
function sortOrderLogic(_sortOrder) {
if (_sortOrder !== "Title") {
setSortAsc(false);
setSortDirection(false);
} else {
setSortAsc(true);
setSortDirection(true);
}
setSortOrder(_sortOrder);
setSortingOrder(_sortOrder);
}
function setSortDirection(asc) {
setSortAsc(asc);
localStorage.setItem("PREF_sortAsc", asc);
}
function setSortingOrder(order) {
setSortOrder(order);
localStorage.setItem("PREF_sortOrder", order);
}
function setArchivedFilter(value) {
setShowArchived(value);
localStorage.setItem("PREF_archiveFilterValue", value);
}
let filteredData = data;
@@ -105,7 +124,11 @@ function LibraryItems(props) {
<div className="d-flex flex-column flex-md-row">
<div className="d-flex flex-row w-md-75">
<FormSelect onChange={(e) => setShowArchived(e.target.value)} className="my-md-3 w-100 rounded">
<FormSelect
value={showArchived}
onChange={(e) => setArchivedFilter(e.target.value)}
className="my-md-3 w-100 rounded"
>
<option value="all">
<Trans i18nKey="ALL" />
</option>
@@ -121,6 +144,7 @@ function LibraryItems(props) {
<FormSelect
onChange={(e) => sortOrderLogic(e.target.value)}
className="ms-md-3 my-md-3 w-100 rounded-0 rounded-start"
value={sortOrder}
>
<option value="Title">
<Trans i18nKey="TITLE" />
@@ -139,7 +163,7 @@ function LibraryItems(props) {
</option>
</FormSelect>
<Button className="my-md-3 rounded-0 rounded-end" onClick={() => setSortAsc(!sortAsc)}>
<Button className="my-md-3 rounded-0 rounded-end" onClick={() => setSortDirection(!sortAsc)}>
{sortAsc ? <SortAscIcon /> : <SortDescIcon />}
</Button>
</div>

View File

@@ -1,4 +1,5 @@
import {Tabs, Tab } from 'react-bootstrap';
import { Tabs, Tab } from "react-bootstrap";
import { useState } from "react";
import SettingsConfig from "./components/settings/settingsConfig";
import Tasks from "./components/settings/Tasks";
@@ -8,47 +9,68 @@ import LibrarySelector from "./library_selector";
import Logs from "./components/settings/logs";
import "./css/settings/settings.css";
import { Trans } from "react-i18next";
import BackupPage from './components/settings/backup_page';
import BackupPage from "./components/settings/backup_page";
export default function Settings() {
const [activeTab, setActiveTab] = useState(localStorage.getItem(`PREF_SETTINGS_LAST_SELECTED_TAB`) ?? "tabGeneral");
function setTab(tabName) {
setActiveTab(tabName);
localStorage.setItem(`PREF_SETTINGS_LAST_SELECTED_TAB`, tabName);
}
return (
<div className="settings my-2">
<Tabs defaultActiveKey="tabGeneral" variant='pills'>
<Tabs defaultActiveKey={activeTab} activeTab={activeTab} onSelect={setTab} variant="pills">
<Tab
eventKey="tabGeneral"
className="bg-transparent my-2"
title={<Trans i18nKey={"SETTINGS_PAGE.SETTINGS"} />}
style={{ minHeight: "500px" }}
>
<SettingsConfig />
<SecuritySettings />
<Tasks />
</Tab>
<Tab eventKey="tabGeneral" className='bg-transparent my-2' title={<Trans i18nKey={"SETTINGS_PAGE.SETTINGS"}/>} style={{minHeight:'500px'}}>
<SettingsConfig/>
<SecuritySettings/>
<Tasks/>
</Tab>
<Tab
eventKey="tabLibraries"
className="bg-transparent my-2"
title={<Trans i18nKey={"SETTINGS_PAGE.LIBRARY_SETTINGS"} />}
style={{ minHeight: "500px" }}
>
<LibrarySelector />
</Tab>
<Tab eventKey="tabLibraries" className='bg-transparent my-2' title={<Trans i18nKey={"SETTINGS_PAGE.LIBRARY_SETTINGS"}/>} style={{minHeight:'500px'}}>
<LibrarySelector/>
</Tab>
<Tab
eventKey="tabKeys"
className="bg-transparent my-2"
title={<Trans i18nKey={"SETTINGS_PAGE.API_KEY"} />}
style={{ minHeight: "500px" }}
>
<ApiKeys />
</Tab>
<Tab eventKey="tabKeys" className='bg-transparent my-2' title={<Trans i18nKey={"SETTINGS_PAGE.API_KEY"}/>} style={{minHeight:'500px'}}>
<ApiKeys/>
</Tab>
<Tab
eventKey="tabBackup"
className="bg-transparent my-2"
title={<Trans i18nKey={"SETTINGS_PAGE.BACKUP"} />}
style={{ minHeight: "500px" }}
>
<BackupPage />
</Tab>
<Tab eventKey="tabBackup" className='bg-transparent my-2' title={<Trans i18nKey={"SETTINGS_PAGE.BACKUP"}/>} style={{minHeight:'500px'}}>
<BackupPage/>
</Tab>
<Tab eventKey="tabLogs" className='bg-transparent my-2' title={<Trans i18nKey={"SETTINGS_PAGE.LOGS"}/>} style={{minHeight:'500px'}}>
<Logs/>
</Tab>
</Tabs>
<Tab
eventKey="tabLogs"
className="bg-transparent my-2"
title={<Trans i18nKey={"SETTINGS_PAGE.LOGS"} />}
style={{ minHeight: "500px" }}
>
<Logs />
</Tab>
</Tabs>
</div>
);
}

View File

@@ -8,16 +8,29 @@ import PlayStatsByHour from "./components/statistics/play-stats-by-hour";
import { Trans } from "react-i18next";
function Statistics() {
const [days, setDays] = useState(20);
const [input, setInput] = useState(20);
const [days, setDays] = useState(
localStorage.getItem("PREF_STATISTICS_STAT_DAYS_INPUT") != undefined
? localStorage.getItem("PREF_STATISTICS_STAT_DAYS_INPUT")
: localStorage.getItem("PREF_STATISTICS_STAT_DAYS") ?? 20
);
const [input, setInput] = useState(localStorage.getItem("PREF_STATISTICS_STAT_DAYS_INPUT") ?? 20);
const handleOnChange = (event) => {
setInput(event.target.value);
localStorage.setItem("PREF_STATISTICS_STAT_DAYS_INPUT", event.target.value);
};
const handleKeyDown = (event) => {
if (event.key === "Enter") {
if (input < 1) {
setInput(1);
setDays(0);
localStorage.setItem("PREF_STATISTICS_STAT_DAYS", 0);
localStorage.setItem("PREF_STATISTICS_STAT_DAYS_INPUT", 1);
} else {
setDays(parseInt(input));
localStorage.setItem("PREF_STATISTICS_STAT_DAYS", parseInt(input));
localStorage.setItem("PREF_STATISTICS_STAT_DAYS_INPUT", input);
}
console.log(days);
@@ -27,19 +40,19 @@ function Statistics() {
return (
<div className="watch-stats">
<div className="Heading">
<h1><Trans i18nKey={"STAT_PAGE.STATISTICS"}/></h1>
<h1>
<Trans i18nKey={"STAT_PAGE.STATISTICS"} />
</h1>
<div className="date-range">
<div className="header"><Trans i18nKey={"LAST"}/></div>
<div className="days">
<input
type="number"
min={1}
value={input}
onChange={(event) => setInput(event.target.value)}
onKeyDown={handleKeyDown}
/>
<div className="header">
<Trans i18nKey={"LAST"} />
</div>
<div className="days">
<input type="number" min={1} value={input} onChange={handleOnChange} onKeyDown={handleKeyDown} />
</div>
<div className="trailer">
<Trans i18nKey={`UNITS.DAY${days > 1 ? "S" : ""}`} />
</div>
<div className="trailer"><Trans i18nKey={`UNITS.DAY${days>1 ? 'S':''}`}/></div>
</div>
</div>
<div>

View File

@@ -222,12 +222,18 @@ function Users() {
const [config, setConfig] = useState(null);
const [rowsPerPage, setRowsPerPage] = React.useState(10);
const [page, setPage] = React.useState(0);
const [itemCount, setItemCount] = useState(10);
const [itemCount, setItemCount] = useState(parseInt(localStorage.getItem("PREF_USER_ACTIVITY_ItemCount") ?? "10"));
const [searchQuery, setSearchQuery] = useState("");
const [order, setOrder] = React.useState("asc");
const [orderBy, setOrderBy] = React.useState("LastSeen");
function setItemLimit(limit) {
setItemCount(limit);
localStorage.setItem("PREF_USER_ACTIVITY_ItemCount", limit);
}
useEffect(() => {
const fetchConfig = async () => {
try {
@@ -422,7 +428,7 @@ function Users() {
onChange={(event) => {
setRowsPerPage(event.target.value);
setPage(0);
setItemCount(event.target.value);
setItemLimit(event.target.value);
}}
value={itemCount}
className="my-md-3 w-md-75 rounded-0 rounded-end"