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

VYZN: Matrix Messaging Integration #455

Merged
merged 25 commits into from
Jan 21, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
3d43860
install matrix-widget-api
clecherbauer Oct 21, 2022
798f50f
bldrs to vyzn integration wip
clecherbauer Oct 20, 2022
37a733a
test out routing
clecherbauer Oct 21, 2022
5a68252
refactor code, use store instead of router
clecherbauer Oct 25, 2022
069a99c
changes for codeReview
clecherbauer Nov 5, 2022
4206e78
move WidgetApi into react context, use navigation() instead of the de…
clecherbauer Nov 8, 2022
301b66c
seperate events for selection an unselection of elements
clecherbauer Nov 11, 2022
52f3f1d
select multiple elements
clecherbauer Nov 12, 2022
bcb98a2
remove code comments
clecherbauer Nov 18, 2022
a376e72
changes from codereview
clecherbauer Nov 29, 2022
5ca7f6a
VYZN-806: Tests for Bldrs integration
Dec 16, 2022
2a7e985
Merge pull request #1 from Adrian62D/bldrs-to-vyzn
clecherbauer Dec 19, 2022
f44de2f
Merge remote-tracking branch 'origin/main' into bldrs-to-vyzn
clecherbauer Dec 21, 2022
9053e4d
fix issue after merge
clecherbauer Jan 4, 2023
51c9081
fix new linting issues after merge
clecherbauer Jan 4, 2023
2d7af8f
Merge remote-tracking branch 'origin/main' into bldrs-to-vyzn
clecherbauer Jan 4, 2023
a8ed57d
trigger preview deployment
clecherbauer Jan 6, 2023
adc8cf1
Merge remote-tracking branch 'bldrs/main' into bldrs-to-vyzn
Jan 18, 2023
b8e2267
stabilize cypress integration tests
Jan 19, 2023
c90c50f
cadview test fix
Jan 19, 2023
de92e48
Merge pull request #2 from aozien/bldrs-to-vyzn
clecherbauer Jan 19, 2023
b29368f
fix yarn lock conflict
Jan 20, 2023
a5c8c80
parameters bug fix & adding test case for it
Jan 20, 2023
dd022db
added matrix-widget-api to the lock file
Jan 21, 2023
55ec16a
Merge branch 'main' into bldrs-to-vyzn
pablo-mayrgundter Jan 21, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# misc
.DS_Store
.vscode
.idea
*.log

cypress/videos
Expand Down
3 changes: 2 additions & 1 deletion package.json
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "bldrs",
"version": "1.0.0-r501",
"version": "1.0.0-r534",
"main": "src/index.jsx",
"homepage": "https://github.com/bldrs-ai/Share",
"bugs": {
Expand Down Expand Up @@ -34,6 +34,7 @@
"@mui/styles": "^5.9.2",
"@octokit/rest": "^19.0.3",
"clsx": "^1.2.1",
"matrix-widget-api": "^1.1.1",
"normalize.css": "^8.0.1",
"prop-types": "^15.8.1",
"react": "^18.2.0",
Expand Down
1 change: 0 additions & 1 deletion src/BaseRoutes.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {Outlet, Route, Routes, useLocation, useNavigate} from 'react-router-dom'
import ShareRoutes from './ShareRoutes'
import debug from './utils/debug'


/**
* From URL design: https://github.com/bldrs-ai/Share/wiki/URL-Structure
* ... We adopt a URL structure similar to Google Apps URL structure:
Expand Down
25 changes: 19 additions & 6 deletions src/Containers/CadView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import SearchIndex from './SearchIndex'
* Experimenting with a global. Just calling #indexElement and #clear
* when new models load.
*/
const searchIndex = new SearchIndex()
export const searchIndex = new SearchIndex()


let count = 0
Expand Down Expand Up @@ -74,6 +74,7 @@ export default function CadView({
const setSelectedElements = useStore((state) => state.setSelectedElements)
const setCutPlaneDirection = useStore((state) => state.setCutPlaneDirection)
const setLevelInstance = useStore((state) => state.setLevelInstance)
const selectedElements = useStore((state) => state.selectedElements)


/* eslint-disable react-hooks/exhaustive-deps */
Expand All @@ -100,6 +101,17 @@ export default function CadView({
}, [searchParams])


useEffect(() => {
if (Array.isArray(selectedElements)) {
if (selectedElements.length > 0) {
selectItemsInScene(selectedElements.map((id) => parseInt(id)))
} else {
unSelectItems()
}
}
}, [selectedElements])


// Watch for path changes within the model.
// TODO(pablo): would be nice to have more consistent handling of path parsing.
const location = useLocation()
Expand Down Expand Up @@ -324,7 +336,7 @@ export default function CadView({
throw new Error('IllegalState: empty search query')
}
const resultIDs = searchIndex.search(query)
selectItemsInScene(resultIDs)
setSelectedElements(resultIDs.map((id) => `${id}`))
setDefaultExpandedElements(resultIDs.map((id) => `${id }`))
Privacy.recordEvent('search', {
search_term: query,
Expand Down Expand Up @@ -354,8 +366,10 @@ export default function CadView({

/** Unpick active scene elts and remove clip planes. */
function unSelectItems() {
viewer.IFC.unpickIfcItems()
viewer.clipper.deleteAllPlanes()
if (viewer) {
viewer.IFC.unpickIfcItems()
viewer.clipper.deleteAllPlanes()
}
resetState()
const repoFilePath = modelPath.gitpath ? modelPath.getRepoPath() : modelPath.filepath
navigate(`${pathPrefix}${repoFilePath}`)
Expand All @@ -368,7 +382,6 @@ export default function CadView({
* @param {Array} resultIDs Array of expressIDs
*/
async function selectItemsInScene(resultIDs) {
setSelectedElements(resultIDs.map((id) => `${id}`))
try {
await viewer.pickIfcItemsByID(0, resultIDs, true)
} catch (e) {
Expand Down Expand Up @@ -397,7 +410,7 @@ export default function CadView({
await selectItemsInScene([expressId])
const pathIds = computeElementPathIds(lookupElt, (elt) => elt.expressID)
setExpandedElements(pathIds.map((n) => `${n}`))
setSelectedElements(`${expressId}`)
setSelectedElements([`${expressId}`])
const props = await viewer.getProperties(0, expressId)
setSelectedElement(props)
return pathIds
Expand Down
39 changes: 39 additions & 0 deletions src/Containers/SearchIndex.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export default class SearchIndex {
this.eltsByType = {}
this.eltsByName = {}
this.eltsByGlobalId = {}
this.eltsByExpressId = {}
this.eltsByText = {}
}

Expand Down Expand Up @@ -45,6 +46,10 @@ export default class SearchIndex {
this.indexElementByString(this.eltsByGlobalId, elt.GlobalId.value, elt)
}

if (elt.expressID) {
this.indexElementByString(this.eltsByExpressId, elt.expressID.toString(), elt)
}

const description = Ifc.getDescription(elt)
if (description) {
this.indexElementByStringSet(this.eltsByGlobalId,
Expand Down Expand Up @@ -114,6 +119,7 @@ export default class SearchIndex {
deleteProperties(this.eltsByType)
deleteProperties(this.eltsByName)
deleteProperties(this.eltsByGlobalId)
deleteProperties(this.eltsByExpressId)
deleteProperties(this.eltsByText)
}

Expand Down Expand Up @@ -159,6 +165,7 @@ export default class SearchIndex {
addAll(this.eltsByType[lowerToken])

addAll(this.eltsByGlobalId[token])
addAll(this.eltsByExpressId[token])

addAll(this.eltsByText[token])

Expand All @@ -167,4 +174,36 @@ export default class SearchIndex {
debug().log('result IDs: ', resultIDs)
return resultIDs
}

/**
*
*
* @param {string} expressId.
* @return {string} globalId
*/
getGlobalIdByExpressId(expressId) {
if (Object.prototype.hasOwnProperty.call(this.eltsByExpressId, expressId)) {
const set = this.eltsByExpressId[expressId]
const element = (set.values().next().value)
if (Object.prototype.hasOwnProperty.call(element, 'GlobalId')) {
return element['GlobalId'].value
}
}
}

/**
*
*
* @param {string} globalId.
* @return {string} expressId
*/
getExpressIdByGlobalId(globalId) {
if (Object.prototype.hasOwnProperty.call(this.eltsByGlobalId, globalId)) {
const set = this.eltsByGlobalId[globalId]
const element = (set.values().next().value)
if (Object.prototype.hasOwnProperty.call(element, 'expressID')) {
return element['expressID'].toString()
}
}
}
}
7 changes: 6 additions & 1 deletion src/Share.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {useEffect, useRef, useState} from 'react'
import React, {useEffect, useMemo, useRef, useState} from 'react'
import CssBaseline from '@mui/material/CssBaseline'
import {useNavigate, useParams} from 'react-router-dom'
import {ThemeProvider} from '@mui/material/styles'
Expand All @@ -12,6 +12,8 @@ import './index.css'
// If icons-material isn't imported somewhere, mui dies
/* eslint-disable */
import AccountCircle from '@mui/icons-material/AccountCircle'
import WidgetApi from "./WidgetApi/WidgetApi";
import {searchIndex} from './Containers/CadView';
/* eslint-enable */


Expand All @@ -29,6 +31,9 @@ export default function Share({installPrefix, appPrefix, pathPrefix}) {
const [modelPath, setModelPath] = useState(null)
const setRepository = useStore((state) => state.setRepository)

useMemo(() => {
new WidgetApi(navigation.current, searchIndex)
}, [navigation])

/**
* On a change to urlParams, setting a new model path will clear the
Expand Down
75 changes: 75 additions & 0 deletions src/WidgetApi/ApiConnection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* Abstract ApiConnection
*/
class AbstractApiConnection {
/**
* event resolver.
*
* @param {string} eventName
* @param {Function} callable
*/
on(eventName, callable) {
// do something on event.
}

/**
* starts the api.
*/
start() {
console.warn('start() is not implemented')
}

/**
* stops the api.
*/
stop() {
console.warn('stop() is not implemented')
}

/**
* send event.
*
* @param {string} eventName
* @param {object} data
*/
send(eventName, data) {
console.warn('send() is not implemented')
}

/**
* requests capabilities.
*
* @param {string[]} capabilities
*/
requestCapabilities(capabilities) {
console.warn('requestCapabilities() is not implemented')
}

/**
* returns a missing argument response.
*
* @param {string} argumentName
* @return {object} missing argument response.
*/
missingArgumentResponse = function(argumentName) {
return {
error: true,
reason: `Missing argument ${argumentName}`,
}
}

/**
* returns a successful response.
*
* @param {object} data
* @return {object} successful response.
*/
successfulResponse = function(data) {
return {
error: false,
...data,
}
}
}

export default AbstractApiConnection
73 changes: 73 additions & 0 deletions src/WidgetApi/ApiConnectionIframe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import {WidgetApi as MatrixWidgetApi} from 'matrix-widget-api/lib/WidgetApi'
import AbstractApiConnection from './ApiConnection'


/**
* ApiConnection to Iframed bldrs instance
*/
class ApiConnectionIframe extends AbstractApiConnection {
widgetId = 'bldrs-share'
matrixWidgetApi = null

/**
* constructor
*/
constructor() {
super()
this.matrixWidgetApi = new MatrixWidgetApi(this.widgetId)
this.matrixWidgetApi.requestCapabilities([])
}

/**
* event resolver.
*
* @param {string} eventName
* @param {Function} callable
*/
on(eventName, callable) {
this.matrixWidgetApi.on(
eventName,
(event) => {
event.preventDefault()
const response = callable(event.detail.data)
this.matrixWidgetApi.transport.reply(event.detail, response)
},
)
}

/**
* send event.
*
* @param {string} eventName
* @param {object} data
*/
send(eventName, data) {
this.matrixWidgetApi.transport.send(eventName, data)
}

/**
* requests capabilities.
*
* @param {string[]} capabilities
*/
requestCapabilities(capabilities) {
this.matrixWidgetApi.requestCapabilities(capabilities)
}

/**
* starts the api.
*/
start() {
this.matrixWidgetApi.start()
this.matrixWidgetApi.sendContentLoaded()
}

/**
* stops the api.
*/
stop() {
this.matrixWidgetApi.stop()
}
}

export default ApiConnectionIframe