@capytale/meta-player 0.1.0 → 0.1.2

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.1.0",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "vite",
@@ -4,6 +4,7 @@ import {
4
4
  ReactNode,
5
5
  createContext,
6
6
  useContext,
7
+ useEffect,
7
8
  useState,
8
9
  } from "react";
9
10
 
@@ -17,6 +18,8 @@ import { useAppDispatch } from "../../app/hooks";
17
18
  import ActivitySession from "@capytale/activity.js/activity/activitySession";
18
19
  import { setActivityJSData } from "../activityData/activityDataSlice";
19
20
 
21
+ import tracker from "@capytale/activity.js/backend/capytale/tracker";
22
+
20
23
  const ActivityJSContext = createContext<ActivitySessionLoaderReturnValue>({
21
24
  state: "loading",
22
25
  activitySession: null,
@@ -32,10 +35,14 @@ export const ActivityJSProvider: FC<ActivityJSProviderProps> = (props) => {
32
35
  const activityId = getIdFromUrl();
33
36
  const dispatch = useAppDispatch();
34
37
 
38
+ useEffect(() => {
39
+ tracker.trackPageView();
40
+ }, []);
41
+
35
42
  const callback = (data: ActivitySession) => {
36
43
  //@ts-expect-error
37
44
  window.capy = data;
38
-
45
+
39
46
  const ab = data.activityBunch;
40
47
  /*
41
48
  console.log("Test accès");
@@ -87,6 +94,7 @@ export const ActivityJSProvider: FC<ActivityJSProviderProps> = (props) => {
87
94
  workflow: ab.assignmentNode?.workflow,
88
95
  }),
89
96
  );
97
+ tracker.trackActivity(data);
90
98
  setLoaded(true);
91
99
  };
92
100
 
@@ -7,6 +7,8 @@ import SidebarContent from "./SidebarContent";
7
7
  import settings from "../../settings";
8
8
  import ActivityQuickActions from "./ActivityQuickActions";
9
9
  import useFullscreen from "../../utils/useFullscreen";
10
+ import { useActivityJS } from "../activityJS/ActivityJSProvider";
11
+ import { Dialog } from "primereact/dialog";
10
12
 
11
13
  const ActivityMenu: React.FC = memo(() => {
12
14
  const [settingsSidebarVisible, setSettingsSidebarVisible] = useState(false);
@@ -14,13 +16,15 @@ const ActivityMenu: React.FC = memo(() => {
14
16
  const isFullscreen = useFullscreen(wantFullscreen, () =>
15
17
  setWantFullscreen(false),
16
18
  );
19
+ const [helpDialogVisible, setHelpDialogVisible] = useState(false);
20
+ const activityJS = useActivityJS();
17
21
  return (
18
22
  <div className={styles.activityMenu}>
19
23
  <ActivityQuickActions />
20
24
  <Button
21
25
  severity="secondary"
22
26
  size="small"
23
- icon={isFullscreen ? "pi pi-expand" : "pi pi-expand" }
27
+ icon={isFullscreen ? "pi pi-expand" : "pi pi-expand"}
24
28
  text
25
29
  tooltip="Plein écran"
26
30
  tooltipOptions={{
@@ -47,8 +51,32 @@ const ActivityMenu: React.FC = memo(() => {
47
51
  position="right"
48
52
  onHide={() => setSettingsSidebarVisible(false)}
49
53
  >
50
- <SidebarContent />
54
+ <SidebarContent
55
+ showHelp={
56
+ activityJS.activitySession?.type.helpUrl
57
+ ? () => {
58
+ setHelpDialogVisible(true);
59
+ setSettingsSidebarVisible(false);
60
+ }
61
+ : undefined
62
+ }
63
+ />
51
64
  </Sidebar>
65
+ {activityJS.activitySession?.type.helpUrl && (
66
+ <Dialog
67
+ id="metaPlayerHelpDialog"
68
+ header="Documentation"
69
+ visible={helpDialogVisible}
70
+ onHide={() => setHelpDialogVisible(false)}
71
+ maximizable={true}
72
+ >
73
+ <iframe
74
+ src={activityJS.activitySession?.type.helpUrl}
75
+ style={{ width: "100%", height: "100%" }}
76
+ title="Documentation"
77
+ />
78
+ </Dialog>
79
+ )}
52
80
  </div>
53
81
  );
54
82
  });
@@ -1,9 +1,10 @@
1
1
  import { Button } from "primereact/button";
2
2
  import { SplitButton } from "primereact/splitbutton";
3
3
  import { ConfirmDialog, confirmDialog } from "primereact/confirmdialog";
4
+ import { Toast } from "primereact/toast";
4
5
 
5
6
  import styles from "./style.module.scss";
6
- import { useMemo } from "react";
7
+ import { useMemo, useRef } from "react";
7
8
  import { useWindowSize } from "@uidotdev/usehooks";
8
9
  import { ML, XL } from "../../utils/breakpoints";
9
10
  import { useAppDispatch, useAppSelector } from "../../app/hooks";
@@ -38,6 +39,7 @@ const CapytaleMenu: React.FC = () => {
38
39
  () => windowsSize.width && windowsSize.width < ML,
39
40
  [windowsSize.width],
40
41
  );
42
+ const toast = useRef<Toast>(null);
41
43
  const changeWorkflow = (value: wf) => {
42
44
  dispatch(setWorkflow(value));
43
45
  dispatch(setSaveState("should-save"));
@@ -55,134 +57,151 @@ const CapytaleMenu: React.FC = () => {
55
57
  });
56
58
  };
57
59
  return (
58
- <div className={styles.capytaleMenu}>
59
- {showSaveButton && (
60
- <Button
61
- label={isQuiteSmall ? undefined : "Enregistrer"}
62
- disabled={!isDirty}
63
- severity={"warning"}
64
- size="small"
65
- icon="pi pi-save"
66
- loading={saveState !== "idle"}
67
- tooltip={isDirty ? "Enregistrer l'activité" : "Rien à enregistrer"}
68
- tooltipOptions={{
69
- position: "bottom",
70
- showDelay: settings.TOOLTIP_SHOW_DELAY,
71
- showOnDisabled: true,
72
- }}
73
- onClick={() => {
74
- dispatch(setSaveState("should-save"));
75
- }}
76
- />
77
- )}
78
-
79
- {mode === "create" && (
80
- <SplitButton
81
- label={isLarge ? sharingInfo.code : undefined}
82
- severity="secondary"
83
- size="small"
84
- icon="pi pi-share-alt"
85
- outlined
86
- buttonProps={{
87
- tooltip: "Copier le code de partage",
88
- tooltipOptions: {
60
+ <>
61
+ <Toast ref={toast} position="bottom-right" />
62
+ <div className={styles.capytaleMenu}>
63
+ {showSaveButton && (
64
+ <Button
65
+ label={isQuiteSmall ? undefined : "Enregistrer"}
66
+ disabled={!isDirty}
67
+ severity={"warning"}
68
+ size="small"
69
+ icon="pi pi-save"
70
+ loading={saveState !== "idle"}
71
+ tooltip={isDirty ? "Enregistrer l'activité" : "Rien à enregistrer"}
72
+ tooltipOptions={{
89
73
  position: "bottom",
90
74
  showDelay: settings.TOOLTIP_SHOW_DELAY,
91
- },
92
- }}
93
- onClick={() => {
94
- copyToClipboard(sharingInfo.code);
95
- }}
96
- model={[
97
- {
98
- label: "Copier l'URL de partage",
99
- icon: "pi pi-link",
100
- command: () => {
101
- copyToClipboard(sharingInfo.codeLink);
75
+ showOnDisabled: true,
76
+ }}
77
+ onClick={() => {
78
+ dispatch(setSaveState("should-save"));
79
+ }}
80
+ />
81
+ )}
82
+
83
+ {mode === "create" && (
84
+ <SplitButton
85
+ label={isLarge ? sharingInfo.code : undefined}
86
+ severity="secondary"
87
+ size="small"
88
+ icon="pi pi-share-alt"
89
+ outlined
90
+ buttonProps={{
91
+ tooltip: "Copier le code de partage",
92
+ tooltipOptions: {
93
+ position: "bottom",
94
+ showDelay: settings.TOOLTIP_SHOW_DELAY,
95
+ },
96
+ }}
97
+ onClick={async () => {
98
+ await copyToClipboard(sharingInfo.code);
99
+ toast.current!.show({
100
+ summary: "Code copié",
101
+ detail: "Le code de partage a été copié dans le presse-papier.",
102
+ severity: "info",
103
+ life: 2000,
104
+ });
105
+ }}
106
+ model={[
107
+ {
108
+ label: "Copier l'URL de partage",
109
+ icon: "pi pi-link",
110
+ command: () => {
111
+ copyToClipboard(sharingInfo.codeLink).then(() => {
112
+ toast.current!.show({
113
+ summary: "URL copiée",
114
+ detail:
115
+ "L'URL de partage a été copiée dans le presse-papier.",
116
+ severity: "info",
117
+ life: 2000,
118
+ });
119
+ });
120
+ },
102
121
  },
103
- },
104
- ]}
105
- />
106
- )}
107
- {mode === "assignment" && workflow === "current" && (
108
- <Button
109
- outlined
110
- label="Rendre"
111
- icon="pi pi-envelope"
112
- onClick={() => {
113
- confirmFinishAssignment();
114
- }}
115
- />
116
- )}
117
- {mode === "assignment" && workflow !== "current" && (
118
- <Button
119
- outlined
120
- label={workflow === "finished" ? "Rendue" : "Corrigée"}
121
- disabled
122
- icon={
123
- workflow === "finished" ? "pi pi-envelope" : "pi pi-check-square"
124
- }
125
- tooltip="Copie déjà rendue"
126
- />
127
- )}
128
- {mode === "review" && (
129
- <SplitButton
130
- label={
131
- workflow === "current"
132
- ? "En cours"
133
- : workflow === "finished"
134
- ? "Rendue"
135
- : "Corrigée"
136
- }
137
- severity="secondary"
138
- size="small"
139
- icon={
140
- workflow === "current"
141
- ? "pi pi-pencil"
142
- : workflow === "finished"
143
- ? "pi pi-envelope"
144
- : "pi pi-check-square"
145
- }
146
- outlined
147
- model={[
148
- ...(workflow === "current"
149
- ? []
150
- : [
151
- {
152
- label: "Réautoriser la modification",
153
- icon: "pi pi-pencil",
154
- command: () => {
155
- changeWorkflow("current");
122
+ ]}
123
+ />
124
+ )}
125
+ {mode === "assignment" && workflow === "current" && (
126
+ <Button
127
+ outlined
128
+ label="Rendre"
129
+ icon="pi pi-envelope"
130
+ onClick={() => {
131
+ confirmFinishAssignment();
132
+ }}
133
+ />
134
+ )}
135
+ {mode === "assignment" && workflow !== "current" && (
136
+ <Button
137
+ outlined
138
+ label={workflow === "finished" ? "Rendue" : "Corrigée"}
139
+ disabled
140
+ icon={
141
+ workflow === "finished" ? "pi pi-envelope" : "pi pi-check-square"
142
+ }
143
+ tooltip="Copie déjà rendue"
144
+ />
145
+ )}
146
+ {mode === "review" && (
147
+ <SplitButton
148
+ label={
149
+ workflow === "current"
150
+ ? "En cours"
151
+ : workflow === "finished"
152
+ ? "Rendue"
153
+ : "Corrigée"
154
+ }
155
+ severity="secondary"
156
+ size="small"
157
+ icon={
158
+ workflow === "current"
159
+ ? "pi pi-pencil"
160
+ : workflow === "finished"
161
+ ? "pi pi-envelope"
162
+ : "pi pi-check-square"
163
+ }
164
+ outlined
165
+ model={[
166
+ ...(workflow === "current"
167
+ ? []
168
+ : [
169
+ {
170
+ label: "Réautoriser la modification",
171
+ icon: "pi pi-pencil",
172
+ command: () => {
173
+ changeWorkflow("current");
174
+ },
156
175
  },
157
- },
158
- ]),
159
- ...(workflow === "finished"
160
- ? []
161
- : [
162
- {
163
- label: "Marquer comme rendue",
164
- icon: "pi pi-envelope",
165
- command: () => {
166
- changeWorkflow("finished");
176
+ ]),
177
+ ...(workflow === "finished"
178
+ ? []
179
+ : [
180
+ {
181
+ label: "Marquer comme rendue",
182
+ icon: "pi pi-envelope",
183
+ command: () => {
184
+ changeWorkflow("finished");
185
+ },
167
186
  },
168
- },
169
- ]),
170
- ...(workflow === "corrected"
171
- ? []
172
- : [
173
- {
174
- label: "Marquer comme corrigée",
175
- icon: "pi pi-check-square",
176
- command: () => {
177
- changeWorkflow("corrected");
187
+ ]),
188
+ ...(workflow === "corrected"
189
+ ? []
190
+ : [
191
+ {
192
+ label: "Marquer comme corrigée",
193
+ icon: "pi pi-check-square",
194
+ command: () => {
195
+ changeWorkflow("corrected");
196
+ },
178
197
  },
179
- },
180
- ]),
181
- ]}
182
- />
183
- )}
184
- <ConfirmDialog />
185
- </div>
198
+ ]),
199
+ ]}
200
+ />
201
+ )}
202
+ <ConfirmDialog />
203
+ </div>
204
+ </>
186
205
  );
187
206
  };
188
207
 
@@ -20,8 +20,14 @@ import {
20
20
  selectCanChooseTheme,
21
21
  } from "../activityData/activityDataSlice";
22
22
  import { ActivitySettingsDisplay } from "../activitySettings";
23
+ import { Button } from "primereact/button";
24
+ import settings from "../../settings";
23
25
 
24
- const SidebarContent: FC = () => {
26
+ type SidebarContentProps = {
27
+ showHelp?: () => void;
28
+ };
29
+
30
+ const SidebarContent: FC<SidebarContentProps> = (props) => {
25
31
  const canChooseOrientation = useAppSelector(selectCanChoosePedagoLayout);
26
32
  const canChooseTheme = useAppSelector(selectCanChooseTheme);
27
33
  const orientation = useAppSelector(selectOrientation);
@@ -30,6 +36,25 @@ const SidebarContent: FC = () => {
30
36
  const dispatch = useAppDispatch();
31
37
  return (
32
38
  <>
39
+ {props.showHelp && (
40
+ <div className={styles.sidebarCapytaleActions}>
41
+ <Button
42
+ severity="secondary"
43
+ size="small"
44
+ icon={"pi pi-question-circle"}
45
+ onClick={() => {
46
+ props.showHelp!();
47
+ }}
48
+ outlined
49
+ label="Documentation"
50
+ tooltip="Voir la documentation"
51
+ tooltipOptions={{
52
+ position: "left",
53
+ showDelay: settings.TOOLTIP_SHOW_DELAY,
54
+ }}
55
+ />
56
+ </div>
57
+ )}
33
58
  {sidebarActions.length > 0 && (
34
59
  <Fieldset
35
60
  legend="Actions"
@@ -144,3 +144,10 @@
144
144
  flex-direction: column;
145
145
  gap: 6px;
146
146
  }
147
+
148
+ .sidebarCapytaleActions {
149
+ margin-bottom: 8px;
150
+ & > button {
151
+ width: 100%;
152
+ }
153
+ }
package/src/index.css CHANGED
@@ -59,9 +59,6 @@ body,
59
59
 
60
60
  .sidebarFieldset {
61
61
  margin-bottom: 8px;
62
- & .p-button-label {
63
- text-align: left;
64
- }
65
62
  }
66
63
 
67
64
  .sidebarRadioButtons {
@@ -75,3 +72,18 @@ body,
75
72
  gap: 8px;
76
73
  align-items: center;
77
74
  }
75
+
76
+ #metaPlayerHelpDialog {
77
+ width: 80vw;
78
+ height: 80vh;
79
+ }
80
+
81
+ #metaPlayerHelpDialog_content {
82
+ padding: 0;
83
+ & iframe {
84
+ width: 100%;
85
+ height: 100%;
86
+ border: 0;
87
+ display: block;
88
+ }
89
+ }