language selector, but not quite workinhg yet

This commit is contained in:
lingdocs 2022-02-10 11:27:34 +04:00
parent 36bcf7277c
commit e7701f4b7d
3 changed files with 87 additions and 17 deletions

View File

@ -4,7 +4,7 @@ Easily create EPUB e-book files with proper RTL support.
This is a web app that uses [pandoc](https://pandoc.org) to create .epub files for e-books in RTL languages. Making RTL e-books can be tricky. This tries app tries to simplify the process as much as possible, so that anyone can make them. This is a web app that uses [pandoc](https://pandoc.org) to create .epub files for e-books in RTL languages. Making RTL e-books can be tricky. This tries app tries to simplify the process as much as possible, so that anyone can make them.
[Try it live - RTL EPUB Maker](https://rtl-epub-maker.lingdocs.com) ### [Try it live - RTL EPUB Maker 📚](https://rtl-epub-maker.lingdocs.com)
## Running ## Running
@ -39,7 +39,7 @@ If you are using `linux/amd64` architecture you can just run the [the docker ima
docker compose up docker compose up
``` ```
If you are using an architecture other than `linux/amd64` you will need to build your own Docker image. If you are using an architecture other than `linux/amd64` you will need to build your own docker image.
```sh ```sh
docker build . -t rtl-epub-maker docker build . -t rtl-epub-maker
@ -52,4 +52,4 @@ The app will be served on `http://localhost:3001`. Add a reverse proxy with SSL
--- ---
Code is licensed under a [MIT License](https://github.com/lingdocs/rtl-epub-maker/blob/master/LICENSE). Contributions are welcome. Code is licensed under an [MIT License](https://github.com/lingdocs/rtl-epub-maker/blob/master/LICENSE). Contributions are welcome.

View File

@ -1,5 +1,6 @@
import { ChangeEvent, useState, useRef } from "react"; import { ChangeEvent, useState, useRef } from "react";
import Select from "react-select"; import Select from "react-select";
import LanguageSelect from "./LanguageSelect";
const requiredFields = [ const requiredFields = [
"title", "title",
@ -20,8 +21,7 @@ type Option = {
label: string, label: string,
}; };
const baseSettings = { const baseSettings = {
language: "ps-AF",
dir: "rtl", dir: "rtl",
"page-progression-direction": "rtl", "page-progression-direction": "rtl",
}; };
@ -55,6 +55,21 @@ function BookInfoInput({ handleSubmit }: { handleSubmit: (info: { frontmatter: F
[name]: value, [name]: value,
})); }));
} }
function handleLanguageChange(lang: string | null) {
setState(s => {
if (!lang) {
delete s.lang;
delete s.language;
return s
}
return {
...s,
// TODO: using both, but which is proper/necessary?
lang,
language: lang,
};
});
}
function submit() { function submit() {
const cover = coverRef.current.files[0] as (File | undefined); const cover = coverRef.current.files[0] as (File | undefined);
handleSubmit({ handleSubmit({
@ -65,24 +80,24 @@ function BookInfoInput({ handleSubmit }: { handleSubmit: (info: { frontmatter: F
cover, cover,
}); });
} }
console.log(state);
console.log("will render");
return <div style={{ maxWidth: "500px" }}> return <div style={{ maxWidth: "500px" }}>
<div className="my-3"> <div className="my-3">
<label htmlFor="cover-file" className="form-label">cover image <span className="text-muted">(.jpg or .png less than 5mb)</span></label> <label htmlFor="cover-file" className="form-label">cover image <span className="text-muted">(.jpg or .png less than 5mb)</span></label>
<input multiple={false} ref={coverRef} className="form-control" type="file" id="cover-file" accept="image/jpeg,image/png"/> <input multiple={false} ref={coverRef} className="form-control" type="file" id="cover-file" accept="image/jpeg,image/png"/>
</div> </div>
{fields.map((field) => ( {fields.map((field) => (
<div key={field} className="d-flex flex-row align-items-end mb-2"> <div className="mb-2">
<div className="col-auto" style={{ width: "100%" }}> <label htmlFor={field} className="form-label d-flex flex-row align-items-center">
<label htmlFor={field} className="form-label d-flex flex-row align-items-center"> {!requiredFields.includes(field) && <span className="me-2">
{!requiredFields.includes(field) && <span className="me-2"> <button type="button" className="btn btn-sm btn-outline-secondary" onClick={() => handleRemoveField(field)}>
<button type="button" className="btn btn-sm btn-outline-secondary" onClick={() => handleRemoveField(field)}> X
X </button>
</button> </span>}
</span>} <span>{field}</span>
<span>{field}</span> </label>
</label> <input onChange={handleFieldChange} type="text" className="form-control" id={field} name={field} value={state[field]} />
<input onChange={handleFieldChange} type="text" className="form-control" id={field} name={field} value={state[field]} />
</div>
</div> </div>
))} ))}
<div className="mt-4 mb-2">add fields:</div> <div className="mt-4 mb-2">add fields:</div>
@ -97,6 +112,7 @@ function BookInfoInput({ handleSubmit }: { handleSubmit: (info: { frontmatter: F
// @ts-ignore // @ts-ignore
options={availableFieldsOptions} options={availableFieldsOptions}
/> />
<LanguageSelect value={state.lang} onChange={handleLanguageChange} />
<button onClick={submit} type="button" className="btn btn-primary my-4">Create .epub</button> <button onClick={submit} type="button" className="btn btn-primary my-4">Create .epub</button>
</div> </div>
} }

View File

@ -0,0 +1,54 @@
import Select from "react-select";
import { useState } from "react";
const languageOptions = [
{ value: "ar", label: "Arabic" },
{ value: "fa", label: "Farsi" },
{ value: "prs", label: "Dari" },
{ value: "ps", label: "Pashto" },
{ value: "ps-AF", label: "Pashto (Afghanistan) "},
{ value: "ps-PK", label: "Pashto (Pakistan) "},
{ value: "ur", label: "Urdu" },
{ value: "other", label: "Other..." },
];
function LanguageSelect({ value, onChange }: {
value: string | null,
onChange: (language: string | null) => void,
}) {
const [showingOther, setShowingOther] = useState<boolean>(false);
function handleChange(o: { value: string, label: string }) {
if (!o) {
onChange(null);
} else if (o.value === "other") {
setShowingOther(true);
onChange(null);
} else {
if (showingOther) setShowingOther(false);
onChange(o.value);
}
}
return <div>
<div className="mt-4 mb-2">language:</div>
<Select
className="basic-single"
classNamePrefix="select"
isClearable={true}
value={typeof value === "number" ? null : languageOptions.find(o => value === o.value)}
isSearchable
// @ts-ignore
onChange={handleChange}
// @ts-ignore
options={languageOptions}
/>
{showingOther && <div className="my-2">
<label htmlFor="otherLang" className="form-label d-flex flex-row align-items-center">
<span>Custom <a href="https://www.w3.org/International/articles/language-tags/" target="_blank">IETF BCP 47</a> Language Code</span>
</label>
{/* TODO: for some reason can't use value={value} with this - but it still works */}
<input onChange={(e) => onChange(e.target.value)} type="text" className="form-control" id="otherLang" />
</div>}
</div>;
}
export default LanguageSelect;