This function was used in class components, now I want to change that in functional component. How can I do that? - react-functional-component

`
if (sInd === dInd) {
const reorderCardItems = reorderCard(items[sInd], source.index, destination.index);
const newState = [...items];
newState[sInd].card = reorderCardItems;
seState({newState: newState});
`
if (sInd === dInd) {
const reorderCardItems = reorderCard(items[sInd], source.index, destination.index);
let newState = [...items];
newState[sInd].card = reorderCardItems;
newState= newState;
it's giving me error that 'newState' is assigned to itself.

Related

Rooms with Forge

My goal is to see the Revit rooms in the Forge viewer. The application is in .NET Core. I have tried implementing GenerateMasterViews.
The code I am using to achieve this is:
[Route("api/forge/modelderivative/jobs")]
public async Task<dynamic> TranslateObject([FromBody]TranslateObjectModel objModel)
{
dynamic oauth = await OAuthController.GetInternalAsync();
// prepare the payload
var advOutputPayload = new JobSvf2OutputPayloadAdvanced();
advOutputPayload.GenerateMasterViews = true;
List<JobPayloadItem> outputs = new List<JobPayloadItem>()
{
new JobPayloadItem(
JobPayloadItem.TypeEnum.Svf2,
new List<JobPayloadItem.ViewsEnum>()
{
JobPayloadItem.ViewsEnum._2d,
JobPayloadItem.ViewsEnum._3d
},
advOutputPayload
)
};
JobPayload job;
job = new JobPayload(new JobPayloadInput(objModel.objectName), new JobPayloadOutput(outputs));
// start the translation
DerivativesApi derivative = new DerivativesApi();
derivative.Configuration.AccessToken = oauth.access_token;
dynamic jobPosted = await derivative.TranslateAsync(job);
return jobPosted;
}
Autodesk.Viewing.Initializer(options, () => {
viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('forgeViewer'));
viewer.start();
var documentId = 'urn:' + urn;
Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
});
}
function onDocumentLoadSuccess(doc) {
var viewables = doc.getRoot().getDefaultGeometry();
viewer.loadDocumentNode(doc, viewables).then(i => {
// documented loaded, any action?
});
}
But I can't get it to work.
I have looked for information, but this url: https://forge.autodesk.com/en/docs/model-derivative/v2/tutorials/prep-roominfo4viewer/option2/ and this url:
https://forge.autodesk.com/en/docs/model-derivative/v2/tutorials/prep-roominfo4viewer/option1/ they don't work and I couldn't see how to do it.
To check if the object is in the room, we can do the following:
Get bounds for each room and object
getBoundingBox(dbId, model) {
const it = model.getInstanceTree();
const fragList = model.getFragmentList();
let bounds = new THREE.Box3();
it.enumNodeFragments(dbId, (fragId) => {
let box = new THREE.Box3();
fragList.getWorldBounds(fragId, box);
bounds.union(box);
}, true);
return bounds;
}
Iterate rooms and objects and use containsBox or containsPoint to check if their bounding box has intersection.
If you want to do an acute collision check, you can take advantage of the ThreeCSG.js to do geometry intersection. Here is a blog post demonstrating how to integrate ThreeCSG.js with Forge Viewer.
https://forge.autodesk.com/blog/boolean-operations-forge-viewer
Note. This process would reduce the viewer performance since JavaScript is running on a single thread on the Web Browser, so you may use some technologies like the web worker to do the complex calculations on a separate thread.
Update:
Here is a working sample extension demonstrating the above idea:
/////////////////////////////////////////////////////////////////////
// Copyright (c) Autodesk, Inc. All rights reserved
// Written by Forge Partner Development
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
/////////////////////////////////////////////////////////////////////
(function () {
const Utility = {
/**
* Rest an object
* #param {Object} obj An object to be reset.
* ref: https://stackoverflow.com/a/24090180
*/
resetObject: function (obj) {
for (let key in Object.getOwnPropertyNames(obj)) {
if (!obj.hasOwnProperty(key)) continue;
let val = obj[key];
switch (typeof val) {
case 'string':
obj[key] = ''; break;
case 'number':
obj[key] = 0; break;
case 'boolean':
obj[key] = false; break;
case 'object':
if (val === null) break;
if (val instanceof Array) {
while (obj[key].length > 0) {
obj[key].pop();
}
break;
}
val = {};
//Or recursively clear the sub-object
//resetObject(val);
break;
}
}
}
};
/**
* A Forge Viewer extension for loading and rendering Revit Grids by AEC Model Data
* #class
*/
class RoomLocatorExtension extends Autodesk.Viewing.Extension {
constructor(viewer, options) {
super(viewer, options);
this.roomCategoryName = options.roomCategoryName || 'Revit Rooms';//'Revit Habitaciones'
this.onContextMenu = this.onContextMenu.bind(this);
}
onContextMenu(menu, status) {
if (status.hasSelected) {
menu.push({
title: 'Find room',
target: async () => {
let selSet = this.viewer.getSelection();
this.viewer.clearSelection();
const roomDbIds = await this.locateElementByRoom(selSet[0]);
if (!roomDbIds || roomDbIds.length <= 0) return;
this.viewer.select(roomDbIds);
}
});
}
}
async getPropertiesAsync(dbId, model) {
return new Promise((resolve, reject) => {
model.getProperties2(
dbId,
(result) => resolve(result),
(error) => reject(error)
);
});
}
async getElementsByCategoryAsync(category) {
return new Promise((resolve, reject) => {
this.viewer.search(
category,
(dbIds) => resolve(dbIds),
(error) => reject(error),
['Category'],
{ searchHidden: true }
);
});
}
async getRoomDbIds() {
try {
const roomDbIds = await this.getElementsByCategoryAsync(this.roomCategoryName);
if (!roomDbIds || roomDbIds.length <= 0) {
throw new Error('No Rooms found in current model');
}
return roomDbIds;
} catch (ex) {
console.warn(`[RoomLocatorExtension]: ${ex}`);
throw new Error('No room found');
}
}
getBoundingBox(dbId, model) {
const it = model.getInstanceTree();
const fragList = model.getFragmentList();
let bounds = new THREE.Box3();
it.enumNodeFragments(dbId, (fragId) => {
let box = new THREE.Box3();
fragList.getWorldBounds(fragId, box);
bounds.union(box);
}, true);
return bounds;
}
getLeafFragIds(model, leafId) {
const instanceTree = model.getData().instanceTree;
const fragIds = [];
instanceTree.enumNodeFragments(leafId, function (fragId) {
fragIds.push(fragId);
});
return fragIds;
}
getComponentGeometryInfo(dbId, model) {
const viewer = this.viewer;
const viewerImpl = viewer.impl;
const fragIds = this.getLeafFragIds(model, dbId);
let matrixWorld = null;
const meshes = fragIds.map((fragId) => {
const renderProxy = viewerImpl.getRenderProxy(model, fragId);
const geometry = renderProxy.geometry;
const attributes = geometry.attributes;
const positions = geometry.vb ? geometry.vb : attributes.position.array;
const indices = attributes.index.array || geometry.ib;
const stride = geometry.vb ? geometry.vbstride : 3;
const offsets = geometry.offsets;
matrixWorld = matrixWorld || renderProxy.matrixWorld.elements;
return {
positions,
indices,
offsets,
stride
};
});
return {
matrixWorld,
meshes
};
}
getComponentGeometry(data, vertexArray) {
const offsets = [
{
count: data.indices.length,
index: 0,
start: 0
}
];
for (let oi = 0, ol = offsets.length; oi < ol; ++oi) {
let start = offsets[oi].start;
let count = offsets[oi].count;
let index = offsets[oi].index;
for (let i = start, il = start + count; i < il; i += 3) {
const a = index + data.indices[i];
const b = index + data.indices[i + 1];
const c = index + data.indices[i + 2];
const vA = new THREE.Vector3();
const vB = new THREE.Vector3();
const vC = new THREE.Vector3();
vA.fromArray(data.positions, a * data.stride);
vB.fromArray(data.positions, b * data.stride);
vC.fromArray(data.positions, c * data.stride);
vertexArray.push(vA);
vertexArray.push(vB);
vertexArray.push(vC);
}
}
}
buildComponentMesh(data) {
const vertexArray = [];
for (let idx = 0; idx < data.nbMeshes; ++idx) {
const meshData = {
positions: data['positions' + idx],
indices: data['indices' + idx],
stride: data['stride' + idx]
}
this.getComponentGeometry(meshData, vertexArray);
}
const geometry = new THREE.Geometry();
for (let i = 0; i < vertexArray.length; i += 3) {
geometry.vertices.push(vertexArray[i]);
geometry.vertices.push(vertexArray[i + 1]);
geometry.vertices.push(vertexArray[i + 2]);
const face = new THREE.Face3(i, i + 1, i + 2);
geometry.faces.push(face);
}
const matrixWorld = new THREE.Matrix4();
matrixWorld.fromArray(data.matrixWorld);
const mesh = new THREE.Mesh(geometry);
mesh.applyMatrix(matrixWorld);
mesh.boundingBox = data.boundingBox;
mesh.bsp = new ThreeBSP(mesh)
mesh.dbId = data.dbId;
return mesh;
}
buildCsgMesh(dbId, model) {
const geometry = this.getComponentGeometryInfo(dbId, model);
const data = {
boundingBox: this.getBoundingBox(dbId, model),
matrixWorld: geometry.matrixWorld,
nbMeshes: geometry.meshes.length,
dbId
};
geometry.meshes.forEach((mesh, idx) => {
data['positions' + idx] = mesh.positions;
data['indices' + idx] = mesh.indices;
data['stride' + idx] = mesh.stride;
});
return this.buildComponentMesh(data);
}
async buildBBoxes() {
try {
const model = this.viewer.model;
const roomBBoxes = {};
const roomDbIds = await this.getRoomDbIds();
for (let i = 0; i < roomDbIds.length; i++) {
let dbId = roomDbIds[i];
let bbox = await this.getBoundingBox(dbId, model);
roomBBoxes[dbId] = bbox;
}
this.cachedBBoxes['rooms'] = roomBBoxes;
} catch (ex) {
console.warn(`[RoomLocatorExtension]: ${ex}`);
throw new Error('Cannot build bounding boxes from rooms');
}
}
async locateElementByRoom(dbId) {
let bbox = await this.getBoundingBox(dbId, this.viewer.model);
const roomDbIds = Object.keys(this.cachedBBoxes['rooms']);
const roomBoxes = Object.values(this.cachedBBoxes['rooms']);
// Coarse Phase Collision
const coarseResult = [];
for (let i = 0; i < roomDbIds.length; i++) {
let roomDbId = roomDbIds[i];
let roomBox = roomBoxes[i];
if (roomBox.containsBox(bbox)) {
coarseResult.push(parseInt(roomDbId));
} else {
if (roomBox.containsPoint(bbox.min) || roomBox.containsPoint(bbox.max) || roomBox.containsPoint(bbox.center())) {
coarseResult.push(parseInt(roomDbId));
}
}
}
// Fine Phase Collision
const fineResult = [];
let elementCsgMesh = this.buildCsgMesh(dbId, this.viewer.model);
for (let i = 0; i < coarseResult.length; i++) {
let roomDbId = coarseResult[i];
let roomCsgMesh = this.buildCsgMesh(roomDbId, this.viewer.model);
let result = elementCsgMesh.bsp.intersect(roomCsgMesh.bsp);
if (result.tree.polygons.length <= 0) {
result = roomCsgMesh.bsp.intersect(elementCsgMesh.bsp);
// if (!this.viewer.overlays.hasScene('csg'))
// this.viewer.overlays.addScene('csg');
// else
// this.viewer.overlays.clearScene('csg');
// let mat = new THREE.MeshBasicMaterial({ color: 'red' })
// let mesh = result.toMesh(mat);
// this.viewer.overlays.addMesh(mesh, 'csg')
if (result.tree.polygons.length <= 0) continue;
}
fineResult.push(roomDbId);
}
return fineResult;
}
async load() {
await Autodesk.Viewing.Private.theResourceLoader.loadScript(
'https://cdn.jsdelivr.net/gh/Wilt/ThreeCSG#develop/ThreeCSG.js',
'ThreeBSP'
);
if (!window.ThreeBSP)
throw new Error('Cannot load ThreeCSG.js, please download a copy from https://github.com/Wilt/ThreeCSG/blob/develop/ThreeCSG.js')
await this.viewer.waitForLoadDone();
this.cachedBBoxes = {};
await this.buildBBoxes();
this.viewer.registerContextMenuCallback(
'RoomLocatorExtension',
this.onContextMenu
);
return true;
}
unload() {
Utility.resetObject(this.cachedBBoxes);
this.viewer.unregisterContextMenuCallback(
'RoomLocatorExtension',
this.onContextMenu
);
return true;
}
}
Autodesk.Viewing.theExtensionManager.registerExtension('RoomLocatorExtension', RoomLocatorExtension);
})();
Snapshots:

How to decrypt AES with Google Apps Script

I am trying to decrypt AES with GAS. The target of decryption is a document file retrieved by Amazon Selling Partner API.
The key, iv, and URL are obtained by the API, and I want to decrypt the data downloaded by accessing the URL with the key and iv.
However, the decrypted text is either empty or garbled.
Can you please tell me what is wrong with the following code? The code uses cCryptoGS, which is a wrapper library for CryptoJS.
const decrypt_test = () => {
const url = 'https://tortuga-prod-fe.s3-us-west-2.amazonaws.com/%2FNinetyDays/amzn1.tortuga.3.5d4685fe-cdf1-4f37-8dfc-a25b85468e34.T1J5QXLEXAMPLE';
const response = UrlFetchApp.fetch(url);
const file = response.getContentText();
const key = 'xiZ8FGT6pYo49ZwfvAplJxKgO0qW46Morzs5aEXAMPLE';
const iv = 'aoGh0rhbB3ALlCFKiEXAMPLE';
const enc_key = cCryptoGS.CryptoJS.enc.Base64.parse(key);
const enc_iv = cCryptoGS.CryptoJS.enc.Base64.parse(iv);
const cipherParams = cCryptoGS.CryptoJS.lib.CipherParams.create({
ciphertext: file//cCryptoGS.CryptoJS.enc.Base64.parse(file)
});
console.log(`enc_key_length:${enc_key.words.length}`);
console.log(`enc_iv_length:${enc_iv.words.length}`);
const decryptedMessage = cCryptoGS.CryptoJS.AES.decrypt(cipherParams, enc_key, { iv: enc_iv, mode: cCryptoGS.CryptoJS.mode.CBC}).toString();
console.log(`decryptedMessage:${decryptedMessage}`);
return decryptedMessage;
};
[output]
2021/06/20 20:04:04 debug enc_key_length:8
2021/06/20 20:04:04 debug enc_iv_length:4
2021/06/20 20:04:04 debug decryptedMessage:bfc095f3ecec221e8585ceb68031078d25112f5f26ea2c1f80470f5f4f19f2e1c2cd94638e8666c3486fa29191b568bcd9e8d5a3bdcbbc05456f0567bb6cdae675fa044f94e560379d16b1d370cd7c4a9c5afbbcf4fde2694ed01c1b7950eaabc65e46c4640d8f0814bfe66e8ae65f7768136ac4615624be25373d665ee8fde82742e26664d7c09c61ac8994dc3052f0f22d5042f0b407d696e3c84a3906350dc60c46001ef7865d0c6594c57c5af22616688e028f52d4f12b538d0580c420fdcb0ee61287d4ee2629cd7d39f739d63e84dd75e948eaffb4383076f0c66997
The following code solved the problem
const decrypt_test = () => {
const url = 'https://tortuga-prod-fe.s3-us-west-2.amazonaws.com/%2FNinetyDays/EXAMPLE';
let options = {
'method': 'get',
'muteHttpExceptions': true,
};
const response = UrlFetchApp.fetch(url, options);
const file = response.getBlob().getBytes();
const key = 'xiZ8FGT6pYo49ZwfvAplJxKgO0qW46MoEXAMPLE';
const iv = 'aoGh0rhbB3ALlCFKiuJEXAMPLE';
const enc_key = cCryptoGS.CryptoJS.enc.Base64.parse(key);
const enc_iv = cCryptoGS.CryptoJS.enc.Base64.parse(iv);
const cipherParams = cCryptoGS.CryptoJS.lib.CipherParams.create({
ciphertext: cCryptoGS.CryptoJS.enc.Hex.parse(hexes(file))
});
const decryptedMessage = cCryptoGS.CryptoJS.AES.decrypt(cipherParams, enc_key,
{ iv: enc_iv, mode: cCryptoGS.CryptoJS.mode.CBC}).toString();
console.log(`decryptedMessage:${decryptedMessage}`);
const bin = bytes(decryptedMessage)
const myBlob = Utilities.newBlob(bin, MimeType.TEXT, "decrypted.csv");
DriveApp.createFile(myBlob);
};
const bytes = (hexstr) => {
ary = [];
for (var i = 0; i < hexstr.length; i += 2) {
ary.push(parseInt(hexstr.substr(i, 2), 16));
}
return ary;
}
const hexes = (ary) => {
return ary.map((e) => ( '00' + (e < 0 ? e += 0x0100 : e).toString(16)).slice(-2)).join('')
}

How to properly use html-to-react?

so i am learning about this package html-to-react, and for the most part, i understand it. However, their is a piece of code i just cannot seem to be able to get my head around. The code is:
var React = require('react');
var HtmlToReact = require('html-to-react');
var HtmlToReactParser = require('html-to-react').Parser;
var htmlToReactParser = new HtmlToReactParser();
var htmlInput = '<div><div data-test="foo"><p>Text</p><p>Text</p></div></div>';
var htmlExpected = '<div><div data-test="foo"><h1>Heading</h1></div></div>';
var isValidNode = function () {
return true;
};
var processNodeDefinitions = new HtmlToReact.ProcessNodeDefinitions(React);
// Order matters. Instructions are processed in
// the order they're defined
var processingInstructions = [
{
// This is REQUIRED, it tells the parser
// that we want to insert our React
// component as a child
replaceChildren: true,
shouldProcessNode: function (node) {
return node.attribs && node.attribs['data-test'] === 'foo';
},
processNode: function (node, children, index) {
return React.createElement('h1', {key: index,}, 'Heading');
}
},
{
// Anything else
shouldProcessNode: function (node) {
return true;
},
processNode: processNodeDefinitions.processDefaultNode,
},
];
var reactComponent = htmlToReactParser.parseWithInstructions(
htmlInput, isValidNode, processingInstructions);
var reactHtml = ReactDOMServer.renderToStaticMarkup(
reactComponent);
assert.equal(reactHtml, htmlExpected);
The code i don't understand is the:
shouldProcessNode: function (node) {
return node.attribs && node.attribs['data-test'] === 'foo';
},
Any help would be very appreciated. Thanks

How to determine if variable is a Cheerio object?

How do you tell if something is a loaded cheerio object? For instance:
const cheerio = require('cheerio');
const html = '<div>';
const $ = cheerio.load(html);
const $div = $('div');
// if isCheerio func existed..
if (cheerio.isCheerio(html)) {} // return false
if (cheerio.isCheerio($)) {} // return true
if (cheerio.isCheerio($div)) {} // return true
I could just check the typeof for a string vs func, but that is just a hack.
You do it like this:
const cheerio = require('cheerio');
const html = '<div>';
const $ = cheerio.load(html);
const $div = $('div');
console.log(html.cheerio) // undefined
console.log($.cheerio) // undefined
console.log($().cheerio) // [cheerio object]
console.log($div.cheerio) // [cheerio object]
So you can then use these in conditionals, like:
if ($div.cheerio) {
console.log($div.get())
}

Autodesk Forge - Isolating element: amount of transparency of others

When we isolate an element in a 3d view, is there anyway to control the amount of transparency of all the other elements? Say, change to 50% translucent?
Have I missed something obvious?
And can you do the same for 2d views?
I dug out the following code for you, it shows how to set all leaf nodes to 50% opacity by changing their material properties:
AutodeskNamespace("Autodesk.ADN.Viewing.Extension");
function getLeafNodes(model, nodeId) {
return new Promise((resolve, reject)=>{
try{
var leafIds = [];
var instanceTree = model.getData().instanceTree
nodeId = nodeId || instanceTree.getRootId()
function _getLeafNodesRec(id){
var childCount = 0;
instanceTree.enumNodeChildren(id,
function(childId) {
_getLeafNodesRec(childId)
++childCount
})
if(childCount == 0){
leafIds.push(id)
}
}
_getLeafNodesRec(nodeId)
return resolve(leafIds)
} catch(ex){
return reject(ex)
}
})
}
function nodeIdToFragIds(model, nodeId) {
var instanceTree = model.getData().instanceTree
var fragIds = []
instanceTree.enumNodeFragments(
nodeId, (fragId) => {
fragIds.push(fragId)
});
return fragIds
}
Autodesk.ADN.Viewing.Extension.Basic = function (viewer, options) {
Autodesk.Viewing.Extension.call(this, viewer, options);
var _this = this;
_this.load = function () {
var fragList = viewer.model.getFragmentList()
getLeafNodes(viewer.model).then((dbIds) => {
dbIds.forEach((dbId) => {
const fragIds = nodeIdToFragIds(
viewer.model, dbId)
fragIds.forEach((fragId) => {
var material = fragList.getMaterial(fragId)
if(material) {
material.opacity = 0.5
material.transparent = true
material.needsUpdate = true
}
})
})
viewer.impl.invalidate(true, true, true)
})
return true;
};
_this.unload = function () {
Autodesk.Viewing.theExtensionManager.unregisterExtension(
"Autodesk.ADN.Viewing.Extension.Basic");
return true;
};
};
Autodesk.ADN.Viewing.Extension.Basic.prototype =
Object.create(Autodesk.Viewing.Extension.prototype);
Autodesk.ADN.Viewing.Extension.Basic.prototype.constructor =
Autodesk.ADN.Viewing.Extension.Basic;
Autodesk.Viewing.theExtensionManager.registerExtension(
"Autodesk.ADN.Viewing.Extension.Basic",
Autodesk.ADN.Viewing.Extension.Basic);
Some syntax requires ES6 transpiling. You can quickly paste the code there to test it: http://viewer.autodesk.io/node/gallery/#/extension-editor?id=560c6c57611ca14810e1b2bf
This works only for 3D, I'll see what we can do for 2D and update that topic.