catchup-library-web 1.0.0 → 1.0.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/dist/index.d.mts +239 -2
- package/dist/index.d.ts +239 -2
- package/dist/index.js +4686 -2
- package/dist/index.mjs +4621 -1
- package/package.json +10 -2
- package/src/components/activities/DropdownActivityContent.tsx +73 -0
- package/src/components/activities/FillInTheBlanksActivityContent.tsx +102 -0
- package/src/components/activities/GroupingActivityContent.tsx +62 -0
- package/src/components/activities/MCMAActivityContent.tsx +65 -0
- package/src/components/activities/MCSAActivityContent.tsx +58 -0
- package/src/components/activities/MatchingActivityContent.tsx +57 -0
- package/src/components/activities/OpenEndedActivityContent.tsx +92 -0
- package/src/components/activities/OrderingActivityContent.tsx +59 -0
- package/src/components/activities/TrueFalseActivityContent.tsx +98 -0
- package/src/components/activities/body-content/ActivityBodyContent.tsx +108 -0
- package/src/components/activities/body-content/ShowBodyMediaByContentType.tsx +404 -0
- package/src/components/activities/empty-content/ActivityEmptyContent.tsx +15 -0
- package/src/components/activities/material-content/DropdownActivityMaterialContent.tsx +227 -0
- package/src/components/activities/material-content/FillInTheBlanksActivityMaterialContent.tsx +270 -0
- package/src/components/activities/material-content/GroupingActivityMaterialContent.tsx +359 -0
- package/src/components/activities/material-content/MCMAActivityMaterialContent.tsx +166 -0
- package/src/components/activities/material-content/MCSAActivityMaterialContent.tsx +165 -0
- package/src/components/activities/material-content/MatchingActivityMaterialContent.tsx +332 -0
- package/src/components/activities/material-content/OpenEndedActivityMaterialContent.tsx +818 -0
- package/src/components/activities/material-content/OrderingActivityMaterialContent.tsx +216 -0
- package/src/components/activities/material-content/ShowMaterialMediaByContentType.tsx +172 -0
- package/src/components/activities/material-content/TrueFalseActivityMaterialContent.tsx +217 -0
- package/src/components/activities/solution-content/ActivitySolutionContent.tsx +86 -0
- package/src/components/dividers/BlueVerticalDividerLine.tsx +13 -0
- package/src/components/dividers/DividerLine.tsx +5 -0
- package/src/components/dividers/VerticalDividerLine.tsx +5 -0
- package/src/components/dnds/DraggableDroppableItem.tsx +62 -0
- package/src/components/dnds/DraggableItem.tsx +41 -0
- package/src/components/dnds/DroppableItem.tsx +38 -0
- package/src/components/dropdowns/MediaDropdown.tsx +51 -0
- package/src/components/groups/InputGroup.tsx +330 -0
- package/src/hooks/useScreenSize.ts +40 -0
- package/src/index.ts +24 -0
- package/src/language/i18n.ts +10 -0
- package/src/properties/ActivityProperties.ts +204 -0
- package/src/properties/ButtonProperties.ts +1 -1
- package/src/properties/CommonProperties.ts +1 -1
- package/src/properties/DividerLineProperties.ts +3 -0
- package/src/properties/DnDProperties.ts +28 -0
- package/src/properties/DropdownProperties.ts +5 -0
- package/src/properties/EnumProperties.ts +11 -0
- package/src/properties/GroupProperties.ts +19 -0
- package/src/utilization/AppUtilization.ts +56 -0
- package/src/utilization/CatchtivityUtilization.ts +1566 -0
- package/src/utilization/StorageUtilization.ts +35 -0
- package/tsconfig.json +2 -1
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import {
|
|
2
|
+
parseBodyMapFromData,
|
|
3
|
+
parseContentMapFromData,
|
|
4
|
+
parseMaterialMapFromData,
|
|
5
|
+
} from "../../utilization/CatchtivityUtilization";
|
|
6
|
+
import ActivityBodyContent from "./body-content/ActivityBodyContent";
|
|
7
|
+
import TrueFalseActivityMaterialContent from "./material-content/TrueFalseActivityMaterialContent";
|
|
8
|
+
import { ITrueFalseActivityProps } from "../../properties/ActivityProperties";
|
|
9
|
+
import DividerLine from "../dividers/DividerLine";
|
|
10
|
+
import VerticalDividerLine from "../dividers/VerticalDividerLine";
|
|
11
|
+
|
|
12
|
+
const TrueFalseActivityContent = ({
|
|
13
|
+
answer,
|
|
14
|
+
data,
|
|
15
|
+
canAnswerQuestion,
|
|
16
|
+
changeAnswer,
|
|
17
|
+
isPreview,
|
|
18
|
+
showCorrectAnswer,
|
|
19
|
+
}: ITrueFalseActivityProps) => {
|
|
20
|
+
const contentMap = parseContentMapFromData(data);
|
|
21
|
+
const trueFalseBodyMap = parseBodyMapFromData(data, "TRUE_FALSE");
|
|
22
|
+
const trueFalseMaterialMap = parseMaterialMapFromData(data, "TRUE_FALSE");
|
|
23
|
+
|
|
24
|
+
const retrieveCurrentAnswerMap = () => {
|
|
25
|
+
let foundIndex = answer.data.findIndex(
|
|
26
|
+
(answerData: any) => answerData.type === "TRUE_FALSE"
|
|
27
|
+
);
|
|
28
|
+
return answer.data[foundIndex].answerMap;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const handleTrueFalseAnswerOnChange = (
|
|
32
|
+
answer: any,
|
|
33
|
+
key: any,
|
|
34
|
+
value: string
|
|
35
|
+
) => {
|
|
36
|
+
const answerMap = retrieveCurrentAnswerMap();
|
|
37
|
+
if (key === "TRUE") {
|
|
38
|
+
const foundFalseIndex = answerMap.falseList.findIndex(
|
|
39
|
+
(item: string) => item === value
|
|
40
|
+
);
|
|
41
|
+
if (foundFalseIndex !== -1) {
|
|
42
|
+
answerMap.falseList.splice(foundFalseIndex, 1);
|
|
43
|
+
}
|
|
44
|
+
const foundTrueIndex = answerMap.falseList.findIndex(
|
|
45
|
+
(item: string) => item === value
|
|
46
|
+
);
|
|
47
|
+
if (foundTrueIndex === -1) {
|
|
48
|
+
answerMap.trueList.push(value);
|
|
49
|
+
}
|
|
50
|
+
} else if (key === "FALSE") {
|
|
51
|
+
const foundTrueIndex = answerMap.trueList.findIndex(
|
|
52
|
+
(item: string) => item === value
|
|
53
|
+
);
|
|
54
|
+
if (foundTrueIndex !== -1) {
|
|
55
|
+
answerMap.trueList.splice(foundTrueIndex, 1);
|
|
56
|
+
}
|
|
57
|
+
const foundFalseIndex = answerMap.falseList.findIndex(
|
|
58
|
+
(item: string) => item === value
|
|
59
|
+
);
|
|
60
|
+
if (foundFalseIndex === -1) {
|
|
61
|
+
answerMap.falseList.push(value);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
changeAnswer(answer);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<div className="flex flex-row flex-wrap">
|
|
69
|
+
<div className="w-full md:w-[40%]">
|
|
70
|
+
<ActivityBodyContent
|
|
71
|
+
bodyMap={trueFalseBodyMap}
|
|
72
|
+
templateType={"GROUPING"}
|
|
73
|
+
/>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<div className="contents md:hidden">
|
|
77
|
+
<DividerLine />
|
|
78
|
+
</div>
|
|
79
|
+
<div className="hidden md:block">
|
|
80
|
+
<VerticalDividerLine />
|
|
81
|
+
</div>
|
|
82
|
+
<div className="w-full md:flex-1">
|
|
83
|
+
<TrueFalseActivityMaterialContent
|
|
84
|
+
uniqueValue={JSON.stringify(data.contentMap)}
|
|
85
|
+
answer={answer}
|
|
86
|
+
materialMap={trueFalseMaterialMap}
|
|
87
|
+
contentMap={contentMap}
|
|
88
|
+
checkCanAnswerQuestion={canAnswerQuestion}
|
|
89
|
+
onChange={handleTrueFalseAnswerOnChange}
|
|
90
|
+
isPreview={isPreview}
|
|
91
|
+
showCorrectAnswer={showCorrectAnswer}
|
|
92
|
+
/>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export default TrueFalseActivityContent;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { IActivityBodyContentProps } from "../../../properties/ActivityProperties";
|
|
2
|
+
import ShowBodyMediaByContentType from "./ShowBodyMediaByContentType";
|
|
3
|
+
|
|
4
|
+
const ActivityBodyContent = ({
|
|
5
|
+
templateType,
|
|
6
|
+
bodyMap,
|
|
7
|
+
contentMap,
|
|
8
|
+
answerMap,
|
|
9
|
+
}: IActivityBodyContentProps) => {
|
|
10
|
+
let currentQQIndex = 0;
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<div className="flex flex-col justify-center items-center">
|
|
14
|
+
{Object.keys(bodyMap).map((key, index) => {
|
|
15
|
+
const body = JSON.parse(bodyMap[key]);
|
|
16
|
+
if (templateType === "DROPDOWN") {
|
|
17
|
+
while (body.value.includes("@@")) {
|
|
18
|
+
if (
|
|
19
|
+
answerMap[currentQQIndex].trim() === "" ||
|
|
20
|
+
answerMap[currentQQIndex].trim() === "DEFAULT_OPTION"
|
|
21
|
+
) {
|
|
22
|
+
body.value = body.value.replace(
|
|
23
|
+
"@@",
|
|
24
|
+
`----(${currentQQIndex + 1})----`
|
|
25
|
+
);
|
|
26
|
+
} else {
|
|
27
|
+
if (contentMap["type"] === "TEXT") {
|
|
28
|
+
body.value = body.value.replace(
|
|
29
|
+
"@@",
|
|
30
|
+
`--TEXT--${answerMap[currentQQIndex]}--TEXT--`
|
|
31
|
+
);
|
|
32
|
+
} else if (contentMap["type"] === "IMAGE") {
|
|
33
|
+
body.value = body.value.replace(
|
|
34
|
+
"@@",
|
|
35
|
+
`--IMAGE--${answerMap[currentQQIndex]}--IMAGE--`
|
|
36
|
+
);
|
|
37
|
+
} else if (contentMap["type"] === "VIDEO") {
|
|
38
|
+
body.value = body.value.replace(
|
|
39
|
+
"@@",
|
|
40
|
+
`--VIDEO--${answerMap[currentQQIndex]}--VIDEO--`
|
|
41
|
+
);
|
|
42
|
+
} else if (contentMap["type"] === "AUDIO") {
|
|
43
|
+
body.value = body.value.replace(
|
|
44
|
+
"@@",
|
|
45
|
+
`--AUDIO--${answerMap[currentQQIndex]}--AUDIO--`
|
|
46
|
+
);
|
|
47
|
+
} else {
|
|
48
|
+
body.value = body.value.replace(
|
|
49
|
+
"@@",
|
|
50
|
+
answerMap[currentQQIndex]
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
currentQQIndex++;
|
|
55
|
+
}
|
|
56
|
+
} else if (templateType === "FILL_IN_THE_BLANKS") {
|
|
57
|
+
while (body.value.includes("@@")) {
|
|
58
|
+
if (answerMap[currentQQIndex].trim() === "") {
|
|
59
|
+
body.value = body.value.replace(
|
|
60
|
+
"@@",
|
|
61
|
+
`----(${currentQQIndex + 1})----`
|
|
62
|
+
);
|
|
63
|
+
} else {
|
|
64
|
+
if (contentMap["type"] === "TEXT") {
|
|
65
|
+
body.value = body.value.replace(
|
|
66
|
+
"@@",
|
|
67
|
+
`--TEXT--${answerMap[currentQQIndex]}--TEXT--`
|
|
68
|
+
);
|
|
69
|
+
} else if (contentMap["type"] === "IMAGE") {
|
|
70
|
+
body.value = body.value.replace(
|
|
71
|
+
"@@",
|
|
72
|
+
`--IMAGE--${answerMap[currentQQIndex]}--IMAGE--`
|
|
73
|
+
);
|
|
74
|
+
} else if (contentMap["type"] === "VIDEO") {
|
|
75
|
+
body.value = body.value.replace(
|
|
76
|
+
"@@",
|
|
77
|
+
`--VIDEO--${answerMap[currentQQIndex]}--VIDEO--`
|
|
78
|
+
);
|
|
79
|
+
} else if (contentMap["type"] === "AUDIO") {
|
|
80
|
+
body.value = body.value.replace(
|
|
81
|
+
"@@",
|
|
82
|
+
`--AUDIO--${answerMap[currentQQIndex]}--AUDIO--`
|
|
83
|
+
);
|
|
84
|
+
} else {
|
|
85
|
+
body.value = body.value.replace(
|
|
86
|
+
"@@",
|
|
87
|
+
answerMap[currentQQIndex]
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
currentQQIndex++;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<ShowBodyMediaByContentType
|
|
97
|
+
index={index}
|
|
98
|
+
type={body.type}
|
|
99
|
+
value={body.value}
|
|
100
|
+
size={body.size}
|
|
101
|
+
/>
|
|
102
|
+
);
|
|
103
|
+
})}
|
|
104
|
+
</div>
|
|
105
|
+
);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export default ActivityBodyContent;
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import Modal from "react-modal";
|
|
3
|
+
import { constructInputWithSpecialExpressionList } from "../../../utilization/CatchtivityUtilization";
|
|
4
|
+
import { InlineMath } from "react-katex";
|
|
5
|
+
import BaseImage from "../../images/BaseImage";
|
|
6
|
+
import i18n from "../../../language/i18n";
|
|
7
|
+
import {
|
|
8
|
+
IInputPart,
|
|
9
|
+
IShowBodyMediaByContentTypeProps,
|
|
10
|
+
} from "../../../properties/ActivityProperties";
|
|
11
|
+
|
|
12
|
+
const ShowBodyMediaByContentType = ({
|
|
13
|
+
index,
|
|
14
|
+
type,
|
|
15
|
+
value,
|
|
16
|
+
size,
|
|
17
|
+
}: IShowBodyMediaByContentTypeProps) => {
|
|
18
|
+
const [showFullScreen, setShowFullScreen] = useState<boolean>(false);
|
|
19
|
+
const [selectedFullScreenItem, setSelectedFullScreenItem] =
|
|
20
|
+
useState<string>("");
|
|
21
|
+
|
|
22
|
+
const convertToPercentage = (size: string) => {
|
|
23
|
+
if (size === "1/3") {
|
|
24
|
+
return "w-small-media";
|
|
25
|
+
} else if (size === "1/2") {
|
|
26
|
+
return "w-medium-media";
|
|
27
|
+
} else if (size === "1") {
|
|
28
|
+
return "w-large-media";
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const retrieveValueParts = (value: string) => {
|
|
33
|
+
let currentIndex = 0;
|
|
34
|
+
const valuePartList = [];
|
|
35
|
+
let copyValue = JSON.parse(JSON.stringify(value));
|
|
36
|
+
currentIndex = 0;
|
|
37
|
+
let checkText = "--TEXT--";
|
|
38
|
+
while (copyValue.includes(checkText)) {
|
|
39
|
+
const firstIndex = copyValue.indexOf(checkText);
|
|
40
|
+
let textValue = copyValue.substring(0, firstIndex);
|
|
41
|
+
let addition = 0;
|
|
42
|
+
if (textValue.trim() !== "") {
|
|
43
|
+
if ((textValue.split("__").length - 1) % 2 === 1) {
|
|
44
|
+
textValue = textValue + "__";
|
|
45
|
+
addition += 2;
|
|
46
|
+
}
|
|
47
|
+
if ((textValue.split("**").length - 1) % 2 === 1) {
|
|
48
|
+
textValue = textValue + "**";
|
|
49
|
+
addition += 2;
|
|
50
|
+
}
|
|
51
|
+
if ((textValue.split("`").length - 1) % 2 === 1) {
|
|
52
|
+
textValue = textValue + "`";
|
|
53
|
+
addition += 1;
|
|
54
|
+
}
|
|
55
|
+
valuePartList.push(
|
|
56
|
+
<span
|
|
57
|
+
key={`${index}-${currentIndex}`}
|
|
58
|
+
className="text-xl whitespace-pre-wrap"
|
|
59
|
+
>
|
|
60
|
+
{constructInputWithSpecialExpressionList(textValue).map(
|
|
61
|
+
(inputPart: IInputPart, index: number) => (
|
|
62
|
+
<span
|
|
63
|
+
key={index}
|
|
64
|
+
className={`${inputPart.isBold ? "font-bold" : ""} ${
|
|
65
|
+
inputPart.isUnderline ? "underline" : ""
|
|
66
|
+
}`}
|
|
67
|
+
>
|
|
68
|
+
{inputPart.isEquation ? (
|
|
69
|
+
<span className="text-2xl">
|
|
70
|
+
<InlineMath math={inputPart.value} />
|
|
71
|
+
</span>
|
|
72
|
+
) : (
|
|
73
|
+
inputPart.value
|
|
74
|
+
)}
|
|
75
|
+
</span>
|
|
76
|
+
)
|
|
77
|
+
)}
|
|
78
|
+
</span>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
const subValue = copyValue.substring(firstIndex + checkText.length);
|
|
82
|
+
const secondIndex =
|
|
83
|
+
subValue.indexOf(checkText) +
|
|
84
|
+
checkText.length +
|
|
85
|
+
textValue.length -
|
|
86
|
+
addition;
|
|
87
|
+
currentIndex++;
|
|
88
|
+
valuePartList.push(
|
|
89
|
+
<span
|
|
90
|
+
key={`${index}-${currentIndex}`}
|
|
91
|
+
className={`text-xl font-bold whitespace-pre-wrap`}
|
|
92
|
+
>
|
|
93
|
+
{constructInputWithSpecialExpressionList(
|
|
94
|
+
copyValue.substring(firstIndex + checkText.length, secondIndex)
|
|
95
|
+
).map((inputPart: IInputPart, index: number) => (
|
|
96
|
+
<span
|
|
97
|
+
key={index}
|
|
98
|
+
className={`${inputPart.isBold ? "font-bold" : ""} ${
|
|
99
|
+
inputPart.isUnderline ? "underline" : ""
|
|
100
|
+
}`}
|
|
101
|
+
>
|
|
102
|
+
{inputPart.isEquation ? (
|
|
103
|
+
<span className="text-2xl">
|
|
104
|
+
<InlineMath math={inputPart.value} />
|
|
105
|
+
</span>
|
|
106
|
+
) : (
|
|
107
|
+
inputPart.value
|
|
108
|
+
)}
|
|
109
|
+
</span>
|
|
110
|
+
))}
|
|
111
|
+
</span>
|
|
112
|
+
);
|
|
113
|
+
copyValue = copyValue.substring(secondIndex + checkText.length);
|
|
114
|
+
if ((copyValue.split("`").length - 1) % 2 === 1) {
|
|
115
|
+
copyValue = "`" + copyValue;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
checkText = "--IMAGE--";
|
|
119
|
+
while (copyValue.includes(checkText)) {
|
|
120
|
+
const firstIndex = copyValue.indexOf(checkText);
|
|
121
|
+
const textValue = copyValue.substring(0, firstIndex);
|
|
122
|
+
if (textValue.trim() !== "") {
|
|
123
|
+
currentIndex++;
|
|
124
|
+
valuePartList.push(
|
|
125
|
+
<p key={`${index}_${currentIndex}`} className="text-xl">
|
|
126
|
+
{textValue}
|
|
127
|
+
</p>
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
const subValue = copyValue.substring(firstIndex + checkText.length);
|
|
131
|
+
const secondIndex =
|
|
132
|
+
subValue.indexOf(checkText) + checkText.length + textValue.length;
|
|
133
|
+
const imageSource = copyValue.substring(
|
|
134
|
+
firstIndex + checkText.length,
|
|
135
|
+
secondIndex
|
|
136
|
+
);
|
|
137
|
+
currentIndex++;
|
|
138
|
+
valuePartList.push(
|
|
139
|
+
<div key={`${index}-${currentIndex}`} className="relative w-[200px]">
|
|
140
|
+
<BaseImage
|
|
141
|
+
src={imageSource}
|
|
142
|
+
alt="media"
|
|
143
|
+
size="custom"
|
|
144
|
+
className="rounded-catchup-xlarge"
|
|
145
|
+
/>
|
|
146
|
+
<div
|
|
147
|
+
className="absolute flex items-center justify-center top-2 right-2 h-6 w-6 cursor-pointer border rounded-catchup-xlarge border-catchup-blue p-1"
|
|
148
|
+
onClick={(event) => {
|
|
149
|
+
setShowFullScreen(true);
|
|
150
|
+
setSelectedFullScreenItem(imageSource);
|
|
151
|
+
}}
|
|
152
|
+
>
|
|
153
|
+
<BaseImage
|
|
154
|
+
src="/icons/arrow-up.png"
|
|
155
|
+
alt="arrow-up"
|
|
156
|
+
size="custom"
|
|
157
|
+
className="w-full"
|
|
158
|
+
/>
|
|
159
|
+
</div>
|
|
160
|
+
</div>
|
|
161
|
+
);
|
|
162
|
+
copyValue = copyValue.substring(secondIndex + checkText.length);
|
|
163
|
+
}
|
|
164
|
+
checkText = "--VIDEO--";
|
|
165
|
+
while (copyValue.includes(checkText)) {
|
|
166
|
+
const firstIndex = copyValue.indexOf(checkText);
|
|
167
|
+
const textValue = copyValue.substring(0, firstIndex);
|
|
168
|
+
if (textValue.trim() !== "") {
|
|
169
|
+
currentIndex++;
|
|
170
|
+
valuePartList.push(
|
|
171
|
+
<p key={`${index}-${currentIndex}`} className="text-xl">
|
|
172
|
+
{textValue}
|
|
173
|
+
</p>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
const subValue = copyValue.substring(firstIndex + checkText.length);
|
|
177
|
+
const secondIndex =
|
|
178
|
+
subValue.indexOf(checkText) + checkText.length + textValue.length;
|
|
179
|
+
const videoSource = copyValue.substring(
|
|
180
|
+
firstIndex + checkText.length,
|
|
181
|
+
secondIndex
|
|
182
|
+
);
|
|
183
|
+
currentIndex++;
|
|
184
|
+
valuePartList.push(
|
|
185
|
+
<video
|
|
186
|
+
key={`${index}-${currentIndex}`}
|
|
187
|
+
src={videoSource}
|
|
188
|
+
className={`w-[200px] rounded-catchup-xlarge`}
|
|
189
|
+
/>
|
|
190
|
+
);
|
|
191
|
+
copyValue = copyValue.substring(secondIndex + checkText.length);
|
|
192
|
+
}
|
|
193
|
+
checkText = "--AUDIO--";
|
|
194
|
+
while (copyValue.includes(checkText)) {
|
|
195
|
+
const firstIndex = copyValue.indexOf(checkText);
|
|
196
|
+
const textValue = copyValue.substring(0, firstIndex);
|
|
197
|
+
if (textValue.trim() !== "") {
|
|
198
|
+
currentIndex++;
|
|
199
|
+
valuePartList.push(
|
|
200
|
+
<p key={`${index}-${currentIndex}`} className="text-xl">
|
|
201
|
+
{textValue}
|
|
202
|
+
</p>
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
const subValue = copyValue.substring(firstIndex + checkText.length);
|
|
206
|
+
const secondIndex =
|
|
207
|
+
subValue.indexOf(checkText) + checkText.length + textValue.length;
|
|
208
|
+
const audioSource = copyValue.substring(
|
|
209
|
+
firstIndex + checkText.length,
|
|
210
|
+
secondIndex
|
|
211
|
+
);
|
|
212
|
+
currentIndex++;
|
|
213
|
+
valuePartList.push(
|
|
214
|
+
<audio
|
|
215
|
+
key={`${index}-${currentIndex}`}
|
|
216
|
+
src={audioSource}
|
|
217
|
+
className={`w-[200px] rounded-catchup-xlarge`}
|
|
218
|
+
/>
|
|
219
|
+
);
|
|
220
|
+
copyValue = copyValue.substring(secondIndex + checkText.length);
|
|
221
|
+
}
|
|
222
|
+
if (copyValue.trim() !== "") {
|
|
223
|
+
currentIndex++;
|
|
224
|
+
if ((copyValue.split("__").length - 1) % 2 === 1) {
|
|
225
|
+
copyValue = "__" + copyValue;
|
|
226
|
+
}
|
|
227
|
+
if ((copyValue.split("**").length - 1) % 2 === 1) {
|
|
228
|
+
copyValue = "**" + copyValue;
|
|
229
|
+
}
|
|
230
|
+
if ((copyValue.split("`").length - 1) % 2 === 1) {
|
|
231
|
+
copyValue = "`" + copyValue;
|
|
232
|
+
}
|
|
233
|
+
const regexMatchImageText = copyValue.match(/<image>([\s\S]*?)<\/image>/);
|
|
234
|
+
if (regexMatchImageText) {
|
|
235
|
+
const imageText = regexMatchImageText[1];
|
|
236
|
+
valuePartList.push(
|
|
237
|
+
<div className="bg-catchup-gray-50 relative px-4 py-4 rounded-catchup-small mt-2">
|
|
238
|
+
<div className="absolute -top-3 bg-catchup-white border rounded-catchup-small px-2 left-2">
|
|
239
|
+
<p className="font-bold">{i18n.t("image_description")}</p>
|
|
240
|
+
</div>
|
|
241
|
+
<span
|
|
242
|
+
key={`${index}-${currentIndex}`}
|
|
243
|
+
className="text-xl whitespace-pre-wrap "
|
|
244
|
+
>
|
|
245
|
+
{imageText}
|
|
246
|
+
</span>
|
|
247
|
+
</div>
|
|
248
|
+
);
|
|
249
|
+
} else {
|
|
250
|
+
valuePartList.push(
|
|
251
|
+
<span
|
|
252
|
+
key={`${index}-${currentIndex}`}
|
|
253
|
+
className="text-xl whitespace-pre-wrap"
|
|
254
|
+
>
|
|
255
|
+
{constructInputWithSpecialExpressionList(copyValue).map(
|
|
256
|
+
(inputPart: IInputPart, index: number) => (
|
|
257
|
+
<span
|
|
258
|
+
key={index}
|
|
259
|
+
className={`${inputPart.isBold ? "font-bold" : ""} ${
|
|
260
|
+
inputPart.isUnderline ? "underline" : ""
|
|
261
|
+
}`}
|
|
262
|
+
>
|
|
263
|
+
{inputPart.isEquation ? (
|
|
264
|
+
<span className="text-2xl">
|
|
265
|
+
<InlineMath math={inputPart.value} />
|
|
266
|
+
</span>
|
|
267
|
+
) : (
|
|
268
|
+
inputPart.value
|
|
269
|
+
)}
|
|
270
|
+
</span>
|
|
271
|
+
)
|
|
272
|
+
)}
|
|
273
|
+
</span>
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return valuePartList;
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
const RenderShowFullScreenItem = () => {
|
|
281
|
+
return (
|
|
282
|
+
<Modal
|
|
283
|
+
isOpen={showFullScreen}
|
|
284
|
+
onAfterOpen={() => {}}
|
|
285
|
+
onRequestClose={() => {
|
|
286
|
+
setShowFullScreen(false);
|
|
287
|
+
setSelectedFullScreenItem("");
|
|
288
|
+
}}
|
|
289
|
+
style={{
|
|
290
|
+
content: {
|
|
291
|
+
top: "50%",
|
|
292
|
+
left: "50%",
|
|
293
|
+
right: "auto",
|
|
294
|
+
bottom: "auto",
|
|
295
|
+
marginRight: "-50%",
|
|
296
|
+
transform: "translate(-50%, -50%)",
|
|
297
|
+
padding: 0,
|
|
298
|
+
borderRadius: 20,
|
|
299
|
+
background: "",
|
|
300
|
+
border: "",
|
|
301
|
+
width: "900px",
|
|
302
|
+
maxHeight: "70%",
|
|
303
|
+
overflow: "auto",
|
|
304
|
+
},
|
|
305
|
+
overlay: {
|
|
306
|
+
background: "rgba(0, 0, 0, 0.6)",
|
|
307
|
+
},
|
|
308
|
+
}}
|
|
309
|
+
contentLabel=""
|
|
310
|
+
>
|
|
311
|
+
<div className="flex-1 flex flex-col">
|
|
312
|
+
{/* <div className="m-4"> */}
|
|
313
|
+
<div className="ml-auto px-5 py-3">
|
|
314
|
+
<BaseImage
|
|
315
|
+
src="/icons/cross-red.png"
|
|
316
|
+
alt="cross-red"
|
|
317
|
+
size="medium"
|
|
318
|
+
onClick={() => {
|
|
319
|
+
setShowFullScreen(false);
|
|
320
|
+
setSelectedFullScreenItem("");
|
|
321
|
+
}}
|
|
322
|
+
/>
|
|
323
|
+
</div>
|
|
324
|
+
<div className="flex items-center justify-center h-[500]">
|
|
325
|
+
<BaseImage
|
|
326
|
+
src={selectedFullScreenItem}
|
|
327
|
+
alt="selected-fullscreen-item"
|
|
328
|
+
size="custom"
|
|
329
|
+
className="w-full"
|
|
330
|
+
/>
|
|
331
|
+
</div>
|
|
332
|
+
</div>
|
|
333
|
+
</Modal>
|
|
334
|
+
);
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
const RenderMainContent = () => {
|
|
338
|
+
if (type === "TEXT") {
|
|
339
|
+
return (
|
|
340
|
+
<div className="mb-3 flex flex-row flex-wrap items-center mx-auto w-full">
|
|
341
|
+
<span>{retrieveValueParts(value)}</span>
|
|
342
|
+
</div>
|
|
343
|
+
);
|
|
344
|
+
} else if (type === "IMAGE") {
|
|
345
|
+
return (
|
|
346
|
+
<div className="mb-3 flex flex-col items-center relative">
|
|
347
|
+
<div
|
|
348
|
+
className={`${
|
|
349
|
+
size ? `${convertToPercentage(size)}` : ""
|
|
350
|
+
} rounded-catchup-xlarge relative`}
|
|
351
|
+
>
|
|
352
|
+
<BaseImage
|
|
353
|
+
src={value}
|
|
354
|
+
alt="body-image"
|
|
355
|
+
size="custom"
|
|
356
|
+
className="w-full rounded-catchup-xlarge"
|
|
357
|
+
/>
|
|
358
|
+
<div
|
|
359
|
+
className="absolute flex items-center justify-center top-2 right-2 h-6 w-6 cursor-pointer border rounded-catchup-xlarge border-catchup-blue p-1"
|
|
360
|
+
onClick={() => {
|
|
361
|
+
setShowFullScreen(true);
|
|
362
|
+
setSelectedFullScreenItem(value);
|
|
363
|
+
}}
|
|
364
|
+
>
|
|
365
|
+
<BaseImage
|
|
366
|
+
src="/icons/arrow-up.png"
|
|
367
|
+
alt="arrow-up"
|
|
368
|
+
size="custom"
|
|
369
|
+
className="w-full"
|
|
370
|
+
/>
|
|
371
|
+
</div>
|
|
372
|
+
</div>
|
|
373
|
+
</div>
|
|
374
|
+
);
|
|
375
|
+
} else if (type === "VIDEO") {
|
|
376
|
+
return (
|
|
377
|
+
<div className="mb-3 flex flex-col items-center">
|
|
378
|
+
<video
|
|
379
|
+
src={value}
|
|
380
|
+
className={`${
|
|
381
|
+
size ? `${convertToPercentage(size)}` : ""
|
|
382
|
+
} rounded-catchup-xlarge`}
|
|
383
|
+
controls
|
|
384
|
+
/>
|
|
385
|
+
</div>
|
|
386
|
+
);
|
|
387
|
+
} else if (type === "AUDIO") {
|
|
388
|
+
return (
|
|
389
|
+
<div className="mb-3 flex flex-col items-center">
|
|
390
|
+
<audio src={value} controls className={`rounded-catchup-xlarge`} />
|
|
391
|
+
</div>
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
return (
|
|
397
|
+
<div key={index} className="w-full">
|
|
398
|
+
{RenderShowFullScreenItem()}
|
|
399
|
+
{RenderMainContent()}
|
|
400
|
+
</div>
|
|
401
|
+
);
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
export default ShowBodyMediaByContentType;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import i18n from "../../../language/i18n";
|
|
2
|
+
|
|
3
|
+
const ActivityEmptyContent = () => {
|
|
4
|
+
return (
|
|
5
|
+
<div className="flex flex-col items-center justify-center border-2 border-catchup-orange rounded-catchup-xlarge px-5 py-2 my-5 bg-catchup-orange">
|
|
6
|
+
<div className="">
|
|
7
|
+
<p className="text-catchup-white text-xl">
|
|
8
|
+
{i18n.t("you_have_set_this_activity_as_empty")}
|
|
9
|
+
</p>
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default ActivityEmptyContent;
|