Skip to content

Commit

Permalink
feat: import from file
Browse files Browse the repository at this point in the history
  • Loading branch information
valeriocomo committed Nov 12, 2024
1 parent fdbf36d commit 5a021e8
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 69 deletions.
76 changes: 26 additions & 50 deletions src/app/components/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,43 +35,10 @@ import EditorContractors from "./EditorContractors";
import linter from "../linter";

import useFormPersist from "react-hook-form-persist";
import yaml from 'js-yaml'


async function readStreamAsText<T extends ArrayBuffer>(readableStream: ReadableStream<T>) {
const reader = readableStream.getReader();
let result = '';
const decoder = new TextDecoder();

while (true) {
const { done, value } = await reader.read();
if (done) break;
result += decoder.decode(value, { stream: true });
}

result += decoder.decode(); // Finalize decoding
return result;
}

const serializeYml = (yamlString: string) => {
if (!yamlString) {
throw new Error('serializeYml: yamlString is a falsy value')
}
try {
return yaml.load(yamlString)
} catch {
throw new Error('serializeYml: error on load')
}
}
import yamlSerializer from "../yaml-serializer";

const resolver: Resolver<PublicCode> = async (values) => {
const res = await validator(JSON.stringify(values), "main");
// loadWasm()
// .catch((e) => console.error(`Failed to load Wasm: ${e}`))
// .then((res) => {
// console.log("loadWasm OK");
// return res;
// });

if (res.errors.length === 0)
return {
Expand Down Expand Up @@ -123,7 +90,7 @@ export default function Editor() {
const [isYamlModalVisible, setYamlModalVisibility] = useState(false);

const submit = handleSubmit(
async (_) => {
async () => {
setYamlModalVisibility(true);
},
(e) => {
Expand All @@ -133,24 +100,32 @@ export default function Editor() {
}
);

const loadRemoteYamlHandler = async (url: string) => {
console.log('loadRemoteYaml', url)
const setFormDataAfterImport = async (fetchData: () => Promise<PublicCode | null>) => {
const publicCode = await fetchData();

const publicCode = await fetch(url)
.then(res => res.body)
.then(res => res ? readStreamAsText(res) : '')
.then(res => serializeYml(res) as PublicCode)
.then(res => {
console.log(res)
return res;
})
if (publicCode) {
setImportedValue(publicCode)
Object.keys(publicCode).forEach((value) => {
const key = value as keyof PublicCode
setValue(key as keyof PublicCode, publicCode[key as keyof PublicCode])
});
}
}

setImportedValue(publicCode)
const loadFileYamlHandler = async (file: File) => {
console.log('loadFileYamlHandler', file)
const fetchDataFn = () => yamlSerializer(file.stream());

Object.keys(publicCode).forEach((value) => {
const key = value as keyof PublicCode
setValue(key as keyof PublicCode, publicCode[key as keyof PublicCode])
});
await setFormDataAfterImport(fetchDataFn);
}

const loadRemoteYamlHandler = async (url: string) => {
console.log('loadRemoteYaml', url)
const fetchDataFn = () => fetch(url)
.then(res => res.body)
.then(res => res && yamlSerializer(res));

await setFormDataAfterImport(fetchDataFn)
}

return (
Expand Down Expand Up @@ -315,6 +290,7 @@ export default function Editor() {
reset={() => reset()}
submit={() => undefined}
loadRemoteYaml={(url) => loadRemoteYamlHandler(url)}
loadFileYaml={(file) => loadFileYamlHandler(file)}
trigger={() => submit()}
languages={languages}
yamlLoaded
Expand Down
71 changes: 55 additions & 16 deletions src/app/components/Foot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import UploadModal from "./UploadModal";
interface Props {
submit: () => void;
loadRemoteYaml: (url: string) => void;
loadFileYaml: (file: File) => void;
trigger: () => void;
reset: () => void;
languages: Array<string>;
Expand All @@ -20,31 +21,63 @@ export const Footer = (props: Props): JSX.Element => {
const [uploadOpen, setUploadOpen] = useState(false);
const [isModalVisible, setModalVisibility] = useState(false);
const [url, setUrl] = useState("");
//https://raw.githubusercontent.com/italia/design-angular-kit/refs/heads/main/publiccode.yml
const [file, setFile] = useState<File | null>(null);
const [submitType, setSubmitType] = useState<'file' | 'url' | undefined>(undefined)


//https://raw.githubusercontent.com/italia/design-angular-kit/refs/heads/main/publiccode.yml
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
console.log('handleSubmit', event)
const {
[0]: { value },
} = event.target as typeof event.target & {
[0]: { value?: string };
};
console.log(value)
if (!value || !validator.isURL(value)) {
notify(t("editor.notvalidurl"), { state: "error" });

const submitFormId = (event.nativeEvent.target as HTMLFormElement).id

if (!['file', 'url'].includes(submitFormId)) {
return;
}
const submitType = submitFormId === 'file' ? 'file' : 'url';

setSubmitType(submitType)

const ext = value.split(/[. ]+/).pop();
if (ext != "yml" && ext != "yaml") {
notify(t("editor.filenotsupported"), { state: "error" });
return;
if (submitType === 'url') {
const {
[0]: { value },
} = event.target as typeof event.target & {
[0]: { value?: string };
};
console.log(value)
if (!value || !validator.isURL(value)) {
notify(t("editor.notvalidurl"), { state: "error" });
return;
}

const ext = value.split(/[. ]+/).pop();
if (ext != "yml" && ext != "yaml") {
notify(t("editor.filenotsupported"), { state: "error" });
return;
}
}

if (submitType === 'file') {
//check application type
const isNotApplicationTypeYaml = file?.type !== 'application/yaml';
if(isNotApplicationTypeYaml) {
notify(t("editor.filenotsupported"), { state: "error" });
return;
}
}

setModalVisibility(true);
};

const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
console.log('handleFileChange', e.target.files)
if (e.target.files) {
setFile(e.target.files[0]);
}
};

const handleUrlChange = (event: ChangeEvent<HTMLInputElement>) => {
console.log(event);
const { value } = event.target;
setUrl(value);
Expand All @@ -68,7 +101,8 @@ export const Footer = (props: Props): JSX.Element => {
isOpen={uploadOpen}
toggle={() => setUploadOpen(!uploadOpen)}
url={url}
onUrlChange={handleChange}
onUrlChange={handleUrlChange}
onFileChange={handleFileChange}
onSubmit={handleSubmit}
/>
<Button color="light" onClick={() => setUploadOpen(!uploadOpen)}>
Expand All @@ -89,7 +123,12 @@ export const Footer = (props: Props): JSX.Element => {
submit={() => {
setModalVisibility(false);
setUploadOpen(false);
props.loadRemoteYaml(url);
if (submitType === 'url') {
props.loadRemoteYaml(url);
}
if (submitType === 'file' && file) {
props.loadFileYaml(file)
}
}}
/>
</div>
Expand Down
9 changes: 6 additions & 3 deletions src/app/components/UploadModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
ModalHeader,
Row,
} from "design-react-kit";
import { MouseEventHandler, useRef } from "react";
import { ChangeEventHandler, MouseEventHandler, useRef } from "react";
import { useTranslation } from "react-i18next";
import { SAMPLE_YAML_URL } from "../contents/constants";

Expand All @@ -21,6 +21,7 @@ interface Props {
toggle: MouseEventHandler<unknown>;
url: string;
onUrlChange: InputProps["onChange"];
onFileChange: ChangeEventHandler<HTMLInputElement>;
onSubmit: FormProps["onSubmit"];
}

Expand All @@ -30,6 +31,7 @@ export default function UploadModal({
url,
onUrlChange,
onSubmit,
onFileChange
}: Props) {
const inputRef = useRef<HTMLInputElement>(null);
const { t } = useTranslation();
Expand All @@ -40,7 +42,7 @@ export default function UploadModal({
Upload an existing publiccode.yml
</ModalHeader>
<ModalBody>
<Form inline onSubmit={onSubmit}>
<Form id="file" inline onSubmit={onSubmit}>

<Row>
<p>{t("editor.browsefile")}</p>
Expand All @@ -50,6 +52,7 @@ export default function UploadModal({
innerRef={inputRef}
type="file"
accept=".yml, .yaml"
onChange={onFileChange}
/>

<Button color="primary" onClick={() => inputRef.current?.click()}>
Expand All @@ -63,7 +66,7 @@ export default function UploadModal({
<Row className="mt-3">
<p>{t("editor.pastefile")}</p>
</Row>
<Form inline onSubmit={onSubmit}>
<Form id="url" inline onSubmit={onSubmit}>
<Row>
<InputGroup>
<input
Expand Down
36 changes: 36 additions & 0 deletions src/app/yaml-serializer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import yaml from 'js-yaml'
import PublicCode from './contents/publiccode';

async function readStreamAsText<T extends ArrayBuffer>(readableStream: ReadableStream<T>) {
const reader = readableStream.getReader();
let result = '';
const decoder = new TextDecoder();

while (true) {
const { done, value } = await reader.read();
if (done) break;
result += decoder.decode(value, { stream: true });
}

result += decoder.decode(); // Finalize decoding
return result;
}

const serializeYml = (yamlString: string) => {
if (!yamlString) {
throw new Error('serializeYml: yamlString is a falsy value')
}
try {
return yaml.load(yamlString)
} catch {
throw new Error('serializeYml: error on load')
}
}

const serializeToPublicCode = async (stream: ReadableStream) => {
return await readStreamAsText(stream).then(serializeYml).then(res => { console.log(res); return res; }) as Promise<PublicCode>;
}

export default async (stream: ReadableStream) => {
return await serializeToPublicCode(stream)
}

0 comments on commit 5a021e8

Please sign in to comment.