Conversation
Reviewer's GuideThis PR scaffolds a new Backstage frontend plugin named 'router-companion-android', providing boilerplate setup, routing, dev tooling, core components for data fetching and display, utility styling, and documentation. Sequence diagram for fetching and displaying GitHub users in ExampleFetchComponentsequenceDiagram
participant User
participant ExampleFetchComponent
participant fetchApi
participant discoveryApi
participant Table
User->>ExampleFetchComponent: Visit plugin page
ExampleFetchComponent->>discoveryApi: getBaseUrl('proxy')
discoveryApi-->>ExampleFetchComponent: Return proxy URL
ExampleFetchComponent->>fetchApi: fetch(proxyURL + '/github/users')
fetchApi-->>ExampleFetchComponent: Return response
ExampleFetchComponent->>ExampleFetchComponent: Parse response as JSON
ExampleFetchComponent->>Table: Render user data
Table-->>User: Display GitHub users
Class diagram for new components in router-companion-android pluginclassDiagram
class ExampleComponent {
+render()
}
class ExampleFetchComponent {
+render()
}
class DenseTable {
+render(users)
}
class ExampleComponentIcon {
+render()
}
class Router {
+render()
}
ExampleComponent --> ExampleFetchComponent
ExampleFetchComponent --> DenseTable
Router --> ExampleComponent
ExampleComponentIcon <|-- Router
ExampleComponentIcon <|-- ExampleComponent
Class diagram for plugin setup and routingclassDiagram
class plugin {
+id: string
+routes: object
}
class PluginPage {
+component: Router
+mountPoint: rootRouteRef
}
class PluginIcon {
+component: ExampleComponentIcon
}
plugin --> PluginPage
plugin --> PluginIcon
PluginPage --> Router
PluginIcon --> ExampleComponentIcon
Class diagram for utility function getChipStyleclassDiagram
class getChipStyle {
+getChipStyle(theme: Theme): object
}
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey there - I've reviewed your changes - here's some feedback:
- There’s a mix of MUI v4 (@material-ui/core/icons) and MUI v5 (@mui/icons‐material) imports—please consolidate to a single major version to avoid styling/runtime conflicts.
- The repository.url in your package.json is set to "[object Object]"—replace it with the actual Git URL and update catalog-info.yaml if necessary.
- Avoid using
anyin ExampleFetchComponent and define proper interfaces for the fetched GitHub user shape, or remap fields with a clearly typed DTO to improve type safety.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- There’s a mix of MUI v4 (@material-ui/core/icons) and MUI v5 (@mui/icons‐material) imports—please consolidate to a single major version to avoid styling/runtime conflicts.
- The repository.url in your package.json is set to "[object Object]"—replace it with the actual Git URL and update catalog-info.yaml if necessary.
- Avoid using `any` in ExampleFetchComponent and define proper interfaces for the fetched GitHub user shape, or remap fields with a clearly typed DTO to improve type safety.
## Individual Comments
### Comment 1
<location> `plugins/router-companion-android/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx:20` </location>
<code_context>
+ type: string;
+};
+
+export const DenseTable = ({ users }: any) => {
+ const theme = useTheme();
+ const chipStyle = getChipStyle(theme);
</code_context>
<issue_to_address>
Consider using a more specific type for the 'users' prop.
Defining 'users' as 'User[]' instead of 'any' will improve type safety and maintainability.
Suggested implementation:
```typescript
export const DenseTable = ({ users }: { users: User[] }) => {
```
```typescript
const data = users.map((user: User) => {
```
</issue_to_address>
### Comment 2
<location> `plugins/router-companion-android/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx:31` </location>
<code_context>
+
+ const data = users.map((user: any) => {
+ return {
+ id: user.login,
+ githubId: (
+ <Chip
+ style={chipStyle}
+ avatar={<Avatar alt={user.login} src={user.avatar_url} />}
+ label={user.login}
+ variant="outlined"
+ />
+ ),
+ repoUrl: user.html_url,
+ type: user.type,
+ };
+ });
</code_context>
<issue_to_address>
The 'id' field is set but not used in the Table columns.
If 'id' is not needed, remove it from the mapped data to simplify the structure.
</issue_to_address>
<suggested_fix>
<<<<<<< SEARCH
const data = users.map((user: any) => {
return {
id: user.login,
githubId: (
<Chip
style={chipStyle}
avatar={<Avatar alt={user.login} src={user.avatar_url} />}
label={user.login}
variant="outlined"
/>
),
repoUrl: user.html_url,
type: user.type,
};
});
=======
const data = users.map((user: any) => {
return {
githubId: (
<Chip
style={chipStyle}
avatar={<Avatar alt={user.login} src={user.avatar_url} />}
label={user.login}
variant="outlined"
/>
),
repoUrl: user.html_url,
type: user.type,
};
});
>>>>>>> REPLACE
</suggested_fix>
### Comment 3
<location> `plugins/router-companion-android/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx:62` </location>
<code_context>
+
+ const { value, loading, error } = useAsync(async (): Promise<User[]> => {
+ const res = await fetchApi.fetch(`${await proxyURL}/github/users`);
+ if (!res.ok) throw new Error(res.statusText || "Error occured");
+ const users = await res.json();
+ return users;
</code_context>
<issue_to_address>
Typo in error message: 'Error occured' should be 'Error occurred'.
Fixing this typo enhances clarity and maintains a professional user experience.
</issue_to_address>
<suggested_fix>
<<<<<<< SEARCH
if (!res.ok) throw new Error(res.statusText || "Error occured");
=======
if (!res.ok) throw new Error(res.statusText || "Error occurred");
>>>>>>> REPLACE
</suggested_fix>
### Comment 4
<location> `plugins/router-companion-android/README.md:59` </location>
<code_context>
+ );
+ ```
+
+4. Set-up the Backstage Proxy. Follow https://backstage.io/docs/integrations/github/locations#token-scopes for creating personal access token
+
+ ```yaml title="app-config.yaml"
</code_context>
<issue_to_address>
Change 'Set-up' to 'Set up' for correct usage.
Use 'Set up' instead of 'Set-up' for grammatical accuracy.
</issue_to_address>
<suggested_fix>
<<<<<<< SEARCH
4. Set-up the Backstage Proxy. Follow https://backstage.io/docs/integrations/github/locations#token-scopes for creating personal access token
=======
4. Set up the Backstage Proxy. Follow https://backstage.io/docs/integrations/github/locations#token-scopes for creating personal access token
>>>>>>> REPLACE
</suggested_fix>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| type: string; | ||
| }; | ||
|
|
||
| export const DenseTable = ({ users }: any) => { |
There was a problem hiding this comment.
suggestion: Consider using a more specific type for the 'users' prop.
Defining 'users' as 'User[]' instead of 'any' will improve type safety and maintainability.
Suggested implementation:
export const DenseTable = ({ users }: { users: User[] }) => { const data = users.map((user: User) => {| const data = users.map((user: any) => { | ||
| return { | ||
| id: user.login, | ||
| githubId: ( | ||
| <Chip | ||
| style={chipStyle} | ||
| avatar={<Avatar alt={user.login} src={user.avatar_url} />} | ||
| label={user.login} | ||
| variant="outlined" | ||
| /> | ||
| ), | ||
| repoUrl: user.html_url, | ||
| type: user.type, | ||
| }; | ||
| }); |
There was a problem hiding this comment.
suggestion: The 'id' field is set but not used in the Table columns.
If 'id' is not needed, remove it from the mapped data to simplify the structure.
| const data = users.map((user: any) => { | |
| return { | |
| id: user.login, | |
| githubId: ( | |
| <Chip | |
| style={chipStyle} | |
| avatar={<Avatar alt={user.login} src={user.avatar_url} />} | |
| label={user.login} | |
| variant="outlined" | |
| /> | |
| ), | |
| repoUrl: user.html_url, | |
| type: user.type, | |
| }; | |
| }); | |
| const data = users.map((user: any) => { | |
| return { | |
| githubId: ( | |
| <Chip | |
| style={chipStyle} | |
| avatar={<Avatar alt={user.login} src={user.avatar_url} />} | |
| label={user.login} | |
| variant="outlined" | |
| /> | |
| ), | |
| repoUrl: user.html_url, | |
| type: user.type, | |
| }; | |
| }); |
|
|
||
| const { value, loading, error } = useAsync(async (): Promise<User[]> => { | ||
| const res = await fetchApi.fetch(`${await proxyURL}/github/users`); | ||
| if (!res.ok) throw new Error(res.statusText || "Error occured"); |
There was a problem hiding this comment.
nitpick (typo): Typo in error message: 'Error occured' should be 'Error occurred'.
Fixing this typo enhances clarity and maintains a professional user experience.
| if (!res.ok) throw new Error(res.statusText || "Error occured"); | |
| if (!res.ok) throw new Error(res.statusText || "Error occurred"); |
| ); | ||
| ``` | ||
|
|
||
| 4. Set-up the Backstage Proxy. Follow https://backstage.io/docs/integrations/github/locations#token-scopes for creating personal access token |
There was a problem hiding this comment.
suggestion (typo): Change 'Set-up' to 'Set up' for correct usage.
Use 'Set up' instead of 'Set-up' for grammatical accuracy.
| 4. Set-up the Backstage Proxy. Follow https://backstage.io/docs/integrations/github/locations#token-scopes for creating personal access token | |
| 4. Set up the Backstage Proxy. Follow https://backstage.io/docs/integrations/github/locations#token-scopes for creating personal access token |
| const users = await res.json(); | ||
| return users; |
There was a problem hiding this comment.
suggestion (code-quality): Inline variable that is immediately returned (inline-immediately-returned-variable)
| const users = await res.json(); | |
| return users; | |
| return await res.json(); | |
Explanation
Something that we often see in people's code is assigning to a result variableand then immediately returning it.
Returning the result directly shortens the code and removes an unnecessary
variable, reducing the mental load of reading the function.
Where intermediate variables can be useful is if they then get used as a
parameter or a condition, and the name can act like a comment on what the
variable represents. In the case where you're returning it from a function, the
function name is there to tell you what the result is, so the variable name
is unnecessary.
|
Just for testing Backstage/RHDH |
This pull request creates the skeleton for your frontend plugin
Summary by Sourcery
Scaffold a new Frontend plugin “router-companion-android” including plugin registration, routing, sample UI components, example data fetching, docs, and development setup
New Features:
Build:
Documentation:
Tests: