import React, { useRef, useEffect } from 'react'; import superagent from 'superagent'; import { fromUnixTime, formatDistanceToNow } from "date-fns"; import { formatInTimeZone } from 'date-fns-tz'; import * as THREE from 'three'; import { STLLoader } from 'three/examples/jsm/loaders/STLLoader'; import * as ApiUtils from '../CloudApi/ApiUtils.js'; import constants, { DEFAULT_TIMEZONE } from '../CloudApi/Constants.js'; import WaxIdBitField from './WaxIdBitField.jsx'; import ToolPathDownloadButton from './ToolPathDownloadButton.jsx'; import { Header, Message, Icon, Button, Table, Label, Modal } from 'semantic-ui-react' const MeshViewer = (props) => { const { scanFileMeshBuffer } = props; const containerRef = useRef(null); useEffect(() => { const renderer = new THREE.WebGLRenderer({ antialias: true }); const width = containerRef.current.offsetWidth; const height = 1000; renderer.setSize(width, height); containerRef.current.appendChild(renderer.domElement); const scene = new THREE.Scene(); scene.background = new THREE.Color(0xffffff); const camera = new THREE.PerspectiveCamera( 90, containerRef.current.offsetWidth / 1000, 0.1, 1000); // Lighting setup const light = new THREE.AmbientLight(0xffffff); scene.add(light); // Load STL file const loader = new STLLoader(); const geometry = loader.parse(scanFileMeshBuffer); const material = new THREE.MeshStandardMaterial({ wireframe: true, color: 0xaaaaaa }); const mesh = new THREE.Mesh(geometry, material); camera.position.z = 20; camera.lookAt(mesh.position); scene.add(mesh); mesh.position.x -= 5; // Rotate the mesh by 90 degrees so the face is correctly oriented. mesh.rotation.x = Math.PI / 2; let t = 0; // Animation loop const animate = () => { requestAnimationFrame(animate); renderer.render(scene, camera); mesh.rotation.z = Math.sin(t++ / 100); }; animate(); // Cleanup return () => { renderer.dispose(); }; }, []); return
; }; export default class ScanRequestComponent extends React.Component { constructor(props) { super(props); this.state = { loading: false, revokeScanRequestModalOpen: false, }; } async componentDidMount() { /* const res = await superagent.get(`/api/admin/fabricator/scan_request/${this.props.scanRequest.id}/mesh`).accept("application/json"); const decodedData = window.atob(res.body.data); const arrayBuffer = new ArrayBuffer(decodedData.length); const uint8Array = new Uint8Array(arrayBuffer); for (let i = 0; i < decodedData.length; i++) { uint8Array[i] = decodedData.charCodeAt(i); } this.setState({ scanFileMeshBuffer: arrayBuffer }) */ } showRevokeScanRequestModal() {} openRevokeScanRequestModal(i, e) { this.setState({ revokeScanRequestModalOpen: true}); } closeRevokeScanRequestModal(i, e) { this.setState({ revokeScanRequestModalOpen: false}); } async onRevokeScanRequest(e) { e.preventDefault(); this.setState({ loading: true }); try { let res = await superagent.put(`/api/admin/fabricator/scan_request/${this.props.scanRequest.id}`).send({ scanRequestState: this.props.schemas.ScanRequestStates["Revoked"] }); window.location.reload(); } catch (e) { window.alert("Error sending scan request email: " + e.message); console.error(e); } this.setState({ loading: false, revokeScanRequestModalOpen: false}); } renderScanMesh() { return
; /* if (!this.state.scanFileMeshBuffer) { return
; } return ; */ } renderIpdLabel() { if (this.props.scanRequest.ipd === -1) { return } return } render() { if (this.state.loading) { return (
) } let createdAtDateTime = fromUnixTime(this.props.scanRequest.createdAt / 1000); const createdAt = formatInTimeZone(createdAtDateTime, DEFAULT_TIMEZONE, 'PPPp z'); const fromNow = formatDistanceToNow(createdAtDateTime, { addSuffix: true }); const history = this.props.scanRequest.history && this.props.scanRequest.history.map((historyItem, historyItemIndex) => { let createdAtDateTime = fromUnixTime(historyItem.createdAt / 1000); const createdAt = formatInTimeZone(createdAtDateTime, DEFAULT_TIMEZONE, 'PPPp z'); return ( {createdAt} {historyItem.bigscreenAccountId} {historyItem.message} {(historyItem.metaData && historyItem.metaData.reason) &&
Reason: {historyItem.metaData.reason}
}
) }); const scanRequestState = Object.entries(this.props.schemas.ScanRequestStates).find(entry => entry[1] === this.props.scanRequest.scanRequestState)[0]; const stateLabelColor = (this.props.scanRequest.scanRequestState === this.props.schemas.ScanRequestStates["VerifiedAndReady"]) ? "green" : "grey"; const footer = ( ); return (
Are you sure you want to revoke this scan request? ID {this.props.scanRequest.id}  Owner View account Created {createdAt} ({fromNow}) State Version {this.props.scanRequest.version} IPD {this.renderIpdLabel()} Mesh {this.renderScanMesh()} {(this.props.scanRequest.jobIds && this.props.scanRequest.jobIds.length > 0) && Attached Jobs {this.props.scanRequest.jobIds.map(jobId => )} } {footer}
When User Message {history}
) } }