Skip to content

Commit

Permalink
add an Inline Submit Image Input component and its stories file
Browse files Browse the repository at this point in the history
  • Loading branch information
andre-code committed Sep 21, 2023
1 parent 5f22354 commit 8c56b21
Show file tree
Hide file tree
Showing 4 changed files with 316 additions and 119 deletions.
6 changes: 3 additions & 3 deletions client/src/components/form-field/FormGeneratorImageInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ function ImagePreview({
});
}, [originalImageInput]);

const selectedIndex = value.selected;
const selectedIndex = value?.selected ?? -1;
const imageSize = { width: 133, height: 77, borderRadius: "8px" };
const imageStyle = { ...imageSize, objectFit: "cover" };
const imagePreviewStyle = {
Expand Down Expand Up @@ -418,8 +418,8 @@ function ImageInput(props) {
} = props;
const [sizeAlert, setSizeAlert] = useState(null);
const [originalImageInput, setOriginalImageInput] = useState(null);
const options = value.options;
const selectedIndex = value.selected;
const options = value?.options ?? [];
const selectedIndex = value?.selected ?? -1;
const selected =
selectedIndex > -1
? options[selectedIndex]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*!
* Copyright 2023 - Swiss Data Science Center (SDSC)
* A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
* Eidgenössische Technische Hochschule Zürich (ETHZ).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Meta, StoryObj } from "@storybook/react";

import InlineSubmitImageInput from "./InlineSubmitImageInput";

const meta: Meta = {
title: "components/Forms/InlineSubmitImageInput",
component: InlineSubmitImageInput,
parameters: {
docs: {
description: {
component: `Inline Submit Image Input combines an input field with a submit button inline used in user interfaces
to allow users to quickly submit an image without navigating to a different page or section of the application.`,
},
},
},
args: {
alert: "",
classNameSubmitButton: "updateProjectSettings",
currentImageName: "",
doneText: "Updated",
includeRequiredLabel: true,
imageMaxSize: 1024000,
isDisabled: false,
isDone: false,
isSubmitting: false,
label: "Project Image",
name: "projectImage",
onCancel: () => {
return "";
},
onChange: () => {
return "";
},
onSubmit: () => {
return "";
},
pristine: false,
readOnly: false,
submitButtonId: "project-button-id",
value: null,
},
};
export default meta;

type Story = StoryObj<typeof InlineSubmitImageInput>;

export const Default: Story = {
render: (_args) => {
return (
<div className="form-rk-green">
<InlineSubmitImageInput {..._args} />
</div>
);
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
/*!
* Copyright 2023 - Swiss Data Science Center (SDSC)
* A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
* Eidgenössische Technische Hochschule Zürich (ETHZ).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { Button } from "reactstrap";
import { ChangeEvent, useState } from "react";
import { InlineSubmitButton } from "../buttons/Button";
import ImageInput, {
ImageFieldPropertyName as Prop,
ImageInputMode,
} from "../form-field/FormGeneratorImageInput";

interface OptionType {
[key: string]: string | File; // You can specify the type you expect for the properties here
}
interface ImageValue {
selected: number;
options: OptionType[];
}
interface InputSubmitButtonsProps {
currentImageName: string;
doneText: string;
isDone: boolean; //updated
onCancel: () => void;
onImageChange: (image: File) => void;
pristine: boolean;
readOnly: boolean;
isSubmitting: boolean;
submitId: string;
textPristine: string;
value: ImageValue;
}
function InputSubmitButtons({
currentImageName,
doneText,
isDone,
onCancel,
onImageChange,
pristine,
readOnly,
isSubmitting,
submitId,
textPristine,
value,
}: InputSubmitButtonsProps) {
if (readOnly || !value) return null;
// No options, no submit button
if (value?.options?.length < 1) return null;
// The current image is selected, no submit button
if (
value.selected > -1 &&
value.options[value.selected][Prop.NAME] === currentImageName
)
return null;

const selectedFile = value.options[value.selected][Prop.FILE] as File;
const submit = () => {
onImageChange(selectedFile);
};

const submitButton = (
<InlineSubmitButton
className=""
doneText={doneText}
id={submitId}
submittingText="Updating"
text="Submit"
isDone={isDone}
isReadOnly={readOnly || pristine}
isSubmitting={isSubmitting}
onSubmit={submit}
pristine={pristine}
tooltipPristine={textPristine}
isMainButton={true}
/>
);

return (
<div className="d-flex flex-row-reverse">
<div>{submitButton}</div>
{!isDone ? (
<div>
<Button
disabled={isSubmitting}
className="btn-outline-rk-green"
onClick={() => {
onCancel();
}}
>
Cancel
</Button>
</div>
) : null}
</div>
);
}

interface InlineImageInputProps {
alert: string | null;
currentImageName: string;
doneText: string;
imageFormat?: string;
imageMaxSize: number;
includeRequiredLabel: boolean;
isDisabled: boolean;
isDone: boolean;
isSubmitting: boolean;
label: string;
name: string;
onCancel: () => void;
onChange: (value: string) => void;
onSubmit: (value: File) => void;
readOnly: boolean;
submitButtonId: string;
initialValue: ImageValue;
}
function InlineSubmitImageInput({
alert,
currentImageName,
doneText,
includeRequiredLabel,
imageMaxSize,
imageFormat,
isDisabled,
isDone,
isSubmitting,
label,
name,
onCancel,
onChange,
onSubmit,
readOnly,
submitButtonId,
initialValue,
}: InlineImageInputProps) {
const [value, setValue] = useState(initialValue);
const [pristine, setPristine] = useState(true);

const cancelValue = () => {
setValue(initialValue);
if (onCancel) onCancel();
};

const changeValue = (value: string) => {
setValue(value as unknown as ImageValue);
setPristine(false);
if (onChange) onChange(value);
};
const defaultFormat = "image/png, image/jpeg, image/gif, image/tiff";

return (
<div>
<ImageInput
name={name}
label={label}
value={value}
help={null}
maxSize={imageMaxSize}
alert={alert}
modes={[ImageInputMode.FILE]}
format={imageFormat ?? defaultFormat}
disabled={isDisabled}
submitting={isSubmitting}
setInputs={(e: ChangeEvent<HTMLInputElement>) => {
changeValue(e.target.value);
}}
includeRequiredLabel={includeRequiredLabel}
/>
<InputSubmitButtons
currentImageName={currentImageName}
doneText={doneText}
submitId={submitButtonId}
textPristine={""}
value={value}
onCancel={cancelValue}
readOnly={readOnly || pristine} //settingsReadOnly
isDone={isDone}
isSubmitting={isSubmitting}
pristine={pristine}
onImageChange={(f) => onSubmit(f)}
/>
</div>
);
}

export default InlineSubmitImageInput;
Loading

0 comments on commit 8c56b21

Please sign in to comment.