Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mytime
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
Narendar Vakiti
mytime
Commits
1b5f9eab
Commit
1b5f9eab
authored
May 07, 2018
by
Rajeshekar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MT-43[Rajeshekar]: Added work location feature
parent
00b2f4e0
Changes
10
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
471 additions
and
287 deletions
+471
-287
UserController.java
...main/java/com/nisum/mytime/controller/UserController.java
+135
-91
EmployeeRoles.java
src/main/java/com/nisum/mytime/model/EmployeeRoles.java
+21
-20
Location.java
src/main/java/com/nisum/mytime/model/Location.java
+34
-0
LocationRepo.java
src/main/java/com/nisum/mytime/repository/LocationRepo.java
+9
-0
UserService.java
src/main/java/com/nisum/mytime/service/UserService.java
+27
-19
UserServiceImpl.java
src/main/java/com/nisum/mytime/service/UserServiceImpl.java
+191
-153
LoginController.js
src/main/webapp/WEB-INF/controllers/LoginController.js
+28
-4
app.js
src/main/webapp/WEB-INF/js/app.js
+9
-0
profile.html
src/main/webapp/WEB-INF/templates/profile.html
+14
-0
registerEmployee.html
src/main/webapp/WEB-INF/templates/registerEmployee.html
+3
-0
No files found.
src/main/java/com/nisum/mytime/controller/UserController.java
View file @
1b5f9eab
This diff is collapsed.
Click to expand it.
src/main/java/com/nisum/mytime/model/EmployeeRoles.java
View file @
1b5f9eab
...
...
@@ -34,6 +34,7 @@ public class EmployeeRoles implements Serializable {
private
String
designation
;
private
String
shift
;
private
String
baseTechnology
;
private
String
empLocation
;
private
String
technologyKnown
;
private
String
mobileNumber
;
private
String
alternateMobileNumber
;
...
...
src/main/java/com/nisum/mytime/model/Location.java
0 → 100644
View file @
1b5f9eab
package
com
.
nisum
.
mytime
.
model
;
import
java.io.Serializable
;
import
org.bson.types.ObjectId
;
import
org.springframework.data.annotation.Id
;
import
org.springframework.data.mongodb.core.mapping.Document
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
import
lombok.NoArgsConstructor
;
import
lombok.Setter
;
import
lombok.ToString
;
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Document
(
collection
=
"Locations"
)
public
class
Location
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
@Id
private
ObjectId
id
;
private
String
locationCode
;
private
String
location
;
private
String
country
;
private
String
state
;
private
String
city
;
private
boolean
activeStatus
;
private
String
comments
;
}
src/main/java/com/nisum/mytime/repository/LocationRepo.java
0 → 100644
View file @
1b5f9eab
package
com
.
nisum
.
mytime
.
repository
;
import
org.springframework.data.mongodb.repository.MongoRepository
;
import
com.nisum.mytime.model.Location
;
public
interface
LocationRepo
extends
MongoRepository
<
Location
,
String
>
{
}
\ No newline at end of file
src/main/java/com/nisum/mytime/service/UserService.java
View file @
1b5f9eab
...
...
@@ -7,20 +7,25 @@ import com.nisum.mytime.model.Account;
import
com.nisum.mytime.model.Designation
;
import
com.nisum.mytime.model.EmpLoginData
;
import
com.nisum.mytime.model.EmployeeRoles
;
import
com.nisum.mytime.model.Location
;
import
com.nisum.mytime.model.Shift
;
import
com.nisum.mytime.model.Skill
;
public
interface
UserService
{
Boolean
fetchEmployeesData
(
String
perticularDate
,
boolean
resynchFlag
)
throws
MyTimeException
;
Boolean
fetchEmployeesData
(
String
perticularDate
,
boolean
resynchFlag
)
throws
MyTimeException
;
List
<
EmpLoginData
>
employeeLoginsBasedOnDate
(
long
id
,
String
fromDate
,
String
toDate
)
throws
MyTimeException
;
List
<
EmpLoginData
>
employeeLoginsBasedOnDate
(
long
id
,
String
fromDate
,
String
toDate
)
throws
MyTimeException
;
List
<
EmployeeRoles
>
getEmployeeRoles
()
throws
MyTimeException
;
EmployeeRoles
assigingEmployeeRole
(
EmployeeRoles
employeeRoles
)
throws
MyTimeException
;
EmployeeRoles
assigingEmployeeRole
(
EmployeeRoles
employeeRoles
)
throws
MyTimeException
;
String
generatePdfReport
(
long
id
,
String
fromDate
,
String
toDate
)
throws
MyTimeException
;
String
generatePdfReport
(
long
id
,
String
fromDate
,
String
toDate
)
throws
MyTimeException
;
EmployeeRoles
getEmployeesRole
(
String
emailId
);
...
...
@@ -36,7 +41,10 @@ public interface UserService {
List
<
Skill
>
getTechnologies
()
throws
MyTimeException
;
public
EmployeeRoles
updateProfile
(
EmployeeRoles
employeeRoles
)
throws
MyTimeException
;
public
EmployeeRoles
updateProfile
(
EmployeeRoles
employeeRoles
)
throws
MyTimeException
;
public
List
<
Account
>
getAccounts
()
throws
MyTimeException
;
List
<
Location
>
getLocations
()
throws
MyTimeException
;
}
src/main/java/com/nisum/mytime/service/UserServiceImpl.java
View file @
1b5f9eab
...
...
@@ -16,12 +16,14 @@ import com.nisum.mytime.model.Account;
import
com.nisum.mytime.model.Designation
;
import
com.nisum.mytime.model.EmpLoginData
;
import
com.nisum.mytime.model.EmployeeRoles
;
import
com.nisum.mytime.model.Location
;
import
com.nisum.mytime.model.ProjectTeamMate
;
import
com.nisum.mytime.model.Shift
;
import
com.nisum.mytime.model.Skill
;
import
com.nisum.mytime.repository.AccountRepo
;
import
com.nisum.mytime.repository.DesignationRepo
;
import
com.nisum.mytime.repository.EmployeeRolesRepo
;
import
com.nisum.mytime.repository.LocationRepo
;
import
com.nisum.mytime.repository.ProjectTeamMatesRepo
;
import
com.nisum.mytime.repository.ShiftRepo
;
import
com.nisum.mytime.repository.TechnologyRepo
;
...
...
@@ -48,6 +50,9 @@ public class UserServiceImpl implements UserService {
@Autowired
private
TechnologyRepo
technologyRepo
;
@Autowired
private
LocationRepo
locationRepo
;
@Autowired
private
EmployeeDataService
employeeDataBaseService
;
...
...
@@ -58,18 +63,22 @@ public class UserServiceImpl implements UserService {
private
MongoTemplate
mongoTemplate
;
@Override
public
Boolean
fetchEmployeesData
(
String
perticularDate
,
boolean
resynchFlag
)
throws
MyTimeException
{
return
employeeDataBaseService
.
fetchEmployeesData
(
perticularDate
,
resynchFlag
);
public
Boolean
fetchEmployeesData
(
String
perticularDate
,
boolean
resynchFlag
)
throws
MyTimeException
{
return
employeeDataBaseService
.
fetchEmployeesData
(
perticularDate
,
resynchFlag
);
}
@Override
public
List
<
EmpLoginData
>
employeeLoginsBasedOnDate
(
long
id
,
String
fromDate
,
String
toDate
)
throws
MyTimeException
{
return
employeeDataBaseService
.
fetchEmployeeLoginsBasedOnDates
(
id
,
fromDate
,
toDate
);
public
List
<
EmpLoginData
>
employeeLoginsBasedOnDate
(
long
id
,
String
fromDate
,
String
toDate
)
throws
MyTimeException
{
return
employeeDataBaseService
.
fetchEmployeeLoginsBasedOnDates
(
id
,
fromDate
,
toDate
);
}
@Override
public
String
generatePdfReport
(
long
id
,
String
fromDate
,
String
toDate
)
throws
MyTimeException
{
public
String
generatePdfReport
(
long
id
,
String
fromDate
,
String
toDate
)
throws
MyTimeException
{
return
pdfReportGenerator
.
generateEmployeeReport
(
id
,
fromDate
,
toDate
);
}
...
...
@@ -79,7 +88,8 @@ public class UserServiceImpl implements UserService {
}
@Override
public
EmployeeRoles
assigingEmployeeRole
(
EmployeeRoles
employeeRoles
)
throws
MyTimeException
{
public
EmployeeRoles
assigingEmployeeRole
(
EmployeeRoles
employeeRoles
)
throws
MyTimeException
{
employeeRoles
.
setCreatedOn
(
new
Date
());
return
employeeRolesRepo
.
save
(
employeeRoles
);
}
...
...
@@ -98,7 +108,8 @@ public class UserServiceImpl implements UserService {
@Override
public
EmployeeRoles
updateEmployeeRole
(
EmployeeRoles
employeeRoles
)
{
Query
query
=
new
Query
(
Criteria
.
where
(
"employeeId"
).
is
(
employeeRoles
.
getEmployeeId
()));
Query
query
=
new
Query
(
Criteria
.
where
(
"employeeId"
).
is
(
employeeRoles
.
getEmployeeId
()));
Update
update
=
new
Update
();
update
.
set
(
"employeeName"
,
employeeRoles
.
getEmployeeName
());
update
.
set
(
"emailId"
,
employeeRoles
.
getEmailId
());
...
...
@@ -107,15 +118,20 @@ public class UserServiceImpl implements UserService {
FindAndModifyOptions
options
=
new
FindAndModifyOptions
();
options
.
returnNew
(
true
);
options
.
upsert
(
true
);
EmployeeRoles
emp
=
mongoTemplate
.
findAndModify
(
query
,
update
,
options
,
EmployeeRoles
.
class
);
EmployeeRoles
emp
=
mongoTemplate
.
findAndModify
(
query
,
update
,
options
,
EmployeeRoles
.
class
);
try
{
List
<
ProjectTeamMate
>
employeeProfiles
=
projectTeamMatesRepo
.
findByEmployeeId
(
emp
.
getEmployeeId
());
if
(
employeeProfiles
!=
null
&&!
employeeProfiles
.
isEmpty
())
{
for
(
ProjectTeamMate
profile:
employeeProfiles
){
profile
.
setRole
(
emp
.
getRole
());;
List
<
ProjectTeamMate
>
employeeProfiles
=
projectTeamMatesRepo
.
findByEmployeeId
(
emp
.
getEmployeeId
());
if
(
employeeProfiles
!=
null
&&
!
employeeProfiles
.
isEmpty
())
{
for
(
ProjectTeamMate
profile
:
employeeProfiles
)
{
profile
.
setRole
(
emp
.
getRole
());
;
projectTeamMatesRepo
.
save
(
profile
);
}
}}
catch
(
Exception
e
)
{}
}
}
catch
(
Exception
e
)
{
}
return
emp
;
}
...
...
@@ -145,40 +161,62 @@ public class UserServiceImpl implements UserService {
}
@Override
public
EmployeeRoles
updateProfile
(
EmployeeRoles
employeeRoles
)
throws
MyTimeException
{
boolean
mobileNumberChnaged
=
false
;
boolean
designationChnaged
=
false
;
employeeRoles
.
setLastModifiedOn
(
new
Date
());
EmployeeRoles
existingEmployee
=
employeeRolesRepo
.
findByEmployeeId
(
employeeRoles
.
getEmployeeId
());
String
newMobileNumber
=
employeeRoles
.
getMobileNumber
();
String
designation
=
employeeRoles
.
getDesignation
();
if
(
newMobileNumber
!=
null
&&!
newMobileNumber
.
equalsIgnoreCase
(
""
))
{
if
((
existingEmployee
!=
null
&&
existingEmployee
.
getMobileNumber
()!=
null
&&!
existingEmployee
.
getMobileNumber
().
equalsIgnoreCase
(
newMobileNumber
)
)||
(
existingEmployee
.
getMobileNumber
()==
null
)){
mobileNumberChnaged
=
true
;
public
List
<
Location
>
getLocations
()
throws
MyTimeException
{
return
locationRepo
.
findAll
();
}
}
if
(
designation
!=
null
&&!
designation
.
equalsIgnoreCase
(
""
))
{
if
((
existingEmployee
!=
null
&&
existingEmployee
.
getDesignation
()!=
null
&&!
existingEmployee
.
getDesignation
().
equalsIgnoreCase
(
newMobileNumber
)
)||
(
existingEmployee
.
getDesignation
()==
null
)){
designationChnaged
=
true
;
@Override
public
EmployeeRoles
updateProfile
(
EmployeeRoles
employeeRoles
)
throws
MyTimeException
{
boolean
mobileNumberChnaged
=
false
;
boolean
designationChnaged
=
false
;
employeeRoles
.
setLastModifiedOn
(
new
Date
());
EmployeeRoles
existingEmployee
=
employeeRolesRepo
.
findByEmployeeId
(
employeeRoles
.
getEmployeeId
());
String
newMobileNumber
=
employeeRoles
.
getMobileNumber
();
String
designation
=
employeeRoles
.
getDesignation
();
if
(
newMobileNumber
!=
null
&&
!
newMobileNumber
.
equalsIgnoreCase
(
""
))
{
if
((
existingEmployee
!=
null
&&
existingEmployee
.
getMobileNumber
()
!=
null
&&
!
existingEmployee
.
getMobileNumber
()
.
equalsIgnoreCase
(
newMobileNumber
))
||
(
existingEmployee
.
getMobileNumber
()
==
null
))
{
mobileNumberChnaged
=
true
;
}
}
if
(
designation
!=
null
&&
!
designation
.
equalsIgnoreCase
(
""
))
{
if
((
existingEmployee
!=
null
&&
existingEmployee
.
getDesignation
()
!=
null
&&
!
existingEmployee
.
getDesignation
()
.
equalsIgnoreCase
(
newMobileNumber
))
||
(
existingEmployee
.
getDesignation
()
==
null
))
{
designationChnaged
=
true
;
}
}
existingEmployee
.
setDesignation
(
employeeRoles
.
getDesignation
());
existingEmployee
.
setMobileNumber
(
employeeRoles
.
getMobileNumber
());
existingEmployee
.
setAlternateMobileNumber
(
employeeRoles
.
getAlternateMobileNumber
());
existingEmployee
.
setAlternateMobileNumber
(
employeeRoles
.
getAlternateMobileNumber
());
existingEmployee
.
setPersonalEmailId
(
employeeRoles
.
getPersonalEmailId
());
existingEmployee
.
setBaseTechnology
(
employeeRoles
.
getBaseTechnology
());
existingEmployee
.
setTechnologyKnown
(
employeeRoles
.
getTechnologyKnown
());
EmployeeRoles
employeeRolesDB
=
employeeRolesRepo
.
save
(
existingEmployee
);
if
(
mobileNumberChnaged
||
designationChnaged
)
{
EmployeeRoles
employeeRolesDB
=
employeeRolesRepo
.
save
(
existingEmployee
);
if
(
mobileNumberChnaged
||
designationChnaged
)
{
try
{
List
<
ProjectTeamMate
>
employeeProfiles
=
projectTeamMatesRepo
.
findByEmployeeId
(
employeeRoles
.
getEmployeeId
());
if
(
employeeProfiles
!=
null
&&!
employeeProfiles
.
isEmpty
())
{
for
(
ProjectTeamMate
profile:
employeeProfiles
){
profile
.
setDesignation
(
employeeRolesDB
.
getDesignation
());
profile
.
setMobileNumber
(
employeeRolesDB
.
getMobileNumber
());
List
<
ProjectTeamMate
>
employeeProfiles
=
projectTeamMatesRepo
.
findByEmployeeId
(
employeeRoles
.
getEmployeeId
());
if
(
employeeProfiles
!=
null
&&
!
employeeProfiles
.
isEmpty
())
{
for
(
ProjectTeamMate
profile
:
employeeProfiles
)
{
profile
.
setDesignation
(
employeeRolesDB
.
getDesignation
());
profile
.
setMobileNumber
(
employeeRolesDB
.
getMobileNumber
());
projectTeamMatesRepo
.
save
(
profile
);
}
}}
catch
(
Exception
e
)
{}
}
}
catch
(
Exception
e
)
{
}
}
return
employeeRolesDB
;
...
...
src/main/webapp/WEB-INF/controllers/LoginController.js
View file @
1b5f9eab
...
...
@@ -11,6 +11,7 @@ myApp.controller("loginController",function($scope, myFactory, $compile, $window
getAllShifts
();
getAllDesignations
();
getAllTechnologies
();
getAllLocations
();
getAllAccounts
();
$
(
"#start"
).
trigger
(
"click"
);
}
...
...
@@ -86,6 +87,16 @@ myApp.controller("loginController",function($scope, myFactory, $compile, $window
});
};
function
getAllLocations
(){
$http
({
method
:
"GET"
,
url
:
appConfig
.
appUri
+
"user/getLocations"
}).
then
(
function
mySuccess
(
response
)
{
myFactory
.
setLocations
(
response
.
data
);
},
function
myError
(
response
)
{
});
};
function
getAllAccounts
(){
$http
({
method
:
"GET"
,
...
...
@@ -125,7 +136,8 @@ myApp.controller("loginController",function($scope, myFactory, $compile, $window
$scope
.
empName
=
dataToPass
.
getName
();
$scope
.
empEmail
=
dataToPass
.
getEmail
();
$scope
.
empShift
;
$scope
.
shifts
=
myFactory
.
getTechnologies
();
//["Shift 1(09:00 AM - 06:00 PM)","Shift 2(03:30 PM - 12:30 PM)", "Shift 3(09:00 PM - 06:00 AM)"];
$scope
.
shifts
=
myFactory
.
getTechnologies
();
$scope
.
locations
=
myFactory
.
getLocations
();
//["Shift 1(09:00 AM - 06:00 PM)","Shift 2(03:30 PM - 12:30 PM)", "Shift 3(09:00 PM - 06:00 AM)"];
$scope
.
getSelectedShift
=
function
(){
if
(
$scope
.
empShift
!==
undefined
)
{
...
...
@@ -134,6 +146,13 @@ myApp.controller("loginController",function($scope, myFactory, $compile, $window
return
"Please select primary skill"
;
}
};
$scope
.
getSelectedLocation
=
function
(){
if
(
$scope
.
empLocation
!==
undefined
)
{
return
$scope
.
empLocation
;
}
else
{
return
"Please select work location"
;
}
};
$scope
.
validateEmpId
=
function
(){
var
searchId
=
$scope
.
empId
;
...
...
@@ -171,6 +190,7 @@ myApp.controller("loginController",function($scope, myFactory, $compile, $window
var
searchId
=
$scope
.
empId
;
var
empName
=
$scope
.
empName
;
var
empShift
=
$scope
.
empShift
;
var
empLocation
=
$scope
.
empLocation
;
var
mobileNumber
=
$scope
.
mobileNumber
;
if
(
searchId
==
""
){
...
...
@@ -191,9 +211,13 @@ myApp.controller("loginController",function($scope, myFactory, $compile, $window
}
else
if
(
empShift
==
undefined
){
$scope
.
alertMsg
=
"Please select a primary skill"
;
document
.
getElementById
(
'empShift'
).
focus
();
}
else
if
(
empLocation
==
undefined
){
$scope
.
alertMsg
=
"Please select a work location"
;
document
.
getElementById
(
'empLocation'
).
focus
();
}
else
{
$scope
.
alertMsg
=
""
;
var
record
=
{
"employeeId"
:
$scope
.
empId
,
"employeeName"
:
$scope
.
empName
,
"emailId"
:
$scope
.
empEmail
,
"role"
:
"Employee"
,
"shift"
:
"Shift 1(09:00 AM - 06:00 PM)"
,
"mobileNumber"
:
$scope
.
mobileNumber
,
"baseTechnology"
:
$scope
.
empShift
};
var
record
=
{
"employeeId"
:
$scope
.
empId
,
"employeeName"
:
$scope
.
empName
,
"emailId"
:
$scope
.
empEmail
,
"role"
:
"Employee"
,
"shift"
:
"Shift 1(09:00 AM - 06:00 PM)"
,
"mobileNumber"
:
$scope
.
mobileNumber
,
"baseTechnology"
:
$scope
.
empShift
,
"empLocation"
:
$scope
.
empLocation
};
addEmployee
(
record
);
}
};
...
...
@@ -313,7 +337,7 @@ myApp.controller("loginController",function($scope, myFactory, $compile, $window
auth2
.
disconnect
();
//Clear if any values set to factory
var
menuItems
=
[],
designations
=
[],
accounts
=
[],
technologies
=
[],
shifts
=
[];
var
menuItems
=
[],
designations
=
[],
accounts
=
[],
technologies
=
[],
shifts
=
[]
,
locations
=
[]
;
myFactory
.
setEmpId
(
""
);
myFactory
.
setEmpName
(
""
);
myFactory
.
setEmpEmailId
(
""
);
...
...
@@ -325,7 +349,7 @@ myApp.controller("loginController",function($scope, myFactory, $compile, $window
myFactory
.
setAccounts
(
accounts
);
myFactory
.
setTechnologies
(
technologies
);
myFactory
.
setShifts
(
shifts
);
myFactory
.
setLocations
(
locations
);
var
element
=
document
.
getElementById
(
'home'
);
var
path
=
"'templates/login.html'"
;
element
.
setAttribute
(
"src"
,
path
);
...
...
src/main/webapp/WEB-INF/js/app.js
View file @
1b5f9eab
...
...
@@ -35,6 +35,7 @@ myApp.factory('myFactory', function() {
var
profileUrl
=
""
;
var
designations
=
""
;
var
technologies
=
""
;
var
locations
=
""
;
var
shifts
=
""
;
var
accounts
=
""
;
function
setEmpId
(
id
)
{
...
...
@@ -95,6 +96,12 @@ myApp.factory('myFactory', function() {
function
getTechnologies
()
{
return
technologies
;
}
function
setLocations
(
locations1
)
{
locations
=
locations1
;
}
function
getLocations
()
{
return
locations
;
}
function
setShifts
(
shifts1
)
{
shifts
=
shifts1
;
}
...
...
@@ -135,6 +142,8 @@ myApp.factory('myFactory', function() {
getAccounts
:
getAccounts
,
setTechnologies
:
setTechnologies
,
getTechnologies
:
getTechnologies
,
setLocations
:
setLocations
,
getLocations
:
getLocations
,
setShifts
:
setShifts
,
getShifts
:
getShifts
,
setTemplateUrl
:
setTemplateUrl
,
...
...
src/main/webapp/WEB-INF/templates/profile.html
View file @
1b5f9eab
...
...
@@ -158,6 +158,20 @@
</div>
</div>
<div
class=
"row col-lg-12 col-xs-12"
>
<div
class=
"col-lg-5 col-xs-6"
>
<p>
<b>
Work Location
</b>
</p>
</div>
<div
class=
"col-lg-7 col-xs-6"
>
<p>
<b>
:
</b>
{{profile.empLocation}}
</p>
</div>
</div>
</div>
...
...
src/main/webapp/WEB-INF/templates/registerEmployee.html
View file @
1b5f9eab
...
...
@@ -25,6 +25,9 @@
<md-select
ng-model=
"empShift"
md-selected-text=
"getSelectedShift()"
id=
"empShift"
>
<md-optgroup
label=
"skills"
>
<md-option
ng-value=
"shift"
ng-repeat=
"shift in shifts"
>
{{shift}}
</md-option>
</md-optgroup>
</md-select>
<md-select
ng-model=
"empLocation"
md-selected-text=
"getSelectedLocation()"
id=
"empLocation"
>
<md-optgroup
label=
"locations"
>
<md-option
ng-value=
"location"
ng-repeat=
"location in locations"
>
{{location}}
</md-option>
</md-optgroup>
</md-select>
<div
role=
"alert"
>
<span
class=
"error"
style=
"color: red;"
>
{{alertMsg}}
</span>
</div>
...
...
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