query more of the text fields in markdown and make figure component#37
query more of the text fields in markdown and make figure component#37
Conversation
✅ Deploy Preview for project-idea-board ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Pull request overview
This PR enhances the idea post template by querying and rendering additional markdown frontmatter fields that were previously not displayed, including authors, publication info, preliminary findings with figures, and next steps. A new Figure component was created to display images with captions.
Changes:
- Added type definitions for
PreliminaryFindingsandFigureto support the new data structures - Created a
FigureComponentto render images with captions in a styled card container - Updated the idea post template to display authors, publication, preliminary findings with figures, and next steps as a formatted list
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/types/index.ts | Added type exports for PreliminaryFindings and Figure |
| src/templates/idea-post.tsx | Integrated new fields into template, added Figure rendering, and updated GraphQL query |
| src/style/figure.module.css | Added styling for figure container and captions with responsive design |
| src/pages/ideas/dev-example.md | Reformatted markdown structure and updated example content |
| src/components/Figure.tsx | Created new component to render figures with GatsbyImage and captions |
| gatsby-node.js | Added schema definitions and resolvers for new frontmatter fields |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/types/index.ts
Outdated
| export type IdeasForTags = Queries.AllIdeasForTagsQuery["allMarkdownRemark"]["edges"]; | ||
|
|
||
| export type PreliminaryFindings = NonNullable<IdeaFrontmatter["preliminaryFindings"]>; | ||
| export type Figure = NonNullable<IdeaFrontmatter["preliminaryFindings"]>["figures"][number] No newline at end of file |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…eature/more-queries
…eature/more-queries
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/templates/idea-post.tsx
Outdated
| import React from "react"; | ||
| import { Helmet } from "react-helmet-async"; | ||
| import { graphql, Link, PageProps } from "gatsby"; | ||
| import { GatsbyImage, getImage } from "gatsby-plugin-image"; |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
src/templates/idea-post.tsx
Outdated
| {hasFigures && | ||
| preliminaryFindings.figures.map((figure) => { | ||
| return ( | ||
| <FigureComponent | ||
| figure={figure} | ||
| /> | ||
| ); | ||
| })} |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
src/templates/idea-post.tsx
Outdated
| {nextSteps && ( | ||
| <div className={section}> | ||
| <h2 className={sectionTitle}>Suggested next steps:</h2> | ||
| {nextSteps} | ||
| <h4 className={sectionTitle}>Suggested next steps:</h4> | ||
| <ul> | ||
| {nextSteps.map((step: string, index: number) => ( | ||
| <li key={index}>{step}</li> | ||
| ))} | ||
| </ul> | ||
| </div> | ||
| )} |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| preliminaryFindings: { | ||
| resolve: (source) => { | ||
| const raw = source.preliminaryFindings; | ||
| if (!raw || typeof raw !== "object") { | ||
| return { | ||
| summary: "", | ||
| figures: [], | ||
| }; | ||
| } | ||
| return { | ||
| summary: stringWithDefault(raw.summary, ""), | ||
| figures: resolveToArray(raw.figures), | ||
| }; | ||
| }, | ||
| }, |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
Handled this slightly differently
| type ImgWithCaption @dontInfer { | ||
| type: String! | ||
| url: String | ||
| file: File @fileByRelativePath | ||
| caption: String | ||
| } |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
src/templates/idea-post.tsx
Outdated
| caption | ||
| } | ||
| } | ||
| publication |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| types: | ||
| [ | ||
| { | ||
| label: "Image link", | ||
| name: "imageLink", | ||
| widget: "object", | ||
| fields: [ | ||
| { | ||
| label: "Figure URL", | ||
| name: "url", | ||
| widget: "url-image", | ||
| hint: "Enter a valid image URL to see a preview", | ||
| }, | ||
| { | ||
| label: "Caption", | ||
| name: "caption", | ||
| widget: "string", | ||
| required: false, | ||
| }, | ||
| ], | ||
| }, | ||
| { | ||
| label: "Image file", | ||
| name: "imageFile", | ||
| widget: "object", | ||
| fields: [ | ||
| { | ||
| label: "Figure", | ||
| name: "file", | ||
| widget: "image", | ||
| choose_url: false, | ||
| }, | ||
| { | ||
| label: "Caption", | ||
| name: "caption", | ||
| widget: "string", | ||
| required: false, | ||
| }, | ||
| ], | ||
| }, | ||
| ], |
There was a problem hiding this comment.
The default image widget is nice in the admin page, but a bit of pain when it comes time to query and use a remote URL for an image (like the one Jess added). This sets us up to use our custom url-image widget and preview.
| import React from "react"; | ||
|
|
||
| // Custom widget for URL-only image input with preview | ||
| export const UrlImageControl = ({ value, onChange, forID, classNameWrapper }) => { | ||
| return React.createElement( | ||
| "div", | ||
| { className: classNameWrapper }, | ||
| React.createElement("input", { | ||
| id: forID, | ||
| type: "text", | ||
| value: value || "", | ||
| onChange: (e) => onChange(e.target.value), | ||
| placeholder: "https://example.com/image.png", | ||
| style: { width: "100%" }, | ||
| }), | ||
| value && | ||
| React.createElement("img", { | ||
| src: value, | ||
| alt: "Preview", | ||
| style: { display: "block", marginTop: "12px", maxWidth: "100%", maxHeight: "200px" }, | ||
| }) | ||
| ); | ||
| }; | ||
|
|
||
| export const UrlImagePreview = ({ value }) => | ||
| value ? React.createElement("img", { src: value, alt: "Preview" }) : null; |
There was a problem hiding this comment.
Custom widget and preview for the CMS.
Essentially all this is is a "string" widget and a preview so that we can get the functionality of an "image" widget without the button that gives the option to load in a local file.
That way when we query by type we know easily which one we are dealing with. The suggested workaround from gatsby seemed like a pain, especially given that we are not storing figures directly on a markdown node:
https://www.gatsbyjs.com/docs/how-to/images-and-media/preprocessing-external-images/
|
@interim17 Not sure if just me, but the images are displaying diagonally for me on the dev example:
|
gatsby-node.js
Outdated
| Shared frontmatter fields for idea posts (and other markdown). | ||
| """ | ||
| type Frontmatter { | ||
| authors: [String!]! |
There was a problem hiding this comment.
It means not nullable.
So in this case authors type is authors: string[]; and we get an error if markdown doesn't provide it, or a resolver doesn't handle providing a default.
Default gatsby inference would type this as authors: (string | null)[] | null;
| import React from "react"; | ||
|
|
||
| // Custom widget for URL-only image input with preview | ||
| export const UrlImageControl = ({ | ||
| value, | ||
| onChange, | ||
| forID, | ||
| classNameWrapper, | ||
| }) => { | ||
| return React.createElement( | ||
| "div", | ||
| { className: classNameWrapper }, | ||
| React.createElement("input", { | ||
| id: forID, | ||
| type: "text", | ||
| value: value || "", | ||
| onChange: (e) => onChange(e.target.value), | ||
| placeholder: "https://example.com/image.png", | ||
| style: { width: "100%" }, | ||
| }), | ||
| value && | ||
| React.createElement("img", { | ||
| src: value, | ||
| alt: "Preview", | ||
| style: { | ||
| display: "block", | ||
| marginTop: "12px", | ||
| maxWidth: "100%", | ||
| maxHeight: "200px", | ||
| }, | ||
| }), | ||
| ); | ||
| }; | ||
|
|
||
| export const UrlImagePreview = ({ value }) => | ||
| value ? React.createElement("img", { src: value, alt: "Preview" }) : null; |
There was a problem hiding this comment.
Will consider refactoring this to use the pattern in #49 when that gets merged.
Deferring the long term design choice here, but wrapped it in a flex box for now. |
|
@interim17 can you add the |
|
@Megan making those widgets into markdown widgets is easy, will do. After trying to add That typing is made available by a plugin: https://www.npmjs.com/package/gatsby-transformer-remark-frontmatter?activeTab=versions The plugin converts that Another way to handle it is to use a markdown widget, leave the schema type as a raw string, and then render it with something like I am leaning towards the second option although I think there are good arguments for both. In either case implementing this feels out of scope for this PR? |
|
@meganrm as requested I added the
This PR is officially TOO BIG, let's merge it soon and we can keep cleaning up the idea page in subsequent PRs. @jessicasyu are you willing to rubber stamp this? |
jessicasyu
left a comment
There was a problem hiding this comment.
Mostly over my head, but the images are rendering as expected and the various fields are showing up in the deploy preview!
Looks like the markdown rendering in the resource description is still a little wonky, but that can be fixed later?



Update:
In response to @jessicasyu nicely stress testing the figures data entry, I pushed up a few changes
imageLinkandimageFilefor figuresurl-imageforimageLinkProblem
Advances #7
Not a polished design, but it's easier to picture the final result if add better placeholders, and actually query and render the data. Then we can design around something more reasonable.