diff --git a/ui/v2.5/.stylelintrc b/ui/v2.5/.stylelintrc index ee81606c1..0cd6917bb 100644 --- a/ui/v2.5/.stylelintrc +++ b/ui/v2.5/.stylelintrc @@ -3,6 +3,7 @@ "stylelint-order" ], "rules": { + "indentation": 2, "at-rule-empty-line-before": [ "always", { except: ["after-same-name", "first-nested" ], ignore: ["after-comment"], @@ -46,7 +47,6 @@ "function-parentheses-space-inside": "never-single-line", "function-url-quotes": "always", "function-whitespace-after": "always", - "indentation": 4, "length-zero-no-unit": true, "max-empty-lines": 1, "max-nesting-depth": 3, diff --git a/ui/v2.5/src/App.tsx b/ui/v2.5/src/App.tsx index 4331adcb4..f10df123b 100755 --- a/ui/v2.5/src/App.tsx +++ b/ui/v2.5/src/App.tsx @@ -12,7 +12,7 @@ import Scenes from "./components/scenes/scenes"; import { Settings } from "./components/Settings/Settings"; import { Stats } from "./components/Stats"; import Studios from "./components/Studios/Studios"; -import Tags from "./components/Tags/Tags"; +import { TagList } from "./components/Tags/TagList"; import { SceneFilenameParser } from "./components/scenes/SceneFilenameParser"; library.add(fas); @@ -20,8 +20,8 @@ library.add(fas); export const App: React.FC = () => (
- +
@@ -29,7 +29,7 @@ export const App: React.FC = () => ( {/* */} - + { @@ -26,10 +27,8 @@ export const SettingsAboutPanel: React.FC = () => { function maybeRenderLatestVersion() { if ( - !dataLatest || - !dataLatest.latestversion || - !dataLatest.latestversion.shorthash || - !dataLatest.latestversion.url + !dataLatest?.latestversion.shorthash || + !dataLatest?.latestversion.url ) { return; } @@ -149,12 +148,12 @@ export const SettingsAboutPanel: React.FC = () => { - {!data || loading ? : ""} + {!data || loading ? : ""} {error && {error.message}} {errorLatest && {errorLatest.message}} {renderVersion()} {!dataLatest || loadingLatest || networkStatus === 4 ? ( - + ) : ( <>{renderLatestVersion()} )} diff --git a/ui/v2.5/src/components/Settings/SettingsConfigurationPanel.tsx b/ui/v2.5/src/components/Settings/SettingsConfigurationPanel.tsx index 6a3151f03..3ab11fa12 100644 --- a/ui/v2.5/src/components/Settings/SettingsConfigurationPanel.tsx +++ b/ui/v2.5/src/components/Settings/SettingsConfigurationPanel.tsx @@ -1,9 +1,9 @@ import React, { useEffect, useState } from "react"; -import { Button, Form, InputGroup, Spinner } from "react-bootstrap"; +import { Button, Form, InputGroup } from "react-bootstrap"; import * as GQL from "src/core/generated-graphql"; import { StashService } from "src/core/StashService"; import { useToast } from "src/hooks"; -import { Icon } from "src/components/Shared"; +import { Icon, LoadingIndicator } from "src/components/Shared"; import { FolderSelect } from "src/components/Shared/FolderSelect/FolderSelect"; export const SettingsConfigurationPanel: React.FC = () => { @@ -154,7 +154,7 @@ export const SettingsConfigurationPanel: React.FC = () => { if (error) return

{error.message}

; if (!data?.configuration || loading) - return ; + return ; return ( <> diff --git a/ui/v2.5/src/components/Settings/SettingsInterfacePanel.tsx b/ui/v2.5/src/components/Settings/SettingsInterfacePanel.tsx index 8f02b877f..f3e699942 100644 --- a/ui/v2.5/src/components/Settings/SettingsInterfacePanel.tsx +++ b/ui/v2.5/src/components/Settings/SettingsInterfacePanel.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from "react"; -import { Button, Form, Spinner } from "react-bootstrap"; +import { Button, Form } from "react-bootstrap"; +import { LoadingIndicator } from 'src/components/Shared'; import { StashService } from "src/core/StashService"; import { useToast } from "src/hooks"; @@ -52,7 +53,7 @@ export const SettingsInterfacePanel: React.FC = () => { <> {config.error ?

{config.error.message}

: ""} {!config?.data?.configuration || config.loading ? ( - + ) : ( "" )} diff --git a/ui/v2.5/src/components/Shared/DetailsEditNavbar.tsx b/ui/v2.5/src/components/Shared/DetailsEditNavbar.tsx index 6be81b8a8..72dae007b 100644 --- a/ui/v2.5/src/components/Shared/DetailsEditNavbar.tsx +++ b/ui/v2.5/src/components/Shared/DetailsEditNavbar.tsx @@ -1,16 +1,10 @@ import { Button, - Form, Modal, - Nav, - Navbar, - OverlayTrigger, - Popover } from "react-bootstrap"; import React, { useState } from "react"; -import { Link } from "react-router-dom"; import * as GQL from "src/core/generated-graphql"; -import { NavUtils } from "src/utils"; +import { ImageInput } from 'src/components/Shared'; interface IProps { performer?: Partial; @@ -22,102 +16,46 @@ interface IProps { onDelete: () => void; onAutoTag?: () => void; onImageChange: (event: React.FormEvent) => void; - - // TODO: only for performers. make generic - scrapers?: Pick[]; - onDisplayScraperDialog?: (scraper: Pick) => void; } export const DetailsEditNavbar: React.FC = (props: IProps) => { const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false); function renderEditButton() { - if (props.isNew) { - return; - } + if (props.isNew) return; return ( - ); } function renderSaveButton() { - if (!props.isEditing) { - return; - } + if (!props.isEditing) return; + return ( - ); } function renderDeleteButton() { - if (props.isNew || props.isEditing) { - return; - } + if (props.isNew || props.isEditing) return; return ( - ); } - function renderImageInput() { - if (!props.isEditing) { - return; - } - return ( - - Choose image... - - - ); - } - - function renderScraperMenu() { - if (!props.performer || !props.isEditing) { - return; - } - - const popover = ( - - -
- {props.scrapers - ? props.scrapers.map(s => ( - - )) - : ""} -
-
-
- ); - - return ( - - - - ); - } - function renderAutoTagButton() { - if (props.isNew || props.isEditing) { - return; - } + if (props.isNew || props.isEditing) return; + if (props.onAutoTag) { return ( - @@ -53,7 +53,7 @@ export const DurationInput: React.FC = (props: IProps) => { function maybeRenderReset() { if (props.onReset) { return ( - ); diff --git a/ui/v2.5/src/components/Shared/FolderSelect/FolderSelect.tsx b/ui/v2.5/src/components/Shared/FolderSelect/FolderSelect.tsx index 7c605cbce..f0f626788 100644 --- a/ui/v2.5/src/components/Shared/FolderSelect/FolderSelect.tsx +++ b/ui/v2.5/src/components/Shared/FolderSelect/FolderSelect.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from "react"; -import { Button, InputGroup, Form, Modal, Spinner } from "react-bootstrap"; +import { Button, InputGroup, Form, Modal } from "react-bootstrap"; +import { LoadingIndicator } from 'src/components/Shared'; import { StashService } from "src/core/StashService"; interface IProps { @@ -55,7 +56,7 @@ export const FolderSelect: React.FC = (props: IProps) => { /> {!data || !data.directories || loading ? ( - + ) : ( "" )} diff --git a/ui/v2.5/src/components/Shared/ImageInput.tsx b/ui/v2.5/src/components/Shared/ImageInput.tsx new file mode 100644 index 000000000..7a2711083 --- /dev/null +++ b/ui/v2.5/src/components/Shared/ImageInput.tsx @@ -0,0 +1,23 @@ +import React from "react"; +import { Button, Form } from 'react-bootstrap'; + +interface IImageInput { + isEditing: boolean; + onImageChange: (event: React.FormEvent) => void; +} + +export const ImageInput: React.FC = ({ isEditing, onImageChange }) => { + if (!isEditing) return
; + + return ( + + + + + ); +} + diff --git a/ui/v2.5/src/components/Shared/LoadingIndicator.tsx b/ui/v2.5/src/components/Shared/LoadingIndicator.tsx index 07119f222..5415eb985 100644 --- a/ui/v2.5/src/components/Shared/LoadingIndicator.tsx +++ b/ui/v2.5/src/components/Shared/LoadingIndicator.tsx @@ -1,19 +1,21 @@ import React from "react"; import { Spinner } from "react-bootstrap"; +import cx from 'classnames'; interface ILoadingProps { - message: string; + message?: string; + inline?: boolean; } const CLASSNAME = "LoadingIndicator"; const CLASSNAME_MESSAGE = `${CLASSNAME}-message`; -const LoadingIndicator: React.FC = ({ message }) => ( -
+const LoadingIndicator: React.FC = ({ message, inline = false }) => ( +
Loading... -

{message}

+

{message ?? "Loading..."}

); diff --git a/ui/v2.5/src/components/Shared/Select.tsx b/ui/v2.5/src/components/Shared/Select.tsx index a587a964e..61b318c41 100644 --- a/ui/v2.5/src/components/Shared/Select.tsx +++ b/ui/v2.5/src/components/Shared/Select.tsx @@ -1,4 +1,4 @@ -import React, { useState, useCallback } from "react"; +import React, { useState, useCallback, CSSProperties } from "react"; import Select, { ValueType } from "react-select"; import CreatableSelect from "react-select/creatable"; import { debounce } from "lodash"; @@ -38,6 +38,8 @@ interface ISelectProps { isClearable?: boolean, onInputChange?: (input: string) => void; placeholder?: string; + showDropdown?: boolean; + groupHeader?: string; } interface ISceneGallerySelect { @@ -120,6 +122,8 @@ export const ScrapePerformerSuggest: React.FC = pr items={items} initialIds={[]} placeholder={props.placeholder} + className="select-suggest" + showDropdown={false} /> ); }; @@ -147,10 +151,13 @@ export const MarkerTitleSuggest: React.FC = props => { isLoading={loading} items={items} initialIds={initialIds} + placeholder="Marker title..." + className="select-suggest" + showDropdown={false} + groupHeader="Previously used titles..." /> ); }; - export const FilterSelect: React.FC = props => props.type === "performers" ? ( @@ -304,44 +311,28 @@ const SelectComponent: React.FC = ({ creatable = false, isMulti = false, onInputChange, - placeholder + placeholder, + showDropdown = true, + groupHeader }) => { const defaultValue = items.filter(item => initialIds?.indexOf(item.value) !== -1) ?? null; + const options = groupHeader ? [{ + label: groupHeader, + options: items + }] : items; + const styles = { - control: (provided:any) => ({ + option: (provided:CSSProperties) => ({ ...provided, - background: '#394b59', - borderColor: 'rgba(16,22,26,.4)' - }), - singleValue: (provided:any) => ({ - ...provided, - color: 'f5f8fa', - }), - placeholder: (provided:any) => ({ - ...provided, - color: 'f5f8fa', - }), - menu: (provided:any) => ({ - ...provided, - color: 'f5f8fa', - background: '#394b59', - borderColor: 'rgba(16,22,26,.4)', - zIndex: 3 - }), - option: (provided:any, state:any ) => ( - state.isFocused ? { ...provided, backgroundColor: '#137cbd' } : provided - ), - multiValueRemove: (provided:any, state:any) => ( - { ...provided, color: 'black' } - ) + color: "#000" + }) }; const props = { - options: items, + options, value: selectedOptions, - styles, className, onChange, isMulti, @@ -351,7 +342,11 @@ const SelectComponent: React.FC = ({ placeholder, onInputChange, isLoading, - components: { IndicatorSeparator: () => null } + styles, + components: { + IndicatorSeparator: () => null, + ...(!showDropdown && { DropdownIndicator: () => null }) + } }; return creatable ? ( diff --git a/ui/v2.5/src/components/Shared/index.ts b/ui/v2.5/src/components/Shared/index.ts index 1ddd817e0..9138f415e 100644 --- a/ui/v2.5/src/components/Shared/index.ts +++ b/ui/v2.5/src/components/Shared/index.ts @@ -15,3 +15,4 @@ export { DurationInput } from "./DurationInput"; export { TagLink } from "./TagLink"; export { HoverPopover } from "./HoverPopover"; export { default as LoadingIndicator } from "./LoadingIndicator"; +export { ImageInput } from './ImageInput'; diff --git a/ui/v2.5/src/components/Shared/styles.scss b/ui/v2.5/src/components/Shared/styles.scss index 0c29e1daa..aa23b93f4 100644 --- a/ui/v2.5/src/components/Shared/styles.scss +++ b/ui/v2.5/src/components/Shared/styles.scss @@ -1,17 +1,49 @@ .LoadingIndicator { - align-items: center; - display: flex; - flex-direction: column; - height: 70vh; - justify-content: center; - width: 100%; + align-items: center; + display: flex; + flex-direction: column; + height: 70vh; + justify-content: center; + width: 100%; - &-message { - margin-top: 1rem; - } + &-message { + margin-top: 1rem; + } - .spinner-border { - height: 3rem; - width: 3rem; - } + .spinner-border { + height: 3rem; + width: 3rem; + } + + &.inline { + height: inherit; + } +} + +.details-edit { + display: flex; + justify-content: left; + + .btn { + margin-right: .5rem; + } + + .delete, + .save { + margin-left: auto; + } +} + +.select-suggest { + &:hover { + cursor: text; + } +} + +.duration-button { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + line-height: 10px; + margin-left: 0 !important; + padding: 1px 7px; } diff --git a/ui/v2.5/src/components/Studios/StudioCard.tsx b/ui/v2.5/src/components/Studios/StudioCard.tsx index 095c6a564..8507263e8 100644 --- a/ui/v2.5/src/components/Studios/StudioCard.tsx +++ b/ui/v2.5/src/components/Studios/StudioCard.tsx @@ -9,14 +9,14 @@ interface IProps { export const StudioCard: React.FC = ({ studio }) => { return ( - +
-

{studio.name}

+
{studio.name}
{studio.scene_count} scenes.
diff --git a/ui/v2.5/src/components/Studios/StudioDetails/Studio.tsx b/ui/v2.5/src/components/Studios/StudioDetails/Studio.tsx index 8369f0676..93bd56d25 100644 --- a/ui/v2.5/src/components/Studios/StudioDetails/Studio.tsx +++ b/ui/v2.5/src/components/Studios/StudioDetails/Studio.tsx @@ -1,14 +1,16 @@ /* eslint-disable react/no-this-in-sfc */ -import { Form, Spinner, Table } from "react-bootstrap"; +import { Table } from "react-bootstrap"; import React, { useEffect, useState } from "react"; import { useParams, useHistory } from "react-router-dom"; +import cx from 'classnames'; import * as GQL from "src/core/generated-graphql"; import { StashService } from "src/core/StashService"; import { ImageUtils, TableUtils } from "src/utils"; -import { DetailsEditNavbar } from "src/components/Shared"; +import { DetailsEditNavbar, Modal, LoadingIndicator } from "src/components/Shared"; import { useToast } from "src/hooks"; +import { StudioScenesPanel } from './StudioScenesPanel'; export const Studio: React.FC = () => { const history = useHistory(); @@ -18,17 +20,16 @@ export const Studio: React.FC = () => { // Editing state const [isEditing, setIsEditing] = useState(isNew); + const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false); // Editing studio state - const [image, setImage] = useState(undefined); - const [name, setName] = useState(undefined); - const [url, setUrl] = useState(undefined); + const [image, setImage] = useState(); + const [name, setName] = useState(); + const [url, setUrl] = useState(); // Studio state const [studio, setStudio] = useState>({}); - const [imagePreview, setImagePreview] = useState( - undefined - ); + const [imagePreview, setImagePreview] = useState(); const { data, error, loading } = StashService.useFindStudio(id); const [updateStudio] = StashService.useStudioUpdate( @@ -71,7 +72,7 @@ export const Studio: React.FC = () => { if (!isNew && !isEditing) { if (!data?.findStudio || loading) - return ; + return ; if (error) return
{error.message}
; } @@ -98,8 +99,10 @@ export const Studio: React.FC = () => { } } else { const result = await createStudio(); - if (result.data?.studioCreate?.id) + if (result.data?.studioCreate?.id) { history.push(`/studios/${result.data.studioCreate.id}`); + setIsEditing(false); + } } } catch (e) { Toast.error(e); @@ -107,9 +110,7 @@ export const Studio: React.FC = () => { } async function onAutoTag() { - if (!studio || !studio.id) { - return; - } + if (!studio.id) return; try { await StashService.queryMetadataAutoTag({ studios: [studio.id] }); Toast.success({ content: "Started auto tagging" }); @@ -133,52 +134,57 @@ export const Studio: React.FC = () => { ImageUtils.onImageChange(event, onImageLoad); } - // TODO: CSS class + function renderDeleteAlert() { + return ( + setIsDeleteAlertOpen(false) }} + > +

Are you sure you want to delete {studio.name ?? 'studio'}?

+
+ ); + } + return ( -
-
- {name} -
-
+
+
+ { isNew &&

Add Studio

} + {name} + + + {TableUtils.renderInputGroup({ + title: "Name", + value: studio.name ?? '', + isEditing: !!isEditing, + onChange: setName + })} + {TableUtils.renderInputGroup({ + title: "URL", + value: url, + isEditing: !!isEditing, + onChange: setUrl + })} + +
{ - setIsEditing(!isEditing); - updateStudioEditState(studio); - }} + onToggleEdit={() => setIsEditing(!isEditing)} onSave={onSave} - onDelete={onDelete} - onAutoTag={onAutoTag} onImageChange={onImageChangeHandler} + onAutoTag={onAutoTag} + onDelete={onDelete} /> -

- {!isEditing ? ( - {studio.name} - ) : ( - - Name - setName(event.target.value)} - /> - - )} -

- - - - {TableUtils.renderInputGroup({ - title: "URL", - value: studio.url ?? undefined, - isEditing, - onChange: (val: string) => setUrl(val) - })} - -
+ { !isNew && ( +
+ +
+ )} + {renderDeleteAlert()}
); }; diff --git a/ui/v2.5/src/components/Studios/StudioDetails/StudioScenesPanel.tsx b/ui/v2.5/src/components/Studios/StudioDetails/StudioScenesPanel.tsx new file mode 100644 index 000000000..92a4d5f24 --- /dev/null +++ b/ui/v2.5/src/components/Studios/StudioDetails/StudioScenesPanel.tsx @@ -0,0 +1,47 @@ +import React from "react"; +import * as GQL from "src/core/generated-graphql"; +import { StudiosCriterion } from "src/models/list-filter/criteria/studios"; +import { ListFilterModel } from "src/models/list-filter/filter"; +import { SceneList } from "../../scenes/SceneList"; + +interface IStudioScenesPanel { + studio: Partial; +} + +export const StudioScenesPanel: React.FC = ({ + studio +}) => { + function filterHook(filter: ListFilterModel) { + const studioValue = { id: studio.id!, label: studio.name! }; + // if studio is already present, then we modify it, otherwise add + let studioCriterion = filter.criteria.find(c => { + return c.type === "studios"; + }); + + if ( + studioCriterion && + (studioCriterion.modifier === GQL.CriterionModifier.IncludesAll || + studioCriterion.modifier === GQL.CriterionModifier.Includes) + ) { + // add the studio if not present + if ( + !studioCriterion.value.find((p: any) => { + return p.id === studio.id; + }) + ) { + studioCriterion.value.push(studioValue); + } + + studioCriterion.modifier = GQL.CriterionModifier.IncludesAll; + } else { + // overwrite + studioCriterion = new StudiosCriterion(); + studioCriterion.value = [studioValue]; + filter.criteria.push(studioCriterion); + } + + return filter; + } + + return ; +}; diff --git a/ui/v2.5/src/components/Studios/StudioList.tsx b/ui/v2.5/src/components/Studios/StudioList.tsx index cc3f795b9..1173b1678 100644 --- a/ui/v2.5/src/components/Studios/StudioList.tsx +++ b/ui/v2.5/src/components/Studios/StudioList.tsx @@ -14,9 +14,9 @@ export const StudioList: React.FC = () => { result: FindStudiosQueryResult, filter: ListFilterModel ) { - if (!result.data || !result.data.findStudios) { + if (!result.data?.findStudios) return; - } + if (filter.displayMode === DisplayMode.Grid) { return (
diff --git a/ui/v2.5/src/components/Studios/styles.scss b/ui/v2.5/src/components/Studios/styles.scss new file mode 100644 index 000000000..e5ea10296 --- /dev/null +++ b/ui/v2.5/src/components/Studios/styles.scss @@ -0,0 +1,8 @@ +.studio-details { + padding-left: 4rem; + + .logo { + margin: 4rem 0; + width: 100%; + } +} diff --git a/ui/v2.5/src/components/Tags/TagList.tsx b/ui/v2.5/src/components/Tags/TagList.tsx index dfc975188..7dfbfb6fc 100644 --- a/ui/v2.5/src/components/Tags/TagList.tsx +++ b/ui/v2.5/src/components/Tags/TagList.tsx @@ -1,10 +1,10 @@ import React, { useState } from "react"; -import { Button, Form, Spinner } from "react-bootstrap"; +import { Button, Form } from "react-bootstrap"; import { Link } from "react-router-dom"; import * as GQL from "src/core/generated-graphql"; import { StashService } from "src/core/StashService"; import { NavUtils } from "src/utils"; -import { Icon, Modal } from "src/components/Shared"; +import { Icon, Modal, LoadingIndicator } from "src/components/Shared"; import { useToast } from "src/hooks"; export const TagList: React.FC = () => { @@ -93,34 +93,36 @@ export const TagList: React.FC = () => { ); - if (!data?.allTags) return ; + if (!data?.allTags) + return ; if (error) return
{error.message}
; const tagElements = data.allTags.map(tag => { return ( - <> - {deleteAlert} -
- -
- +
+ +
+ + + -
+ + + Total: {(tag.scene_count || 0) + (tag.scene_marker_count || 0)} + +
- +
); }); @@ -154,6 +156,7 @@ export const TagList: React.FC = () => { {tagElements} + {deleteAlert}
); }; diff --git a/ui/v2.5/src/components/Tags/Tags.tsx b/ui/v2.5/src/components/Tags/Tags.tsx deleted file mode 100644 index ef9678c39..000000000 --- a/ui/v2.5/src/components/Tags/Tags.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from "react"; -import { Route, Switch } from "react-router-dom"; -import { TagList } from "./TagList"; - -const Tags = () => ( - - - -); - -export default Tags; diff --git a/ui/v2.5/src/components/Tags/styles.scss b/ui/v2.5/src/components/Tags/styles.scss new file mode 100644 index 000000000..54652f2d8 --- /dev/null +++ b/ui/v2.5/src/components/Tags/styles.scss @@ -0,0 +1,28 @@ + +#tag-list-container { + display: flex; + flex-direction: column; + margin: 0 auto; + width: 50vw; + + a, + .btn { + color: $text-color; + text-decoration: none; + } + + .tag-list-row { + cursor: pointer; + margin: 10px; + + .btn { + margin: 0 10px; + } + } + + .tag-list-row:hover { + text-decoration: underline; + } +} + + diff --git a/ui/v2.5/src/components/Wall/Wall.scss b/ui/v2.5/src/components/Wall/Wall.scss index b1d870b96..78c4218a1 100644 --- a/ui/v2.5/src/components/Wall/Wall.scss +++ b/ui/v2.5/src/components/Wall/Wall.scss @@ -1,35 +1,38 @@ .wall-overlay { - background-color: rgba(0,0,0,.8); - position: fixed; - top: 0; - left: 0; - right: 0; + background-color: rgba(0, 0, 0, .8); bottom: 0; - z-index: 1; + left: 0; pointer-events: none; + position: fixed; + right: 0; + top: 0; transition: transform .5s ease-in-out; + z-index: 1; } + .visible { opacity: 1; transition: opacity .5s ease-in-out; } + .hidden { opacity: 0; transition: opacity .5s ease-in-out; } + .visible-unanimated { opacity: 1; } + .hidden-unanimated { opacity: 0; } - .double-scale { - position: absolute; - z-index: 2; - transform: scale(2); background-color: black; + position: absolute; + transform: scale(2); + z-index: 2; } .double-scale img { @@ -38,60 +41,61 @@ .scene-wall-item-container { display: flex; - justify-content: center; - position: relative; - width: 100%; height: 100%; - transition: transform .5s; + justify-content: center; max-height: 253px; + position: relative; + transition: transform .5s; + width: 100%; } .scene-wall-item-container video { + height: 100%; position: absolute; width: 100%; - height: 100%; z-index: -1; } .scene-wall-item-text-container { - position: absolute; - font-weight: 700; - color: #444; - padding: 5px; - width: 100%; + background: linear-gradient(rgba(255, 255, 255, .25), rgba(255, 255, 255, .65)); bottom: 0; + color: #444; + font-weight: 700; left: 0; - background: linear-gradient(rgba(255, 255, 255, 0.25), rgba(255, 255, 255, 0.65)); overflow: hidden; + padding: 5px; + position: absolute; text-align: center; + width: 100%; & span { - line-height: 1; - font-weight: 400; font-size: 10px; + font-weight: 400; + line-height: 1; margin: 0 3px; } } .scene-wall-item-blur { - position: absolute; - top: -5px; - left: -5px; - right: -5px; bottom: -5px; + left: -5px; + position: absolute; + right: -5px; + top: -5px; z-index: -1; } -.wall-item video, .wall-item img { - width: 100%; +.wall-item video, +.wall-item img { height: 100%; object-fit: contain; + width: 100%; } .wall-item { - width: 20%; - padding: 0 !important; line-height: 0; overflow: visible; + padding: 0 !important; position: relative; + width: 20%; } diff --git a/ui/v2.5/src/components/Wall/WallItem.tsx b/ui/v2.5/src/components/Wall/WallItem.tsx index 6fb6a7d2e..37e45f6d6 100644 --- a/ui/v2.5/src/components/Wall/WallItem.tsx +++ b/ui/v2.5/src/components/Wall/WallItem.tsx @@ -62,7 +62,7 @@ export const WallItem: React.FC = ( } let linkSrc: string = "#"; - if (props.clickHandler) { + if (!props.clickHandler) { if (props.scene) { linkSrc = `/scenes/${props.scene.id}`; } else if (props.sceneMarker) { @@ -100,7 +100,6 @@ export const WallItem: React.FC = ( setPreviewPath(props.scene.paths.webp || ""); setScreenshotPath(props.scene.paths.screenshot || ""); setTitle(props.scene.title || ""); - // tags = props.scene.tags.map((tag) => ({tag.name})); } }, [props.sceneMarker, props.scene]); @@ -128,7 +127,7 @@ export const WallItem: React.FC = ( onMouseMove={() => debouncedOnMouseEnter.current()} onMouseLeave={onMouseLeave} > - onClick()} to={linkSrc}> +