@stackoverflow/backstage-plugin-stack-overflow-teams 1.5.0 → 1.6.0
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.
- package/README.md +3 -3
- package/config.d.ts +1 -1
- package/package.json +4 -12
- package/dist/api/StackOverflowAPI.esm.js +0 -125
- package/dist/api/StackOverflowAPI.esm.js.map +0 -1
- package/dist/components/StackOverflow/StackOverflowMe.esm.js +0 -110
- package/dist/components/StackOverflow/StackOverflowMe.esm.js.map +0 -1
- package/dist/components/StackOverflow/StackOverflowPostQuestionModal.esm.js +0 -406
- package/dist/components/StackOverflow/StackOverflowPostQuestionModal.esm.js.map +0 -1
- package/dist/components/StackOverflow/StackOverflowPosts.esm.js +0 -402
- package/dist/components/StackOverflow/StackOverflowPosts.esm.js.map +0 -1
- package/dist/components/StackOverflow/StackOverflowSearchResultListItem.esm.js +0 -147
- package/dist/components/StackOverflow/StackOverflowSearchResultListItem.esm.js.map +0 -1
- package/dist/components/StackOverflow/StackOverflowTags.esm.js +0 -117
- package/dist/components/StackOverflow/StackOverflowTags.esm.js.map +0 -1
- package/dist/components/StackOverflow/StackOverflowUsers.esm.js +0 -193
- package/dist/components/StackOverflow/StackOverflowUsers.esm.js.map +0 -1
- package/dist/components/StackOverflow/TiptapEditor.esm.js +0 -308
- package/dist/components/StackOverflow/TiptapEditor.esm.js.map +0 -1
- package/dist/components/StackOverflow/hooks/useStackOverflowData.esm.js +0 -128
- package/dist/components/StackOverflow/hooks/useStackOverflowData.esm.js.map +0 -1
- package/dist/components/StackOverflow/hooks/useStackOverflowSearch.esm.js +0 -53
- package/dist/components/StackOverflow/hooks/useStackOverflowSearch.esm.js.map +0 -1
- package/dist/components/StackOverflow/hooks/useStackOverflowStyles.esm.js +0 -39
- package/dist/components/StackOverflow/hooks/useStackOverflowStyles.esm.js.map +0 -1
- package/dist/components/StackOverflowAuth/StackAuthCallback.esm.js +0 -47
- package/dist/components/StackOverflowAuth/StackAuthCallback.esm.js.map +0 -1
- package/dist/components/StackOverflowAuth/StackAuthFailed.esm.js +0 -35
- package/dist/components/StackOverflowAuth/StackAuthFailed.esm.js.map +0 -1
- package/dist/components/StackOverflowAuth/StackAuthLoading.esm.js +0 -20
- package/dist/components/StackOverflowAuth/StackAuthLoading.esm.js.map +0 -1
- package/dist/components/StackOverflowAuth/StackAuthStart.esm.js +0 -225
- package/dist/components/StackOverflowAuth/StackAuthStart.esm.js.map +0 -1
- package/dist/components/StackOverflowAuth/StackAuthSuccess.esm.js +0 -37
- package/dist/components/StackOverflowAuth/StackAuthSuccess.esm.js.map +0 -1
- package/dist/icons/LogoutIcon.esm.js +0 -24
- package/dist/icons/LogoutIcon.esm.js.map +0 -1
- package/dist/icons/StackOverflowIcon.esm.js +0 -25
- package/dist/icons/StackOverflowIcon.esm.js.map +0 -1
- package/dist/index.d.ts +0 -48
- package/dist/index.esm.js +0 -18
- package/dist/index.esm.js.map +0 -1
- package/dist/package.json.esm.js +0 -98
- package/dist/package.json.esm.js.map +0 -1
- package/dist/pages/StackOverflowHub.esm.js +0 -82
- package/dist/pages/StackOverflowHub.esm.js.map +0 -1
- package/dist/pages/StackOverflowTeamsPage.esm.js +0 -42
- package/dist/pages/StackOverflowTeamsPage.esm.js.map +0 -1
- package/dist/pages/index.esm.js +0 -3
- package/dist/pages/index.esm.js.map +0 -1
- package/dist/plugin.esm.js +0 -27
- package/dist/plugin.esm.js.map +0 -1
- package/dist/routes.esm.js +0 -8
- package/dist/routes.esm.js.map +0 -1
- package/dist/utils/decodeHtml.esm.js +0 -8
- package/dist/utils/decodeHtml.esm.js.map +0 -1
- package/dist/utils/getTimeAgo.esm.js +0 -30
- package/dist/utils/getTimeAgo.esm.js.map +0 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ It provides the UI and interacts with the [backend service](https://github.com/E
|
|
|
8
8
|
|
|
9
9
|
### Backend Dependency
|
|
10
10
|
|
|
11
|
-
To fully utilize this plugin, you must also install and configure the corresponding **backend package** (
|
|
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
|
|
|
@@ -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
|
|
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
|
|
|
@@ -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 Overflow for Teams, 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
|
@@ -18,7 +18,7 @@ export interface Config {
|
|
|
18
18
|
/**
|
|
19
19
|
* Configuration options for the stack overflow for teams 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
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackoverflow/backstage-plugin-stack-overflow-teams",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
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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"}
|