@capytale/meta-player 0.5.2 → 0.5.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capytale/meta-player",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "vite",
package/src/App.tsx CHANGED
@@ -34,7 +34,8 @@ const App: FC<AppProps> = (props) => {
34
34
  const isPedagoVisible = useAppSelector(selectIsPedagoVisible) as boolean;
35
35
  const hasInstructions = useAppSelector(selectHasInstructions);
36
36
  const hasGradingOrComments = useAppSelector(selectHasGradingOrComments);
37
- const hasPedago = hasInstructions || hasGradingOrComments || mode === "review";
37
+ const hasPedago =
38
+ hasInstructions || hasGradingOrComments || mode === "review";
38
39
  const dispatch = useAppDispatch();
39
40
  const showPedago = hasPedago && isPedagoVisible;
40
41
  const isDirty = useAppSelector(selectIsDirty);
@@ -118,7 +119,9 @@ const App: FC<AppProps> = (props) => {
118
119
  </SplitterPanel>
119
120
  <SplitterPanel minSize={40} size={70} className={styles.contentPanel}>
120
121
  <div className="meta-player-content-cover"></div>
121
- <div id="meta-player-content">{props.children}</div>
122
+ <div id="meta-player-content" aria-label="Activité">
123
+ {props.children}
124
+ </div>
122
125
  </SplitterPanel>
123
126
  </Splitter>
124
127
  </div>
@@ -15,12 +15,22 @@ const ActivityInfo: React.FC = () => {
15
15
  return (
16
16
  <div className={styles.activityInfo}>
17
17
  <div className={styles.activityInfoText}>
18
- <div className={styles.activityInfoTitle}>{activityInfo.title}</div>
18
+ <div
19
+ className={styles.activityInfoTitle}
20
+ aria-label="Titre de l'activité"
21
+ >
22
+ {activityInfo.title}
23
+ </div>
19
24
  {mode === "assignment" && studentName && (
20
- <div className={styles.activityInfoStudentName}>{studentName}</div>
25
+ <div
26
+ className={styles.activityInfoStudentName}
27
+ aria-label="Nom de l'élève"
28
+ >
29
+ {studentName}
30
+ </div>
21
31
  )}
22
32
  {mode === "create" && (
23
- <div className={styles.activityInfoStudentName}>
33
+ <div className={styles.activityInfoStudentName} aria-label="Mode">
24
34
  Création d'activité
25
35
  </div>
26
36
  )}
@@ -28,6 +38,7 @@ const ActivityInfo: React.FC = () => {
28
38
  {icon?.path && (
29
39
  <img
30
40
  className={styles.activityLogo}
41
+ aria-label="Logo de l'activité"
31
42
  src={icon.path}
32
43
  style={{
33
44
  backgroundColor: icon.style
@@ -15,7 +15,10 @@ import { selectHasAntiCheat } from "../activityData/activityDataSlice";
15
15
  import AttachedFilesSidebarContent from "./AttachedFilesSidebarContent";
16
16
  import { Badge } from "primereact/badge";
17
17
  import { useAttachedFiles } from "../functionalities/hooks";
18
- import { selectAttachedFilesEnabled, selectAttachedFilesOptions } from "../functionalities/functionalitiesSlice";
18
+ import {
19
+ selectAttachedFilesEnabled,
20
+ selectAttachedFilesOptions,
21
+ } from "../functionalities/functionalitiesSlice";
19
22
 
20
23
  const ActivityMenu: React.FC = memo(() => {
21
24
  const [settingsSidebarVisible, setSettingsSidebarVisible] = useState(false);
@@ -37,6 +40,7 @@ const ActivityMenu: React.FC = memo(() => {
37
40
  <ActivityQuickActions />
38
41
  {attachedFilesEnabled && (
39
42
  <Button
43
+ aria-label="Afficher les fichiers joints"
40
44
  severity="secondary"
41
45
  size="small"
42
46
  icon={
@@ -60,6 +64,7 @@ const ActivityMenu: React.FC = memo(() => {
60
64
  />
61
65
  )}
62
66
  <Button
67
+ aria-label="Afficher les paramètres"
63
68
  severity="secondary"
64
69
  size="small"
65
70
  icon="pi pi-cog" // pi-ellipsis-v
@@ -73,6 +78,7 @@ const ActivityMenu: React.FC = memo(() => {
73
78
  />
74
79
  {!hasAntiCheat && (
75
80
  <Button
81
+ aria-label="Mettre en plein écran"
76
82
  severity="secondary"
77
83
  size="small"
78
84
  icon={isFullscreen ? "pi pi-expand" : "pi pi-expand"}
@@ -87,6 +93,7 @@ const ActivityMenu: React.FC = memo(() => {
87
93
  )}
88
94
  {isInIframe && (
89
95
  <Button
96
+ aria-label="Retour à la liste des activités (droite)"
90
97
  severity="secondary"
91
98
  size="small"
92
99
  icon={"pi pi-times"}
@@ -16,6 +16,7 @@ const ActivityQuickActions: FC<{}> = () => {
16
16
  <>
17
17
  {quickActions.map((action) => (
18
18
  <Button
19
+ aria-label={action.title}
19
20
  key={action.title}
20
21
  severity="secondary"
21
22
  size="small"
@@ -16,6 +16,7 @@ const ActivitySidebarActions: FC<{}> = () => {
16
16
  <>
17
17
  {sidebarActions.map((action) => (
18
18
  <Button
19
+ aria-label={action.title}
19
20
  key={action.title}
20
21
  severity="secondary"
21
22
  size="small"
@@ -28,6 +28,7 @@ const AttachedFilesSidebarContent: FC = () => {
28
28
  {attachedFilesOptions.uploadTemporaryFiles && (
29
29
  <div className={styles.uploadFilesButtonContainer}>
30
30
  <Button
31
+ aria-label="Ajouter fichier temporaire"
31
32
  icon="pi pi-upload"
32
33
  label={
33
34
  attachedFilesOptions.uploadTemporaryFiles?.uploadButtonLabel ||
@@ -1,5 +1,5 @@
1
1
  import { Button } from "primereact/button";
2
- import { SplitButton } from "primereact/splitbutton";
2
+ import { ButtonGroup } from "primereact/buttongroup";
3
3
  import { ConfirmDialog, confirmDialog } from "primereact/confirmdialog";
4
4
  import { Toast } from "primereact/toast";
5
5
  import { OverlayPanel } from "primereact/overlaypanel";
@@ -78,6 +78,7 @@ const CapytaleMenu: React.FC = () => {
78
78
  <div className={styles.capytaleMenu}>
79
79
  {isInIframe && (
80
80
  <Button
81
+ aria-label="Retour à la liste des activités (gauche)"
81
82
  label="Retour"
82
83
  icon="pi pi-chevron-left"
83
84
  size="small"
@@ -96,6 +97,7 @@ const CapytaleMenu: React.FC = () => {
96
97
  <Countdown />
97
98
  <Button
98
99
  label={isQuiteSmall ? undefined : "Enregistrer"}
100
+ aria-label="Enregistrer"
99
101
  disabled={!isDirty}
100
102
  severity={"warning"}
101
103
  size="small"
@@ -116,51 +118,60 @@ const CapytaleMenu: React.FC = () => {
116
118
  }
117
119
 
118
120
  {mode === "create" && sharingInfo.code && (
119
- <SplitButton
120
- label={isLarge ? sharingInfo.code : undefined}
121
- severity="secondary"
122
- size="small"
123
- icon="pi pi-share-alt"
124
- outlined
125
- buttonProps={{
126
- tooltip: "Copier le code de partage",
127
- tooltipOptions: {
121
+ <ButtonGroup>
122
+ <Button
123
+ label={isLarge ? sharingInfo.code : undefined}
124
+ aria-label="Copier le code de partage"
125
+ severity="secondary"
126
+ size="small"
127
+ icon="pi pi-share-alt"
128
+ outlined
129
+ tooltip="Copier le code de partage"
130
+ tooltipOptions={{
128
131
  position: "bottom",
129
132
  showDelay: settings.TOOLTIP_SHOW_DELAY,
130
- },
131
- }}
132
- onClick={async () => {
133
- await copyToClipboard(sharingInfo.code!);
134
- toast.current!.show({
135
- summary: "Code copié",
136
- detail: "Le code de partage a été copié dans le presse-papier.",
137
- severity: "info",
138
- life: 2000,
139
- });
140
- }}
141
- model={[
142
- {
143
- label: "Copier l'URL de partage",
144
- icon: "pi pi-link",
145
- command: () => {
146
- copyToClipboard(sharingInfo.codeLink!).then(() => {
147
- toast.current!.show({
148
- summary: "URL copiée",
149
- detail:
150
- "L'URL de partage a été copiée dans le presse-papier.",
151
- severity: "info",
152
- life: 2000,
153
- });
133
+ }}
134
+ onClick={async () => {
135
+ await copyToClipboard(sharingInfo.code!);
136
+ toast.current!.show({
137
+ summary: "Code copié",
138
+ detail:
139
+ "Le code de partage a été copié dans le presse-papier.",
140
+ severity: "info",
141
+ life: 2000,
142
+ });
143
+ }}
144
+ />
145
+ <Button
146
+ aria-label="Copier l'URL de partage"
147
+ icon="pi pi-link"
148
+ severity="secondary"
149
+ size="small"
150
+ outlined
151
+ tooltip="Copier l'URL de partage"
152
+ tooltipOptions={{
153
+ position: "bottom",
154
+ showDelay: settings.TOOLTIP_SHOW_DELAY,
155
+ }}
156
+ onClick={() => {
157
+ copyToClipboard(sharingInfo.codeLink!).then(() => {
158
+ toast.current!.show({
159
+ summary: "URL copiée",
160
+ detail:
161
+ "L'URL de partage a été copiée dans le presse-papier.",
162
+ severity: "info",
163
+ life: 2000,
154
164
  });
155
- },
156
- },
157
- ]}
158
- />
165
+ });
166
+ }}
167
+ />
168
+ </ButtonGroup>
159
169
  )}
160
170
  {showWorkflow && (
161
171
  <>
162
172
  {mode === "assignment" && workflow === "current" && (
163
173
  <Button
174
+ aria-label="Rendre la copie"
164
175
  outlined
165
176
  label="Rendre"
166
177
  icon="pi pi-envelope"
@@ -171,6 +182,11 @@ const CapytaleMenu: React.FC = () => {
171
182
  )}
172
183
  {mode === "assignment" && workflow !== "current" && (
173
184
  <Button
185
+ aria-label={
186
+ workflow === "finished"
187
+ ? "Copie déjà rendue"
188
+ : "Copie déjà rendue et corrigée"
189
+ }
174
190
  outlined
175
191
  label={workflow === "finished" ? "Rendue" : "Corrigée"}
176
192
  disabled
@@ -185,6 +201,7 @@ const CapytaleMenu: React.FC = () => {
185
201
  {mode === "review" && (
186
202
  <div>
187
203
  <ButtonDoubleIcon
204
+ aria-label="Changer l'état de la copie"
188
205
  severity="secondary"
189
206
  size="small"
190
207
  outlined
@@ -208,7 +225,10 @@ const CapytaleMenu: React.FC = () => {
208
225
  }
209
226
  rightIcon="pi pi-angle-down"
210
227
  />
211
- <OverlayPanel ref={overlayPanelWorkflow}>
228
+ <OverlayPanel
229
+ ref={overlayPanelWorkflow}
230
+ aria-label="Panneau de changement d'état de la copie"
231
+ >
212
232
  <h3 className={styles.overlayPanelWorkflowTitle}>
213
233
  État de la copie
214
234
  </h3>
@@ -175,6 +175,7 @@ const Countdown: FC = () => {
175
175
  if (diffMs >= MS_PER_DAY) {
176
176
  return (
177
177
  <div
178
+ aria-label="Deadline"
178
179
  style={{
179
180
  display: "flex",
180
181
  alignItems: "center",
@@ -200,7 +201,12 @@ const Countdown: FC = () => {
200
201
  })
201
202
  .split(", ")
202
203
  .map((s, i) => (
203
- <div key={i}>{s}</div>
204
+ <div
205
+ key={i}
206
+ aria-label={i === 0 ? "Date limite" : "Heure limite"}
207
+ >
208
+ {s}
209
+ </div>
204
210
  ))}
205
211
  </div>
206
212
  </div>
@@ -209,6 +215,7 @@ const Countdown: FC = () => {
209
215
  if (diffMs <= 0) {
210
216
  return (
211
217
  <div
218
+ aria-label="Temps écoulé"
212
219
  style={{
213
220
  display: "flex",
214
221
  alignItems: "center",
@@ -227,6 +234,7 @@ const Countdown: FC = () => {
227
234
  const hours = Math.floor(diffSeconds / 3600) % 24;
228
235
  return (
229
236
  <div
237
+ aria-label="Temps restant"
230
238
  style={{
231
239
  display: "flex",
232
240
  alignItems: "center",
@@ -81,18 +81,20 @@ const GradingNav: React.FC = () => {
81
81
  return (
82
82
  <div className="p-inputgroup flex-1">
83
83
  <Button
84
+ aria-label="Passer à la copie précédente"
84
85
  size="small"
85
86
  icon="pi pi-chevron-left"
86
87
  severity="secondary"
87
88
  onClick={handlePrev}
88
89
  tooltip="Copie précédente"
89
90
  tooltipOptions={{
90
- position: "left"
91
+ position: "left",
91
92
  }}
92
93
  disabled={nid == firstNid}
93
94
  outlined
94
95
  />
95
96
  <Dropdown
97
+ aria-label="Sélectionner une copie"
96
98
  value={nid}
97
99
  options={options}
98
100
  filter
@@ -101,13 +103,14 @@ const GradingNav: React.FC = () => {
101
103
  }}
102
104
  />
103
105
  <Button
106
+ aria-label="Passer à la copie suivante"
104
107
  size="small"
105
108
  icon="pi pi-chevron-right"
106
109
  severity="secondary"
107
110
  onClick={handleNext}
108
111
  tooltip="Copie suivante"
109
112
  tooltipOptions={{
110
- position: "right"
113
+ position: "right",
111
114
  }}
112
115
  disabled={nid == lastNid}
113
116
  outlined
@@ -6,7 +6,7 @@ import styles from "./style.module.scss";
6
6
  const ReviewNavbar: FC = () => {
7
7
  return (
8
8
  <div className={styles.reviewNavbar}>
9
- <div>Mode correction</div>
9
+ <div aria-label="Indicateur de mode correction">Mode correction</div>
10
10
  <div>
11
11
  <GradingNav />
12
12
  </div>
@@ -42,6 +42,7 @@ const SettingsSidebarContent: FC<SettingsSidebarContentProps> = (props) => {
42
42
  <div className={styles.sidebarCapytaleActions}>
43
43
  {props.showHelp && (
44
44
  <Button
45
+ aria-label="Voir la documentation"
45
46
  severity="secondary"
46
47
  size="small"
47
48
  icon={"pi pi-question-circle"}
@@ -61,6 +62,7 @@ const SettingsSidebarContent: FC<SettingsSidebarContentProps> = (props) => {
61
62
  <>
62
63
  <ConfirmPopup />
63
64
  <Button
65
+ aria-label="Réinitialiser l'activité"
64
66
  severity="secondary"
65
67
  size="small"
66
68
  icon={"pi pi-undo"}
@@ -104,6 +106,7 @@ const SettingsSidebarContent: FC<SettingsSidebarContentProps> = (props) => {
104
106
  <div className="sidebarRadioButtons">
105
107
  <div className="sidebarRadioGroup">
106
108
  <RadioButton
109
+ aria-label="Option de disposition horizontale"
107
110
  inputId="rb-horizontal"
108
111
  name="horizontal"
109
112
  value="horizontal"
@@ -116,6 +119,7 @@ const SettingsSidebarContent: FC<SettingsSidebarContentProps> = (props) => {
116
119
  </div>
117
120
  <div className="sidebarRadioGroup">
118
121
  <RadioButton
122
+ aria-label="Option de disposition verticale"
119
123
  inputId="rb-vertical"
120
124
  name="vertical"
121
125
  value="vertical"
@@ -134,6 +138,7 @@ const SettingsSidebarContent: FC<SettingsSidebarContentProps> = (props) => {
134
138
  <div className="sidebarRadioButtons">
135
139
  <div className="sidebarRadioGroup">
136
140
  <RadioButton
141
+ aria-label="Option de thème clair"
137
142
  inputId="rb-light"
138
143
  name="light"
139
144
  value="light"
@@ -149,6 +154,7 @@ const SettingsSidebarContent: FC<SettingsSidebarContentProps> = (props) => {
149
154
  </div>
150
155
  <div className="sidebarRadioGroup">
151
156
  <RadioButton
157
+ aria-label="Option de thème sombre"
152
158
  inputId="rb-dark"
153
159
  name="dark"
154
160
  value="dark"
@@ -164,6 +170,7 @@ const SettingsSidebarContent: FC<SettingsSidebarContentProps> = (props) => {
164
170
  </div>
165
171
  <div className="sidebarRadioGroup">
166
172
  <RadioButton
173
+ aria-label="Option de thème système"
167
174
  inputId="rb-auto"
168
175
  name="auto"
169
176
  value="auto"
@@ -22,7 +22,11 @@ const Navbar: React.FC = () => {
22
22
  <div className={styles.navbar}>
23
23
  <div className={styles.navbarContainer}>
24
24
  <div className={styles.navbarLogo}>
25
- {!isInIframe && <a href={returnUrl}>{logoText}</a>}
25
+ {!isInIframe && (
26
+ <a href={returnUrl} aria-label="Capytale (accueil)">
27
+ {logoText}
28
+ </a>
29
+ )}
26
30
  </div>
27
31
  <CapytaleMenu />
28
32
  <ActivityInfo />
@@ -43,7 +43,7 @@ export const CloseOnlyPedagoCommands: FC = () => {
43
43
  icon="pi pi-times"
44
44
  rounded
45
45
  text
46
- aria-label="Masquer l'évaluation"
46
+ aria-label="Masquer consignes et évaluation"
47
47
  tooltip="Masquer l'évaluation"
48
48
  tooltipOptions={{
49
49
  position: "left",
@@ -90,7 +90,7 @@ const HorizontalPedagoCommands = () => {
90
90
  icon="pi pi-times"
91
91
  rounded
92
92
  text
93
- aria-label="Masquer les consignes"
93
+ aria-label="Masquer consignes et évaluation"
94
94
  tooltip="Masquer les consignes"
95
95
  tooltipOptions={{
96
96
  position: "left",
@@ -132,6 +132,7 @@ const DocumentSelectorItemActions: FC<{
132
132
  </div>
133
133
  {item.value !== "pdf" && (
134
134
  <SelectButton
135
+ aria-label={`Sélectionner le type de ${item.name}`}
135
136
  className={styles.smallSelectButton}
136
137
  value={
137
138
  item.value === "instructions"
@@ -241,7 +242,7 @@ const VerticalPedagoCommands = () => {
241
242
  icon="pi pi-times"
242
243
  rounded
243
244
  text
244
- aria-label="Masquer les consignes"
245
+ aria-label="Masquer consignes et évaluation"
245
246
  tooltip="Masquer les consignes"
246
247
  tooltipOptions={{
247
248
  position: "left",
@@ -73,6 +73,7 @@ const Pedago: React.FC<DivProps> = ({ className, ...props }) => {
73
73
  >
74
74
  {mayReverse([
75
75
  <SplitterPanel
76
+ aria-label="Panneau de notation"
76
77
  key="gradingPanel"
77
78
  minSize={30}
78
79
  size={40}
@@ -81,6 +82,7 @@ const Pedago: React.FC<DivProps> = ({ className, ...props }) => {
81
82
  <Grading />
82
83
  </SplitterPanel>,
83
84
  <SplitterPanel
85
+ aria-label="Panneau de consignes"
84
86
  key="pedagoPanel"
85
87
  minSize={50}
86
88
  size={60}
@@ -138,6 +140,7 @@ const Grading: FC = () => {
138
140
  <div className={styles.pedagoFeedback}>
139
141
  {(comments || mode !== "assignment") && (
140
142
  <textarea
143
+ aria-label="Saisie de l'appréciation"
141
144
  value={comments || ""}
142
145
  placeholder={
143
146
  mode !== "review" ? "" : "Rédigez ici l'appréciation."
@@ -159,6 +162,7 @@ const Grading: FC = () => {
159
162
  <div className={styles.pedagoGrade}>
160
163
  {(grading || mode !== "assignment") && (
161
164
  <textarea
165
+ aria-label="Saisie de l'évaluation"
162
166
  value={grading || ""}
163
167
  placeholder={
164
168
  mode !== "review"
package/src/index.css CHANGED
@@ -126,3 +126,7 @@ body,
126
126
  .anti-cheat h1:first-child {
127
127
  margin-top: 0;
128
128
  }
129
+
130
+ .p-button-group .p-button:not(:last-child):not(:active):not(:focus) {
131
+ border-right: 0 !important;
132
+ }
@@ -14,6 +14,8 @@ const CardSelector = function <ValueType>(props: CardSelectorProps<ValueType>) {
14
14
  <div
15
15
  className={styles.cardSelectorOption}
16
16
  data-selected={props.selected === option.value}
17
+ role="button"
18
+ aria-label={`Sélectionner l'option ${option.title}`}
17
19
  onClick={() => {
18
20
  props.onChange(option.value);
19
21
  }}