diff --git a/src/app/components/Editor.tsx b/src/app/components/Editor.tsx index 24327acf..db06e9f7 100644 --- a/src/app/components/Editor.tsx +++ b/src/app/components/Editor.tsx @@ -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(readableStream: ReadableStream) { - 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 = 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 { @@ -123,7 +90,7 @@ export default function Editor() { const [isYamlModalVisible, setYamlModalVisibility] = useState(false); const submit = handleSubmit( - async (_) => { + async () => { setYamlModalVisibility(true); }, (e) => { @@ -133,24 +100,32 @@ export default function Editor() { } ); - const loadRemoteYamlHandler = async (url: string) => { - console.log('loadRemoteYaml', url) + const setFormDataAfterImport = async (fetchData: () => Promise) => { + 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 ( @@ -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 diff --git a/src/app/components/Foot.tsx b/src/app/components/Foot.tsx index 7128f03c..68188232 100644 --- a/src/app/components/Foot.tsx +++ b/src/app/components/Foot.tsx @@ -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; @@ -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(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) => { 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) => { + const handleFileChange = (e: React.ChangeEvent) => { + console.log('handleFileChange', e.target.files) + if (e.target.files) { + setFile(e.target.files[0]); + } + }; + + const handleUrlChange = (event: ChangeEvent) => { console.log(event); const { value } = event.target; setUrl(value); @@ -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} />