Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/employee edit 224 serializers 207 #229

Merged
merged 20 commits into from
Apr 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
a5a6824
Refactor code of API model view for packages with aggregate pages
adam-sas-on Apr 12, 2021
b68b45c
Limit API response for employee
adam-sas-on Apr 12, 2021
619c586
Import new serializer
adam-sas-on Apr 12, 2021
193fbd1
Create special serializer for HRs
adam-sas-on Apr 12, 2021
56e185d
Simplify class for package endpoint
adam-sas-on Apr 12, 2021
250a401
Remove old endpoint suffix
adam-sas-on Apr 12, 2021
035ce8f
Add serializer to update the User; #224
adam-sas-on Apr 13, 2021
19a4f18
Refactor: reformat imports. Add queryset to User class
adam-sas-on Apr 13, 2021
ec31d4e
Add method for User to update some data; #224
adam-sas-on Apr 13, 2021
948eb44
Add function to update some data of User; #224
adam-sas-on Apr 13, 2021
0d6814c
Use function to update employee; #224. Include name property
adam-sas-on Apr 13, 2021
9d179bf
Enable to print if data the user requested for update was really changed
adam-sas-on Apr 13, 2021
2ed508d
Refactor code to enable the user to update or get only his own data a…
adam-sas-on Apr 13, 2021
e70416f
Merge branch 'react_dev' of github.com:binawork/OnlineOnboarding into…
adam-sas-on Apr 14, 2021
152c3e0
Fix conflict after merge
adam-sas-on Apr 16, 2021
fbec8f0
Add Promise-based avatar uploading function; #224
adam-sas-on Apr 19, 2021
99fbd1d
Add state properties to update user 'on-the-fly'
adam-sas-on Apr 19, 2021
7979351
Use Promise-based avatar uploading function with function updating da…
adam-sas-on Apr 19, 2021
4c79148
Add documentation for function to uploading avatar
adam-sas-on Apr 20, 2021
1c25c2c
Fix noun for avatar in Polish
adam-sas-on Apr 20, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions onboarding/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,16 @@ class Meta:
)


class UserUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = get_user_model()
fields = (
'first_name',
'last_name',
'phone_number'
)


class UserSerializer(serializers.ModelSerializer):
# password = serializers.CharField(write_only=True)

Expand Down Expand Up @@ -181,6 +191,19 @@ class Meta:

# PACKAGE
class PackageSerializer(serializers.ModelSerializer):
class Meta:
ordering = ['-id']
model = Package
fields = (
'id',
'title',
'description',
'created_on',
'updated_on',
)


class PackageForHrSerializer(serializers.ModelSerializer):
class Meta:
ordering = ['-id']
model = Package
Expand Down Expand Up @@ -246,7 +269,7 @@ class Meta:
'description',
'link',
'updated_on',
'package',
'package', # to POST a page for respective package;
)
extra_kwargs = {
'package': {'required': False},
Expand Down Expand Up @@ -281,7 +304,23 @@ class Meta:
'description',
'created_on',
'updated_on',
'users',
'page_set'
)


class PackagePagesForHrSerializer(serializers.ModelSerializer):
page_set = PageSerializer(many=True)

class Meta:
ordering = ['-updated_on']
model = Package
fields = (
'id',
'title',
'description',
'created_on',
'updated_on',
'users', # for hr
'page_set'
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import EmployeeAvatar from "./EmployeeAvatar";
import EmployeeProfile from "./EmployeeProfile";
import ModalWarning from "../../ModalWarning";
import PageAddressBar from "../../PageAddressBar";
import { uploadAvatar, employeeAddEdit } from "../../hooks/Users";
import { uploadAvatarSync, employeeSelfEdit } from "../../hooks/Users";

function EmployeeAccount({ loggedUser }){

function EmployeeAccount({ loggedUser, countUpdate, updateUser }){
const [employeeModal, setModal ] = useState(<></>);
let editedUser = {...loggedUser};

Expand All @@ -21,26 +22,31 @@ function EmployeeAccount({ loggedUser }){
if(typeof editedUser.avatar !== "string" || editedUser.avatar.length < 1)
editedUser.avatar = "/onboarding/static/images/unknown-profile.jpg";

const [imageFile, setImageFile] = useState({localChanged: false, img: editedUser.avatar});
const [imageFile, setImageFile] = useState({localChanged: false, img: editedUser.avatar, msg: ""});

const handleEdit = function(user){
if(imageFile.localChanged){
console.log("EAc - av");
uploadAvatar(updateImage, imageFile.img, user);
}
uploadAvatarSync(imageFile, user).then(function(result){
if(typeof result.avatarData === "string"){
setImageFile({localChanged: false, img: result.avatarData, msg: result.avatarMsg?result.avatarMsg:""});
}

user.name = user.first_name;
employeeAddEdit(showModal, user);
return result;
}).then((result) => {
let user = {...result};
if(user.avatarData)
delete user.avatarData;
employeeSelfEdit(showModal, user);
});
};

const changeImage = (file) => {
setImageFile({localChanged: true, img: file});
setImageFile({localChanged: true, img: file, msg: ""});
};

const updateImage = function(response){
/*const updateImage = function(response){
if(typeof response.avatar === "string")
setImageFile({localChanged: false, img: response.avatar});
};
setImageFile({localChanged: false, img: response.avatar, msg: ""});
};*/

const showModal = (message) => {
setModal(
Expand All @@ -55,6 +61,7 @@ function EmployeeAccount({ loggedUser }){
};
const hideModal = function(){
setModal(<></>);
updateUser(countUpdate + 1);
};

return (
Expand Down
6 changes: 3 additions & 3 deletions onboarding/src/Components/FormTable/FormTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ function FormTable({ companyId, setPackageTitleInAddressBar, handleEditTitle })
loading = false;
packageData = location.state.packageData;
pages = location.state.pages;
}
}
if(!location.state || countUpdate > 0) {
if(packageAndForms) {
packageData = packageAndForms;
pages = packageAndForms?.page_set.sort((a,b) => b.id - a.id);
errorMessage = error;
loading = isLoading;
};
};
}
}

useEffect(() => {
if(pages) {
Expand Down
2 changes: 1 addition & 1 deletion onboarding/src/Components/hooks/EmployeeForms.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export function SingleEmployeeForms(count, setError, setLoading){
fetchProps = {method:"GET", headers:{"Accept":"application/json", "Content-Type":"application/json", "X-CSRFToken":""}};

useEffect(() => {
fetch(url + "api/package_pages/list_by_company_employee/", fetchProps).then(
fetch(url + "api/package_pages/", fetchProps).then(
(res) => {
if(!res.ok){
throw Error("Wystąpił błąd w pobieraniu katalogów!");
Expand Down
2 changes: 1 addition & 1 deletion onboarding/src/Components/hooks/Packages.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function fetchPackages(count) {
};

useEffect(() => {
fetch(url + "api/package/list_by_company_hr/", fetchProps)
fetch(url + "api/package/", fetchProps)
.catch(error => {
showError(error.message);
console.error(error);
Expand Down
2 changes: 1 addition & 1 deletion onboarding/src/Components/hooks/ProgressStats.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ export function usersWithPackages(props){
};

useEffect(() => {
fetch(url + "api/package/list_by_company_hr/", fetchProps).then((res) => res.json()).then(
fetch(url + "api/package/", fetchProps).then((res) => res.json()).then(
(result) => {
if(Array.isArray(result)){
let users4Packages = [], packageIds;
Expand Down
108 changes: 107 additions & 1 deletion onboarding/src/Components/hooks/Users.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export function uploadAvatar(handleSuccess, avatarFile, employeeObject, showModa
fetch(url + 'api/user-avatar/', fetchProps)
.then(response => {
if(!response.ok) {
throw Error("Wystąpił błąd podczas zapisywania avatara!")
throw Error("Wystąpił błąd podczas zapisywania zdjęcia!")
}
return response.json();
})
Expand All @@ -188,6 +188,112 @@ export function uploadAvatar(handleSuccess, avatarFile, employeeObject, showModa
});
}

/**
* Updates user (mainly employee) on endpoint for some (not most) data.
* @param handleMessage - function to call on response;
* @param employeeObject - object with same fields like those listed in serializer,
* {first_name": String,
"last_name": String,
"phone_number": String};
*/
export function employeeSelfEdit(handleMessage, employeeObject){
let url = getPath(), userData, token = getCookie('csrftoken'),
fetchProps = {method: "PATCH", headers: {}, body: null};

fetchProps.headers = {"Accept":"application/json", "Content-Type":"application/json", "X-CSRFToken":token};

userData = {...employeeObject};
if(userData.avatar)
delete userData.avatar;

if(typeof userData.id)
delete userData.id;

let avatarMessage = "";
if(userData.avatarMsg){
avatarMessage = userData.avatarMsg;
delete userData.avatarMsg;
}

if(userData.name)
userData.first_name = userData.name;

fetchProps.body = JSON.stringify(userData);

fetch(url + "api/users/update_user/", fetchProps).then(res => {
if(!res.ok)
throw Error("Nie udpało się zapisać zmian.");
return res.json();
}
).then((result) => {
let msg = avatarMessage + " Zaktualizowano dane.";
if(Object.keys(result).length < 1){
msg = avatarMessage + " Aktualizacja danych nie nastąpiła: brak właściwych pól.";
} else {
msg = avatarMessage + " Zaktualizowano dane.";
if(result.hasOwnProperty("detail"))
msg += " " + result.detail;
}

handleMessage(msg, true);
},
(error) => {
handleMessage(avatarMessage + " Wystąpił błąd: " + error.message, false);
}
).catch(err => {
handleMessage(avatarMessage + " " + err.message, false);
});
}

/**
* Enables the user to change his avatar. It returns Promise object which returns employeeObject
* joined with the result from server or empty avatar properties if it not expected to be updated.
* @param avatarObject := {localChanged: Boolean, img: image or string-path, msg: String}
* localChanged - if true then avatar is to be uploaded, otherwise return an 'empty' Promise;
* img - an image to be uploaded;
* @param employeeObject - object with same fields like those listed in serializer for "api/users/update_user/" endpoint,
* {first_name: String,
* last_name: String,
* phone_number: String, ...};
* @returns {Promise<unknown>|Promise<{avatarData: null, avatarMsg: string} | {avatarData: *, avatarMsg: *}>}
*/
export function uploadAvatarSync(avatarObject, employeeObject){
if( !avatarObject.hasOwnProperty("localChanged") || avatarObject.localChanged === false){
let defaultResponse = {...employeeObject, avatarData: null, avatarMsg: ""};
return new Promise((resolve) => resolve(defaultResponse) );
}

let data = new FormData();
let url = getPath(),
token = getCookie('csrftoken'),
fetchProps = {
method:"POST",
headers:{"Accept":"application/json", "X-CSRFToken":token, "Authorization": "Token " + token},
body:null
};

data.append('avatar', avatarObject.img);
fetchProps.body = data;

return fetch(url + 'api/user-avatar/', fetchProps)
.then(response => {
if(!response.ok) {
throw Error("Wystąpił błąd podczas zapisywania zdjęcia!")
}
return response.json();
})
.then(data => {
let response = {...employeeObject, avatarData: null, avatarMsg: "Pomyślnie zaktualizowano zdjęcie. "};
if(data.avatar)
response.avatarData = data.avatar;
return response;
})
.catch(error => {
let response = {...employeeObject, avatarData: avatarObject.img, avatarMsg: error.message};
return response;
});
}

export function employeeRemove(handleSuccess, userId, setLoadingSave){
setLoadingSave(true);
if(userId < 2)
Expand Down
5 changes: 3 additions & 2 deletions onboarding/src/EmployeeApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import QnAList from "./Components/Employee/QnA/QnAList";
import EmployeeAccount from "./Components/Employee/EmployeeAccount/EmployeeAccount";

function EmployeeApp() {
const loggedUser = LoggedUser();
const [countUpdate, updateUser] = useState(0);
const loggedUser = LoggedUser(countUpdate);
const [showAside, setToggleAside] = useState(false);
const [page, setPage] = useState(null);

Expand All @@ -36,7 +37,7 @@ function EmployeeApp() {
<div className="page container-xl">
<Switch>
<Route path="/my_profile">
<EmployeeAccount loggedUser={ loggedUser } />
<EmployeeAccount loggedUser={ loggedUser } countUpdate={ countUpdate } updateUser={ updateUser } />
</Route>
<Route path="/q_and_a">
<QnAList />
Expand Down
Loading