import * as React from 'react'; import * as CSS from 'csstype'; import { Form, FormGroup, ActionGroup, FileUpload, Avatar, Button, Tooltip } from "@patternfly/react-core"; import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons'; import { AccountServiceContext } from '../../account-service/AccountServiceContext'; import { ContentAlert } from '../ContentAlert'; import { Msg } from '../../widgets/Msg'; interface AvatarFormProps { accountUrl: string; } interface AvatarFormState { errors: any; imageBlob: any; filename: string; avatarUrl: string; avatarSrc: string; noAvatarSrc: string; } export class AvatarForm extends React.Component { static contextType = AccountServiceContext; context: React.ContextType; private handleFileInputChange: any; constructor(props: AvatarFormProps, context: React.ContextType) { super(props); this.context = context; var currentAvatar = props.accountUrl + "-avatar" this.state = { errors: {avatar: ''}, imageBlob: null, filename: "", avatarUrl: currentAvatar, avatarSrc: currentAvatar, noAvatarSrc: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI0LjAuMiwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAzNiAzNiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMzYgMzY7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCS5zdDB7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojRjBGMEYwO30KCS5zdDF7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojRDJEMkQyO30KCS5zdDJ7ZmlsbDojQjhCQkJFO30KCS5zdDN7ZmlsbDojRDJEMkQyO30KPC9zdHlsZT4KPHJlY3QgY2xhc3M9InN0MCIgd2lkdGg9IjM2IiBoZWlnaHQ9IjM2Ii8+CjxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0xNy43LDIwLjFjLTMuNSwwLTYuNC0yLjktNi40LTYuNHMyLjktNi40LDYuNC02LjRzNi40LDIuOSw2LjQsNi40UzIxLjMsMjAuMSwxNy43LDIwLjF6Ii8+CjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0xMy4zLDM2bDAtNi43Yy0yLDAuNC0yLjksMS40LTMuMSwzLjVMMTAuMSwzNkgxMy4zeiIvPgo8cGF0aCBjbGFzcz0ic3QzIiBkPSJNMTAuMSwzNmwwLjEtMy4yYzAuMi0yLjEsMS4xLTMuMSwzLjEtMy41bDAsNi43aDkuNGwwLTYuN2MyLDAuNCwyLjksMS40LDMuMSwzLjVsMC4xLDMuMmg0LjcKCWMtMC40LTMuOS0xLjMtOS0yLjktMTFjLTEuMS0xLjQtMi4zLTIuMi0zLjUtMi42cy0xLjgtMC42LTYuMy0wLjZzLTYuMSwwLjctNi4xLDAuN2MtMS4yLDAuNC0yLjQsMS4yLTMuNCwyLjYKCUM2LjcsMjcsNS44LDMyLjIsNS40LDM2SDEwLjF6Ii8+CjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0yNS45LDM2bC0wLjEtMy4yYy0wLjItMi4xLTEuMS0zLjEtMy4xLTMuNWwwLDYuN0gyNS45eiIvPgo8L3N2Zz4=" } var reader = new FileReader() reader.onloadend = function (event: any) { var imgData = String(event.target!.result) this.imageScale(imgData, (blob: Blob) => { this.setState({ imageBlob: blob, avatarSrc: URL.createObjectURL(blob) }) }) }.bind(this) this.handleFileInputChange = (file: File, filename: string) => { if (filename != "") { this.setState({ filename: filename }) reader.readAsDataURL(file) } else { this.setState({ imageBlob: null, filename: "", avatarSrc: currentAvatar }) } } } private imageScale = (imgData: string, callback: any) => { var img = new Image() img.src = imgData img.onload = (event: Event) => { var canvas = document.createElement("canvas") var ctx = canvas.getContext("2d") ctx!.drawImage(img, 0, 0) var MAX_WIDTH = 250 var MAX_HEIGHT = 250 var width = img.width var height = img.height if (width > height) { if (width > MAX_WIDTH) { height *= MAX_WIDTH / width width = MAX_WIDTH } } else { if (height > MAX_HEIGHT) { width *= MAX_HEIGHT / height height = MAX_HEIGHT } } canvas.width = width canvas.height = height ctx = canvas.getContext("2d") ctx!.drawImage(img, 0, 0, width, height) canvas.toBlob(callback) } } private handleSubmit = (event: React.FormEvent): void => { event.preventDefault() const form = event.target as HTMLFormElement var formData = new FormData(form) formData.append("image", this.state.imageBlob) var xhr = new XMLHttpRequest(); xhr.onreadystatechange = () => { if (xhr.readyState == 4) { if (200 <= xhr.status && xhr.status <= 204) { ContentAlert.success('avatarUpdatedMessage') } else { ContentAlert.danger(xhr.response) } // force reload avatar this.setState({ errors: {avatar: ""}, imageBlob: null, filename: "", avatarSrc: this.state.avatarUrl }) } } xhr.open(form.method, form.action, true); xhr.send(formData); } private handleError = (event: any) => { this.setState({ errors: {avatar: Msg.localize('error-noAvatarFound')}, avatarSrc: "" }) } render() { const { filename, avatarUrl, avatarSrc, noAvatarSrc } = this.state const avatarStyle: CSS.Properties = { objectFit: 'cover', width: '150px', height: '150px', border: '1px solid lightgray', boxShadow: 'lightgray 6px 3px 10px 2px' } return (
this.handleSubmit(event)} > { avatarSrc !== "" ? : } {' '} }> } >
) } }