mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 12:54:38 +03:00
React code splitting (#2603)
* Code split using react lazy * Split locales * Move to lodash-es * Import individual icons
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import _ from "lodash";
|
||||
import cloneDeep from "lodash-es/cloneDeep";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { Button, Form, Modal } from "react-bootstrap";
|
||||
import { CriterionModifier } from "src/core/generated-graphql";
|
||||
@@ -80,13 +80,13 @@ export const AddFilterDialog: React.FC<IAddFilterProps> = ({
|
||||
function onChangedModifierSelect(
|
||||
event: React.ChangeEvent<HTMLSelectElement>
|
||||
) {
|
||||
const newCriterion = _.cloneDeep(criterion);
|
||||
const newCriterion = cloneDeep(criterion);
|
||||
newCriterion.modifier = event.target.value as CriterionModifier;
|
||||
setCriterion(newCriterion);
|
||||
}
|
||||
|
||||
function onValueChanged(value: CriterionValue) {
|
||||
const newCriterion = _.cloneDeep(criterion);
|
||||
const newCriterion = cloneDeep(criterion);
|
||||
newCriterion.value = value;
|
||||
setCriterion(newCriterion);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
} from "src/models/list-filter/criteria/criterion";
|
||||
import { useIntl } from "react-intl";
|
||||
import { Icon } from "../Shared";
|
||||
import { faTimes } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
interface IFilterTagsProps {
|
||||
criteria: Criterion<CriterionValue>[];
|
||||
@@ -48,7 +49,7 @@ export const FilterTags: React.FC<IFilterTagsProps> = ({
|
||||
variant="secondary"
|
||||
onClick={($event) => onRemoveCriterionTag(criterion, $event)}
|
||||
>
|
||||
<Icon icon="times" />
|
||||
<Icon icon={faTimes} />
|
||||
</Button>
|
||||
</Badge>
|
||||
));
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import _, { debounce } from "lodash";
|
||||
import debounce from "lodash-es/debounce";
|
||||
import cloneDeep from "lodash-es/cloneDeep";
|
||||
import React, { HTMLAttributes, useEffect, useRef, useState } from "react";
|
||||
import cx from "classnames";
|
||||
import Mousetrap from "mousetrap";
|
||||
@@ -23,6 +24,15 @@ import { ListFilterOptions } from "src/models/list-filter/filter-options";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import { PersistanceLevel } from "src/hooks/ListHook";
|
||||
import { SavedFilterList } from "./SavedFilterList";
|
||||
import {
|
||||
faBookmark,
|
||||
faCaretDown,
|
||||
faCaretUp,
|
||||
faCheck,
|
||||
faFilter,
|
||||
faRandom,
|
||||
faTimes,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
const maxPageSize = 1000;
|
||||
interface IListFilterProps {
|
||||
@@ -53,7 +63,7 @@ export const ListFilter: React.FC<IListFilterProps> = ({
|
||||
const [perPageInput, perPageFocus] = useFocus();
|
||||
|
||||
const searchCallback = debounce((value: string) => {
|
||||
const newFilter = _.cloneDeep(filter);
|
||||
const newFilter = cloneDeep(filter);
|
||||
newFilter.searchTerm = value;
|
||||
newFilter.currentPage = 1;
|
||||
onFilterUpdate(newFilter);
|
||||
@@ -101,7 +111,7 @@ export const ListFilter: React.FC<IListFilterProps> = ({
|
||||
pp = maxPageSize;
|
||||
}
|
||||
|
||||
const newFilter = _.cloneDeep(filter);
|
||||
const newFilter = cloneDeep(filter);
|
||||
newFilter.itemsPerPage = pp;
|
||||
newFilter.currentPage = 1;
|
||||
onFilterUpdate(newFilter);
|
||||
@@ -120,7 +130,7 @@ export const ListFilter: React.FC<IListFilterProps> = ({
|
||||
}
|
||||
|
||||
function onChangeSortDirection() {
|
||||
const newFilter = _.cloneDeep(filter);
|
||||
const newFilter = cloneDeep(filter);
|
||||
if (filter.sortDirection === SortDirectionEnum.Asc) {
|
||||
newFilter.sortDirection = SortDirectionEnum.Desc;
|
||||
} else {
|
||||
@@ -131,14 +141,14 @@ export const ListFilter: React.FC<IListFilterProps> = ({
|
||||
}
|
||||
|
||||
function onChangeSortBy(eventKey: string | null) {
|
||||
const newFilter = _.cloneDeep(filter);
|
||||
const newFilter = cloneDeep(filter);
|
||||
newFilter.sortBy = eventKey ?? undefined;
|
||||
newFilter.currentPage = 1;
|
||||
onFilterUpdate(newFilter);
|
||||
}
|
||||
|
||||
function onReshuffleRandomSort() {
|
||||
const newFilter = _.cloneDeep(filter);
|
||||
const newFilter = cloneDeep(filter);
|
||||
newFilter.currentPage = 1;
|
||||
newFilter.randomSeed = -1;
|
||||
onFilterUpdate(newFilter);
|
||||
@@ -225,7 +235,7 @@ export const ListFilter: React.FC<IListFilterProps> = ({
|
||||
queryClearShowing ? "" : "d-none"
|
||||
)}
|
||||
>
|
||||
<Icon icon="times" />
|
||||
<Icon icon={faTimes} />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -241,7 +251,7 @@ export const ListFilter: React.FC<IListFilterProps> = ({
|
||||
}
|
||||
>
|
||||
<Dropdown.Toggle variant="secondary">
|
||||
<Icon icon="bookmark" />
|
||||
<Icon icon={faBookmark} />
|
||||
</Dropdown.Toggle>
|
||||
</OverlayTrigger>
|
||||
<Dropdown.Menu
|
||||
@@ -262,7 +272,7 @@ export const ListFilter: React.FC<IListFilterProps> = ({
|
||||
onClick={() => openFilterDialog()}
|
||||
active={filterDialogOpen}
|
||||
>
|
||||
<Icon icon="filter" />
|
||||
<Icon icon={faFilter} />
|
||||
</Button>
|
||||
</OverlayTrigger>
|
||||
</ButtonGroup>
|
||||
@@ -291,8 +301,8 @@ export const ListFilter: React.FC<IListFilterProps> = ({
|
||||
<Icon
|
||||
icon={
|
||||
filter.sortDirection === SortDirectionEnum.Asc
|
||||
? "caret-up"
|
||||
: "caret-down"
|
||||
? faCaretUp
|
||||
: faCaretDown
|
||||
}
|
||||
/>
|
||||
</Button>
|
||||
@@ -306,7 +316,7 @@ export const ListFilter: React.FC<IListFilterProps> = ({
|
||||
}
|
||||
>
|
||||
<Button variant="secondary" onClick={onReshuffleRandomSort}>
|
||||
<Icon icon="random" />
|
||||
<Icon icon={faRandom} />
|
||||
</Button>
|
||||
</OverlayTrigger>
|
||||
)}
|
||||
@@ -362,7 +372,7 @@ export const ListFilter: React.FC<IListFilterProps> = ({
|
||||
)
|
||||
}
|
||||
>
|
||||
<Icon icon="check" />
|
||||
<Icon icon={faCheck} />
|
||||
</Button>
|
||||
</InputGroup.Append>
|
||||
</InputGroup>
|
||||
|
||||
@@ -8,14 +8,19 @@ import {
|
||||
} from "react-bootstrap";
|
||||
import Mousetrap from "mousetrap";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import { IconProp } from "@fortawesome/fontawesome-svg-core";
|
||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
||||
import { Icon } from "../Shared";
|
||||
import {
|
||||
faEllipsisH,
|
||||
faPencilAlt,
|
||||
faTrash,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
interface IListFilterOperation {
|
||||
text: string;
|
||||
onClick: () => void;
|
||||
isDisplayed?: () => boolean;
|
||||
icon?: IconProp;
|
||||
icon?: IconDefinition;
|
||||
buttonVariant?: string;
|
||||
}
|
||||
|
||||
@@ -78,14 +83,14 @@ export const ListOperationButtons: React.FC<IListOperationButtonsProps> = ({
|
||||
if (itemsSelected) {
|
||||
if (onEdit) {
|
||||
buttons.push({
|
||||
icon: "pencil-alt",
|
||||
icon: faPencilAlt,
|
||||
text: intl.formatMessage({ id: "actions.edit" }),
|
||||
onClick: onEdit,
|
||||
});
|
||||
}
|
||||
if (onDelete) {
|
||||
buttons.push({
|
||||
icon: "trash",
|
||||
icon: faTrash,
|
||||
text: intl.formatMessage({ id: "actions.delete" }),
|
||||
onClick: onDelete,
|
||||
buttonVariant: "danger",
|
||||
@@ -106,7 +111,7 @@ export const ListOperationButtons: React.FC<IListOperationButtonsProps> = ({
|
||||
variant={button.buttonVariant ?? "secondary"}
|
||||
onClick={button.onClick}
|
||||
>
|
||||
<Icon icon={button.icon as IconProp} />
|
||||
{button.icon ? <Icon icon={button.icon} /> : undefined}
|
||||
</Button>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
@@ -173,7 +178,7 @@ export const ListOperationButtons: React.FC<IListOperationButtonsProps> = ({
|
||||
return (
|
||||
<Dropdown className="mb-1">
|
||||
<Dropdown.Toggle variant="secondary" id="more-menu">
|
||||
<Icon icon="ellipsis-h" />
|
||||
<Icon icon={faEllipsisH} />
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu className="bg-secondary text-white">
|
||||
{options}
|
||||
|
||||
@@ -10,6 +10,12 @@ import {
|
||||
import { DisplayMode } from "src/models/list-filter/types";
|
||||
import { useIntl } from "react-intl";
|
||||
import { Icon } from "../Shared";
|
||||
import {
|
||||
faList,
|
||||
faSquare,
|
||||
faTags,
|
||||
faThLarge,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
interface IListViewOptionsProps {
|
||||
zoomIndex?: number;
|
||||
@@ -71,13 +77,13 @@ export const ListViewOptions: React.FC<IListViewOptionsProps> = ({
|
||||
function getIcon(option: DisplayMode) {
|
||||
switch (option) {
|
||||
case DisplayMode.Grid:
|
||||
return "th-large";
|
||||
return faThLarge;
|
||||
case DisplayMode.List:
|
||||
return "list";
|
||||
return faList;
|
||||
case DisplayMode.Wall:
|
||||
return "square";
|
||||
return faSquare;
|
||||
case DisplayMode.Tagger:
|
||||
return "tags";
|
||||
return faTags;
|
||||
}
|
||||
}
|
||||
function getLabel(option: DisplayMode) {
|
||||
|
||||
@@ -22,6 +22,7 @@ import { LoadingIndicator } from "src/components/Shared";
|
||||
import { PersistanceLevel } from "src/hooks/ListHook";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import { Icon } from "../Shared";
|
||||
import { faSave, faTimes } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
interface ISavedFilterListProps {
|
||||
filter: ListFilterModel;
|
||||
@@ -191,7 +192,7 @@ export const SavedFilterList: React.FC<ISavedFilterListProps> = ({
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<Icon icon="save" />
|
||||
<Icon icon={faSave} />
|
||||
</Button>
|
||||
<Button
|
||||
className="delete-button"
|
||||
@@ -203,7 +204,7 @@ export const SavedFilterList: React.FC<ISavedFilterListProps> = ({
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<Icon icon="times" />
|
||||
<Icon icon={faTimes} />
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
@@ -344,7 +345,7 @@ export const SavedFilterList: React.FC<ISavedFilterListProps> = ({
|
||||
onSaveFilter(filterName);
|
||||
}}
|
||||
>
|
||||
<Icon icon="save" />
|
||||
<Icon icon={faSave} />
|
||||
</Button>
|
||||
</OverlayTrigger>
|
||||
</InputGroup.Append>
|
||||
|
||||
Reference in New Issue
Block a user