Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 7 additions & 13 deletions components/shared/IndexIssueListItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,25 @@ import Card from "react-bootstrap/Card";
import Link from "next/link";
import ReactMarkdown from "react-markdown";

function parseBody(body) {
// extract content up to the first sentence or linebreak if no period to use as description
const reDescriptionSentence = /^(.*?)[.?!]\s+/;
const reDescriptionLinebreak = /.*/;
const description =
body.match(reDescriptionSentence)?.[0] ||
body.match(reDescriptionLinebreak)?.[0];
const reImg = /(?:!\[(.*?)\]\((.*?)\))/;
function parseImage(body) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we dont need to parse the body test for the description anymore now that we are using the description field, so this function becomes entirely about parsing the image

// find the first img (if one exists)
const reImg = /(?:!\[(.*?)\]\((.*?)\))/;
const imgMatch = body.match(reImg);
let img = null;
if (imgMatch && imgMatch.length > 0) {
img = { alt: imgMatch[1], src: imgMatch[2] };
}
return [description, img];
return img;
}
Comment on lines +6 to 15

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I spun this up, I was surprised to see that only one Service card had an image because I knew that @katelunceford had added some to, at least, the dev services. I looked at the issues for these service cards, and it looks like the images have been added using an image tag (example 1) instead of a markdown tag shown below in example 2.

Example 1:
<img width="1382" height="921" alt="Image" src="https://github.com/user-attachments/assets/a21bab84-2377-4547-9bac-ed69085cdf40" />

Example 2:
![ECM Index image](https://github.com/cityofaustin/atd-data-tech/assets/49930868/64ee6500-659f-477b-94d4-9043ca5ec23d)

I think it'd be cleaner to use a consistent mechanism (Example 2 style) in our GitHub issues, and I think getting those issues' images converted should block this going live.

@amenity amenity Jul 28, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @frankhereford - this has always caused us trouble; see #16240. 😢 Unfortunately, the Markdown syntax doesn't work consistently either.

If necessary, I'd prefer to standardize to Example 1, as that's the default a user gets when dragging an image from their desktop. Then we'd need to go through the 250+ existing indices to identify and update those using Markdown. I could probably sic Claude on it to expedite save human time on it.

All those Maximo tiles are because a lot of issues were miscategorized as Service types:
Screenshot 2026-07-28 at 8 43 47 PM

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we make a spinoff issue to update the code to handle a markdown or html image tag? I can't recall why we've never tried to do that.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rose and I sync'd on this, and we discussed this as an option and looked at some example code that does exactly this. I'll sync up with her and ask if we can go in this direction.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just realized that the old bug report I pulled up had the right issue # but the wrong link. 🙃 Corrected above, and for the record and an excuse to use John's Chrome extension:
#16240 - [Bug] Occasional project index images do not display on the website


function getIndexType(issue) {
if (issue.labels.includes("Product Index")) return "product";
if (issue.labels.includes("Project Index")) return "project";
if (issue.type === "Product") return "product";
if (issue.type === "Project") return "project";
return "service";
}

export default function IndexIssueListItem({ issue }) {
const [description, img] = parseBody(issue.body);
const img = parseImage(issue.body);

return (
<Link
Expand Down Expand Up @@ -61,7 +55,7 @@ export default function IndexIssueListItem({ issue }) {
}}
skipHtml
>
{description}
{issue.description}
</ReactMarkdown>
</small>
</Card.Text>
Expand Down
4 changes: 2 additions & 2 deletions components/shared/indexIssueDetails/IndexIssueDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@ function InfoRow({ indexType, issue }) {
})[0];
return (
<Row className="mb-4">
{issue.type && (
{issue.labelType && (
<Col sm={3} md="auto">
<h6 className="mb-0 mt-2 text-muted">Type</h6> {issue.type}
<h6 className="mb-0 mt-2 text-muted">Type</h6> {issue.labelType}
</Col>
)}
<Col sm={3} md="auto">
Expand Down
11 changes: 8 additions & 3 deletions components/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function useSocrata({ url }) {
};
}

function getIssueType(labels) {
function getLabelType(labels) {
// if an issue has more than one `type: ` label, all but one are ignored
const types = labels.filter((label) => label.startsWith("Type"));
const typesParsed = types.map((type) => type.split("Type: ")[1]);
Expand Down Expand Up @@ -61,7 +61,7 @@ function sortByUpdatedDate(a, b) {
}

export function handleIssueData(data) {
// do some global tidying of the data.
// do some global tidying of the data
const dataHandled = data.map((issue) => {
// copy issue to avoid modifying data in-place, which can have unexpected effects on re-render
const newIssue = { ...issue };
Expand All @@ -75,9 +75,14 @@ export function handleIssueData(data) {
newIssue.workgroups = newIssue.workgroups
? newIssue.workgroups.split(", ")
: [];
newIssue.type = getIssueType(newIssue.labels);
// labelType is found in the label
newIssue.labelType = getLabelType(newIssue.labels);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we already had a field called "type" before which i have renamed to labelType, bc it exists in the Labels field. ie: "Type: DevOps"

// type is the Github project issue Type
newIssue.type.trim();
// assign a generalized "status" based on the issue pipeline
newIssue.status = getStatus(newIssue.pipeline);
// Github project field called DTS Description
newIssue.description = newIssue.description?.trim() || "";
newIssue.title = dropTitlePrefix(newIssue.title);
newIssue.isFeatured = newIssue.labels.includes("Featured Project");
return newIssue;
Expand Down
9 changes: 4 additions & 5 deletions components/wrappers/IssuesContextWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,26 @@ import { ISSUES_ENDPOINT } from "../settings";

const STATUSES = ["needs_scoping", "backlog", "in_progress", "completed"];

// The `labels` column is a comma-separated string of labels, so we use wildcard string searching
const QUERY =
"$limit=100000&$where=(labels like '%Project Index%' or labels like '%Product Index%' or labels like '%Service Index%') and labels not like '%Archived Project%' and (pipeline != 'Icebox' or pipeline is null)";
"$limit=100000&$where=(type like '%Project%' or type like '%Product%' or type like '%Service%') and type not like '%Archived Project%' and (pipeline != 'Icebox' or pipeline is null)";

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@katelunceford @amenity will we still be using "Archived Project" as a type?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks like archived project will not be a Type, will it still be used as a Label?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@johnclary those are being converted into a single Service: AMANDA support!


function useProjectIssues(data) {
return useMemo(
() => data.filter((issue) => issue.labels.includes("Project Index")),
() => data.filter((issue) => issue.type === "Project"),
[data]
);
}

function useProductIssues(data) {
return useMemo(
() => data.filter((issue) => issue.labels.includes("Product Index")),
() => data.filter((issue) => issue.type === "Product"),
[data]
);
}

function useServiceIssues(data) {
return useMemo(
() => data.filter((issue) => issue.labels.includes("Service Index")),
() => data.filter((issue) => issue.type === "Service"),
[data]
);
}
Expand Down