Skip to content

Commit

Permalink
Merge pull request #195 from K-Phoen/fix-search
Browse files Browse the repository at this point in the history
Correctly index announcements
  • Loading branch information
K-Phoen authored Dec 28, 2023
2 parents e77d514 + 556d00e commit 977c8eb
Show file tree
Hide file tree
Showing 18 changed files with 151 additions and 98 deletions.
7 changes: 7 additions & 0 deletions .changeset/serious-otters-call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@k-phoen/backstage-plugin-announcements-backend': minor
'@k-phoen/backstage-plugin-announcements-common': minor
'@k-phoen/backstage-plugin-announcements': minor
---

Correctly index announcements
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ import { Readable } from 'stream';
import { Logger } from 'winston';
import { DiscoveryApi } from '@backstage/core-plugin-api';
import { DocumentCollatorFactory } from '@backstage/plugin-search-common';
import { IndexableDocument } from '@backstage/plugin-search-common';
import { Announcement, AnnouncementsClient } from './api';

export type IndexableAnnouncementDocument = IndexableDocument & {
excerpt: string;
createdAt: string;
};
import { AnnouncementsClient } from './api';
import { TokenManager } from '@backstage/backend-common';
import {
Announcement,
IndexableAnnouncement,
} from '@k-phoen/backstage-plugin-announcements-common';

type AnnouncementCollatorOptions = {
logger: Logger;
discoveryApi: DiscoveryApi;
tokenManager?: TokenManager;
};

export class AnnouncementCollatorFactory implements DocumentCollatorFactory {
Expand All @@ -29,28 +29,40 @@ export class AnnouncementCollatorFactory implements DocumentCollatorFactory {
this.logger = options.logger;
this.announcementsClient = new AnnouncementsClient({
discoveryApi: options.discoveryApi,
tokenManager: options.tokenManager,
});
}

async getCollator() {
return Readable.from(this.execute());
}

private async *execute(): AsyncGenerator<IndexableAnnouncementDocument> {
this.logger.info('indexing announcements');
private async *execute(): AsyncGenerator<IndexableAnnouncement> {
this.logger.info('started indexing announcements');

let results: Announcement[] = [];
let page = 1;
const maxPerPage = 50;

do {
results = await this.announcementsClient.announcements({
page,
maxPerPage,
});

this.logger.debug(`got ${results.length} announcements for page ${page}`);

const results = await this.announcementsClient.announcements();
for (const result of results) {
yield this.getDocumentInfo(result);
}

this.logger.debug(`got ${results.length} announcements`);
page += 1;
} while (results.length !== 0);

for (const result of results) {
yield this.getDocumentInfo(result);
}
this.logger.info('finished indexing announcements');
}

private getDocumentInfo(
announcement: Announcement,
): IndexableAnnouncementDocument {
private getDocumentInfo(announcement: Announcement): IndexableAnnouncement {
this.logger.debug(
`mapping announcement ${announcement.id} to indexable document`,
);
Expand Down
45 changes: 32 additions & 13 deletions plugins/announcements-backend/src/search/api.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,54 @@
import fetch from 'node-fetch';
import { DiscoveryApi } from '@backstage/core-plugin-api';
import { ResponseError } from '@backstage/errors';

export type Announcement = {
id: string;
publisher: string;
title: string;
excerpt: string;
body: string;
created_at: string;
};
import { TokenManager } from '@backstage/backend-common';
import {
Announcement,
AnnouncementsList,
} from '@k-phoen/backstage-plugin-announcements-common';

export class AnnouncementsClient {
private readonly discoveryApi: DiscoveryApi;
private readonly tokenManager?: TokenManager;

constructor(opts: { discoveryApi: DiscoveryApi }) {
constructor(opts: {
discoveryApi: DiscoveryApi;
tokenManager?: TokenManager;
}) {
this.discoveryApi = opts.discoveryApi;
}

private async fetch<T = any>(input: string): Promise<T> {
const baseApiUrl = await this.discoveryApi.getBaseUrl('announcements');

const response = await fetch(`${baseApiUrl}${input}`);
let headers = {};

if (this.tokenManager) {
const { token } = await this.tokenManager.getToken();
headers = {
Authorization: `Bearer ${token}`,
};
}

const response = await fetch(`${baseApiUrl}${input}`, headers);
if (!response.ok) {
throw await ResponseError.fromResponse(response);
}

return response.json() as Promise<T>;
}

async announcements(): Promise<Announcement[]> {
return await this.fetch<Announcement[]>('/');
async announcements({
page,
maxPerPage,
}: {
page: number;
maxPerPage: number;
}): Promise<Announcement[]> {
return this.fetch<AnnouncementsList>(
`/announcements?page=${page}&max=${maxPerPage}`,
).then(response => {
return response.results || [];
});
}
}
24 changes: 9 additions & 15 deletions plugins/announcements-backend/src/service/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,15 @@ import {
BasicPermission,
} from '@backstage/plugin-permission-common';
import {
CreateAnnouncementRequest,
CreateCategoryRequest,
UpdateAnnouncementRequest,
announcementCreatePermission,
announcementDeletePermission,
announcementUpdatePermission,
} from '@k-phoen/backstage-plugin-announcements-common';
import { AnnouncementsContext } from './announcementsContextBuilder';

interface AnnouncementRequest {
publisher: string;
category?: string;
title: string;
excerpt: string;
body: string;
}

interface CategoryRequest {
title: string;
}

export async function createRouter(
options: AnnouncementsContext,
): Promise<express.Router> {
Expand Down Expand Up @@ -112,7 +103,7 @@ export async function createRouter(

router.post(
'/announcements',
async (req: Request<{}, {}, AnnouncementRequest, {}>, res) => {
async (req: Request<{}, {}, CreateAnnouncementRequest, {}>, res) => {
if (!(await isRequestAuthorized(req, announcementCreatePermission))) {
throw new NotAllowedError('Unauthorized');
}
Expand All @@ -132,7 +123,10 @@ export async function createRouter(

router.put(
'/announcements/:id',
async (req: Request<{ id: string }, {}, AnnouncementRequest, {}>, res) => {
async (
req: Request<{ id: string }, {}, UpdateAnnouncementRequest, {}>,
res,
) => {
if (!(await isRequestAuthorized(req, announcementUpdatePermission))) {
throw new NotAllowedError('Unauthorized');
}
Expand Down Expand Up @@ -173,7 +167,7 @@ export async function createRouter(

router.post(
'/categories',
async (req: Request<{}, {}, CategoryRequest, {}>, res) => {
async (req: Request<{}, {}, CreateCategoryRequest, {}>, res) => {
const category = {
...req.body,
...{
Expand Down
3 changes: 2 additions & 1 deletion plugins/announcements-common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
"@backstage/cli": "^0.25.0"
},
"dependencies": {
"@backstage/plugin-permission-common": "^0.7.11"
"@backstage/plugin-permission-common": "^0.7.11",
"@backstage/plugin-search-common": "^1.2.9"
},
"files": [
"dist"
Expand Down
1 change: 1 addition & 0 deletions plugins/announcements-common/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './permissions';
export * from './types';
39 changes: 39 additions & 0 deletions plugins/announcements-common/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { IndexableDocument } from '@backstage/plugin-search-common';

export type Category = {
slug: string;
title: string;
};

export type Announcement = {
id: string;
category?: Category;
publisher: string;
title: string;
excerpt: string;
body: string;
created_at: string;
};

export type AnnouncementsList = {
count: number;
results: Announcement[];
};

export type IndexableAnnouncement = IndexableDocument & {
excerpt: string;
createdAt: string;
};

export type CreateAnnouncementRequest = Omit<
Announcement,
'id' | 'category' | 'created_at'
> & {
category?: string;
};

export type UpdateAnnouncementRequest = CreateAnnouncementRequest;

export type CreateCategoryRequest = {
title: string;
};
43 changes: 10 additions & 33 deletions plugins/announcements/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,16 @@ import {
} from '@backstage/core-plugin-api';
import { ResponseError } from '@backstage/errors';
import { FetchApi } from '@backstage/core-plugin-api';

const lastSeenKey = 'user_last_seen_date';

export type Category = {
slug: string;
title: string;
};

export type Announcement = {
id: string;
category?: Category;
publisher: string;
title: string;
excerpt: string;
body: string;
created_at: string;
};

export type AnnouncementsList = {
count: number;
results: Announcement[];
};

export type CreateAnnouncementRequest = Omit<
import {
Announcement,
'id' | 'category' | 'created_at'
> & {
category?: string;
};
AnnouncementsList,
Category,
CreateAnnouncementRequest,
CreateCategoryRequest,
UpdateAnnouncementRequest,
} from '@k-phoen/backstage-plugin-announcements-common';

export type CreateCategoryRequest = {
title: string;
};
const lastSeenKey = 'user_last_seen_date';

export interface AnnouncementsApi {
announcements(opts: {
Expand All @@ -53,7 +30,7 @@ export interface AnnouncementsApi {
createAnnouncement(request: CreateAnnouncementRequest): Promise<Announcement>;
updateAnnouncement(
id: string,
request: CreateAnnouncementRequest,
request: UpdateAnnouncementRequest,
): Promise<Announcement>;
deleteAnnouncementByID(id: string): Promise<void>;

Expand Down Expand Up @@ -171,7 +148,7 @@ export class DefaultAnnouncementsApi implements AnnouncementsApi {

async updateAnnouncement(
id: string,
request: CreateAnnouncementRequest,
request: UpdateAnnouncementRequest,
): Promise<Announcement> {
return this.fetch<Announcement>(`/announcements/${id}`, {
method: 'PUT',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import {
makeStyles,
TextField,
} from '@material-ui/core';
import { announcementsApiRef } from '../../api';
import { Autocomplete } from '@material-ui/lab';
import { useAsync } from 'react-use';
import {
Announcement,
announcementsApiRef,
CreateAnnouncementRequest,
} from '../../api';
import { Autocomplete } from '@material-ui/lab';
import { useAsync } from 'react-use';
} from '@k-phoen/backstage-plugin-announcements-common';

const useStyles = makeStyles(theme => ({
formRoot: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ import {
} from '@backstage/plugin-catalog-react';
import Alert from '@material-ui/lab/Alert';
import { Grid } from '@material-ui/core';
import { Announcement, announcementsApiRef } from '../../api';
import { announcementsApiRef } from '../../api';
import { announcementViewRouteRef, rootRouteRef } from '../../routes';
import { Announcement } from '@k-phoen/backstage-plugin-announcements-common';

const AnnouncementDetails = ({
announcement,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
makeStyles,
} from '@material-ui/core';
import RecordVoiceOverIcon from '@material-ui/icons/RecordVoiceOver';
import { IndexableAnnouncement } from '@k-phoen/backstage-plugin-announcements-common';

const useStyles = makeStyles({
createdAt: {
Expand All @@ -30,10 +31,6 @@ const useStyles = makeStyles({
},
});

export type IndexableAnnouncement = IndexableDocument & {
createdAt: string;
};

export interface AnnouncementSearchResultProps {
result?: IndexableDocument;
highlight?: ResultHighlight;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
announcementCreatePermission,
announcementUpdatePermission,
announcementDeletePermission,
Announcement,
} from '@k-phoen/backstage-plugin-announcements-common';
import { DateTime } from 'luxon';
import {
Expand Down Expand Up @@ -42,7 +43,7 @@ import {
announcementViewRouteRef,
rootRouteRef,
} from '../../routes';
import { Announcement, announcementsApiRef } from '../../api';
import { announcementsApiRef } from '../../api';
import { DeleteAnnouncementDialog } from './DeleteAnnouncementDialog';
import { useDeleteAnnouncementDialogState } from './useDeleteAnnouncementDialogState';
import { Pagination } from '@material-ui/lab';
Expand Down
Loading

0 comments on commit 977c8eb

Please sign in to comment.