@stackoverflow/backstage-plugin-stack-overflow-teams 1.5.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.
Files changed (58) hide show
  1. package/README.md +91 -0
  2. package/config.d.ts +71 -0
  3. package/dist/api/StackOverflowAPI.esm.js +125 -0
  4. package/dist/api/StackOverflowAPI.esm.js.map +1 -0
  5. package/dist/components/StackOverflow/StackOverflowMe.esm.js +110 -0
  6. package/dist/components/StackOverflow/StackOverflowMe.esm.js.map +1 -0
  7. package/dist/components/StackOverflow/StackOverflowPostQuestionModal.esm.js +406 -0
  8. package/dist/components/StackOverflow/StackOverflowPostQuestionModal.esm.js.map +1 -0
  9. package/dist/components/StackOverflow/StackOverflowPosts.esm.js +402 -0
  10. package/dist/components/StackOverflow/StackOverflowPosts.esm.js.map +1 -0
  11. package/dist/components/StackOverflow/StackOverflowSearchResultListItem.esm.js +147 -0
  12. package/dist/components/StackOverflow/StackOverflowSearchResultListItem.esm.js.map +1 -0
  13. package/dist/components/StackOverflow/StackOverflowTags.esm.js +117 -0
  14. package/dist/components/StackOverflow/StackOverflowTags.esm.js.map +1 -0
  15. package/dist/components/StackOverflow/StackOverflowUsers.esm.js +193 -0
  16. package/dist/components/StackOverflow/StackOverflowUsers.esm.js.map +1 -0
  17. package/dist/components/StackOverflow/TiptapEditor.esm.js +308 -0
  18. package/dist/components/StackOverflow/TiptapEditor.esm.js.map +1 -0
  19. package/dist/components/StackOverflow/hooks/useStackOverflowData.esm.js +128 -0
  20. package/dist/components/StackOverflow/hooks/useStackOverflowData.esm.js.map +1 -0
  21. package/dist/components/StackOverflow/hooks/useStackOverflowSearch.esm.js +53 -0
  22. package/dist/components/StackOverflow/hooks/useStackOverflowSearch.esm.js.map +1 -0
  23. package/dist/components/StackOverflow/hooks/useStackOverflowStyles.esm.js +39 -0
  24. package/dist/components/StackOverflow/hooks/useStackOverflowStyles.esm.js.map +1 -0
  25. package/dist/components/StackOverflowAuth/StackAuthCallback.esm.js +47 -0
  26. package/dist/components/StackOverflowAuth/StackAuthCallback.esm.js.map +1 -0
  27. package/dist/components/StackOverflowAuth/StackAuthFailed.esm.js +35 -0
  28. package/dist/components/StackOverflowAuth/StackAuthFailed.esm.js.map +1 -0
  29. package/dist/components/StackOverflowAuth/StackAuthLoading.esm.js +20 -0
  30. package/dist/components/StackOverflowAuth/StackAuthLoading.esm.js.map +1 -0
  31. package/dist/components/StackOverflowAuth/StackAuthStart.esm.js +225 -0
  32. package/dist/components/StackOverflowAuth/StackAuthStart.esm.js.map +1 -0
  33. package/dist/components/StackOverflowAuth/StackAuthSuccess.esm.js +37 -0
  34. package/dist/components/StackOverflowAuth/StackAuthSuccess.esm.js.map +1 -0
  35. package/dist/icons/LogoutIcon.esm.js +24 -0
  36. package/dist/icons/LogoutIcon.esm.js.map +1 -0
  37. package/dist/icons/StackOverflowIcon.esm.js +25 -0
  38. package/dist/icons/StackOverflowIcon.esm.js.map +1 -0
  39. package/dist/index.d.ts +48 -0
  40. package/dist/index.esm.js +18 -0
  41. package/dist/index.esm.js.map +1 -0
  42. package/dist/package.json.esm.js +98 -0
  43. package/dist/package.json.esm.js.map +1 -0
  44. package/dist/pages/StackOverflowHub.esm.js +82 -0
  45. package/dist/pages/StackOverflowHub.esm.js.map +1 -0
  46. package/dist/pages/StackOverflowTeamsPage.esm.js +42 -0
  47. package/dist/pages/StackOverflowTeamsPage.esm.js.map +1 -0
  48. package/dist/pages/index.esm.js +3 -0
  49. package/dist/pages/index.esm.js.map +1 -0
  50. package/dist/plugin.esm.js +27 -0
  51. package/dist/plugin.esm.js.map +1 -0
  52. package/dist/routes.esm.js +8 -0
  53. package/dist/routes.esm.js.map +1 -0
  54. package/dist/utils/decodeHtml.esm.js +8 -0
  55. package/dist/utils/decodeHtml.esm.js.map +1 -0
  56. package/dist/utils/getTimeAgo.esm.js +30 -0
  57. package/dist/utils/getTimeAgo.esm.js.map +1 -0
  58. package/package.json +88 -0
@@ -0,0 +1,308 @@
1
+ import React from 'react';
2
+ import { useEditor, EditorContent } from '@tiptap/react';
3
+ import StarterKit from '@tiptap/starter-kit';
4
+ import { Placeholder } from '@tiptap/extensions';
5
+ import Box from '@mui/material/Box';
6
+ import Paper from '@mui/material/Paper';
7
+ import Toolbar from '@mui/material/Toolbar';
8
+ import Divider from '@mui/material/Divider';
9
+ import Typography from '@mui/material/Typography';
10
+ import { useTheme } from '@mui/material/styles';
11
+ import { FormatBold, FormatItalic, FormatUnderlined, Code, FormatListBulleted, FormatListNumbered, FormatQuote, FormatClear } from '@mui/icons-material';
12
+ import Button from '@mui/material/Button';
13
+
14
+ const TiptapEditor = ({
15
+ content = "",
16
+ onUpdate,
17
+ placeholder = "Start typing...",
18
+ editable = true,
19
+ error = false,
20
+ onFocus,
21
+ modifierKey = { symbol: "Ctrl", text: "Ctrl" }
22
+ }) => {
23
+ const theme = useTheme();
24
+ const editor = useEditor({
25
+ extensions: [
26
+ StarterKit,
27
+ Placeholder.configure({
28
+ placeholder,
29
+ emptyEditorClass: "is-editor-empty"
30
+ })
31
+ ],
32
+ shouldRerenderOnTransaction: true,
33
+ content,
34
+ editable,
35
+ onUpdate: ({ editor: tiptapEditor }) => {
36
+ if (onUpdate) {
37
+ onUpdate(tiptapEditor.getHTML());
38
+ }
39
+ },
40
+ onFocus: () => {
41
+ if (onFocus) {
42
+ onFocus();
43
+ }
44
+ }
45
+ });
46
+ if (!editor) {
47
+ return null;
48
+ }
49
+ const ToolbarButton = ({
50
+ onClick,
51
+ isActive,
52
+ disabled,
53
+ children,
54
+ title
55
+ }) => /* @__PURE__ */ React.createElement(
56
+ Button,
57
+ {
58
+ onMouseDown: (e) => {
59
+ e.preventDefault();
60
+ },
61
+ onClick,
62
+ disabled,
63
+ variant: isActive ? "contained" : "text",
64
+ title,
65
+ size: "small"
66
+ },
67
+ children
68
+ );
69
+ return /* @__PURE__ */ React.createElement(
70
+ Paper,
71
+ {
72
+ variant: "outlined",
73
+ sx: {
74
+ border: error ? `2px solid ${theme.palette.error.main}` : `1px solid ${theme.palette.divider}`,
75
+ borderRadius: 2,
76
+ overflow: "hidden",
77
+ "&:focus-within": {
78
+ borderColor: theme.palette.primary.main,
79
+ borderWidth: "2px"
80
+ },
81
+ transition: "border-color 0.2s ease-in-out"
82
+ }
83
+ },
84
+ /* @__PURE__ */ React.createElement(
85
+ Toolbar,
86
+ {
87
+ sx: {
88
+ backgroundColor: theme.palette.background.default,
89
+ borderBottom: `1px solid ${theme.palette.divider}`,
90
+ minHeight: 48,
91
+ flexWrap: "wrap",
92
+ py: 0.5,
93
+ px: 1,
94
+ alignItems: "center"
95
+ }
96
+ },
97
+ /* @__PURE__ */ React.createElement(
98
+ ToolbarButton,
99
+ {
100
+ onClick: () => editor.chain().focus().toggleBold().run(),
101
+ isActive: editor.isActive("bold"),
102
+ title: `Bold (${modifierKey.text}+B)`
103
+ },
104
+ /* @__PURE__ */ React.createElement(FormatBold, { fontSize: "medium" })
105
+ ),
106
+ /* @__PURE__ */ React.createElement(
107
+ ToolbarButton,
108
+ {
109
+ onClick: () => editor.chain().focus().toggleItalic().run(),
110
+ isActive: editor.isActive("italic"),
111
+ title: `Italic (${modifierKey.text}+I)`
112
+ },
113
+ /* @__PURE__ */ React.createElement(FormatItalic, { fontSize: "medium" })
114
+ ),
115
+ /* @__PURE__ */ React.createElement(
116
+ ToolbarButton,
117
+ {
118
+ onClick: () => editor.chain().focus().toggleUnderline().run(),
119
+ isActive: editor.isActive("underline"),
120
+ title: `Underline (${modifierKey.text}+U)`
121
+ },
122
+ /* @__PURE__ */ React.createElement(FormatUnderlined, { fontSize: "medium" })
123
+ ),
124
+ /* @__PURE__ */ React.createElement(
125
+ ToolbarButton,
126
+ {
127
+ onClick: () => editor.chain().focus().toggleCode().run(),
128
+ isActive: editor.isActive("code"),
129
+ title: `Inline Code (${modifierKey.text}+E)`
130
+ },
131
+ /* @__PURE__ */ React.createElement(Code, { fontSize: "medium" })
132
+ ),
133
+ /* @__PURE__ */ React.createElement(Divider, { orientation: "vertical", flexItem: true, sx: { mx: 0.5, height: 24, alignSelf: "center" } }),
134
+ /* @__PURE__ */ React.createElement(
135
+ ToolbarButton,
136
+ {
137
+ onClick: () => editor.chain().focus().toggleHeading({ level: 1 }).run(),
138
+ isActive: editor.isActive("heading", { level: 1 }),
139
+ title: `Heading 1 (${modifierKey.text}+Alt+1)`
140
+ },
141
+ /* @__PURE__ */ React.createElement(Typography, { component: "span", fontWeight: "bold", fontSize: "11px" }, "H1")
142
+ ),
143
+ /* @__PURE__ */ React.createElement(
144
+ ToolbarButton,
145
+ {
146
+ onClick: () => editor.chain().focus().toggleHeading({ level: 2 }).run(),
147
+ isActive: editor.isActive("heading", { level: 2 }),
148
+ title: `Heading 2 (${modifierKey.text}+Alt+2)`
149
+ },
150
+ /* @__PURE__ */ React.createElement(Typography, { component: "span", fontWeight: "bold", fontSize: "11px" }, "H2")
151
+ ),
152
+ /* @__PURE__ */ React.createElement(
153
+ ToolbarButton,
154
+ {
155
+ onClick: () => editor.chain().focus().toggleHeading({ level: 3 }).run(),
156
+ isActive: editor.isActive("heading", { level: 3 }),
157
+ title: `Heading 3 (${modifierKey.text}+Alt+3)`
158
+ },
159
+ /* @__PURE__ */ React.createElement(Typography, { component: "span", fontWeight: "bold", fontSize: "11px" }, "H3")
160
+ ),
161
+ /* @__PURE__ */ React.createElement(Divider, { orientation: "vertical", flexItem: true, sx: { mx: 0.5, height: 24, alignSelf: "center" } }),
162
+ /* @__PURE__ */ React.createElement(
163
+ ToolbarButton,
164
+ {
165
+ onClick: () => editor.chain().focus().toggleBulletList().run(),
166
+ isActive: editor.isActive("bulletList"),
167
+ title: "Bullet List"
168
+ },
169
+ /* @__PURE__ */ React.createElement(FormatListBulleted, { fontSize: "medium" })
170
+ ),
171
+ /* @__PURE__ */ React.createElement(
172
+ ToolbarButton,
173
+ {
174
+ onClick: () => editor.chain().focus().toggleOrderedList().run(),
175
+ isActive: editor.isActive("orderedList"),
176
+ title: "Numbered List"
177
+ },
178
+ /* @__PURE__ */ React.createElement(FormatListNumbered, { fontSize: "medium" })
179
+ ),
180
+ /* @__PURE__ */ React.createElement(
181
+ ToolbarButton,
182
+ {
183
+ onClick: () => editor.chain().focus().toggleBlockquote().run(),
184
+ isActive: editor.isActive("blockquote"),
185
+ title: "Quote"
186
+ },
187
+ /* @__PURE__ */ React.createElement(FormatQuote, { fontSize: "medium" })
188
+ ),
189
+ /* @__PURE__ */ React.createElement(
190
+ ToolbarButton,
191
+ {
192
+ onClick: () => editor.chain().focus().toggleCodeBlock().run(),
193
+ isActive: editor.isActive("codeBlock"),
194
+ title: "Code Block"
195
+ },
196
+ /* @__PURE__ */ React.createElement(Typography, { variant: "caption", component: "span", fontWeight: "bold", fontSize: "10px" }, "</>")
197
+ ),
198
+ /* @__PURE__ */ React.createElement(Divider, { orientation: "vertical", flexItem: true, sx: { mx: 0.5, height: 24, alignSelf: "center" } }),
199
+ /* @__PURE__ */ React.createElement(
200
+ ToolbarButton,
201
+ {
202
+ onClick: () => editor.chain().focus().clearNodes().unsetAllMarks().run(),
203
+ title: "Clear Format"
204
+ },
205
+ /* @__PURE__ */ React.createElement(FormatClear, { fontSize: "medium" })
206
+ ),
207
+ /* @__PURE__ */ React.createElement(Box, { sx: { flexGrow: 1 } })
208
+ ),
209
+ /* @__PURE__ */ React.createElement(
210
+ Box,
211
+ {
212
+ onClick: () => editor.chain().focus().run(),
213
+ sx: {
214
+ p: 2,
215
+ minHeight: 200,
216
+ cursor: "text",
217
+ backgroundColor: theme.palette.background.paper,
218
+ "& .ProseMirror": {
219
+ outline: "none",
220
+ minHeight: 168,
221
+ fontFamily: theme.typography.body1.fontFamily,
222
+ fontSize: theme.typography.body1.fontSize,
223
+ lineHeight: theme.typography.body1.lineHeight,
224
+ color: theme.palette.text.primary,
225
+ "& p": {
226
+ margin: theme.spacing(0, 0, 1, 0),
227
+ "&:last-child": {
228
+ marginBottom: 0
229
+ }
230
+ },
231
+ "& h1, & h2, & h3, & h4, & h5, & h6": {
232
+ fontWeight: theme.typography.fontWeightBold,
233
+ marginTop: theme.spacing(2),
234
+ marginBottom: theme.spacing(1),
235
+ "&:first-of-type": {
236
+ marginTop: 0
237
+ }
238
+ },
239
+ "& h1": {
240
+ fontSize: theme.typography.h4.fontSize
241
+ },
242
+ "& h2": {
243
+ fontSize: theme.typography.h5.fontSize
244
+ },
245
+ "& h3": {
246
+ fontSize: theme.typography.h6.fontSize
247
+ },
248
+ "& ul, & ol": {
249
+ paddingLeft: theme.spacing(3),
250
+ margin: theme.spacing(1, 0)
251
+ },
252
+ "& li": {
253
+ marginBottom: theme.spacing(0.5)
254
+ },
255
+ "& blockquote": {
256
+ borderLeft: `4px solid ${theme.palette.primary.main}`,
257
+ paddingLeft: theme.spacing(2),
258
+ margin: theme.spacing(2, 0),
259
+ backgroundColor: theme.palette.mode === "dark" ? theme.palette.grey[700] : theme.palette.grey[50],
260
+ borderRadius: theme.spacing(0, 1, 1, 0)
261
+ },
262
+ "& code": {
263
+ backgroundColor: theme.palette.mode === "dark" ? theme.palette.grey[700] : theme.palette.grey[100],
264
+ padding: theme.spacing(0.5, 0.75),
265
+ borderRadius: theme.shape.borderRadius,
266
+ fontFamily: 'Monaco, "Roboto Mono", monospace',
267
+ fontSize: "0.875em",
268
+ color: theme.palette.mode === "dark" ? theme.palette.primary.light : theme.palette.primary.dark
269
+ },
270
+ "& pre": {
271
+ backgroundColor: theme.palette.mode === "dark" ? theme.palette.grey[700] : theme.palette.grey[100],
272
+ padding: theme.spacing(2),
273
+ overflow: "auto",
274
+ margin: theme.spacing(2, 0),
275
+ border: `1px solid ${theme.palette.divider}`,
276
+ "& code": {
277
+ backgroundColor: "transparent",
278
+ padding: 0,
279
+ color: theme.palette.text.primary
280
+ }
281
+ },
282
+ "& strong": {
283
+ fontWeight: theme.typography.fontWeightBold
284
+ },
285
+ "& em": {
286
+ fontStyle: "italic"
287
+ },
288
+ "& u": {
289
+ textDecoration: "underline"
290
+ },
291
+ "& p.is-editor-empty:first-of-type::before": {
292
+ content: "attr(data-placeholder)",
293
+ float: "left",
294
+ color: theme.palette.text.disabled,
295
+ pointerEvents: "none",
296
+ height: 0,
297
+ fontStyle: "italic"
298
+ }
299
+ }
300
+ }
301
+ },
302
+ /* @__PURE__ */ React.createElement(EditorContent, { editor })
303
+ )
304
+ );
305
+ };
306
+
307
+ export { TiptapEditor };
308
+ //# sourceMappingURL=TiptapEditor.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TiptapEditor.esm.js","sources":["../../../src/components/StackOverflow/TiptapEditor.tsx"],"sourcesContent":["import React from 'react';\nimport { useEditor, EditorContent } from '@tiptap/react';\nimport StarterKit from '@tiptap/starter-kit';\nimport { Placeholder } from '@tiptap/extensions';\nimport Box from '@mui/material/Box';\nimport Paper from '@mui/material/Paper';\nimport Toolbar from '@mui/material/Toolbar';\nimport Divider from '@mui/material/Divider';\nimport Typography from '@mui/material/Typography';\nimport { useTheme } from '@mui/material/styles';\nimport {\n FormatBold,\n FormatItalic,\n FormatUnderlined,\n FormatListBulleted,\n FormatListNumbered,\n FormatQuote,\n Code,\n FormatClear,\n // Undo,\n // Redo\n} from '@mui/icons-material';\nimport Button from '@mui/material/Button';\n\ninterface TiptapEditorProps {\n content?: string;\n onUpdate?: (content: string) => void;\n placeholder?: string;\n editable?: boolean;\n error?: boolean;\n onFocus?: () => void;\n modifierKey?: {\n symbol: string,\n text: string\n }\n}\n\nexport const TiptapEditor: React.FC<TiptapEditorProps> = ({\n content = '',\n onUpdate,\n placeholder = 'Start typing...',\n editable = true,\n error = false,\n onFocus,\n modifierKey = { symbol: 'Ctrl', text: 'Ctrl' }\n}) => {\n const theme = useTheme();\n \n const editor = useEditor({\n extensions: [\n StarterKit,\n Placeholder.configure({\n placeholder,\n emptyEditorClass: 'is-editor-empty',\n }),\n ],\n shouldRerenderOnTransaction: true,\n content,\n editable,\n onUpdate: ({ editor: tiptapEditor }) => {\n if (onUpdate) {\n onUpdate(tiptapEditor.getHTML());\n }\n },\n onFocus: () => {\n if (onFocus) {\n onFocus();\n }\n },\n });\n\n if (!editor) {\n return null;\n }\n\n const ToolbarButton = ({ \n onClick, \n isActive, \n disabled, \n children, \n title \n }: {\n onClick: () => void;\n isActive?: boolean;\n disabled?: boolean;\n children: React.ReactNode;\n title: string;\n }) => (\n <Button\n onMouseDown={(e) => {\n e.preventDefault()\n }}\n onClick={onClick}\n disabled={disabled}\n variant={isActive ? 'contained' : 'text'}\n title={title}\n size=\"small\"\n >\n {children}\n </Button>\n );\n\n return (\n <Paper \n variant=\"outlined\"\n sx={{\n border: error ? `2px solid ${theme.palette.error.main}` : `1px solid ${theme.palette.divider}`,\n borderRadius: 2,\n overflow: 'hidden',\n '&:focus-within': {\n borderColor: theme.palette.primary.main,\n borderWidth: '2px',\n },\n transition: 'border-color 0.2s ease-in-out',\n }}\n >\n <Toolbar \n sx={{ \n backgroundColor: theme.palette.background.default,\n borderBottom: `1px solid ${theme.palette.divider}`,\n minHeight: 48,\n flexWrap: 'wrap',\n py: 0.5,\n px: 1,\n alignItems: 'center',\n }}\n >\n {/* Text Formatting Group */}\n <ToolbarButton\n onClick={() => editor.chain().focus().toggleBold().run()}\n isActive={editor.isActive('bold')}\n title={`Bold (${modifierKey.text}+B)`}\n >\n <FormatBold fontSize=\"medium\" />\n </ToolbarButton>\n \n <ToolbarButton\n onClick={() => editor.chain().focus().toggleItalic().run()}\n isActive={editor.isActive('italic')}\n title={`Italic (${modifierKey.text}+I)`}\n >\n <FormatItalic fontSize=\"medium\" />\n </ToolbarButton>\n \n <ToolbarButton\n onClick={() => editor.chain().focus().toggleUnderline().run()}\n isActive={editor.isActive('underline')}\n title={`Underline (${modifierKey.text}+U)`}\n >\n <FormatUnderlined fontSize=\"medium\" />\n </ToolbarButton>\n \n <ToolbarButton\n onClick={() => editor.chain().focus().toggleCode().run()}\n isActive={editor.isActive('code')}\n title={`Inline Code (${modifierKey.text}+E)`}\n >\n <Code fontSize=\"medium\" />\n </ToolbarButton>\n\n <Divider orientation=\"vertical\" flexItem sx={{ mx: 0.5, height: 24, alignSelf: 'center' }} />\n\n {/* Headings Group */}\n <ToolbarButton\n onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}\n isActive={editor.isActive('heading', { level: 1 })}\n title={`Heading 1 (${modifierKey.text}+Alt+1)`}\n >\n <Typography component=\"span\" fontWeight=\"bold\" fontSize=\"11px\">\n H1\n </Typography>\n </ToolbarButton>\n \n <ToolbarButton\n onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}\n isActive={editor.isActive('heading', { level: 2 })}\n title={`Heading 2 (${modifierKey.text}+Alt+2)`}\n >\n <Typography component=\"span\" fontWeight=\"bold\" fontSize=\"11px\">\n H2\n </Typography>\n </ToolbarButton>\n \n <ToolbarButton\n onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}\n isActive={editor.isActive('heading', { level: 3 })}\n title={`Heading 3 (${modifierKey.text}+Alt+3)`}\n >\n <Typography component=\"span\" fontWeight=\"bold\" fontSize=\"11px\">\n H3\n </Typography>\n </ToolbarButton>\n\n <Divider orientation=\"vertical\" flexItem sx={{ mx: 0.5, height: 24, alignSelf: 'center' }} />\n\n {/* Lists and Blocks Group */}\n <ToolbarButton\n onClick={() => editor.chain().focus().toggleBulletList().run()}\n isActive={editor.isActive('bulletList')}\n title=\"Bullet List\"\n >\n <FormatListBulleted fontSize=\"medium\" />\n </ToolbarButton>\n \n <ToolbarButton\n onClick={() => editor.chain().focus().toggleOrderedList().run()}\n isActive={editor.isActive('orderedList')}\n title=\"Numbered List\"\n >\n <FormatListNumbered fontSize=\"medium\" />\n </ToolbarButton>\n \n <ToolbarButton\n onClick={() => editor.chain().focus().toggleBlockquote().run()}\n isActive={editor.isActive('blockquote')}\n title=\"Quote\"\n >\n <FormatQuote fontSize=\"medium\" />\n </ToolbarButton>\n \n <ToolbarButton\n onClick={() => editor.chain().focus().toggleCodeBlock().run()}\n isActive={editor.isActive('codeBlock')}\n title=\"Code Block\"\n >\n <Typography variant=\"caption\" component=\"span\" fontWeight=\"bold\" fontSize=\"10px\">\n {'</>'}\n </Typography>\n </ToolbarButton>\n\n <Divider orientation=\"vertical\" flexItem sx={{ mx: 0.5, height: 24, alignSelf: 'center' }} />\n\n {/* Utility Group */}\n <ToolbarButton\n onClick={() => editor.chain().focus().clearNodes().unsetAllMarks().run()}\n title=\"Clear Format\"\n >\n <FormatClear fontSize=\"medium\" />\n </ToolbarButton>\n\n <Box sx={{ flexGrow: 1 }} />\n\n {/* History Group */}\n {/* <ToolbarButton\n onClick={() => editor.chain().focus().undo().run()}\n disabled={!editor.can().undo()}\n title={`Undo (${modifierKey.text}+Z)`}\n >\n <Undo fontSize=\"medium\" />\n </ToolbarButton>\n \n <ToolbarButton\n onClick={() => editor.chain().focus().redo().run()}\n disabled={!editor.can().redo()}\n title={`Redo (${modifierKey.text}+Y)`}\n >\n <Redo fontSize=\"medium\" />\n </ToolbarButton> */}\n </Toolbar>\n \n <Box \n onClick={() => editor.chain().focus().run()}\n sx={{\n p: 2,\n minHeight: 200,\n cursor: 'text',\n backgroundColor: theme.palette.background.paper,\n '& .ProseMirror': {\n outline: 'none',\n minHeight: 168,\n fontFamily: theme.typography.body1.fontFamily,\n fontSize: theme.typography.body1.fontSize,\n lineHeight: theme.typography.body1.lineHeight,\n color: theme.palette.text.primary,\n '& p': {\n margin: theme.spacing(0, 0, 1, 0),\n '&:last-child': {\n marginBottom: 0,\n },\n },\n '& h1, & h2, & h3, & h4, & h5, & h6': {\n fontWeight: theme.typography.fontWeightBold,\n marginTop: theme.spacing(2),\n marginBottom: theme.spacing(1),\n '&:first-of-type': {\n marginTop: 0,\n },\n },\n '& h1': {\n fontSize: theme.typography.h4.fontSize,\n },\n '& h2': {\n fontSize: theme.typography.h5.fontSize,\n },\n '& h3': {\n fontSize: theme.typography.h6.fontSize,\n },\n '& ul, & ol': {\n paddingLeft: theme.spacing(3),\n margin: theme.spacing(1, 0),\n },\n '& li': {\n marginBottom: theme.spacing(0.5),\n },\n '& blockquote': {\n borderLeft: `4px solid ${theme.palette.primary.main}`,\n paddingLeft: theme.spacing(2),\n margin: theme.spacing(2, 0),\n backgroundColor: theme.palette.mode === 'dark' \n ? theme.palette.grey[700] \n : theme.palette.grey[50],\n borderRadius: theme.spacing(0, 1, 1, 0),\n },\n '& code': {\n backgroundColor: theme.palette.mode === 'dark' \n ? theme.palette.grey[700] \n : theme.palette.grey[100],\n padding: theme.spacing(0.5, 0.75),\n borderRadius: theme.shape.borderRadius,\n fontFamily: 'Monaco, \"Roboto Mono\", monospace',\n fontSize: '0.875em',\n color: theme.palette.mode === 'dark'\n ? theme.palette.primary.light\n : theme.palette.primary.dark,\n },\n '& pre': {\n backgroundColor: theme.palette.mode === 'dark' \n ? theme.palette.grey[700] \n : theme.palette.grey[100],\n padding: theme.spacing(2),\n overflow: 'auto',\n margin: theme.spacing(2, 0),\n border: `1px solid ${theme.palette.divider}`,\n '& code': {\n backgroundColor: 'transparent',\n padding: 0,\n color: theme.palette.text.primary,\n },\n },\n '& strong': {\n fontWeight: theme.typography.fontWeightBold,\n },\n '& em': {\n fontStyle: 'italic',\n },\n '& u': {\n textDecoration: 'underline',\n },\n '& p.is-editor-empty:first-of-type::before': {\n content: 'attr(data-placeholder)',\n float: 'left',\n color: theme.palette.text.disabled,\n pointerEvents: 'none',\n height: 0,\n fontStyle: 'italic',\n },\n },\n }}\n >\n <EditorContent editor={editor} />\n </Box>\n </Paper>\n );\n};"],"names":[],"mappings":"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"}
@@ -0,0 +1,128 @@
1
+ import { useState, useCallback } from 'react';
2
+ import { useApi } from '@backstage/core-plugin-api';
3
+ import { stackoverflowteamsApiRef } from '../../../api/StackOverflowAPI.esm.js';
4
+
5
+ const useStackOverflowData = (type, options) => {
6
+ const stackOverflowTeamsApi = useApi(stackoverflowteamsApiRef);
7
+ const [data, setData] = useState(null);
8
+ const [loading, setLoading] = useState(true);
9
+ const [error, setError] = useState(null);
10
+ const fetchData = useCallback(async () => {
11
+ setLoading(true);
12
+ setError(null);
13
+ try {
14
+ let response;
15
+ switch (type) {
16
+ case "questions":
17
+ response = await stackOverflowTeamsApi.getQuestions(options?.questionFilters);
18
+ setData({
19
+ questions: response.items,
20
+ totalPages: response.totalPages,
21
+ totalCount: response.totalCount,
22
+ currentPage: response.page
23
+ });
24
+ break;
25
+ case "tags":
26
+ response = await stackOverflowTeamsApi.getTags(options?.tagSearch);
27
+ setData({ tags: response.items });
28
+ break;
29
+ case "users":
30
+ response = await stackOverflowTeamsApi.getUsers();
31
+ setData({ users: response.items });
32
+ break;
33
+ default:
34
+ throw new Error(`Invalid data type: ${type}`);
35
+ }
36
+ } catch (e) {
37
+ setError(e instanceof Error ? e : new Error(String(e)));
38
+ } finally {
39
+ setLoading(false);
40
+ }
41
+ }, [type, stackOverflowTeamsApi, options?.questionFilters, options?.tagSearch]);
42
+ const fetchActiveQuestions = useCallback(async (page) => {
43
+ if (type !== "questions") return;
44
+ setLoading(true);
45
+ setError(null);
46
+ try {
47
+ const response = await stackOverflowTeamsApi.getActiveQuestions(page);
48
+ setData({
49
+ questions: response.items,
50
+ totalPages: response.totalPages,
51
+ totalCount: response.totalCount,
52
+ currentPage: response.page
53
+ });
54
+ } catch (e) {
55
+ setError(e instanceof Error ? e : new Error(String(e)));
56
+ } finally {
57
+ setLoading(false);
58
+ }
59
+ }, [type, stackOverflowTeamsApi]);
60
+ const fetchNewestQuestions = useCallback(async (page) => {
61
+ if (type !== "questions") return;
62
+ setLoading(true);
63
+ setError(null);
64
+ try {
65
+ const response = await stackOverflowTeamsApi.getNewestQuestions(page);
66
+ setData({
67
+ questions: response.items,
68
+ totalPages: response.totalPages,
69
+ totalCount: response.totalCount,
70
+ currentPage: response.page
71
+ });
72
+ } catch (e) {
73
+ setError(e instanceof Error ? e : new Error(String(e)));
74
+ } finally {
75
+ setLoading(false);
76
+ }
77
+ }, [type, stackOverflowTeamsApi]);
78
+ const fetchTopScoredQuestions = useCallback(async (page) => {
79
+ if (type !== "questions") return;
80
+ setLoading(true);
81
+ setError(null);
82
+ try {
83
+ const response = await stackOverflowTeamsApi.getTopScoredQuestions(page);
84
+ setData({
85
+ questions: response.items,
86
+ totalPages: response.totalPages,
87
+ totalCount: response.totalCount,
88
+ currentPage: response.page
89
+ });
90
+ } catch (e) {
91
+ setError(e instanceof Error ? e : new Error(String(e)));
92
+ } finally {
93
+ setLoading(false);
94
+ }
95
+ }, [type, stackOverflowTeamsApi]);
96
+ const fetchUnansweredQuestions = useCallback(async (page) => {
97
+ if (type !== "questions") return;
98
+ setLoading(true);
99
+ setError(null);
100
+ try {
101
+ const response = await stackOverflowTeamsApi.getUnansweredQuestions(page);
102
+ setData({
103
+ questions: response.items,
104
+ totalPages: response.totalPages,
105
+ totalCount: response.totalCount,
106
+ currentPage: response.page
107
+ });
108
+ } catch (e) {
109
+ setError(e instanceof Error ? e : new Error(String(e)));
110
+ } finally {
111
+ setLoading(false);
112
+ }
113
+ }, [type, stackOverflowTeamsApi]);
114
+ return {
115
+ data,
116
+ loading,
117
+ error,
118
+ fetchData,
119
+ // Convenience methods for questions
120
+ fetchActiveQuestions,
121
+ fetchNewestQuestions,
122
+ fetchTopScoredQuestions,
123
+ fetchUnansweredQuestions
124
+ };
125
+ };
126
+
127
+ export { useStackOverflowData };
128
+ //# sourceMappingURL=useStackOverflowData.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStackOverflowData.esm.js","sources":["../../../../src/components/StackOverflow/hooks/useStackOverflowData.ts"],"sourcesContent":["import { useState, useCallback } from 'react';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { Question, stackoverflowteamsApiRef, Tag, User } from '../../../api/';\n\ntype PostType = 'questions' | 'tags' | 'users' \n\ninterface QuestionFilters {\n sort?: 'activity' | 'creation' | 'score';\n order?: 'asc' | 'desc';\n isAnswered?: boolean;\n page?: number;\n pageSize?: number;\n}\n\ninterface StackOverflowData {\n questions?: Question[];\n tags?: Tag[];\n users?: User[];\n totalPages?: number;\n totalCount?: number;\n currentPage?: number;\n}\n\ninterface UseStackOverflowDataOptions {\n questionFilters?: QuestionFilters;\n tagSearch?: string;\n}\n\nexport const useStackOverflowData = (type: PostType, options?: UseStackOverflowDataOptions) => {\n const stackOverflowTeamsApi = useApi(stackoverflowteamsApiRef);\n const [data, setData] = useState<StackOverflowData | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetchData = useCallback(async () => {\n setLoading(true);\n setError(null);\n \n try {\n let response;\n switch (type) {\n case 'questions':\n response = await stackOverflowTeamsApi.getQuestions(options?.questionFilters);\n setData({ \n questions: response.items,\n totalPages: response.totalPages,\n totalCount: response.totalCount,\n currentPage: response.page\n });\n break;\n case 'tags':\n response = await stackOverflowTeamsApi.getTags(options?.tagSearch);\n setData({ tags: response.items });\n break;\n case 'users':\n response = await stackOverflowTeamsApi.getUsers();\n setData({ users: response.items });\n break;\n default:\n throw new Error(`Invalid data type: ${type}`);\n }\n } catch (e) {\n setError(e instanceof Error ? e : new Error(String(e)));\n } finally {\n setLoading(false);\n }\n }, [type, stackOverflowTeamsApi, options?.questionFilters, options?.tagSearch]);\n\n // Convenience methods for questions\n const fetchActiveQuestions = useCallback(async (page?: number) => {\n if (type !== 'questions') return;\n setLoading(true);\n setError(null);\n \n try {\n const response = await stackOverflowTeamsApi.getActiveQuestions(page);\n setData({ \n questions: response.items,\n totalPages: response.totalPages,\n totalCount: response.totalCount,\n currentPage: response.page\n });\n } catch (e) {\n setError(e instanceof Error ? e : new Error(String(e)));\n } finally {\n setLoading(false);\n }\n }, [type, stackOverflowTeamsApi]);\n\n const fetchNewestQuestions = useCallback(async (page?: number) => {\n if (type !== 'questions') return;\n setLoading(true);\n setError(null);\n \n try {\n const response = await stackOverflowTeamsApi.getNewestQuestions(page);\n setData({ \n questions: response.items,\n totalPages: response.totalPages,\n totalCount: response.totalCount,\n currentPage: response.page\n });\n } catch (e) {\n setError(e instanceof Error ? e : new Error(String(e)));\n } finally {\n setLoading(false);\n }\n }, [type, stackOverflowTeamsApi]);\n\n const fetchTopScoredQuestions = useCallback(async (page?: number) => {\n if (type !== 'questions') return;\n setLoading(true);\n setError(null);\n \n try {\n const response = await stackOverflowTeamsApi.getTopScoredQuestions(page);\n setData({ \n questions: response.items,\n totalPages: response.totalPages,\n totalCount: response.totalCount,\n currentPage: response.page\n });\n } catch (e) {\n setError(e instanceof Error ? e : new Error(String(e)));\n } finally {\n setLoading(false);\n }\n }, [type, stackOverflowTeamsApi]);\n\n const fetchUnansweredQuestions = useCallback(async (page?: number) => {\n if (type !== 'questions') return;\n setLoading(true);\n setError(null);\n \n try {\n const response = await stackOverflowTeamsApi.getUnansweredQuestions(page);\n setData({ \n questions: response.items,\n totalPages: response.totalPages,\n totalCount: response.totalCount,\n currentPage: response.page\n });\n } catch (e) {\n setError(e instanceof Error ? e : new Error(String(e)));\n } finally {\n setLoading(false);\n }\n }, [type, stackOverflowTeamsApi]);\n\n return { \n data, \n loading, \n error, \n fetchData,\n // Convenience methods for questions\n fetchActiveQuestions,\n fetchNewestQuestions, \n fetchTopScoredQuestions,\n fetchUnansweredQuestions\n };\n};"],"names":[],"mappings":";;;;AA4Ba,MAAA,oBAAA,GAAuB,CAAC,IAAA,EAAgB,OAA0C,KAAA;AAC7F,EAAM,MAAA,qBAAA,GAAwB,OAAO,wBAAwB,CAAA;AAC7D,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAmC,IAAI,CAAA;AAC/D,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,IAAI,CAAA;AAC3C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAuB,IAAI,CAAA;AAErD,EAAM,MAAA,SAAA,GAAY,YAAY,YAAY;AACxC,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,QAAA,CAAS,IAAI,CAAA;AAEb,IAAI,IAAA;AACF,MAAI,IAAA,QAAA;AACJ,MAAA,QAAQ,IAAM;AAAA,QACZ,KAAK,WAAA;AACH,UAAA,QAAA,GAAW,MAAM,qBAAA,CAAsB,YAAa,CAAA,OAAA,EAAS,eAAe,CAAA;AAC5E,UAAQ,OAAA,CAAA;AAAA,YACN,WAAW,QAAS,CAAA,KAAA;AAAA,YACpB,YAAY,QAAS,CAAA,UAAA;AAAA,YACrB,YAAY,QAAS,CAAA,UAAA;AAAA,YACrB,aAAa,QAAS,CAAA;AAAA,WACvB,CAAA;AACD,UAAA;AAAA,QACF,KAAK,MAAA;AACH,UAAA,QAAA,GAAW,MAAM,qBAAA,CAAsB,OAAQ,CAAA,OAAA,EAAS,SAAS,CAAA;AACjE,UAAA,OAAA,CAAQ,EAAE,IAAA,EAAM,QAAS,CAAA,KAAA,EAAO,CAAA;AAChC,UAAA;AAAA,QACF,KAAK,OAAA;AACH,UAAW,QAAA,GAAA,MAAM,sBAAsB,QAAS,EAAA;AAChD,UAAA,OAAA,CAAQ,EAAE,KAAA,EAAO,QAAS,CAAA,KAAA,EAAO,CAAA;AACjC,UAAA;AAAA,QACF;AACE,UAAA,MAAM,IAAI,KAAA,CAAM,CAAsB,mBAAA,EAAA,IAAI,CAAE,CAAA,CAAA;AAAA;AAChD,aACO,CAAG,EAAA;AACV,MAAS,QAAA,CAAA,CAAA,YAAa,QAAQ,CAAI,GAAA,IAAI,MAAM,MAAO,CAAA,CAAC,CAAC,CAAC,CAAA;AAAA,KACtD,SAAA;AACA,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA;AAClB,GACF,EAAG,CAAC,IAAM,EAAA,qBAAA,EAAuB,SAAS,eAAiB,EAAA,OAAA,EAAS,SAAS,CAAC,CAAA;AAG9E,EAAM,MAAA,oBAAA,GAAuB,WAAY,CAAA,OAAO,IAAkB,KAAA;AAChE,IAAA,IAAI,SAAS,WAAa,EAAA;AAC1B,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,QAAA,CAAS,IAAI,CAAA;AAEb,IAAI,IAAA;AACF,MAAA,MAAM,QAAW,GAAA,MAAM,qBAAsB,CAAA,kBAAA,CAAmB,IAAI,CAAA;AACpE,MAAQ,OAAA,CAAA;AAAA,QACN,WAAW,QAAS,CAAA,KAAA;AAAA,QACpB,YAAY,QAAS,CAAA,UAAA;AAAA,QACrB,YAAY,QAAS,CAAA,UAAA;AAAA,QACrB,aAAa,QAAS,CAAA;AAAA,OACvB,CAAA;AAAA,aACM,CAAG,EAAA;AACV,MAAS,QAAA,CAAA,CAAA,YAAa,QAAQ,CAAI,GAAA,IAAI,MAAM,MAAO,CAAA,CAAC,CAAC,CAAC,CAAA;AAAA,KACtD,SAAA;AACA,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA;AAClB,GACC,EAAA,CAAC,IAAM,EAAA,qBAAqB,CAAC,CAAA;AAEhC,EAAM,MAAA,oBAAA,GAAuB,WAAY,CAAA,OAAO,IAAkB,KAAA;AAChE,IAAA,IAAI,SAAS,WAAa,EAAA;AAC1B,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,QAAA,CAAS,IAAI,CAAA;AAEb,IAAI,IAAA;AACF,MAAA,MAAM,QAAW,GAAA,MAAM,qBAAsB,CAAA,kBAAA,CAAmB,IAAI,CAAA;AACpE,MAAQ,OAAA,CAAA;AAAA,QACN,WAAW,QAAS,CAAA,KAAA;AAAA,QACpB,YAAY,QAAS,CAAA,UAAA;AAAA,QACrB,YAAY,QAAS,CAAA,UAAA;AAAA,QACrB,aAAa,QAAS,CAAA;AAAA,OACvB,CAAA;AAAA,aACM,CAAG,EAAA;AACV,MAAS,QAAA,CAAA,CAAA,YAAa,QAAQ,CAAI,GAAA,IAAI,MAAM,MAAO,CAAA,CAAC,CAAC,CAAC,CAAA;AAAA,KACtD,SAAA;AACA,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA;AAClB,GACC,EAAA,CAAC,IAAM,EAAA,qBAAqB,CAAC,CAAA;AAEhC,EAAM,MAAA,uBAAA,GAA0B,WAAY,CAAA,OAAO,IAAkB,KAAA;AACnE,IAAA,IAAI,SAAS,WAAa,EAAA;AAC1B,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,QAAA,CAAS,IAAI,CAAA;AAEb,IAAI,IAAA;AACF,MAAA,MAAM,QAAW,GAAA,MAAM,qBAAsB,CAAA,qBAAA,CAAsB,IAAI,CAAA;AACvE,MAAQ,OAAA,CAAA;AAAA,QACN,WAAW,QAAS,CAAA,KAAA;AAAA,QACpB,YAAY,QAAS,CAAA,UAAA;AAAA,QACrB,YAAY,QAAS,CAAA,UAAA;AAAA,QACrB,aAAa,QAAS,CAAA;AAAA,OACvB,CAAA;AAAA,aACM,CAAG,EAAA;AACV,MAAS,QAAA,CAAA,CAAA,YAAa,QAAQ,CAAI,GAAA,IAAI,MAAM,MAAO,CAAA,CAAC,CAAC,CAAC,CAAA;AAAA,KACtD,SAAA;AACA,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA;AAClB,GACC,EAAA,CAAC,IAAM,EAAA,qBAAqB,CAAC,CAAA;AAEhC,EAAM,MAAA,wBAAA,GAA2B,WAAY,CAAA,OAAO,IAAkB,KAAA;AACpE,IAAA,IAAI,SAAS,WAAa,EAAA;AAC1B,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,QAAA,CAAS,IAAI,CAAA;AAEb,IAAI,IAAA;AACF,MAAA,MAAM,QAAW,GAAA,MAAM,qBAAsB,CAAA,sBAAA,CAAuB,IAAI,CAAA;AACxE,MAAQ,OAAA,CAAA;AAAA,QACN,WAAW,QAAS,CAAA,KAAA;AAAA,QACpB,YAAY,QAAS,CAAA,UAAA;AAAA,QACrB,YAAY,QAAS,CAAA,UAAA;AAAA,QACrB,aAAa,QAAS,CAAA;AAAA,OACvB,CAAA;AAAA,aACM,CAAG,EAAA;AACV,MAAS,QAAA,CAAA,CAAA,YAAa,QAAQ,CAAI,GAAA,IAAI,MAAM,MAAO,CAAA,CAAC,CAAC,CAAC,CAAA;AAAA,KACtD,SAAA;AACA,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA;AAClB,GACC,EAAA,CAAC,IAAM,EAAA,qBAAqB,CAAC,CAAA;AAEhC,EAAO,OAAA;AAAA,IACL,IAAA;AAAA,IACA,OAAA;AAAA,IACA,KAAA;AAAA,IACA,SAAA;AAAA;AAAA,IAEA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,uBAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
@@ -0,0 +1,53 @@
1
+ import { useApi } from '@backstage/core-plugin-api';
2
+ import { stackoverflowteamsApiRef } from '../../../api/StackOverflowAPI.esm.js';
3
+ import { useState, useCallback } from 'react';
4
+
5
+ const useStackOverflowSearch = () => {
6
+ const stackOverflowTeamsApi = useApi(stackoverflowteamsApiRef);
7
+ const [searchData, setSearchData] = useState(null);
8
+ const [loading, setLoading] = useState(false);
9
+ const [error, setError] = useState(null);
10
+ const search = useCallback(async (query, page) => {
11
+ if (!query.trim()) {
12
+ setSearchData(null);
13
+ setError(null);
14
+ return;
15
+ }
16
+ setLoading(true);
17
+ setError(null);
18
+ try {
19
+ const response = await stackOverflowTeamsApi.search(query, page);
20
+ setSearchData({
21
+ items: response.items,
22
+ totalCount: response.totalCount,
23
+ totalPages: response.totalPages,
24
+ page: response.page,
25
+ pageSize: response.pageSize
26
+ });
27
+ } catch (e) {
28
+ setError(e instanceof Error ? e : new Error(String(e)));
29
+ setSearchData(null);
30
+ } finally {
31
+ setLoading(false);
32
+ }
33
+ }, [stackOverflowTeamsApi]);
34
+ const clearSearch = useCallback(() => {
35
+ setSearchData(null);
36
+ setError(null);
37
+ }, []);
38
+ return {
39
+ searchData,
40
+ loading,
41
+ error,
42
+ search,
43
+ clearSearch,
44
+ // Convenience getters
45
+ hasResults: !!searchData?.items.length,
46
+ totalPages: searchData?.totalPages || 0,
47
+ currentPage: searchData?.page || 1,
48
+ totalCount: searchData?.totalCount
49
+ };
50
+ };
51
+
52
+ export { useStackOverflowSearch };
53
+ //# sourceMappingURL=useStackOverflowSearch.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStackOverflowSearch.esm.js","sources":["../../../../src/components/StackOverflow/hooks/useStackOverflowSearch.ts"],"sourcesContent":["import { useApi } from \"@backstage/core-plugin-api\";\nimport { stackoverflowteamsApiRef } from \"../../../api/StackOverflowAPI\";\nimport { useCallback, useState } from \"react\";\nimport { PaginatedResponse } from \"../../../types\";\n\ninterface SearchData {\n items: any[];\n totalCount: number;\n totalPages: number;\n page: number;\n pageSize: number;\n}\n\nexport const useStackOverflowSearch = () => {\n const stackOverflowTeamsApi = useApi(stackoverflowteamsApiRef);\n const [searchData, setSearchData] = useState<SearchData | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const search = useCallback(async (query: string, page?: number) => {\n if (!query.trim()) {\n setSearchData(null);\n setError(null);\n return;\n }\n\n setLoading(true);\n setError(null);\n\n try {\n const response: PaginatedResponse<any> = await stackOverflowTeamsApi.search(query, page);\n setSearchData({\n items: response.items,\n totalCount: response.totalCount,\n totalPages: response.totalPages,\n page: response.page,\n pageSize: response.pageSize,\n });\n } catch (e) {\n setError(e instanceof Error ? e : new Error(String(e)));\n setSearchData(null);\n } finally {\n setLoading(false);\n }\n }, [stackOverflowTeamsApi]);\n\n const clearSearch = useCallback(() => {\n setSearchData(null);\n setError(null);\n }, []);\n\n return { \n searchData, \n loading, \n error, \n search, \n clearSearch,\n // Convenience getters\n hasResults: !!searchData?.items.length,\n totalPages: searchData?.totalPages || 0,\n currentPage: searchData?.page || 1,\n totalCount: searchData?.totalCount,\n };\n};"],"names":[],"mappings":";;;;AAaO,MAAM,yBAAyB,MAAM;AAC1C,EAAM,MAAA,qBAAA,GAAwB,OAAO,wBAAwB,CAAA;AAC7D,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAA4B,IAAI,CAAA;AACpE,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAuB,IAAI,CAAA;AAErD,EAAA,MAAM,MAAS,GAAA,WAAA,CAAY,OAAO,KAAA,EAAe,IAAkB,KAAA;AACjE,IAAI,IAAA,CAAC,KAAM,CAAA,IAAA,EAAQ,EAAA;AACjB,MAAA,aAAA,CAAc,IAAI,CAAA;AAClB,MAAA,QAAA,CAAS,IAAI,CAAA;AACb,MAAA;AAAA;AAGF,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,QAAA,CAAS,IAAI,CAAA;AAEb,IAAI,IAAA;AACF,MAAA,MAAM,QAAmC,GAAA,MAAM,qBAAsB,CAAA,MAAA,CAAO,OAAO,IAAI,CAAA;AACvF,MAAc,aAAA,CAAA;AAAA,QACZ,OAAO,QAAS,CAAA,KAAA;AAAA,QAChB,YAAY,QAAS,CAAA,UAAA;AAAA,QACrB,YAAY,QAAS,CAAA,UAAA;AAAA,QACrB,MAAM,QAAS,CAAA,IAAA;AAAA,QACf,UAAU,QAAS,CAAA;AAAA,OACpB,CAAA;AAAA,aACM,CAAG,EAAA;AACV,MAAS,QAAA,CAAA,CAAA,YAAa,QAAQ,CAAI,GAAA,IAAI,MAAM,MAAO,CAAA,CAAC,CAAC,CAAC,CAAA;AACtD,MAAA,aAAA,CAAc,IAAI,CAAA;AAAA,KAClB,SAAA;AACA,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA;AAClB,GACF,EAAG,CAAC,qBAAqB,CAAC,CAAA;AAE1B,EAAM,MAAA,WAAA,GAAc,YAAY,MAAM;AACpC,IAAA,aAAA,CAAc,IAAI,CAAA;AAClB,IAAA,QAAA,CAAS,IAAI,CAAA;AAAA,GACf,EAAG,EAAE,CAAA;AAEL,EAAO,OAAA;AAAA,IACL,UAAA;AAAA,IACA,OAAA;AAAA,IACA,KAAA;AAAA,IACA,MAAA;AAAA,IACA,WAAA;AAAA;AAAA,IAEA,UAAY,EAAA,CAAC,CAAC,UAAA,EAAY,KAAM,CAAA,MAAA;AAAA,IAChC,UAAA,EAAY,YAAY,UAAc,IAAA,CAAA;AAAA,IACtC,WAAA,EAAa,YAAY,IAAQ,IAAA,CAAA;AAAA,IACjC,YAAY,UAAY,EAAA;AAAA,GAC1B;AACF;;;;"}
@@ -0,0 +1,39 @@
1
+ import { makeStyles } from '@material-ui/core/styles';
2
+
3
+ const useStackOverflowStyles = makeStyles((theme) => ({
4
+ title: {
5
+ color: theme.palette.type === "dark" ? "#4CA8FF" : "#0077CC",
6
+ // Brighter blue in dark mode
7
+ fontWeight: "bold"
8
+ },
9
+ unanswered: {
10
+ backgroundColor: theme.palette.type === "dark" ? "#3B2D1F" : "#FFF4E5",
11
+ // Darker orange for dark mode
12
+ borderRadius: "4px",
13
+ padding: "4px 8px"
14
+ },
15
+ answered: {
16
+ backgroundColor: theme.palette.type === "dark" ? "#1E4620" : "#E3FCEF",
17
+ // Darker green for dark mode
18
+ borderRadius: "4px",
19
+ padding: "4px 8px"
20
+ },
21
+ button: {
22
+ backgroundColor: "#F48024",
23
+ // Stack Overflow orange
24
+ color: "#fff",
25
+ "&:hover": {
26
+ backgroundColor: theme.palette.type === "dark" ? "#C15C17" : "#D4691E"
27
+ }
28
+ },
29
+ tableRow: {
30
+ backgroundColor: theme.palette.background.paper,
31
+ "&:hover": {
32
+ backgroundColor: theme.palette.type === "dark" ? theme.palette.action.hover : "#F5F5F5"
33
+ // Light gray hover effect in light mode
34
+ }
35
+ }
36
+ }));
37
+
38
+ export { useStackOverflowStyles };
39
+ //# sourceMappingURL=useStackOverflowStyles.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStackOverflowStyles.esm.js","sources":["../../../../src/components/StackOverflow/hooks/useStackOverflowStyles.ts"],"sourcesContent":["import { makeStyles, Theme } from '@material-ui/core/styles';\n\n/**\n * Reusable styles for Stack Overflow-themed components with dark mode support\n */\nexport const useStackOverflowStyles = makeStyles((theme: Theme) => ({\n title: {\n color: theme.palette.type === 'dark' ? '#4CA8FF' : '#0077CC', // Brighter blue in dark mode\n fontWeight: 'bold',\n },\n unanswered: {\n backgroundColor: theme.palette.type === 'dark' ? '#3B2D1F' : '#FFF4E5', // Darker orange for dark mode\n borderRadius: '4px',\n padding: '4px 8px',\n },\n answered: {\n backgroundColor: theme.palette.type === 'dark' ? '#1E4620' : '#E3FCEF', // Darker green for dark mode\n borderRadius: '4px',\n padding: '4px 8px',\n },\n button: {\n backgroundColor: '#F48024', // Stack Overflow orange\n color: '#fff',\n '&:hover': {\n backgroundColor: theme.palette.type === 'dark' ? '#C15C17' : '#D4691E',\n },\n },\n tableRow: {\n backgroundColor: theme.palette.background.paper,\n '&:hover': {\n backgroundColor:\n theme.palette.type === 'dark'\n ? theme.palette.action.hover\n : '#F5F5F5', // Light gray hover effect in light mode\n },\n },\n}));\n"],"names":[],"mappings":";;AAKa,MAAA,sBAAA,GAAyB,UAAW,CAAA,CAAC,KAAkB,MAAA;AAAA,EAClE,KAAO,EAAA;AAAA,IACL,KAAO,EAAA,KAAA,CAAM,OAAQ,CAAA,IAAA,KAAS,SAAS,SAAY,GAAA,SAAA;AAAA;AAAA,IACnD,UAAY,EAAA;AAAA,GACd;AAAA,EACA,UAAY,EAAA;AAAA,IACV,eAAiB,EAAA,KAAA,CAAM,OAAQ,CAAA,IAAA,KAAS,SAAS,SAAY,GAAA,SAAA;AAAA;AAAA,IAC7D,YAAc,EAAA,KAAA;AAAA,IACd,OAAS,EAAA;AAAA,GACX;AAAA,EACA,QAAU,EAAA;AAAA,IACR,eAAiB,EAAA,KAAA,CAAM,OAAQ,CAAA,IAAA,KAAS,SAAS,SAAY,GAAA,SAAA;AAAA;AAAA,IAC7D,YAAc,EAAA,KAAA;AAAA,IACd,OAAS,EAAA;AAAA,GACX;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,eAAiB,EAAA,SAAA;AAAA;AAAA,IACjB,KAAO,EAAA,MAAA;AAAA,IACP,SAAW,EAAA;AAAA,MACT,eAAiB,EAAA,KAAA,CAAM,OAAQ,CAAA,IAAA,KAAS,SAAS,SAAY,GAAA;AAAA;AAC/D,GACF;AAAA,EACA,QAAU,EAAA;AAAA,IACR,eAAA,EAAiB,KAAM,CAAA,OAAA,CAAQ,UAAW,CAAA,KAAA;AAAA,IAC1C,SAAW,EAAA;AAAA,MACT,eAAA,EACE,MAAM,OAAQ,CAAA,IAAA,KAAS,SACnB,KAAM,CAAA,OAAA,CAAQ,OAAO,KACrB,GAAA;AAAA;AAAA;AACR;AAEJ,CAAE,CAAA;;;;"}
@@ -0,0 +1,47 @@
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 { useLocation } from 'react-router-dom';
5
+ import { StackAuthSuccess } from './StackAuthSuccess.esm.js';
6
+ import { StackAuthLoading } from './StackAuthLoading.esm.js';
7
+ import { StackAuthFailed } from './StackAuthFailed.esm.js';
8
+
9
+ const StackOverflowCallback = () => {
10
+ const stackOverflowTeamsApi = useApi(stackoverflowteamsApiRef);
11
+ const location = useLocation();
12
+ const [status, setStatus] = useState("loading");
13
+ useEffect(() => {
14
+ const handleCallback = async () => {
15
+ const queryParams = new URLSearchParams(location.search);
16
+ const code = queryParams.get("code");
17
+ const state = queryParams.get("state");
18
+ const isLoggedIn = await stackOverflowTeamsApi.getAuthStatus();
19
+ if (isLoggedIn) {
20
+ setStatus("success");
21
+ return;
22
+ }
23
+ if (!code || !state) {
24
+ setStatus("error");
25
+ return;
26
+ }
27
+ try {
28
+ await stackOverflowTeamsApi.completeAuth(code, state);
29
+ setStatus("success");
30
+ window.history.replaceState({}, document.title, location.pathname);
31
+ } catch (error) {
32
+ setStatus("error");
33
+ }
34
+ };
35
+ handleCallback();
36
+ }, [location.pathname, location.search, stackOverflowTeamsApi]);
37
+ if (status === "loading") {
38
+ return /* @__PURE__ */ React.createElement(StackAuthLoading, null);
39
+ }
40
+ if (status === "success") {
41
+ return /* @__PURE__ */ React.createElement(StackAuthSuccess, null);
42
+ }
43
+ return /* @__PURE__ */ React.createElement(StackAuthFailed, null);
44
+ };
45
+
46
+ export { StackOverflowCallback };
47
+ //# sourceMappingURL=StackAuthCallback.esm.js.map