This commit is contained in:
Infinite
2020-01-20 21:56:23 +01:00
parent 9827647122
commit 244c8ff234
82 changed files with 3729 additions and 2304 deletions

View File

@@ -4,34 +4,38 @@ const readImage = (file: File, onLoadEnd: (this: FileReader) => void) => {
const reader: FileReader = new FileReader();
reader.onloadend = onLoadEnd;
reader.readAsDataURL(file);
}
};
const pasteImage = (event: ClipboardEvent, onLoadEnd: (this: FileReader) => void) => {
const pasteImage = (
event: ClipboardEvent,
onLoadEnd: (this: FileReader) => void
) => {
const files = event?.clipboardData?.files;
if(!files?.length)
return;
if (!files?.length) return;
const file = files[0];
readImage(file, onLoadEnd);
}
};
const onImageChange = (event: React.FormEvent<HTMLInputElement>, onLoadEnd: (this: FileReader) => void) => {
const onImageChange = (
event: React.FormEvent<HTMLInputElement>,
onLoadEnd: (this: FileReader) => void
) => {
const file = event?.currentTarget?.files?.[0];
if(file)
readImage(file, onLoadEnd);
}
if (file) readImage(file, onLoadEnd);
};
const usePasteImage = (onLoadEnd: (this: FileReader) => void) => {
useEffect(() => {
const paste = (event: ClipboardEvent) => ( pasteImage(event, onLoadEnd) );
const paste = (event: ClipboardEvent) => pasteImage(event, onLoadEnd);
document.addEventListener("paste", paste);
return () => document.removeEventListener("paste", paste);
});
}
};
const Image = {
onImageChange,
usePasteImage
}
};
export default Image;

View File

@@ -1,4 +1,4 @@
export { default as ImageUtils } from './image';
export { default as NavUtils } from './navigation';
export { default as TableUtils } from './table';
export { default as TextUtils } from './text';
export { default as ImageUtils } from "./image";
export { default as NavUtils } from "./navigation";
export { default as TableUtils } from "./table";
export { default as TextUtils } from "./text";

View File

@@ -5,51 +5,54 @@ import { TagsCriterion } from "../models/list-filter/criteria/tags";
import { ListFilterModel } from "../models/list-filter/filter";
import { FilterMode } from "../models/list-filter/types";
const makePerformerScenesUrl = (performer: Partial<GQL.PerformerDataFragment>) => {
if (!performer.id)
return "#";
const makePerformerScenesUrl = (
performer: Partial<GQL.PerformerDataFragment>
) => {
if (!performer.id) return "#";
const filter = new ListFilterModel(FilterMode.Scenes);
const criterion = new PerformersCriterion();
criterion.value = [{ id: performer.id, label: performer.name || `Performer ${performer.id}` }];
criterion.value = [
{ id: performer.id, label: performer.name || `Performer ${performer.id}` }
];
filter.criteria.push(criterion);
return `/scenes?${filter.makeQueryParameters()}`;
}
};
const makeStudioScenesUrl = (studio: Partial<GQL.StudioDataFragment>) => {
if (!studio.id)
return "#";
if (!studio.id) return "#";
const filter = new ListFilterModel(FilterMode.Scenes);
const criterion = new StudiosCriterion();
criterion.value = [{ id: studio.id, label: studio.name || `Studio ${studio.id}` }];
criterion.value = [
{ id: studio.id, label: studio.name || `Studio ${studio.id}` }
];
filter.criteria.push(criterion);
return `/scenes?${filter.makeQueryParameters()}`;
}
};
const makeTagScenesUrl = (tag: Partial<GQL.TagDataFragment>) => {
if (!tag.id)
return "#";
if (!tag.id) return "#";
const filter = new ListFilterModel(FilterMode.Scenes);
const criterion = new TagsCriterion("tags");
criterion.value = [{ id: tag.id, label: tag.name || `Tag ${tag.id}` }];
filter.criteria.push(criterion);
return `/scenes?${filter.makeQueryParameters()}`;
}
};
const makeTagSceneMarkersUrl = (tag: Partial<GQL.TagDataFragment>) => {
if (!tag.id)
return "#";
if (!tag.id) return "#";
const filter = new ListFilterModel(FilterMode.SceneMarkers);
const criterion = new TagsCriterion("tags");
criterion.value = [{ id: tag.id, label: tag.name || `Tag ${tag.id}` }];
filter.criteria.push(criterion);
return `/scenes/markers?${filter.makeQueryParameters()}`;
}
};
const makeSceneMarkerUrl = (sceneMarker: Partial<GQL.SceneMarkerDataFragment>) => {
if (!sceneMarker.id || !sceneMarker.scene)
return "#";
const makeSceneMarkerUrl = (
sceneMarker: Partial<GQL.SceneMarkerDataFragment>
) => {
if (!sceneMarker.id || !sceneMarker.scene) return "#";
return `/scenes/${sceneMarker.scene.id}?t=${sceneMarker.seconds}`;
}
};
const Nav = {
makePerformerScenesUrl,
@@ -57,5 +60,5 @@ const Nav = {
makeTagSceneMarkersUrl,
makeTagScenesUrl,
makeSceneMarkerUrl
}
};
export default Nav;

View File

@@ -1,12 +1,12 @@
import React from "react";
import { Form } from 'react-bootstrap';
import { Form } from "react-bootstrap";
import { FilterSelect } from "src/components/Shared";
const renderEditableTextTableRow = (options: {
title: string;
value?: string | number;
isEditing: boolean;
onChange: ((value: string) => void);
onChange: (value: string) => void;
}) => (
<tr>
<td>{options.title}</td>
@@ -14,19 +14,25 @@ const renderEditableTextTableRow = (options: {
<Form.Control
readOnly={!options.isEditing}
plaintext={!options.isEditing}
onChange={(event: React.FormEvent<HTMLInputElement>) => ( options.onChange(event.currentTarget.value) )}
value={typeof options.value === 'number' ? options.value.toString() : options.value}
onChange={(event: React.FormEvent<HTMLInputElement>) =>
options.onChange(event.currentTarget.value)
}
value={
typeof options.value === "number"
? options.value.toString()
: options.value
}
placeholder={options.title}
/>
</td>
</tr>
)
);
const renderTextArea = (options: {
title: string,
value: string | undefined,
isEditing: boolean,
onChange: ((value: string) => void),
title: string;
value: string | undefined;
isEditing: boolean;
onChange: (value: string) => void;
}) => (
<tr>
<td>{options.title}</td>
@@ -35,19 +41,21 @@ const renderTextArea = (options: {
as="textarea"
readOnly={!options.isEditing}
plaintext={!options.isEditing}
onChange={(event: React.FormEvent<HTMLTextAreaElement>) => ( options.onChange(event.currentTarget.value) )}
onChange={(event: React.FormEvent<HTMLTextAreaElement>) =>
options.onChange(event.currentTarget.value)
}
value={options.value}
/>
</td>
</tr>
)
);
const renderInputGroup = (options: {
title: string,
placeholder?: string,
value: string | undefined,
isEditing: boolean,
onChange: ((value: string) => void),
title: string;
placeholder?: string;
value: string | undefined;
isEditing: boolean;
onChange: (value: string) => void;
}) => (
<tr>
<td>{options.title}</td>
@@ -56,19 +64,21 @@ const renderInputGroup = (options: {
readOnly={!options.isEditing}
plaintext={!options.isEditing}
defaultValue={options.value}
placeholder={options.placeholder ?? options.title}
onChange={(event: React.FormEvent<HTMLInputElement>) => ( options.onChange(event.currentTarget.value) )}
placeholder={options.placeholder ?? options.title}
onChange={(event: React.FormEvent<HTMLInputElement>) =>
options.onChange(event.currentTarget.value)
}
/>
</td>
</tr>
)
);
const renderHtmlSelect = (options: {
title: string,
value?: string | number,
isEditing: boolean,
onChange: ((value: string) => void),
selectOptions: Array<string | number>,
title: string;
value?: string | number;
isEditing: boolean;
onChange: (value: string) => void;
selectOptions: Array<string | number>;
}) => (
<tr>
<td>{options.title}</td>
@@ -77,37 +87,39 @@ const renderHtmlSelect = (options: {
as="select"
readOnly={!options.isEditing}
plaintext={!options.isEditing}
onChange={(event: React.FormEvent<HTMLSelectElement>) => ( options.onChange(event.currentTarget.value) )}
onChange={(event: React.FormEvent<HTMLSelectElement>) =>
options.onChange(event.currentTarget.value)
}
/>
</td>
</tr>
)
);
// TODO: isediting
const renderFilterSelect = (options: {
title: string,
type: "performers" | "studios" | "tags",
initialId: string | undefined,
onChange: ((id: string | undefined) => void),
title: string;
type: "performers" | "studios" | "tags";
initialId: string | undefined;
onChange: (id: string | undefined) => void;
}) => (
<tr>
<td>{options.title}</td>
<td>
<FilterSelect
type={options.type}
onSelect={(items) => options.onChange(items[0]?.id)}
onSelect={items => options.onChange(items[0]?.id)}
initialIds={options.initialId ? [options.initialId] : []}
/>
</td>
</tr>
)
);
// TODO: isediting
const renderMultiSelect = (options: {
title: string,
type: "performers" | "studios" | "tags",
initialIds: string[] | undefined,
onChange: ((ids: string[]) => void),
title: string;
type: "performers" | "studios" | "tags";
initialIds: string[] | undefined;
onChange: (ids: string[]) => void;
}) => (
<tr>
<td>{options.title}</td>
@@ -115,12 +127,12 @@ const renderMultiSelect = (options: {
<FilterSelect
type={options.type}
isMulti
onSelect={(items) => options.onChange(items.map((i) => i.id))}
onSelect={items => options.onChange(items.map(i => i.id))}
initialIds={options.initialIds ?? []}
/>
</td>
</tr>
)
);
const Table = {
renderEditableTextTableRow,
@@ -129,5 +141,5 @@ const Table = {
renderHtmlSelect,
renderFilterSelect,
renderMultiSelect
}
};
export default Table;

View File

@@ -1,19 +1,13 @@
const Units = [
"bytes",
"kB",
"MB",
"GB",
"TB",
"PB",
];
const Units = ["bytes", "kB", "MB", "GB", "TB", "PB"];
const truncate = (value?: string, limit: number = 100, tail: string = "...") => {
if (!value)
return "";
return value.length > limit
? value.substring(0, limit) + tail
: value;
}
const truncate = (
value?: string,
limit: number = 100,
tail: string = "..."
) => {
if (!value) return "";
return value.length > limit ? value.substring(0, limit) + tail : value;
};
const fileSize = (bytes: number = 0, precision: number = 2) => {
if (Number.isNaN(parseFloat(String(bytes))) || !Number.isFinite(bytes))
@@ -21,13 +15,13 @@ const fileSize = (bytes: number = 0, precision: number = 2) => {
let unit = 0;
let count = bytes;
while ( count >= 1024 ) {
while (count >= 1024) {
count /= 1024;
unit++;
}
return `${bytes.toFixed(+precision)} ${Units[unit]}`;
}
};
const secondsToTimestamp = (seconds: number) => {
let ret = new Date(seconds * 1000).toISOString().substr(11, 8);
@@ -41,34 +35,35 @@ const secondsToTimestamp = (seconds: number) => {
ret = ret.substr(1);
}
return ret;
}
};
const fileNameFromPath = (path: string) => {
if (!!path === false)
return "No File Name";
if (!!path === false) return "No File Name";
return path.replace(/^.*[\\/]/, "");
}
};
const getAge = (dateString?: string, fromDateString?: string) => {
if (!dateString)
return 0;
if (!dateString) return 0;
const birthdate = new Date(dateString);
const fromDate = fromDateString ? new Date(fromDateString) : new Date();
let age = fromDate.getFullYear() - birthdate.getFullYear();
if (birthdate.getMonth() > fromDate.getMonth() ||
(birthdate.getMonth() >= fromDate.getMonth() && birthdate.getDay() > fromDate.getDay())) {
if (
birthdate.getMonth() > fromDate.getMonth() ||
(birthdate.getMonth() >= fromDate.getMonth() &&
birthdate.getDay() > fromDate.getDay())
) {
age -= 1;
}
return age;
}
};
const bitRate = (bitrate: number) => {
const megabits = bitrate / 1000000;
return `${megabits.toFixed(2)} megabits per second`;
}
};
const resolution = (height: number) => {
if (height >= 240 && height < 480) {
@@ -86,7 +81,7 @@ const resolution = (height: number) => {
if (height >= 2160) {
return "4K";
}
}
};
const TextUtils = {
truncate,
@@ -96,6 +91,6 @@ const TextUtils = {
age: getAge,
bitRate,
resolution
}
};
export default TextUtils;