@local-civics/mgmt-ui 0.1.54 → 0.1.56
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/dist/index.d.ts +55 -35
- package/dist/index.js +125 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +154 -48
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { NotificationsProvider } from '@mantine/notifications';
|
|
2
2
|
export { showNotification, updateNotification } from '@mantine/notifications';
|
|
3
|
-
import { IconArrowLeft, IconCategory2, IconCheck, IconTrash,
|
|
3
|
+
import { IconArrowLeft, IconCategory2, IconPlaylistAdd, IconChevronDown, IconClipboardCopy, IconCheck, IconTrash, IconDownload, IconX, IconCloudUpload, IconInfoCircle, IconColorSwatch, IconSwitchHorizontal, IconLogout, IconHome2, IconGauge, IconAlbum, IconLambda, IconBrandInstagram, IconBrandLinkedin, IconBrandFacebook } from '@tabler/icons';
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { useState } from 'react';
|
|
6
|
-
import { createStyles, Text, Tabs as Tabs$1, Title, Image,
|
|
6
|
+
import { createStyles, Text, Tabs as Tabs$1, Title, Image, Grid, Badge as Badge$1, ScrollArea, UnstyledButton, Group, Avatar, Table as Table$g, Container, Stack as Stack$3, ActionIcon, Button, LoadingOverlay, Select, Autocomplete, Menu, Drawer, Divider, TextInput, Tooltip, Paper, ThemeIcon, Card, Overlay, createEmotionCache, MantineProvider, Modal, Navbar as Navbar$1, Center, AppShell, Loader } from '@mantine/core';
|
|
7
|
+
import { DataTable } from 'mantine-datatable';
|
|
7
8
|
import { Dropzone, MIME_TYPES } from '@mantine/dropzone';
|
|
8
9
|
import { useForm } from '@mantine/form';
|
|
9
10
|
import * as papa from 'papaparse';
|
|
10
11
|
import { openConfirmModal, ModalsProvider } from '@mantine/modals';
|
|
11
12
|
import { Chart } from 'react-charts';
|
|
12
13
|
|
|
13
|
-
const useStyles$
|
|
14
|
+
const useStyles$d = createStyles((theme) => ({
|
|
14
15
|
root: {
|
|
15
16
|
display: "flex",
|
|
16
17
|
backgroundImage: `linear-gradient(-60deg, ${theme.colors[theme.primaryColor][4]} 0%, ${theme.colors[theme.primaryColor][7]} 100%)`,
|
|
@@ -57,7 +58,7 @@ const useStyles$c = createStyles((theme) => ({
|
|
|
57
58
|
}
|
|
58
59
|
}));
|
|
59
60
|
const StatsGroup = ({ data }) => {
|
|
60
|
-
const { classes } = useStyles$
|
|
61
|
+
const { classes } = useStyles$d();
|
|
61
62
|
const stats = data.map((stat) => {
|
|
62
63
|
const value = (() => {
|
|
63
64
|
if (stat.unit === "%") {
|
|
@@ -76,7 +77,7 @@ const Tabs = (props) => {
|
|
|
76
77
|
return /* @__PURE__ */ React.createElement(Tabs$1, { value: props.value, onTabChange: props.onChange }, /* @__PURE__ */ React.createElement(Tabs$1.List, null, tabs));
|
|
77
78
|
};
|
|
78
79
|
|
|
79
|
-
const useStyles$
|
|
80
|
+
const useStyles$c = createStyles((theme) => ({
|
|
80
81
|
wrapper: {
|
|
81
82
|
display: "flex",
|
|
82
83
|
alignItems: "center",
|
|
@@ -127,12 +128,20 @@ const useStyles$b = createStyles((theme) => ({
|
|
|
127
128
|
}
|
|
128
129
|
}));
|
|
129
130
|
const PlaceholderBanner = (props) => {
|
|
130
|
-
const { classes } = useStyles$
|
|
131
|
+
const { classes } = useStyles$c();
|
|
131
132
|
const title = props.title || "Nothing to display";
|
|
132
133
|
const description = props.description || "We don't have anything to show you here just yet. Add data, check back later, or adjust your search.";
|
|
133
134
|
return /* @__PURE__ */ React.createElement("div", { className: classes.wrapper }, /* @__PURE__ */ React.createElement("div", { className: classes.body }, /* @__PURE__ */ React.createElement(Title, { className: classes.title }, props.loading ? "Loading..." : title), /* @__PURE__ */ React.createElement(Text, { size: "sm", color: "dimmed" }, props.loading ? "Hold on, we're loading your data." : description)), /* @__PURE__ */ React.createElement(Image, { src: `https://cdn.localcivics.io/illustrations/${props.icon}.svg`, className: classes.image }));
|
|
134
135
|
};
|
|
135
136
|
|
|
137
|
+
function Stack$2(props) {
|
|
138
|
+
if (props.items.length === 0) {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
const rows = props.items.map((row) => /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Grid.Col, { span: 6 }, /* @__PURE__ */ React.createElement(Title, { color: "dark.4", size: "lg" }, row.lessonName)), /* @__PURE__ */ React.createElement(Grid.Col, { span: 6 }, !!row.isComplete && /* @__PURE__ */ React.createElement(Badge$1, { variant: "filled" }, "Complete"), !row.isComplete && !row.isStarted && /* @__PURE__ */ React.createElement(Badge$1, { color: "red", variant: "filled" }, "Not started"), !row.isComplete && !!row.isStarted && /* @__PURE__ */ React.createElement(Badge$1, { color: "violet", variant: "filled" }, "In progress"))));
|
|
142
|
+
return /* @__PURE__ */ React.createElement(Grid, { grow: true, gutter: "lg", sx: { padding: 20, minWidth: 700 } }, rows);
|
|
143
|
+
}
|
|
144
|
+
|
|
136
145
|
function Table$f(props) {
|
|
137
146
|
if (props.items.length === 0) {
|
|
138
147
|
return /* @__PURE__ */ React.createElement(
|
|
@@ -145,8 +154,31 @@ function Table$f(props) {
|
|
|
145
154
|
}
|
|
146
155
|
);
|
|
147
156
|
}
|
|
148
|
-
|
|
149
|
-
|
|
157
|
+
return /* @__PURE__ */ React.createElement(ScrollArea.Autosize, { maxHeight: 500 }, /* @__PURE__ */ React.createElement(
|
|
158
|
+
DataTable,
|
|
159
|
+
{
|
|
160
|
+
verticalSpacing: "sm",
|
|
161
|
+
sx: { minWidth: 700 },
|
|
162
|
+
withBorder: false,
|
|
163
|
+
borderRadius: "sm",
|
|
164
|
+
withColumnBorders: true,
|
|
165
|
+
striped: true,
|
|
166
|
+
highlightOnHover: true,
|
|
167
|
+
records: props.items,
|
|
168
|
+
idAccessor: "userId",
|
|
169
|
+
columns: [{
|
|
170
|
+
accessor: "name",
|
|
171
|
+
title: "Student Name",
|
|
172
|
+
render: (row) => /* @__PURE__ */ React.createElement(UnstyledButton, null, /* @__PURE__ */ React.createElement(Group, { spacing: "sm" }, /* @__PURE__ */ React.createElement(Avatar, { size: 40, src: row.avatar, radius: 40 }), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Text, { size: "sm", weight: 500 }, row.name), /* @__PURE__ */ React.createElement(Text, { size: "xs", color: "dimmed" }, row.email))))
|
|
173
|
+
}, {
|
|
174
|
+
accessor: "status",
|
|
175
|
+
render: (row) => /* @__PURE__ */ React.createElement(React.Fragment, null, !!row.isComplete && /* @__PURE__ */ React.createElement(Badge$1, { variant: "filled" }, "Complete"), !row.isComplete && /* @__PURE__ */ React.createElement(Badge$1, { color: "red", variant: "filled" }, "Incomplete"))
|
|
176
|
+
}],
|
|
177
|
+
rowExpansion: {
|
|
178
|
+
content: ({ record }) => /* @__PURE__ */ React.createElement(Stack$2, { items: record.lessons })
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
));
|
|
150
182
|
}
|
|
151
183
|
|
|
152
184
|
function Table$e(props) {
|
|
@@ -168,7 +200,7 @@ function Table$e(props) {
|
|
|
168
200
|
return /* @__PURE__ */ React.createElement(ScrollArea.Autosize, { maxHeight: 500 }, /* @__PURE__ */ React.createElement(Table$g, { verticalSpacing: "sm", sx: { minWidth: 700 }, highlightOnHover: true, striped: true }, /* @__PURE__ */ React.createElement("thead", null, /* @__PURE__ */ React.createElement("tr", null, /* @__PURE__ */ React.createElement("th", null, "Lesson Name"), /* @__PURE__ */ React.createElement("th", null, "Lesson Completion"))), /* @__PURE__ */ React.createElement("tbody", null, rows)));
|
|
169
201
|
}
|
|
170
202
|
|
|
171
|
-
const useStyles$
|
|
203
|
+
const useStyles$b = createStyles((theme) => ({
|
|
172
204
|
title: {
|
|
173
205
|
fontSize: 34,
|
|
174
206
|
fontWeight: 900,
|
|
@@ -181,11 +213,11 @@ const useStyles$a = createStyles((theme) => ({
|
|
|
181
213
|
}
|
|
182
214
|
}));
|
|
183
215
|
const Badge = (props) => {
|
|
184
|
-
const { classes } = useStyles$
|
|
216
|
+
const { classes } = useStyles$b();
|
|
185
217
|
const [tab, setTab] = useState("lessons");
|
|
186
218
|
const numberOfStudents = props.students.length;
|
|
187
219
|
const percentageOfBadgesEarned = numberOfStudents > 0 ? props.students.filter((u) => u.isComplete).length / numberOfStudents : 0;
|
|
188
|
-
return /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$
|
|
220
|
+
return /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$3, { spacing: "md" }, /* @__PURE__ */ React.createElement(Grid, null, /* @__PURE__ */ React.createElement(Grid.Col, { sm: "auto" }, /* @__PURE__ */ React.createElement(
|
|
189
221
|
Badge$1,
|
|
190
222
|
{
|
|
191
223
|
variant: "filled",
|
|
@@ -193,14 +225,14 @@ const Badge = (props) => {
|
|
|
193
225
|
size: "lg"
|
|
194
226
|
},
|
|
195
227
|
"Badges"
|
|
196
|
-
), /* @__PURE__ */ React.createElement(Group, null, /* @__PURE__ */ React.createElement(Stack$
|
|
228
|
+
), /* @__PURE__ */ React.createElement(Group, null, /* @__PURE__ */ React.createElement(Stack$3, { spacing: 0 }, /* @__PURE__ */ React.createElement(Title, { order: 2, className: classes.title, mt: "md" }, props.displayName || "Badge"), /* @__PURE__ */ React.createElement(Text, { color: "dimmed", className: classes.description, mt: "sm" }, props.description || "No description")), /* @__PURE__ */ React.createElement(Stack$3, { ml: "auto" }, /* @__PURE__ */ React.createElement(
|
|
197
229
|
Button,
|
|
198
230
|
{
|
|
199
231
|
variant: "gradient",
|
|
200
232
|
onClick: props.onPreviewClick
|
|
201
233
|
},
|
|
202
234
|
"Preview"
|
|
203
|
-
))))), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React.createElement(LoadingOverlay, { visible: props.loading, overlayBlur: 2 }), /* @__PURE__ */ React.createElement(Stack$
|
|
235
|
+
))))), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React.createElement(LoadingOverlay, { visible: props.loading, overlayBlur: 2 }), /* @__PURE__ */ React.createElement(Stack$3, null, /* @__PURE__ */ React.createElement(StatsGroup, { data: [
|
|
204
236
|
{
|
|
205
237
|
title: "BADGE COMPLETION",
|
|
206
238
|
value: percentageOfBadgesEarned,
|
|
@@ -221,7 +253,7 @@ const Badge = (props) => {
|
|
|
221
253
|
return { value: g.classId, label: g.name };
|
|
222
254
|
})
|
|
223
255
|
}
|
|
224
|
-
), /* @__PURE__ */ React.createElement(Stack$
|
|
256
|
+
), /* @__PURE__ */ React.createElement(Stack$3, { spacing: 0 }, /* @__PURE__ */ React.createElement(
|
|
225
257
|
Tabs,
|
|
226
258
|
{
|
|
227
259
|
value: tab,
|
|
@@ -279,7 +311,7 @@ function Table$d(props) {
|
|
|
279
311
|
return /* @__PURE__ */ React.createElement(ScrollArea.Autosize, { maxHeight: 500 }, /* @__PURE__ */ React.createElement(Table$g, { horizontalSpacing: 0, verticalSpacing: 0, sx: { minWidth: 700 } }, /* @__PURE__ */ React.createElement("tbody", null, rows)));
|
|
280
312
|
}
|
|
281
313
|
|
|
282
|
-
const useStyles$
|
|
314
|
+
const useStyles$a = createStyles((theme) => ({
|
|
283
315
|
title: {
|
|
284
316
|
fontSize: 34,
|
|
285
317
|
fontWeight: 900,
|
|
@@ -292,8 +324,8 @@ const useStyles$9 = createStyles((theme) => ({
|
|
|
292
324
|
}
|
|
293
325
|
}));
|
|
294
326
|
const Badges = (props) => {
|
|
295
|
-
const { classes } = useStyles$
|
|
296
|
-
return /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$
|
|
327
|
+
const { classes } = useStyles$a();
|
|
328
|
+
return /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$3, { spacing: "md" }, /* @__PURE__ */ React.createElement(Grid, null, /* @__PURE__ */ React.createElement(Grid.Col, { sm: "auto" }, /* @__PURE__ */ React.createElement(Badge$1, { variant: "filled", size: "lg" }, "Badges"), /* @__PURE__ */ React.createElement(Title, { order: 2, className: classes.title, mt: "md" }, "Badges and micro-credentials"), /* @__PURE__ */ React.createElement(Text, { color: "dimmed", className: classes.description, mt: "sm" }, "Project-sized skills acquisition and standards alignment."))), /* @__PURE__ */ React.createElement(
|
|
297
329
|
Autocomplete,
|
|
298
330
|
{
|
|
299
331
|
placeholder: "Search for a badge that fits your needs",
|
|
@@ -416,7 +448,7 @@ function Table$8(props) {
|
|
|
416
448
|
|
|
417
449
|
const Dashboard = (props) => {
|
|
418
450
|
const [tab, setTab] = useState("students");
|
|
419
|
-
return /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$
|
|
451
|
+
return /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$3, null, /* @__PURE__ */ React.createElement(Stack$3, { spacing: 0 }, /* @__PURE__ */ React.createElement(Title, { size: "h3" }, "Dashboard"), /* @__PURE__ */ React.createElement(Text, { color: "dimmed", size: "sm", mt: "md" }, "Fast-track learning for your students.")), /* @__PURE__ */ React.createElement(Stack$3, null, /* @__PURE__ */ React.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React.createElement(LoadingOverlay, { visible: props.loading, overlayBlur: 2 }), /* @__PURE__ */ React.createElement(Stack$3, { spacing: "sm" }, /* @__PURE__ */ React.createElement(StatsGroup, { data: [
|
|
420
452
|
{
|
|
421
453
|
title: "# OF STUDENTS",
|
|
422
454
|
value: props.students.length
|
|
@@ -451,7 +483,7 @@ const Dashboard = (props) => {
|
|
|
451
483
|
return { value: g.classId, label: g.name };
|
|
452
484
|
})
|
|
453
485
|
}
|
|
454
|
-
), /* @__PURE__ */ React.createElement(Stack$
|
|
486
|
+
), /* @__PURE__ */ React.createElement(Stack$3, { spacing: 0 }, /* @__PURE__ */ React.createElement(
|
|
455
487
|
Tabs,
|
|
456
488
|
{
|
|
457
489
|
value: tab,
|
|
@@ -500,6 +532,50 @@ const Dashboard = (props) => {
|
|
|
500
532
|
)))))));
|
|
501
533
|
};
|
|
502
534
|
|
|
535
|
+
const useStyles$9 = createStyles((theme) => ({
|
|
536
|
+
button: {
|
|
537
|
+
borderTopRightRadius: 0,
|
|
538
|
+
borderBottomRightRadius: 0,
|
|
539
|
+
marginLeft: 0,
|
|
540
|
+
marginRight: 0
|
|
541
|
+
},
|
|
542
|
+
menuControl: {
|
|
543
|
+
borderTopLeftRadius: 0,
|
|
544
|
+
borderBottomLeftRadius: 0,
|
|
545
|
+
border: 0,
|
|
546
|
+
borderLeft: `1px solid ${theme.colorScheme === "dark" ? theme.colors.dark[7] : theme.white}`
|
|
547
|
+
}
|
|
548
|
+
}));
|
|
549
|
+
const SplitButton = (props) => {
|
|
550
|
+
const { classes, theme } = useStyles$9();
|
|
551
|
+
const menuIconColor = theme.colors[theme.primaryColor][theme.colorScheme === "dark" ? 5 : 6];
|
|
552
|
+
return /* @__PURE__ */ React.createElement(Group, { noWrap: true, spacing: 0 }, /* @__PURE__ */ React.createElement(
|
|
553
|
+
Button,
|
|
554
|
+
{
|
|
555
|
+
className: classes.button,
|
|
556
|
+
leftIcon: /* @__PURE__ */ React.createElement(IconPlaylistAdd, { size: 14 }),
|
|
557
|
+
onClick: props.onAddStudentsClick
|
|
558
|
+
},
|
|
559
|
+
"Add students"
|
|
560
|
+
), /* @__PURE__ */ React.createElement(Menu, { transition: "pop", position: "bottom-end" }, /* @__PURE__ */ React.createElement(Menu.Target, null, /* @__PURE__ */ React.createElement(
|
|
561
|
+
ActionIcon,
|
|
562
|
+
{
|
|
563
|
+
variant: "filled",
|
|
564
|
+
color: theme.primaryColor,
|
|
565
|
+
size: 36,
|
|
566
|
+
className: classes.menuControl
|
|
567
|
+
},
|
|
568
|
+
/* @__PURE__ */ React.createElement(IconChevronDown, { size: 16, stroke: 1.5 })
|
|
569
|
+
)), /* @__PURE__ */ React.createElement(Menu.Dropdown, null, /* @__PURE__ */ React.createElement(
|
|
570
|
+
Menu.Item,
|
|
571
|
+
{
|
|
572
|
+
icon: /* @__PURE__ */ React.createElement(IconClipboardCopy, { size: 16, stroke: 1.5, color: menuIconColor }),
|
|
573
|
+
onClick: props.onCopyClassLinkClick
|
|
574
|
+
},
|
|
575
|
+
"Copy class link"
|
|
576
|
+
))));
|
|
577
|
+
};
|
|
578
|
+
|
|
503
579
|
function Table$7(props) {
|
|
504
580
|
if (props.items.length === 0) {
|
|
505
581
|
return /* @__PURE__ */ React.createElement(
|
|
@@ -603,12 +679,12 @@ const Class = (props) => {
|
|
|
603
679
|
padding: "xl",
|
|
604
680
|
size: "xl"
|
|
605
681
|
},
|
|
606
|
-
/* @__PURE__ */ React.createElement(Stack$
|
|
682
|
+
/* @__PURE__ */ React.createElement(Stack$3, { spacing: "md" }, /* @__PURE__ */ React.createElement(DropzoneButton, __spreadProps(__spreadValues$3({}, props), { close: () => setOpened(false) })), /* @__PURE__ */ React.createElement(Divider, { label: "or", labelPosition: "center", my: "md", variant: "dashed" }), /* @__PURE__ */ React.createElement("form", { onSubmit: form.onSubmit(() => {
|
|
607
683
|
const values = form.values;
|
|
608
684
|
form.reset();
|
|
609
685
|
setOpened(false);
|
|
610
686
|
props.onCreateStudents && props.onCreateStudents([values]);
|
|
611
|
-
}) }, /* @__PURE__ */ React.createElement(Stack$
|
|
687
|
+
}) }, /* @__PURE__ */ React.createElement(Stack$3, null, /* @__PURE__ */ React.createElement(
|
|
612
688
|
TextInput,
|
|
613
689
|
__spreadValues$3({
|
|
614
690
|
withAsterisk: true,
|
|
@@ -628,7 +704,7 @@ const Class = (props) => {
|
|
|
628
704
|
placeholder: "Family name"
|
|
629
705
|
}, form.getInputProps("familyName"))
|
|
630
706
|
)), /* @__PURE__ */ React.createElement(Button, { type: "submit", fullWidth: true, mt: "md" }, "Submit"))))
|
|
631
|
-
), /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$
|
|
707
|
+
), /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$3, { spacing: "md" }, /* @__PURE__ */ React.createElement(Grid, null, /* @__PURE__ */ React.createElement(Grid.Col, { sm: "auto" }, /* @__PURE__ */ React.createElement(
|
|
632
708
|
Badge$1,
|
|
633
709
|
{
|
|
634
710
|
variant: "filled",
|
|
@@ -637,13 +713,12 @@ const Class = (props) => {
|
|
|
637
713
|
},
|
|
638
714
|
"Classes"
|
|
639
715
|
), /* @__PURE__ */ React.createElement(Title, { order: 2, className: classes.title, mt: "md" }, props.displayName || "Class"), /* @__PURE__ */ React.createElement(Text, { color: "dimmed", className: classes.description, mt: "sm" }, props.description || "No description")), /* @__PURE__ */ React.createElement(Grid.Col, { sm: "content" }, !props.loading && /* @__PURE__ */ React.createElement(
|
|
640
|
-
|
|
716
|
+
SplitButton,
|
|
641
717
|
{
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
))), /* @__PURE__ */ React.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React.createElement(LoadingOverlay, { visible: props.loading, overlayBlur: 2 }), /* @__PURE__ */ React.createElement(Stack$1, { spacing: "sm" }, /* @__PURE__ */ React.createElement(StatsGroup, { data: [
|
|
718
|
+
onAddStudentsClick: () => setOpened(true),
|
|
719
|
+
onCopyClassLinkClick: props.onCopyLinkClick
|
|
720
|
+
}
|
|
721
|
+
))), /* @__PURE__ */ React.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React.createElement(LoadingOverlay, { visible: props.loading, overlayBlur: 2 }), /* @__PURE__ */ React.createElement(Stack$3, { spacing: "sm" }, /* @__PURE__ */ React.createElement(StatsGroup, { data: [
|
|
647
722
|
{
|
|
648
723
|
title: "# OF STUDENTS",
|
|
649
724
|
value: props.students.length
|
|
@@ -799,7 +874,7 @@ const Classes = (props) => {
|
|
|
799
874
|
form.reset();
|
|
800
875
|
setOpened(false);
|
|
801
876
|
props.onCreateClass && props.onCreateClass(values);
|
|
802
|
-
}) }, /* @__PURE__ */ React.createElement(Stack$
|
|
877
|
+
}) }, /* @__PURE__ */ React.createElement(Stack$3, null, /* @__PURE__ */ React.createElement(
|
|
803
878
|
TextInput,
|
|
804
879
|
__spreadValues$2({
|
|
805
880
|
withAsterisk: true,
|
|
@@ -813,14 +888,14 @@ const Classes = (props) => {
|
|
|
813
888
|
placeholder: "A class for my first period English students"
|
|
814
889
|
}, form.getInputProps("description"))
|
|
815
890
|
)), /* @__PURE__ */ React.createElement(Button, { type: "submit", fullWidth: true, mt: "md" }, "Submit"))
|
|
816
|
-
), /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$
|
|
891
|
+
), /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$3, { spacing: "md" }, /* @__PURE__ */ React.createElement(Grid, null, /* @__PURE__ */ React.createElement(Grid.Col, { sm: "auto" }, /* @__PURE__ */ React.createElement(Badge$1, { variant: "filled", size: "lg" }, "Classes"), /* @__PURE__ */ React.createElement(Title, { order: 2, className: classes.title, mt: "md" }, "Organize students into classes"), /* @__PURE__ */ React.createElement(Text, { color: "dimmed", className: classes.description, mt: "sm" }, "A class can be for a specific period of time, grade, team, or other cohorts.")), /* @__PURE__ */ React.createElement(Grid.Col, { sm: "content" }, !props.loading && /* @__PURE__ */ React.createElement(
|
|
817
892
|
Button,
|
|
818
893
|
{
|
|
819
894
|
onClick: () => setOpened(true),
|
|
820
895
|
leftIcon: /* @__PURE__ */ React.createElement(IconPlaylistAdd, { size: 14 })
|
|
821
896
|
},
|
|
822
897
|
"Create class"
|
|
823
|
-
))), /* @__PURE__ */ React.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React.createElement(LoadingOverlay, { visible: props.loading, overlayBlur: 2 }), /* @__PURE__ */ React.createElement(Stack$
|
|
898
|
+
))), /* @__PURE__ */ React.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React.createElement(LoadingOverlay, { visible: props.loading, overlayBlur: 2 }), /* @__PURE__ */ React.createElement(Stack$3, { spacing: "sm" }, /* @__PURE__ */ React.createElement(StatsGroup, { data: [
|
|
824
899
|
{
|
|
825
900
|
title: "# OF CLASSES",
|
|
826
901
|
value: props.classes.length
|
|
@@ -906,7 +981,7 @@ const Student = (props) => {
|
|
|
906
981
|
const [tab, setTab] = useState("badges");
|
|
907
982
|
const numberOfBadges = props.badges.length;
|
|
908
983
|
const percentageOfBadgesEarned = numberOfBadges > 0 ? props.badges.filter((b) => b.isComplete).length / numberOfBadges : 0;
|
|
909
|
-
return /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$
|
|
984
|
+
return /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$3, { spacing: "md" }, /* @__PURE__ */ React.createElement(Grid, { gutter: "md" }, /* @__PURE__ */ React.createElement(Grid.Col, { sm: "auto" }, /* @__PURE__ */ React.createElement(
|
|
910
985
|
Badge$1,
|
|
911
986
|
{
|
|
912
987
|
variant: "filled",
|
|
@@ -921,7 +996,7 @@ const Student = (props) => {
|
|
|
921
996
|
name: props.name,
|
|
922
997
|
impactStatement: props.impactStatement
|
|
923
998
|
}
|
|
924
|
-
))), /* @__PURE__ */ React.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React.createElement(LoadingOverlay, { visible: props.loading, overlayBlur: 2 }), /* @__PURE__ */ React.createElement(Stack$
|
|
999
|
+
))), /* @__PURE__ */ React.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React.createElement(LoadingOverlay, { visible: props.loading, overlayBlur: 2 }), /* @__PURE__ */ React.createElement(Stack$3, { spacing: "lg" }, /* @__PURE__ */ React.createElement(StatsGroup, { data: [
|
|
925
1000
|
{
|
|
926
1001
|
title: "PROBLEMS SOLVED",
|
|
927
1002
|
value: props.numberOfProblemsSolved
|
|
@@ -936,7 +1011,7 @@ const Student = (props) => {
|
|
|
936
1011
|
value: percentageOfBadgesEarned,
|
|
937
1012
|
unit: "%"
|
|
938
1013
|
}
|
|
939
|
-
] }), /* @__PURE__ */ React.createElement(Stack$
|
|
1014
|
+
] }), /* @__PURE__ */ React.createElement(Stack$3, { spacing: 0 }, /* @__PURE__ */ React.createElement(
|
|
940
1015
|
Tabs,
|
|
941
1016
|
{
|
|
942
1017
|
value: tab,
|
|
@@ -1121,7 +1196,7 @@ const TenantBanner = (_a) => {
|
|
|
1121
1196
|
};
|
|
1122
1197
|
|
|
1123
1198
|
const Home = (props) => {
|
|
1124
|
-
return /* @__PURE__ */ React.createElement(Container, { size: "lg" }, /* @__PURE__ */ React.createElement(Stack$
|
|
1199
|
+
return /* @__PURE__ */ React.createElement(Container, { size: "lg" }, /* @__PURE__ */ React.createElement(Stack$3, { spacing: "lg" }, /* @__PURE__ */ React.createElement(Grid, { gutter: "md" }, /* @__PURE__ */ React.createElement(Grid.Col, { md: 6 }, /* @__PURE__ */ React.createElement(
|
|
1125
1200
|
UserInfo,
|
|
1126
1201
|
{
|
|
1127
1202
|
variant: "compact",
|
|
@@ -1186,6 +1261,14 @@ function Table$2(props) {
|
|
|
1186
1261
|
return /* @__PURE__ */ React.createElement(ScrollArea.Autosize, { maxHeight: 500 }, /* @__PURE__ */ React.createElement(Table$g, { verticalSpacing: "sm", sx: { minWidth: 700 }, highlightOnHover: true, striped: true }, /* @__PURE__ */ React.createElement("thead", null, /* @__PURE__ */ React.createElement("tr", null, /* @__PURE__ */ React.createElement("th", null, "Student Name"), /* @__PURE__ */ React.createElement("th", null, "Reflection"), /* @__PURE__ */ React.createElement("th", null, "Rating"))), /* @__PURE__ */ React.createElement("tbody", null, rows)));
|
|
1187
1262
|
}
|
|
1188
1263
|
|
|
1264
|
+
function Stack$1(props) {
|
|
1265
|
+
if (props.items.length === 0) {
|
|
1266
|
+
return null;
|
|
1267
|
+
}
|
|
1268
|
+
const rows = props.items.map((row) => /* @__PURE__ */ React.createElement(Stack$3, { spacing: 0, key: row.questionName }, /* @__PURE__ */ React.createElement(Title, { color: "dark.4", size: "lg" }, row.questionName), /* @__PURE__ */ React.createElement(Text, null, row.answer.join(",") || "No answer.")));
|
|
1269
|
+
return /* @__PURE__ */ React.createElement(ScrollArea.Autosize, { maxHeight: 500 }, /* @__PURE__ */ React.createElement(Stack$3, { spacing: 24, sx: { padding: 20, minWidth: 700 } }, rows));
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1189
1272
|
function Table$1(props) {
|
|
1190
1273
|
if (props.items.length === 0) {
|
|
1191
1274
|
return /* @__PURE__ */ React.createElement(
|
|
@@ -1198,8 +1281,31 @@ function Table$1(props) {
|
|
|
1198
1281
|
}
|
|
1199
1282
|
);
|
|
1200
1283
|
}
|
|
1201
|
-
|
|
1202
|
-
|
|
1284
|
+
return /* @__PURE__ */ React.createElement(ScrollArea.Autosize, { maxHeight: 500 }, /* @__PURE__ */ React.createElement(
|
|
1285
|
+
DataTable,
|
|
1286
|
+
{
|
|
1287
|
+
verticalSpacing: "sm",
|
|
1288
|
+
sx: { minWidth: 700 },
|
|
1289
|
+
withBorder: false,
|
|
1290
|
+
borderRadius: "sm",
|
|
1291
|
+
withColumnBorders: true,
|
|
1292
|
+
striped: true,
|
|
1293
|
+
highlightOnHover: true,
|
|
1294
|
+
idAccessor: "userId",
|
|
1295
|
+
records: props.items,
|
|
1296
|
+
columns: [{
|
|
1297
|
+
accessor: "name",
|
|
1298
|
+
title: "Student Name",
|
|
1299
|
+
render: (row) => /* @__PURE__ */ React.createElement(UnstyledButton, null, /* @__PURE__ */ React.createElement(Group, { spacing: "sm" }, /* @__PURE__ */ React.createElement(Avatar, { size: 40, src: row.avatar, radius: 40 }), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Text, { size: "sm", weight: 500 }, row.name), /* @__PURE__ */ React.createElement(Text, { size: "xs", color: "dimmed" }, row.email))))
|
|
1300
|
+
}, {
|
|
1301
|
+
accessor: "status",
|
|
1302
|
+
render: (row) => /* @__PURE__ */ React.createElement(React.Fragment, null, !!row.isComplete && /* @__PURE__ */ React.createElement(Badge$1, { variant: "filled" }, "Complete"), !row.isComplete && !row.isStarted && /* @__PURE__ */ React.createElement(Badge$1, { color: "red", variant: "filled" }, "Not started"), !row.isComplete && !!row.isStarted && /* @__PURE__ */ React.createElement(Badge$1, { color: "violet", variant: "filled" }, "In progress"))
|
|
1303
|
+
}],
|
|
1304
|
+
rowExpansion: {
|
|
1305
|
+
content: ({ record }) => /* @__PURE__ */ React.createElement(Stack$1, { items: record.answers })
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
));
|
|
1203
1309
|
}
|
|
1204
1310
|
|
|
1205
1311
|
function Stack(props) {
|
|
@@ -1242,7 +1348,7 @@ function Stack(props) {
|
|
|
1242
1348
|
labelMap[r] = labelMap[r] ? labelMap[r] + 1 : 1;
|
|
1243
1349
|
}
|
|
1244
1350
|
}));
|
|
1245
|
-
return /* @__PURE__ */ React.createElement(Card, { key: row.question, withBorder: true, p: "xl", radius: "md" }, /* @__PURE__ */ React.createElement(Stack$
|
|
1351
|
+
return /* @__PURE__ */ React.createElement(Card, { key: row.question, withBorder: true, p: "xl", radius: "md" }, /* @__PURE__ */ React.createElement(Stack$3, { spacing: 4 }, /* @__PURE__ */ React.createElement(Title, { size: "lg" }, row.question), /* @__PURE__ */ React.createElement(Text, { size: "sm" }, row.answers.length, " answers"), /* @__PURE__ */ React.createElement("div", { style: { background: "white", height: "300px", width: "100%", position: "relative" } }, /* @__PURE__ */ React.createElement(
|
|
1246
1352
|
Chart,
|
|
1247
1353
|
{
|
|
1248
1354
|
options: {
|
|
@@ -1261,12 +1367,12 @@ function Stack(props) {
|
|
|
1261
1367
|
}
|
|
1262
1368
|
))));
|
|
1263
1369
|
}
|
|
1264
|
-
return /* @__PURE__ */ React.createElement(Card, { key: row.question, withBorder: true, p: "xl", radius: "md" }, /* @__PURE__ */ React.createElement(Stack$
|
|
1370
|
+
return /* @__PURE__ */ React.createElement(Card, { key: row.question, withBorder: true, p: "xl", radius: "md" }, /* @__PURE__ */ React.createElement(Stack$3, { spacing: 4 }, /* @__PURE__ */ React.createElement(Title, { size: "lg" }, row.question), /* @__PURE__ */ React.createElement(Text, { size: "sm" }, row.answers.length, " answers"), /* @__PURE__ */ React.createElement(ScrollArea.Autosize, { maxHeight: 500 }, /* @__PURE__ */ React.createElement(Stack$3, { spacing: 4 }, row.answers.map((a) => {
|
|
1265
1371
|
const answerText = a.join("\n");
|
|
1266
1372
|
return /* @__PURE__ */ React.createElement(Card, { key: answerText, p: 5, radius: 0, bg: "gray.0" }, /* @__PURE__ */ React.createElement(Text, null, answerText));
|
|
1267
1373
|
})))));
|
|
1268
1374
|
});
|
|
1269
|
-
return /* @__PURE__ */ React.createElement(Stack$
|
|
1375
|
+
return /* @__PURE__ */ React.createElement(Stack$3, { py: 4, spacing: 10, sx: { minWidth: 700 } }, rows);
|
|
1270
1376
|
}
|
|
1271
1377
|
const truncateWithEllipses = (text, max) => text.substr(0, max - 1) + (text.length > max ? "…" : "");
|
|
1272
1378
|
|
|
@@ -1287,7 +1393,7 @@ const Lesson = (props) => {
|
|
|
1287
1393
|
const [tab, setTab] = useState("question");
|
|
1288
1394
|
const numberOfStudents = props.students.length;
|
|
1289
1395
|
const percentageOfLessonsCompleted = numberOfStudents > 0 ? props.students.filter((u) => u.isComplete).length / numberOfStudents : 0;
|
|
1290
|
-
return /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$
|
|
1396
|
+
return /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$3, { spacing: "md" }, /* @__PURE__ */ React.createElement(Grid, null, /* @__PURE__ */ React.createElement(Grid.Col, { sm: "auto" }, /* @__PURE__ */ React.createElement(
|
|
1291
1397
|
Badge$1,
|
|
1292
1398
|
{
|
|
1293
1399
|
variant: "filled",
|
|
@@ -1295,14 +1401,14 @@ const Lesson = (props) => {
|
|
|
1295
1401
|
size: "lg"
|
|
1296
1402
|
},
|
|
1297
1403
|
"Lessons"
|
|
1298
|
-
), /* @__PURE__ */ React.createElement(Group, null, /* @__PURE__ */ React.createElement(Stack$
|
|
1404
|
+
), /* @__PURE__ */ React.createElement(Group, null, /* @__PURE__ */ React.createElement(Stack$3, { spacing: 0 }, /* @__PURE__ */ React.createElement(Title, { order: 2, className: classes.title, mt: "md" }, props.displayName || "Lesson"), /* @__PURE__ */ React.createElement(Text, { color: "dimmed", className: classes.description, mt: "sm" }, props.description || "No description")), /* @__PURE__ */ React.createElement(Stack$3, { ml: "auto" }, /* @__PURE__ */ React.createElement(
|
|
1299
1405
|
Button,
|
|
1300
1406
|
{
|
|
1301
1407
|
variant: "gradient",
|
|
1302
1408
|
onClick: props.onPreviewClick
|
|
1303
1409
|
},
|
|
1304
1410
|
"Preview"
|
|
1305
|
-
))))), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React.createElement(LoadingOverlay, { visible: props.loading, overlayBlur: 2 }), /* @__PURE__ */ React.createElement(Stack$
|
|
1411
|
+
))))), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React.createElement(LoadingOverlay, { visible: props.loading, overlayBlur: 2 }), /* @__PURE__ */ React.createElement(Stack$3, null, /* @__PURE__ */ React.createElement(StatsGroup, { data: [
|
|
1306
1412
|
{
|
|
1307
1413
|
title: "LESSON COMPLETION",
|
|
1308
1414
|
value: percentageOfLessonsCompleted,
|
|
@@ -1323,14 +1429,14 @@ const Lesson = (props) => {
|
|
|
1323
1429
|
return { value: g.classId, label: g.name };
|
|
1324
1430
|
})
|
|
1325
1431
|
}
|
|
1326
|
-
), /* @__PURE__ */ React.createElement(Stack$
|
|
1432
|
+
), /* @__PURE__ */ React.createElement(Stack$3, { spacing: 0 }, /* @__PURE__ */ React.createElement(
|
|
1327
1433
|
Tabs,
|
|
1328
1434
|
{
|
|
1329
1435
|
value: tab,
|
|
1330
1436
|
data: [
|
|
1331
1437
|
{ label: "By question", value: "question" },
|
|
1332
|
-
{ label: "By
|
|
1333
|
-
{ label: "By
|
|
1438
|
+
{ label: "By student", value: "students" },
|
|
1439
|
+
{ label: "By reflection", value: "reflections" }
|
|
1334
1440
|
],
|
|
1335
1441
|
onChange: setTab
|
|
1336
1442
|
}
|
|
@@ -1401,7 +1507,7 @@ const useStyles$2 = createStyles((theme) => ({
|
|
|
1401
1507
|
}));
|
|
1402
1508
|
const Lessons = (props) => {
|
|
1403
1509
|
const { classes } = useStyles$2();
|
|
1404
|
-
return /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$
|
|
1510
|
+
return /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$3, { spacing: "md" }, /* @__PURE__ */ React.createElement(Grid, null, /* @__PURE__ */ React.createElement(Grid.Col, { sm: "auto" }, /* @__PURE__ */ React.createElement(Badge$1, { variant: "filled", size: "lg" }, "Lessons"), /* @__PURE__ */ React.createElement(Title, { order: 2, className: classes.title, mt: "md" }, "Lessons"), /* @__PURE__ */ React.createElement(Text, { color: "dimmed", className: classes.description, mt: "sm" }, "Explore units of instruction and/or see corresponding class progress."))), /* @__PURE__ */ React.createElement(
|
|
1405
1511
|
Autocomplete,
|
|
1406
1512
|
{
|
|
1407
1513
|
placeholder: "Search for a lesson that fits your needs",
|
|
@@ -1515,7 +1621,7 @@ const Navbar = (props) => {
|
|
|
1515
1621
|
onClick: () => props.navigate(link.href)
|
|
1516
1622
|
}
|
|
1517
1623
|
));
|
|
1518
|
-
return /* @__PURE__ */ React.createElement(Navbar$1, { width: { base: 80 }, p: "md" }, /* @__PURE__ */ React.createElement(Center, null, /* @__PURE__ */ React.createElement(Avatar, { color: "blue", radius: "sm" }, /* @__PURE__ */ React.createElement("div", { style: { width: 15, marginLeft: "auto", marginRight: "auto" } }, /* @__PURE__ */ React.createElement(Image, { fit: "contain", src: "https://cdn.localcivics.io/brand/l.png" })))), /* @__PURE__ */ React.createElement(Navbar$1.Section, { grow: true, mt: 50 }, /* @__PURE__ */ React.createElement(Stack$
|
|
1624
|
+
return /* @__PURE__ */ React.createElement(Navbar$1, { width: { base: 80 }, p: "md" }, /* @__PURE__ */ React.createElement(Center, null, /* @__PURE__ */ React.createElement(Avatar, { color: "blue", radius: "sm" }, /* @__PURE__ */ React.createElement("div", { style: { width: 15, marginLeft: "auto", marginRight: "auto" } }, /* @__PURE__ */ React.createElement(Image, { fit: "contain", src: "https://cdn.localcivics.io/brand/l.png" })))), /* @__PURE__ */ React.createElement(Navbar$1.Section, { grow: true, mt: 50 }, /* @__PURE__ */ React.createElement(Stack$3, { justify: "center", spacing: 0 }, links)), /* @__PURE__ */ React.createElement(Navbar$1.Section, null, /* @__PURE__ */ React.createElement(Stack$3, { justify: "center", spacing: 0 }, /* @__PURE__ */ React.createElement(
|
|
1519
1625
|
NavbarLink,
|
|
1520
1626
|
{
|
|
1521
1627
|
icon: IconSwitchHorizontal,
|