Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nisum-scorecard
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Venkaiah Naidu Singamchetty
nisum-scorecard
Commits
223aa5fb
Commit
223aa5fb
authored
Mar 15, 2024
by
Your Name
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Latest pull
parent
59c0b16b
Changes
16
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
484 additions
and
120 deletions
+484
-120
man.png
public/man.png
+0
-0
server.js
server.js
+170
-96
App.js
src/App.js
+2
-0
index.jsx
src/components/header/index.jsx
+11
-5
index.jsx
src/components/modal/index.jsx
+119
-0
modalButton.jsx
src/components/modal/modalButton.jsx
+25
-0
index.jsx
src/components/sidebar/index.jsx
+23
-1
index.jsx
src/components/table/index.jsx
+7
-6
index.css
src/index.css
+3
-0
index.jsx
src/pages/dashboard/index.jsx
+5
-4
index.jsx
src/pages/reports/index.jsx
+47
-0
reportSlice.js
src/redux/reducers/reportSlice.js
+45
-0
reporteesSlice.js
src/redux/reducers/reporteesSlice.js
+8
-4
rootReducer.js
src/redux/reducers/rootReducer.js
+3
-1
userSlice.js
src/redux/reducers/userSlice.js
+7
-3
clearStore.js
src/utils/clearStore.js
+9
-0
No files found.
public/man.png
0 → 100644
View file @
223aa5fb
24 KB
server.js
View file @
223aa5fb
This diff is collapsed.
Click to expand it.
src/App.js
View file @
223aa5fb
...
...
@@ -2,6 +2,7 @@ import {BrowserRouter, Routes, Route} from 'react-router-dom';
import
Home
from
"./pages/home"
;
import
Dashboard
from
'./pages/dashboard'
;
import
Layout
from
'./pages/layout'
;
import
Reports
from
'./pages/reports'
;
import
'./App.css'
;
function
App
()
{
...
...
@@ -10,6 +11,7 @@ function App() {
<
Routes
>
<
Route
path
=
'/'
element
=
{
<
Home
/>
}
/
>
<
Route
path
=
":id/dashboard"
element
=
{
<
Layout
><
Dashboard
/><
/Layout>}/
>
<
Route
path
=
":id/reports"
element
=
{
<
Layout
><
Reports
/><
/Layout>}/
>
<
/Routes
>
<
/BrowserRouter
>
);
...
...
src/components/header/index.jsx
View file @
223aa5fb
import
React
from
'react'
;
import
{
Link
}
from
'react-router-dom'
;
import
{
useNavigate
}
from
'react-router-dom'
;
import
{
useDispatch
}
from
'react-redux'
;
import
clearStore
from
'../../utils/clearStore'
;
function
Header
()
{
const
dispatch
=
useDispatch
();
const
navigate
=
useNavigate
()
const
handleLogout
=
()
=>
{
navigate
(
'/'
);
clearStore
(
dispatch
)
}
return
(
<
div
className=
"flex items-center justify-between py-5 px-10"
>
<
img
src=
"/logo.png"
/>
<
div
className=
"flex items-center"
>
<
img
src=
"/power-button.png"
width=
"30px"
height=
"30px"
/>
<
button
className=
"ml-2 -mt-1 text-2xl"
>
<
Link
to=
"/"
>
Logout
</
Link
>
<
button
className=
"ml-2 -mt-1 text-2xl"
onClick=
{
handleLogout
}
>
Logout
</
button
>
</
div
>
</
div
>
...
...
src/components/modal/index.jsx
0 → 100644
View file @
223aa5fb
import
axios
from
"axios"
;
import
React
,
{
useMemo
,
useEffect
,
useState
,
useCallback
}
from
"react"
;
import
{
base_url
}
from
"../../utils/constants"
;
export
default
function
MyModal
({
visible
,
onClose
,
type
})
{
const
[
activitiesList
,
setActivitiesList
]
=
useState
([])
const
[
enableSubmit
,
setEnableSubmit
]
=
useState
(
false
)
const
[
scoreType
,
setScoreType
]
=
useState
(
1
)
const
[
activityData
,
setActivityData
]
=
useState
({
aName
:
""
,
aId
:
""
,
type
:
type
,
score
:
0
,
comments
:
""
})
const
getActivitysList
=
async
()
=>
{
const
activities
=
await
axios
.
get
(
`
${
base_url
}
/activities`
)
const
response
=
await
activities
.
data
.
filter
((
item
)
=>
item
.
type
==
type
)
setActivitiesList
(
response
)
}
const
handleActivityName
=
(
e
)
=>
{
setActivityData
({...
activityData
,
aName
:
e
.
target
.
value
,
aId
:
e
.
target
.
options
[
e
.
target
.
selectedIndex
].
id
})
}
const
handleScoreChange
=
(
value
)
=>
{
setActivityData
({...
activityData
,
score
:(
scoreType
)
*
(
value
)})
}
function
handlePerformance
(
value
){
setScoreType
(
value
)
}
const
handleComments
=
(
e
)
=>
{
setActivityData
({...
activityData
,
comments
:
e
.
target
.
value
})
}
const
handleSubmit
=
(
e
)
=>
{
onClose
()
console
.
log
(
activityData
)
}
useEffect
(()
=>
{
handleScoreChange
(
activityData
.
score
)},[
scoreType
])
useEffect
(()
=>
{
if
(
activityData
.
aName
!==
""
&&
activityData
.
aId
!==
""
&&
activityData
.
comments
!==
""
&&
activityData
.
score
!=
0
||
-
0
)
{
setEnableSubmit
(
true
);
}
else
{
setEnableSubmit
(
false
);
}
},
[
activityData
]);
useEffect
(()
=>
{
if
(
visible
===
false
){
setActivityData
({
aName
:
""
,
aId
:
""
,
type
:
type
,
score
:
0
,
comments
:
""
})
}
else
{
getActivitysList
();
}
},[
visible
,
type
])
if
(
!
visible
)
return
null
;
return
(
<
div
className=
"fixed inset-0 bg-black bg-opacity-25 backdrop-blur-sm flex items-center justify-center"
>
<
div
className=
"bg-white rounded lg:w-4/12 sm:w-100"
>
<
div
className=
" text-white py-3 pl-2 bg-blue-500"
>
Default Activity
</
div
>
<
div
>
<
div
>
<
form
className=
" p-2 max-w-sm mx-auto"
>
<
div
className=
"flex items-center my-5"
>
<
label
htmlFor=
"countries"
>
Select Activity:
</
label
>
<
select
className=
"bg-gray-50 ml-2 w-7/12 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
onChange=
{
(
e
)
=>
handleActivityName
(
e
)
}
>
<
option
id=
""
value=
""
className=
"text-[16px]"
>
Select
</
option
>
{
activitiesList
&&
activitiesList
.
map
((
activity
)
=>
<
option
className=
"text-[16px] w-7/12"
key=
{
activity
.
aId
}
id=
{
activity
.
aId
}
value=
{
activity
.
aName
}
>
{
activity
.
aName
}
</
option
>)
}
</
select
>
</
div
>
<
div
className=
"flex items-center mb-4 "
>
<
label
htmlFor=
"appreciate"
className=
" text-sm font-medium text-gray-900 dark:text-gray-300"
>
Appreciation:
</
label
>
<
input
id=
"appreciate"
type=
"radio"
value=
"appreciate"
name=
"performance"
className=
"w-4 h-4 m-3 text-blue-600 bg-gray-100 border-gray-300 dark:bg-gray-700 dark:border-gray-600"
onChange=
{
()
=>
handlePerformance
(
1
)
}
/>
<
label
htmlFor=
"depreciate"
className=
"ms-2 text-sm font-medium text-gray-900 dark:text-gray-300"
>
Depreciation:
</
label
>
<
input
id=
"depreciate"
type=
"radio"
value=
"depreciate"
name=
"performance"
className=
"w-4 h-4 m-3 text-blue-600 bg-gray-100 border-gray-300 dark:bg-gray-700 dark:border-gray-600"
onChange=
{
()
=>
handlePerformance
(
-
1
)
}
/>
</
div
>
<
div
className=
"flex "
>
<
span
>
Score
</
span
>
<
select
className=
"border w-1/5"
onChange=
{
(
e
)
=>
handleScoreChange
(
e
.
target
.
value
)
}
>
<
option
value=
{
0
}
>
Select
</
option
>
<
option
value=
{
1
}
>
1
</
option
>
<
option
value=
{
2
}
>
2
</
option
>
<
option
value=
{
3
}
>
3
</
option
>
<
option
value=
{
4
}
>
4
</
option
>
<
option
value=
{
5
}
>
5
</
option
>
</
select
>
</
div
>
<
div
className=
"flex items-center my-5"
>
<
label
htmlFor=
"comments"
className=
"block w-3/12 mb-20 text-sm font-medium text-gray-900 dark:text-white"
>
Comments :
</
label
>
<
textarea
id=
"comments"
rows=
"4"
className=
"block ml-2 p-2.5 w-9/12 text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder=
"activity comments"
onChange=
{
(
e
)
=>
handleComments
(
e
)
}
></
textarea
>
</
div
>
<
div
className=
"flex items-center justify-end mb-3"
>
<
button
onClick=
{
onClose
}
className=
"px-3 py-2 bg-gray-700 text-white rounded"
>
Cancel
</
button
>
{
enableSubmit
?<
button
type=
"button"
className=
"px-3 py-2 ml-5 bg-green-700 text-white rounded"
onClick=
{
handleSubmit
}
>
Submit
</
button
>:
<
button
type=
"button"
className=
"px-3 py-2 ml-5 bg-gray-400 text-white rounded"
disabled=
{
!
enableSubmit
}
title=
"Please fill all fileds to submit"
>
Submit
</
button
>
}
</
div
>
</
form
>
</
div
>
</
div
>
</
div
>
</
div
>
);
}
\ No newline at end of file
src/components/modal/modalButton.jsx
0 → 100644
View file @
223aa5fb
import
React
,
{
useState
}
from
"react"
;
import
MyModal
from
"./index"
;
export
default
function
ModalButton
({
type
})
{
const
[
showMyModal
,
setShowMyModal
]
=
useState
(
false
);
const
handleOnClose
=
()
=>
setShowMyModal
(
false
);
return
(
<
div
className=
"bg-blue-400 bg-opacity-30"
>
{
/* // <div className="max-w-3xl mx-auto">
// <div className="text-center py-3"> */
}
<
button
onClick=
{
()
=>
setShowMyModal
(
true
)
}
className=
"bg-red-400 text-white px-3 py-2 rounded hover:scale-95 transition text-xl"
>
Add Activity
</
button
>
{
/* // </div>
// <p className="text-lg">
// </p>
// </div> */
}
<
MyModal
onClose=
{
handleOnClose
}
visible=
{
showMyModal
}
type=
{
type
}
/>
</
div
>
);
}
\ No newline at end of file
src/components/sidebar/index.jsx
View file @
223aa5fb
import
React
from
"react"
;
import
{
useSelector
}
from
"react-redux"
;
import
{
useParams
}
from
"react-router-dom"
;
function
Sidebar
()
{
const
user
=
useSelector
((
state
)
=>
state
.
userDetails
.
user
);
const
reportees
=
useSelector
((
state
)
=>
state
.
reportees
.
reportees
);
const
url
=
window
.
location
.
href
return
(
<
div
className=
"w-[30%] flex items-center flex-col"
>
<
div
className=
"w-[30%] flex items-center flex-col
px-4
"
>
<
div
>
<
img
src=
"/user.png"
width=
"130px"
height=
"130px"
/>
</
div
>
...
...
@@ -12,6 +17,23 @@ function Sidebar() {
<
p
className=
"text-lg font-semibold"
>
{
user
.
empName
}
</
p
>
<
p
>
{
user
.
designation
}
</
p
>
</
div
>
{
url
.
includes
(
'/reports'
)
&&
<
div
className=
"mt-5 border-t-2 border-gray-300 w-[-webkit-fill-available] flex flex-col "
>
<
p
className=
"text-xl text-blue-400 font-semibold pl-4 mt-3"
>
My Project Allocations
</
p
>
<
div
className=
"p-2 bg-[#E9EDEE] mt-4 max-h-[50vh] overflow-auto"
>
{
reportees
?.
map
(({
empName
,
score
,
empId
})
=>
(
<
div
className=
"flex items-center bg-white p-2 justify-between mb-1"
key=
{
empId
}
>
<
img
src=
"/man.png"
width=
"18px"
height=
"18px"
/>
<
p
className=
"w-[80%]"
>
{
empName
}
</
p
>
<
p
className=
"w-[10%] bg-blue-200 rounded-sm text-center"
>
{
score
}
</
p
>
</
div
>
))
}
</
div
>
</
div
>
}
</
div
>
);
}
...
...
src/components/table/index.jsx
View file @
223aa5fb
import
React
from
"react"
;
import
{
Link
}
from
'react-router-dom'
;
function
Table
({
headers
,
data
,
isView
})
{
return
(
<
div
class
=
"relative overflow-x-auto shadow-md sm:rounded-lg
"
>
<
table
class
=
"w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400
"
>
<
thead
class
=
"text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400
"
>
<
div
class
Name=
"relative overflow-x-auto shadow-md sm:rounded-lg p-3
"
>
<
table
class
Name=
"w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400 bg-transparent justify-center
"
>
<
thead
class
Name=
"text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400
"
>
<
tr
>
{
headers
.
map
((
item
)
=>
(
<
th
scope=
"col"
class
=
"px-6 py-3 font-bold"
>
<
th
scope=
"col"
class
Name=
"px-6 py-3"
>
{
item
.
title
}
</
th
>
))
}
...
...
@@ -16,9 +17,9 @@ function Table({headers, data, isView}) {
<
tbody
>
{
data
?.
map
((
item
,
index
)
=>
(
<
tr
class
=
"bg-white border-b
dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600"
>
<
tr
class
Name=
"bg-white border-b-8
dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600"
>
{
headers
?.
map
((
field
)
=>
(
field
.
id
!==
"action"
?
<
td
class=
"px-6 py-4"
>
{
item
[
field
.
id
]
}
</
td
>
:
<
td
class=
"px-6 py-4"
><
button
>
View
</
button
></
td
>
field
.
id
!==
"action"
?
<
td
className=
"px-6 py-4 listData"
>
{
field
.
id
===
"empName"
?<
span
className=
"flex items-center"
><
img
className=
"pr-2"
src=
"/user.png"
width=
"30px"
height=
"30px"
/>
{
item
[
field
.
id
]
}
</
span
>
:
item
[
field
.
id
]
}
</
td
>
:
<
td
className=
"px-6 py-3 border-l-2"
><
Link
to=
{
`/${item.empId}/reports`
}
><
button
type=
"button"
className=
"bg-blue-400 text-white rounded-md px-3 py-1"
>
View
</
button
></
Link
></
td
>
))
}
</
tr
>
...
...
src/index.css
View file @
223aa5fb
...
...
@@ -15,3 +15,6 @@ code {
font-family
:
source-code-pro
,
Menlo
,
Monaco
,
Consolas
,
'Courier New'
,
monospace
;
}
.listData
:nth-child
(
4
)
{
padding-left
:
35px
;
}
\ No newline at end of file
src/pages/dashboard/index.jsx
View file @
223aa5fb
...
...
@@ -10,7 +10,7 @@ function Dashboard() {
const
reportees
=
useSelector
((
state
)
=>
state
.
reportees
.
reportees
);
const
userDetails
=
useSelector
((
state
)
=>
state
.
userDetails
);
const
{
id
}
=
useParams
();
const
reporteIds
=
userDetails
.
user
.
reportees
||
{}
;
const
reporteIds
=
userDetails
.
user
.
reportees
||
[]
;
useEffect
(()
=>
{
if
(
reporteIds
.
length
>
0
)
{
...
...
@@ -25,11 +25,12 @@ function Dashboard() {
},
[
reporteIds
]);
useEffect
(()
=>
{
if
(
id
!==
undefined
||
null
)
dispatch
(
fetchUser
(
id
));
},
[]);
},
[
id
]);
const
headers
=
[
{
title
:
"Name"
,
id
:
"empName"
},
{
title
:
"
Employee
Name"
,
id
:
"empName"
},
{
title
:
"Emp.Id"
,
id
:
"empId"
},
{
title
:
"Designation"
,
id
:
'designation'
},
{
title
:
"score"
,
id
:
"score"
},
...
...
@@ -38,7 +39,7 @@ function Dashboard() {
]
return
(
<
div
>
<
Table
headers=
{
headers
}
data=
{
reportees
.
data
}
isView=
{
true
}
/>
<
Table
headers=
{
headers
}
data=
{
reportees
}
isView=
{
true
}
/>
</
div
>
)
}
...
...
src/pages/reports/index.jsx
0 → 100644
View file @
223aa5fb
import
React
,
{
useState
,
useEffect
}
from
'react'
;
import
{
useSelector
,
useDispatch
}
from
'react-redux'
;
import
{
useParams
}
from
'react-router'
;
import
{
fetchReports
}
from
"../../redux/reducers/reportSlice"
;
import
ModalButton
from
'../../components/modal/modalButton'
;
function
Reports
()
{
const
{
id
}
=
useParams
();
const
dispatch
=
useDispatch
();
const
reportees
=
useSelector
((
state
)
=>
state
.
reportees
.
reportees
);
const
[
empDetails
,
setEmpDetails
]
=
useState
(
null
);
const
{
report
,
loading
,
error
}
=
useSelector
((
state
)
=>
state
.
reports
)
/*Example post data
{
"empId":41689,
"fromDate":"2024-03-10",
"toDate":"2024-03-11"
}
*/
useEffect
(()
=>
{
if
(
id
)
{
const
emp
=
reportees
?.
filter
((
item
)
=>
item
.
empId
===
Number
(
id
));
setEmpDetails
(
emp
[
0
]);
const
data
=
{
"empId"
:
Number
(
id
),
"fromDate"
:
"2024-03-10"
,
"toDate"
:
"2024-03-15"
}
dispatch
(
fetchReports
(
data
))
}
return
(()
=>
{
setEmpDetails
(
null
)
})
},[
id
]);
return
(
<
div
>
This Perots
<
ModalButton
type=
{
"default"
}
/>
</
div
>
)
}
export
default
Reports
src/redux/reducers/reportSlice.js
0 → 100644
View file @
223aa5fb
import
{
createSlice
,
createAsyncThunk
}
from
"@reduxjs/toolkit"
;
import
{
base_url
}
from
"../../utils/constants"
;
import
axios
from
"axios"
;
const
initialState
=
{
reports
:
[],
loading
:
false
,
error
:
null
,
};
export
const
fetchReports
=
createAsyncThunk
(
"getReports"
,
async
(
data
)
=>
{
return
await
axios
.
post
(
`
${
base_url
}
/getActivities`
,
data
)
.
then
((
response
)
=>
response
.
data
);
});
const
reportSlice
=
createSlice
({
name
:
"reportees"
,
initialState
,
reducers
:
{
resetReports
:()
=>
{
return
initialState
}
},
extraReducers
:
(
builder
)
=>
{
builder
.
addCase
(
fetchReports
.
pending
,
(
state
)
=>
{
state
.
loading
=
true
;
state
.
error
=
"pending"
;
});
builder
.
addCase
(
fetchReports
.
fulfilled
,
(
state
,
action
)
=>
{
state
.
loading
=
false
;
state
.
reports
=
action
.
payload
?.
activities
;
state
.
error
=
""
;
});
builder
.
addCase
(
fetchReports
.
rejected
,
(
state
,
action
)
=>
{
state
.
loading
=
false
;
state
.
reports
=
[];
state
.
error
=
action
.
error
||
"Something went wrong!"
;
});
},
});
export
const
{
resetReports
}
=
reportSlice
.
actions
;
export
default
reportSlice
.
reducer
;
src/redux/reducers/reporteesSlice.js
View file @
223aa5fb
...
...
@@ -15,9 +15,13 @@ export const fetchReportees = createAsyncThunk("getReportees", async (data) => {
});
const
reporteesSlice
=
createSlice
({
name
:
"
counter
"
,
name
:
"
reportees
"
,
initialState
,
reducers
:
{},
reducers
:
{
resetReportees
:()
=>
{
return
initialState
}
},
extraReducers
:
(
builder
)
=>
{
builder
.
addCase
(
fetchReportees
.
pending
,
(
state
)
=>
{
state
.
loading
=
true
;
...
...
@@ -25,7 +29,7 @@ const reporteesSlice = createSlice({
});
builder
.
addCase
(
fetchReportees
.
fulfilled
,
(
state
,
action
)
=>
{
state
.
loading
=
false
;
state
.
reportees
=
action
.
payload
;
state
.
reportees
=
action
.
payload
.
data
;
state
.
error
=
""
;
});
builder
.
addCase
(
fetchReportees
.
rejected
,
(
state
,
action
)
=>
{
...
...
@@ -36,6 +40,6 @@ const reporteesSlice = createSlice({
},
});
export
const
{}
=
reporteesSlice
.
actions
;
export
const
{
resetReportees
}
=
reporteesSlice
.
actions
;
export
default
reporteesSlice
.
reducer
;
src/redux/reducers/rootReducer.js
View file @
223aa5fb
import
{
combineReducers
}
from
'redux'
;
import
reporteesReducer
from
'./reporteesSlice'
;
import
userReducer
from
'./userSlice'
;
import
reportReducer
from
'./reportSlice'
;
const
rootReducer
=
combineReducers
({
userDetails
:
userReducer
,
reportees
:
reporteesReducer
reportees
:
reporteesReducer
,
reports
:
reportReducer
});
export
default
rootReducer
;
\ No newline at end of file
src/redux/reducers/userSlice.js
View file @
223aa5fb
...
...
@@ -15,9 +15,13 @@ export const fetchUser = createAsyncThunk("getUser", async (id) => {
});
const
userSlice
=
createSlice
({
name
:
"
count
er"
,
name
:
"
us
er"
,
initialState
,
reducers
:
{},
reducers
:
{
resetUser
:()
=>
{
return
initialState
}
},
extraReducers
:
(
builder
)
=>
{
// fetch user
builder
.
addCase
(
fetchUser
.
pending
,
(
state
)
=>
{
...
...
@@ -37,6 +41,6 @@ const userSlice = createSlice({
},
});
export
const
{}
=
userSlice
.
actions
;
export
const
{
resetUser
}
=
userSlice
.
actions
;
export
default
userSlice
.
reducer
;
src/utils/clearStore.js
0 → 100644
View file @
223aa5fb
import
{
resetUser
}
from
'../redux/reducers/userSlice'
;
import
{
resetReportees
}
from
'../redux/reducers/reporteesSlice'
;
const
clearStore
=
(
dispatch
)
=>
{
dispatch
(
resetUser
());
dispatch
(
resetReportees
());
};
export
default
clearStore
;
\ No newline at end of file
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