-
+
{props.scene.title
? props.scene.title
: TextUtils.fileNameFromPath(props.scene.path)}
-
+
{props.scene.date}
{TextUtils.truncate(
diff --git a/ui/v2.5/src/components/scenes/SceneMarkerList.tsx b/ui/v2.5/src/components/scenes/SceneMarkerList.tsx
index aea72d974..f3e705585 100644
--- a/ui/v2.5/src/components/scenes/SceneMarkerList.tsx
+++ b/ui/v2.5/src/components/scenes/SceneMarkerList.tsx
@@ -28,7 +28,7 @@ export const SceneMarkerList: React.FC = () => {
filter: ListFilterModel
) {
// query for a random scene
- if (result.data && result.data.findSceneMarkers) {
+ if (result.data?.findSceneMarkers) {
const { count } = result.data.findSceneMarkers;
const index = Math.floor(Math.random() * count);
@@ -37,10 +37,7 @@ export const SceneMarkerList: React.FC = () => {
filterCopy.currentPage = index + 1;
const singleResult = await StashService.queryFindSceneMarkers(filterCopy);
if (
- singleResult &&
- singleResult.data &&
- singleResult.data.findSceneMarkers &&
- singleResult.data.findSceneMarkers.scene_markers.length === 1
+ singleResult?.data?.findSceneMarkers?.scene_markers?.length === 1
) {
// navigate to the scene player page
const url = NavUtils.makeSceneMarkerUrl(
diff --git a/ui/v2.5/src/components/scenes/SceneSelectedOptions.tsx b/ui/v2.5/src/components/scenes/SceneSelectedOptions.tsx
index b40d45d50..6cebdb88a 100644
--- a/ui/v2.5/src/components/scenes/SceneSelectedOptions.tsx
+++ b/ui/v2.5/src/components/scenes/SceneSelectedOptions.tsx
@@ -16,16 +16,14 @@ export const SceneSelectedOptions: React.FC = (
) => {
const Toast = useToast();
const [rating, setRating] = useState("");
- const [studioId, setStudioId] = useState(undefined);
- const [performerIds, setPerformerIds] = useState(
- undefined
- );
- const [tagIds, setTagIds] = useState(undefined);
+ const [studioId, setStudioId] = useState();
+ const [performerIds, setPerformerIds] = useState();
+ const [tagIds, setTagIds] = useState();
const [updateScenes] = StashService.useBulkSceneUpdate(getSceneInput());
// Network state
- const [isLoading, setIsLoading] = useState(false);
+ const [isLoading, setIsLoading] = useState(true);
function getSceneInput(): GQL.BulkSceneUpdateInput {
// need to determine what we are actually setting on each scene
@@ -184,14 +182,14 @@ export const SceneSelectedOptions: React.FC = (
function updateScenesEditState(state: GQL.SlimSceneDataFragment[]) {
let updateRating = "";
- let updateStudioId: string | undefined;
+ let updateStudioId: string|undefined;
let updatePerformerIds: string[] = [];
let updateTagIds: string[] = [];
let first = true;
state.forEach((scene: GQL.SlimSceneDataFragment) => {
- const thisRating = scene.rating ? scene.rating.toString() : "";
- const thisStudio = scene.studio ? scene.studio.id : undefined;
+ const thisRating = scene.rating?.toString() ?? "";
+ const thisStudio = scene?.studio?.id;
if (first) {
updateRating = thisRating;
@@ -231,76 +229,76 @@ export const SceneSelectedOptions: React.FC = (
useEffect(() => {
updateScenesEditState(props.selected);
+ setIsLoading(false);
}, [props.selected]);
function renderMultiSelect(
type: "performers" | "tags",
- initialIds: string[] | undefined
+ ids: string[] | undefined
) {
return (
{
- const ids = items.map(i => i.id);
+ const itemIDs = items.map(i => i.id);
switch (type) {
case "performers":
- setPerformerIds(ids);
+ setPerformerIds(itemIDS);
break;
case "tags":
- setTagIds(ids);
+ setTagIds(itemIDs);
break;
}
}}
- initialIds={initialIds ?? []}
+ ids={ids ?? []}
/>
);
}
+ if(isLoading)
+ return ;
+
function render() {
return (
- <>
- {isLoading ? : undefined}
-
-
- Rating
- setRating(event.target.value)}
- >
- {["", 1, 2, 3, 4, 5].map(opt => (
-
- ))}
-
-
+
+
+ Rating
+ setRating(event.target.value)}
+ >
+ {["", '1', '2', '3', '4', '5'].map(opt => (
+
+ ))}
+
+
-
- Studio
- setStudioId(items[0]?.id)}
- initialIds={studioId ? [studioId] : []}
- />
-
+
+ Studio
+ setStudioId(items[0]?.id)}
+ ids={studioId ? [studioId] : []}
+ />
+
-
- Performers
- {renderMultiSelect("performers", performerIds)}
-
+
+ Performers
+ {renderMultiSelect("performers", performerIds)}
+
-
- Performers
- {renderMultiSelect("tags", tagIds)}
-
+
+ Tags
+ {renderMultiSelect("tags", tagIds)}
+
-
-
-
-
- >
+
+
);
}
diff --git a/ui/v2.5/src/components/scenes/styles.scss b/ui/v2.5/src/components/scenes/styles.scss
new file mode 100644
index 000000000..cd4e36977
--- /dev/null
+++ b/ui/v2.5/src/components/scenes/styles.scss
@@ -0,0 +1,28 @@
+.scene-popovers {
+ display: flex;
+ justify-content: center;
+ margin-bottom: 10px;
+
+ button {
+ padding-top: 3px;
+ padding-bottom: 3px;
+ }
+
+ svg {
+ margin-right: 7px;
+ }
+}
+
+.operation-container {
+ .operation-item {
+ min-width: 200px;
+ }
+
+ .rating-operation {
+ min-width: 20px;
+ }
+
+ .apply-operation {
+ margin-top: 2rem;
+ }
+}
diff --git a/ui/v2.5/src/index.scss b/ui/v2.5/src/index.scss
index 4ced94b47..617966629 100755
--- a/ui/v2.5/src/index.scss
+++ b/ui/v2.5/src/index.scss
@@ -3,6 +3,7 @@
@import "styles/shared/details";
+@import "styles/range";
@import "styles/scrollbars";
@import "styles/variables";
@@ -17,7 +18,6 @@ body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
height: 100vh;
- background: $dark-gray2;
}
code {
@@ -37,10 +37,6 @@ code {
margin: 0;
}
- & .bp3-button.favorite .bp3-icon {
- color: #ff7373 !important
- }
-
& .performer-list-thumbnail {
min-width: 50px;
height: 100px;
@@ -55,58 +51,59 @@ code {
text-align: center;
vertical-align: middle;
}
-}
-.grid-item {
- // flex: auto;
- width: 320px;
- min-width: 185px;
- margin: 0px 0 $pt-grid-size $pt-grid-size;
- overflow: hidden;
+ .card {
+ margin: 0 0 10px 10px;
+ overflow: hidden;
- &.wall {
- width: calc(20%);
- margin: 0;
- }
+ &.zoom-0 {
+ width: 15rem;
- &.zoom-0 {
- width: 240px;
+ & .previewable {
+ max-height: 11.25rem;
+ }
+ & .previewable.portrait {
+ max-height: 11.25rem;
+ }
+ }
+ &.zoom-1 {
+ width: 20rem;
- & .previewable {
- max-height: 180px;
+ & .previewable {
+ max-height: 15rem;
+ }
+ & .previewable.portrait {
+ height: 15rem;
+ }
}
- & .previewable.portrait {
- height: 180px;
- }
- }
- &.zoom-1 {
- width: 320px;
+ &.zoom-2 {
+ width: 30rem;
- & .previewable {
- max-height: 240px;
+ & .previewable {
+ max-height: 22.5rem;
+ }
+ & .previewable.portrait {
+ height: 22.5rem;
+ }
}
- & .previewable.portrait {
- height: 240px;
- }
- }
- &.zoom-2 {
- width: 480px;
+ &.zoom-3 {
+ width: 40rem;
- & .previewable {
- max-height: 360px;
+ & .previewable {
+ max-height: 30rem;
+ }
+ & .previewable.portrait {
+ height: 30rem;
+ }
}
- & .previewable.portrait {
- height: 360px;
- }
- }
- &.zoom-3 {
- width: 640px;
- & .previewable {
- max-height: 480px;
- }
- & .previewable.portrait {
- height: 480px;
+ .card-select {
+ position: absolute;
+ padding-left: 15px;
+ margin-top: -12px;
+ z-index: 1;
+ opacity: 0.5;
+ width: 1.2rem;
}
}
}
@@ -125,14 +122,6 @@ code {
height: 240px;
}
-.grid-item label.card-select {
- position: absolute;
- padding-left: 15px;
- margin-top: -12px;
- z-index: 9;
- opacity: 0.5;
-}
-
.video-container {
width: 100%;
height: 100%;
@@ -336,6 +325,7 @@ span.block {
.performer-tag-container {
margin: 5px;
+ display: inline-block;
}
.performer-tag.image {
@@ -548,7 +538,7 @@ span.block {
background-color: #30404d;
border-radius: 3px;
box-shadow: 0 0 0 1px rgba(16,22,26,.4), 0 0 0 rgba(16,22,26,0), 0 0 0 rgba(16,22,26,0);
- padding: 20px;
+ padding: 20px 20px 0px 20px;
}
.toast-container {
diff --git a/ui/v2.5/src/styles/_range.scss b/ui/v2.5/src/styles/_range.scss
new file mode 100644
index 000000000..f24066ea8
--- /dev/null
+++ b/ui/v2.5/src/styles/_range.scss
@@ -0,0 +1,94 @@
+input[type=range] {
+ height: 22px;
+ -webkit-appearance: none;
+ margin: 10px 0;
+ background-color: transparent;
+ border-color: transparent;
+}
+input[type=range]:focus {
+ border: inherit;
+ box-shadow: none;
+ outline: none;
+ background-color: transparent;
+ border-color: transparent;
+}
+input[type=range]::-webkit-slider-runnable-track {
+ width: 100%;
+ height: 6px;
+ cursor: pointer;
+ animate: 0.2s;
+ box-shadow: 0px 0px 0px #000000;
+ background: #137cbd;
+ border-radius: 25px;
+ border: 0px solid #000101;
+}
+input[type=range]::-webkit-slider-thumb {
+ box-shadow: 0px 0px 0px #000000;
+ border: 0px solid #000000;
+ height: 16px;
+ width: 16px;
+ border-radius: 5px;
+ background: #394B59;
+ cursor: pointer;
+ -webkit-appearance: none;
+ margin-top: -5px;
+}
+input[type=range]:focus::-webkit-slider-runnable-track {
+ background: #137cbd;
+}
+input[type=range]::-moz-range-track {
+ width: 100%;
+ height: 6px;
+ cursor: pointer;
+ animate: 0.2s;
+ box-shadow: 0px 0px 0px #000000;
+ background: #137cbd;
+ border-radius: 25px;
+ border: 0px solid #000101;
+}
+input[type=range]::-moz-range-thumb {
+ box-shadow: 0px 0px 0px #000000;
+ border: 0px solid #000000;
+ height: 16px;
+ width: 16px;
+ border-radius: 5px;
+ background: #394B59;
+ cursor: pointer;
+}
+input[type=range]::-ms-track {
+ width: 100%;
+ height: 6px;
+ cursor: pointer;
+ animate: 0.2s;
+ background: transparent;
+ border-color: transparent;
+ color: transparent;
+}
+input[type=range]::-ms-fill-lower {
+ background: #137cbd;
+ border: 0px solid #000101;
+ border-radius: 50px;
+ box-shadow: 0px 0px 0px #000000;
+}
+input[type=range]::-ms-fill-upper {
+ background: #137cbd;
+ border: 0px solid #000101;
+ border-radius: 50px;
+ box-shadow: 0px 0px 0px #000000;
+}
+input[type=range]::-ms-thumb {
+ margin-top: 1px;
+ box-shadow: 0px 0px 0px #000000;
+ border: 0px solid #000000;
+ height: 16px;
+ width: 16px;
+ border-radius: 5px;
+ background: #394B59;
+ cursor: pointer;
+}
+input[type=range]:focus::-ms-fill-lower {
+ background: #137cbd;
+}
+input[type=range]:focus::-ms-fill-upper {
+ background: #137cbd;
+}
diff --git a/ui/v2.5/src/styles/_theme.scss b/ui/v2.5/src/styles/_theme.scss
index c9247656a..308d5e335 100644
--- a/ui/v2.5/src/styles/_theme.scss
+++ b/ui/v2.5/src/styles/_theme.scss
@@ -1,9 +1,80 @@
/* Blueprint dark theme */
+
+$secondary: #394b59;
+
+$theme-colors: (
+ primary: #137cbd,
+ secondary: $secondary,
+ success: #0f9960,
+ warning: #d9822b,
+ danger: #db3737,
+ dark: #394b59
+);
+
+$body-bg: #202b33;
$text-muted: #bfccd6;
$link-color: #48aff0;
$link-hover-color: #48aff0;
-$text-color: f5f8fa;
+$text-color: #f5f8fa;
$pre-color: $text-color;
+$navbar-dark-color: rgb(245, 248, 250);
+$input-bg: $secondary;
+$input-color: #f5f8fa;
+$popover-bg: $secondary;
@import "node_modules/bootstrap/scss/bootstrap";
+
+.btn.active:not(.disabled),
+.btn.active.minimal:not(.disabled) {
+ background-color: rgba(138,155,168,.3);
+ color: #f5f8fa;
+}
+
+a.minimal,
+button.minimal {
+ background: none;
+ border: none;
+ color: $text-color;
+ transition: none;
+
+ &:hover {
+ background: rgba(138,155,168,.15);
+ color: $text-color;
+ }
+ &:active {
+ background: rgba(138,155,168,.3);
+ color: $text-color;
+ }
+}
+
+input.form-control {
+ background-color: rgba(16, 22, 26, 0.3);
+}
+.form-control {
+ border-color: rgba(16,22,26,.4);
+}
+
+.dropdown-toggle:after {
+ content: none;
+}
+
+nav .svg-inline--fa {
+ margin-right: 7px;
+}
+
+hr {
+ margin: 5px 0;
+}
+
+.table {
+ th {
+ border-top: none;
+ }
+
+ thead {
+ th {
+ border-bottom-width: 1px;
+ }
+ }
+}