Skip to content

Commit

Permalink
Merge pull request #3702 from voxel51/merge/v0.22.2-to-main
Browse files Browse the repository at this point in the history
Merge/v0.22.2 to main
  • Loading branch information
findtopher authored Oct 20, 2023
2 parents c098d9c + b785fc7 commit 3d5fe39
Show file tree
Hide file tree
Showing 70 changed files with 1,167 additions and 360 deletions.
13 changes: 13 additions & 0 deletions app/packages/core/src/plugins/OperatorIO/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const inputComponentsByType = {
OneOf: "OneOfView",
Tuple: "TupleView",
Map: "MapView",
File: "FileExplorerView",
UploadedFile: "FileView",
};
const outputComponentsByType = {
Object: "ObjectView",
Expand All @@ -18,6 +20,8 @@ const outputComponentsByType = {
List: "ListView",
OneOf: "OneOfView",
Tuple: "TupleView",
File: "FileExplorerView",
UploadedFile: "FileView",
};
const baseViews = ["View", "PromptView"];
const viewAliases = {
Expand All @@ -41,6 +45,8 @@ const operatorTypeToJSONSchemaType = {
OneOf: "oneOf",
Tuple: "array",
Map: "object",
File: "object",
UploadedFile: "object",
};
const unsupportedView = "UnsupportedView";

Expand Down Expand Up @@ -105,6 +111,13 @@ function getSchema(property, options = {}) {

const computedOptions = { ...options, readOnly: schema.view.readOnly };

if (typeName === "Number") {
const { min, max, float } = property.type;
schema.min = min;
schema.max = max;
schema.multipleOf = float ? 0.01 : 1;
}

if (typeName === "Object") {
schema.properties = getPropertiesSchema(property, computedOptions);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,20 @@ export default function FileDrop({
const [fileIds, setFileIds] = useState(new Set());
const fileInputRef = useRef(null);

const clear = () => {
setFiles([]);
setFileIds(new Set());
};

useEffect(() => {
const updatedFileIds = new Set();
for (const file of files) {
updatedFileIds.add(getFileId(file));
}
if (onChange) onChange(files);
setFileIds(updatedFileIds);
if (onChange) {
onChange(files, clear);
}
}, [files]);

function addUniqueFiles(newFiles: FileList) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import FolderIcon from "@mui/icons-material/Folder";
import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile";
import moment from "moment";
import { scrollable } from "@fiftyone/components";
import { humanReadableBytes } from "@fiftyone/utilities";

const Wrapper = ({ children }) => (
<Paper
Expand All @@ -30,19 +31,6 @@ const Wrapper = ({ children }) => (
</Paper>
);

function humanReadableBytes(bytes: number): string {
if (!bytes) return "";

const units: string[] = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];

if (bytes === 0) return "0 Byte";

const k = 1024;
const i = Math.floor(Math.log(bytes) / Math.log(k));

return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + units[i];
}

function FileTable({
chooseMode,
files,
Expand Down
81 changes: 52 additions & 29 deletions app/packages/core/src/plugins/SchemaIO/components/FileView.tsx
Original file line number Diff line number Diff line change
@@ -1,57 +1,76 @@
import { Box } from "@mui/material";
import { Alert, Box, Typography } from "@mui/material";
import React, { useState } from "react";
import FileDrop from "./FileDrop";
import HeaderView from "./HeaderView";
import TabsView from "./TabsView";
import TextFieldView from "./TextFieldView";
import { getComponentProps } from "../utils";
import { humanReadableBytes } from "@fiftyone/utilities";

export default function FileView(props) {
const { onChange, path, schema, autoFocused } = props;
const { view = {} } = schema;
const { types } = view;
const [type, setType] = useState("file");
const [type] = useState("file");
const isObject = schema.type === "object";
const maxSize = view.max_size || null;
const customMaxSizeMessage = view.max_size_error_message || null;
const [currentError, setCurrentError] = useState(null);

const showError = (message) => {
setCurrentError({ message });
};

return (
<Box {...getComponentProps(props, "container")}>
<HeaderView {...props} nested />
<TabsView
schema={{
view: {
choices: [
{ value: "file", label: "Upload" },
{ value: "url", label: "URL" },
],
},
}}
onChange={(path, value) => {
setType(value);
onChange(path, "");
}}
{...getComponentProps(props, "tabs")}
/>
<Box sx={{ pt: 1 }} {...getComponentProps(props, "fileContainer")}>
{type === "file" && (
<FileDrop
onChange={async (files) => {
if (files?.length === 0) return onChange(path, "");
onChange={async (files, clear) => {
if (files?.length === 0) {
return onChange(path, null);
}
const [file] = files;
const { error, result } = await fileToBase64(file);
if (error) return; // todo: handle error
onChange(path, result);
if (error) {
clear();
// NOTE: error is a ProgressEvent<EventTarget>
// there is no error message - so we print it to the console
const msg = "Error reading file";
console.error(msg);
console.error(error);
showError(msg);
return;
}
if (maxSize && file.size > maxSize) {
clear();
showError(
customMaxSizeMessage ||
`File size must be less than ${humanReadableBytes(maxSize)}`
);
return;
}
setCurrentError(null);
const resultStripped = stripBase64Prefix(result);
const obj = {
content: resultStripped,
name: file.name,
type: file.type,
size: file.size,
last_modified: file.lastModified,
};
if (isObject) return onChange(path, obj);
onChange(path, resultStripped);
}}
types={types}
autoFocused={autoFocused}
// allowMultiple={allowMultiple}
{...getComponentProps(props, "fileDrop")}
/>
)}
{type === "url" && (
<TextFieldView
schema={{ view: { placeholder: "URL to a file" } }}
onChange={onChange}
{...getComponentProps(props, "fileURL")}
/>
{currentError && (
<Alert severity="warning">
<Typography>{currentError.message}</Typography>
</Alert>
)}
</Box>
</Box>
Expand All @@ -68,3 +87,7 @@ function fileToBase64(
fileReader.onerror = (error) => resolve({ error });
});
}

function stripBase64Prefix(data: string): string {
return data.slice(data.indexOf(",") + 1);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default function SliderView(props) {
const { data, onChange, path, schema } = props;
const sliderRef = useRef<HTMLInputElement>(null);
const focus = autoFocus(props);
const { min = 0, max = 100, multipleOf = 1 } = schema;

useEffect(() => {
if (sliderRef.current && focus) {
Expand All @@ -17,6 +18,9 @@ export default function SliderView(props) {
return (
<FieldWrapper {...props}>
<Slider
min={min}
max={max}
step={multipleOf}
disabled={schema.view?.readOnly}
valueLabelDisplay="auto"
value={data ?? schema.default}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import { getComponentProps } from "../utils";

export default function TextFieldView(props) {
const { schema, onChange, path, data } = props;
const { type, view = {} } = schema;
const { type, view = {}, min, max, multipleOf = 1 } = schema;

const { inputProps = {}, ...fieldProps } = getComponentProps(props, "field");

return (
<FieldWrapper {...props}>
Expand All @@ -22,7 +24,8 @@ export default function TextFieldView(props) {
const value = e.target.value;
onChange(path, type === "number" ? parseFloat(value) : value);
}}
{...getComponentProps(props, "field")}
inputProps={{ min, max, step: multipleOf, ...inputProps }}
{...fieldProps}
/>
</FieldWrapper>
);
Expand Down
13 changes: 11 additions & 2 deletions app/packages/operators/src/OperatorIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@ import { useColorScheme } from "@mui/material";
import { resolveServerPath } from "./utils";

export default function OperatorIcon(props: CustomIconPropsType) {
const { pluginName, icon, lightIcon, darkIcon, _builtIn, Fallback } = props;
const {
pluginName,
icon,
lightIcon,
darkIcon,
_builtIn,
Fallback,
canExecute,
} = props;
const { mode } = useColorScheme();
const iconPath = mode === "dark" && darkIcon ? darkIcon : lightIcon || icon;

if (!iconPath) return Fallback ? <Fallback /> : null;
if (!iconPath || !canExecute) return Fallback ? <Fallback /> : null;
if (_builtIn) return <ImageIcon src={iconPath} />;
return <CustomOperatorIcon pluginName={pluginName} iconPath={iconPath} />;
}
Expand All @@ -32,6 +40,7 @@ export type CustomIconPropsType = {
darkIcon?: string;
_builtIn?: boolean;
Fallback?: React.ComponentType;
canExecute?: boolean;
};

type CustomOperatorIconPropsType = {
Expand Down
2 changes: 2 additions & 0 deletions app/packages/operators/src/OperatorPlacements.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ function ButtonPlacement(props: OperatorPlacementProps) {
const { label } = view;
const { icon, darkIcon, lightIcon, prompt = true } = view?.options || {};
const { execute } = useOperatorExecutor(uri);
const canExecute = operator?.config?.canExecute;

const showIcon =
isPrimitiveString(icon) ||
Expand All @@ -64,6 +65,7 @@ function ButtonPlacement(props: OperatorPlacementProps) {
darkIcon={darkIcon}
lightIcon={lightIcon}
Fallback={Extension}
canExecute={canExecute}
/>
);

Expand Down
4 changes: 2 additions & 2 deletions app/packages/operators/src/built-in-operators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -780,9 +780,9 @@ export function registerBuiltInOperators() {
}
}

export async function loadOperators() {
export async function loadOperators(datasetName: string) {
registerBuiltInOperators();
await loadOperatorsFromServer();
await loadOperatorsFromServer(datasetName);
}

function getLayout(layout) {
Expand Down
8 changes: 6 additions & 2 deletions app/packages/operators/src/operators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,14 @@ export function _registerBuiltInOperator(OperatorType: typeof Operator) {
localRegistry.register(operator);
}

export async function loadOperatorsFromServer() {
export async function loadOperatorsFromServer(datasetName: string) {
initializationErrors = [];
try {
const { operators, errors } = await getFetchFunction()("GET", "/operators");
const { operators, errors } = await getFetchFunction()(
"POST",
"/operators",
{ dataset_name: datasetName }
);
const operatorInstances = operators.map((d: any) =>
Operator.fromRemoteJSON(d)
);
Expand Down
8 changes: 7 additions & 1 deletion app/packages/operators/src/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,9 +389,15 @@ export function filterChoicesByQuery(query, all) {
});
}

export const availableOperatorsRefreshCount = atom({
key: "availableOperatorsRefreshCount",
default: 0,
});

export const availableOperators = selector({
key: "availableOperators",
get: () => {
get: ({ get }) => {
get(availableOperatorsRefreshCount); // triggers force refresh manually
return listLocalAndRemoteOperators().allOperators.map((operator) => {
return {
label: operator.label,
Expand Down
Loading

0 comments on commit 3d5fe39

Please sign in to comment.