diff --git a/app/web/src/components/AttributesPanel/TreeFormItem.vue b/app/web/src/components/AttributesPanel/TreeFormItem.vue
index b0d11c6600..49061efd83 100644
--- a/app/web/src/components/AttributesPanel/TreeFormItem.vue
+++ b/app/web/src/components/AttributesPanel/TreeFormItem.vue
@@ -401,7 +401,10 @@
name="nested-arrow-right"
size="none"
/>
+
@@ -944,6 +947,7 @@ export type TreeFormProp = {
widgetKind: PropertyEditorPropWidgetKind;
isHidden: boolean;
isReadonly: boolean;
+ documentation?: string;
};
export type TreeFormData = {
@@ -1058,6 +1062,7 @@ const widgetOptions = computed(
() => (fullPropDef.value.widgetKind as any).options,
);
const propName = computed(() => fullPropDef.value.name);
+const propDocumentation = computed(() => fullPropDef.value.documentation);
const propLabelParts = computed(() => {
if (isChildOfArray.value)
return [`${propName.value}[${props.treeDef.arrayIndex}]`];
diff --git a/lib/dal/src/pkg/import.rs b/lib/dal/src/pkg/import.rs
index ae51c57228..0a58d28905 100644
--- a/lib/dal/src/pkg/import.rs
+++ b/lib/dal/src/pkg/import.rs
@@ -1628,6 +1628,7 @@ async fn create_dal_prop(
kind,
data.hidden,
data.doc_link.as_ref().map(|l| l.to_string()),
+ data.documentation.clone(),
Some(((&data.widget_kind).into(), data.widget_options.to_owned())),
data.validation_format.clone(),
parent_info.prop_id,
@@ -1640,6 +1641,7 @@ async fn create_dal_prop(
kind,
data.hidden,
data.doc_link.as_ref().map(|l| l.to_string()),
+ data.documentation.clone(),
Some(((&data.widget_kind).into(), data.widget_options.to_owned())),
data.validation_format.clone(),
schema_variant_id,
diff --git a/lib/dal/src/prop.rs b/lib/dal/src/prop.rs
index d96af9e289..359a84b0e4 100644
--- a/lib/dal/src/prop.rs
+++ b/lib/dal/src/prop.rs
@@ -404,6 +404,7 @@ impl Prop {
None,
None,
None,
+ None,
parent_prop_id,
)
.await
@@ -420,6 +421,7 @@ impl Prop {
kind: PropKind,
hidden: bool,
doc_link: Option,
+ documentation: Option,
widget_kind_and_options: Option<(WidgetKind, Option)>,
validation_format: Option,
parent_prop_id: PropId,
@@ -430,6 +432,7 @@ impl Prop {
kind,
hidden,
doc_link,
+ documentation,
widget_kind_and_options,
validation_format,
)
@@ -449,6 +452,7 @@ impl Prop {
kind: PropKind,
hidden: bool,
doc_link: Option,
+ documentation: Option,
widget_kind_and_options: Option<(WidgetKind, Option)>,
validation_format: Option,
schema_variant_id: SchemaVariantId,
@@ -459,6 +463,7 @@ impl Prop {
kind,
hidden,
doc_link,
+ documentation,
widget_kind_and_options,
validation_format,
)
@@ -481,12 +486,14 @@ impl Prop {
///
/// A corresponding [`AttributePrototype`] and [`AttributeValue`] will be created when the
/// provided [`SchemaVariant`] is [`finalized`](SchemaVariant::finalize).
+ #[allow(clippy::too_many_arguments)]
async fn new_inner(
ctx: &DalContext,
name: impl Into,
kind: PropKind,
hidden: bool,
doc_link: Option,
+ documentation: Option,
widget_kind_and_options: Option<(WidgetKind, Option)>,
validation_format: Option,
) -> PropResult {
@@ -513,7 +520,7 @@ impl Prop {
widget_kind,
widget_options,
doc_link,
- documentation: None,
+ documentation,
hidden,
refers_to_prop_id: None,
diff_func_id: None,
diff --git a/lib/dal/src/schema/variant/root_prop.rs b/lib/dal/src/schema/variant/root_prop.rs
index eaa8ec1364..bbb0124abd 100644
--- a/lib/dal/src/schema/variant/root_prop.rs
+++ b/lib/dal/src/schema/variant/root_prop.rs
@@ -123,6 +123,7 @@ impl RootProp {
None,
None,
None,
+ None,
schema_variant_id,
)
.await?;
@@ -154,6 +155,7 @@ impl RootProp {
None,
None,
None,
+ None,
root_prop_id,
)
.await?;
@@ -191,6 +193,7 @@ impl RootProp {
None,
None,
None,
+ None,
root_prop_id,
)
.await?;
@@ -203,6 +206,7 @@ impl RootProp {
None,
None,
None,
+ None,
leaf_prop.id(),
)
.await?;
@@ -231,6 +235,7 @@ impl RootProp {
PropKind::String,
false,
None,
+ None,
Some((
WidgetKind::Select,
Some(serde_json::json!([
@@ -264,6 +269,7 @@ impl RootProp {
PropKind::String,
false,
None,
+ None,
Some((WidgetKind::Color, None)),
None,
si_prop.id(),
@@ -287,6 +293,7 @@ impl RootProp {
None,
None,
None,
+ None,
root_prop_id,
)
.await?;
@@ -300,6 +307,7 @@ impl RootProp {
None,
None,
None,
+ None,
resource_prop.id(),
)
.await?;
@@ -313,6 +321,7 @@ impl RootProp {
None,
None,
None,
+ None,
resource_prop.id(),
)
.await?;
@@ -326,6 +335,7 @@ impl RootProp {
None,
None,
None,
+ None,
resource_prop.id(),
)
.await?;
@@ -339,6 +349,7 @@ impl RootProp {
None,
None,
None,
+ None,
resource_prop.id(),
)
.await?;
@@ -358,6 +369,7 @@ impl RootProp {
None,
None,
None,
+ None,
root_prop_id,
)
.await?;
@@ -377,6 +389,7 @@ impl RootProp {
None,
None,
None,
+ None,
code_map_item_prop_id,
)
.await?;
@@ -389,6 +402,7 @@ impl RootProp {
None,
None,
None,
+ None,
code_map_item_prop_id,
)
.await?;
@@ -411,6 +425,7 @@ impl RootProp {
None,
None,
None,
+ None,
qualification_map_item_prop_id,
)
.await?;
@@ -423,6 +438,7 @@ impl RootProp {
None,
None,
None,
+ None,
qualification_map_item_prop_id,
)
.await?;
diff --git a/lib/dal/tests/integration_test/prop.rs b/lib/dal/tests/integration_test/prop.rs
index 7d3ee57e2a..574d695689 100644
--- a/lib/dal/tests/integration_test/prop.rs
+++ b/lib/dal/tests/integration_test/prop.rs
@@ -1,5 +1,9 @@
-use dal::{prop::PropPath, DalContext, Prop, Schema, SchemaVariant};
-use dal_test::test;
+use dal::{
+ prop::PropPath, property_editor::schema::PropertyEditorSchema,
+ schema::variant::authoring::VariantAuthoringClient, ComponentType, DalContext, Prop, Schema,
+ SchemaVariant,
+};
+use dal_test::{helpers::ChangeSetTestHelpers, test};
use pretty_assertions_sorted::assert_eq;
#[test]
@@ -152,3 +156,196 @@ async fn ordered_child_props(ctx: &DalContext) {
ordered_child_prop_names // actual
);
}
+
+#[test]
+async fn prop_documentation(ctx: &mut DalContext) {
+ let name = "Toto Wolff";
+ let description = None;
+ let link = None;
+ let category = "Mercedes AMG Petronas";
+ let color = "#00A19B";
+
+ // Create an asset with a corresponding asset func. After that, commit.
+ let schema_variant_id = {
+ let schema_variant = VariantAuthoringClient::create_schema_and_variant(
+ ctx,
+ name,
+ description.clone(),
+ link.clone(),
+ category,
+ color,
+ )
+ .await
+ .expect("unable to create schema and variant");
+ schema_variant.id()
+ };
+ let asset_func = "function main() {
+ const asset = new AssetBuilder();
+
+ const alpha_source_prop = new PropBuilder()
+ .setName(\"alpha_source_prop\")
+ .setKind(\"string\")
+ .setWidget(new PropWidgetDefinitionBuilder().setKind(\"text\").build())
+ .build();
+ asset.addProp(alpha_source_prop);
+
+ const alpha_destination_prop = new PropBuilder()
+ .setName(\"alpha_destination_prop\")
+ .setKind(\"string\")
+ .setWidget(new PropWidgetDefinitionBuilder().setKind(\"text\").build())
+ .build();
+ asset.addProp(alpha_destination_prop);
+
+ const beta_source_prop = new PropBuilder()
+ .setName(\"beta_source_prop\")
+ .setKind(\"string\")
+ .setDocumentation(\"sweet docs yo\")
+ .setWidget(new PropWidgetDefinitionBuilder().setKind(\"text\").build())
+ .build();
+ asset.addProp(beta_source_prop);
+
+ const beta_destination_output_socket = new SocketDefinitionBuilder()
+ .setName(\"beta_destination_output_socket\")
+ .setArity(\"one\")
+ .build();
+ asset.addOutputSocket(beta_destination_output_socket);
+
+ return asset.build();
+ }";
+ VariantAuthoringClient::save_variant_content(
+ ctx,
+ schema_variant_id,
+ name,
+ name,
+ category,
+ description.clone(),
+ link.clone(),
+ color,
+ ComponentType::Component,
+ Some(asset_func),
+ )
+ .await
+ .expect("could not save content");
+ ChangeSetTestHelpers::commit_and_update_snapshot_to_visibility(ctx)
+ .await
+ .expect("could not commit");
+
+ // Once it's all ready, regenerate and commit.
+ let schema_variant_id = VariantAuthoringClient::regenerate_variant(ctx, schema_variant_id)
+ .await
+ .expect("could not regenerate variant");
+ ChangeSetTestHelpers::commit_and_update_snapshot_to_visibility(ctx)
+ .await
+ .expect("could not commit");
+
+ // Assemble property editor schema and ensure Prop Documentation is there.
+ let property_editor_schema = PropertyEditorSchema::assemble(ctx, schema_variant_id)
+ .await
+ .expect("could not assemble property editor schema");
+
+ let prop = property_editor_schema
+ .props
+ .values()
+ .find(|schema| schema.name == "beta_source_prop")
+ .expect("could not find prop");
+
+ assert_eq!(
+ prop.documentation.as_ref().expect("has documentation"),
+ "sweet docs yo"
+ );
+
+ // now let's add documentation for the other prop, regenerate, and make sure everything works
+
+ let asset_func = "function main() {
+ const asset = new AssetBuilder();
+
+ const alpha_source_prop = new PropBuilder()
+ .setName(\"alpha_source_prop\")
+ .setKind(\"string\")
+ .setWidget(new PropWidgetDefinitionBuilder().setKind(\"text\").build())
+ .build();
+ asset.addProp(alpha_source_prop);
+
+ const alpha_destination_prop = new PropBuilder()
+ .setName(\"alpha_destination_prop\")
+ .setKind(\"string\")
+ .setDocumentation(\"more cool docs!\")
+ .setWidget(new PropWidgetDefinitionBuilder().setKind(\"text\").build())
+ .build();
+ asset.addProp(alpha_destination_prop);
+
+ const beta_source_prop = new PropBuilder()
+ .setName(\"beta_source_prop\")
+ .setKind(\"string\")
+ .setDocumentation(\"sweet docs yo\")
+ .setWidget(new PropWidgetDefinitionBuilder().setKind(\"text\").build())
+ .build();
+ asset.addProp(beta_source_prop);
+
+ const beta_destination_output_socket = new SocketDefinitionBuilder()
+ .setName(\"beta_destination_output_socket\")
+ .setArity(\"one\")
+ .build();
+ asset.addOutputSocket(beta_destination_output_socket);
+
+ return asset.build();
+ }";
+ VariantAuthoringClient::save_variant_content(
+ ctx,
+ schema_variant_id,
+ name,
+ name,
+ category,
+ description,
+ link,
+ color,
+ ComponentType::Component,
+ Some(asset_func),
+ )
+ .await
+ .expect("could not save content");
+ ChangeSetTestHelpers::commit_and_update_snapshot_to_visibility(ctx)
+ .await
+ .expect("could not commit");
+
+ // Once it's all ready, regenerate and commit.
+ let schema_variant_id = VariantAuthoringClient::regenerate_variant(ctx, schema_variant_id)
+ .await
+ .expect("could not regenerate variant");
+ ChangeSetTestHelpers::commit_and_update_snapshot_to_visibility(ctx)
+ .await
+ .expect("could not commit");
+
+ // Assemble property editor schema and ensure both Prop Documentation is there.
+ let property_editor_schema = PropertyEditorSchema::assemble(ctx, schema_variant_id)
+ .await
+ .expect("could not assemble property editor schema");
+
+ let first_prop = property_editor_schema
+ .props
+ .values()
+ .find(|schema| schema.name == "beta_source_prop")
+ .expect("could not find prop");
+
+ assert_eq!(
+ first_prop
+ .documentation
+ .as_ref()
+ .expect("has documentation"),
+ "sweet docs yo"
+ );
+
+ let second_prop = property_editor_schema
+ .props
+ .values()
+ .find(|schema| schema.name == "alpha_destination_prop")
+ .expect("could not find prop");
+
+ assert_eq!(
+ second_prop
+ .documentation
+ .as_ref()
+ .expect("has documentation"),
+ "more cool docs!"
+ );
+}