diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 0c29a1198..1be1b4829 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -4,7 +4,6 @@ about: Help improve Speckle! title: '' labels: bug assignees: '' - --- **What package are you referring to?** @@ -15,6 +14,7 @@ A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: + 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' @@ -27,18 +27,20 @@ A clear and concise description of what you expected to happen. If applicable, add screenshots to help explain your problem. **System Info** -If applicable, please fill in the below details - they help a lot! +If applicable, please fill in the below details - they help a lot! **Desktop (please complete the following information):** - - OS: [e.g. iOS] - - Browser [e.g. chrome, safari] - - Version [e.g. 22] + +- OS: [e.g. iOS] +- Browser [e.g. chrome, safari] +- Version [e.g. 22] **Smartphone (please complete the following information):** - - Device: [e.g. iPhone6] - - OS: [e.g. iOS8.1] - - Browser [e.g. stock browser, safari] - - Version [e.g. 22] + +- Device: [e.g. iPhone6] +- OS: [e.g. iOS8.1] +- Browser [e.g. stock browser, safari] +- Version [e.g. 22] **Additional context** Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 31aed1557..d23811f2c 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -4,7 +4,6 @@ about: Suggest an idea for Speckle! title: '' labels: enhancement, question assignees: '' - --- **What package are you referring to?** diff --git a/.github/workflows/close-issue.yml b/.github/workflows/close-issue.yml index 094d6dff2..21a1d7a96 100644 --- a/.github/workflows/close-issue.yml +++ b/.github/workflows/close-issue.yml @@ -32,10 +32,10 @@ jobs: echo 'PROJECT_ID='$(jq '.data.organization.projectNext.id' project_data.json) >> $GITHUB_ENV echo 'STATUS_FIELD_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") | .id' project_data.json) >> $GITHUB_ENV - + echo "$PROJECT_ID" echo "$STATUS_FIELD_ID" - + echo 'DONE_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") | .settings | fromjson | .options[] | select(.name== "Done") | .id' project_data.json) >> $GITHUB_ENV echo "$DONE_ID" @@ -52,9 +52,9 @@ jobs: } } }' -f project=$PROJECT_ID -f id=$ISSUE_ID --jq '.data.addProjectNextItem.projectNextItem.id')" - + echo 'ITEM_ID='$item_id >> $GITHUB_ENV - + - name: Update Status env: GITHUB_TOKEN: ${{secrets.GHPROJECT_TOKEN}} @@ -75,4 +75,3 @@ jobs: } } }' -f project=$PROJECT_ID -f status=$STATUS_FIELD_ID -f id=$ITEM_ID -f value=${{ env.DONE_ID }} - diff --git a/.github/workflows/open-issue.yml b/.github/workflows/open-issue.yml index 831d2b0e5..0c0943c66 100644 --- a/.github/workflows/open-issue.yml +++ b/.github/workflows/open-issue.yml @@ -32,7 +32,7 @@ jobs: echo 'PROJECT_ID='$(jq '.data.organization.projectNext.id' project_data.json) >> $GITHUB_ENV echo 'STATUS_FIELD_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") | .id' project_data.json) >> $GITHUB_ENV - + - name: Add Issue to project env: GITHUB_TOKEN: ${{secrets.GHPROJECT_TOKEN}} @@ -46,5 +46,5 @@ jobs: } } }' -f project=$PROJECT_ID -f id=$ISSUE_ID --jq '.data.addProjectNextItem.projectNextItem.id')" - + echo 'ITEM_ID='$item_id >> $GITHUB_ENV diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..75cdb6183 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,11 @@ +node_modules +build +dist +coverage +.nyc_output +packages/server/reports* +package-lock.json +yarn.lock + +# Prettier doesn't understand the syntax inside the Yaml files, because of the brackets +utils/helm/speckle-server/templates \ No newline at end of file diff --git a/.prettierrc b/.prettierrc index 51f05c399..1a1ea1a0e 100644 --- a/.prettierrc +++ b/.prettierrc @@ -4,10 +4,8 @@ "semi": false, "endOfLine": "auto", "bracketSpacing": true, - "eslintIntegration": true, - "jsxBracketSameLine": true, "vueIndentScriptAndStyle": false, "htmlWhitespaceSensitivity": "ignore", - "printWidth": 100, + "printWidth": 88, "singleQuote": true } diff --git a/SECURITY.md b/SECURITY.md index eef98c031..6485c32c8 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -9,4 +9,4 @@ ## Reporting a Vulnerability -Hi! If you've found something off, we'd be more than happy if you would report it via security@speckle.systems. We will work together with you to correctly identify the cause and implement a fix. Thanks for helping make Speckle safer! +Hi! If you've found something off, we'd be more than happy if you would report it via security@speckle.systems. We will work together with you to correctly identify the cause and implement a fix. Thanks for helping make Speckle safer! diff --git a/docker-compose-speckle.yml b/docker-compose-speckle.yml index cc3268352..757559624 100644 --- a/docker-compose-speckle.yml +++ b/docker-compose-speckle.yml @@ -1,6 +1,5 @@ -version: "2" +version: '2' services: - speckle-frontend: build: context: . @@ -8,7 +7,7 @@ services: image: speckle/speckle-frontend:local restart: always ports: - - "0.0.0.0:80:80" + - '0.0.0.0:80:80' speckle-server: build: @@ -18,26 +17,26 @@ services: restart: always environment: # TODO: Change this to the URL of the speckle server, as accessed from the network - CANONICAL_URL: "http://localhost" + CANONICAL_URL: 'http://localhost' # TODO: Change this to a unique secret for this server - SESSION_SECRET: "TODO:Replace" + SESSION_SECRET: 'TODO:Replace' - STRATEGY_LOCAL: "true" - DEBUG: "speckle:*" + STRATEGY_LOCAL: 'true' + DEBUG: 'speckle:*' - POSTGRES_URL: "postgres" - POSTGRES_USER: "speckle" - POSTGRES_PASSWORD: "speckle" - POSTGRES_DB: "speckle" + POSTGRES_URL: 'postgres' + POSTGRES_USER: 'speckle' + POSTGRES_PASSWORD: 'speckle' + POSTGRES_DB: 'speckle' - REDIS_URL: "redis://redis" + REDIS_URL: 'redis://redis' - S3_ENDPOINT: "http://minio:9000" - S3_ACCESS_KEY: "minioadmin" - S3_SECRET_KEY: "minioadmin" - S3_BUCKET: "speckle-server" - S3_CREATE_BUCKET: "true" + S3_ENDPOINT: 'http://minio:9000' + S3_ACCESS_KEY: 'minioadmin' + S3_SECRET_KEY: 'minioadmin' + S3_BUCKET: 'speckle-server' + S3_CREATE_BUCKET: 'true' preview-service: build: @@ -45,11 +44,11 @@ services: dockerfile: packages/preview-service/Dockerfile image: speckle/speckle-preview-service:local restart: always - mem_limit: "3000m" - memswap_limit: "3000m" + mem_limit: '3000m' + memswap_limit: '3000m' environment: - DEBUG: "preview-service:*" - PG_CONNECTION_STRING: "postgres://speckle:speckle@postgres/speckle" + DEBUG: 'preview-service:*' + PG_CONNECTION_STRING: 'postgres://speckle:speckle@postgres/speckle' webhook-service: build: @@ -58,8 +57,8 @@ services: image: speckle/speckle-webhook-service:local restart: always environment: - DEBUG: "webhook-service:*" - PG_CONNECTION_STRING: "postgres://speckle:speckle@postgres/speckle" + DEBUG: 'webhook-service:*' + PG_CONNECTION_STRING: 'postgres://speckle:speckle@postgres/speckle' fileimport-service: build: @@ -68,12 +67,12 @@ services: image: speckle/speckle-fileimport-service:local restart: always environment: - DEBUG: "fileimport-service:*" - PG_CONNECTION_STRING: "postgres://speckle:speckle@postgres/speckle" + DEBUG: 'fileimport-service:*' + PG_CONNECTION_STRING: 'postgres://speckle:speckle@postgres/speckle' - S3_ENDPOINT: "http://minio:9000" - S3_ACCESS_KEY: "minioadmin" - S3_SECRET_KEY: "minioadmin" - S3_BUCKET: "speckle-server" + S3_ENDPOINT: 'http://minio:9000' + S3_ACCESS_KEY: 'minioadmin' + S3_SECRET_KEY: 'minioadmin' + S3_BUCKET: 'speckle-server' - SPECKLE_SERVER_URL: "http://speckle-server:3000" + SPECKLE_SERVER_URL: 'http://speckle-server:3000' diff --git a/lerna.json b/lerna.json index a2bb50ba7..7926728a6 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,4 @@ { - "packages": [ - "packages/*" - ], + "packages": ["packages/*"], "version": "independent" } diff --git a/package.json b/package.json index f08944d83..5f2d4f49c 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,8 @@ "private": true, "scripts": { "lint": "eslint . --ext .js,.ts,.vue", + "prettier:check": "prettier --check .", + "prettier:fix": "prettier --write .", "docker:deps:up": "docker-compose -f ./docker-compose-deps.yml up -d", "docker:deps:down": "docker-compose -f ./docker-compose-deps.yml down", "dev": "lerna run dev --parallel", diff --git a/packages/fileimport-service/ifc/api.js b/packages/fileimport-service/ifc/api.js index bb9c430b4..ab2cf5a1e 100644 --- a/packages/fileimport-service/ifc/api.js +++ b/packages/fileimport-service/ifc/api.js @@ -1,49 +1,52 @@ 'use strict' -const crypto = require( 'crypto' ) -const crs = require( 'crypto-random-string' ) -const bcrypt = require( 'bcrypt' ) +const crypto = require('crypto') +const crs = require('crypto-random-string') +const bcrypt = require('bcrypt') -const knex = require( '../knex' ) -const Streams = ( ) => knex( 'streams' ) -const Branches = ( ) => knex( 'branches' ) -const Objects = ( ) => knex( 'objects' ) -const Closures = ( ) => knex( 'object_children_closure' ) -const ApiTokens = ( ) => knex( 'api_tokens' ) -const TokenScopes = ( ) => knex( 'token_scopes' ) +const knex = require('../knex') +const Streams = () => knex('streams') +const Branches = () => knex('branches') +const Objects = () => knex('objects') +const Closures = () => knex('object_children_closure') +const ApiTokens = () => knex('api_tokens') +const TokenScopes = () => knex('token_scopes') module.exports = class ServerAPI { - - constructor( { streamId } ) { + constructor({ streamId }) { this.streamId = streamId this.isSending = false this.buffer = [] } - async saveObject( obj ) { - if( !obj ) throw new Error( 'Null object' ) - - if( !obj.id ) { - obj.id = crypto.createHash( 'md5' ).update( JSON.stringify( obj ) ).digest( 'hex' ) + async saveObject(obj) { + if (!obj) throw new Error('Null object') + + if (!obj.id) { + obj.id = crypto.createHash('md5').update(JSON.stringify(obj)).digest('hex') } - - await this.createObject( this.streamId, obj ) + + await this.createObject(this.streamId, obj) return obj.id - } + } - async createObject( streamId, object ) { - let insertionObject = this.prepInsertionObject( streamId, object ) + async createObject(streamId, object) { + let insertionObject = this.prepInsertionObject(streamId, object) - let closures = [ ] + let closures = [] let totalChildrenCountByDepth = {} - if ( object.__closure !== null ) { - for ( const prop in object.__closure ) { - closures.push( { streamId: streamId, parent: insertionObject.id, child: prop, minDepth: object.__closure[ prop ] } ) + if (object.__closure !== null) { + for (const prop in object.__closure) { + closures.push({ + streamId: streamId, + parent: insertionObject.id, + child: prop, + minDepth: object.__closure[prop] + }) - if ( totalChildrenCountByDepth[ object.__closure[ prop ].toString( ) ] ) - totalChildrenCountByDepth[ object.__closure[ prop ].toString( ) ]++ - else - totalChildrenCountByDepth[ object.__closure[ prop ].toString( ) ] = 1 + if (totalChildrenCountByDepth[object.__closure[prop].toString()]) + totalChildrenCountByDepth[object.__closure[prop].toString()]++ + else totalChildrenCountByDepth[object.__closure[prop].toString()] = 1 } } @@ -51,30 +54,34 @@ module.exports = class ServerAPI { delete insertionObject.__closure insertionObject.totalChildrenCount = closures.length - insertionObject.totalChildrenCountByDepth = JSON.stringify( totalChildrenCountByDepth ) + insertionObject.totalChildrenCountByDepth = JSON.stringify( + totalChildrenCountByDepth + ) - let q1 = Objects( ).insert( insertionObject ).toString( ) + ' on conflict do nothing' - await knex.raw( q1 ) + let q1 = Objects().insert(insertionObject).toString() + ' on conflict do nothing' + await knex.raw(q1) - if ( closures.length > 0 ) { - let q2 = `${ Closures().insert( closures ).toString() } on conflict do nothing` - await knex.raw( q2 ) + if (closures.length > 0) { + let q2 = `${Closures().insert(closures).toString()} on conflict do nothing` + await knex.raw(q2) } return insertionObject.id } - prepInsertionObject( streamId, obj ) { + prepInsertionObject(streamId, obj) { const MAX_OBJECT_SIZE = 10 * 1024 * 1024 - if ( obj.hash ) - obj.id = obj.hash + if (obj.hash) obj.id = obj.hash else - obj.id = obj.id || crypto.createHash( 'md5' ).update( JSON.stringify( obj ) ).digest( 'hex' ) // generate a hash if none is present + obj.id = + obj.id || crypto.createHash('md5').update(JSON.stringify(obj)).digest('hex') // generate a hash if none is present - let stringifiedObj = JSON.stringify( obj ) - if ( stringifiedObj.length > MAX_OBJECT_SIZE ) { - throw new Error( `Object too large (${stringifiedObj.length} > ${MAX_OBJECT_SIZE})` ) + let stringifiedObj = JSON.stringify(obj) + if (stringifiedObj.length > MAX_OBJECT_SIZE) { + throw new Error( + `Object too large (${stringifiedObj.length} > ${MAX_OBJECT_SIZE})` + ) } return { @@ -85,41 +92,44 @@ module.exports = class ServerAPI { } } - - async getBranchByNameAndStreamId( { streamId, name } ) { - let query = Branches( ).select( '*' ).where( { streamId: streamId } ).andWhere( knex.raw( 'LOWER(name) = ?', [ name ] ) ).first( ) + async getBranchByNameAndStreamId({ streamId, name }) { + let query = Branches() + .select('*') + .where({ streamId: streamId }) + .andWhere(knex.raw('LOWER(name) = ?', [name])) + .first() return await query } - async createBranch( { name, description, streamId, authorId } ) { - let branch = {} - branch.id = crs( { length: 10 } ) - branch.streamId = streamId - branch.authorId = authorId - branch.name = name.toLowerCase( ) - branch.description = description + async createBranch({ name, description, streamId, authorId }) { + let branch = {} + branch.id = crs({ length: 10 }) + branch.streamId = streamId + branch.authorId = authorId + branch.name = name.toLowerCase() + branch.description = description - await Branches( ).returning( 'id' ).insert( branch ) + await Branches().returning('id').insert(branch) - // update stream updated at - await Streams().where( { id: streamId } ).update( { updatedAt: knex.fn.now() } ) + // update stream updated at + await Streams().where({ id: streamId }).update({ updatedAt: knex.fn.now() }) - return branch.id + return branch.id } - async createBareToken( ) { - let tokenId = crs( { length: 10 } ) - let tokenString = crs( { length: 32 } ) - let tokenHash = await bcrypt.hash( tokenString, 10 ) - let lastChars = tokenString.slice( tokenString.length - 6, tokenString.length ) + async createBareToken() { + let tokenId = crs({ length: 10 }) + let tokenString = crs({ length: 32 }) + let tokenHash = await bcrypt.hash(tokenString, 10) + let lastChars = tokenString.slice(tokenString.length - 6, tokenString.length) return { tokenId, tokenString, tokenHash, lastChars } } - async createToken( { userId, name, scopes, lifespan } ) { - let { tokenId, tokenString, tokenHash, lastChars } = await this.createBareToken( ) + async createToken({ userId, name, scopes, lifespan }) { + let { tokenId, tokenString, tokenHash, lastChars } = await this.createBareToken() - if ( scopes.length === 0 ) throw new Error( 'No scopes provided' ) + if (scopes.length === 0) throw new Error('No scopes provided') let token = { id: tokenId, @@ -129,21 +139,20 @@ module.exports = class ServerAPI { name: name, lifespan: lifespan } - let tokenScopes = scopes.map( scope => ( { tokenId: tokenId, scopeName: scope } ) ) + let tokenScopes = scopes.map((scope) => ({ tokenId: tokenId, scopeName: scope })) - await ApiTokens( ).insert( token ) - await TokenScopes( ).insert( tokenScopes ) + await ApiTokens().insert(token) + await TokenScopes().insert(tokenScopes) return { id: tokenId, token: tokenId + tokenString } } - async revokeTokenById( tokenId ) { - let delCount = await ApiTokens( ).where( { id: tokenId.slice( 0, 10 ) } ).del( ) + async revokeTokenById(tokenId) { + let delCount = await ApiTokens() + .where({ id: tokenId.slice(0, 10) }) + .del() - if ( delCount === 0 ) - throw new Error( 'Token revokation failed' ) + if (delCount === 0) throw new Error('Token revokation failed') return true } - - -} \ No newline at end of file +} diff --git a/packages/fileimport-service/ifc/import_file.js b/packages/fileimport-service/ifc/import_file.js index c789de66f..2c923d715 100644 --- a/packages/fileimport-service/ifc/import_file.js +++ b/packages/fileimport-service/ifc/import_file.js @@ -1,47 +1,47 @@ -const fs = require( 'fs' ) +const fs = require('fs') const TMP_RESULTS_PATH = '/tmp/import_result.json' -const { parseAndCreateCommit } = require( './index' ) +const { parseAndCreateCommit } = require('./index') async function main() { - let cmdArgs = process.argv.slice( 2 ) + let cmdArgs = process.argv.slice(2) - let [ filePath, userId, streamId, branchName, commitMessage ] = cmdArgs + let [filePath, userId, streamId, branchName, commitMessage] = cmdArgs - console.log( 'ARGV: ', filePath, userId, streamId, branchName, commitMessage ) + console.log('ARGV: ', filePath, userId, streamId, branchName, commitMessage) - const data = fs.readFileSync( filePath ) + const data = fs.readFileSync(filePath) - let ifcInput = { - data, - streamId: streamId, - userId: userId, - message: commitMessage || 'Imported file' + let ifcInput = { + data, + streamId: streamId, + userId: userId, + message: commitMessage || 'Imported file' + } + if (branchName) ifcInput.branchName = branchName + + let output = { + success: false, + error: 'Unknown error' + } + + try { + let commitId = await parseAndCreateCommit(ifcInput) + output = { + success: true, + commitId } - if ( branchName ) ifcInput.branchName = branchName - - let output = { - success: false, - error: 'Unknown error' + } catch (err) { + output = { + success: false, + error: err.toString() } + } - try { - let commitId = await parseAndCreateCommit( ifcInput ) - output = { - success: true, - commitId - } - } catch ( err ) { - output = { - success: false, - error: err.toString() - } - } - - fs.writeFileSync( TMP_RESULTS_PATH, JSON.stringify( output ) ) - - process.exit( 0 ) + fs.writeFileSync(TMP_RESULTS_PATH, JSON.stringify(output)) + + process.exit(0) } main() diff --git a/packages/fileimport-service/ifc/index.js b/packages/fileimport-service/ifc/index.js index 07a158a2a..16dcb0851 100644 --- a/packages/fileimport-service/ifc/index.js +++ b/packages/fileimport-service/ifc/index.js @@ -23,7 +23,10 @@ async function parseAndCreateCommit({ totalChildrenCount: tCount } - let branch = await serverApi.getBranchByNameAndStreamId({ streamId: streamId, name: branchName }) + let branch = await serverApi.getBranchByNameAndStreamId({ + streamId: streamId, + name: branchName + }) if (!branch) { await serverApi.createBranch({ diff --git a/packages/fileimport-service/ifc/parser.js b/packages/fileimport-service/ifc/parser.js index 55cb71974..6a4cd76c0 100644 --- a/packages/fileimport-service/ifc/parser.js +++ b/packages/fileimport-service/ifc/parser.js @@ -1,118 +1,146 @@ -const WebIFC = require( 'web-ifc/web-ifc-api-node' ) -const ServerAPI = require( './api.js' ) +const WebIFC = require('web-ifc/web-ifc-api-node') +const ServerAPI = require('./api.js') module.exports = class IFCParser { - - constructor( { serverApi } ) { + constructor({ serverApi }) { this.api = new WebIFC.IfcAPI() this.serverApi = serverApi || new ServerAPI() } - async parse( data ) { - if ( this.api.wasmModule === undefined ) await this.api.Init() + async parse(data) { + if (this.api.wasmModule === undefined) await this.api.Init() - this.modelId = this.api.OpenModel( data, { COORDINATE_TO_ORIGIN: true, USE_FAST_BOOLS: true } ) + this.modelId = this.api.OpenModel(data, { + COORDINATE_TO_ORIGIN: true, + USE_FAST_BOOLS: true + }) - this.projectId = this.api.GetLineIDsWithType( this.modelId, WebIFC.IFCPROJECT ).get( 0 ) + this.projectId = this.api.GetLineIDsWithType(this.modelId, WebIFC.IFCPROJECT).get(0) - this.project = this.api.GetLine( this.modelId, this.projectId, true ) + this.project = this.api.GetLine(this.modelId, this.projectId, true) this.project.__closure = {} - + this.cache = {} this.closureCache = {} - // Steps: create and store in speckle all the geometries (meshes) from this project and store them + // Steps: create and store in speckle all the geometries (meshes) from this project and store them // as reference objects in this.productGeo this.productGeo = {} - await this.createGeometries() - console.log( `Geometries created: ${Object.keys( this.productGeo ).length} meshes.` ) - - // Lastly, traverse the ifc project object and parse it into something friendly; as well as + await this.createGeometries() + console.log(`Geometries created: ${Object.keys(this.productGeo).length} meshes.`) + + // Lastly, traverse the ifc project object and parse it into something friendly; as well as // replace all its geometries with actual references to speckle meshes from the productGeo map - - await this.traverse( this.project, true, 0 ) - - let id = await this.serverApi.saveObject( this.project ) - return { id, tCount: Object.keys( this.project.__closure ).length } + + await this.traverse(this.project, true, 0) + + let id = await this.serverApi.saveObject(this.project) + return { id, tCount: Object.keys(this.project.__closure).length } } async createGeometries() { - this.rawGeo = this.api.LoadAllGeometry( this.modelId ) - - for( let i = 0; i < this.rawGeo.size(); i++ ) { - const mesh = this.rawGeo.get( i ) - const prodId = mesh.expressID - this.productGeo[prodId ] = [] - - for( let j = 0; j < mesh.geometries.size(); j++ ) { - let placedGeom = mesh.geometries.get( j ) - let geom = this.api.GetGeometry( this.modelId, placedGeom.geometryExpressID ) + this.rawGeo = this.api.LoadAllGeometry(this.modelId) - let matrix = placedGeom.flatTransformation + for (let i = 0; i < this.rawGeo.size(); i++) { + const mesh = this.rawGeo.get(i) + const prodId = mesh.expressID + this.productGeo[prodId] = [] + + for (let j = 0; j < mesh.geometries.size(); j++) { + let placedGeom = mesh.geometries.get(j) + let geom = this.api.GetGeometry(this.modelId, placedGeom.geometryExpressID) + + let matrix = placedGeom.flatTransformation let raw = { color: geom.color, // NOTE: material: x, y, z = rgb, w = opacity - vertices: this.api.GetVertexArray( geom.GetVertexData(), geom.GetVertexDataSize() ), - indices: this.api.GetIndexArray( geom.GetIndexData(), geom.GetIndexDataSize() ) + vertices: this.api.GetVertexArray( + geom.GetVertexData(), + geom.GetVertexDataSize() + ), + indices: this.api.GetIndexArray(geom.GetIndexData(), geom.GetIndexDataSize()) } - - const { vertices } = this.extractVertexData( raw.vertices ) - for( let k = 0; k < vertices.length; k += 3 ) { - let x = vertices[k], y = vertices[k + 1], z = vertices[k + 2] - vertices[k] = matrix[0] * x + matrix[4] * y + matrix[8] * z + matrix[12] - vertices[k + 1] = ( matrix[2] * x + matrix[6] * y + matrix[10] * z + matrix[14] ) * -1 + const { vertices } = this.extractVertexData(raw.vertices) + + for (let k = 0; k < vertices.length; k += 3) { + let x = vertices[k], + y = vertices[k + 1], + z = vertices[k + 2] + vertices[k] = matrix[0] * x + matrix[4] * y + matrix[8] * z + matrix[12] + vertices[k + 1] = + (matrix[2] * x + matrix[6] * y + matrix[10] * z + matrix[14]) * -1 vertices[k + 2] = matrix[1] * x + matrix[5] * y + matrix[9] * z + matrix[13] } // Since all faces are triangles, we must add a `0` before each group of 3. - let spcklFaces = [ ] - for ( let i = 0; i < raw.indices.length; i++ ) { - if( i % 3 === 0 ) - spcklFaces.push( 0 ) - spcklFaces.push( raw.indices[i] ) + let spcklFaces = [] + for (let i = 0; i < raw.indices.length; i++) { + if (i % 3 === 0) spcklFaces.push(0) + spcklFaces.push(raw.indices[i]) } // Create a propper Speckle Mesh - let spcklMesh = { + let spcklMesh = { speckle_type: 'Objects.Geometry.Mesh', units: 'm', volume: 0, area: 0, faces: spcklFaces, - vertices: Array.from( vertices ), - renderMaterial: placedGeom.color ? this.colorToMaterial( placedGeom.color ) : null + vertices: Array.from(vertices), + renderMaterial: placedGeom.color + ? this.colorToMaterial(placedGeom.color) + : null } - - let id = await this.serverApi.saveObject( spcklMesh ) + + let id = await this.serverApi.saveObject(spcklMesh) let ref = { speckle_type: 'reference', referencedId: id } - this.productGeo[prodId].push( ref ) + this.productGeo[prodId].push(ref) } } } - async traverse( element, recursive = true, depth = 0, specialTypes = [ { type: 'IfcProject', key: 'Name' }, { type: 'IfcBuilding', key: 'Name' }, { type: 'IfcSite', key: 'Name' } ] ) { - + async traverse( + element, + recursive = true, + depth = 0, + specialTypes = [ + { type: 'IfcProject', key: 'Name' }, + { type: 'IfcBuilding', key: 'Name' }, + { type: 'IfcSite', key: 'Name' } + ] + ) { // Fast exit if null/undefined - if ( !element ) return + if (!element) return - // If array, traverse all items in it. - if( Array.isArray( element ) ) { - return await Promise.all( element.map( async el => await this.traverse( el,recursive, depth + 1 , specialTypes ) ) ) + if (Array.isArray(element)) { + return await Promise.all( + element.map( + async (el) => await this.traverse(el, recursive, depth + 1, specialTypes) + ) + ) } - // If it has no expressID, its either a simple type or a { type, value } object. - if( !element.expressID ) { - return await Promise.resolve( element.value !== null && element.value !== undefined ? element.value : element ) + // If it has no expressID, its either a simple type or a { type, value } object. + if (!element.expressID) { + return await Promise.resolve( + element.value !== null && element.value !== undefined ? element.value : element + ) } - if( this.cache[element.expressID.toString()] ) return this.cache[element.expressID.toString()] + if (this.cache[element.expressID.toString()]) + return this.cache[element.expressID.toString()] // If you got here -> It's an IFC Element: create base object, upload and return ref. // console.log( `Traversing element ${element.expressID}; Recurse: ${recursive}; Stack ${depth}` ) // Traverse all key/value pairs first. - for( let key of Object.keys( element ) ) { - element[key] = await this.traverse( element[key], recursive, depth + 1, specialTypes ) + for (let key of Object.keys(element)) { + element[key] = await this.traverse( + element[key], + recursive, + depth + 1, + specialTypes + ) } // Assign speckle_type and empty closure table. @@ -120,50 +148,130 @@ module.exports = class IFCParser { element.__closure = {} // Find spatial children and assign to element - const spatialChildrenIds = this.getAllRelatedItemsOfType( element.expressID, WebIFC.IFCRELAGGREGATES, 'RelatingObject', 'RelatedObjects' ) - if( spatialChildrenIds.length > 0 ) element.rawSpatialChildren = spatialChildrenIds.map( ( childId ) => this.api.GetLine( this.modelId, childId, true ) ) + const spatialChildrenIds = this.getAllRelatedItemsOfType( + element.expressID, + WebIFC.IFCRELAGGREGATES, + 'RelatingObject', + 'RelatedObjects' + ) + if (spatialChildrenIds.length > 0) + element.rawSpatialChildren = spatialChildrenIds.map((childId) => + this.api.GetLine(this.modelId, childId, true) + ) // Find children and populate element - const childrenIds = this.getAllRelatedItemsOfType( element.expressID, WebIFC.IFCRELCONTAINEDINSPATIALSTRUCTURE, 'RelatingStructure', 'RelatedElements' ) - if( childrenIds.length > 0 ) element.rawChildren = childrenIds.map( ( childId ) => this.api.GetLine( this.modelId, childId, true ) ) - + const childrenIds = this.getAllRelatedItemsOfType( + element.expressID, + WebIFC.IFCRELCONTAINEDINSPATIALSTRUCTURE, + 'RelatingStructure', + 'RelatedElements' + ) + if (childrenIds.length > 0) + element.rawChildren = childrenIds.map((childId) => + this.api.GetLine(this.modelId, childId, true) + ) + // Find related property sets - const psetsIds = this.getAllRelatedItemsOfType( element.expressID, WebIFC.IFCRELDEFINESBYPROPERTIES, 'RelatingPropertyDefinition', 'RelatedObjects' ) - if( psetsIds.length > 0 ) element.rawPsets = psetsIds.map( ( childId ) => this.api.GetLine( this.modelId, childId, true ) ) + const psetsIds = this.getAllRelatedItemsOfType( + element.expressID, + WebIFC.IFCRELDEFINESBYPROPERTIES, + 'RelatingPropertyDefinition', + 'RelatedObjects' + ) + if (psetsIds.length > 0) + element.rawPsets = psetsIds.map((childId) => + this.api.GetLine(this.modelId, childId, true) + ) // Find related type properties - const typePropsId = this.getAllRelatedItemsOfType( element.expressID, WebIFC.IFCRELDEFINESBYTYPE, 'RelatingType', 'RelatedObjects' ) - if( typePropsId.length > 0 ) element.rawTypeProps = typePropsId.map( ( childId ) => this.api.GetLine( this.modelId, childId, true ) ) + const typePropsId = this.getAllRelatedItemsOfType( + element.expressID, + WebIFC.IFCRELDEFINESBYTYPE, + 'RelatingType', + 'RelatedObjects' + ) + if (typePropsId.length > 0) + element.rawTypeProps = typePropsId.map((childId) => + this.api.GetLine(this.modelId, childId, true) + ) // Lookup geometry in generated geometries object - if( this.productGeo[element.expressID] ) { + if (this.productGeo[element.expressID]) { element['@displayValue'] = this.productGeo[element.expressID] - this.productGeo[element.expressID].forEach( ref => { - this.project.__closure[ref.referencedId.toString()] = depth + this.productGeo[element.expressID].forEach((ref) => { + this.project.__closure[ref.referencedId.toString()] = depth element.__closure[ref.referencedId.toString()] = 1 - } ) + }) } - const isSpecial = specialTypes.find( t => t.type === element.speckle_type ) + const isSpecial = specialTypes.find((t) => t.type === element.speckle_type) // Recurse all children - if ( recursive ) { - await this.processSubElements( element, 'rawSpatialChildren', 'spatialChildren', isSpecial, recursive, depth, specialTypes ) - await this.processSubElements( element, 'rawChildren', 'children', isSpecial, recursive, depth, specialTypes ) - await this.processSubElements( element, 'rawPsets', 'propertySets', false, recursive, depth, specialTypes ) - await this.processSubElements( element, 'rawTypeProps', 'typeProps', false, recursive, depth, specialTypes ) + if (recursive) { + await this.processSubElements( + element, + 'rawSpatialChildren', + 'spatialChildren', + isSpecial, + recursive, + depth, + specialTypes + ) + await this.processSubElements( + element, + 'rawChildren', + 'children', + isSpecial, + recursive, + depth, + specialTypes + ) + await this.processSubElements( + element, + 'rawPsets', + 'propertySets', + false, + recursive, + depth, + specialTypes + ) + await this.processSubElements( + element, + 'rawTypeProps', + 'typeProps', + false, + recursive, + depth, + specialTypes + ) - if( element.children || element.spatialChildren || element.propertySets || element.typeProps ) { - console.log( `${element.constructor.name} ${element.GlobalId}:\n\tchildren count: ${ element.children ? element.children.length : '0'};\n\tspatial children count: ${element.spatialChildren ? element.spatialChildren.length : '0'};\n\tproperty sets count: ${element.propertySets ? element.propertySets.length : 0};\n\ttype properties: ${element.typeProps ? element.typeProps.length : 0}` ) + if ( + element.children || + element.spatialChildren || + element.propertySets || + element.typeProps + ) { + console.log( + `${element.constructor.name} ${element.GlobalId}:\n\tchildren count: ${ + element.children ? element.children.length : '0' + };\n\tspatial children count: ${ + element.spatialChildren ? element.spatialChildren.length : '0' + };\n\tproperty sets count: ${ + element.propertySets ? element.propertySets.length : 0 + };\n\ttype properties: ${element.typeProps ? element.typeProps.length : 0}` + ) } - } - if( this.productGeo[element.expressID] || element.spatialChildren || element.children ) { - let id = await this.serverApi.saveObject( element ) + if ( + this.productGeo[element.expressID] || + element.spatialChildren || + element.children + ) { + let id = await this.serverApi.saveObject(element) let ref = { speckle_type: 'reference', referencedId: id } this.cache[element.expressID.toString()] = ref this.closureCache[element.expressID.toString()] = element.__closure - return ref + return ref } else { this.cache[element.expressID.toString()] = element this.closureCache[element.expressID.toString()] = element.__closure @@ -171,34 +279,38 @@ module.exports = class IFCParser { } } - - async processSubElements( element, key, newKey, isSpecial, recursive, depth, specialTypes ) { - if ( element[key] ) { - if ( !isSpecial ) - element[newKey] = [] + async processSubElements( + element, + key, + newKey, + isSpecial, + recursive, + depth, + specialTypes + ) { + if (element[key]) { + if (!isSpecial) element[newKey] = [] let childCount = {} - for ( let child of element[key] ) { - let res = await this.traverse( child, recursive, depth + 1, specialTypes ) - if ( res.referencedId ) { - if ( isSpecial ) { + for (let child of element[key]) { + let res = await this.traverse(child, recursive, depth + 1, specialTypes) + if (res.referencedId) { + if (isSpecial) { let name = child[isSpecial.key] - if ( !name || name.length === 0 ) - name = 'Undefined' - if ( !childCount[name] ) - childCount[name] = 0 - if ( childCount[name] > 0 ) - name += '-' + childCount[name]++ + if (!name || name.length === 0) name = 'Undefined' + if (!childCount[name]) childCount[name] = 0 + if (childCount[name] > 0) name += '-' + childCount[name]++ element[name] = res - } - else - element[newKey].push( res ) + } else element[newKey].push(res) this.project.__closure[res.referencedId.toString()] = depth element.__closure[res.referencedId.toString()] = 1 // adds to parent (this element) the child's closure tree. - if ( this.closureCache[child.expressID.toString()] ) { - for ( let key of Object.keys( this.closureCache[child.expressID.toString()] ) ) { - element.__closure[key] = this.closureCache[child.expressID.toString()][key] + 1 + if (this.closureCache[child.expressID.toString()]) { + for (let key of Object.keys( + this.closureCache[child.expressID.toString()] + )) { + element.__closure[key] = + this.closureCache[child.expressID.toString()][key] + 1 } } } @@ -208,46 +320,47 @@ module.exports = class IFCParser { } // (c) https://github.com/agviegas/web-ifc-three - extractVertexData( vertexData ) { + extractVertexData(vertexData) { const vertices = [] const normals = [] let isNormalData = false - for ( let i = 0; i < vertexData.length; i++ ) { - isNormalData ? normals.push( vertexData[i] ) : vertices.push( vertexData[i] ) - if ( ( i + 1 ) % 3 === 0 ) isNormalData = !isNormalData + for (let i = 0; i < vertexData.length; i++) { + isNormalData ? normals.push(vertexData[i]) : vertices.push(vertexData[i]) + if ((i + 1) % 3 === 0) isNormalData = !isNormalData } return { vertices, normals } } // (c) https://github.com/agviegas/web-ifc-three/blob/907e08b5673d5e1c18261a4fceade7189d6b2db7/src/IFC/PropertyManager.ts#L110 - getAllRelatedItemsOfType( elementID, type, relation, relatedProperty ) { - const lines = this.api.GetLineIDsWithType( this.modelId, type ) + getAllRelatedItemsOfType(elementID, type, relation, relatedProperty) { + const lines = this.api.GetLineIDsWithType(this.modelId, type) const IDs = [] - for ( let i = 0; i < lines.size(); i++ ) { - const relID = lines.get( i ) - const rel = this.api.GetLine( this.modelId, relID ) + for (let i = 0; i < lines.size(); i++) { + const relID = lines.get(i) + const rel = this.api.GetLine(this.modelId, relID) const relatedItems = rel[relation] let foundElement = false - if ( Array.isArray( relatedItems ) ) { - const values = relatedItems.map( ( item ) => item.value ) - foundElement = values.includes( elementID ) - } else foundElement = ( relatedItems.value === elementID ) + if (Array.isArray(relatedItems)) { + const values = relatedItems.map((item) => item.value) + foundElement = values.includes(elementID) + } else foundElement = relatedItems.value === elementID - if ( foundElement ) { + if (foundElement) { const element = rel[relatedProperty] - if ( !Array.isArray( element ) ) IDs.push( element.value ) - else element.forEach( ( ele ) => IDs.push( ele.value ) ) + if (!Array.isArray(element)) IDs.push(element.value) + else element.forEach((ele) => IDs.push(ele.value)) } } return IDs } - - colorToMaterial( color ) { - let intColor = ( color.w << 24 ) + ( ( color.x * 255 ) << 16 ) + ( ( color.y * 255 ) << 8 ) + ( ( color.z * 255 ) ) - + + colorToMaterial(color) { + let intColor = + (color.w << 24) + ((color.x * 255) << 16) + ((color.y * 255) << 8) + color.z * 255 + return { diffuse: intColor, opacity: color.w, @@ -256,4 +369,4 @@ module.exports = class IFCParser { speckle_type: 'Objects.Other.RenderMaterial' } } -} \ No newline at end of file +} diff --git a/packages/fileimport-service/knex.js b/packages/fileimport-service/knex.js index ff2e57488..de716d950 100644 --- a/packages/fileimport-service/knex.js +++ b/packages/fileimport-service/knex.js @@ -1,8 +1,9 @@ 'use strict' -module.exports = require( 'knex' )( { +module.exports = require('knex')({ client: 'pg', - connection: process.env.PG_CONNECTION_STRING || 'postgres://speckle:speckle@localhost/speckle', + connection: + process.env.PG_CONNECTION_STRING || 'postgres://speckle:speckle@localhost/speckle', pool: { min: 1, max: 1 } // migrations are in managed in the server package -} ) +}) diff --git a/packages/fileimport-service/src/daemon.js b/packages/fileimport-service/src/daemon.js index b48e63cd4..4b5e471a6 100644 --- a/packages/fileimport-service/src/daemon.js +++ b/packages/fileimport-service/src/daemon.js @@ -1,12 +1,12 @@ 'use strict' -const knex = require( '../knex' ) +const knex = require('../knex') -const { getFileStream } = require( './filesApi' ) -const fs = require( 'fs' ) -const { spawn } = require( 'child_process' ) +const { getFileStream } = require('./filesApi') +const fs = require('fs') +const { spawn } = require('child_process') -const ServerAPI = require( '../ifc/api' ) +const ServerAPI = require('../ifc/api') const HEALTHCHECK_FILE_PATH = '/tmp/last_successful_query' @@ -16,7 +16,7 @@ const TMP_RESULTS_PATH = '/tmp/import_result.json' let shouldExit = false async function startTask() { - let { rows } = await knex.raw( ` + let { rows } = await knex.raw(` UPDATE file_uploads SET "convertedStatus" = 1, @@ -29,37 +29,45 @@ async function startTask() { ) as task WHERE file_uploads."id" = task."id" RETURNING file_uploads."id" - ` ) + `) return rows[0] } -async function doTask( task ) { +async function doTask(task) { let tempUserToken = null let serverApi = null try { - console.log( 'Doing task ', task ) - let { rows } = await knex.raw( ` + console.log('Doing task ', task) + let { rows } = await knex.raw( + ` SELECT id as "fileId", "streamId", "branchName", "userId", "fileName", "fileType" FROM file_uploads WHERE id = ? LIMIT 1 - `, [ task.id ] ) + `, + [task.id] + ) let info = rows[0] - if ( !info ) { - throw new Error( 'Internal error: DB inconsistent' ) + if (!info) { + throw new Error('Internal error: DB inconsistent') } - let upstreamFileStream = await getFileStream( { fileId: info.fileId } ) - let diskFileStream = fs.createWriteStream( TMP_FILE_PATH ) - - upstreamFileStream.pipe( diskFileStream ) + let upstreamFileStream = await getFileStream({ fileId: info.fileId }) + let diskFileStream = fs.createWriteStream(TMP_FILE_PATH) - await new Promise( fulfill => diskFileStream.on( 'finish' , fulfill ) ) - - serverApi = new ServerAPI( { streamId: info.streamId } ) - let { token } = await serverApi.createToken( { userId: info.userId, name: 'temp upload token', scopes: [ 'streams:write', 'streams:read' ], lifespan: 1000000 } ) + upstreamFileStream.pipe(diskFileStream) + + await new Promise((fulfill) => diskFileStream.on('finish', fulfill)) + + serverApi = new ServerAPI({ streamId: info.streamId }) + let { token } = await serverApi.createToken({ + userId: info.userId, + name: 'temp upload token', + scopes: ['streams:write', 'streams:read'], + lifespan: 1000000 + }) tempUserToken = token await runProcessWithTimeout( @@ -78,14 +86,14 @@ async function doTask( task ) { 10 * 60 * 1000 ) - let output = JSON.parse( fs.readFileSync( TMP_RESULTS_PATH ) ) + let output = JSON.parse(fs.readFileSync(TMP_RESULTS_PATH)) - if ( !output.success ) - throw new Error( output.error ) + if (!output.success) throw new Error(output.error) let commitId = output.commitId - await knex.raw( ` + await knex.raw( + ` UPDATE file_uploads SET "convertedStatus" = 2, @@ -93,103 +101,103 @@ async function doTask( task ) { "convertedMessage" = 'File converted successfully', "convertedCommitId" = ? WHERE "id" = ? - `, [ commitId, task.id ] ) - } catch ( err ) { - console.log( 'Error: ', err ) - await knex.raw( ` + `, + [commitId, task.id] + ) + } catch (err) { + console.log('Error: ', err) + await knex.raw( + ` UPDATE file_uploads SET "convertedStatus" = 3, "convertedLastUpdate" = NOW(), "convertedMessage" = ? WHERE "id" = ? - `, [ err.toString(), task.id ] ) + `, + [err.toString(), task.id] + ) } - if ( fs.existsSync( TMP_FILE_PATH ) ) fs.unlinkSync( TMP_FILE_PATH ) - if ( fs.existsSync( TMP_RESULTS_PATH ) ) fs.unlinkSync( TMP_RESULTS_PATH ) + if (fs.existsSync(TMP_FILE_PATH)) fs.unlinkSync(TMP_FILE_PATH) + if (fs.existsSync(TMP_RESULTS_PATH)) fs.unlinkSync(TMP_RESULTS_PATH) - if ( tempUserToken ) { - await serverApi.revokeTokenById( tempUserToken ) + if (tempUserToken) { + await serverApi.revokeTokenById(tempUserToken) } - } -function runProcessWithTimeout( cmd, cmdArgs, extraEnv, timeoutMs ) { - - return new Promise( ( resolve, reject ) => { - console.log( `Starting process: ${cmd} ${cmdArgs}` ) - const childProc = spawn( cmd, cmdArgs, { env: { ...process.env, ...extraEnv } } ) +function runProcessWithTimeout(cmd, cmdArgs, extraEnv, timeoutMs) { + return new Promise((resolve, reject) => { + console.log(`Starting process: ${cmd} ${cmdArgs}`) + const childProc = spawn(cmd, cmdArgs, { env: { ...process.env, ...extraEnv } }) - childProc.stdout.on( 'data', ( data ) => { - console.log( 'Parser: ', data.toString() ) - } ) + childProc.stdout.on('data', (data) => { + console.log('Parser: ', data.toString()) + }) - childProc.stderr.on( 'data', ( data ) => { - console.error( 'Parser: ', data.toString() ) - } ) + childProc.stderr.on('data', (data) => { + console.error('Parser: ', data.toString()) + }) let timedOut = false - let timeout = setTimeout( () => { - console.log( 'Process timeout. Killing process...' ) + let timeout = setTimeout(() => { + console.log('Process timeout. Killing process...') timedOut = true - childProc.kill( 9 ) - reject( `Timeout: Process took longer than ${timeoutMs} ms to execute` ) - }, timeoutMs ) + childProc.kill(9) + reject(`Timeout: Process took longer than ${timeoutMs} ms to execute`) + }, timeoutMs) - childProc.on( 'close', ( code ) => { - console.log( `Process exited with code ${code}` ) + childProc.on('close', (code) => { + console.log(`Process exited with code ${code}`) - if ( timedOut ) return // ignore `close` calls after killing (the promise was already rejected) + if (timedOut) return // ignore `close` calls after killing (the promise was already rejected) - clearTimeout( timeout ) + clearTimeout(timeout) - if ( code === 0 ) { + if (code === 0) { resolve() } else { - reject( `Parser exited with code ${code}` ) + reject(`Parser exited with code ${code}`) } - } ) - - } ) - + }) + }) } async function tick() { - if ( shouldExit ) { - process.exit( 0 ) + if (shouldExit) { + process.exit(0) } try { let task = await startTask() - fs.writeFile( HEALTHCHECK_FILE_PATH, '' + Date.now(), () => {} ) + fs.writeFile(HEALTHCHECK_FILE_PATH, '' + Date.now(), () => {}) - if ( !task ) { - setTimeout( tick, 1000 ) + if (!task) { + setTimeout(tick, 1000) return } - await doTask( task ) + await doTask(task) // Check for another task very soon - setTimeout( tick, 10 ) - } catch ( err ) { - console.log( 'Error executing task: ', err ) - setTimeout( tick, 5000 ) + setTimeout(tick, 10) + } catch (err) { + console.log('Error executing task: ', err) + setTimeout(tick, 5000) } } - async function main() { - console.log( 'Starting FileUploads Service...' ) - - process.on( 'SIGTERM', () => { + console.log('Starting FileUploads Service...') + + process.on('SIGTERM', () => { shouldExit = true - console.log( 'Shutting down...' ) - } ) + console.log('Shutting down...') + }) tick() } diff --git a/packages/frontend/.eslintrc.js b/packages/frontend/.eslintrc.js index f2cecff32..b220ffd5d 100644 --- a/packages/frontend/.eslintrc.js +++ b/packages/frontend/.eslintrc.js @@ -18,6 +18,15 @@ const config = { parserOptions: { sourceType: 'module' }, + overrides: [ + { + files: './*.{js, ts}', + env: { + node: true, + commonjs: true + } + } + ], plugins: ['vue'], rules: { 'no-console': 1 diff --git a/packages/frontend/.vscode/launch.json b/packages/frontend/.vscode/launch.json index 511204d3b..ed8b45d76 100644 --- a/packages/frontend/.vscode/launch.json +++ b/packages/frontend/.vscode/launch.json @@ -36,4 +36,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/packages/frontend/README.md b/packages/frontend/README.md index dd92b19d2..eb75bddd3 100644 --- a/packages/frontend/README.md +++ b/packages/frontend/README.md @@ -37,6 +37,7 @@ npm run serve ``` ### Packaging for production + If you plan to package the frontend to use in a production setting, see our [Server deployment instructions](https://speckle.guide/dev/server-setup.html) (chapter `Run your speckle-server fork`) ## Community diff --git a/packages/frontend/apollo.config.js b/packages/frontend/apollo.config.js index 473a2c111..08cdb76b5 100644 --- a/packages/frontend/apollo.config.js +++ b/packages/frontend/apollo.config.js @@ -2,7 +2,10 @@ const path = require('path') // Load .env files const { loadEnv } = require('vue-cli-plugin-apollo/utils/load-env') -const env = loadEnv([path.resolve(__dirname, '.env'), path.resolve(__dirname, '.env.local')]) +const env = loadEnv([ + path.resolve(__dirname, '.env'), + path.resolve(__dirname, '.env.local') +]) module.exports = { client: { diff --git a/packages/frontend/babel.config.js b/packages/frontend/babel.config.js index a00288472..1f4ca007e 100644 --- a/packages/frontend/babel.config.js +++ b/packages/frontend/babel.config.js @@ -1,6 +1,4 @@ module.exports = { presets: ['@vue/cli-plugin-babel/preset'], - exclude: [ - /(Speckle.js\.). / - ] + exclude: [/(Speckle.js\.). /] } diff --git a/packages/frontend/public/app.html b/packages/frontend/public/app.html index 4592d94d1..fa09b2312 100644 --- a/packages/frontend/public/app.html +++ b/packages/frontend/public/app.html @@ -2,32 +2,41 @@ - - - - - - - - - + + + + + + + + + <%= htmlWebpackPlugin.options.title %> - - - - + + + + + - 100% { - -webkit-transform: scale3d(1, 1, 1); - transform: scale3d(1, 1, 1); - } - } - - - - - -
-
- + + +
+
+ +
- - - \ No newline at end of file + + diff --git a/packages/frontend/src/embed/EmbedApp.vue b/packages/frontend/src/embed/EmbedApp.vue index 36f371624..514f50bd6 100644 --- a/packages/frontend/src/embed/EmbedApp.vue +++ b/packages/frontend/src/embed/EmbedApp.vue @@ -6,7 +6,10 @@ export default { components: {}, mounted() { let mixpanelId = this.$mixpanelId() - this.$mixpanel.register({ server_id: this.$mixpanelServerId(), hostApp: 'web-embed' }) + this.$mixpanel.register({ + server_id: this.$mixpanelServerId(), + hostApp: 'web-embed' + }) if (mixpanelId !== null) { this.$mixpanel.identify(mixpanelId) } diff --git a/packages/frontend/src/embed/EmbedViewer.vue b/packages/frontend/src/embed/EmbedViewer.vue index 19a901798..f529bdbde 100644 --- a/packages/frontend/src/embed/EmbedViewer.vue +++ b/packages/frontend/src/embed/EmbedViewer.vue @@ -1,12 +1,18 @@