Skip to content

Commit

Permalink
merge: #2937
Browse files Browse the repository at this point in the history
2937: feat(lang-js, dal, sdf-server): Add ability to set documentation for a prop r=stack72 a=stack72

This means we can do things like:

```
 const propName = new PropBuilder()
  .setName("name")
  .setKind("string")
  .setDocumentation("This is the documentation for the prop")
  .setWidget(new PropWidgetDefinitionBuilder().setKind("text").build())
 .build();
```

And that documentation is plumbed the whole way through the pkg layer, sdf and to the frontend where we can do with it as we wish

Co-authored-by: stack72 <[email protected]>
  • Loading branch information
si-bors-ng[bot] and stack72 authored Nov 8, 2023
2 parents 0b05bef + f1ab936 commit fa0fcaf
Show file tree
Hide file tree
Showing 34 changed files with 901 additions and 14 deletions.
1 change: 1 addition & 0 deletions app/web/src/api/sdf/dal/property_editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export interface PropertyEditorProp {
docLink?: string;
isHidden: boolean;
isReadonly: boolean;
documentation?: string;
}

export interface PropertyEditorSchema {
Expand Down
1 change: 1 addition & 0 deletions app/web/src/components/PropertyEditor/WidgetTextBox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const props = defineProps<{
validation?: PropertyEditorValidation;
disabled?: boolean;
textArea?: boolean;
documentation?: string;
}>();
const emit = defineEmits<{
Expand Down
19 changes: 19 additions & 0 deletions bin/lang-js/src/asset_builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,7 @@ export interface PropDefinition {
kind: PropDefinitionKind;
docLinkRef?: string;
docLink?: string;
documentation?: string;
children?: PropDefinition[];
entry?: PropDefinition;
widget?: PropWidgetDefinition;
Expand All @@ -592,6 +593,8 @@ export interface IPropBuilder {

setDocLinkRef(ref: string): this;

setDocumentation(ref: string): this;

setDocLink(link: string): this;

addChild(child: PropDefinition): this;
Expand Down Expand Up @@ -621,6 +624,7 @@ export interface IPropBuilder {
* const propName = new PropBuilder()
* .setName("name")
* .setKind("string")
* .setDocumentation("This is the documentation for the prop")
* .setWidget(new PropWidgetDefinitionBuilder().setKind("text").build())
* .build();
*/
Expand Down Expand Up @@ -764,6 +768,21 @@ export class PropBuilder implements IPropBuilder {
return this;
}

/**
* Sets inline documentation for the prop
*
* @param {string} docs
*
* @returns this
*
* @example
* .setDocumentation("This is documentation for the prop")
*/
setDocumentation(docs: string): this {
this.prop.documentation = docs;
return this;
}

setDocLinkRef(ref: string): this {
this.prop.docLinkRef = ref;
return this;
Expand Down
64 changes: 64 additions & 0 deletions lib/dal/src/migrations/U2404__add_documentation_to_props.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
-- Add the new columns to the props table.
ALTER TABLE props ADD COLUMN documentation text;

-- The new prop creation function automatically builds the path using the parent and sets the belongs to relationship.
CREATE OR REPLACE FUNCTION prop_create_v2(
this_tenancy jsonb,
this_visibility jsonb,
this_name text,
this_kind text,
this_widget_kind text,
this_widget_options jsonb,
this_schema_variant_id ident,
this_parent_prop_id ident,
this_documentation text,
OUT object json) AS
$$
DECLARE
this_tenancy_record tenancy_record_v1;
this_visibility_record visibility_record_v1;
this_new_row props%ROWTYPE;
this_path text;
this_parent_kind text;
BEGIN
this_tenancy_record := tenancy_json_to_columns_v1(this_tenancy);
this_visibility_record := visibility_json_to_columns_v1(this_visibility);

-- Set the path according to the lineage. If there's no parent, then we know we are the root
-- prop. We also need to ensure that the provided parent is either an object, a map or an
-- array.
IF this_parent_prop_id IS NULL
THEN this_path = this_name;
ELSE
SELECT kind, path || E'\x0B' || this_name INTO STRICT this_parent_kind, this_path
FROM props_v1(this_tenancy, this_visibility) AS props
WHERE props.id = this_parent_prop_id;

IF this_parent_kind != 'object' AND this_parent_kind != 'array' AND this_parent_kind != 'map'
THEN RAISE EXCEPTION 'prop create: provided parent is not a valid kind: %', this_parent_kind;
END IF;
END IF;

-- Create and populate the row.
INSERT INTO props (tenancy_workspace_pk,
visibility_change_set_pk,
name, kind, widget_kind, widget_options, schema_variant_id, path, documentation)
VALUES (this_tenancy_record.tenancy_workspace_pk,
this_visibility_record.visibility_change_set_pk,
this_name, this_kind, this_widget_kind, this_widget_options, this_schema_variant_id, this_path, this_documentation)
RETURNING * INTO this_new_row;

-- Now that we have the row, we can set the parent prop.
IF this_parent_prop_id IS NOT NULL THEN
PERFORM set_belongs_to_v1(
'prop_belongs_to_prop',
this_tenancy,
this_visibility,
this_new_row.id,
this_parent_prop_id
);
END IF;

object := row_to_json(this_new_row);
END;
$$ LANGUAGE PLPGSQL VOLATILE;
4 changes: 4 additions & 0 deletions lib/dal/src/pkg/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,10 @@ impl PkgExporter {
builder.try_doc_link(doc_link.as_str())?;
}

if let Some(documentation) = tree_node.documentation {
builder.documentation(documentation.as_str());
}

traversal_stack.push(TraversalStackEntry {
builder,
prop_id,
Expand Down
12 changes: 7 additions & 5 deletions lib/dal/src/pkg/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ async fn import_edge(
head_component_unique_id,
edge_spec.from_socket_name().to_owned(),
edge_spec.to_socket_name().to_owned(),
))
));
}
};

Expand All @@ -277,7 +277,7 @@ async fn import_edge(
tail_component_unique_id,
edge_spec.from_socket_name().to_owned(),
edge_spec.to_socket_name().to_owned(),
))
));
}
};

Expand All @@ -293,7 +293,7 @@ async fn import_edge(
None => {
return Ok(Some(ImportEdgeSkip::MissingInputSocket(
edge_spec.to_socket_name().to_owned(),
)))
)));
}
};

Expand All @@ -309,7 +309,7 @@ async fn import_edge(
None => {
return Ok(Some(ImportEdgeSkip::MissingOutputSocket(
edge_spec.from_socket_name().to_owned(),
)))
)));
}
};

Expand Down Expand Up @@ -408,7 +408,7 @@ async fn import_component(
return Err(PkgError::ComponentMissingSchemaVariant(
variant_unique_id.to_owned(),
component_spec.name().into(),
))
));
}
}
}
Expand Down Expand Up @@ -2190,6 +2190,7 @@ async fn import_schema_variant(
None,
*schema_variant.id(),
Some(*schema_variant.find_prop(ctx, &["root"]).await?.id()),
None,
)
.await?
.id();
Expand Down Expand Up @@ -3066,6 +3067,7 @@ async fn create_dal_prop(
Some(((&data.widget_kind).into(), data.widget_options.to_owned())),
schema_variant_id,
parent_prop_id,
data.documentation.to_owned(),
)
.await
.map_err(SiPkgError::visit_prop)?;
Expand Down
7 changes: 6 additions & 1 deletion lib/dal/src/prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ pub struct Prop {
widget_options: Option<Value>,
/// A link to external documentation for working with this specific [`Prop`].
doc_link: Option<String>,
/// Embedded documentation for working with this specific [`Prop`].
documentation: Option<String>,
/// A toggle for whether or not the [`Prop`] should be visually hidden.
hidden: bool,
/// The "path" for a given [`Prop`]. It is a concatenation of [`Prop`] names based on lineage
Expand Down Expand Up @@ -297,6 +299,7 @@ impl Prop {
widget_kind_and_options: Option<(WidgetKind, Option<Value>)>,
schema_variant_id: SchemaVariantId,
parent_prop_id: Option<PropId>,
documentation: Option<String>,
) -> PropResult<Self> {
let name = name.as_ref();
let (widget_kind, widget_options) = match widget_kind_and_options {
Expand All @@ -309,7 +312,7 @@ impl Prop {
.await?
.pg()
.query_one(
"SELECT object FROM prop_create_v2($1, $2, $3, $4, $5, $6, $7, $8)",
"SELECT object FROM prop_create_v2($1, $2, $3, $4, $5, $6, $7, $8, $9)",
&[
ctx.tenancy(),
ctx.visibility(),
Expand All @@ -319,6 +322,7 @@ impl Prop {
&widget_options.as_ref(),
&schema_variant_id,
&parent_prop_id,
&documentation,
],
)
.await?;
Expand All @@ -330,6 +334,7 @@ impl Prop {
standard_model_accessor!(widget_kind, Enum(WidgetKind), PropResult);
standard_model_accessor!(widget_options, Option<Value>, PropResult);
standard_model_accessor!(doc_link, Option<String>, PropResult);
standard_model_accessor!(documentation, Option<String>, PropResult);
standard_model_accessor!(hidden, bool, PropResult);
standard_model_accessor!(refers_to_prop_id, Option<Pk(PropId)>, PropResult);
standard_model_accessor!(diff_func_id, Option<Pk(FuncId)>, PropResult);
Expand Down
5 changes: 5 additions & 0 deletions lib/dal/src/prop_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ pub struct PropTreeNode {
pub widget_kind: WidgetKind,
pub widget_options: Option<serde_json::Value>,
pub doc_link: Option<String>,
pub documentation: Option<String>,
}

impl PropTreeNode {
Expand Down Expand Up @@ -138,6 +139,9 @@ impl PropTree {
for row in rows {
let prop_json: serde_json::Value = row.try_get("object")?;
let prop: Prop = serde_json::from_value(prop_json)?;

dbg!(&prop);

if prop.hidden() && !include_hidden {
continue;
}
Expand Down Expand Up @@ -170,6 +174,7 @@ impl PropTree {
widget_kind: *prop.widget_kind(),
widget_options: prop.widget_options().cloned(),
doc_link: prop.doc_link().map(|l| l.to_owned()),
documentation: prop.documentation().map(|d| d.to_owned()),
visibility_change_set_pk,
};

Expand Down
2 changes: 2 additions & 0 deletions lib/dal/src/property_editor/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ pub struct PropertyEditorProp {
pub kind: PropertyEditorPropKind,
pub widget_kind: PropertyEditorPropWidgetKind,
pub doc_link: Option<String>,
pub documentation: Option<String>,
}

impl PropertyEditorProp {
Expand All @@ -100,6 +101,7 @@ impl PropertyEditorProp {
prop.widget_options().map(|v| v.to_owned()),
),
doc_link: prop.doc_link().map(Into::into),
documentation: prop.documentation().map(Into::into),
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions lib/dal/src/schema/variant/definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,9 @@ pub struct PropDefinition {
/// An optional documentation link for the [`Prop`](crate::Prop) to be created.
#[serde(skip_serializing_if = "Option::is_none")]
pub doc_link: Option<String>,
/// An optional set of inline documentation for the [`Prop`](crate::Prop) to be created.
#[serde(skip_serializing_if = "Option::is_none")]
pub documentation: Option<String>,
/// If our [`kind`](crate::PropKind) is [`Object`](crate::PropKind::Object), specify the
/// child definition(s).
#[serde(default)]
Expand Down Expand Up @@ -612,6 +615,9 @@ impl PropDefinition {
if let Some(doc_url) = &self.doc_link {
builder.try_doc_link(doc_url.as_str())?;
}
if let Some(docs) = &self.documentation {
builder.documentation(docs);
}
if let Some(default_value) = &self.default_value {
builder.default_value(default_value.to_owned());
}
Expand Down
Loading

0 comments on commit fa0fcaf

Please sign in to comment.