Skip to content
Open
8 changes: 7 additions & 1 deletion gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ const read = (p) => fs.readFileSync(path.join(__dirname, p), "utf8");
* They serve as single source of truth, can be added/edited via CMS,
* and are referenced by other markdown files.
*/
const DATA_ONLY_PAGES = ["software", "dataset", "allenite", "program"];
const DATA_ONLY_PAGES = [
"software",
"dataset",
"allenite",
"program",
"resource",
];

exports.createSchemaCustomization = ({ actions, schema }) => {
const { createTypes } = actions;
Expand Down
16 changes: 16 additions & 0 deletions src/cms/cms.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
import CMS from "decap-cms-app";
import CMS from "decap-cms-app";

import AboutPagePreview from "./preview-templates/AboutPagePreview";
import IdeaPostPreview from "./preview-templates/IdeaPostPreview";
import IndexPagePreview from "./preview-templates/IndexPagePreview";
import VariableResourceUnionControl from "./widgets/VariableResourceWidget/VariableResourceUnionControl";
import copyResourceNameHandler from "./widgets/VariableResourceWidget/copyResourceNameHandler";

// Register custom widgets, with optional preview components
// and global styles.
CMS.registerWidget({
name: "resource_union",
controlComponent: VariableResourceUnionControl,
});

CMS.registerPreviewTemplate("index", IndexPagePreview);
CMS.registerPreviewTemplate("about", AboutPagePreview);
CMS.registerPreviewTemplate("idea", IdeaPostPreview);

// Decap exposes a number of lifecycle stages we can hook into and register.
CMS.registerEventListener({
name: "preSave",
handler: copyResourceNameHandler,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from "react";



import type { CmsWidgetControlProps } from "decap-cms-core";



import VariableTypeWidgetControl from "../VariableTypeWidget/VariableTypeWidgetControl";
import { VARIABLE_TYPE_RESOURCE_CONFIG } from "./constants";





/**
* Implementation of VariableTypeWidgetControl for a union of different
* resource types (software tools, datasets, etc.).
* Config defined in VARIABLE_TYPE_RESOURCE_CONFIG.
*/
const ResourceUnionControl = (props: CmsWidgetControlProps) => {
return (
<VariableTypeWidgetControl
{...props}
types={VARIABLE_TYPE_RESOURCE_CONFIG}
defaultType="softwareTool"
/>
);
};

export default ResourceUnionControl;
70 changes: 70 additions & 0 deletions src/cms/widgets/VariableResourceWidget/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { TypeConfig } from "../VariableTypeWidget/types";

const SOFTWARE_STATUS_OPTIONS = [
"Public",
"In development",
"Internal use only",
];

const DATASET_STATUS_OPTIONS = [
"Public",
"Not QCed",
"Preliminary",
"Need to request data directly",
];

// Optional: override baseFields per type,
// defaults to name, description, link.
export const VARIABLE_TYPE_RESOURCE_CONFIG: TypeConfig[] = [
{
value: "softwareTool",
label: "Software Tool",
fields: [
{
label: "README/Quickstart Link",
name: "readmeLink",
type: "input",
},
{
label: "Status",
name: "status",
type: "select",
options: SOFTWARE_STATUS_OPTIONS,
},
],
},
{
value: "dataset",
label: "Dataset",
fields: [
{
label: "Status",
name: "status",
type: "select",
options: DATASET_STATUS_OPTIONS,
},
],
},
{
value: "protocolLink",
label: "Protocol (Link)",
fields: [],
},
{
value: "protocolFile",
label: "Protocol (File)",
fields: [
{
label: "File Path",
name: "file",
type: "file",
hint: "Use Media Library to upload, then paste path here",
},
],
},
{
value: "cellLine",
label: "Cell Line",
fields: [],
},
];
41 changes: 41 additions & 0 deletions src/cms/widgets/VariableResourceWidget/copyResourceNameHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import CMS from "decap-cms-core";

// For some reason I could not import CmsEventListener as a type
// because it was resolving to the global CMS object, so this is the workaround.
type CmsEventListenerHandler = Parameters<
typeof CMS.registerEventListener
>[0]["handler"];
type CmsEventListenerHandlerArg = Parameters<CmsEventListenerHandler>[0];

/**
Certain fields are required to be top-level by the CMS, which clutters the UI
when we have a redundant field in widget. This preSave hook copies the resource.name
field to the top-level from the nested widget.
*/
Comment on lines +11 to +14

This comment was marked as resolved.

export const copyResourceNameHandler = ({
entry,
}: CmsEventListenerHandlerArg) => {
const collection = entry.get("collection");

// Only apply to resources collection
if (collection !== "resources") {
return entry.get("data");
}

const data = entry.get("data");
const resource = data.get("resourceDetails");

if (resource) {
// Copy resource.name to top-level name
const resourceName = resource.get
? resource.get("name")
: resource.name;
if (resourceName) {
return data.set("name", resourceName);
}
}

return data;
};

export default copyResourceNameHandler;
Loading