-
Notifications
You must be signed in to change notification settings - Fork 0
slugs for foreign keys #33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
3e349d2
add dev script
interim17 489bf39
show related posts in tag popover component
interim17 7e48bf6
Update src/components/IdeaRoll.tsx
interim17 2e32af0
Update src/components/TagPopover.tsx
interim17 f961a52
add non null assertions to fields
interim17 6c51ce7
Merge branch 'main' of https://github.com/AllenCell/idea-board into f…
interim17 81d0ab5
use generated types with tag popover
interim17 da89847
install slugify and vitest
interim17 f52f2b8
rename timelapse-feature-explorer markdown file
interim17 01a10e4
add link and description to emt dataset markdown
interim17 ade267c
use link directive and slugs to map foreign key relationships
interim17 56b1bc7
Merge branch 'main' into feature/fk
meganrm da2a471
bump node version for netlify
interim17 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| const DATASET_PATH = `dataset`; | ||
| const SOFTWARE_PATH = `software`; | ||
|
|
||
| module.exports = { | ||
| DATASET_PATH, | ||
| SOFTWARE_PATH, | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,79 @@ | ||
| const { SOFTWARE_PATH } = require("../gatsbyutils/constants"); | ||
| const slugify = require("slugify"); | ||
|
|
||
| /** | ||
| * Returns the raw value if it's a non-empty string, otherwise returns the fallback. | ||
| * @param {unknown} rawValue - The value to check | ||
| * @param {T} fallback - The fallback value to return if rawValue is not a valid string | ||
| * @returns {string|T} The raw string value or the fallback | ||
| * @template T | ||
| */ | ||
| function stringWithDefault(rawValue, fallback) { | ||
| if (typeof rawValue !== "string") return fallback; | ||
| if (rawValue.trim() === "") return fallback; | ||
| return rawValue; | ||
| } | ||
|
|
||
| /** | ||
| * Ensures the value is returned as an array. | ||
| * @param {unknown} value - The value to convert to an array | ||
| * @returns {Array} The original array if value is an array, otherwise an empty array | ||
| */ | ||
| function resolveToArray(value) { | ||
| if (Array.isArray(value)) { | ||
| return value; | ||
| } | ||
| return []; | ||
| } | ||
|
|
||
| /** | ||
| * Prepares software tool references for Gatsby's @link directive. | ||
| * Transforms tool names into slug paths that @link(by: "fields.slug") uses | ||
| * to resolve the actual MarkdownRemark nodes. Filters out invalid entries | ||
| * and preserves custom descriptions. | ||
| * @param {Array<{softwareTool?: string, customDescription?: string}>|unknown} rawSoftware - Array of software tool objects from frontmatter | ||
| * @returns {Array<{softwareTool: string|null, customDescription: string|null}>} Array with slug keys for @link resolution | ||
| */ | ||
| const resolveSoftwareTools = (rawSoftware) => { | ||
| if (!Array.isArray(rawSoftware)) { | ||
| return []; | ||
| } | ||
| return rawSoftware | ||
| .map((item) => { | ||
| if (item && typeof item === "object" && item.softwareTool) { | ||
| return { | ||
| softwareTool: resolveSlug(item.softwareTool, SOFTWARE_PATH), | ||
| customDescription: stringWithDefault( | ||
| item.customDescription, | ||
| null | ||
| ), | ||
| }; | ||
| } | ||
| return null; | ||
| }) | ||
| .filter((item) => item !== null); | ||
| }; | ||
|
|
||
| /** | ||
| * Builds slugs from directory paths and ids/names. | ||
| * Uses slugs in place of names to prevent namespace | ||
| * collisions when using @link directive in Gatsby schema. | ||
| * @param {string|null|undefined} id - The identifier to slugify (e.g., "My Dataset") | ||
| * @param {string} directory - The directory prefix (e.g., "dataset", "software") | ||
| * @returns {string|null} The full slug path (e.g., "/dataset/my-dataset/") or null if id is falsy | ||
| */ | ||
| const resolveSlug = (id, directory) => { | ||
| if (!id) return null; | ||
| const slugPart = slugify(id, { lower: true, strict: true }).replace( | ||
| /^\/+|\/+$/g, | ||
| "" | ||
| ); // Slugify and remove leading/trailing slashes | ||
| return `/${directory}/${slugPart}/`; | ||
| }; | ||
|
|
||
| module.exports = { | ||
| stringWithDefault, | ||
| resolveToArray, | ||
| }; | ||
| resolveSlug, | ||
| resolveSoftwareTools, | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| import { describe, it, expect } from 'vitest'; | ||
| import { resolveSlug, resolveSoftwareTools } from '../gatsby-resolver-utils'; | ||
| import { DATASET_PATH, SOFTWARE_PATH } from '../constants'; | ||
|
|
||
| describe('resolveSlug', () => { | ||
| it('should return null when id is falsy', () => { | ||
| expect(resolveSlug(null, 'software')).toBe(null); | ||
| expect(resolveSlug(undefined, 'software')).toBe(null); | ||
| expect(resolveSlug('', 'software')).toBe(null); | ||
| }); | ||
|
|
||
| it('should build a slug from id and directory', () => { | ||
| expect(resolveSlug("released-emt-dataset", DATASET_PATH)).toBe( | ||
| "/dataset/released-emt-dataset/" | ||
| ); | ||
| }); | ||
|
|
||
| it('should slugify the id to lowercase', () => { | ||
| expect(resolveSlug("UPPERCASE", DATASET_PATH)).toBe( | ||
| "/dataset/uppercase/" | ||
| ); | ||
| }); | ||
|
|
||
| it('should handle special characters in id', () => { | ||
| expect(resolveSlug("Tool & Library", SOFTWARE_PATH)).toBe( | ||
| "/software/tool-and-library/" | ||
| ); | ||
| expect(resolveSlug("Some/Path/Name", SOFTWARE_PATH)).toBe( | ||
| "/software/somepathname/" | ||
| ); | ||
| }); | ||
|
|
||
| it('should handle ids with leading/trailing spaces', () => { | ||
| expect(resolveSlug(' trimmed ', 'software')).toBe('/software/trimmed/'); | ||
| }); | ||
| }); | ||
|
|
||
| describe('resolveSoftwareTools', () => { | ||
| it('should return empty array for non-array inputs', () => { | ||
| expect(resolveSoftwareTools(null)).toEqual([]); | ||
| expect(resolveSoftwareTools(undefined)).toEqual([]); | ||
| expect(resolveSoftwareTools('string')).toEqual([]); | ||
| expect(resolveSoftwareTools({})).toEqual([]); | ||
| expect(resolveSoftwareTools(123)).toEqual([]); | ||
| }); | ||
|
|
||
| it('should return empty array for empty array', () => { | ||
| expect(resolveSoftwareTools([])).toEqual([]); | ||
| }); | ||
|
|
||
| it('should filter out invalid items', () => { | ||
| const input = [null, undefined, 'string', {}, { other: 'prop' }]; | ||
| expect(resolveSoftwareTools(input)).toEqual([]); | ||
| }); | ||
|
|
||
| it('should transform valid items with softwareTool', () => { | ||
| const input = [{ softwareTool: 'Simularium' }]; | ||
| expect(resolveSoftwareTools(input)).toEqual([ | ||
| { | ||
| softwareTool: '/software/simularium/', | ||
| customDescription: null, | ||
| }, | ||
| ]); | ||
| }); | ||
|
|
||
| it('should preserve customDescription when provided', () => { | ||
| const input = [ | ||
| { | ||
| softwareTool: 'Simularium', | ||
| customDescription: 'Custom description here', | ||
| }, | ||
| ]; | ||
| expect(resolveSoftwareTools(input)).toEqual([ | ||
| { | ||
| softwareTool: '/software/simularium/', | ||
| customDescription: 'Custom description here', | ||
| }, | ||
| ]); | ||
| }); | ||
|
|
||
| it('should return null for empty customDescription', () => { | ||
| const input = [{ softwareTool: 'Simularium', customDescription: '' }]; | ||
| expect(resolveSoftwareTools(input)).toEqual([ | ||
| { | ||
| softwareTool: '/software/simularium/', | ||
| customDescription: null, | ||
| }, | ||
| ]); | ||
| }); | ||
|
|
||
| it('should handle mixed valid and invalid items', () => { | ||
| const input = [ | ||
| null, | ||
| { softwareTool: 'Simularium' }, | ||
| { other: 'invalid' }, | ||
| { softwareTool: 'TFE', customDescription: 'Time explorer' }, | ||
| ]; | ||
| expect(resolveSoftwareTools(input)).toEqual([ | ||
| { | ||
| softwareTool: '/software/simularium/', | ||
| customDescription: null, | ||
| }, | ||
| { | ||
| softwareTool: '/software/tfe/', | ||
| customDescription: 'Time explorer', | ||
| }, | ||
| ]); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,8 @@ | ||
| --- | ||
| templateKey: dataset | ||
| name: Released EMT dataset | ||
| link: test | ||
| link: "https://www.biorxiv.org/content/10.1101/2024.08.16.608353v1.full" | ||
| description: Description for released EMT dataset in the markdown file for the dataset. | ||
| status: Public | ||
| date: 2025-06-02T16:11:00.000Z | ||
| --- |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we talked about this. I'm skeptical of including this but it's fine for now