aboutsummaryrefslogtreecommitdiff
path: root/src/forms.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/forms.rs')
-rw-r--r--src/forms.rs137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/forms.rs b/src/forms.rs
new file mode 100644
index 0000000..fc16d09
--- /dev/null
+++ b/src/forms.rs
@@ -0,0 +1,137 @@
+use serde::Deserialize;
+use sputnik::html_escape;
+
+use crate::{action_links, controller::Controller, get_renderer, Context, Error, Page, Response};
+
+fn render_error(message: &str) -> String {
+ format!("<div class=error>error: {}</div>", html_escape(message))
+}
+
+#[derive(Deserialize, Default)]
+pub struct EditForm {
+ pub text: String,
+ pub msg: Option<String>,
+ pub oid: Option<String>,
+}
+
+pub fn edit_text_form<'a, C: Controller>(
+ data: &EditForm,
+ error: Option<&str>,
+ controller: &'a C,
+ ctx: &'a Context,
+) -> Page<'a> {
+ let mut page = Page {
+ title: format!(
+ "{} {}",
+ if data.oid.is_some() {
+ "Editing"
+ } else {
+ "Creating"
+ },
+ ctx.path.file_name().unwrap().to_str().unwrap()
+ ),
+ header: data
+ .oid
+ .is_some()
+ .then(|| action_links("edit", controller, ctx)),
+ body: String::new(),
+ controller,
+ parts: &ctx.parts,
+ };
+ if let Some(access_info_html) = controller.access_info_html(&ctx) {
+ page.body.push_str(&access_info_html);
+ }
+ if let Some(hint_html) = controller.edit_hint_html(ctx) {
+ page.body
+ .push_str(&format!("<div class=edit-hint>{}</div>", hint_html));
+ }
+ if let Some(error) = error {
+ page.body.push_str(&render_error(error));
+ }
+ page.body.push_str(&format!(
+ "<form method=post action='?action=edit' class=edit-form>\
+ <textarea name=text autofocus autocomplete=off>{}</textarea>",
+ html_escape(&data.text)
+ ));
+ page.body
+ .push_str("<div class=buttons><button>Save</button>");
+ if let Some(oid) = &data.oid {
+ page.body.push_str(&format!(
+ "<input name=oid type=hidden value='{}'>
+ <button formaction='?action=diff'>Diff</button>",
+ oid
+ ));
+ }
+ if get_renderer(&ctx.path).is_some() {
+ page.body
+ .push_str(" <button formaction='?action=preview'>Preview</button>")
+ }
+ page.body.push_str(&format!(
+ "<input name=msg placeholder=Message value='{}' autocomplete=off></div></form>",
+ html_escape(data.msg.as_deref().unwrap_or_default())
+ ));
+
+ page.body.push_str(&format!(
+ "<script>{}</script>",
+ include_str!("static/edit_script.js")
+ ));
+ page
+}
+
+#[derive(Deserialize)]
+pub struct MoveForm {
+ pub dest: String,
+ pub msg: Option<String>,
+}
+
+pub fn move_form<C: Controller>(
+ filename: &str,
+ data: &MoveForm,
+ error: Option<&str>,
+ controller: &C,
+ ctx: &Context,
+) -> Result<Response, Error> {
+ let mut page = Page {
+ title: format!("Move {}", filename),
+ controller,
+ parts: &ctx.parts,
+ body: String::new(),
+ header: Some(action_links("move", controller, ctx)),
+ };
+
+ if let Some(error) = error {
+ page.body.push_str(&render_error(error));
+ }
+
+ page.body.push_str(&format!(
+ "<form method=post autocomplete=off>
+ <label>Destination <input name=dest value='{}' autofocus></label>
+ <label>Message <input name=msg value='{}'></label>
+ <button>Move</button>
+ </form>",
+ html_escape(&data.dest),
+ data.msg.as_ref().map(html_escape).unwrap_or_default(),
+ ));
+
+ Ok(page.into())
+}
+
+pub fn upload_form<'a, C: Controller>(
+ file_exists: bool,
+ controller: &'a C,
+ ctx: &'a Context,
+) -> Page<'a> {
+ let filename = ctx.path.file_name().unwrap().to_str().unwrap();
+ Page {
+ title: format!("Uploading {}", filename),
+ // TODO: add input for commit message
+ body: "<form action=?action=upload method=post enctype='multipart/form-data'>\
+ <input name=file type=file>\
+ <button>Upload</button>\
+ </form>"
+ .into(),
+ header: file_exists.then(|| action_links("edit", controller, &ctx)),
+ controller,
+ parts: &ctx.parts,
+ }
+}