mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
update profile layout
This commit is contained in:
parent
c91a714e3c
commit
318ea81e7e
@ -8,8 +8,8 @@ function checkResponse(response) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getProfileImageUrl(token) {
|
export function getProfileImageUrl(token, revision) {
|
||||||
return '/profile/image?agent=' + token
|
return '/profile/image?agent=' + token + "&revision=" + revision
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchWithTimeout(url, options) {
|
async function fetchWithTimeout(url, options) {
|
||||||
@ -61,6 +61,12 @@ export async function setProfileData(token, name, location, description) {
|
|||||||
return await profile.json()
|
return await profile.json()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function setProfileImage(token, image) {
|
||||||
|
let profile = await fetchWithTimeout('/profile/image?agent=' + token, { method: 'PUT', body: JSON.stringify(image), timeout: FETCH_TIMEOUT });
|
||||||
|
checkResponse(profile)
|
||||||
|
return await profile.json()
|
||||||
|
}
|
||||||
|
|
||||||
export async function getGroups(token, revision) {
|
export async function getGroups(token, revision) {
|
||||||
let param = "?agent=" + token
|
let param = "?agent=" + token
|
||||||
if (revision != null) {
|
if (revision != null) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useState, useRef } from 'react';
|
import { useEffect, useState, useRef } from 'react';
|
||||||
import { setProfileData, getProfileImageUrl, getProfile, getGroups, getAvailable, getUsername, setLogin, createAccount } from './fetchUtil';
|
import { setProfileImage, setProfileData, getProfileImageUrl, getProfile, getGroups, getAvailable, getUsername, setLogin, createAccount } from './fetchUtil';
|
||||||
|
|
||||||
async function updateProfile(token, updateData) {
|
async function updateProfile(token, updateData) {
|
||||||
let profile = await getProfile(token);
|
let profile = await getProfile(token);
|
||||||
@ -71,10 +71,13 @@ export function useAppContext() {
|
|||||||
appLogout(updateState, clearWebsocket);
|
appLogout(updateState, clearWebsocket);
|
||||||
resetData();
|
resetData();
|
||||||
},
|
},
|
||||||
setProfile: async (name, location, description) => {
|
setProfileData: async (name, location, description) => {
|
||||||
await setProfileData(state.token, name, location, description);
|
await setProfileData(state.token, name, location, description);
|
||||||
},
|
},
|
||||||
profileImageUrl: () => getProfileImageUrl(state.token)
|
setProfileImage: async (image) => {
|
||||||
|
await setProfileImage(state.token, image);
|
||||||
|
},
|
||||||
|
profileImageUrl: () => getProfileImageUrl(state.token, state.Data?.profile?.revision)
|
||||||
}
|
}
|
||||||
|
|
||||||
const adminActions = {
|
const adminActions = {
|
||||||
|
@ -45,11 +45,17 @@ export function Profile(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onProfileSave = async () => {
|
const onProfileSave = async () => {
|
||||||
if (await actions.setModalProfile()) {
|
if (await actions.setProfileData()) {
|
||||||
setInfoVisible(false);
|
setInfoVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onImageSave = async () => {
|
||||||
|
if (await actions.setProfileImage()) {
|
||||||
|
setLogoVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const onSelectImage = () => {
|
const onSelectImage = () => {
|
||||||
imageFile.current.click();
|
imageFile.current.click();
|
||||||
};
|
};
|
||||||
@ -64,12 +70,12 @@ export function Profile(props) {
|
|||||||
|
|
||||||
const Footer = (
|
const Footer = (
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
<input type='file' id='file' ref={imageFile} onChange={e => selected(e)} style={{display: 'none'}}/>
|
<input type='file' id='file' accept="image/*" ref={imageFile} onChange={e => selected(e)} style={{display: 'none'}}/>
|
||||||
<div class="select">
|
<div class="select">
|
||||||
<Button key="select" class="select" onClick={() => onSelectImage()}>Select Image</Button>
|
<Button key="select" class="select" onClick={() => onSelectImage()}>Select Image</Button>
|
||||||
</div>
|
</div>
|
||||||
<Button key="back" onClick={() => setLogoVisible(false)}>Cancel</Button>
|
<Button key="back" onClick={() => setLogoVisible(false)}>Cancel</Button>
|
||||||
<Button key="save" type="primary" onClick={() => setLogoVisible(false)}>Save</Button>
|
<Button key="save" type="primary" onClick={() => onImageSave()}>Save</Button>
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -88,7 +94,7 @@ export function Profile(props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="block" onClick={() => setInfoVisible(true)}>
|
<div class="block" onClick={() => setInfoVisible(true)}>
|
||||||
<span class="label">detail:</span>
|
<span class="label">details:</span>
|
||||||
<EditIcon class="detailedit" />
|
<EditIcon class="detailedit" />
|
||||||
</div>
|
</div>
|
||||||
<div class="details">
|
<div class="details">
|
||||||
@ -99,7 +105,7 @@ export function Profile(props) {
|
|||||||
</div>
|
</div>
|
||||||
<div class="contact"></div>
|
<div class="contact"></div>
|
||||||
</div>
|
</div>
|
||||||
<Modal title="Profile Info" centered visible={infoVisible} okText="Save"
|
<Modal title="Profile Details" centered visible={infoVisible} okText="Save"
|
||||||
onOk={() => onProfileSave()} onCancel={() => setInfoVisible(false)}>
|
onOk={() => onProfileSave()} onCancel={() => setInfoVisible(false)}>
|
||||||
<ProfileInfo state={state} actions={actions} />
|
<ProfileInfo state={state} actions={actions} />
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -84,6 +84,10 @@ export const ProfileWrapper = styled.div`
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
padding-right: 8px;
|
padding-right: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
background: #f6f5ed;
|
||||||
|
padding-left: 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #dddddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detailedit {
|
.detailedit {
|
||||||
@ -98,7 +102,7 @@ export const ProfileWrapper = styled.div`
|
|||||||
|
|
||||||
.label {
|
.label {
|
||||||
padding-right: 8px;
|
padding-right: 8px;
|
||||||
font-size: 1.2em;
|
font-size: 1em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #888888;
|
color: #888888;
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import React, { useState, useCallback } from 'react';
|
import React, { useState, useCallback } from 'react';
|
||||||
import Cropper from 'react-easy-crop'
|
import Cropper from 'react-easy-crop'
|
||||||
import { UserOutlined } from '@ant-design/icons';
|
import { UserOutlined } from '@ant-design/icons';
|
||||||
import { ProfileImageWrapper, ProfileDefaultImage } from './ProfileImage.styled';
|
import { ProfileSpin, ProfileImageWrapper, ProfileDefaultImage } from './ProfileImage.styled';
|
||||||
|
|
||||||
export function ProfileImage({ state, actions }) {
|
export function ProfileImage({ state, actions }) {
|
||||||
|
|
||||||
const [crop, setCrop] = useState({ x: 0, y: 0 })
|
const [crop, setCrop] = useState({ x: 0, y: 0 })
|
||||||
const [zoom, setZoom] = useState(1)
|
const [zoom, setZoom] = useState(1)
|
||||||
|
|
||||||
const onCropComplete = useCallback((croppedArea, croppedAreaPixels) => {
|
const onCropComplete = useCallback((area, crop) => {
|
||||||
console.log("crop complete");
|
actions.setModalCrop(crop.width, crop.height, crop.x, crop.y)
|
||||||
});
|
});
|
||||||
|
|
||||||
const Logo = () => {
|
const Logo = () => {
|
||||||
@ -19,15 +19,12 @@ export function ProfileImage({ state, actions }) {
|
|||||||
return <></>
|
return <></>
|
||||||
}
|
}
|
||||||
|
|
||||||
const onSelect = () => {
|
|
||||||
console.log("ON SELECT");
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ProfileImageWrapper>
|
<ProfileImageWrapper>
|
||||||
<Cropper onClick={() => onSelect()} image={state.modalImage} crop={crop} zoom={zoom} aspect={1}
|
<Cropper image={state.modalImage} crop={crop} zoom={zoom} aspect={1}
|
||||||
onCropChange={setCrop} onCropComplete={onCropComplete} onZoomChange={setZoom} />
|
onCropChange={setCrop} onCropComplete={onCropComplete} onZoomChange={setZoom} />
|
||||||
<Logo />
|
<Logo />
|
||||||
|
<ProfileSpin size="large" spinning={state.modalBusy} />
|
||||||
</ProfileImageWrapper>
|
</ProfileImageWrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { Spin } from 'antd';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
export const ProfileImageWrapper = styled.div`
|
export const ProfileImageWrapper = styled.div`
|
||||||
@ -23,3 +24,8 @@ export const ProfileDefaultImage = styled.div`
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const ProfileSpin = styled(Spin)`
|
||||||
|
position: absolute;
|
||||||
|
x-index: 10;
|
||||||
|
`;
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ export function useProfile() {
|
|||||||
modalLocation: '',
|
modalLocation: '',
|
||||||
modalDescription: '',
|
modalDescription: '',
|
||||||
modalImage: null,
|
modalImage: null,
|
||||||
|
crop: { w :0, h: 0, x: 0, y: 0 }
|
||||||
});
|
});
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -40,12 +41,15 @@ export function useProfile() {
|
|||||||
setModalImage: (value) => {
|
setModalImage: (value) => {
|
||||||
updateState({ modalImage: value });
|
updateState({ modalImage: value });
|
||||||
},
|
},
|
||||||
setModalProfile: async () => {
|
setModalCrop: (w, h, x, y) => {
|
||||||
|
updateState({ crop: { w: w, h: h, x: x, y: y } });
|
||||||
|
},
|
||||||
|
setProfileData: async () => {
|
||||||
let set = false
|
let set = false
|
||||||
if(!state.modalBusy) {
|
if(!state.modalBusy) {
|
||||||
updateState({ modalBusy: true });
|
updateState({ modalBusy: true });
|
||||||
try {
|
try {
|
||||||
await app.actions.setProfile(state.modalName, state.modalLocation, state.modalDescription);
|
await app.actions.setProfileData(state.modalName, state.modalLocation, state.modalDescription);
|
||||||
set = true
|
set = true
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
@ -55,6 +59,39 @@ export function useProfile() {
|
|||||||
}
|
}
|
||||||
return set
|
return set
|
||||||
},
|
},
|
||||||
|
setProfileImage: async () => {
|
||||||
|
let set = false
|
||||||
|
if(!state.modalBusy) {
|
||||||
|
updateState({ modalBusy: true });
|
||||||
|
try {
|
||||||
|
const processImg = () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let img = new Image();
|
||||||
|
img.onload = () => {
|
||||||
|
var canvas = document.createElement("canvas");
|
||||||
|
var context = canvas.getContext('2d');
|
||||||
|
canvas.width = state.crop.w;
|
||||||
|
canvas.height = state.crop.h;
|
||||||
|
context.drawImage(img, state.crop.x, state.crop.y, state.crop.w, state.crop.h,
|
||||||
|
0, 0, state.crop.w, state.crop.h);
|
||||||
|
resolve(canvas.toDataURL());
|
||||||
|
}
|
||||||
|
img.onerror = reject;
|
||||||
|
img.src = state.modalImage;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
let dataUrl = await processImg();
|
||||||
|
let data = dataUrl.split(",")[1];
|
||||||
|
await app.actions.setProfileImage(data);
|
||||||
|
set = true
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
window.alert(err);
|
||||||
|
}
|
||||||
|
updateState({ modalBusy: false });
|
||||||
|
}
|
||||||
|
return set;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -10,6 +10,7 @@ export function Identity() {
|
|||||||
const { state, actions } = useIdentity()
|
const { state, actions } = useIdentity()
|
||||||
|
|
||||||
const Logo = () => {
|
const Logo = () => {
|
||||||
|
console.log(state);
|
||||||
if (state.imageUrl != null) {
|
if (state.imageUrl != null) {
|
||||||
if (state.imageUrl === '') {
|
if (state.imageUrl === '') {
|
||||||
return <UserOutlined />
|
return <UserOutlined />
|
||||||
|
Loading…
Reference in New Issue
Block a user