Skip to content

Commit

Permalink
Use schemas to dynamically display editPage
Browse files Browse the repository at this point in the history
Update routes with correct names
  • Loading branch information
BenjaminCharmes committed Oct 21, 2024
1 parent 21ed72d commit ffc68d5
Show file tree
Hide file tree
Showing 4 changed files with 594 additions and 2 deletions.
38 changes: 37 additions & 1 deletion pydatalab/src/pydatalab/routes/v0_1/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from pydatalab import __version__
from pydatalab.blocks import BLOCK_TYPES
from pydatalab.config import CONFIG, FEATURE_FLAGS, FeatureFlags
from pydatalab.models import Person
from pydatalab.models import Collection, Equipment, Person, Sample, StartingMaterial
from pydatalab.mongo import flask_mongo

from ._version import __api_version__
Expand Down Expand Up @@ -143,3 +143,39 @@ def list_block_types():
).json()
)
)


@INFO.route("/info/types", methods=["GET"])
def list_supported_types_schemas():
"""Returns a dictionary of supported item types and their schemas."""
schemas = {
"samples": Sample.schema(),
"collections": Collection.schema(),
"starting_materials": StartingMaterial.schema(),
"equipment": Equipment.schema(),
}
return jsonify(schemas)


@INFO.route("/info/types/samples", methods=["GET"])
def get_sample_schema():
"""Returns the JSON schema for the Sample type."""
return jsonify(Sample.schema())


@INFO.route("/info/types/collections", methods=["GET"])
def get_collection_schema():
"""Returns the JSON schema for the Collection type."""
return jsonify(Collection.schema())


@INFO.route("/info/types/starting_materials", methods=["GET"])
def get_starting_material_schema():
"""Returns the JSON StartingMaterial for the Sample type."""
return jsonify(StartingMaterial.schema())


@INFO.route("/info/types/equipment", methods=["GET"])
def get_equipment_schema():
"""Returns the JSON schema for the Equipment type."""
return jsonify(Equipment.schema())
163 changes: 163 additions & 0 deletions webapp/src/components/DynamicSchema.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
<template>
<div v-if="schema?.properties && data">
<div v-for="(field, index) in Object.keys(schema.properties)" :key="index">
<label v-if="field != 'relationships'" :for="field">{{
schema.properties[field].title
}}</label>
<component
:is="getComponentType(field)"
:key="index"
:value="data[field]"
:placeholder="field.title"
v-bind="getComponentProps(field)"
@input="(value) => updateData(field.name, value)"
/>
</div>
</div>
</template>
<script>
import { getSchema } from "@/server_fetch_utils";
import FormattedItemName from "@/components/FormattedItemName";
import FormattedRefcode from "@/components/FormattedRefcode";
import Creators from "@/components/Creators";
import ToggleableCollectionFormGroup from "@/components/ToggleableCollectionFormGroup";
import TinyMceInline from "@/components/TinyMceInline";
import ItemRelationshipVisualization from "@/components/ItemRelationshipVisualization";
export default {
props: {
modelValue: {
type: Object,
required: true,
},
},
emits: ["update:modelValue"],
data() {
return {
schema: null,
};
},
computed: {
data() {
return this.modelValue;
},
},
async mounted() {
this.schema = await getSchema(this.data?.type);
console.log("#%#%%#%#%#%#%#%#%#");
console.log(this.schema);
console.log("#%#%%#%#%#%#%#%#%#");
},
methods: {
getComponentType(field) {
const fieldSchema = this.schema.properties[field];

switch (field) {
case "item_id":
return FormattedItemName;
case "refcode":
return FormattedRefcode;
case "creators":
return Creators;
case "collections":
return ToggleableCollectionFormGroup;
case "description":
return TinyMceInline;
case "relationships":
return ItemRelationshipVisualization;

case fieldSchema.type:
if (["date", "string", "integer", "object"].includes(fieldSchema.type)) {
return "input";
}
if (fieldSchema.type === "array") {
return "textarea";
}

return "input";
default:
return "input";
}
},

getComponentProps(field) {
const fieldSchema = this.schema.properties[field];

if (field === "item_id") {
return {
itemType: this.data.type,
item_id: this.data.item_id,
enableClick: true,
};
}
if (field === "refcode") {
return {
refcode: this.data.refcode,
};
}
if (field === "creators") {
return {
creators: this.data.creators,
};
}
if (field === "collections") {
return {
modelValue: this.data.collections,
};
}
if (field === "description") {
return {
modelValue: this.data.description,
};
}
if (field === "relationships") {
return {
item_id: this.data.item_id,
};
}

if (fieldSchema.type === "date") {
return {
value: this.data[field],
type: "datetime-local",
class: "form-control",
};
}
if (fieldSchema.type === "string") {
return {
value: this.data[field],
type: "text",
class: "form-control",
};
}
if (fieldSchema.type === "integer") {
return {
value: this.data[field],
type: "number",
class: "form-control",
};
}
if (fieldSchema.type === "array") {
return {
value: this.data[field].join(", "),
class: "form-control",
};
}
if (fieldSchema.type === "object") {
return {
value: JSON.stringify(this.data[field]),
class: "form-control",
};
}

return { readonly: true, disabled: true };
},
updateData(fieldName, value) {
const newData = { ...this.data, [fieldName]: value };
this.$emit("update:modelValue", newData);
},
},
};
</script>
2 changes: 1 addition & 1 deletion webapp/src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Equipment from "../views/Equipment.vue";
import StartingMaterials from "../views/StartingMaterials.vue";
import Collections from "@/views/Collections.vue";
import NotFound from "../views/NotFound.vue";
import EditPage from "../views/EditPage.vue";
import EditPage from "../views/EditPageV2.vue";
import CollectionPage from "../views/CollectionPage.vue";
import ExampleGraph from "@/views/ExampleGraph.vue";
import ItemGraphPage from "@/views/ItemGraphPage.vue";
Expand Down
Loading

0 comments on commit ffc68d5

Please sign in to comment.