Merge remote-tracking branch 'upstream/master' into gh-3811-repo-url-file-registration
This commit is contained in:
Vendored
+1
-1
@@ -51,7 +51,7 @@ export interface Config {
|
||||
cert?: string;
|
||||
privateKey?: string;
|
||||
decryptionPvk?: string;
|
||||
signatureAlgorithm?: 'sha1' | 'sha256' | 'sha512';
|
||||
signatureAlgorithm?: 'sha256' | 'sha512';
|
||||
digestAlgorithm?: string;
|
||||
};
|
||||
okta?: {
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
"passport-oauth2": "^1.5.0",
|
||||
"passport-okta-oauth": "^0.0.1",
|
||||
"passport-onelogin-oauth": "^0.0.1",
|
||||
"passport-saml": "^1.3.5, <1.4.0",
|
||||
"passport-saml": "^2.0.0",
|
||||
"uuid": "^8.0.0",
|
||||
"winston": "^3.2.1",
|
||||
"yn": "^4.0.0"
|
||||
@@ -74,6 +74,8 @@
|
||||
"@types/passport-google-oauth20": "^2.0.3",
|
||||
"@types/passport-microsoft": "^0.0.0",
|
||||
"@types/passport-saml": "^1.1.2",
|
||||
"@types/passport-strategy": "^0.2.35",
|
||||
"@types/xml2js": "^0.4.7",
|
||||
"msw": "^0.21.2",
|
||||
"nock": "^13.0.5"
|
||||
},
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
|
||||
import express from 'express';
|
||||
import { SamlConfig } from 'passport-saml/lib/passport-saml/types';
|
||||
import {
|
||||
SamlConfig,
|
||||
Strategy as SamlStrategy,
|
||||
Profile as SamlProfile,
|
||||
VerifyWithoutRequest,
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"@backstage/backend-common": "^0.4.2",
|
||||
"@backstage/catalog-model": "^0.6.0",
|
||||
"@backstage/config": "^0.1.2",
|
||||
"@octokit/graphql": "^4.5.6",
|
||||
"@octokit/graphql": "^4.5.8",
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/ldapjs": "^1.0.9",
|
||||
"codeowners-utils": "^1.0.2",
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"@material-ui/core": "^4.11.0",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "4.0.0-alpha.45",
|
||||
"@octokit/rest": "^18.0.6",
|
||||
"@octokit/rest": "^18.0.12",
|
||||
"git-url-parse": "^11.4.3",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
|
||||
@@ -37,8 +37,6 @@
|
||||
"@material-ui/core": "^4.11.0",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "4.0.0-alpha.45",
|
||||
"@octokit/rest": "^18.0.0",
|
||||
"@octokit/types": "^5.4.1",
|
||||
"moment": "^2.27.0",
|
||||
"qs": "^6.9.4",
|
||||
"react": "^16.13.1",
|
||||
|
||||
@@ -40,8 +40,7 @@
|
||||
"@material-ui/core": "^4.11.0",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "4.0.0-alpha.45",
|
||||
"@octokit/rest": "^18.0.0",
|
||||
"@octokit/types": "^5.4.1",
|
||||
"@octokit/rest": "^18.0.12",
|
||||
"moment": "^2.27.0",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
|
||||
@@ -15,12 +15,7 @@
|
||||
*/
|
||||
|
||||
import { createApiRef } from '@backstage/core';
|
||||
import {
|
||||
ActionsListWorkflowRunsForRepoResponseData,
|
||||
ActionsGetWorkflowResponseData,
|
||||
ActionsGetWorkflowRunResponseData,
|
||||
EndpointInterface,
|
||||
} from '@octokit/types';
|
||||
import { RestEndpointMethodTypes } from '@octokit/rest';
|
||||
|
||||
export const githubActionsApiRef = createApiRef<GithubActionsApi>({
|
||||
id: 'plugin.githubactions.service',
|
||||
@@ -42,7 +37,9 @@ export type GithubActionsApi = {
|
||||
pageSize?: number;
|
||||
page?: number;
|
||||
branch?: string;
|
||||
}) => Promise<ActionsListWorkflowRunsForRepoResponseData>;
|
||||
}) => Promise<
|
||||
RestEndpointMethodTypes['actions']['listWorkflowRuns']['response']['data']
|
||||
>;
|
||||
getWorkflow: ({
|
||||
token,
|
||||
owner,
|
||||
@@ -53,7 +50,9 @@ export type GithubActionsApi = {
|
||||
owner: string;
|
||||
repo: string;
|
||||
id: number;
|
||||
}) => Promise<ActionsGetWorkflowResponseData>;
|
||||
}) => Promise<
|
||||
RestEndpointMethodTypes['actions']['getWorkflow']['response']['data']
|
||||
>;
|
||||
getWorkflowRun: ({
|
||||
token,
|
||||
owner,
|
||||
@@ -64,7 +63,9 @@ export type GithubActionsApi = {
|
||||
owner: string;
|
||||
repo: string;
|
||||
id: number;
|
||||
}) => Promise<ActionsGetWorkflowRunResponseData>;
|
||||
}) => Promise<
|
||||
RestEndpointMethodTypes['actions']['getWorkflowRun']['response']['data']
|
||||
>;
|
||||
reRunWorkflow: ({
|
||||
token,
|
||||
owner,
|
||||
@@ -86,5 +87,7 @@ export type GithubActionsApi = {
|
||||
owner: string;
|
||||
repo: string;
|
||||
runId: number;
|
||||
}) => Promise<EndpointInterface>;
|
||||
}) => Promise<
|
||||
RestEndpointMethodTypes['actions']['downloadJobLogsForWorkflowRun']['response']['data']
|
||||
>;
|
||||
};
|
||||
|
||||
@@ -15,13 +15,7 @@
|
||||
*/
|
||||
|
||||
import { GithubActionsApi } from './GithubActionsApi';
|
||||
import { Octokit } from '@octokit/rest';
|
||||
import {
|
||||
ActionsListWorkflowRunsForRepoResponseData,
|
||||
ActionsGetWorkflowResponseData,
|
||||
ActionsGetWorkflowRunResponseData,
|
||||
EndpointInterface,
|
||||
} from '@octokit/types';
|
||||
import { Octokit, RestEndpointMethodTypes } from '@octokit/rest';
|
||||
|
||||
export class GithubActionsClient implements GithubActionsApi {
|
||||
async reRunWorkflow({
|
||||
@@ -55,7 +49,9 @@ export class GithubActionsClient implements GithubActionsApi {
|
||||
pageSize?: number;
|
||||
page?: number;
|
||||
branch?: string;
|
||||
}): Promise<ActionsListWorkflowRunsForRepoResponseData> {
|
||||
}): Promise<
|
||||
RestEndpointMethodTypes['actions']['listWorkflowRuns']['response']['data']
|
||||
> {
|
||||
const workflowRuns = await new Octokit({
|
||||
auth: token,
|
||||
}).actions.listWorkflowRunsForRepo({
|
||||
@@ -77,7 +73,9 @@ export class GithubActionsClient implements GithubActionsApi {
|
||||
owner: string;
|
||||
repo: string;
|
||||
id: number;
|
||||
}): Promise<ActionsGetWorkflowResponseData> {
|
||||
}): Promise<
|
||||
RestEndpointMethodTypes['actions']['getWorkflow']['response']['data']
|
||||
> {
|
||||
const workflow = await new Octokit({ auth: token }).actions.getWorkflow({
|
||||
owner,
|
||||
repo,
|
||||
@@ -95,7 +93,9 @@ export class GithubActionsClient implements GithubActionsApi {
|
||||
owner: string;
|
||||
repo: string;
|
||||
id: number;
|
||||
}): Promise<ActionsGetWorkflowRunResponseData> {
|
||||
}): Promise<
|
||||
RestEndpointMethodTypes['actions']['getWorkflowRun']['response']['data']
|
||||
> {
|
||||
const run = await new Octokit({ auth: token }).actions.getWorkflowRun({
|
||||
owner,
|
||||
repo,
|
||||
@@ -113,7 +113,9 @@ export class GithubActionsClient implements GithubActionsApi {
|
||||
owner: string;
|
||||
repo: string;
|
||||
runId: number;
|
||||
}): Promise<EndpointInterface> {
|
||||
}): Promise<
|
||||
RestEndpointMethodTypes['actions']['downloadJobLogsForWorkflowRun']['response']['data']
|
||||
> {
|
||||
const workflow = await new Octokit({
|
||||
auth: token,
|
||||
}).actions.downloadJobLogsForWorkflowRun({
|
||||
|
||||
@@ -209,8 +209,8 @@ export const WorkflowRunDetails = ({ entity }: { entity: Entity }) => {
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<WorkflowRunStatus
|
||||
status={details.value?.status}
|
||||
conclusion={details.value?.conclusion}
|
||||
status={details.value?.status || undefined}
|
||||
conclusion={details.value?.conclusion || undefined}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
@@ -218,7 +218,7 @@ export const WorkflowRunDetails = ({ entity }: { entity: Entity }) => {
|
||||
<TableCell>
|
||||
<Typography noWrap>Author</Typography>
|
||||
</TableCell>
|
||||
<TableCell>{`${details.value?.head_commit.author.name} (${details.value?.head_commit.author.email})`}</TableCell>
|
||||
<TableCell>{`${details.value?.head_commit.author?.name} (${details.value?.head_commit.author?.email})`}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
|
||||
@@ -18,7 +18,6 @@ import { useAsyncRetry } from 'react-use';
|
||||
import { WorkflowRun } from './WorkflowRunsTable/WorkflowRunsTable';
|
||||
import { githubActionsApiRef } from '../api/GithubActionsApi';
|
||||
import { useApi, githubAuthApiRef, errorApiRef } from '@backstage/core';
|
||||
import { ActionsListWorkflowRunsForRepoResponseData } from '@octokit/types';
|
||||
|
||||
export function useWorkflowRuns({
|
||||
owner,
|
||||
@@ -55,44 +54,40 @@ export function useWorkflowRuns({
|
||||
page: page + 1,
|
||||
branch,
|
||||
})
|
||||
.then(
|
||||
(
|
||||
workflowRunsData: ActionsListWorkflowRunsForRepoResponseData,
|
||||
): WorkflowRun[] => {
|
||||
setTotal(workflowRunsData.total_count);
|
||||
// Transformation here
|
||||
return workflowRunsData.workflow_runs.map(run => ({
|
||||
message: run.head_commit.message,
|
||||
id: `${run.id}`,
|
||||
onReRunClick: async () => {
|
||||
try {
|
||||
await api.reRunWorkflow({
|
||||
token,
|
||||
owner,
|
||||
repo,
|
||||
runId: run.id,
|
||||
});
|
||||
} catch (e) {
|
||||
errorApi.post(e);
|
||||
}
|
||||
.then((workflowRunsData): WorkflowRun[] => {
|
||||
setTotal(workflowRunsData.total_count);
|
||||
// Transformation here
|
||||
return workflowRunsData.workflow_runs.map(run => ({
|
||||
message: run.head_commit.message,
|
||||
id: `${run.id}`,
|
||||
onReRunClick: async () => {
|
||||
try {
|
||||
await api.reRunWorkflow({
|
||||
token,
|
||||
owner,
|
||||
repo,
|
||||
runId: run.id,
|
||||
});
|
||||
} catch (e) {
|
||||
errorApi.post(e);
|
||||
}
|
||||
},
|
||||
source: {
|
||||
branchName: run.head_branch,
|
||||
commit: {
|
||||
hash: run.head_commit.id,
|
||||
url: run.head_repository.branches_url.replace(
|
||||
'{/branch}',
|
||||
run.head_branch,
|
||||
),
|
||||
},
|
||||
source: {
|
||||
branchName: run.head_branch,
|
||||
commit: {
|
||||
hash: run.head_commit.id,
|
||||
url: run.head_repository.branches_url.replace(
|
||||
'{/branch}',
|
||||
run.head_branch,
|
||||
),
|
||||
},
|
||||
},
|
||||
status: run.status,
|
||||
conclusion: run.conclusion,
|
||||
url: run.url,
|
||||
githubUrl: run.html_url,
|
||||
}));
|
||||
},
|
||||
)
|
||||
},
|
||||
status: run.status,
|
||||
conclusion: run.conclusion,
|
||||
url: run.url,
|
||||
githubUrl: run.html_url,
|
||||
}));
|
||||
})
|
||||
);
|
||||
}, [page, pageSize, repo, owner]);
|
||||
|
||||
|
||||
+50
-39
@@ -12,53 +12,64 @@ By exposing GraphiQL as a plugin instead of a standalone app, it's possible to p
|
||||
Start out by installing the plugin in your Backstage app:
|
||||
|
||||
```bash
|
||||
cd packages/app
|
||||
yarn add @backstage/plugin-graphiql
|
||||
```
|
||||
|
||||
Then add an entry to your App's `plugins.ts` to import the plugin.
|
||||
```diff
|
||||
# in packages/app/src/plugins.ts
|
||||
+export { plugin as GraphiQL } from '@backstage/plugin-graphiql';
|
||||
```
|
||||
|
||||
The plugin registers a `/graphiql` route, which you can link to from the Sidebar if desired.
|
||||
```diff
|
||||
# in packages/app/src/App.tsx
|
||||
+import { Router as GraphiQLRouter } from '@backstage/plugin-graphiql';
|
||||
|
||||
const AppRoutes = () => (
|
||||
<Routes>
|
||||
+ <Route path="/graphiql" element={<GraphiQLRouter />} />
|
||||
```
|
||||
|
||||
### Adding GraphQL endpoints
|
||||
|
||||
For the plugin to function, you need to supply GraphQL endpoints through the GraphQLBrowse API, which is done by implementing the `GraphQLBrowseApi` exported by this plugin.
|
||||
For the plugin to function, you need to supply GraphQL endpoints through the GraphQLBrowse API. This is done by implementing the `graphQlBrowseApiRef` exported by this plugin.
|
||||
|
||||
If all you need is a static list of endpoints, the plugin exports a `GraphQLEndpoints` class that implements the `GraphQLBrowseApi` for you. Here's and example of how you could expose two GraphQL endpoints in your App:
|
||||
If all you need is a static list of endpoints, the plugin exports a `GraphQLEndpoints` class that implements the `GraphQLBrowseApi` for you. Here's an example of how you could expose two GraphQL endpoints in your App:
|
||||
|
||||
```tsx
|
||||
import {
|
||||
graphQlBrowseApiRef,
|
||||
GraphQLEndpoints,
|
||||
} from '@backstage/plugin-graphiql';
|
||||
```diff
|
||||
# in packages/app/src/apis.ts
|
||||
+import {
|
||||
+ graphQlBrowseApiRef,
|
||||
+ GraphQLEndpoints,
|
||||
+} from '@backstage/plugin-graphiql';
|
||||
|
||||
// Implement the Graph QL browse API using a static list of endpoints
|
||||
const graphQlBrowseApi = GraphQLEndpoints.from([
|
||||
// Use the .create function if all you need is a static URL and headers.
|
||||
GraphQLEndpoints.create({
|
||||
id: 'gitlab',
|
||||
title: 'GitLab',
|
||||
url: 'https://gitlab.com/api/graphql',
|
||||
// Optional extra headers
|
||||
headers: { Extra: 'Header' },
|
||||
}),
|
||||
{
|
||||
id: 'hooli-search',
|
||||
title: 'Hooli Search',
|
||||
// Custom fetch function, this one is equivalent to using GraphQLEndpoints.create()
|
||||
// with url set to https://internal.hooli.com/search
|
||||
fetcher: async (params: any) => {
|
||||
return fetch('https://internal.hooli.com/search', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(params),
|
||||
}).then(res => res.json());
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
// ApiRegistry builder created somewhere in your App
|
||||
const builder = ApiRegistry.builder();
|
||||
|
||||
// Add the instance to the API registry
|
||||
builder.add(graphQlBrowseApiRef, graphQlBrowseApi);
|
||||
export const apis = [
|
||||
+ createApiFactory({
|
||||
+ api: graphQlBrowseApiRef,
|
||||
+ deps: { errorApi: errorApiRef, githubAuthApi: githubAuthApiRef },
|
||||
+ factory: ({ errorApi, githubAuthApi }) =>
|
||||
+ GraphQLEndpoints.from([
|
||||
+ // Use the .create function if all you need is a static URL and headers.
|
||||
+ GraphQLEndpoints.create({
|
||||
+ id: 'gitlab',
|
||||
+ title: 'GitLab',
|
||||
+ url: 'https://gitlab.com/api/graphql',
|
||||
+ // Optional extra headers
|
||||
+ headers: { Extra: 'Header' },
|
||||
+ }),
|
||||
+ {
|
||||
+ id: 'hooli-search',
|
||||
+ title: 'Hooli Search',
|
||||
+ // Custom fetch function, this one is equivalent to using GraphQLEndpoints.create()
|
||||
+ // with url set to https://internal.hooli.com/search
|
||||
+ fetcher: async (params: any) => {
|
||||
+ return fetch('https://internal.hooli.com/search', {
|
||||
+ method: 'POST',
|
||||
+ headers: { 'Content-Type': 'application/json' },
|
||||
+ body: JSON.stringify(params),
|
||||
+ }).then(res => res.json());
|
||||
+ },
|
||||
+ }
|
||||
+ ]),
|
||||
+ }),
|
||||
```
|
||||
|
||||
@@ -25,7 +25,8 @@ import { graphiQLRouteRef } from './route-refs';
|
||||
export const plugin = createPlugin({
|
||||
id: 'graphiql',
|
||||
apis: [
|
||||
// GitLab is used as an example endpoint, but most plug
|
||||
// GitLab is used as an example endpoint, but most will want to plug in
|
||||
// their own instead.
|
||||
createApiFactory(
|
||||
graphQlBrowseApiRef,
|
||||
GraphQLEndpoints.from([
|
||||
|
||||
@@ -125,7 +125,9 @@ export const MembersListCard = ({
|
||||
UserEntity
|
||||
>).filter(member =>
|
||||
member?.relations?.some(
|
||||
r => r.type === RELATION_MEMBER_OF && r.target.name === groupName,
|
||||
r =>
|
||||
r.type === RELATION_MEMBER_OF &&
|
||||
r.target.name.toLowerCase() === groupName.toLowerCase(),
|
||||
),
|
||||
);
|
||||
return groupMembersList;
|
||||
|
||||
@@ -33,9 +33,9 @@
|
||||
"@backstage/catalog-model": "^0.6.0",
|
||||
"@backstage/config": "^0.1.2",
|
||||
"@backstage/integration": "^0.1.5",
|
||||
"@gitbeaker/core": "^25.2.0",
|
||||
"@gitbeaker/node": "^25.2.0",
|
||||
"@octokit/rest": "^18.0.0",
|
||||
"@gitbeaker/core": "^28.0.2",
|
||||
"@gitbeaker/node": "^28.0.2",
|
||||
"@octokit/rest": "^18.0.12",
|
||||
"@types/dockerode": "^3.2.1",
|
||||
"@types/express": "^4.17.6",
|
||||
"azure-devops-node-api": "^10.1.1",
|
||||
@@ -60,7 +60,6 @@
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.4.5",
|
||||
"@backstage/test-utils": "^0.1.5",
|
||||
"@octokit/types": "^5.4.1",
|
||||
"@types/fs-extra": "^9.0.1",
|
||||
"@types/git-url-parse": "^9.0.0",
|
||||
"@types/supertest": "^2.0.8",
|
||||
|
||||
@@ -17,15 +17,10 @@
|
||||
jest.mock('@octokit/rest');
|
||||
jest.mock('./helpers');
|
||||
|
||||
import { Octokit } from '@octokit/rest';
|
||||
import {
|
||||
OctokitResponse,
|
||||
ReposCreateInOrgResponseData,
|
||||
UsersGetByUsernameResponseData,
|
||||
} from '@octokit/types';
|
||||
import { getVoidLogger } from '@backstage/backend-common';
|
||||
import { Octokit, RestEndpointMethodTypes } from '@octokit/rest';
|
||||
import { GithubPublisher } from './github';
|
||||
import { initRepoAndPush } from './helpers';
|
||||
import { getVoidLogger } from '@backstage/backend-common';
|
||||
|
||||
const { mockGithubClient } = require('@octokit/rest') as {
|
||||
mockGithubClient: {
|
||||
@@ -54,12 +49,12 @@ describe('GitHub Publisher', () => {
|
||||
data: {
|
||||
clone_url: 'https://github.com/backstage/backstage.git',
|
||||
},
|
||||
} as OctokitResponse<ReposCreateInOrgResponseData>);
|
||||
} as RestEndpointMethodTypes['repos']['createInOrg']['response']);
|
||||
mockGithubClient.users.getByUsername.mockResolvedValue({
|
||||
data: {
|
||||
type: 'Organization',
|
||||
},
|
||||
} as OctokitResponse<UsersGetByUsernameResponseData>);
|
||||
} as RestEndpointMethodTypes['users']['getByUsername']['response']);
|
||||
|
||||
const result = await publisher.publish({
|
||||
values: {
|
||||
@@ -104,12 +99,12 @@ describe('GitHub Publisher', () => {
|
||||
data: {
|
||||
clone_url: 'https://github.com/backstage/backstage.git',
|
||||
},
|
||||
} as OctokitResponse<ReposCreateInOrgResponseData>);
|
||||
} as RestEndpointMethodTypes['repos']['createForAuthenticatedUser']['response']);
|
||||
mockGithubClient.users.getByUsername.mockResolvedValue({
|
||||
data: {
|
||||
type: 'User',
|
||||
},
|
||||
} as OctokitResponse<UsersGetByUsernameResponseData>);
|
||||
} as RestEndpointMethodTypes['users']['getByUsername']['response']);
|
||||
|
||||
const result = await publisher.publish({
|
||||
values: {
|
||||
@@ -148,12 +143,12 @@ describe('GitHub Publisher', () => {
|
||||
data: {
|
||||
clone_url: 'https://github.com/backstage/backstage.git',
|
||||
},
|
||||
} as OctokitResponse<ReposCreateInOrgResponseData>);
|
||||
} as RestEndpointMethodTypes['repos']['createForAuthenticatedUser']['response']);
|
||||
mockGithubClient.users.getByUsername.mockResolvedValue({
|
||||
data: {
|
||||
type: 'User',
|
||||
},
|
||||
} as OctokitResponse<UsersGetByUsernameResponseData>);
|
||||
} as RestEndpointMethodTypes['users']['getByUsername']['response']);
|
||||
|
||||
const result = await publisher.publish({
|
||||
values: {
|
||||
@@ -205,12 +200,12 @@ describe('GitHub Publisher', () => {
|
||||
data: {
|
||||
clone_url: 'https://github.com/backstage/backstage.git',
|
||||
},
|
||||
} as OctokitResponse<ReposCreateInOrgResponseData>);
|
||||
} as RestEndpointMethodTypes['repos']['createInOrg']['response']);
|
||||
mockGithubClient.users.getByUsername.mockResolvedValue({
|
||||
data: {
|
||||
type: 'Organization',
|
||||
},
|
||||
} as OctokitResponse<UsersGetByUsernameResponseData>);
|
||||
} as RestEndpointMethodTypes['users']['getByUsername']['response']);
|
||||
|
||||
const result = await publisher.publish({
|
||||
values: {
|
||||
@@ -254,12 +249,12 @@ describe('GitHub Publisher', () => {
|
||||
data: {
|
||||
clone_url: 'https://github.com/backstage/backstage.git',
|
||||
},
|
||||
} as OctokitResponse<ReposCreateInOrgResponseData>);
|
||||
} as RestEndpointMethodTypes['repos']['createForAuthenticatedUser']['response']);
|
||||
mockGithubClient.users.getByUsername.mockResolvedValue({
|
||||
data: {
|
||||
type: 'User',
|
||||
},
|
||||
} as OctokitResponse<UsersGetByUsernameResponseData>);
|
||||
} as RestEndpointMethodTypes['users']['getByUsername']['response']);
|
||||
|
||||
const result = await publisher.publish({
|
||||
values: {
|
||||
|
||||
@@ -115,7 +115,15 @@ export const Reader = ({ entityId, onReady }: Props) => {
|
||||
baseUrl: window.location.origin,
|
||||
onClick: (_: MouseEvent, url: string) => {
|
||||
const parsedUrl = new URL(url);
|
||||
navigate(`${parsedUrl.pathname}${parsedUrl.hash}`);
|
||||
if (parsedUrl.hash) {
|
||||
history.pushState(
|
||||
null,
|
||||
'',
|
||||
`${parsedUrl.pathname}${parsedUrl.hash}`,
|
||||
);
|
||||
} else {
|
||||
navigate(parsedUrl.pathname);
|
||||
}
|
||||
|
||||
shadowRoot?.querySelector(parsedUrl.hash)?.scrollIntoView();
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user