Skip to content
Merged
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
11 changes: 11 additions & 0 deletions dashboard/src/skills/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
ResponsiveContainer,
} from "recharts";
import { apiUrl } from "../shared/apiUrl";
import { issuesUrl } from "./issuesUrl";
import {
buildDaySeries,
groupByTest,
Expand Down Expand Up @@ -279,6 +280,16 @@ export default function App() {
<p className="skills-file-count">
Files: {selectedSkill.fileCount}
</p>
<p className="skills-issues-link">
<a
href={issuesUrl(selectedSkill.name)}
Comment thread
tmeschter marked this conversation as resolved.
target="_blank"
rel="noopener noreferrer"
title={`Open issues for ${selectedSkill.name} in a new tab`}
>
View open issues for {selectedSkill.name} ↗
</a>
</p>
<p className="skills-telemetry">
<a
className="skills-telemetry-link"
Expand Down
24 changes: 24 additions & 0 deletions dashboard/src/skills/__tests__/issuesUrl.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { describe, it, expect } from "vitest";
import { issuesUrl } from "../issuesUrl";

Comment thread
tmeschter marked this conversation as resolved.
describe("issuesUrl", () => {
it("points at the repo's issue search", () => {
expect(issuesUrl("azure-deploy")).toContain(
"https://github.com/microsoft/GitHub-Copilot-for-Azure/issues?q=",
);
});

it("filters to open issues labelled with the skill name", () => {
const url = issuesUrl("azure-deploy");
const query = new URL(url).searchParams.get("q");
expect(query).toBe('is:issue state:open label:"azure-deploy"');
});

it("url-encodes skill names with special characters", () => {
const url = issuesUrl("foundry agent/create");
// Raw skill name must not appear unencoded in the URL.
expect(url).not.toContain("foundry agent/create");
const query = new URL(url).searchParams.get("q");
expect(query).toBe('is:issue state:open label:"foundry agent/create"');
});
});
11 changes: 11 additions & 0 deletions dashboard/src/skills/issuesUrl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/** Repository whose issues are surfaced from each skill page. */
const ISSUES_REPO = "microsoft/GitHub-Copilot-for-Azure";

/**
* Build a GitHub search URL for the open issues labelled with a skill's name.
* The skill name is used verbatim as the label value.
*/
export function issuesUrl(skillName: string): string {
const query = `is:issue state:open label:"${skillName}"`;
return `https://github.com/${ISSUES_REPO}/issues?q=${encodeURIComponent(query)}`;
}
21 changes: 21 additions & 0 deletions dashboard/src/skills/skills.css
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,27 @@
font-size: 0.9rem;
}

.skills-issues-link {
margin: 0.5rem 0 0;
font-size: 0.9rem;
}

.skills-issues-link a {
color: var(--color-focus, #3b82f6);
text-decoration: none;
}

.skills-issues-link a:hover {
text-decoration: underline;
}

.skills-issues-link a:focus-visible {
outline: 2px solid var(--color-focus, #3b82f6);
outline-offset: 2px;
text-decoration: underline;
border-radius: 2px;
}

.skills-file-count {
margin: 0;
color: var(--color-text-muted);
Expand Down
Loading