Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ members = ["storybook", "examples/form"]
name = "vertigo-forms"
version = "0.1.0"
authors = ["Michał Pokrywka <wolfmoon@o2.pl>"]
edition = "2021"
edition = "2024"

[dependencies]
base64 = "0.22"
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ Blocks for building forms in [vertigo](https://crates.io/crates/vertigo).
[![CI](https://github.com/vertigo-web/vertigo-forms/actions/workflows/pipeline.yaml/badge.svg)](https://github.com/vertigo-web/vertigo-forms/actions/workflows/pipeline.yaml)
[![downloads](https://img.shields.io/crates/d/vertigo-forms.svg)](https://crates.io/crates/vertigo-forms)

See [Changelog](https://github.com/vertigo-web/vertigo/blob/master/CHANGES.md) for recent features.
See [Changelog](https://github.com/vertigo-web/vertigo-forms/blob/master/CHANGES.md) for recent features.

## Example

Dependencies:

```toml
vertigo = "0.7"
vertigo = "0.8"
vertigo-forms = { git = "https://github.com/vertigo-web/vertigo-forms" }
```

Expand Down
28 changes: 15 additions & 13 deletions src/drop_image_file.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use base64::{engine::general_purpose::STANDARD_NO_PAD as BASE_64, Engine as _};
use base64::{Engine as _, engine::general_purpose::STANDARD_NO_PAD as BASE_64};
use std::rc::Rc;
use vertigo::{
bind, computed_tuple, css, dom, Computed, Css, DomNode, DropFileEvent, DropFileItem, Value,
Computed, Css, DomNode, DropFileEvent, DropFileItem, Value, bind, computed_tuple, css, dom,
};

/// Box that allows to accept image files on it, connected to `Value<Option<DropFileItem>>`.
Expand All @@ -13,7 +13,8 @@ pub struct DropImageFile {

#[derive(Clone)]
pub struct DropImageFileParams {
pub callback: Option<Rc<dyn Fn(DropFileItem)>>,
/// Custom callback when new image dropped, leave empty to automatically set/unset `item`
pub callback: Option<Rc<dyn Fn(Option<DropFileItem>)>>,
pub revert_label: String,
pub cancel_label: String,
pub no_image_text: String,
Expand Down Expand Up @@ -63,14 +64,21 @@ impl DropImageFile {
);
let item_clone = self.item.clone();
let params = self.params.clone();
let callback = self.params.callback.clone();
let image_view = view_deps.render_value(move |(original, item, base64_date)| match item {
Some(item) => {
let message = format_line(&item);
let image_css = css! {"
display: flex;
flex-flow: column;
"};
let restore = bind!(item_clone, |_| item_clone.set(None));
let restore = bind!(item_clone, callback, |_| {
if let Some(callback) = &callback {
callback(None);
} else {
item_clone.set(None);
}
});
let restore_text = if original.is_some() {
&params.revert_label
} else {
Expand All @@ -97,20 +105,14 @@ impl DropImageFile {
let on_dropfile = move |event: DropFileEvent| {
for file in event.items.into_iter() {
if let Some(callback) = callback.as_deref() {
callback(file);
callback(Some(file));
} else {
item.change(|current| {
*current = Some(file);
});
item.set(Some(file));
}
}
};

let dropzone_css = self
.params
.dropzone_css
.clone()
.extend(self.params.dropzone_add_css.clone());
let dropzone_css = &self.params.dropzone_css + &self.params.dropzone_add_css;

dom! {
<div css={dropzone_css} on_dropfile={on_dropfile}>
Expand Down
103 changes: 103 additions & 0 deletions src/form/data/data_field.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use std::{collections::HashMap, rc::Rc};
use vertigo::{Computed, Context, DomNode, DropFileItem, Value};

use crate::DropImageFileParams;

use super::form_export::FieldExport;

/// Value of a field in form section.
#[derive(Clone)]
pub enum DataFieldValue {
/// Regular string field.
String(StringValue),
/// Textarea string field.
TextArea(TextAreaValue),
/// String field with options.
List(ListValue),
/// Integer (foreign key) field with labels for each integer.
Dict(DictValue),
/// Array of integers (foreign key) field with labels for each integer.
Multi(MultiValue),
/// Checkbox
Bool(BoolValue),
/// Image (bytes) field.
Image(ImageValue),
/// Custom field
Custom(CustomValue),
/// Custom component without value
StaticCustom(Rc<dyn Fn() -> DomNode>),
}

impl DataFieldValue {
pub fn export(&self, ctx: &Context) -> FieldExport {
match self {
Self::String(val) => FieldExport::String(val.value.get(ctx)),
Self::TextArea(val) => FieldExport::String(val.value.get(ctx)),
Self::List(val) => FieldExport::List(val.value.get(ctx)),
Self::Dict(val) => FieldExport::Dict(val.value.get(ctx)),
Self::Multi(val) => {
FieldExport::Multi(val.value.get(ctx).iter().map(|v| v.get(ctx)).collect())
}
Self::Bool(val) => FieldExport::Bool(val.value.get(ctx)),
Self::Image(val) => FieldExport::Image((val.original_link.clone(), val.value.get(ctx))),
Self::Custom(val) => FieldExport::String(val.value.get(ctx)),
Self::StaticCustom(_) => FieldExport::String("".to_string()),
}
}
}

#[derive(Clone)]
pub struct StringValue {
pub value: Value<String>,
pub original_value: Rc<String>,
}

#[derive(Clone)]
pub struct TextAreaValue {
pub value: Value<String>,
pub original_value: Option<Rc<String>>,
pub rows: Option<i32>,
pub cols: Option<i32>,
}

#[derive(Clone)]
pub struct ListValue {
pub value: Value<String>,
pub original_value: Option<Rc<String>>,
pub options: Computed<Vec<String>>,
}

#[derive(Clone)]
pub struct DictValue {
pub value: Value<i64>,
pub original_value: Option<Rc<i64>>,
pub options: Computed<Vec<(i64, String)>>,
}

#[derive(Clone)]
pub struct MultiValue {
pub value: Value<Vec<Value<i64>>>,
pub original_value: Rc<Vec<i64>>,
pub options: Computed<HashMap<i64, String>>,
pub add_label: Rc<String>,
}

#[derive(Clone)]
pub struct BoolValue {
pub value: Value<bool>,
pub original_value: Option<Rc<bool>>,
}

#[derive(Clone)]
pub struct ImageValue {
pub value: Value<Option<DropFileItem>>,
pub original_link: Option<Rc<String>>,
pub component_params: Option<DropImageFileParams>,
}

#[derive(Clone)]
pub struct CustomValue {
pub value: Value<String>,
pub original_value: Option<Rc<String>>,
pub render: Rc<dyn Fn() -> DomNode>,
}
Loading
Loading