eionet2-dashboard 1.4.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 (111) hide show
  1. package/.fx/configs/azure.parameters.Prod_EEA.json +15 -0
  2. package/.fx/configs/azure.parameters.dev.json +15 -0
  3. package/.fx/configs/config.Prod_EEA.json +10 -0
  4. package/.fx/configs/config.dev.json +10 -0
  5. package/.fx/configs/projectSettings.json +83 -0
  6. package/.fx/states/state.Prod_EEA.json +47 -0
  7. package/.fx/states/state.dev.json +47 -0
  8. package/.vscode/launch.json +91 -0
  9. package/.vscode/settings.json +6 -0
  10. package/.vscode/tasks.json +63 -0
  11. package/CHANGELOG.md +140 -0
  12. package/Jenkinsfile +166 -0
  13. package/LICENSE.md +9 -0
  14. package/README.md +55 -0
  15. package/api/.funcignore +11 -0
  16. package/api/extensions.csproj +11 -0
  17. package/api/getGraphData/function.json +27 -0
  18. package/api/getGraphData/index.js +147 -0
  19. package/api/host.json +11 -0
  20. package/api/package-lock.json +1546 -0
  21. package/api/package.json +17 -0
  22. package/api/proxies.json +4 -0
  23. package/package.json +25 -0
  24. package/tabs/.env.teamsfx.Prod_EEA +11 -0
  25. package/tabs/.env.teamsfx.dev +11 -0
  26. package/tabs/.eslintrc.json +48 -0
  27. package/tabs/.prettierrc +7 -0
  28. package/tabs/.stylelintrc.json +6 -0
  29. package/tabs/babel.config.js +3 -0
  30. package/tabs/package-lock.json +15564 -0
  31. package/tabs/package.json +88 -0
  32. package/tabs/public/auth-end.html +76 -0
  33. package/tabs/public/auth-start.html +178 -0
  34. package/tabs/public/deploy.png +0 -0
  35. package/tabs/public/favicon.ico +0 -0
  36. package/tabs/public/hello.png +0 -0
  37. package/tabs/public/index.html +20 -0
  38. package/tabs/public/publish.png +0 -0
  39. package/tabs/src/components/App.jsx +36 -0
  40. package/tabs/src/components/CustomColumnResizeIcon.jsx +68 -0
  41. package/tabs/src/components/CustomDrawer.jsx +51 -0
  42. package/tabs/src/components/EventDialogTitle.jsx +29 -0
  43. package/tabs/src/components/HtmlBox.jsx +18 -0
  44. package/tabs/src/components/Privacy.jsx +17 -0
  45. package/tabs/src/components/ResizableGrid.jsx +44 -0
  46. package/tabs/src/components/Tab.jsx +477 -0
  47. package/tabs/src/components/Tab.scss +138 -0
  48. package/tabs/src/components/TabConfig.jsx +51 -0
  49. package/tabs/src/components/TabPanel.jsx +29 -0
  50. package/tabs/src/components/TermsOfUse.jsx +17 -0
  51. package/tabs/src/components/UnderConstruction.jsx +24 -0
  52. package/tabs/src/components/UserMenu.jsx +109 -0
  53. package/tabs/src/components/_variables.scss +10 -0
  54. package/tabs/src/components/activity/Activity.jsx +301 -0
  55. package/tabs/src/components/activity/ConsultationList.jsx +297 -0
  56. package/tabs/src/components/activity/EventList.jsx +463 -0
  57. package/tabs/src/components/activity/GroupsTags.jsx +26 -0
  58. package/tabs/src/components/activity/Reporting.jsx +13 -0
  59. package/tabs/src/components/activity/activity.scss +153 -0
  60. package/tabs/src/components/event_rating/EventRating.jsx +92 -0
  61. package/tabs/src/components/event_rating/EventRatingDialog.jsx +46 -0
  62. package/tabs/src/components/event_registration/Approval.jsx +80 -0
  63. package/tabs/src/components/event_registration/ApprovalDialog.jsx +30 -0
  64. package/tabs/src/components/event_registration/ApprovalList.jsx +62 -0
  65. package/tabs/src/components/event_registration/EventRegistration.jsx +214 -0
  66. package/tabs/src/components/lib/useData.js +33 -0
  67. package/tabs/src/components/lib/useGraph.js +39 -0
  68. package/tabs/src/components/lib/useTeamsFx.js +55 -0
  69. package/tabs/src/components/my_country/AtAGlance.jsx +151 -0
  70. package/tabs/src/components/my_country/CountryProgress.jsx +92 -0
  71. package/tabs/src/components/my_country/DataReporters.jsx +13 -0
  72. package/tabs/src/components/my_country/GroupView.jsx +54 -0
  73. package/tabs/src/components/my_country/GroupsBoard.jsx +52 -0
  74. package/tabs/src/components/my_country/IndicatorCard.jsx +60 -0
  75. package/tabs/src/components/my_country/ManagementBoard.jsx +109 -0
  76. package/tabs/src/components/my_country/MyCountry.jsx +186 -0
  77. package/tabs/src/components/my_country/ProgressGauge.jsx +125 -0
  78. package/tabs/src/components/my_country/ScientificCommittee.jsx +13 -0
  79. package/tabs/src/components/my_country/YearlyProgress.jsx +41 -0
  80. package/tabs/src/components/my_country/my_country.scss +81 -0
  81. package/tabs/src/components/publications/Publications.jsx +13 -0
  82. package/tabs/src/components/self_service/UserEdit.jsx +334 -0
  83. package/tabs/src/components/self_service/UserEdit.scss +107 -0
  84. package/tabs/src/data/apiProvider.js +153 -0
  85. package/tabs/src/data/constants.json +7 -0
  86. package/tabs/src/data/hooks/useConfiguration.js +18 -0
  87. package/tabs/src/data/icsHelper.js +38 -0
  88. package/tabs/src/data/messages.json +39 -0
  89. package/tabs/src/data/provider.js +199 -0
  90. package/tabs/src/data/selfServiceProvider.js +59 -0
  91. package/tabs/src/data/selfServiceSharepointProvider.js +68 -0
  92. package/tabs/src/data/sharepointProvider.js +729 -0
  93. package/tabs/src/data/validator.js +25 -0
  94. package/tabs/src/data/validator.test.js +9 -0
  95. package/tabs/src/index.css +16 -0
  96. package/tabs/src/index.jsx +6 -0
  97. package/tabs/src/static/images/teams-icon.svg +1 -0
  98. package/tabs/src/utils/uiHelper.js +6 -0
  99. package/templates/appPackage/aad.template.json +133 -0
  100. package/templates/appPackage/manifest.template.json +58 -0
  101. package/templates/appPackage/resources/color.png +0 -0
  102. package/templates/appPackage/resources/outline.png +0 -0
  103. package/templates/azure/config.bicep +27 -0
  104. package/templates/azure/main.bicep +20 -0
  105. package/templates/azure/provision/frontendHosting.bicep +23 -0
  106. package/templates/azure/provision/function.bicep +82 -0
  107. package/templates/azure/provision/identity.bicep +14 -0
  108. package/templates/azure/provision/simpleAuth.bicep +44 -0
  109. package/templates/azure/provision.bicep +58 -0
  110. package/templates/azure/teamsFx/function.bicep +76 -0
  111. package/templates/azure/teamsFx/simpleAuth.bicep +43 -0
@@ -0,0 +1,477 @@
1
+ import { React, useState, useEffect, useCallback } from 'react';
2
+
3
+ import { getMe } from '../data/provider';
4
+ import { useConfiguration } from '../data/hooks/useConfiguration';
5
+ import { getCountries, getCurrentParticipant, getParticipants } from '../data/sharepointProvider';
6
+
7
+ import {
8
+ Backdrop,
9
+ CircularProgress,
10
+ AppBar,
11
+ Toolbar,
12
+ MenuItem,
13
+ Typography,
14
+ Autocomplete,
15
+ Box,
16
+ TextField,
17
+ BottomNavigation,
18
+ Paper,
19
+ Button,
20
+ Dialog,
21
+ DialogTitle,
22
+ IconButton,
23
+ } from '@mui/material';
24
+ import { ThemeProvider, createTheme } from '@mui/material/styles';
25
+
26
+ import FeedIcon from '@mui/icons-material/Feed';
27
+ import OpenInNewIcon from '@mui/icons-material/OpenInNew';
28
+ import CloseIcon from '@mui/icons-material/Close';
29
+
30
+ import './Tab.scss';
31
+
32
+ import { UserMenu } from './UserMenu';
33
+ import { Activity } from './activity/Activity';
34
+ import { MyCountry } from './my_country/MyCountry';
35
+ import { Publications } from './publications/Publications';
36
+ import { UserEdit } from './self_service/UserEdit';
37
+ import { ApprovalDialog } from './event_registration/ApprovalDialog';
38
+ import { EventRatingDialog } from './event_rating/EventRatingDialog';
39
+ import { HtmlBox } from './HtmlBox';
40
+
41
+ const theme = createTheme({
42
+ palette: {
43
+ primary: {
44
+ light: '#00A390',
45
+ main: '#004B7F',
46
+ dark: '#005248',
47
+ },
48
+ secondary: {
49
+ light: '#006BB8',
50
+ main: '#007B6C',
51
+ dark: '#003052',
52
+ },
53
+ tertiary: {
54
+ light: '',
55
+ main: '#747678',
56
+ dark: '',
57
+ },
58
+ error: {
59
+ main: '#B83230',
60
+ },
61
+ warning: {
62
+ main: '#FF9933',
63
+ },
64
+ success: {
65
+ main: '#007B6C',
66
+ },
67
+ info: {
68
+ main: '#004B7F',
69
+ },
70
+ text: {
71
+ primary: '#3D5265',
72
+ },
73
+ suplementary: {
74
+ main: '#F9F9F9',
75
+ text: '#3D5265',
76
+ },
77
+ },
78
+ components: {
79
+ MuiBottomNavigationAction: {
80
+ styleOverrides: {
81
+ root: {
82
+ maxWidth: '250px',
83
+ },
84
+ },
85
+ },
86
+ MuiButton: {
87
+ styleOverrides: {
88
+ root: {
89
+ textTransform: 'none',
90
+ },
91
+ },
92
+ },
93
+ MuiDataGrid: {
94
+ styleOverrides: {
95
+ root: {
96
+ border: 'none',
97
+ },
98
+ },
99
+ },
100
+ },
101
+ });
102
+
103
+ export default function Tab() {
104
+ const configuration = useConfiguration();
105
+
106
+ const version = process.env.REACT_APP_VERSION;
107
+
108
+ const [userInfo, setUserInfo] = useState({
109
+ isAdmin: false,
110
+ isNFP: false,
111
+ isGuest: true,
112
+ country: '',
113
+ isLoaded: false,
114
+ }),
115
+ [selfInfo, setSelfInfo] = useState({}),
116
+ [userMenuData, setUserMenuData] = useState({
117
+ event2Approve: [],
118
+ events2Rate: [],
119
+ }),
120
+ [isEionetUser, setIsEionetUser] = useState(false),
121
+ [selectedCountry, setSelectedCountry] = useState(''),
122
+ [countries, setCountries] = useState([]),
123
+ [canChangeCountry, setCanChangeCountry] = useState(false),
124
+ [loading, setLoading] = useState(false),
125
+ [participant, setParticipant] = useState({}),
126
+ [selectedEvent, setSelectedEvent] = useState({}),
127
+ [approvalVisible, setApprovalVisible] = useState(false),
128
+ [ratingVisible, setRatingVisible] = useState(false),
129
+ [versionDialogOpen, setVersionDialogOpen] = useState(false);
130
+
131
+ useEffect(() => {
132
+ (async () => {
133
+ setLoading(true);
134
+ let me = await getMe();
135
+ setUserInfo({
136
+ isAdmin: me.isAdmin,
137
+ isNFP: me.isNFP,
138
+ isGuest: me.isGuest,
139
+ country: me.country,
140
+ isEionetUser: me.isEionetUser,
141
+ isLoaded: true,
142
+ mail: me.mail,
143
+ displayName: me.displayName,
144
+ givenName: me.givenName,
145
+ surname: me.surname,
146
+ });
147
+
148
+ setSelectedCountry(me.country);
149
+
150
+ if (me.isAdmin) {
151
+ setCanChangeCountry(true);
152
+ const loadedCountries = await getCountries();
153
+ loadedCountries && setCountries(loadedCountries);
154
+ }
155
+
156
+ me.isLoaded = true;
157
+ setSelfInfo(me);
158
+ setIsEionetUser(me && me.isEionetUser);
159
+ setLoading(false);
160
+ !!configuration.DashboardVersion &&
161
+ setVersionDialogOpen(configuration.DashboardVersion != version);
162
+ })();
163
+ }, [getMe, configuration]);
164
+
165
+ const [menuId, setMenuId] = useState(1),
166
+ onMenuClick = (index) => {
167
+ setMenuId(index);
168
+ },
169
+ openSelfService = () => {
170
+ setMenuId(4);
171
+ },
172
+ activityVisible = useCallback(() => {
173
+ return userInfo.isLoaded && menuId == 1;
174
+ }, [userInfo, menuId]),
175
+ myCountryVisible = useCallback(() => {
176
+ return userInfo.isLoaded && menuId == 2;
177
+ }, [userInfo, menuId]),
178
+ publicationsVisible = useCallback(() => {
179
+ return userInfo.isLoaded && menuId == 3;
180
+ }, [userInfo, menuId]),
181
+ selfServiceVisible = useCallback(() => {
182
+ return selfInfo && selfInfo.isLoaded && menuId == 4 && isEionetUser;
183
+ }, [selfInfo, menuId, isEionetUser]);
184
+
185
+ const setData4Menu = useCallback(
186
+ (events) => {
187
+ const event2Approve = events.filter(
188
+ (e) =>
189
+ e.IsUpcoming &&
190
+ e.IsOffline &&
191
+ e.Participants &&
192
+ e.Participants.length > 0 &&
193
+ e.Participants.filter((p) => !p.NFPApproved || p.NFPApproved == 'No value').length >
194
+ 0,
195
+ ),
196
+ events2Rate = events.filter((e) => !e.IsUpcoming && !!e.AllowVote);
197
+
198
+ setUserMenuData({
199
+ allEvents: events,
200
+ event2Approve: event2Approve,
201
+ events2Rate: events2Rate,
202
+ });
203
+ },
204
+ [userMenuData],
205
+ ),
206
+ refreshData4Menu = useCallback(() => {
207
+ setData4Menu(userMenuData.allEvents);
208
+ }, [userMenuData]),
209
+ openRating = useCallback(
210
+ async (event) => {
211
+ setLoading(true);
212
+ const participant = await getCurrentParticipant(event, userInfo);
213
+ setSelectedEvent(event);
214
+ setParticipant(participant);
215
+ setRatingVisible(true);
216
+ setLoading(false);
217
+ },
218
+ [userInfo],
219
+ ),
220
+ openApproval = useCallback(
221
+ async (event) => {
222
+ setLoading(true);
223
+ const participant = await getCurrentParticipant(event, userInfo);
224
+ event.Participants = await getParticipants(event.id, userInfo.country);
225
+ setSelectedEvent(event);
226
+ setParticipant(participant);
227
+ setApprovalVisible(true);
228
+ setLoading(false);
229
+ },
230
+ [userInfo],
231
+ ),
232
+ handleApprovalClose = () => {
233
+ refreshData4Menu();
234
+ setApprovalVisible(false);
235
+ },
236
+ handleRatingClose = (result) => {
237
+ setRatingVisible(false);
238
+ selectedEvent.HasVoted = result;
239
+ selectedEvent.AllowVote = !result;
240
+ refreshData4Menu();
241
+ },
242
+ handleVersionDialogClose = () => {
243
+ setVersionDialogOpen(false);
244
+ };
245
+
246
+ const nonIsoCountryCodes = {
247
+ el: 'gr',
248
+ io: '',
249
+ uk: 'gb',
250
+ },
251
+ preProcessCountryCode = (code) => {
252
+ return Object.prototype.hasOwnProperty.call(nonIsoCountryCodes, code)
253
+ ? nonIsoCountryCodes[code]
254
+ : code;
255
+ };
256
+
257
+ return (
258
+ <div className="main">
259
+ <ThemeProvider theme={theme}>
260
+ <Backdrop
261
+ sx={{ color: '#6b32a8', zIndex: (theme) => theme.zIndex.drawer + 1 }}
262
+ open={loading}
263
+ >
264
+ <CircularProgress color="primary" />
265
+ </Backdrop>
266
+ <AppBar
267
+ color="suplementary"
268
+ position="fixed"
269
+ sx={{ zIndex: (theme) => theme.zIndex.drawer + 1 }}
270
+ >
271
+ <Toolbar>
272
+ <MenuItem onClick={() => onMenuClick(1)}>
273
+ <Typography
274
+ color="suplementary.text"
275
+ className={'appbar-item' + (menuId == 1 ? ' appbar-item-selected' : '')}
276
+ >
277
+ Activity
278
+ </Typography>
279
+ </MenuItem>
280
+ <MenuItem onClick={() => onMenuClick(2)}>
281
+ <Typography className={'appbar-item' + (menuId == 2 ? ' appbar-item-selected' : '')}>
282
+ My country
283
+ </Typography>
284
+ {selectedCountry && preProcessCountryCode(selectedCountry.toLowerCase()) && (
285
+ <img
286
+ loading="lazy"
287
+ src={`https://flagcdn.com/h20/${preProcessCountryCode(
288
+ selectedCountry.toLowerCase(),
289
+ )}.png`}
290
+ alt=""
291
+ />
292
+ )}
293
+ </MenuItem>
294
+ {canChangeCountry && (
295
+ <Autocomplete
296
+ sx={{
297
+ width: '5%',
298
+ }}
299
+ disablePortal
300
+ id="country"
301
+ defaultValue={userInfo.country}
302
+ options={countries}
303
+ onChange={async (_e, value) => {
304
+ setSelectedCountry(value);
305
+ }}
306
+ renderOption={(props, option) => {
307
+ const countryCode = preProcessCountryCode(option.toLowerCase());
308
+ return (
309
+ <Box component="li" sx={{ '& > img': { ml: 2, flexShrink: 0 } }} {...props}>
310
+ {option}
311
+ {countryCode && (
312
+ <img
313
+ loading="lazy"
314
+ width="20"
315
+ src={`https://flagcdn.com/w20/${countryCode}.png`}
316
+ alt=""
317
+ />
318
+ )}
319
+ </Box>
320
+ );
321
+ }}
322
+ renderInput={(params) => (
323
+ <TextField autoComplete="off" {...params} variant="standard" />
324
+ )}
325
+ />
326
+ )}
327
+ {false && (
328
+ <MenuItem onClick={() => onMenuClick(3)}>
329
+ <Typography sx={{ textAlign: 'center', marginRight: '0.5rem' }}>
330
+ Publications
331
+ </Typography>
332
+ <FeedIcon></FeedIcon>
333
+ </MenuItem>
334
+ )}
335
+ {userInfo.isEionetUser && (
336
+ <Box sx={{ width: '100%', fontSize: '0.8rem', display: 'flex' }}>
337
+ <UserMenu
338
+ userInfo={userInfo}
339
+ openSelfService={openSelfService}
340
+ events2Rate={userMenuData.events2Rate}
341
+ events2Approve={userMenuData.event2Approve}
342
+ openRating={openRating}
343
+ openApproval={openApproval}
344
+ ></UserMenu>
345
+ </Box>
346
+ )}
347
+ </Toolbar>
348
+ </AppBar>
349
+ <Dialog open={versionDialogOpen} onClose={handleVersionDialogClose}>
350
+ <DialogTitle>
351
+ <IconButton
352
+ aria-label="close"
353
+ onClick={handleVersionDialogClose}
354
+ sx={{
355
+ position: 'absolute',
356
+ right: 8,
357
+ top: 8,
358
+ color: (theme) => theme.palette.grey[500],
359
+ }}
360
+ >
361
+ <CloseIcon />
362
+ </IconButton>
363
+ <Typography>Application version</Typography>
364
+ </DialogTitle>
365
+ <Box sx={{ margin: '2rem' }}>
366
+ <HtmlBox html={configuration?.AppVersionMessage}></HtmlBox>
367
+ </Box>
368
+ </Dialog>
369
+ <ApprovalDialog
370
+ open={approvalVisible}
371
+ handleClose={handleApprovalClose}
372
+ event={selectedEvent}
373
+ userInfo={userInfo}
374
+ ></ApprovalDialog>
375
+ <EventRatingDialog
376
+ open={ratingVisible}
377
+ handleClose={handleRatingClose}
378
+ event={selectedEvent}
379
+ participant={participant}
380
+ ></EventRatingDialog>
381
+
382
+ {activityVisible() && (
383
+ <Activity
384
+ userInfo={userInfo}
385
+ configuration={configuration}
386
+ setData4Menu={setData4Menu}
387
+ openRating={openRating}
388
+ openApproval={openApproval}
389
+ />
390
+ )}
391
+ {myCountryVisible() && (
392
+ <MyCountry
393
+ userInfo={userInfo}
394
+ selectedCountry={selectedCountry}
395
+ configuration={configuration}
396
+ />
397
+ )}
398
+ {publicationsVisible() && <Publications userInfo={userInfo} />}
399
+ {selfServiceVisible() && <UserEdit user={selfInfo} />}
400
+ <Paper
401
+ sx={{
402
+ position: 'fixed',
403
+ bottom: 0,
404
+ left: 0,
405
+ right: 0,
406
+ zIndex: (theme) => theme.zIndex.drawer + 1,
407
+ }}
408
+ elevation={5}
409
+ >
410
+ <BottomNavigation
411
+ sx={{ display: 'flex', justifyContent: 'flex-start', border: '2px', height: '55px' }}
412
+ >
413
+ <Typography
414
+ style={{
415
+ paddingLeft: '20px',
416
+ paddingRight: '10px',
417
+ alignSelf: 'center',
418
+ fontSize: '14px',
419
+ }}
420
+ color="tertiary"
421
+ >
422
+ These links open <br />
423
+ in separate windows.
424
+ </Typography>
425
+ <Box sx={{ display: 'flex', alignSelf: 'center', height: '30px' }}>
426
+ <Button
427
+ className="bottom-button"
428
+ color="tertiary"
429
+ variant="outlined"
430
+ endIcon={<OpenInNewIcon color="primary" />}
431
+ onClick={() => {
432
+ window.open(configuration.MeetingListUrl, '_blank');
433
+ }}
434
+ >
435
+ View all meetings
436
+ </Button>
437
+ <Button
438
+ className="bottom-button"
439
+ color="tertiary"
440
+ variant="outlined"
441
+ endIcon={<OpenInNewIcon color="primary" />}
442
+ onClick={() => {
443
+ window.open(configuration.ConsultationListUrl, '_blank');
444
+ }}
445
+ >
446
+ View all consultations
447
+ </Button>
448
+ <Button
449
+ className="bottom-button"
450
+ color="tertiary"
451
+ variant="outlined"
452
+ endIcon={<OpenInNewIcon color="primary" />}
453
+ onClick={() => {
454
+ window.open(configuration.ConsultationListUrl, '_blank');
455
+ }}
456
+ >
457
+ View all inquiries
458
+ </Button>
459
+ </Box>
460
+ <Typography
461
+ align="center"
462
+ sx={{
463
+ position: 'absolute',
464
+ right: 0,
465
+ alignSelf: 'center',
466
+ fontSize: '0.8rem',
467
+ pr: '0.2rem',
468
+ }}
469
+ >
470
+ v{`${process.env.REACT_APP_VERSION}`}
471
+ </Typography>
472
+ </BottomNavigation>
473
+ </Paper>
474
+ </ThemeProvider>
475
+ </div>
476
+ );
477
+ }
@@ -0,0 +1,138 @@
1
+ @import './variables.scss';
2
+
3
+ .main {
4
+ min-height: 100%;
5
+ min-width: 100%;
6
+ }
7
+
8
+ .data-grid {
9
+ min-height: 100px;
10
+ height: 100%;
11
+ }
12
+
13
+ .resizable {
14
+ cursor: ew-resize;
15
+ }
16
+
17
+ .MuiDataGrid-root {
18
+ border-radius: 0 !important;
19
+ }
20
+
21
+ .MuiDataGrid-columnHeaders {
22
+ //background-color: #accae5;
23
+ border-radius: 0 !important;
24
+ }
25
+
26
+ .MuiLink-button {
27
+ color: #006bb8 !important;
28
+
29
+ &:hover {
30
+ color: #004b7f !important;
31
+ }
32
+
33
+ &:visited {
34
+ color: #753aad !important;
35
+ }
36
+
37
+ &:active {
38
+ color: #003052 !important;
39
+ }
40
+ }
41
+
42
+ .appbar-item {
43
+ text-align: center;
44
+ margin-right: 0.5rem !important;
45
+ font-weight: 600 !important;
46
+ font-size: 16px !important;
47
+ border-bottom: 0.2rem solid;
48
+ border-color: $dark-grey;
49
+ height: 100%;
50
+ }
51
+
52
+ .appbar-item-selected {
53
+ border-color: $main-color;
54
+ }
55
+
56
+ .user-menu-button {
57
+ position: absolute !important;
58
+ text-align: center;
59
+ top: 0.5rem;
60
+ right: 0.5rem !important;
61
+ font-weight: 600 !important;
62
+ font-size: 14px !important;
63
+ border-bottom: 0.2rem solid !important;
64
+ border-color: $dark-grey !important;
65
+ }
66
+
67
+ .country-flag {
68
+ margin-left: auto;
69
+ align-self: center;
70
+ box-shadow: lightblue 1px 1px 2px 4px;
71
+ }
72
+
73
+ .drawer {
74
+ position: relative;
75
+
76
+ .MuiDrawer-root {
77
+ position: relative;
78
+ }
79
+
80
+ .MuiDrawer-paper {
81
+ width: 200px;
82
+ position: absolute;
83
+ }
84
+
85
+ .list-item {
86
+ display: block;
87
+
88
+ .list-item-text {
89
+ margin: auto;
90
+ justify-content: center;
91
+
92
+ padding: {
93
+ top: 0.5rem;
94
+ bottom: 0.5rem;
95
+ left: 1rem;
96
+ }
97
+
98
+ .MuiListItemText-primary {
99
+ font-size: 14px !important;
100
+ font-weight: 700 !important;
101
+ }
102
+ }
103
+
104
+ .list-item-button {
105
+ justify-content: center;
106
+
107
+ .MuiListItemText-primary {
108
+ font-size: 14px !important;
109
+ font-weight: 500 !important;
110
+ }
111
+ }
112
+
113
+ .list-item-icon {
114
+ min-width: 0;
115
+ padding-right: 10px;
116
+ }
117
+ }
118
+ }
119
+
120
+ .MuiChip-root {
121
+ background-color: white !important;
122
+ border-color: $dark-grey !important;
123
+ margin-right: 10px !important;
124
+ }
125
+
126
+ .bottom-button {
127
+ height: 35px;
128
+ margin-right: 1rem !important;
129
+ }
130
+
131
+ .menu-icon {
132
+ margin-right: 0.5rem;
133
+ }
134
+
135
+ .menu-item {
136
+ font-size: 14px !important;
137
+ font-weight: 600 !important;
138
+ }
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+ import * as microsoftTeams from '@microsoft/teams-js';
3
+
4
+ /**
5
+ * The 'Config' component is used to display your group tabs
6
+ * user configuration options. Here you will allow the user to
7
+ * make their choices and once they are done you will need to validate
8
+ * their choices and communicate that to Teams to enable the save button.
9
+ */
10
+ class TabConfig extends React.Component {
11
+ render() {
12
+ // Initialize the Microsoft Teams SDK
13
+ microsoftTeams.initialize();
14
+
15
+ /**
16
+ * When the user clicks "Save", save the url for your configured tab.
17
+ * This allows for the addition of query string parameters based on
18
+ * the settings selected by the user.
19
+ */
20
+ microsoftTeams.settings.registerOnSaveHandler((saveEvent) => {
21
+ const baseUrl = `https://${window.location.hostname}:${window.location.port}`;
22
+ microsoftTeams.settings.setSettings({
23
+ suggestedDisplayName: 'Eionet2 Dashboard',
24
+ entityId: 'dashboard',
25
+ contentUrl: baseUrl + '/index.html#/tab',
26
+ websiteUrl: baseUrl + '/index.html#/tab',
27
+ });
28
+ saveEvent.notifySuccess();
29
+ });
30
+
31
+ /**
32
+ * After verifying that the settings for your tab are correctly
33
+ * filled in by the user you need to set the state of the dialog
34
+ * to be valid. This will enable the save button in the configuration
35
+ * dialog.
36
+ */
37
+ microsoftTeams.settings.setValidityState(true);
38
+
39
+ return (
40
+ <div>
41
+ <h1>Tab Configuration</h1>
42
+ <div>
43
+ This is where you will add your tab configuration options the user can choose when the tab
44
+ is added to your team/group chat.
45
+ </div>
46
+ </div>
47
+ );
48
+ }
49
+ }
50
+
51
+ export default TabConfig;
@@ -0,0 +1,29 @@
1
+ import React from 'react';
2
+ import { Box, Typography } from '@mui/material';
3
+ import PropTypes from 'prop-types';
4
+
5
+ export default function TabPanel(props) {
6
+ const { children, value, index, ...other } = props;
7
+
8
+ return (
9
+ <div
10
+ role="tabpanel"
11
+ hidden={value !== index}
12
+ id={`simple-tabpanel-${index}`}
13
+ aria-labelledby={`simple-tab-${index}`}
14
+ {...other}
15
+ >
16
+ {value === index && (
17
+ <Box sx={{ p: 1 }}>
18
+ <Typography component={'span'}>{children}</Typography>
19
+ </Box>
20
+ )}
21
+ </div>
22
+ );
23
+ }
24
+
25
+ TabPanel.propTypes = {
26
+ children: PropTypes.node,
27
+ index: PropTypes.number.isRequired,
28
+ value: PropTypes.number.isRequired,
29
+ };
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ /**
3
+ * This component is used to display the required
4
+ * terms of use statement which can be found in a
5
+ * link in the about tab.
6
+ */
7
+ class TermsOfUse extends React.Component {
8
+ render() {
9
+ return (
10
+ <div>
11
+ <h1>Terms of Use</h1>
12
+ </div>
13
+ );
14
+ }
15
+ }
16
+
17
+ export default TermsOfUse;