Skip to content

Commit c8dade3

Browse files
author
Vivek Chowdhury
committed
loaded options from server and added drop downs in profile screen
1 parent c23f19f commit c8dade3

File tree

11 files changed

+245
-9
lines changed

11 files changed

+245
-9
lines changed

src/api/ProfileService.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { handleError, handleResponse } from "./serviceUtils";
2+
3+
const baseUrl = process.env.REACT_APP_API_URL;
4+
5+
/**
6+
* @description This function is responsible for fetching list of available
7+
* language list from server.
8+
*
9+
* @param {*} userid
10+
* @param {*} password
11+
*/
12+
export function loadLanguages(userid, password) {
13+
const url = baseUrl + "/languages/";
14+
return fetch(url).then(handleResponse).catch(handleError);
15+
}
16+
17+
/**
18+
* @description This function is responsible for fetching list of available
19+
* language list from server.
20+
*
21+
* @param {*} userid
22+
* @param {*} password
23+
*/
24+
export function loadCompleteSchema(userid, password) {
25+
const url = baseUrl + "/schemaOptions/";
26+
return fetch(url).then(handleResponse).catch(handleError);
27+
}

src/app/Shared/ComboBox/ComboBox.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@ function ComboBox(props) {
1818

1919
const renderOptions = (o) => {
2020
return (
21-
<option key={o.id} value={o.id}>
22-
{o.name}
21+
<option
22+
key={props.optionId ? o[props.optionId] : o.id}
23+
value={props.optionId ? o[props.optionId] : o.id}
24+
>
25+
{props.optionName ? o[props.optionName] : o.name}
2326
</option>
2427
);
2528
};

src/app/User/Profile/Profile.js

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import React, { useState, useRef } from "react";
1+
import React, { useState, useRef, useEffect } from "react";
22
import { connect } from "react-redux";
33
import ReactDOM from "react-dom";
44

55
import DialogBox from "./../../Shared/Dialog/DialogBox";
66
import UserForm from "./UserForm";
77
import { updateProfile, registerUser } from "./../state/userActions";
8+
import { loadLanguages, loadProfileStructure } from "./profileActions";
89

910
function Profile(props) {
1011
// Contains detail of logged in or new user
@@ -40,12 +41,32 @@ function Profile(props) {
4041
{ id: "other", name: "Other" },
4142
]);
4243

44+
// Contains error message
4345
const [error, setError] = useState("");
4446

47+
// Contain true if dialog box is visible else false
4548
const [showDialog, setShowDialog] = useState(false);
4649

50+
// Contains reference of dialog reference
4751
const dialogRef = useRef(null);
4852

53+
// Contains true if application is fetching data else false
54+
const [isFetching, setIsFetching] = useState(false);
55+
56+
/**
57+
* @description
58+
*/
59+
useEffect(() => {
60+
if (!isFetching) {
61+
setIsFetching(true);
62+
props.loadProfileStructure().then((response) => {
63+
if (response) {
64+
// console.log(response);
65+
}
66+
});
67+
}
68+
}, [isFetching, props]);
69+
4970
/**
5071
* @description This method is invoked when user change anything in input field. It stores the
5172
* updated value in member variable.
@@ -56,6 +77,7 @@ function Profile(props) {
5677
...user,
5778
[target.name]: target.name !== "iAgree" ? target.value : target.checked,
5879
});
80+
console.log(target.name, target.value);
5981
};
6082

6183
/**
@@ -79,15 +101,27 @@ function Profile(props) {
79101
}
80102
};
81103

104+
/**
105+
* @description This method is responsible for displaying dialog box when user clicks
106+
* on the Add Skill buttons.
107+
*/
82108
const handleAddSkillRequest = () => {
83109
ReactDOM.createPortal(dialogRef, document.getElementById("root"));
84110
setShowDialog(true);
85111
};
86112

113+
/**
114+
* @description This method is invoked when user clicks on the Close
115+
* button in Dialog box.
116+
*/
87117
const handleDialogClose = () => {
88118
setShowDialog(false);
89119
};
90120

121+
/**
122+
* @description This method is invoked when user clicks on the save button in
123+
* Dialog box
124+
*/
91125
const handleDialogSave = () => {
92126
setShowDialog(false);
93127
};
@@ -101,6 +135,7 @@ function Profile(props) {
101135
onSubmit={handleFormSubmit}
102136
{...user}
103137
genderOptions={genderOptions}
138+
{...props.profile}
104139
error={error}
105140
onAddSkillClicked={handleAddSkillRequest}
106141
/>
@@ -124,13 +159,16 @@ function Profile(props) {
124159
function mapStateToProps(state) {
125160
return {
126161
user: state.user,
162+
profile: state.profile,
127163
};
128164
}
129165

130166
// Contains object of actions
131167
const mapDispatchToProps = {
132168
updateProfile,
133169
registerUser,
170+
loadLanguages,
171+
loadProfileStructure,
134172
};
135173

136174
export default connect(mapStateToProps, mapDispatchToProps)(Profile);

src/app/User/Profile/UserForm.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,26 @@ function UserForm(props) {
9696
inputClass="col-sm-8 inline-Column"
9797
></FormInput>
9898
</span>
99+
<span className="secondaryInfo">
100+
<ComboBox
101+
selectId="role"
102+
label="Roles"
103+
options={props.roles}
104+
inputClass="col-sm-8 inline-Column"
105+
onSelectionChange={props.onTextChange}
106+
optionName="roleName"
107+
value={props.role}
108+
/>
109+
<ComboBox
110+
selectId="userType"
111+
label="User Type"
112+
options={props.userTypes}
113+
inputClass="col-sm-8 inline-Column"
114+
onSelectionChange={props.onTextChange}
115+
optionName="typeName"
116+
value={props.role}
117+
/>
118+
</span>
99119
<FormInput
100120
inputId="description"
101121
inputType="text"

src/app/User/Profile/profileActionTypes.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,12 @@ export const USER_REGISTERED_SUCCESSFULLY =
77
"[API_RESPONSE] USER_REGISTERED_SUCCESSFULLY";
88
export const USER_REGISTRATION_FAILED =
99
"[API_RESPONSE] USER_REGISTRATION_FAILED";
10+
11+
export const LANGUAGES_LOADED_SUCCESSFULLY =
12+
"[API RESPONSE] LANGUAGES_LOADED_SUCCESSFULLY";
13+
export const LANGUAGES_LOADED_FAILED = "[API RESPONSE] LANGUAGES_LOADED_FAILED";
14+
15+
export const PROFILE_STRUCTURE_LOADED =
16+
"[API RESPONSE] PROFILE_STRUCTURE_LOADED";
17+
export const PROFILE_STRUCTURE_FAILED =
18+
"[API RESPONSE] PROFILE_STRUCTURE_FAILED";
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import * as LanguageActions from "./profileActionTypes";
2+
import * as LanguageService from "../../../api/ProfileService";
3+
4+
/**
5+
* @description This function is invoked when language list is loaded from server,
6+
* it is responsible for dispatching informaton to reducer.
7+
*
8+
* @param {*} response
9+
*/
10+
export function onProfileStructureloaded(response) {
11+
return { type: LanguageActions.PROFILE_STRUCTURE_LOADED, response };
12+
}
13+
14+
/**
15+
* @description This function is invoked when application failed to load
16+
* language list from server.
17+
*
18+
* @param {*} error
19+
*/
20+
export function onProfileStructureloadedFailure(error) {
21+
return { type: LanguageActions.PROFILE_STRUCTURE_FAILED, error };
22+
}
23+
24+
/**
25+
* @description This function is invoked when language list is loaded from server,
26+
* it is responsible for dispatching informaton to reducer.
27+
*
28+
* @param {*} response
29+
*/
30+
export function onLanguageloaded(response) {
31+
return { type: LanguageActions.LANGUAGES_LOADED_SUCCESSFULLY, response };
32+
}
33+
34+
/**
35+
* @description This function is invoked when application failed to load
36+
* language list from server.
37+
*
38+
* @param {*} error
39+
*/
40+
export function onLanguageloadedFailure(error) {
41+
return { type: LanguageActions.LANGUAGES_LOADED_SUCCESSFULLY, error };
42+
}
43+
44+
/**
45+
* @description This function is responsible for fetching list of available languages
46+
* from server.
47+
*/
48+
export function loadLanguages() {
49+
return function (dispatch) {
50+
return LanguageService.loadLanguages()
51+
.then((response) => {
52+
if (response) {
53+
dispatch(onLanguageloaded(response));
54+
return response;
55+
}
56+
})
57+
.catch((error) => {
58+
throw error;
59+
});
60+
};
61+
}
62+
63+
/**
64+
* @description This function is responsible for fetching list of profile structure data which
65+
* we will use in Profile screen like available languages, roles, user types etc.
66+
*/
67+
export function loadProfileStructure() {
68+
return function (dispatch) {
69+
return LanguageService.loadCompleteSchema()
70+
.then((response) => {
71+
if (response) {
72+
dispatch(onProfileStructureloaded(response));
73+
return response;
74+
}
75+
})
76+
.catch((error) => {
77+
throw error;
78+
});
79+
};
80+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import * as Actions from "./profileActionTypes";
2+
3+
// Initial language list
4+
const profile = {
5+
languages: [],
6+
roles: [],
7+
userTypes: [],
8+
permissions: [],
9+
};
10+
11+
/**
12+
* @description This function is responsible for manipulating profile state. It take previous
13+
* state and return new state depending on the action.
14+
*
15+
* @param {*} state
16+
* @param {*} action
17+
*/
18+
export default function profileReducer(state = profile, action) {
19+
switch (action.type) {
20+
case Actions.LANGUAGES_LOADED_SUCCESSFULLY:
21+
return {
22+
...state,
23+
languages: action.response,
24+
};
25+
case Actions.LANGUAGES_LOADED_FAILED:
26+
return {
27+
...state,
28+
languages: [],
29+
};
30+
case Actions.PROFILE_STRUCTURE_LOADED:
31+
return {
32+
...state,
33+
...action.response,
34+
};
35+
default:
36+
return state;
37+
}
38+
}

src/app/rootReducer.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { combineReducers } from "redux";
22
import loginReducer from "./User/state/userReducer";
3+
import profileReducer from "./User/Profile/profileReducer";
34

45
const rootReducer = combineReducers({
56
user: loginReducer,
7+
profile: profileReducer,
68
});
79

810
export default rootReducer;

tools/db.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"users":[{"id":"vivek.chowdhury","password":"vchowdhury","displayPicture":"","fname":"Vivek","lname":"Chowdhury","age":"36","gender":"male","phonenumber":"9717833999","emailId":"vivek.chowdhury@gmail.com","userType":"type001","role":"rol001","description":"I am super admin let me try this application","totalExperience":"14","languages":[{"languageId":"lng001"}],"projects":[{"projectId":"p001"}]},{"id":"tester.chowdhury","password":"tchowdhury","displayPicture":"","fname":"Tester","lname":"Chowdhury","age":"36","gender":"male","phonenumber":"10011001","emailId":"vivek.chowdhury@gmail.com","userType":"type005","role":"rol002","description":"I am super tester let me try this application","totalExperience":"10","languages":[{"languageId":"lng001"}],"projects":[{"projectId":"p001"}]}],"permissions":[{"id":"per001","permissionName":"All"},{"id":"per002","permissionName":"Normal"},{"id":"per003","permissionName":"Guest"}],"roles":[{"id":"rol001","roleName":"Admin","permissionList":[{"permissionId":"per001"}]},{"id":"rol002","roleName":"Normal","permissionList":[{"permissionId":"per002"}]},{"id":"rol002","roleName":"Guest","permissionList":[{"permissionId":"per003"}]}],"userTypes":[{"id":"type001","typeName":"Super"},{"id":"type002","typeName":"Developer"},{"id":"type002","typeName":"Manager"},{"id":"type003","typeName":"HR"},{"id":"type004","typeName":"Designer"},{"id":"type005","typeName":"Qaulity"}],"feeds":[{"id":"feed1","userid":"vivek.chowdhury","displayPicture":"","message":"this is my first feed","type":"text","likes":[{"userid":"tester.chowdhury","displayPicture":""}],"dislikes":[{"userid":"tester.chowdhury","displayPicture":""}],"comments":[{"commentId":"comment001"}]}],"comments":[{"id":"comment001","userId":"tester.chowdhury","displayPicture":"","message":"This is first comment"}],"languages":[{"id":"lng001","langName":"Javacript","image":"","description":"Front-end"},{"id":"lng002","langName":"ActionScript","image":"","description":"Front-end"},{"id":"lng003","langName":"Java","image":"","description":"Front-end"}],"projects":[{"id":"p001","description":"Test project added","languages":[{"languageId":"lng001","langName":"Javacript","image":"","description":"Front-end"}],"startDate":"2020-07-11T08:26:55.743Z","endDate":"2020-07-11T08:26:55.743Z"}]}
1+
{"users":[{"id":"vivek.chowdhury","password":"vchowdhury","displayPicture":"","fname":"Vivek","lname":"Chowdhury","age":"36","gender":"male","phonenumber":"9717833999","emailId":"vivek.chowdhury@gmail.com","userType":"type001","role":"rol001","description":"I am super admin let me try this application","totalExperience":"14","languages":[{"languageId":"lng001"}],"projects":[{"projectId":"p001"}]},{"id":"tester.chowdhury","password":"tchowdhury","displayPicture":"","fname":"Tester","lname":"Chowdhury","age":"36","gender":"male","phonenumber":"10011001","emailId":"vivek.chowdhury@gmail.com","userType":"type005","role":"rol002","description":"I am super tester let me try this application","totalExperience":"10","languages":[{"languageId":"lng001"}],"projects":[{"projectId":"p001"}]}],"permissions":[{"id":"per001","permissionName":"All"},{"id":"per002","permissionName":"Normal"},{"id":"per003","permissionName":"Guest"}],"roles":[{"id":"rol001","roleName":"Admin","permissionList":[{"permissionId":"per001"}]},{"id":"rol002","roleName":"Normal","permissionList":[{"permissionId":"per002"}]},{"id":"rol003","roleName":"Guest","permissionList":[{"permissionId":"per003"}]}],"userTypes":[{"id":"type001","typeName":"Super"},{"id":"type002","typeName":"Developer"},{"id":"type003","typeName":"Manager"},{"id":"type004","typeName":"HR"},{"id":"type005","typeName":"Designer"},{"id":"type006","typeName":"Qaulity"}],"feeds":[{"id":"feed1","userid":"vivek.chowdhury","displayPicture":"","message":"this is my first feed","type":"text","likes":[{"userid":"tester.chowdhury","displayPicture":""}],"dislikes":[{"userid":"tester.chowdhury","displayPicture":""}],"comments":[{"commentId":"comment001"}]}],"comments":[{"id":"comment001","userId":"tester.chowdhury","displayPicture":"","message":"This is first comment"}],"languages":[{"id":"lng001","langName":"Javacript","image":"","description":"Front-end"},{"id":"lng002","langName":"ActionScript","image":"","description":"Front-end"},{"id":"lng003","langName":"Java","image":"","description":"Front-end"}],"projects":[{"id":"p001","description":"Test project added","languages":[{"languageId":"lng001","langName":"Javacript","image":"","description":"Front-end"}],"startDate":"2020-07-11T08:26:55.743Z","endDate":"2020-07-11T08:26:55.743Z"}]}

tools/localServer.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,25 @@ server.post("/users/", function (req, res, next) {
9393
}
9494
});
9595

96+
server.get("/languages/", function (req, res, next) {
97+
const languages = router.db.getState().languages;
98+
if (languages && languages.length > 0) {
99+
res.status(200);
100+
}
101+
next();
102+
});
103+
104+
server.get("/schemaOptions/", function (req, res, next) {
105+
const db = router.db.getState();
106+
const result = {
107+
languages: db.languages,
108+
roles: db.roles,
109+
userTypes: db.userTypes,
110+
permissions: db.permissions,
111+
};
112+
res.status(200).send(result);
113+
});
114+
96115
server.get("/login/", function (req, res, next) {
97116
const query = req.query;
98117
const users = router.db.getState().users;

0 commit comments

Comments
 (0)