@stackoverflow/backstage-plugin-stack-overflow-teams 1.5.0 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +8 -8
  2. package/config.d.ts +7 -7
  3. package/package.json +4 -12
  4. package/dist/api/StackOverflowAPI.esm.js +0 -125
  5. package/dist/api/StackOverflowAPI.esm.js.map +0 -1
  6. package/dist/components/StackOverflow/StackOverflowMe.esm.js +0 -110
  7. package/dist/components/StackOverflow/StackOverflowMe.esm.js.map +0 -1
  8. package/dist/components/StackOverflow/StackOverflowPostQuestionModal.esm.js +0 -406
  9. package/dist/components/StackOverflow/StackOverflowPostQuestionModal.esm.js.map +0 -1
  10. package/dist/components/StackOverflow/StackOverflowPosts.esm.js +0 -402
  11. package/dist/components/StackOverflow/StackOverflowPosts.esm.js.map +0 -1
  12. package/dist/components/StackOverflow/StackOverflowSearchResultListItem.esm.js +0 -147
  13. package/dist/components/StackOverflow/StackOverflowSearchResultListItem.esm.js.map +0 -1
  14. package/dist/components/StackOverflow/StackOverflowTags.esm.js +0 -117
  15. package/dist/components/StackOverflow/StackOverflowTags.esm.js.map +0 -1
  16. package/dist/components/StackOverflow/StackOverflowUsers.esm.js +0 -193
  17. package/dist/components/StackOverflow/StackOverflowUsers.esm.js.map +0 -1
  18. package/dist/components/StackOverflow/TiptapEditor.esm.js +0 -308
  19. package/dist/components/StackOverflow/TiptapEditor.esm.js.map +0 -1
  20. package/dist/components/StackOverflow/hooks/useStackOverflowData.esm.js +0 -128
  21. package/dist/components/StackOverflow/hooks/useStackOverflowData.esm.js.map +0 -1
  22. package/dist/components/StackOverflow/hooks/useStackOverflowSearch.esm.js +0 -53
  23. package/dist/components/StackOverflow/hooks/useStackOverflowSearch.esm.js.map +0 -1
  24. package/dist/components/StackOverflow/hooks/useStackOverflowStyles.esm.js +0 -39
  25. package/dist/components/StackOverflow/hooks/useStackOverflowStyles.esm.js.map +0 -1
  26. package/dist/components/StackOverflowAuth/StackAuthCallback.esm.js +0 -47
  27. package/dist/components/StackOverflowAuth/StackAuthCallback.esm.js.map +0 -1
  28. package/dist/components/StackOverflowAuth/StackAuthFailed.esm.js +0 -35
  29. package/dist/components/StackOverflowAuth/StackAuthFailed.esm.js.map +0 -1
  30. package/dist/components/StackOverflowAuth/StackAuthLoading.esm.js +0 -20
  31. package/dist/components/StackOverflowAuth/StackAuthLoading.esm.js.map +0 -1
  32. package/dist/components/StackOverflowAuth/StackAuthStart.esm.js +0 -225
  33. package/dist/components/StackOverflowAuth/StackAuthStart.esm.js.map +0 -1
  34. package/dist/components/StackOverflowAuth/StackAuthSuccess.esm.js +0 -37
  35. package/dist/components/StackOverflowAuth/StackAuthSuccess.esm.js.map +0 -1
  36. package/dist/icons/LogoutIcon.esm.js +0 -24
  37. package/dist/icons/LogoutIcon.esm.js.map +0 -1
  38. package/dist/icons/StackOverflowIcon.esm.js +0 -25
  39. package/dist/icons/StackOverflowIcon.esm.js.map +0 -1
  40. package/dist/index.d.ts +0 -48
  41. package/dist/index.esm.js +0 -18
  42. package/dist/index.esm.js.map +0 -1
  43. package/dist/package.json.esm.js +0 -98
  44. package/dist/package.json.esm.js.map +0 -1
  45. package/dist/pages/StackOverflowHub.esm.js +0 -82
  46. package/dist/pages/StackOverflowHub.esm.js.map +0 -1
  47. package/dist/pages/StackOverflowTeamsPage.esm.js +0 -42
  48. package/dist/pages/StackOverflowTeamsPage.esm.js.map +0 -1
  49. package/dist/pages/index.esm.js +0 -3
  50. package/dist/pages/index.esm.js.map +0 -1
  51. package/dist/plugin.esm.js +0 -27
  52. package/dist/plugin.esm.js.map +0 -1
  53. package/dist/routes.esm.js +0 -8
  54. package/dist/routes.esm.js.map +0 -1
  55. package/dist/utils/decodeHtml.esm.js +0 -8
  56. package/dist/utils/decodeHtml.esm.js.map +0 -1
  57. package/dist/utils/getTimeAgo.esm.js +0 -30
  58. package/dist/utils/getTimeAgo.esm.js.map +0 -1
package/README.md CHANGED
@@ -1,14 +1,14 @@
1
- # Stack Overflow Teams Frontend Plugin
1
+ # Stack Internal Frontend Plugin
2
2
 
3
3
  This package is the frontend counterpart of the `stack-overflow-teams` plugin for Backstage.
4
4
 
5
5
  ## Areas of Responsibility
6
6
 
7
- It provides the UI and interacts with the [backend service](https://github.com/EstoesMoises/backstage-stackoverflow/tree/main/plugins/stack-overflow-teams-backend) to fetch data from your Stack Overflow Enterprise instance.
7
+ It provides the UI and interacts with the [backend service](https://github.com/EstoesMoises/backstage-stackoverflow/tree/main/plugins/stack-overflow-teams-backend) to fetch data from your Stack Internal Enterprise instance.
8
8
 
9
9
  ### Backend Dependency
10
10
 
11
- To fully utilize this plugin, you must also install and configure the corresponding **backend package** (`backstage-plugin-stack-overflow-teams-backend`) in your Backstage backend. The frontend plugin relies on the backend for API communication and authentication handling.
11
+ To fully utilize this plugin, you must also install and configure the corresponding **backend package** (`@stackoverflow/backstage-plugin-stack-overflow-teams-backend`) in your Backstage backend. The frontend plugin relies on the backend for API communication and authentication handling.
12
12
 
13
13
  ## More details
14
14
 
@@ -16,7 +16,7 @@ To fully utilize this plugin, you must also install and configure the correspond
16
16
 
17
17
  This component is a modified version of the [community plugin.](https://github.com/backstage/community-plugins/tree/main/workspaces/stack-overflow/plugins/stack-overflow/src/search/StackOverflowSearchResultListItem)
18
18
 
19
- It adds a more Stack Overflow-like interface, including additional information such as the questions' score, user role, user reputation, and timestamp.
19
+ It adds a more Stack Overflow Internal-like interface, including additional information such as the questions' score, user role, user reputation, and timestamp.
20
20
 
21
21
  ---
22
22
 
@@ -28,7 +28,7 @@ It adds a more Stack Overflow-like interface, including additional information s
28
28
 
29
29
  - **`<StackOverflowPostQuestionModal />`**
30
30
 
31
- Provides a form for users to create a new Stack Overflow question. Once submitted, an API request is executed to create the question.
31
+ Provides a form for users to create a new Stack Overflow Internal question. Once submitted, an API request is executed to create the question.
32
32
 
33
33
  This form listens to the `'openAskQuestionModal'` event. You can utilize this anywhere in your Backstage UI. To invoke the form, add the component to your UI along with a button that dispatches the event. Example:
34
34
 
@@ -44,7 +44,7 @@ It adds a more Stack Overflow-like interface, including additional information s
44
44
 
45
45
  - **`<StackOverflowQuestion />`**
46
46
 
47
- Retrieves questions from the API. Uses standard pagination, displaying only the first 30 API results.
47
+ Retrieves questions from the API. Uses API pagination to navigate all pages of questions available to the instance.
48
48
 
49
49
  - **`<StackOverflowTags />`**
50
50
 
@@ -70,7 +70,7 @@ It adds a more Stack Overflow-like interface, including additional information s
70
70
 
71
71
  - **`<StackAuthCallback />`**
72
72
 
73
- Receives the code and state from your Stack Overflow Enterprise instance as part of the OAuth process and initiates **`/callback`** in the backend.
73
+ Receives the code and state from your Stack Internal Enterprise instance as part of the OAuth process and initiates **`/callback`** in the backend.
74
74
 
75
75
  - **`<StackAuthSuccess />`**
76
76
 
@@ -88,4 +88,4 @@ It adds a more Stack Overflow-like interface, including additional information s
88
88
 
89
89
  ### API Requests
90
90
 
91
- The frontend plugin creates an API Ref for Stack Overflow for Teams, which can be found under the `/api` folder. **All API requests from the frontend are directed to Backstage's backend**.
91
+ The frontend plugin creates an API Ref for Stack Internal, which can be found under the `/api` folder. **All API requests from the frontend are directed to Backstage's backend**.
package/config.d.ts CHANGED
@@ -16,34 +16,34 @@
16
16
 
17
17
  export interface Config {
18
18
  /**
19
- * Configuration options for the stack overflow for teams frontend plugin.
19
+ * Configuration options for the Stack Internal frontend plugin.
20
20
  *
21
- * This configuration is shared with the backstage-plugin-stack-overflow-teams-backend and backstage-stack-overflow-teams-collator
21
+ * This configuration is shared with the @stackoverflow/backstage-plugin-stack-overflow-teams-backend and @stackoverflow/backstage-stack-overflow-teams-collator
22
22
  */
23
23
  stackoverflow?: {
24
24
  /**
25
- * The base url of the Stack Overflow API used for the plugin
25
+ * The base url of the Stack Overflow Internal API used for the plugin
26
26
  */
27
27
  baseUrl: string;
28
28
 
29
29
  /**
30
- * The API Access Token to authenticate to Stack Overflow API Version 3
30
+ * The API Access Token to authenticate to Stack Overflow Internal API Version 3
31
31
  * @visibility secret
32
32
  */
33
33
  apiAccessToken: string;
34
34
 
35
35
  /**
36
- * The name of the team for a Stack Overflow for Teams account
36
+ * The name of the team for a Stack Internal account
37
37
  */
38
38
  teamName?: string;
39
39
 
40
40
  /**
41
- * Client Id for the OAuth Application, required to use the Stack Overflow for Teams Hub and write actions.
41
+ * Client Id for the OAuth Application, required to use the Stack Internal Hub and write actions.
42
42
  */
43
43
  clientId: number;
44
44
 
45
45
  /**
46
- * RedirectUri for the OAuth Application, required to use the Stack Overflow for Teams Hub and write actions.
46
+ * RedirectUri for the OAuth Application, required to use the Stack Internal Hub and write actions.
47
47
  *
48
48
  * This should be your Backstage application domain ending in the plugin's <StackOverflowTeamsPage /> route
49
49
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackoverflow/backstage-plugin-stack-overflow-teams",
3
- "version": "1.5.0",
3
+ "version": "1.6.1",
4
4
  "main": "dist/index.esm.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "license": "Apache-2.0",
@@ -13,8 +13,8 @@
13
13
  "role": "frontend-plugin",
14
14
  "pluginId": "stack-overflow-teams",
15
15
  "pluginPackages": [
16
- "backstage-plugin-stack-overflow-teams",
17
- "backstage-plugin-stack-overflow-teams-backend"
16
+ "@stackoverflow/backstage-plugin-stack-overflow-teams",
17
+ "@stackoverflow/backstage-plugin-stack-overflow-teams-backend"
18
18
  ]
19
19
  },
20
20
  "repository": {
@@ -76,13 +76,5 @@
76
76
  "files": [
77
77
  "dist",
78
78
  "config.d.ts"
79
- ],
80
- "typesVersions": {
81
- "*": {
82
- "index": [
83
- "dist/index.d.ts"
84
- ]
85
- }
86
- },
87
- "module": "./dist/index.esm.js"
79
+ ]
88
80
  }
@@ -1,125 +0,0 @@
1
- import { createApiRef } from '@backstage/core-plugin-api';
2
-
3
- const stackoverflowteamsApiRef = createApiRef({
4
- id: "plugin.stackoverflowteams.api"
5
- });
6
- const createStackOverflowApi = (discoveryApi, fetchApi) => {
7
- const getBaseUrl = async () => discoveryApi.getBaseUrl("stack-overflow-teams");
8
- const requestAPI = async (endpoint, method = "GET", body, params) => {
9
- const baseUrl = await getBaseUrl();
10
- const queryString = params ? `?${params.join("&")}` : "";
11
- const url = `${baseUrl}/${endpoint}${queryString}`;
12
- const response = await fetchApi.fetch(url, {
13
- method,
14
- credentials: "include",
15
- headers: { "Content-Type": "application/json" },
16
- body: body ? JSON.stringify(body) : void 0
17
- });
18
- if (!response.ok) {
19
- const errorResponse = await response.json();
20
- throw new Error(errorResponse.error || `Request failed: ${response.statusText}`);
21
- }
22
- return response.json();
23
- };
24
- const buildQuestionParams = (filter) => {
25
- const params = [];
26
- if (filter?.sort) {
27
- params.push(`sort=${filter.sort}`);
28
- }
29
- if (filter?.order) {
30
- params.push(`order=${filter.order}`);
31
- }
32
- if (filter?.isAnswered !== void 0) {
33
- params.push(`isAnswered=${filter.isAnswered}`);
34
- }
35
- if (filter?.page !== void 0) {
36
- params.push(`page=${filter.page}`);
37
- }
38
- if (filter?.pageSize !== void 0) {
39
- params.push(`pageSize=${filter.pageSize}`);
40
- }
41
- return params;
42
- };
43
- return {
44
- search: (query, page) => {
45
- const body = { query };
46
- if (page !== void 0) {
47
- body.page = page;
48
- }
49
- return requestAPI("search", "POST", body);
50
- },
51
- getQuestions: (filter) => {
52
- const params = buildQuestionParams(filter);
53
- return requestAPI("questions", "GET", void 0, params.length > 0 ? params : void 0);
54
- },
55
- getTags: (search) => {
56
- const params = search ? [`search=${encodeURIComponent(search)}`] : void 0;
57
- return requestAPI("tags", "GET", void 0, params);
58
- },
59
- getUsers: () => requestAPI("users"),
60
- getMe: () => requestAPI("me"),
61
- getBaseUrl: async () => {
62
- const response = await requestAPI("baseurl");
63
- return response.SOInstance;
64
- },
65
- getTeamName: async () => {
66
- const response = await requestAPI("baseurl");
67
- return response.teamName;
68
- },
69
- postQuestion: (title, body, tags) => requestAPI("questions", "POST", { title, body, tags }),
70
- startAuth: async () => {
71
- const data = await requestAPI("auth/start");
72
- return data.authUrl;
73
- },
74
- completeAuth: async (code, state) => {
75
- await requestAPI("callback", "GET", void 0, [
76
- `code=${encodeURIComponent(code)}`,
77
- `state=${encodeURIComponent(state)}`
78
- ]);
79
- },
80
- getAuthStatus: async () => {
81
- try {
82
- await requestAPI("authStatus");
83
- return true;
84
- } catch {
85
- return false;
86
- }
87
- },
88
- logout: async () => {
89
- try {
90
- await requestAPI("logout", "POST");
91
- return true;
92
- } catch {
93
- return false;
94
- }
95
- },
96
- submitAccessToken: async (token) => {
97
- try {
98
- await requestAPI("auth/token", "POST", { accessToken: token });
99
- return true;
100
- } catch {
101
- return false;
102
- }
103
- },
104
- // Convenience methods for common filtering scenarios
105
- getActiveQuestions: (page) => {
106
- const params = buildQuestionParams({ sort: "activity", order: "desc", page });
107
- return requestAPI("questions", "GET", void 0, params);
108
- },
109
- getNewestQuestions: (page) => {
110
- const params = buildQuestionParams({ sort: "creation", order: "desc", page });
111
- return requestAPI("questions", "GET", void 0, params);
112
- },
113
- getTopScoredQuestions: (page) => {
114
- const params = buildQuestionParams({ sort: "score", order: "desc", page });
115
- return requestAPI("questions", "GET", void 0, params);
116
- },
117
- getUnansweredQuestions: (page) => {
118
- const params = buildQuestionParams({ isAnswered: false, sort: "creation", order: "desc", page });
119
- return requestAPI("questions", "GET", void 0, params);
120
- }
121
- };
122
- };
123
-
124
- export { createStackOverflowApi, stackoverflowteamsApiRef };
125
- //# sourceMappingURL=StackOverflowAPI.esm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"StackOverflowAPI.esm.js","sources":["../../src/api/StackOverflowAPI.ts"],"sourcesContent":["import {\n createApiRef,\n DiscoveryApi,\n FetchApi,\n} from '@backstage/core-plugin-api';\nimport { Question, Tag, User, PaginatedResponse } from '../api';\n\nexport const stackoverflowteamsApiRef = createApiRef<StackOverflowAPI>({\n id: 'plugin.stackoverflowteams.api',\n});\n\ntype ApiResponse<T> = PaginatedResponse<T>;\n\ninterface BaseUrlResponse {\n SOInstance: string;\n teamName: string\n}\n\n// Enhanced interface for questions filter options\ninterface QuestionsFilter {\n sort?: 'activity' | 'creation' | 'score';\n order?: 'asc' | 'desc';\n isAnswered?: boolean;\n page?: number;\n pageSize?: number;\n}\n\nexport interface StackOverflowAPI {\n search(query: string, page?: number): Promise<any>;\n getQuestions(filter?: QuestionsFilter): Promise<ApiResponse<Question>>;\n getTags(search?: string): Promise<ApiResponse<Tag>>;\n getUsers(): Promise<ApiResponse<User>>;\n getMe(): Promise<User>;\n getBaseUrl(): Promise<string>;\n getTeamName(): Promise<string>;\n postQuestion(title: string, body: string, tags: string[]): Promise<Question>;\n startAuth(): Promise<string>;\n completeAuth(code: string, state: string): Promise<void>;\n getAuthStatus: () => Promise<boolean>;\n logout: () => Promise<boolean>;\n submitAccessToken: (token: string) => Promise<boolean>;\n \n // Convenience methods for common filtering scenarios\n getActiveQuestions(page?: number): Promise<ApiResponse<Question>>;\n getNewestQuestions(page?: number): Promise<ApiResponse<Question>>;\n getTopScoredQuestions(page?: number): Promise<ApiResponse<Question>>;\n getUnansweredQuestions(page?: number): Promise<ApiResponse<Question>>;\n}\n\nexport const createStackOverflowApi = (\n discoveryApi: DiscoveryApi,\n fetchApi: FetchApi,\n): StackOverflowAPI => {\n const getBaseUrl = async () => discoveryApi.getBaseUrl('stack-overflow-teams');\n\n const requestAPI = async <T>(\n endpoint: string,\n method: 'GET' | 'POST' = 'GET',\n body?: Record<string, unknown>,\n params?: string[],\n ): Promise<T> => {\n const baseUrl = await getBaseUrl();\n const queryString = params ? `?${params.join('&')}` : '';\n const url = `${baseUrl}/${endpoint}${queryString}`;\n \n const response = await fetchApi.fetch(url, {\n method,\n credentials: 'include',\n headers: { 'Content-Type': 'application/json' },\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n const errorResponse = await response.json();\n throw new Error(errorResponse.error || `Request failed: ${response.statusText}`);\n }\n\n return response.json();\n };\n\n const buildQuestionParams = (filter?: QuestionsFilter): string[] => {\n const params: string[] = [];\n \n if (filter?.sort) {\n params.push(`sort=${filter.sort}`);\n }\n \n if (filter?.order) {\n params.push(`order=${filter.order}`);\n }\n \n if (filter?.isAnswered !== undefined) {\n params.push(`isAnswered=${filter.isAnswered}`);\n }\n \n if (filter?.page !== undefined) {\n params.push(`page=${filter.page}`);\n }\n \n if (filter?.pageSize !== undefined) {\n params.push(`pageSize=${filter.pageSize}`);\n }\n \n return params;\n };\n\n return {\n search: (query: string, page?: number) => {\n const body: { query: string; page?: number } = { query };\n if (page !== undefined) {\n body.page = page;\n }\n return requestAPI<any>('search', 'POST', body);\n },\n getQuestions: (filter?: QuestionsFilter) => {\n const params = buildQuestionParams(filter);\n return requestAPI<ApiResponse<Question>>('questions', 'GET', undefined, params.length > 0 ? params : undefined);\n },\n getTags: (search?: string) => {\n const params = search ? [`search=${encodeURIComponent(search)}`] : undefined;\n return requestAPI<ApiResponse<Tag>>('tags', 'GET', undefined, params);\n },\n getUsers: () => requestAPI<ApiResponse<User>>('users'),\n getMe: () => requestAPI<User>('me'),\n getBaseUrl: async () => {\n const response = await requestAPI<BaseUrlResponse>('baseurl');\n return response.SOInstance;\n },\n getTeamName: async () => {\n const response = await requestAPI<BaseUrlResponse>('baseurl')\n return response.teamName\n },\n postQuestion: (title: string, body: string, tags: string[]) =>\n requestAPI<Question>('questions', 'POST', { title, body, tags }),\n startAuth: async () => {\n const data = await requestAPI<{ authUrl: string }>('auth/start');\n return data.authUrl;\n },\n completeAuth: async (code: string, state: string) => {\n await requestAPI('callback', 'GET', undefined, [\n `code=${encodeURIComponent(code)}`,\n `state=${encodeURIComponent(state)}`,\n ]);\n },\n getAuthStatus: async (): Promise<boolean> => {\n try {\n await requestAPI('authStatus');\n return true;\n } catch {\n return false;\n }\n },\n logout: async (): Promise<boolean> => {\n try {\n await requestAPI('logout', 'POST');\n return true;\n } catch {\n return false;\n }\n },\n submitAccessToken: async (token: string): Promise<boolean> => {\n try {\n await requestAPI('auth/token', 'POST', { accessToken: token });\n return true;\n } catch {\n return false;\n }\n },\n\n // Convenience methods for common filtering scenarios\n getActiveQuestions: (page?: number) => {\n const params = buildQuestionParams({ sort: 'activity', order: 'desc', page });\n return requestAPI<ApiResponse<Question>>('questions', 'GET', undefined, params);\n },\n\n getNewestQuestions: (page?: number) => {\n const params = buildQuestionParams({ sort: 'creation', order: 'desc', page });\n return requestAPI<ApiResponse<Question>>('questions', 'GET', undefined, params);\n },\n\n getTopScoredQuestions: (page?: number) => {\n const params = buildQuestionParams({ sort: 'score', order: 'desc', page });\n return requestAPI<ApiResponse<Question>>('questions', 'GET', undefined, params);\n },\n\n getUnansweredQuestions: (page?: number) => {\n const params = buildQuestionParams({ isAnswered: false, sort: 'creation', order: 'desc', page });\n return requestAPI<ApiResponse<Question>>('questions', 'GET', undefined, params);\n },\n };\n};"],"names":[],"mappings":"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"}
@@ -1,110 +0,0 @@
1
- import { useApi } from '@backstage/core-plugin-api';
2
- import { stackoverflowteamsApiRef } from '../../api/StackOverflowAPI.esm.js';
3
- import React, { useState, useEffect } from 'react';
4
- import { Box, CircularProgress, Typography, Card, IconButton, CardContent, Avatar, Chip, Link } from '@mui/material';
5
- import { LogoutIcon } from '../../icons/LogoutIcon.esm.js';
6
-
7
- const StackOverflowMe = () => {
8
- const stackOverflowTeamsApi = useApi(stackoverflowteamsApiRef);
9
- const logout = async () => {
10
- try {
11
- const success = await stackOverflowTeamsApi.logout();
12
- if (success) {
13
- window.location.reload();
14
- } else {
15
- throw new Error("Logout failed.");
16
- }
17
- } catch (error2) {
18
- throw new Error("Error during logout:", error2);
19
- }
20
- };
21
- const [userData, setUserData] = useState(null);
22
- const [loading, setLoading] = useState(true);
23
- const [error, setError] = useState(null);
24
- useEffect(() => {
25
- const fetchMe = async () => {
26
- try {
27
- const data = await stackOverflowTeamsApi.getMe();
28
- setUserData(data);
29
- } catch (err) {
30
- setError("Failed to load user data");
31
- } finally {
32
- setLoading(false);
33
- }
34
- };
35
- fetchMe();
36
- }, [stackOverflowTeamsApi]);
37
- if (loading) {
38
- return /* @__PURE__ */ React.createElement(
39
- Box,
40
- {
41
- display: "flex",
42
- justifyContent: "center",
43
- alignItems: "center",
44
- width: "100%"
45
- },
46
- /* @__PURE__ */ React.createElement(CircularProgress, { color: "primary" })
47
- );
48
- }
49
- if (error) {
50
- return /* @__PURE__ */ React.createElement(
51
- Box,
52
- {
53
- display: "flex",
54
- justifyContent: "center",
55
- alignItems: "center",
56
- width: "100%"
57
- },
58
- /* @__PURE__ */ React.createElement(Typography, { color: "error" }, error)
59
- );
60
- }
61
- if (!userData) return null;
62
- return /* @__PURE__ */ React.createElement(
63
- Box,
64
- {
65
- display: "flex",
66
- justifyContent: "center",
67
- alignItems: "center",
68
- width: "100%"
69
- },
70
- /* @__PURE__ */ React.createElement(
71
- Card,
72
- {
73
- variant: "outlined",
74
- sx: {
75
- p: 3,
76
- position: "relative",
77
- boxShadow: 3
78
- }
79
- },
80
- /* @__PURE__ */ React.createElement(Box, { sx: { position: "absolute", top: 8, right: 8 } }, /* @__PURE__ */ React.createElement(
81
- IconButton,
82
- {
83
- onClick: logout
84
- },
85
- /* @__PURE__ */ React.createElement(LogoutIcon, null)
86
- )),
87
- /* @__PURE__ */ React.createElement(CardContent, { sx: { textAlign: "center" } }, /* @__PURE__ */ React.createElement(Avatar, { src: userData.avatarUrl, sx: { mx: "auto", mb: 2 } }), /* @__PURE__ */ React.createElement(Typography, { variant: "h6", fontWeight: "bold", gutterBottom: true }, userData.name), /* @__PURE__ */ React.createElement(Box, { display: "flex", justifyContent: "center", gap: 1, mb: 1 }, /* @__PURE__ */ React.createElement(
88
- Chip,
89
- {
90
- label: `Reputation: ${userData.reputation}`,
91
- size: "small",
92
- color: "primary"
93
- }
94
- ), /* @__PURE__ */ React.createElement(Chip, { label: userData.role, size: "small", variant: "outlined" })), userData.jobTitle && /* @__PURE__ */ React.createElement(Typography, { variant: "body2", fontWeight: "500", mt: 1 }, "Position: ", userData.jobTitle), /* @__PURE__ */ React.createElement(
95
- Link,
96
- {
97
- href: userData.webUrl,
98
- target: "_blank",
99
- rel: "noopener",
100
- color: "primary",
101
- sx: { display: "block", mt: 2, fontWeight: "bold" }
102
- },
103
- "View Profile"
104
- ))
105
- )
106
- );
107
- };
108
-
109
- export { StackOverflowMe };
110
- //# sourceMappingURL=StackOverflowMe.esm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"StackOverflowMe.esm.js","sources":["../../../src/components/StackOverflow/StackOverflowMe.tsx"],"sourcesContent":["import { useApi } from '@backstage/core-plugin-api';\nimport { stackoverflowteamsApiRef, User } from '../../api';\nimport { useEffect, useState } from 'react';\nimport React from 'react';\n// eslint-disable-next-line no-restricted-imports\nimport {\n Box,\n Avatar,\n Typography,\n Card,\n CardContent,\n Link,\n CircularProgress,\n Chip,\n IconButton,\n} from '@mui/material';\nimport { LogoutIcon } from '../../icons';\n\nexport const StackOverflowMe = () => {\n const stackOverflowTeamsApi = useApi(stackoverflowteamsApiRef);\n const logout = async () => {\n try {\n const success = await stackOverflowTeamsApi.logout();\n if (success) {\n window.location.reload();\n } else {\n throw new Error('Logout failed.');\n }\n } catch (error:any) {\n throw new Error('Error during logout:', error);\n }\n };\n\n const [userData, setUserData] = useState<User | null>(null);\n const [loading, setLoading] = useState<Boolean>(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const fetchMe = async () => {\n try {\n const data = await stackOverflowTeamsApi.getMe();\n setUserData(data);\n } catch (err) {\n setError('Failed to load user data');\n } finally {\n setLoading(false);\n }\n };\n\n fetchMe();\n }, [stackOverflowTeamsApi]);\n\n if (loading) {\n return (\n <Box\n display=\"flex\"\n justifyContent=\"center\"\n alignItems=\"center\"\n width=\"100%\"\n >\n <CircularProgress color=\"primary\" />\n </Box>\n );\n }\n\n if (error) {\n return (\n <Box\n display=\"flex\"\n justifyContent=\"center\"\n alignItems=\"center\"\n width=\"100%\"\n >\n <Typography color=\"error\">{error}</Typography>\n </Box>\n );\n }\n\n if (!userData) return null;\n\n return (\n <Box\n display=\"flex\"\n justifyContent=\"center\"\n alignItems=\"center\"\n width=\"100%\"\n >\n <Card\n variant=\"outlined\"\n sx={{\n p: 3,\n position: 'relative',\n boxShadow: 3,\n }}\n >\n {/* Logout Button */}\n <Box sx={{ position: 'absolute', top: 8, right: 8 }}>\n <IconButton\n \n onClick={logout}\n >\n <LogoutIcon />\n </IconButton>\n </Box>\n <CardContent sx={{ textAlign: 'center' }}>\n {/* Avatar */}\n <Avatar src={userData.avatarUrl} sx={{ mx: 'auto', mb: 2 }} />\n\n {/* User Details */}\n <Typography variant=\"h6\" fontWeight=\"bold\" gutterBottom>\n {userData.name}\n </Typography>\n\n <Box display=\"flex\" justifyContent=\"center\" gap={1} mb={1}>\n <Chip\n label={`Reputation: ${userData.reputation}`}\n size=\"small\"\n color=\"primary\"\n />\n <Chip label={userData.role} size=\"small\" variant=\"outlined\" />\n </Box>\n\n {userData.jobTitle && (\n <Typography variant=\"body2\" fontWeight=\"500\" mt={1}>\n Position: {userData.jobTitle}\n </Typography>\n )}\n\n {/* Profile Link */}\n <Link\n href={userData.webUrl}\n target=\"_blank\"\n rel=\"noopener\"\n color=\"primary\"\n sx={{ display: 'block', mt: 2, fontWeight: 'bold' }}\n >\n View Profile\n </Link>\n </CardContent>\n </Card>\n </Box>\n );\n};\n"],"names":["error"],"mappings":"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"}