Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
2
2023-029
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
2023-029
2023-029
Commits
e8822483
Commit
e8822483
authored
Aug 30, 2023
by
Gamage B.G.J
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feature/marks-calculator' into 'master'
Feature/marks calculator See merge request
!13
parents
d073333a
a248a8bd
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
709 additions
and
23 deletions
+709
-23
.vscode/settings.json
.vscode/settings.json
+1
-0
Project/Backend/Server_Node/controllers/marksCalculator.controller.js
...end/Server_Node/controllers/marksCalculator.controller.js
+50
-0
Project/Backend/Server_Node/package-lock.json
Project/Backend/Server_Node/package-lock.json
+140
-0
Project/Backend/Server_Node/package.json
Project/Backend/Server_Node/package.json
+1
-0
Project/Backend/Server_Node/prediction_config/C1T1/predict.py
...ect/Backend/Server_Node/prediction_config/C1T1/predict.py
+116
-0
Project/Backend/Server_Node/prediction_config/C1T1/trained_model_modified.pth
...er_Node/prediction_config/C1T1/trained_model_modified.pth
+0
-0
Project/Backend/Server_Node/routes/marksCalculator.routes.js
Project/Backend/Server_Node/routes/marksCalculator.routes.js
+13
-0
Project/Backend/Server_Node/server.js
Project/Backend/Server_Node/server.js
+8
-0
Project/Frontend/SignConnectPlus/src/layout/MainLayout/Header/HeaderContent/index.tsx
...Plus/src/layout/MainLayout/Header/HeaderContent/index.tsx
+8
-9
Project/Frontend/SignConnectPlus/src/pages/parameter/curriculum-management/list/list.tsx
...s/src/pages/parameter/curriculum-management/list/list.tsx
+21
-7
Project/Frontend/SignConnectPlus/src/pages/parameter/tutorial-management/list/list.tsx
...lus/src/pages/parameter/tutorial-management/list/list.tsx
+19
-5
Project/Frontend/SignConnectPlus/src/sections/parameters/curriculum-management/AddEditCurriculum.tsx
...ns/parameters/curriculum-management/AddEditCurriculum.tsx
+172
-0
Project/Frontend/SignConnectPlus/src/sections/parameters/curriculum-management/AlertCurriculumDelete.tsx
...arameters/curriculum-management/AlertCurriculumDelete.tsx
+1
-1
Project/Frontend/SignConnectPlus/src/sections/parameters/tutorial-management/AddEditTutorial.tsx
...ctions/parameters/tutorial-management/AddEditTutorial.tsx
+158
-0
Project/Frontend/SignConnectPlus/src/sections/parameters/tutorial-management/AlertTutorialDelete.tsx
...ns/parameters/tutorial-management/AlertTutorialDelete.tsx
+1
-1
No files found.
.vscode/settings.json
View file @
e8822483
{
"cSpell.words"
:
[
"formik"
,
"Janith"
,
"leaderboard"
,
"SLIIT"
...
...
Project/Backend/Server_Node/controllers/marksCalculator.controller.js
0 → 100644
View file @
e8822483
import
{
exec
}
from
"
child_process
"
;
export
const
marksCalculator
=
async
(
req
,
res
)
=>
{
const
imageData
=
req
.
file
.
buffer
.
toString
(
'
base64
'
);
const
targetClass
=
req
.
body
.
class
;
const
{
curriculumIndex
,
tutorialIndex
}
=
req
.
params
;
const
status
=
""
;
// console.log(curriculumIndex, tutorialIndex);
try
{
if
(
curriculumIndex
==
1
&&
tutorialIndex
==
1
)
{
// Run Python script to perform prediction
const
pythonProcess
=
exec
(
'
python prediction_config/C1T1/predict.py
'
,
(
error
,
stdout
,
stderr
)
=>
{
if
(
error
)
{
console
.
error
(
error
);
return
res
.
status
(
500
).
json
({
error
:
'
An error occurred
'
});
}
const
[
predicted_class_name
,
confidence
]
=
stdout
.
trim
().
split
(
'
,
'
);
const
parsedConfidence
=
parseFloat
(
confidence
).
toFixed
(
2
);
let
status
=
""
;
if
(
predicted_class_name
===
targetClass
&&
parsedConfidence
>
85
)
{
status
=
"
pass
"
;
}
else
{
status
=
"
fail
"
;
}
res
.
status
(
200
).
json
({
code
:
"
01
"
,
result
:
{
predicted_class_name
,
confidence
:
parsedConfidence
,
status
}
});
});
pythonProcess
.
stdin
.
write
(
`
${
imageData
}
\n
${
targetClass
}
`
);
pythonProcess
.
stdin
.
end
();
}
else
{
return
res
.
status
(
400
).
json
({
code
:
"
02
"
,
message
:
"
Curriculum Index or Tutorial Index Invalid
"
})
}
}
catch
(
error
)
{
res
.
status
(
500
).
json
({
code
:
"
00
"
,
message
:
"
Something went wrong
"
})
}
}
\ No newline at end of file
Project/Backend/Server_Node/package-lock.json
View file @
e8822483
...
...
@@ -19,6 +19,7 @@
"multer"
:
"^1.4.5-lts.1"
,
"nodemailer"
:
"^6.9.1"
,
"nodemon"
:
"^2.0.22"
,
"torch"
:
"^0.2.7"
,
"uuid"
:
"^9.0.0"
}
},
...
...
@@ -58,6 +59,22 @@
"node"
:
">= 0.6"
}
},
"node_modules/ansi-regex"
:
{
"version"
:
"2.1.1"
,
"resolved"
:
"https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz"
,
"integrity"
:
"sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="
,
"engines"
:
{
"node"
:
">=0.10.0"
}
},
"node_modules/ansi-styles"
:
{
"version"
:
"2.2.1"
,
"resolved"
:
"https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz"
,
"integrity"
:
"sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA=="
,
"engines"
:
{
"node"
:
">=0.10.0"
}
},
"node_modules/anymatch"
:
{
"version"
:
"3.1.3"
,
"resolved"
:
"https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz"
,
...
...
@@ -190,6 +207,29 @@
"url"
:
"https://github.com/sponsors/ljharb"
}
},
"node_modules/chalk"
:
{
"version"
:
"1.1.3"
,
"resolved"
:
"https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz"
,
"integrity"
:
"sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A=="
,
"dependencies"
:
{
"ansi-styles"
:
"^2.2.1"
,
"escape-string-regexp"
:
"^1.0.2"
,
"has-ansi"
:
"^2.0.0"
,
"strip-ansi"
:
"^3.0.0"
,
"supports-color"
:
"^2.0.0"
},
"engines"
:
{
"node"
:
">=0.10.0"
}
},
"node_modules/chalk/node_modules/supports-color"
:
{
"version"
:
"2.0.0"
,
"resolved"
:
"https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz"
,
"integrity"
:
"sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g=="
,
"engines"
:
{
"node"
:
">=0.8.0"
}
},
"node_modules/chokidar"
:
{
"version"
:
"3.5.3"
,
"resolved"
:
"https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz"
,
...
...
@@ -343,6 +383,14 @@
"resolved"
:
"https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz"
,
"integrity"
:
"sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
},
"node_modules/escape-string-regexp"
:
{
"version"
:
"1.0.5"
,
"resolved"
:
"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
,
"integrity"
:
"sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
,
"engines"
:
{
"node"
:
">=0.8.0"
}
},
"node_modules/etag"
:
{
"version"
:
"1.8.1"
,
"resolved"
:
"https://registry.npmjs.org/etag/-/etag-1.8.1.tgz"
,
...
...
@@ -526,6 +574,17 @@
"node"
:
">= 0.4.0"
}
},
"node_modules/has-ansi"
:
{
"version"
:
"2.0.0"
,
"resolved"
:
"https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz"
,
"integrity"
:
"sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg=="
,
"dependencies"
:
{
"ansi-regex"
:
"^2.0.0"
},
"engines"
:
{
"node"
:
">=0.10.0"
}
},
"node_modules/has-flag"
:
{
"version"
:
"3.0.0"
,
"resolved"
:
"https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz"
,
...
...
@@ -1343,6 +1402,17 @@
"resolved"
:
"https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz"
,
"integrity"
:
"sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/strip-ansi"
:
{
"version"
:
"3.0.1"
,
"resolved"
:
"https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz"
,
"integrity"
:
"sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg=="
,
"dependencies"
:
{
"ansi-regex"
:
"^2.0.0"
},
"engines"
:
{
"node"
:
">=0.10.0"
}
},
"node_modules/supports-color"
:
{
"version"
:
"5.5.0"
,
"resolved"
:
"https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"
,
...
...
@@ -1373,6 +1443,18 @@
"node"
:
">=0.6"
}
},
"node_modules/torch"
:
{
"version"
:
"0.2.7"
,
"resolved"
:
"https://registry.npmjs.org/torch/-/torch-0.2.7.tgz"
,
"integrity"
:
"sha512-yTv7qWKGg00hMDv0pyBgRjubbf4eygzzrjKPKRC9rbPCKBF0jd+cxnzIoN+pCHgGf2EQbd0jGyy1X7h5BIqjEA=="
,
"deprecated"
:
"Package no longer supported. Contact Support at https://www.npmjs.com/support for more info."
,
"dependencies"
:
{
"chalk"
:
"^1.1.3"
},
"engines"
:
{
"node"
:
">= 0.8.4"
}
},
"node_modules/touch"
:
{
"version"
:
"3.1.0"
,
"resolved"
:
"https://registry.npmjs.org/touch/-/touch-3.1.0.tgz"
,
...
...
@@ -1522,6 +1604,16 @@
"negotiator"
:
"0.6.3"
}
},
"ansi-regex"
:
{
"version"
:
"2.1.1"
,
"resolved"
:
"https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz"
,
"integrity"
:
"sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="
},
"ansi-styles"
:
{
"version"
:
"2.2.1"
,
"resolved"
:
"https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz"
,
"integrity"
:
"sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA=="
},
"anymatch"
:
{
"version"
:
"3.1.3"
,
"resolved"
:
"https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz"
,
...
...
@@ -1629,6 +1721,25 @@
"get-intrinsic"
:
"^1.0.2"
}
},
"chalk"
:
{
"version"
:
"1.1.3"
,
"resolved"
:
"https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz"
,
"integrity"
:
"sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A=="
,
"requires"
:
{
"ansi-styles"
:
"^2.2.1"
,
"escape-string-regexp"
:
"^1.0.2"
,
"has-ansi"
:
"^2.0.0"
,
"strip-ansi"
:
"^3.0.0"
,
"supports-color"
:
"^2.0.0"
},
"dependencies"
:
{
"supports-color"
:
{
"version"
:
"2.0.0"
,
"resolved"
:
"https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz"
,
"integrity"
:
"sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g=="
}
}
},
"chokidar"
:
{
"version"
:
"3.5.3"
,
"resolved"
:
"https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz"
,
...
...
@@ -1743,6 +1854,11 @@
"resolved"
:
"https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz"
,
"integrity"
:
"sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
},
"escape-string-regexp"
:
{
"version"
:
"1.0.5"
,
"resolved"
:
"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
,
"integrity"
:
"sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
},
"etag"
:
{
"version"
:
"1.8.1"
,
"resolved"
:
"https://registry.npmjs.org/etag/-/etag-1.8.1.tgz"
,
...
...
@@ -1887,6 +2003,14 @@
"function-bind"
:
"^1.1.1"
}
},
"has-ansi"
:
{
"version"
:
"2.0.0"
,
"resolved"
:
"https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz"
,
"integrity"
:
"sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg=="
,
"requires"
:
{
"ansi-regex"
:
"^2.0.0"
}
},
"has-flag"
:
{
"version"
:
"3.0.0"
,
"resolved"
:
"https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz"
,
...
...
@@ -2489,6 +2613,14 @@
}
}
},
"strip-ansi"
:
{
"version"
:
"3.0.1"
,
"resolved"
:
"https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz"
,
"integrity"
:
"sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg=="
,
"requires"
:
{
"ansi-regex"
:
"^2.0.0"
}
},
"supports-color"
:
{
"version"
:
"5.5.0"
,
"resolved"
:
"https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"
,
...
...
@@ -2510,6 +2642,14 @@
"resolved"
:
"https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz"
,
"integrity"
:
"sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
},
"torch"
:
{
"version"
:
"0.2.7"
,
"resolved"
:
"https://registry.npmjs.org/torch/-/torch-0.2.7.tgz"
,
"integrity"
:
"sha512-yTv7qWKGg00hMDv0pyBgRjubbf4eygzzrjKPKRC9rbPCKBF0jd+cxnzIoN+pCHgGf2EQbd0jGyy1X7h5BIqjEA=="
,
"requires"
:
{
"chalk"
:
"^1.1.3"
}
},
"touch"
:
{
"version"
:
"3.1.0"
,
"resolved"
:
"https://registry.npmjs.org/touch/-/touch-3.1.0.tgz"
,
...
...
Project/Backend/Server_Node/package.json
View file @
e8822483
...
...
@@ -21,6 +21,7 @@
"multer"
:
"^1.4.5-lts.1"
,
"nodemailer"
:
"^6.9.1"
,
"nodemon"
:
"^2.0.22"
,
"torch"
:
"^0.2.7"
,
"uuid"
:
"^9.0.0"
}
}
Project/Backend/Server_Node/prediction_config/C1T1/predict.py
0 → 100644
View file @
e8822483
import
sys
import
io
import
base64
import
torch
import
torchvision.transforms
as
transforms
from
PIL
import
Image
import
torch.nn
as
nn
import
torch.nn.functional
as
F
import
numpy
as
np
class
theCNN
(
nn
.
Module
):
def
__init__
(
self
):
super
()
.
__init__
()
self
.
conv01
=
nn
.
Conv2d
(
in_channels
=
1
,
out_channels
=
10
,
kernel_size
=
5
,
stride
=
1
,
padding
=
1
)
self
.
dropout1
=
nn
.
Dropout
(
0.2
)
# Add dropout layer
self
.
conv02
=
nn
.
Conv2d
(
in_channels
=
10
,
out_channels
=
20
,
kernel_size
=
5
,
stride
=
1
,
padding
=
1
)
self
.
dropout2
=
nn
.
Dropout
(
0.2
)
# Add dropout layer
expectedSize
=
np
.
floor
((
73
+
2
*
0
-
1
)
/
1
)
+
1
expectedSize
=
20
*
int
(
expectedSize
**
2
)
self
.
fc01
=
nn
.
Linear
(
expectedSize
,
50
)
self
.
output
=
nn
.
Linear
(
50
,
16
)
def
forward
(
self
,
x
):
# convo -> maxpool -> relu
x
=
F
.
relu
(
F
.
max_pool2d
(
self
.
conv01
(
x
),
2
))
# convo -> maxpool -> relu
x
=
F
.
relu
(
F
.
max_pool2d
(
self
.
conv02
(
x
),
2
))
nUnits
=
x
.
shape
.
numel
()
/
x
.
shape
[
0
]
x
=
x
.
view
(
-
1
,
int
(
nUnits
))
x
=
F
.
relu
(
self
.
fc01
(
x
))
return
torch
.
softmax
(
self
.
output
(
x
),
axis
=
1
)
# Load the mapping dictionary
class_mapping
=
{
0
:
'Eight'
,
1
:
'Eleven'
,
2
:
'Fifty'
,
3
:
'Five'
,
4
:
'Four'
,
5
:
'Fourteen'
,
6
:
'Nine'
,
7
:
'One'
,
8
:
'Seven'
,
9
:
'Six'
,
10
:
'Ten'
,
11
:
'Thirteen'
,
12
:
'Thirty'
,
13
:
'Three'
,
14
:
'Twenty'
,
15
:
'Two'
}
# Load the trained model
model
=
theCNN
()
# Instantiate your model class
model
.
load_state_dict
(
torch
.
load
(
'D:/SLIIT_Y4_Research_Module/Research/Project/2023-029/Project/Backend/Server_Node/prediction_config/C1T1/trained_model_modified.pth'
,
map_location
=
torch
.
device
(
'cpu'
)))
model
.
eval
()
# Read image data and target class from standard input
input_data
=
sys
.
stdin
.
readlines
()
image_data
=
input_data
[
0
]
.
strip
()
.
encode
()
# Convert to bytes
target_class
=
input_data
[
1
]
.
strip
()
# Preprocess the image
# image_data = base64.b64decode(sys.argv[1])
# image = Image.open(io.BytesIO(image_data))
image
=
Image
.
open
(
io
.
BytesIO
(
base64
.
b64decode
(
image_data
)))
transform
=
transforms
.
Compose
([
transforms
.
Resize
((
300
,
300
)),
transforms
.
Grayscale
(
num_output_channels
=
1
),
transforms
.
ToTensor
(),
transforms
.
Normalize
(
mean
=
[
0.5
],
std
=
[
0.5
]),
])
image_tensor
=
transform
(
image
)
.
unsqueeze
(
0
)
# Predict the class
with
torch
.
no_grad
():
outputs
=
model
(
image_tensor
)
predicted_class
=
torch
.
argmax
(
outputs
[
0
])
.
item
()
confidence
=
outputs
[
0
][
predicted_class
]
.
item
()
# Get the predicted class name using the mapping dictionary
predicted_class_name
=
class_mapping
[
predicted_class
]
# Calculate similarity or confidence percentage
# target_class = sys.argv[2].lower() # Class name passed from the API
similarity
=
100
*
confidence
print
(
f
"{predicted_class_name},{similarity:.2f}"
)
Project/Backend/Server_Node/prediction_config/C1T1/trained_model_modified.pth
0 → 100644
View file @
e8822483
File added
Project/Backend/Server_Node/routes/marksCalculator.routes.js
0 → 100644
View file @
e8822483
import
express
from
"
express
"
;
import
multer
from
"
multer
"
;
import
{
marksCalculator
}
from
"
../controllers/marksCalculator.controller.js
"
;
// Set up storage for uploaded images
const
storage
=
multer
.
memoryStorage
();
const
upload
=
multer
({
storage
:
storage
});
const
router
=
express
.
Router
();
router
.
post
(
'
/curriculum/:curriculumIndex/tutorial/:tutorialIndex
'
,
upload
.
single
(
'
image
'
),
marksCalculator
)
export
default
router
;
\ No newline at end of file
Project/Backend/Server_Node/server.js
View file @
e8822483
...
...
@@ -4,10 +4,17 @@ import dotenv from "dotenv";
import
express
from
"
express
"
;
import
mongoose
from
"
mongoose
"
;
import
multer
from
"
multer
"
;
// Set up storage for uploaded images
const
storage
=
multer
.
memoryStorage
();
const
upload
=
multer
({
storage
:
storage
});
//import routes
import
curriculumRoutes
from
"
./routes/curriculum.routes.js
"
;
import
feedbackRoutes
from
"
./routes/feedback.routes.js
"
;
import
leaderboardRoutes
from
"
./routes/leaderboard.routes.js
"
;
import
marksCalculatorRoutes
from
"
./routes/marksCalculator.routes.js
"
;
import
translateRoutes
from
"
./routes/translate.routes.js
"
;
import
tutorialRoutes
from
"
./routes/tutorial.routes.js
"
;
import
userRoutes
from
"
./routes/user.routes.js
"
;
...
...
@@ -33,6 +40,7 @@ app.use("/rest_node/tutorial", tutorialRoutes);
app
.
use
(
"
/rest_node/user-progress
"
,
userProgressRoutes
);
app
.
use
(
"
/rest_node/feedback
"
,
feedbackRoutes
);
app
.
use
(
"
/rest_node/leaderboard
"
,
leaderboardRoutes
);
app
.
use
(
"
/rest_node/marks-calculator
"
,
marksCalculatorRoutes
);
const
CONNECTION_URL
=
`mongodb+srv://
${
process
.
env
.
DB_USERNAME
}
:
${
process
.
env
.
DB_PASSWORD
}
@researchmanagement-appl.vzhn4.mongodb.net/?retryWrites=true&w=majority`
;
const
PORT
=
process
.
env
.
PORT
||
5000
;
...
...
Project/Frontend/SignConnectPlus/src/layout/MainLayout/Header/HeaderContent/index.tsx
View file @
e8822483
//
import { useMemo } from 'react';
import
{
useMemo
}
from
'
react
'
;
// material-ui
import
{
Theme
}
from
'
@mui/material/styles
'
;
import
{
Box
,
useMediaQuery
}
from
'
@mui/material
'
;
import
{
Theme
}
from
'
@mui/material/styles
'
;
// project import
import
Search
from
'
./Search
'
;
import
Localization
from
'
./Localization
'
;
import
Message
from
'
./Message
'
;
import
Profile
from
'
./Profile
'
;
// import Localization from './Localization';
import
Notification
from
'
./Notification
'
;
import
Profile
from
'
./Profile
'
;
import
Search
from
'
./Search
'
;
// import Customization from './Customization';
import
MobileSection
from
'
./MobileSection
'
;
// import MegaMenuSection from './MegaMenuSection';
...
...
@@ -23,13 +23,12 @@ import { MenuOrientation } from 'types/config';
// ==============================|| HEADER - CONTENT ||============================== //
const
HeaderContent
=
()
=>
{
// const { i18n, menuOrientation } = useConfig();
const
{
menuOrientation
}
=
useConfig
();
const
{
i18n
,
menuOrientation
}
=
useConfig
();
const
downLG
=
useMediaQuery
((
theme
:
Theme
)
=>
theme
.
breakpoints
.
down
(
'
lg
'
));
// eslint-disable-next-line react-hooks/exhaustive-deps
//
const localization = useMemo(() => <Localization />, [i18n]);
const
localization
=
useMemo
(()
=>
<
Localization
/>,
[
i18n
]);
// const megaMenu = useMemo(() => <MegaMenuSection />, []);
...
...
@@ -38,7 +37,7 @@ const HeaderContent = () => {
{
menuOrientation
===
MenuOrientation
.
HORIZONTAL
&&
!
downLG
&&
<
DrawerHeader
open=
{
true
}
/>
}
{
!
downLG
&&
<
Search
/>
}
{
/* {!downLG && megaMenu} */
}
{
/* {!downLG && localization} */
}
{
!
downLG
&&
localization
}
{
downLG
&&
<
Box
sx=
{
{
width
:
'
100%
'
,
ml
:
1
}
}
/>
}
<
Notification
/>
...
...
Project/Frontend/SignConnectPlus/src/pages/parameter/curriculum-management/list/list.tsx
View file @
e8822483
...
...
@@ -3,6 +3,7 @@ import { MouseEvent, useMemo, useState } from 'react';
// material-ui
import
{
Button
,
Dialog
,
IconButton
,
Stack
,
Table
,
...
...
@@ -32,7 +33,9 @@ import {
import
{
DeleteTwoTone
,
EditTwoTone
,
EyeTwoTone
,
PlusOutlined
}
from
'
@ant-design/icons
'
;
//types
import
AlertTutorialDelete
from
'
sections/parameters/tutorial-management/AlertTutorialDelete
'
;
import
{
PopupTransition
}
from
'
components/@extended/Transitions
'
;
import
AddEditCurriculum
from
'
sections/parameters/curriculum-management/AddEditCurriculum
'
;
import
AlertCurriculumDelete
from
'
sections/parameters/curriculum-management/AlertCurriculumDelete
'
;
import
{
ReactTableProps
,
curriculumProps
,
dataProps
}
from
'
./types/types
'
;
// ==============================|| REACT TABLE ||============================== //
...
...
@@ -205,8 +208,8 @@ const List = () => {
color=
"error"
onClick=
{
(
e
:
MouseEvent
<
HTMLButtonElement
>
)
=>
{
e
.
stopPropagation
();
// setTutorialId(row.values.
id)
//
setOpenAlert(true)
setCurriculumId
(
row
.
values
.
_
id
)
setOpenAlert
(
true
)
}
}
>
<
DeleteTwoTone
twoToneColor=
{
theme
.
palette
.
error
.
main
}
/>
...
...
@@ -232,9 +235,7 @@ const List = () => {
//alert model
const
[
openAlert
,
setOpenAlert
]
=
useState
(
false
);
// const [curriculumId, setCurriculumId] = useState<number | null>(null)
const
curriculumId
:
number
|
null
=
null
const
[
curriculumId
,
setCurriculumId
]
=
useState
<
number
|
string
|
undefined
>
(
undefined
)
const
handleAlertClose
=
()
=>
{
setOpenAlert
(
!
openAlert
);
...
...
@@ -246,8 +247,21 @@ const List = () => {
<
ScrollX
>
<
ReactTable
columns=
{
columns
}
data=
{
data
}
handleAddEdit=
{
handleAddEdit
}
/>
</
ScrollX
>
{
/* add / edit curriculum dialog */
}
<
Dialog
maxWidth=
"sm"
TransitionComponent=
{
PopupTransition
}
keepMounted
fullWidth
onClose=
{
handleAddEdit
}
open=
{
addEdit
}
sx=
{
{
'
& .MuiDialog-paper
'
:
{
p
:
0
},
transition
:
'
transform 225ms
'
}
}
aria
-
describedby=
"alert-dialog-slide-description"
>
<
AddEditCurriculum
curriculum=
{
curriculum
}
onCancel=
{
handleAddEdit
}
/>
</
Dialog
>
{
/* alert model */
}
{
!
curriculum
&&
<
Alert
Tutorial
Delete
title=
{
""
}
open=
{
openAlert
}
handleClose=
{
handleAlertClose
}
deleteId=
{
curriculumId
}
/>
}
{
!
curriculum
&&
<
Alert
Curriculum
Delete
title=
{
""
}
open=
{
openAlert
}
handleClose=
{
handleAlertClose
}
deleteId=
{
curriculumId
}
/>
}
</
MainCard
>
</>
)
...
...
Project/Frontend/SignConnectPlus/src/pages/parameter/tutorial-management/list/list.tsx
View file @
e8822483
...
...
@@ -3,6 +3,7 @@ import { MouseEvent, useMemo, useState } from 'react';
// material-ui
import
{
Button
,
Dialog
,
IconButton
,
Stack
,
Table
,
...
...
@@ -18,6 +19,7 @@ import {
import
{
Cell
,
Column
,
HeaderGroup
,
Row
,
useFilters
,
useGlobalFilter
,
usePagination
,
useTable
}
from
'
react-table
'
;
// project import
import
{
PopupTransition
}
from
'
components/@extended/Transitions
'
;
import
MainCard
from
'
components/MainCard
'
;
import
ScrollX
from
'
components/ScrollX
'
;
import
{
CSVExport
,
EmptyTable
,
TablePagination
}
from
'
components/third-party/ReactTable
'
;
...
...
@@ -32,6 +34,7 @@ import {
import
{
DeleteTwoTone
,
EditTwoTone
,
EyeTwoTone
,
PlusOutlined
}
from
'
@ant-design/icons
'
;
//types
import
AddEditTutorial
from
'
sections/parameters/tutorial-management/AddEditTutorial
'
;
import
AlertTutorialDelete
from
'
sections/parameters/tutorial-management/AlertTutorialDelete
'
;
import
{
ReactTableProps
,
dataProps
,
tutorialProps
}
from
'
./types/types
'
;
...
...
@@ -201,8 +204,8 @@ const List = () => {
color=
"error"
onClick=
{
(
e
:
MouseEvent
<
HTMLButtonElement
>
)
=>
{
e
.
stopPropagation
();
// setTutorialId(row.values.
id)
//
setOpenAlert(true)
setTutorialId
(
row
.
values
.
_
id
)
setOpenAlert
(
true
)
}
}
>
<
DeleteTwoTone
twoToneColor=
{
theme
.
palette
.
error
.
main
}
/>
...
...
@@ -228,9 +231,7 @@ const List = () => {
//alert model
const
[
openAlert
,
setOpenAlert
]
=
useState
(
false
);
// const [tutorialId, setTutorialId] = useState<number | null>(null)
const
tutorialId
:
number
|
null
=
null
const
[
tutorialId
,
setTutorialId
]
=
useState
<
number
|
string
|
undefined
>
(
undefined
)
const
handleAlertClose
=
()
=>
{
setOpenAlert
(
!
openAlert
);
...
...
@@ -242,6 +243,19 @@ const List = () => {
<
ScrollX
>
<
ReactTable
columns=
{
columns
}
data=
{
data
}
handleAddEdit=
{
handleAddEdit
}
/>
</
ScrollX
>
{
/* add / edit tutorial dialog */
}
<
Dialog
maxWidth=
"sm"
TransitionComponent=
{
PopupTransition
}
keepMounted
fullWidth
onClose=
{
handleAddEdit
}
open=
{
addEdit
}
sx=
{
{
'
& .MuiDialog-paper
'
:
{
p
:
0
},
transition
:
'
transform 225ms
'
}
}
aria
-
describedby=
"alert-dialog-slide-description"
>
<
AddEditTutorial
tutorial=
{
tutorial
}
onCancel=
{
handleAddEdit
}
/>
</
Dialog
>
{
/* alert model */
}
{
!
tutorial
&&
<
AlertTutorialDelete
title=
{
""
}
open=
{
openAlert
}
handleClose=
{
handleAlertClose
}
deleteId=
{
tutorialId
}
/>
}
</
MainCard
>
...
...
Project/Frontend/SignConnectPlus/src/sections/parameters/curriculum-management/AddEditCurriculum.tsx
0 → 100644
View file @
e8822483
import
{
useState
}
from
'
react
'
;
// material-ui
import
{
Button
,
DialogActions
,
DialogContent
,
DialogTitle
,
Divider
,
Grid
,
Stack
,
Tooltip
}
from
'
@mui/material
'
;
// import { useTheme } from '@mui/material/styles';
import
{
LocalizationProvider
}
from
'
@mui/x-date-pickers
'
;
import
{
AdapterDateFns
}
from
'
@mui/x-date-pickers/AdapterDateFns
'
;
// third-party
import
{
Form
,
FormikProvider
,
FormikValues
,
useFormik
}
from
'
formik
'
;
import
_
from
'
lodash
'
;
import
*
as
Yup
from
'
yup
'
;
// project imports
import
IconButton
from
'
components/@extended/IconButton
'
;
// assets
import
{
DeleteFilled
}
from
'
@ant-design/icons
'
;
import
AlertCurriculumDelete
from
'
./AlertCurriculumDelete
'
;
// types
// constant
const
getInitialValues
=
(
curriculum
:
FormikValues
|
null
)
=>
{
const
newCurriculum
=
{
_id
:
undefined
,
}
if
(
curriculum
)
{
return
_
.
merge
({},
newCurriculum
,
curriculum
);
}
return
newCurriculum
;
};
// ==============================|| CUSTOMER ADD / EDIT ||============================== //
export
interface
Props
{
curriculum
?:
{
_id
:
number
|
string
|
undefined
;
curriculumCode
:
String
;
curriculumLevel
:
String
;
curriculumName
:
String
;
curriculumImage
:
String
;
tutorials
:
tutorialItemProps
[];
status
:
Number
;
createdBy
:
String
;
updatedBy
:
String
;
createdAt
:
Date
;
updatedAt
:
Date
;
};
onCancel
:
()
=>
void
;
}
export
interface
tutorialItemProps
{
_id
:
number
|
string
|
undefined
;
tutorialCode
:
String
;
tutorialTitle
:
String
;
tutorialImage
:
String
;
status
:
Number
;
createdBy
:
String
;
updatedBy
:
String
;
createdAt
:
Date
;
updatedAt
:
Date
;
taskItems
:
taskItemProps
[]
}
export
interface
taskItemProps
{
_id
:
number
|
string
|
undefined
;
title
:
String
;
description
:
String
;
howToDo
:
String
;
referenceImage
:
String
;
referenceVideo
:
String
;
}
const
AddEditCurriculum
=
({
curriculum
,
onCancel
}:
Props
)
=>
{
// const theme = useTheme();
const
isCreating
=
!
curriculum
;
const
CurriculumSchema
=
Yup
.
object
().
shape
({});
const
[
openAlert
,
setOpenAlert
]
=
useState
(
false
);
const
handleAlertClose
=
()
=>
{
setOpenAlert
(
!
openAlert
);
onCancel
();
};
const
formik
=
useFormik
({
initialValues
:
getInitialValues
(
curriculum
!
),
validationSchema
:
CurriculumSchema
,
enableReinitialize
:
true
,
onSubmit
:
(
values
,
{
setSubmitting
,
resetForm
})
=>
{
try
{
if
(
curriculum
)
{
// PUT API
}
else
{
// POST API
}
resetForm
()
setSubmitting
(
false
);
onCancel
();
}
catch
(
error
)
{
console
.
error
(
error
);
}
}
});
// const { errors, touched, handleSubmit, isSubmitting, getFieldProps } = formik;
const
{
handleSubmit
,
isSubmitting
}
=
formik
;
return
(
<>
<
FormikProvider
value=
{
formik
}
>
<
LocalizationProvider
dateAdapter=
{
AdapterDateFns
}
>
<
Form
autoComplete=
"off"
noValidate
onSubmit=
{
handleSubmit
}
>
<
DialogTitle
>
{
curriculum
?
'
Edit Curriculum
'
:
'
New Curriculum
'
}
</
DialogTitle
>
<
Divider
/>
<
DialogContent
sx=
{
{
p
:
2.5
}
}
>
<
Grid
container
spacing=
{
3
}
>
<
Grid
item
xs=
{
12
}
md=
{
12
}
>
<
Grid
container
spacing=
{
3
}
>
</
Grid
>
</
Grid
>
</
Grid
>
</
DialogContent
>
<
Divider
/>
<
DialogActions
sx=
{
{
p
:
2.5
}
}
>
<
Grid
container
justifyContent=
"space-between"
alignItems=
"center"
>
<
Grid
item
>
{
!
isCreating
&&
(
<
Tooltip
title=
"Delete Tutorial"
placement=
"top"
>
<
IconButton
onClick=
{
()
=>
setOpenAlert
(
true
)
}
size=
"large"
color=
"error"
>
<
DeleteFilled
/>
</
IconButton
>
</
Tooltip
>
)
}
</
Grid
>
<
Grid
item
>
<
Stack
direction=
"row"
spacing=
{
2
}
alignItems=
"center"
>
<
Button
color=
"error"
onClick=
{
onCancel
}
>
Cancel
</
Button
>
<
Button
type=
"submit"
variant=
"contained"
disabled=
{
isSubmitting
}
>
{
curriculum
?
'
Edit
'
:
'
Add
'
}
</
Button
>
</
Stack
>
</
Grid
>
</
Grid
>
</
DialogActions
>
</
Form
>
</
LocalizationProvider
>
</
FormikProvider
>
{
!
isCreating
&&
<
AlertCurriculumDelete
title=
{
""
}
open=
{
openAlert
}
handleClose=
{
handleAlertClose
}
deleteId=
{
curriculum
.
_id
}
/>
}
</>
);
};
export
default
AddEditCurriculum
;
Project/Frontend/SignConnectPlus/src/sections/parameters/curriculum-management/AlertCurriculumDelete.tsx
View file @
e8822483
...
...
@@ -13,7 +13,7 @@ interface Props {
title
:
string
;
open
:
boolean
;
handleClose
:
(
status
:
boolean
)
=>
void
;
deleteId
:
number
|
null
;
deleteId
:
number
|
string
|
undefined
;
}
// ==============================|| Curriculum - DELETE ||============================== //
...
...
Project/Frontend/SignConnectPlus/src/sections/parameters/tutorial-management/AddEditTutorial.tsx
0 → 100644
View file @
e8822483
import
{
useState
}
from
'
react
'
;
// material-ui
import
{
Button
,
DialogActions
,
DialogContent
,
DialogTitle
,
Divider
,
Grid
,
Stack
,
Tooltip
}
from
'
@mui/material
'
;
// import { useTheme } from '@mui/material/styles';
import
{
LocalizationProvider
}
from
'
@mui/x-date-pickers
'
;
import
{
AdapterDateFns
}
from
'
@mui/x-date-pickers/AdapterDateFns
'
;
// third-party
import
{
Form
,
FormikProvider
,
FormikValues
,
useFormik
}
from
'
formik
'
;
import
_
from
'
lodash
'
;
import
*
as
Yup
from
'
yup
'
;
// project imports
import
IconButton
from
'
components/@extended/IconButton
'
;
// assets
import
{
DeleteFilled
}
from
'
@ant-design/icons
'
;
import
AlertTutorialDelete
from
'
./AlertTutorialDelete
'
;
// types
// constant
const
getInitialValues
=
(
tutorial
:
FormikValues
|
null
)
=>
{
const
newTutorial
=
{
_id
:
undefined
,
}
if
(
tutorial
)
{
return
_
.
merge
({},
newTutorial
,
tutorial
);
}
return
newTutorial
;
};
// ==============================|| CUSTOMER ADD / EDIT ||============================== //
export
interface
Props
{
tutorial
?:
{
_id
:
number
|
string
|
undefined
tutorialCode
:
String
;
tutorialTitle
:
String
;
tutorialImage
:
String
;
status
:
Number
;
createdBy
:
String
;
updatedBy
:
String
;
createdAt
:
Date
;
updatedAt
:
Date
;
taskItems
:
taskItemProps
[]
};
onCancel
:
()
=>
void
;
}
export
interface
taskItemProps
{
_id
:
number
|
string
|
undefined
;
title
:
String
;
description
:
String
;
howToDo
:
String
;
referenceImage
:
String
;
referenceVideo
:
String
;
}
const
AddEditTutorial
=
({
tutorial
,
onCancel
}:
Props
)
=>
{
// const theme = useTheme();
const
isCreating
=
!
tutorial
;
const
TutorialSchema
=
Yup
.
object
().
shape
({});
const
[
openAlert
,
setOpenAlert
]
=
useState
(
false
);
const
handleAlertClose
=
()
=>
{
setOpenAlert
(
!
openAlert
);
onCancel
();
};
const
formik
=
useFormik
({
initialValues
:
getInitialValues
(
tutorial
!
),
validationSchema
:
TutorialSchema
,
enableReinitialize
:
true
,
onSubmit
:
(
values
,
{
setSubmitting
,
resetForm
})
=>
{
try
{
if
(
tutorial
)
{
// PUT API
}
else
{
// POST API
}
resetForm
()
setSubmitting
(
false
);
onCancel
();
}
catch
(
error
)
{
console
.
error
(
error
);
}
}
});
// const { errors, touched, handleSubmit, isSubmitting, getFieldProps } = formik;
const
{
handleSubmit
,
isSubmitting
}
=
formik
;
return
(
<>
<
FormikProvider
value=
{
formik
}
>
<
LocalizationProvider
dateAdapter=
{
AdapterDateFns
}
>
<
Form
autoComplete=
"off"
noValidate
onSubmit=
{
handleSubmit
}
>
<
DialogTitle
>
{
tutorial
?
'
Edit Tutorial
'
:
'
New Tutorial
'
}
</
DialogTitle
>
<
Divider
/>
<
DialogContent
sx=
{
{
p
:
2.5
}
}
>
<
Grid
container
spacing=
{
3
}
>
<
Grid
item
xs=
{
12
}
md=
{
12
}
>
<
Grid
container
spacing=
{
3
}
>
</
Grid
>
</
Grid
>
</
Grid
>
</
DialogContent
>
<
Divider
/>
<
DialogActions
sx=
{
{
p
:
2.5
}
}
>
<
Grid
container
justifyContent=
"space-between"
alignItems=
"center"
>
<
Grid
item
>
{
!
isCreating
&&
(
<
Tooltip
title=
"Delete Tutorial"
placement=
"top"
>
<
IconButton
onClick=
{
()
=>
setOpenAlert
(
true
)
}
size=
"large"
color=
"error"
>
<
DeleteFilled
/>
</
IconButton
>
</
Tooltip
>
)
}
</
Grid
>
<
Grid
item
>
<
Stack
direction=
"row"
spacing=
{
2
}
alignItems=
"center"
>
<
Button
color=
"error"
onClick=
{
onCancel
}
>
Cancel
</
Button
>
<
Button
type=
"submit"
variant=
"contained"
disabled=
{
isSubmitting
}
>
{
tutorial
?
'
Edit
'
:
'
Add
'
}
</
Button
>
</
Stack
>
</
Grid
>
</
Grid
>
</
DialogActions
>
</
Form
>
</
LocalizationProvider
>
</
FormikProvider
>
{
!
isCreating
&&
<
AlertTutorialDelete
title=
{
""
}
open=
{
openAlert
}
handleClose=
{
handleAlertClose
}
deleteId=
{
tutorial
.
_id
}
/>
}
</>
);
};
export
default
AddEditTutorial
;
Project/Frontend/SignConnectPlus/src/sections/parameters/tutorial-management/AlertTutorialDelete.tsx
View file @
e8822483
...
...
@@ -13,7 +13,7 @@ interface Props {
title
:
string
;
open
:
boolean
;
handleClose
:
(
status
:
boolean
)
=>
void
;
deleteId
:
number
|
null
;
deleteId
:
number
|
string
|
undefined
;
}
// ==============================|| Tutorial - DELETE ||============================== //
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment