Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 303f3f5a20 | |||
| 3dad1a0849 | |||
| e6d667c951 | |||
| 226693f82d | |||
| 8caf0e5a77 | |||
| 050aab39d0 | |||
| c7d7806a30 | |||
| a9cc5ed161 | |||
| eeba4f860e | |||
| 7aa91c2d86 | |||
| e9edf0fb17 |
+9
-2
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"root": true,
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es2021": true,
|
||||
@@ -9,12 +10,15 @@
|
||||
"prettier",
|
||||
"prettier/vue",
|
||||
"plugin:prettier/recommended",
|
||||
"eslint:recommended"
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"parser": "vue-eslint-parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 12,
|
||||
"sourceType": "module",
|
||||
"parser": "@babel/eslint-parser"
|
||||
"parser": "@typescript-eslint/parser"
|
||||
},
|
||||
"plugins": ["vue", "prettier"],
|
||||
"rules": {
|
||||
@@ -25,6 +29,9 @@
|
||||
"after": true
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"@typescript-eslint/no-array-constructor": "off",
|
||||
//"array-bracket-spacing": [2, "always"],
|
||||
"block-spacing": [2, "always"],
|
||||
"camelcase": [
|
||||
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
}
|
||||
@@ -19,7 +19,7 @@ Comprehensive developer and user documentation can be found in our:
|
||||
For developing and debugging this connector you'll need to set up a Speckle App.
|
||||
The server on which the app runs must be on `https`, so **do not use a local Speckle server** on `http://localhost:3000/` as it will not work.
|
||||
|
||||
You can use `https://latest.speckle.dev/` or `https://speckle.xyz/`.
|
||||
You can use `https://latest.speckle.systems/` or `https://app.speckle.systems/`.
|
||||
|
||||
Now open up its frontend, and under your profile register a new app.
|
||||
|
||||
|
||||
Generated
+403
-81
@@ -4607,6 +4607,12 @@
|
||||
"integrity": "sha1-YcyEaYSeW83QxwRBIiZcOc7BDPQ=",
|
||||
"dev": true
|
||||
},
|
||||
"@types/crypto-js": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.1.tgz",
|
||||
"integrity": "sha512-FSPGd9+OcSok3RsM0UZ/9fcvMOXJ1ENE/ZbLfOPlBWj7BgXtEAM8VYfTtT760GiLbQIMoVozwVuisjvsVwqYWw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/express": {
|
||||
"version": "4.17.11",
|
||||
"resolved": "https://registry.npm.taobao.org/@types/express/download/@types/express-4.17.11.tgz",
|
||||
@@ -4771,6 +4777,18 @@
|
||||
"integrity": "sha1-5IbQ2XOW15vu3QpuM/RTT/a0lz4=",
|
||||
"dev": true
|
||||
},
|
||||
"@types/office-js": {
|
||||
"version": "1.0.364",
|
||||
"resolved": "https://registry.npmjs.org/@types/office-js/-/office-js-1.0.364.tgz",
|
||||
"integrity": "sha512-sEoI3Rhtyz83WjMo3GamshNU7/j8CNY/UVrSVr3n6yOTWo6eG94pZvT4f00g0bvOYlY7Wi+OTZWEqY+MtQ81MQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/office-runtime": {
|
||||
"version": "1.0.35",
|
||||
"resolved": "https://registry.npmjs.org/@types/office-runtime/-/office-runtime-1.0.35.tgz",
|
||||
"integrity": "sha512-qrP3bkDNoPY6WZMTOoutFdkZHdK91OUC1/Ohzw94bE8OD8pVoPjHKSoYaS+NlTFyXH3SNKYmQU+E6o966zARIA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/q": {
|
||||
"version": "1.5.4",
|
||||
"resolved": "https://registry.npm.taobao.org/@types/q/download/@types/q-1.5.4.tgz",
|
||||
@@ -4906,6 +4924,297 @@
|
||||
"integrity": "sha1-gIyfp+RRcnTtVV+hWPLeS09GjnE=",
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
"version": "4.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz",
|
||||
"integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/experimental-utils": "4.33.0",
|
||||
"@typescript-eslint/scope-manager": "4.33.0",
|
||||
"debug": "^4.3.1",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"ignore": "^5.1.8",
|
||||
"regexpp": "^3.1.0",
|
||||
"semver": "^7.3.5",
|
||||
"tsutils": "^3.21.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ignore": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
|
||||
"integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
|
||||
"dev": true
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/experimental-utils": {
|
||||
"version": "4.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz",
|
||||
"integrity": "sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/json-schema": "^7.0.7",
|
||||
"@typescript-eslint/scope-manager": "4.33.0",
|
||||
"@typescript-eslint/types": "4.33.0",
|
||||
"@typescript-eslint/typescript-estree": "4.33.0",
|
||||
"eslint-scope": "^5.1.1",
|
||||
"eslint-utils": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"eslint-scope": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
|
||||
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esrecurse": "^4.3.0",
|
||||
"estraverse": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"eslint-utils": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
|
||||
"integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"eslint-visitor-keys": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"eslint-visitor-keys": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
|
||||
"integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/parser": {
|
||||
"version": "4.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz",
|
||||
"integrity": "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/scope-manager": "4.33.0",
|
||||
"@typescript-eslint/types": "4.33.0",
|
||||
"@typescript-eslint/typescript-estree": "4.33.0",
|
||||
"debug": "^4.3.1"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/scope-manager": {
|
||||
"version": "4.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz",
|
||||
"integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "4.33.0",
|
||||
"@typescript-eslint/visitor-keys": "4.33.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/types": {
|
||||
"version": "4.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz",
|
||||
"integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "4.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz",
|
||||
"integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "4.33.0",
|
||||
"@typescript-eslint/visitor-keys": "4.33.0",
|
||||
"debug": "^4.3.1",
|
||||
"globby": "^11.0.3",
|
||||
"is-glob": "^4.0.1",
|
||||
"semver": "^7.3.5",
|
||||
"tsutils": "^3.21.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nodelib/fs.stat": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
|
||||
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
|
||||
"dev": true
|
||||
},
|
||||
"array-union": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
|
||||
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
|
||||
"dev": true
|
||||
},
|
||||
"braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"dir-glob": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
||||
"integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-type": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"fast-glob": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
|
||||
"integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@nodelib/fs.stat": "^2.0.2",
|
||||
"@nodelib/fs.walk": "^1.2.3",
|
||||
"glob-parent": "^5.1.2",
|
||||
"merge2": "^1.3.0",
|
||||
"micromatch": "^4.0.4"
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"globby": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
|
||||
"integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"array-union": "^2.1.0",
|
||||
"dir-glob": "^3.0.1",
|
||||
"fast-glob": "^3.2.9",
|
||||
"ignore": "^5.2.0",
|
||||
"merge2": "^1.4.1",
|
||||
"slash": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"ignore": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
|
||||
"integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
|
||||
"dev": true
|
||||
},
|
||||
"is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"micromatch": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
|
||||
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"braces": "^3.0.2",
|
||||
"picomatch": "^2.3.1"
|
||||
}
|
||||
},
|
||||
"path-type": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
|
||||
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
|
||||
"dev": true
|
||||
},
|
||||
"picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"dev": true
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"slash": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
|
||||
"dev": true
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/visitor-keys": {
|
||||
"version": "4.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz",
|
||||
"integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "4.33.0",
|
||||
"eslint-visitor-keys": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"eslint-visitor-keys": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
|
||||
"integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@vue/babel-helper-vue-jsx-merge-props": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npm.taobao.org/@vue/babel-helper-vue-jsx-merge-props/download/@vue/babel-helper-vue-jsx-merge-props-1.2.1.tgz",
|
||||
@@ -5215,6 +5524,63 @@
|
||||
"integrity": "sha1-/q7SVZc9LndVW4PbwIhRpsY1IPo=",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
|
||||
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"ssri": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npm.taobao.org/ssri/download/ssri-8.0.1.tgz?cache=0&sync_timestamp=1617826339976&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fssri%2Fdownload%2Fssri-8.0.1.tgz",
|
||||
@@ -5223,6 +5589,28 @@
|
||||
"requires": {
|
||||
"minipass": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"vue-loader-v16": {
|
||||
"version": "npm:vue-loader@16.8.3",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
|
||||
"integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"chalk": "^4.1.0",
|
||||
"hash-sum": "^2.0.0",
|
||||
"loader-utils": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -18672,6 +19060,15 @@
|
||||
"integrity": "sha1-zy04vcNKE0vK8QkcQfZhni9nLQA=",
|
||||
"dev": true
|
||||
},
|
||||
"tsutils": {
|
||||
"version": "3.21.0",
|
||||
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
|
||||
"integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "^1.8.1"
|
||||
}
|
||||
},
|
||||
"tty": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npm.taobao.org/tty/download/tty-1.0.1.tgz",
|
||||
@@ -18739,6 +19136,12 @@
|
||||
"is-typedarray": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.9.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
|
||||
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
|
||||
"dev": true
|
||||
},
|
||||
"ua-parser-js": {
|
||||
"version": "0.7.28",
|
||||
"resolved": "https://registry.npm.taobao.org/ua-parser-js/download/ua-parser-js-0.7.28.tgz?cache=0&sync_timestamp=1618065908450&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fua-parser-js%2Fdownload%2Fua-parser-js-0.7.28.tgz",
|
||||
@@ -19669,87 +20072,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"vue-loader-v16": {
|
||||
"version": "npm:vue-loader@16.8.3",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
|
||||
"integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"chalk": "^4.1.0",
|
||||
"hash-sum": "^2.0.0",
|
||||
"loader-utils": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
|
||||
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"vue-mixpanel": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/vue-mixpanel/-/vue-mixpanel-1.0.7.tgz",
|
||||
|
||||
+12
-2
@@ -4,9 +4,10 @@
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"compile": "tsc && prettier ./src/**/*.js --write",
|
||||
"lint": "vue-cli-service lint",
|
||||
"excel": "office-addin-debugging start public/manifest.xml",
|
||||
"excel:web": "office-addin-debugging start public/manifest.xml web --document https://skfn3-my.sharepoint.com/:x:/r/personal/connorisadmin_skfn3_onmicrosoft_com/_layouts/15/Doc.aspx?sourcedoc=%7B46999CFC-9B5A-4716-9F71-FECAEA59A6E8%7D",
|
||||
"excel:web": "office-addin-debugging start public/manifest.xml web --document https://v2k0p-my.sharepoint.com/:x:/r/personal/connor_v2k0p_onmicrosoft_com/_layouts/15/Doc.aspx?sourcedoc=%7B101920A4-0AEA-4E82-B0E5-36E3162F7E86%7D&file=signalisation-permanente.xlsx&action=default&mobileredirect=true&DefaultItemOpen=1&ct=1705007910553&wdOrigin=OFFICECOM-WEB.MAIN.REC&cid=634f97aa-c5a2-411a-a705-412dc57eaaf7&wdPreviousSessionSrc=HarmonyWeb&wdPreviousSession=96a3ad12-6cd0-44ee-bf8b-c523c706e44e",
|
||||
"excel:web2": "office-addin-debugging start public/manifest.xml web --document https://teocomi-my.sharepoint.com/:x:/g/personal/teocomi_teocomi_onmicrosoft_com/EdxKPPFhnMdDoGclr4J-xJABLf-Ao6CJ902W95kcFPL2fA?e=mD0B8a",
|
||||
"excel:prod": "office-addin-debugging start public/manifest-prod.xml",
|
||||
"excel:web-prod": "office-addin-debugging start public/manifest-prod.xml web --document https://teocomi-my.sharepoint.com/:x:/g/personal/teocomi_teocomi_onmicrosoft_com/EdxKPPFhnMdDoGclr4J-xJAB7H6-TRJ5s5ZnXzVdrdFyUg?e=VAFmBN",
|
||||
@@ -34,6 +35,11 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "^7.14.3",
|
||||
"@types/crypto-js": "^4.2.1",
|
||||
"@types/office-js": "^1.0.364",
|
||||
"@types/office-runtime": "^1.0.35",
|
||||
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
||||
"@typescript-eslint/parser": "^4.33.0",
|
||||
"@vue/cli-plugin-babel": "~4.5.13",
|
||||
"@vue/cli-plugin-eslint": "~4.5.13",
|
||||
"@vue/cli-plugin-router": "^4.5.13",
|
||||
@@ -52,6 +58,7 @@
|
||||
"prettier": "^2.2.1",
|
||||
"sass": "^1.32.0",
|
||||
"sass-loader": "^10.0.0",
|
||||
"typescript": "^4.9.5",
|
||||
"vue-cli-plugin-apollo": "~0.22.2",
|
||||
"vue-cli-plugin-vuetify": "~2.4.0",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
@@ -61,5 +68,8 @@
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not dead"
|
||||
]
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=14.0.0 <15.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -22,8 +22,8 @@
|
||||
<SupportUrl DefaultValue="https://speckle.guide/user/excel.html" />
|
||||
|
||||
<AppDomains>
|
||||
<AppDomain>https://latest.speckle.dev</AppDomain>
|
||||
<AppDomain>https://speckle.xyz</AppDomain>
|
||||
<AppDomain>https://latest.speckle.systems</AppDomain>
|
||||
<AppDomain>https://app.speckle.systems</AppDomain>
|
||||
<AppDomain>https://localhost:3000</AppDomain>
|
||||
</AppDomains>
|
||||
|
||||
|
||||
+10
-5
@@ -18,6 +18,7 @@
|
||||
</v-list-item-avatar>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ user.name }}</v-list-item-title>
|
||||
<v-list-item-subtitle class="smaller-text">{{ serverUrl }}</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
||||
@@ -94,6 +95,7 @@
|
||||
<span class="caption">CONNECTOR</span>
|
||||
</v-btn>
|
||||
</v-app-bar>
|
||||
<global-toast />
|
||||
|
||||
<v-main :style="background">
|
||||
<router-view />
|
||||
@@ -105,13 +107,15 @@
|
||||
const crypto = require('crypto')
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {},
|
||||
components: {
|
||||
GlobalToast: () => import('@/components/GlobalToast')
|
||||
},
|
||||
data: () => ({
|
||||
drawer: null,
|
||||
showSnackbar: false,
|
||||
items: [
|
||||
{
|
||||
name: 'Streams',
|
||||
name: 'Projects',
|
||||
icon: '📃',
|
||||
to: '/'
|
||||
},
|
||||
@@ -186,9 +190,6 @@ export default {
|
||||
'@' +
|
||||
crypto.createHash('md5').update(this.user.email.toLowerCase()).digest('hex').toUpperCase()
|
||||
|
||||
console.log(server_id)
|
||||
console.log(distinct_id)
|
||||
|
||||
this.$mixpanel.register({ server_id: server_id, hostApp: 'excel', type: 'action' })
|
||||
|
||||
this.$mixpanel.identify(distinct_id)
|
||||
@@ -311,4 +312,8 @@ export default {
|
||||
opacity: 1;
|
||||
transition: opacity 0.15s;
|
||||
}
|
||||
|
||||
.smaller-text {
|
||||
font-size: 0.7rem; /* Example: Adjust the size as needed */
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<v-snackbar v-if="text" v-model="snack" app bottom :color="color">
|
||||
<div v-for="(line, index) in text.split('\n')" :key="index">
|
||||
{{ line }}
|
||||
</div>
|
||||
<template #action="{}">
|
||||
<v-btn v-if="actionName" small outlined @click="openUrl(url)" @click:append="snack = false">
|
||||
{{ actionName }}
|
||||
</v-btn>
|
||||
<v-btn small icon @click="snack = false">
|
||||
<v-icon small>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-snackbar>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
snack: false,
|
||||
color: 'primary',
|
||||
text: null,
|
||||
actionName: null,
|
||||
url: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
snack(newVal) {
|
||||
if (!newVal) {
|
||||
this.text = null
|
||||
this.actionName = null
|
||||
this.url = null
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$eventHub.$on('success', (args) => {
|
||||
this.snack = true
|
||||
this.color = 'green'
|
||||
this.text = args.text
|
||||
this.actionName = args.action ? args.action.name : null
|
||||
this.url = args.action ? args.action.url : null
|
||||
})
|
||||
this.$eventHub.$on('notification', (args) => {
|
||||
this.snack = true
|
||||
this.color = 'primary'
|
||||
this.text = args.text
|
||||
this.actionName = args.action ? args.action.name : null
|
||||
this.url = args.action ? args.action.url : null
|
||||
})
|
||||
this.$eventHub.$on('error', (args) => {
|
||||
this.snack = true
|
||||
this.color = '#CC3300'
|
||||
this.text = args.text
|
||||
this.actionName = args.action ? args.action.name : null
|
||||
this.url = args.action ? args.action.url : null
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
openUrl(link) {
|
||||
this.$mixpanel.track('Connector Action', { name: 'Open In Web' })
|
||||
window.open(link)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<v-card class="pa-5 mb-3" style="transition: all 0.2s" @click="openStream">
|
||||
<v-card class="px-5 py-2 mb-3" style="transition: all 0.2s" @click="openStream">
|
||||
<v-row>
|
||||
<v-col cols="12" sm="8" class="align-self-center">
|
||||
<div class="subtitle-1">
|
||||
<div class="text-h6">
|
||||
{{ stream.name }}
|
||||
</div>
|
||||
<div class="caption mb-2 mt-1 text-truncate">
|
||||
@@ -19,11 +19,7 @@
|
||||
{{ role }}
|
||||
</v-chip>
|
||||
<v-chip
|
||||
v-tooltip="
|
||||
stream.branches.totalCount +
|
||||
' branch' +
|
||||
(stream.branches.totalCount === 1 ? '' : 'es')
|
||||
"
|
||||
v-tooltip="`${stream.branches.totalCount === 1 ? '1 model' : 'models'}`"
|
||||
outlined
|
||||
class="ml-2"
|
||||
small
|
||||
@@ -33,9 +29,7 @@
|
||||
</v-chip>
|
||||
|
||||
<v-chip
|
||||
v-tooltip="
|
||||
stream.commits.totalCount + ' commit' + (stream.commits.totalCount === 1 ? '' : 's')
|
||||
"
|
||||
v-tooltip="`${stream.commits.totalCount === 1 ? '1 version' : 'versions'}`"
|
||||
outlined
|
||||
class="ml-2"
|
||||
small
|
||||
@@ -45,7 +39,7 @@
|
||||
</v-chip>
|
||||
</div>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="4" class="text-sm-center text-md-right align-self-center">
|
||||
<v-col cols="12" sm="4" class="text-sm-center text-md-right align-self-center pt-0">
|
||||
<div>
|
||||
<span v-for="user in collaboratorsSlice" :key="user.id">
|
||||
<user-avatar
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
<template>
|
||||
<v-card :class="`my-1 mb-0 pa-0 pb-2 ${localExpand ? 'elevation-3' : 'elevation-0'} my-0`">
|
||||
<v-card-title>
|
||||
<v-chip @click="toggleLoadExpand">
|
||||
<v-icon small class="mr-2">mdi-code-array</v-icon>
|
||||
{{ keyName }}
|
||||
<span class="caption ml-2">List ( >{{ (value.length - 1) * 5000 }} elements)</span>
|
||||
<v-icon class="ml-2" small>
|
||||
{{ localExpand ? 'mdi-minus' : 'mdi-plus' }}
|
||||
</v-icon>
|
||||
</v-chip>
|
||||
<v-dialog v-model="progress" persistent>
|
||||
<v-card class="pt-3">
|
||||
<v-card-text class="caption">
|
||||
Receiving data from the Speckleverse...
|
||||
<v-progress-linear
|
||||
class="mt-2"
|
||||
:value="`${(numChunksReceived / value.length) * 100}`"
|
||||
color="primary"
|
||||
></v-progress-linear>
|
||||
<v-btn class="mt-3" outlined x-small color="primary" @click="cancel">Cancel</v-btn>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
<v-btn icon small @click="bake">
|
||||
<v-icon small>mdi-download</v-icon>
|
||||
</v-btn>
|
||||
</v-card-title>
|
||||
<v-card-text v-if="localExpand" class="pb-0 pr-0 pl-3">
|
||||
<component
|
||||
:is="entry.type"
|
||||
v-for="(entry, index) in rangeEntries"
|
||||
:key="index"
|
||||
:key-name="entry.key"
|
||||
:full-key-name="fullKeyName ? `${fullKeyName}.${entry.key}` : entry.key"
|
||||
:value="entry.value"
|
||||
:stream-id="streamId"
|
||||
:commit-id="commitId"
|
||||
:commit-msg="commitMsg"
|
||||
:nearest-object-id="nearestObjectId"
|
||||
:path-from-nearest-object="`${entry.pathFromNearestObject}`"
|
||||
></component>
|
||||
</v-card-text>
|
||||
<v-card-text v-if="localExpand && currentLimit < value.length">
|
||||
<v-btn small @click="loadMore">Show more</v-btn>
|
||||
</v-card-text>
|
||||
<filter-modal ref="modal" />
|
||||
</v-card>
|
||||
</template>
|
||||
<script>
|
||||
import { bake } from '../plugins/excel'
|
||||
import objectQuery from '../graphql/object.gql'
|
||||
import { createClient } from '../vue-apollo'
|
||||
|
||||
let ac = new AbortController()
|
||||
export default {
|
||||
name: 'ObjectChunkedListViewer',
|
||||
components: {
|
||||
FilterModal: () => import('./FilterModal'),
|
||||
ObjectSpeckleViewer: () => import('./ObjectSpeckleViewer'),
|
||||
ObjectSimpleViewer: () => import('./ObjectSimpleViewer'),
|
||||
ObjectValueViewer: () => import('./ObjectValueViewer')
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
keyName: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
fullKeyName: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
streamId: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
commitId: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
commitMsg: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
nearestObjectId: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
pathFromNearestObject: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
localExpand: false,
|
||||
itemsPerLoad: 3,
|
||||
currentLimit: 3,
|
||||
progress: false,
|
||||
numChunksReceived: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
rangeEntries() {
|
||||
let arr = []
|
||||
let index = 0
|
||||
const delimiter = ':::'
|
||||
for (let val of this.range) {
|
||||
index++
|
||||
if (Array.isArray(val)) {
|
||||
arr.push({
|
||||
key: `${index}`,
|
||||
value: val,
|
||||
type: 'ObjectChunkedListViewer',
|
||||
pathFromNearestObject: this.pathFromNearestObject
|
||||
? this.pathFromNearestObject + (index - 1) + delimiter
|
||||
: index - 1 + delimiter
|
||||
})
|
||||
} else if (typeof val === 'object' && val !== null) {
|
||||
if (val.speckle_type && val.speckle_type === 'reference') {
|
||||
arr.push({
|
||||
key: `${index}`,
|
||||
value: val,
|
||||
type: 'ObjectSpeckleViewer'
|
||||
})
|
||||
} else {
|
||||
arr.push({
|
||||
key: `${index}`,
|
||||
value: val,
|
||||
type: 'ObjectSimpleViewer'
|
||||
})
|
||||
}
|
||||
} else {
|
||||
arr.push({
|
||||
key: `${index}`,
|
||||
value: val,
|
||||
type: 'ObjectValueViewer'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
arr.sort((a, b) => {
|
||||
if (a.type === b.type) return 0
|
||||
if (a.type === 'ObjectValueViewer') return -1
|
||||
return 0
|
||||
})
|
||||
return arr
|
||||
},
|
||||
range() {
|
||||
return this.value.slice(0, this.currentLimit)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleLoadExpand() {
|
||||
this.localExpand = !this.localExpand
|
||||
},
|
||||
loadMore() {
|
||||
this.currentLimit += this.itemsPerLoad
|
||||
},
|
||||
cancel() {
|
||||
ac.abort()
|
||||
},
|
||||
async bake() {
|
||||
ac = new AbortController()
|
||||
|
||||
this.progress = true
|
||||
this.$mixpanel.track('Receive')
|
||||
|
||||
let allData = []
|
||||
|
||||
for (let i = 0; i < this.value.length; i++) {
|
||||
if (ac.signal.aborted) {
|
||||
break
|
||||
}
|
||||
|
||||
let speckleObj = await this.getObjectFromCurrentStreamWithId(this.value[i].referencedId)
|
||||
let speckleType = speckleObj?.data?.stream?.object?.data?.speckle_type
|
||||
if (speckleType !== 'Speckle.Core.Models.DataChunk') {
|
||||
continue
|
||||
}
|
||||
|
||||
allData.push(...speckleObj.data.stream.object.data.data)
|
||||
this.numChunksReceived++
|
||||
}
|
||||
|
||||
let receiverSelection = null
|
||||
if (!ac.signal.aborted) {
|
||||
receiverSelection = await bake(
|
||||
allData,
|
||||
this.streamId,
|
||||
this.commitId,
|
||||
this.commitMsg,
|
||||
this.$refs.modal,
|
||||
ac.signal,
|
||||
this.nearestObjectId,
|
||||
this.pathFromNearestObject
|
||||
)
|
||||
}
|
||||
|
||||
if (receiverSelection) {
|
||||
receiverSelection.fullKeyName = this.fullKeyName
|
||||
|
||||
this.$store.dispatch('setReceiverSelection', {
|
||||
id: this.streamId,
|
||||
receiverSelection: receiverSelection
|
||||
})
|
||||
}
|
||||
|
||||
this.progress = false
|
||||
this.numChunksReceived = 0
|
||||
},
|
||||
async getObjectFromCurrentStreamWithId(id) {
|
||||
let client = createClient()
|
||||
return await client.query({
|
||||
query: objectQuery,
|
||||
variables: {
|
||||
streamId: this.streamId,
|
||||
id: id
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -55,8 +55,7 @@ export default {
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
type: Object
|
||||
},
|
||||
streamId: {
|
||||
type: String,
|
||||
|
||||
@@ -60,6 +60,7 @@ export default {
|
||||
components: {
|
||||
FilterModal: () => import('./FilterModal'),
|
||||
ObjectListViewer: () => import('./ObjectListViewer'),
|
||||
ObjectChunkedListViewer: () => import('./ObjectChunkedListViewer'),
|
||||
ObjectSimpleViewer: () => import('./ObjectSimpleViewer'),
|
||||
ObjectValueViewer: () => import('./ObjectValueViewer')
|
||||
},
|
||||
@@ -123,8 +124,8 @@ export default {
|
||||
id: this.value.referencedId
|
||||
}
|
||||
},
|
||||
result() {
|
||||
this.objectEntries = this.getObjectEntries()
|
||||
async result() {
|
||||
this.objectEntries = await this.getObjectEntries()
|
||||
},
|
||||
skip() {
|
||||
return !this.localExpand
|
||||
@@ -145,14 +146,12 @@ export default {
|
||||
cancel() {
|
||||
ac.abort()
|
||||
},
|
||||
getObjectEntries() {
|
||||
async getObjectEntries() {
|
||||
if (!this.object) return []
|
||||
let entries = Object.entries(this.object.data)
|
||||
let arr = []
|
||||
this.updatedObjectId = this.object.data.id ?? this.nearestObjectId
|
||||
const delimiter = ':::'
|
||||
console.log(this.updatedObjectId, delimiter)
|
||||
console.log(this.nearestObjectId)
|
||||
for (let [key, val] of entries) {
|
||||
let name = key
|
||||
if (key.startsWith('__')) continue
|
||||
@@ -161,13 +160,29 @@ export default {
|
||||
if (key === 'speckle_type') name = 'speckle type'
|
||||
|
||||
if (Array.isArray(val)) {
|
||||
arr.push({
|
||||
key,
|
||||
name,
|
||||
value: val,
|
||||
type: 'ObjectListViewer',
|
||||
pathFromNearestObject: key + delimiter
|
||||
})
|
||||
let speckleTypeOfFirstObj = null
|
||||
if (val.length > 0 && val[0].referencedId) {
|
||||
let firstObj = await this.getObjectFromCurrentStreamWithId(val[0].referencedId)
|
||||
speckleTypeOfFirstObj = firstObj?.data?.stream?.object?.data?.speckle_type
|
||||
}
|
||||
|
||||
if (speckleTypeOfFirstObj === 'Speckle.Core.Models.DataChunk') {
|
||||
arr.push({
|
||||
key,
|
||||
name,
|
||||
value: val,
|
||||
type: 'ObjectChunkedListViewer',
|
||||
pathFromNearestObject: key + delimiter
|
||||
})
|
||||
} else {
|
||||
arr.push({
|
||||
key,
|
||||
name,
|
||||
value: val,
|
||||
type: 'ObjectListViewer',
|
||||
pathFromNearestObject: key + delimiter
|
||||
})
|
||||
}
|
||||
} else if (typeof val === 'object' && val !== null) {
|
||||
if (val.speckle_type && val.speckle_type === 'reference') {
|
||||
arr.push({
|
||||
@@ -236,6 +251,16 @@ export default {
|
||||
}
|
||||
|
||||
this.progress = false
|
||||
},
|
||||
async getObjectFromCurrentStreamWithId(id) {
|
||||
let client = createClient()
|
||||
return await client.query({
|
||||
query: objectQuery,
|
||||
variables: {
|
||||
streamId: this.streamId,
|
||||
id: id
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
small
|
||||
icon
|
||||
color="primary"
|
||||
:href="`${serverUrl}/streams/${stream.id}/branches/${selectedBranch.name}`"
|
||||
:href="commitViewUrl()"
|
||||
target="_blank"
|
||||
>
|
||||
<v-icon small>mdi-open-in-new</v-icon>
|
||||
@@ -313,6 +313,17 @@ export default {
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
commitViewUrl() {
|
||||
if (this.$store.state.isFE2) {
|
||||
if (this.selectedCommit && this.selectedCommit.id) {
|
||||
return `${this.serverUrl}/projects/${this.stream.id}/models/${this.selectedBranch.id}@${this.selectedCommit.id}`
|
||||
} else {
|
||||
return `${this.serverUrl}/projects/${this.stream.id}/models/${this.selectedBranch.id}`
|
||||
}
|
||||
} else {
|
||||
return `${this.serverUrl}/streams/${this.stream.id}/branches/${this.selectedBranch.name}`
|
||||
}
|
||||
},
|
||||
swapReceiver() {
|
||||
this.isReceiver = !this.isReceiver
|
||||
this.$emit('loadByCommitId', this.selectedCommitId)
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-card>
|
||||
<v-card-title class="text-h5 mb-1">Create a New Branch</v-card-title>
|
||||
<v-card-title class="text-h5 mb-1">
|
||||
{{ `Create a New Model` }}
|
||||
</v-card-title>
|
||||
<v-card-subtitle class="py-0 my-0 font-italic">under {{ streamName }} stream</v-card-subtitle>
|
||||
<v-container class="px-6" pb-0>
|
||||
<v-text-field
|
||||
@@ -48,6 +50,7 @@
|
||||
|
||||
<script>
|
||||
import gql from 'graphql-tag'
|
||||
import { createClient } from '../../vue-apollo'
|
||||
// import { bus } from '@/main'
|
||||
export default {
|
||||
name: 'CreateBranchDialog',
|
||||
@@ -66,7 +69,7 @@ export default {
|
||||
showCreateBranch: false,
|
||||
branchName: '',
|
||||
description: '',
|
||||
defaultDescription: 'Stream created from SketchUp',
|
||||
defaultDescription: 'Stream created from Excel',
|
||||
accountToCreateStream: null
|
||||
}
|
||||
},
|
||||
@@ -76,6 +79,9 @@ export default {
|
||||
return this.$store.getters.isAuthenticated
|
||||
}
|
||||
},
|
||||
apollo: {
|
||||
client: createClient()
|
||||
},
|
||||
methods: {
|
||||
async createBranch() {
|
||||
let res = await this.$apollo.mutate({
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
<template>
|
||||
<v-container fluid class="px-1 pb-0 pt-1">
|
||||
<v-row>
|
||||
<v-col class="center-content">
|
||||
<v-row class="px-3 py-0">
|
||||
<v-col class="d-flex justify-center pb-0">
|
||||
<!-- DIALOG: Create New Stream -->
|
||||
<v-dialog v-model="showCreateNewStream">
|
||||
<template #activator="{ on, attrs }">
|
||||
<v-btn class="ma-2 pa-3" x-small v-bind="attrs" v-on="on">
|
||||
<v-btn block class="pa-3" small v-bind="attrs" v-on="on">
|
||||
<v-icon dark left>mdi-plus-circle</v-icon>
|
||||
Create New Stream
|
||||
{{ `Create New Project` }}
|
||||
</v-btn>
|
||||
</template>
|
||||
|
||||
<v-card>
|
||||
<v-card-title class="text-h5">Create a New Stream</v-card-title>
|
||||
<v-card-title class="text-h5">
|
||||
{{ `Create New Project` }}
|
||||
</v-card-title>
|
||||
<v-container class="px-6" pb-0>
|
||||
<v-text-field
|
||||
v-model="streamName"
|
||||
@@ -20,7 +22,7 @@
|
||||
hide-details
|
||||
dense
|
||||
flat
|
||||
placeholder="Stream Name (Optional)"
|
||||
:placeholder="`Project Name (Optional)`"
|
||||
/>
|
||||
<v-text-field
|
||||
v-model="description"
|
||||
@@ -30,7 +32,7 @@
|
||||
flat
|
||||
placeholder="Description (Optional)"
|
||||
/>
|
||||
<v-switch v-model="privateStream" :label="'Private Stream'"></v-switch>
|
||||
<v-switch v-model="privateStream" label="Private Project"></v-switch>
|
||||
</v-container>
|
||||
|
||||
<v-card-actions>
|
||||
@@ -40,19 +42,24 @@
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
</v-col>
|
||||
<v-col class="d-flex justify-center">
|
||||
<!-- DIALOG: Add a Stream by ID or URL -->
|
||||
<v-dialog v-model="showCreateStreamById">
|
||||
<template #activator="{ on, attrs }">
|
||||
<v-btn class="ma-2 pa-3" x-small min-width="163" v-bind="attrs" v-on="on">
|
||||
<v-btn block class="pa-3" small min-width="163" v-bind="attrs" v-on="on">
|
||||
<v-icon dark left>mdi-link-plus</v-icon>
|
||||
Add By ID or URL
|
||||
</v-btn>
|
||||
</template>
|
||||
|
||||
<v-card>
|
||||
<v-card-title class="text-h5">Add a Stream by ID or URL</v-card-title>
|
||||
<v-card-text>Stream IDs and Stream/Branch/Commit URLs are supported.</v-card-text>
|
||||
<v-card-title class="text-h5">
|
||||
{{ `Add a Project by ID or URL` }}
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
{{ 'Project IDs and Project/Model/Version URLs are supported.' }}
|
||||
</v-card-text>
|
||||
<v-container class="px-6">
|
||||
<v-text-field
|
||||
v-model="createStreamByIdText"
|
||||
@@ -60,7 +67,7 @@
|
||||
hide-details
|
||||
dense
|
||||
flat
|
||||
placeholder="Stream URL"
|
||||
:placeholder="'Project URL'"
|
||||
/>
|
||||
</v-container>
|
||||
<v-card-actions>
|
||||
@@ -85,6 +92,7 @@
|
||||
<script>
|
||||
import gql from 'graphql-tag'
|
||||
import { StreamWrapper } from '@/utils/streamWrapper'
|
||||
import { createClient } from '../../vue-apollo'
|
||||
|
||||
export default {
|
||||
name: 'CreateStreamDialog',
|
||||
@@ -117,14 +125,26 @@ export default {
|
||||
return this.$store.getters.isAuthenticated
|
||||
}
|
||||
},
|
||||
apollo: {
|
||||
$client: createClient()
|
||||
},
|
||||
methods: {
|
||||
async getStream() {
|
||||
try {
|
||||
const streamWrapper = new StreamWrapper(
|
||||
this.createStreamByIdText,
|
||||
this.accountId,
|
||||
this.serverUrl
|
||||
this.serverUrl,
|
||||
this.$store.state.isFE2
|
||||
)
|
||||
const match = streamWrapper.matchUrl(this.createStreamByIdText)
|
||||
if (match.groups.additionalModels !== undefined) {
|
||||
this.$eventHub.$emit('error', {
|
||||
text:
|
||||
'Multi-model URLs are not supported!\nTry to select just one single model in the web app and paste that in.'
|
||||
})
|
||||
return
|
||||
}
|
||||
this.$router.push(`/streams/${streamWrapper.streamId}/${streamWrapper.commitId}`)
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
@@ -150,7 +170,6 @@ export default {
|
||||
this.streamName = ''
|
||||
this.description = ''
|
||||
this.$mixpanel.track('Connector Action', { name: 'Create Stream' })
|
||||
this.refresh()
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
query Stream($id: String!) {
|
||||
query Stream($id: String!, $limit: Int!) {
|
||||
stream(id: $id) {
|
||||
id
|
||||
name
|
||||
role
|
||||
branches {
|
||||
branches (limit: $limit) {
|
||||
totalCount
|
||||
items {
|
||||
id
|
||||
|
||||
@@ -6,6 +6,8 @@ import { apolloProvider } from './vue-apollo'
|
||||
import vuetify from './plugins/vuetify'
|
||||
import '@mdi/font/css/materialdesignicons.css'
|
||||
|
||||
Vue.prototype.$eventHub = new Vue()
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
import VueTimeago from 'vue-timeago'
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
'use strict'
|
||||
Object.defineProperty(exports, '__esModule', { value: true })
|
||||
exports.SerializedBase = exports.ObjectReference = exports.DataChunk = exports.BaseObjectSerializer = void 0
|
||||
/* eslint-disable @typescript-eslint/ban-types */
|
||||
const crypto_js_1 = require('crypto-js')
|
||||
/**
|
||||
* Serializer for Speckle objects written in Typescript
|
||||
*/
|
||||
class BaseObjectSerializer {
|
||||
constructor(transports) {
|
||||
this.transports = transports
|
||||
}
|
||||
async SerializeBase(object) {
|
||||
return await this.SerializeBaseWithClosures(object, [])
|
||||
}
|
||||
async SerializeBaseWithClosures(object, closures) {
|
||||
const thisClosure = new Map()
|
||||
closures.push(thisClosure)
|
||||
const converted = await this.PreserializeEachObjectProperty(object, closures)
|
||||
let json = this.SerializeMap(converted)
|
||||
const id = this.GetId(json)
|
||||
converted.set('id', id)
|
||||
this.AddSelfToParentClosures(id, closures)
|
||||
if (thisClosure.size > 0) {
|
||||
converted.set('__closure', Object.fromEntries(thisClosure))
|
||||
}
|
||||
converted.set('totalChildrenCount', thisClosure.size)
|
||||
json = this.SerializeMap(converted)
|
||||
await this.StoreObject(id, converted)
|
||||
return new SerializedBase(id, json)
|
||||
}
|
||||
async PreserializeObject(object, closures) {
|
||||
if (!(object instanceof Object) || object instanceof String) {
|
||||
return object
|
||||
}
|
||||
if (object instanceof DataChunk) {
|
||||
const serialized = await this.SerializeBaseWithClosures(object, [...closures])
|
||||
return new ObjectReference(serialized.id)
|
||||
}
|
||||
if (object instanceof Array) {
|
||||
// chunk array into 5000 by default
|
||||
const chunkSize = 5000
|
||||
if (object.length > chunkSize) {
|
||||
let serializedCount = 0
|
||||
const data = new Array()
|
||||
while (serializedCount < object.length) {
|
||||
const dataChunkCount = Math.min(chunkSize, object.length - serializedCount)
|
||||
data.push(new DataChunk(object.slice(serializedCount, serializedCount + dataChunkCount)))
|
||||
serializedCount += dataChunkCount
|
||||
}
|
||||
return await this.PreserializeObject(data, closures)
|
||||
}
|
||||
const convertedList = new Array()
|
||||
for (const element of object) {
|
||||
convertedList.push(await this.PreserializeObject(element, closures))
|
||||
}
|
||||
return convertedList
|
||||
}
|
||||
if (object instanceof Object) {
|
||||
return Object.fromEntries(await this.PreserializeEachObjectProperty(object, closures))
|
||||
}
|
||||
throw new Error(`Cannot serialize object ${object}`)
|
||||
}
|
||||
async PreserializeEachObjectProperty(o, closures) {
|
||||
const converted = new Map()
|
||||
const getters = Object.entries(Object.getOwnPropertyDescriptors(Reflect.getPrototypeOf(o)))
|
||||
.filter(([key, descriptor]) => typeof descriptor.get === 'function' && key !== '__proto__')
|
||||
.map(([key]) => key)
|
||||
const objectKeys = new Array()
|
||||
objectKeys.push(...Object.keys(o))
|
||||
objectKeys.push(...getters)
|
||||
for (const key of objectKeys) {
|
||||
const objKey = key
|
||||
converted.set(
|
||||
BaseObjectSerializer.CleanKey(key),
|
||||
await this.PreserializeObject(o[objKey], closures)
|
||||
)
|
||||
}
|
||||
return converted
|
||||
}
|
||||
static CleanKey(originalKey) {
|
||||
const newStringChars = []
|
||||
for (let i = 0; i < originalKey.length; i++) {
|
||||
if (i == 1 && originalKey[i] == '@' && originalKey[0] == '@') {
|
||||
continue
|
||||
}
|
||||
if (this.disallowedCharacters.includes(originalKey[i])) {
|
||||
continue
|
||||
}
|
||||
newStringChars.push(originalKey[i])
|
||||
}
|
||||
return newStringChars.join('')
|
||||
}
|
||||
async StoreObject(objectId, object) {
|
||||
for (const transport of this.transports) {
|
||||
await transport.SaveObject(objectId, object)
|
||||
}
|
||||
}
|
||||
SerializeMap(map) {
|
||||
return JSON.stringify(Object.fromEntries(map))
|
||||
}
|
||||
GetId(json) {
|
||||
return (0, crypto_js_1.MD5)(json).toString(crypto_js_1.enc.Hex)
|
||||
}
|
||||
AddSelfToParentClosures(objectId, closureTables) {
|
||||
// only go to closureTable length - 1 because the last closure table belongs to the object with the
|
||||
// provided id
|
||||
const parentClosureTablesCount = closureTables.length - 1
|
||||
for (let parentLevel = 0; parentLevel < parentClosureTablesCount; parentLevel++) {
|
||||
const childDepth = parentClosureTablesCount - parentLevel
|
||||
closureTables[parentLevel].set(objectId, childDepth)
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.BaseObjectSerializer = BaseObjectSerializer
|
||||
BaseObjectSerializer.disallowedCharacters = ['.', '/']
|
||||
class DataChunk {
|
||||
constructor(data) {
|
||||
this.speckle_type = 'Speckle.Core.Models.DataChunk'
|
||||
this.data = data ?? []
|
||||
}
|
||||
}
|
||||
exports.DataChunk = DataChunk
|
||||
class ObjectReference {
|
||||
constructor(referencedId) {
|
||||
this.referencedId = referencedId
|
||||
this.speckle_type = 'reference'
|
||||
}
|
||||
}
|
||||
exports.ObjectReference = ObjectReference
|
||||
class SerializedBase {
|
||||
constructor(id, json) {
|
||||
this.id = id
|
||||
this.json = json
|
||||
}
|
||||
}
|
||||
exports.SerializedBase = SerializedBase
|
||||
@@ -0,0 +1,166 @@
|
||||
/* eslint-disable @typescript-eslint/ban-types */
|
||||
import { MD5, enc } from 'crypto-js'
|
||||
|
||||
/**
|
||||
* Serializer for Speckle objects written in Typescript
|
||||
*/
|
||||
export class BaseObjectSerializer {
|
||||
constructor(public transports: ITransport[]) {}
|
||||
|
||||
public async SerializeBase(object: object): Promise<SerializedBase> {
|
||||
return await this.SerializeBaseWithClosures(object, [])
|
||||
}
|
||||
|
||||
private async SerializeBaseWithClosures(object: object, closures: Array<Map<string, number>>) {
|
||||
const thisClosure = new Map<string, number>()
|
||||
closures.push(thisClosure)
|
||||
|
||||
const converted = await this.PreserializeEachObjectProperty(object, closures)
|
||||
let json = this.SerializeMap(converted)
|
||||
const id = this.GetId(json)
|
||||
converted.set('id', id)
|
||||
|
||||
this.AddSelfToParentClosures(id, closures)
|
||||
if (thisClosure.size > 0) {
|
||||
converted.set('__closure', Object.fromEntries(thisClosure))
|
||||
}
|
||||
converted.set('totalChildrenCount', thisClosure.size)
|
||||
|
||||
json = this.SerializeMap(converted)
|
||||
await this.StoreObject(id, converted)
|
||||
return new SerializedBase(id, json)
|
||||
}
|
||||
|
||||
private async PreserializeObject(
|
||||
object: any,
|
||||
closures: Array<Map<string, number>>
|
||||
): Promise<any> {
|
||||
if (!(object instanceof Object) || object instanceof String) {
|
||||
return object
|
||||
}
|
||||
|
||||
if (object instanceof DataChunk) {
|
||||
const serialized = await this.SerializeBaseWithClosures(object, [...closures])
|
||||
return new ObjectReference(serialized.id)
|
||||
}
|
||||
|
||||
if (object instanceof Array) {
|
||||
// chunk array into 5000 by default
|
||||
const chunkSize = 5000
|
||||
if (object.length > chunkSize) {
|
||||
let serializedCount = 0
|
||||
const data = new Array<DataChunk>()
|
||||
while (serializedCount < object.length) {
|
||||
const dataChunkCount = Math.min(chunkSize, object.length - serializedCount)
|
||||
data.push(new DataChunk(object.slice(serializedCount, serializedCount + dataChunkCount)))
|
||||
serializedCount += dataChunkCount
|
||||
}
|
||||
return await this.PreserializeObject(data, closures)
|
||||
}
|
||||
|
||||
const convertedList = new Array<any>()
|
||||
for (const element of object) {
|
||||
convertedList.push(await this.PreserializeObject(element, closures))
|
||||
}
|
||||
return convertedList
|
||||
}
|
||||
|
||||
if (object instanceof Object) {
|
||||
return Object.fromEntries(await this.PreserializeEachObjectProperty(object, closures))
|
||||
}
|
||||
|
||||
throw new Error(`Cannot serialize object ${object}`)
|
||||
}
|
||||
|
||||
private async PreserializeEachObjectProperty(
|
||||
o: object,
|
||||
closures: Array<Map<string, number>>
|
||||
): Promise<Map<string, any>> {
|
||||
const converted = new Map<string, any>()
|
||||
|
||||
const getters = Object.entries(Object.getOwnPropertyDescriptors(Reflect.getPrototypeOf(o)))
|
||||
.filter(([key, descriptor]) => typeof descriptor.get === 'function' && key !== '__proto__')
|
||||
.map(([key]) => key)
|
||||
|
||||
const objectKeys = new Array<string>()
|
||||
objectKeys.push(...Object.keys(o))
|
||||
objectKeys.push(...getters)
|
||||
|
||||
for (const key of objectKeys) {
|
||||
const objKey = key as keyof object
|
||||
converted.set(
|
||||
BaseObjectSerializer.CleanKey(key),
|
||||
await this.PreserializeObject(o[objKey], closures)
|
||||
)
|
||||
}
|
||||
|
||||
return converted
|
||||
}
|
||||
|
||||
private static disallowedCharacters: string[] = ['.', '/']
|
||||
private static CleanKey(originalKey: string): string {
|
||||
const newStringChars = []
|
||||
for (let i = 0; i < originalKey.length; i++) {
|
||||
if (i == 1 && originalKey[i] == '@' && originalKey[0] == '@') {
|
||||
continue
|
||||
}
|
||||
if (this.disallowedCharacters.includes(originalKey[i])) {
|
||||
continue
|
||||
}
|
||||
|
||||
newStringChars.push(originalKey[i])
|
||||
}
|
||||
return newStringChars.join('')
|
||||
}
|
||||
|
||||
private async StoreObject(objectId: string, object: Map<string, any>) {
|
||||
for (const transport of this.transports) {
|
||||
await transport.SaveObject(objectId, object)
|
||||
}
|
||||
}
|
||||
|
||||
private SerializeMap(map: Map<string, any>): string {
|
||||
return JSON.stringify(Object.fromEntries(map))
|
||||
}
|
||||
|
||||
private GetId(json: string): string {
|
||||
return MD5(json).toString(enc.Hex)
|
||||
}
|
||||
|
||||
private AddSelfToParentClosures(objectId: string, closureTables: Array<Map<string, number>>) {
|
||||
// only go to closureTable length - 1 because the last closure table belongs to the object with the
|
||||
// provided id
|
||||
const parentClosureTablesCount = closureTables.length - 1
|
||||
|
||||
for (let parentLevel = 0; parentLevel < parentClosureTablesCount; parentLevel++) {
|
||||
const childDepth = parentClosureTablesCount - parentLevel
|
||||
closureTables[parentLevel].set(objectId, childDepth)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class DataChunk implements IBase {
|
||||
public speckle_type = 'Speckle.Core.Models.DataChunk'
|
||||
public data: any[]
|
||||
constructor(data: any[] | null) {
|
||||
this.data = data ?? []
|
||||
}
|
||||
}
|
||||
|
||||
export class ObjectReference implements IBase {
|
||||
public speckle_type = 'reference'
|
||||
|
||||
constructor(public referencedId: string) {}
|
||||
}
|
||||
|
||||
export interface IBase {
|
||||
readonly speckle_type: string
|
||||
}
|
||||
|
||||
export interface ITransport {
|
||||
SaveObject(id: string, object: Map<string, any>): Promise<void>
|
||||
}
|
||||
|
||||
export class SerializedBase {
|
||||
constructor(public id: string, public json: string) {}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
'use strict'
|
||||
Object.defineProperty(exports, '__esModule', { value: true })
|
||||
exports.ExcelSheetDataRetriever = void 0
|
||||
class ExcelSheetDataRetriever {
|
||||
// Takes address as a string formatted like this 'Sheet1!A1:B4' and returns a 2d array of values.
|
||||
// This queries the document in batches in order to avoid api errors about requests that are too large
|
||||
static async GetValuesAsNestedList(context, address) {
|
||||
const sheetName = address.split('!')[0].replace(/'/g, '')
|
||||
const rangeAddress = address.split('!')[1]
|
||||
const sheet = context.workbook.worksheets.getItem(sheetName)
|
||||
const totalRange = sheet.getRange(rangeAddress)
|
||||
totalRange.load('columnCount, columnIndex, rowCount, rowIndex')
|
||||
await context.sync()
|
||||
let numRowsRetrieved = 0
|
||||
const chunkSize = 5000
|
||||
let values = []
|
||||
while (numRowsRetrieved < totalRange.rowCount) {
|
||||
const numRowsToRetrieve = Math.min(chunkSize, totalRange.rowCount - numRowsRetrieved)
|
||||
const currentRange = sheet.getRangeByIndexes(
|
||||
totalRange.rowIndex + numRowsRetrieved,
|
||||
totalRange.columnIndex,
|
||||
numRowsToRetrieve,
|
||||
totalRange.columnCount
|
||||
)
|
||||
currentRange.load('values')
|
||||
await context.sync()
|
||||
values = values.concat(currentRange.values)
|
||||
numRowsRetrieved += numRowsToRetrieve
|
||||
}
|
||||
return values
|
||||
}
|
||||
}
|
||||
exports.ExcelSheetDataRetriever = ExcelSheetDataRetriever
|
||||
@@ -0,0 +1,37 @@
|
||||
export class ExcelSheetDataRetriever {
|
||||
// Takes address as a string formatted like this 'Sheet1!A1:B4' and returns a 2d array of values.
|
||||
// This queries the document in batches in order to avoid api errors about requests that are too large
|
||||
static async GetValuesAsNestedList(
|
||||
context: Excel.RequestContext,
|
||||
address: string
|
||||
): Promise<any[][]> {
|
||||
const sheetName = address.split('!')[0].replace(/'/g, '')
|
||||
const rangeAddress = address.split('!')[1]
|
||||
const sheet = context.workbook.worksheets.getItem(sheetName)
|
||||
|
||||
const totalRange = sheet.getRange(rangeAddress)
|
||||
totalRange.load('columnCount, columnIndex, rowCount, rowIndex')
|
||||
await context.sync()
|
||||
|
||||
let numRowsRetrieved = 0
|
||||
const chunkSize = 5000
|
||||
let values: any[][] = []
|
||||
|
||||
while (numRowsRetrieved < totalRange.rowCount) {
|
||||
const numRowsToRetrieve = Math.min(chunkSize, totalRange.rowCount - numRowsRetrieved)
|
||||
const currentRange = sheet.getRangeByIndexes(
|
||||
totalRange.rowIndex + numRowsRetrieved,
|
||||
totalRange.columnIndex,
|
||||
numRowsToRetrieve,
|
||||
totalRange.columnCount
|
||||
)
|
||||
currentRange.load('values')
|
||||
await context.sync()
|
||||
values = values.concat(currentRange.values)
|
||||
|
||||
numRowsRetrieved += numRowsToRetrieve
|
||||
}
|
||||
|
||||
return values
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
'use strict'
|
||||
Object.defineProperty(exports, '__esModule', { value: true })
|
||||
exports.ServerTransport = void 0
|
||||
class ServerTransport {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
constructor(serverUrl, token, streamId) {
|
||||
this.serverUrl = serverUrl
|
||||
this.token = token
|
||||
this.streamId = streamId
|
||||
}
|
||||
async SaveObject(id, map) {
|
||||
const query = `mutation objectCreate ($object: ObjectCreateInput!) {objectCreate(objectInput: $object)}`
|
||||
await fetch(`${this.serverUrl}/graphql`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: 'Bearer ' + this.token,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: query,
|
||||
variables: {
|
||||
object: {
|
||||
streamId: this.streamId,
|
||||
objects: [Object.fromEntries(map)]
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
// const data = (await response.json()) as any
|
||||
}
|
||||
async CreateCommit(branchName, objectId, message) {
|
||||
const query = `mutation commitCreate($myCommit: CommitCreateInput!){ commitCreate(commit: $myCommit)}`
|
||||
await fetch(`${this.serverUrl}/graphql`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: 'Bearer ' + this.token,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: query,
|
||||
variables: {
|
||||
myCommit: {
|
||||
streamId: this.streamId,
|
||||
branchName: branchName,
|
||||
objectId: objectId,
|
||||
message: message ? message : 'Data from Excel',
|
||||
sourceApplication: 'excel'
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
// const data = (await response.json()) as any
|
||||
}
|
||||
}
|
||||
exports.ServerTransport = ServerTransport
|
||||
@@ -0,0 +1,57 @@
|
||||
import { ITransport } from './BaseObjectSerializer'
|
||||
|
||||
export class ServerTransport implements ITransport {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
constructor(private serverUrl: string, private token: string, private streamId: string) {}
|
||||
|
||||
async SaveObject(id: string, map: Map<string, any>): Promise<void> {
|
||||
const query = `mutation objectCreate ($object: ObjectCreateInput!) {objectCreate(objectInput: $object)}`
|
||||
|
||||
await fetch(`${this.serverUrl}/graphql`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: 'Bearer ' + this.token,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: query,
|
||||
variables: {
|
||||
object: {
|
||||
streamId: this.streamId,
|
||||
objects: [Object.fromEntries(map)]
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// const data = (await response.json()) as any
|
||||
}
|
||||
|
||||
async CreateCommit(branchName: string, objectId: string, message: string | null) {
|
||||
const query = `mutation commitCreate($myCommit: CommitCreateInput!){ commitCreate(commit: $myCommit)}`
|
||||
|
||||
await fetch(`${this.serverUrl}/graphql`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: 'Bearer ' + this.token,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: query,
|
||||
variables: {
|
||||
myCommit: {
|
||||
streamId: this.streamId,
|
||||
branchName: branchName,
|
||||
objectId: objectId,
|
||||
message: message ? message : 'Data from Excel',
|
||||
sourceApplication: 'excel'
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// const data = (await response.json()) as any
|
||||
}
|
||||
}
|
||||
+10
-9
@@ -11,6 +11,7 @@ import {
|
||||
onTableChanged,
|
||||
onTableDeleted
|
||||
} from './dataTable.js'
|
||||
import { ExcelSheetDataRetriever } from './ExcelSheetDataRetreiver.js'
|
||||
|
||||
const unflatten = require('flat').unflatten
|
||||
|
||||
@@ -214,7 +215,7 @@ export function hideRowOrColumn(sheet, columnIndex = -1, rowIndex = -1) {
|
||||
}
|
||||
}
|
||||
|
||||
async function addIdDataToObjectData() {
|
||||
async function addIdDataToObjectData(arrayData) {
|
||||
if (
|
||||
arrayData.length != arrayIdData.length ||
|
||||
arrayData.length <= 1 ||
|
||||
@@ -599,14 +600,13 @@ export async function bake(
|
||||
} else if (previousHeaders) {
|
||||
selectedHeaders = filterArrayData(previousHeaders, arrayData)
|
||||
}
|
||||
|
||||
console.log(arrayData)
|
||||
}
|
||||
|
||||
if (signal.aborted) return
|
||||
|
||||
await addIdDataToObjectData()
|
||||
await bakeArray(arrayData, rowStart, colStart, context)
|
||||
selectedHeaders ??= arrayData
|
||||
await addIdDataToObjectData(selectedHeaders)
|
||||
await bakeArray(selectedHeaders, rowStart, colStart, context)
|
||||
}
|
||||
|
||||
await context.sync()
|
||||
@@ -668,11 +668,12 @@ export async function send(savedStream, streamId, branchName, message) {
|
||||
let sheetName = savedStream.selection.split('!')[0].replace(/'/g, '')
|
||||
let rangeAddress = savedStream.selection.split('!')[1]
|
||||
let sheet = context.workbook.worksheets.getItem(sheetName)
|
||||
|
||||
let range = sheet.getRange(rangeAddress)
|
||||
range.load('values')
|
||||
await context.sync()
|
||||
let values = range.values
|
||||
|
||||
let values = await ExcelSheetDataRetriever.GetValuesAsNestedList(
|
||||
context,
|
||||
savedStream.selection
|
||||
)
|
||||
|
||||
let data = []
|
||||
// check for specific conversion
|
||||
|
||||
+58
-42
@@ -6,6 +6,8 @@ import ObjectLoader from '@speckle/objectloader'
|
||||
import streamsModule from './streams'
|
||||
import userModule from './user'
|
||||
import router from '../router'
|
||||
import { BaseObjectSerializer } from '../plugins/BaseObjectSerializer'
|
||||
import { ServerTransport } from '../plugins/ServerTransport'
|
||||
|
||||
const xml2js = require('xml2js')
|
||||
|
||||
@@ -100,7 +102,8 @@ const vuexExcel = new VuexPersistence({
|
||||
|
||||
export default new Vuex.Store({
|
||||
state: {
|
||||
snackbar: {}
|
||||
snackbar: {},
|
||||
isFE2: false
|
||||
},
|
||||
plugins: [vuexLocal.plugin, vuexExcel.plugin],
|
||||
getters: {
|
||||
@@ -109,9 +112,16 @@ export default new Vuex.Store({
|
||||
mutations: {
|
||||
SET_SNACKBAR(state, value) {
|
||||
state.snackbar = value
|
||||
},
|
||||
UPDATE_IS_FE2(state, value) {
|
||||
localStorage.setItem('frontend2', value)
|
||||
state.isFE2 = value
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
updateIsFE2({ commit }, value) {
|
||||
commit('UPDATE_IS_FE2', value)
|
||||
},
|
||||
async redirect(_, data) {
|
||||
//go to login and refresh token
|
||||
window.location = `${data.serverUrl}/authn/verify/${process.env.VUE_APP_SPECKLE_ID}/${data.challenge}`
|
||||
@@ -140,11 +150,13 @@ export default new Vuex.Store({
|
||||
dialog.close()
|
||||
await dispatch('exchangeAccessCode', args.message)
|
||||
await dispatch('hasValidToken')
|
||||
await dispatch('getServerInfo')
|
||||
router.push('/')
|
||||
})
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
async hasValidToken({ state, dispatch }) {
|
||||
if (localStorage.getItem(TOKEN) === null) return false
|
||||
await dispatch('getUser')
|
||||
@@ -161,6 +173,7 @@ export default new Vuex.Store({
|
||||
localStorage.removeItem('serverUrl')
|
||||
localStorage.removeItem(REFRESH_TOKEN)
|
||||
localStorage.removeItem('uuid')
|
||||
localStorage.removeItem('frontend2')
|
||||
|
||||
window.location = window.location.origin
|
||||
},
|
||||
@@ -193,51 +206,14 @@ export default new Vuex.Store({
|
||||
}
|
||||
},
|
||||
async createCommit(context, { streamId, branchName, message, object }) {
|
||||
let query = `mutation objectCreate ($object: ObjectCreateInput!) {objectCreate(objectInput: $object)}`
|
||||
|
||||
let serverUrl = localStorage.getItem('serverUrl')
|
||||
let token = localStorage.getItem(TOKEN)
|
||||
|
||||
let response = await fetch(`${serverUrl}/graphql`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: 'Bearer ' + token,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: query,
|
||||
variables: {
|
||||
object: {
|
||||
streamId: streamId,
|
||||
objects: [object]
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
let data = await response.json()
|
||||
let objectId = data.data.objectCreate[0]
|
||||
const serverTransport = new ServerTransport(serverUrl, token, streamId)
|
||||
const serializer = new BaseObjectSerializer([serverTransport])
|
||||
const serialized = await serializer.SerializeBase(object)
|
||||
|
||||
query = `mutation commitCreate($myCommit: CommitCreateInput!){ commitCreate(commit: $myCommit)}`
|
||||
|
||||
response = await fetch(`${serverUrl}/graphql`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: 'Bearer ' + token,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: query,
|
||||
variables: {
|
||||
myCommit: {
|
||||
streamId: streamId,
|
||||
branchName: branchName,
|
||||
objectId: objectId,
|
||||
message: message ? message : 'Data from Excel',
|
||||
sourceApplication: 'excel'
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
await serverTransport.CreateCommit(branchName, serialized.id, message)
|
||||
},
|
||||
async receiveCommit(context, { sourceApplication, streamId, commitId, message }) {
|
||||
let query = `mutation objectReceive ($myInput:CommitReceivedInput!) {commitReceive(input:$myInput)}`
|
||||
@@ -264,6 +240,46 @@ export default new Vuex.Store({
|
||||
})
|
||||
})
|
||||
},
|
||||
async getServerInfo({ dispatch }) {
|
||||
let serverUrl = localStorage.getItem('serverUrl')
|
||||
|
||||
// Now, to check for a specific header
|
||||
const isFrontend2Server = (headers) => {
|
||||
const HEADER = 'x-speckle-frontend-2'
|
||||
const headerValue = headers.get(HEADER)
|
||||
|
||||
if (headerValue === null) {
|
||||
return false
|
||||
}
|
||||
|
||||
const value = headerValue.toLowerCase() === 'true'
|
||||
if (headerValue !== 'true' && headerValue !== 'false') {
|
||||
throw new Error(
|
||||
`Headers contained ${HEADER} header, but value ${headerValue} could not be parsed to a bool`
|
||||
)
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
// Use the function to check the header
|
||||
try {
|
||||
let response = await fetch(serverUrl, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
|
||||
let isFE2Server = isFrontend2Server(response.headers)
|
||||
await dispatch('updateIsFE2', isFE2Server)
|
||||
console.log('Is Frontend2 Server:', isFE2Server)
|
||||
} catch (error) {
|
||||
console.warn(error.message)
|
||||
// TODO: fallback is FE1, this should be changed later
|
||||
await dispatch('updateIsFE2', false)
|
||||
}
|
||||
},
|
||||
async getUser(context) {
|
||||
try {
|
||||
let query = `query {
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
require('url')
|
||||
|
||||
export class StreamWrapper {
|
||||
constructor(streamIdOrUrl, accountId, serverUrl) {
|
||||
constructor(streamIdOrUrl, accountId, serverUrl, isFE2) {
|
||||
this.isFE2 = isFE2
|
||||
this.streamsKey = this.isFE2 ? 'projects/' : 'streams/'
|
||||
this.branchesKey = this.isFE2 ? 'models/' : 'branches/'
|
||||
this.commitsKey = this.isFE2 ? 'versions/' : 'commits/'
|
||||
this.originalOutput = streamIdOrUrl
|
||||
try {
|
||||
this.streamWrapperFromUrl(streamIdOrUrl)
|
||||
@@ -12,12 +16,17 @@ export class StreamWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
matchUrl(streamUrl) {
|
||||
const fe2UrlRegex = /\/projects\/(?<projectId>[\w\d]+)(?:\/models\/(?<model>[\w\d]+(?:@[\w\d]+)?)(?:,(?<additionalModels>[\w\d]+(?:@[\w\d]+)?))*)?/
|
||||
return fe2UrlRegex.exec(streamUrl)
|
||||
}
|
||||
|
||||
streamWrapperFromUrl(streamUrl) {
|
||||
this.url = new URL(streamUrl)
|
||||
this.segments = this.url.pathname.split('/').map((segment) => segment + '/')
|
||||
this.serverUrl = this.url.origin
|
||||
|
||||
if (this.segments.length >= 4 && this.segments[3]?.toLowerCase() === 'branches/') {
|
||||
if (this.segments.length >= 4 && this.segments[3]?.toLowerCase() === this.branchesKey) {
|
||||
this.streamId = this.segments[2].replace('/', '')
|
||||
if (this.segments.length > 5) {
|
||||
let branchSegments = this.segments.slice(4, this.segments.length - 1)
|
||||
@@ -28,7 +37,7 @@ export class StreamWrapper {
|
||||
} else {
|
||||
switch (this.segments.length) {
|
||||
case 3: // ie http://speckle.server/streams/8fecc9aa6d
|
||||
if (this.segments[1].toLowerCase() === 'streams/')
|
||||
if (this.segments[1].toLowerCase() === this.streamsKey)
|
||||
this.streamId = this.segments[2].replace('/', '')
|
||||
else throw new Error(`Cannot parse ${this.originalOutput} into a stream wrapper class`)
|
||||
break
|
||||
@@ -40,7 +49,7 @@ export class StreamWrapper {
|
||||
break
|
||||
case 5: // ie http://speckle.server/streams/8fecc9aa6d/commits/76a23d7179
|
||||
switch (this.segments[3].toLowerCase()) {
|
||||
case 'commits/':
|
||||
case this.commitsKey:
|
||||
this.streamId = this.segments[2].replace('/', '')
|
||||
this.commitId = this.segments[4].replace('/', '')
|
||||
break
|
||||
@@ -49,7 +58,7 @@ export class StreamWrapper {
|
||||
this.branchName = this.segments[3].replace('/', '')
|
||||
this.commitId = this.segments[4].replace('/', '')
|
||||
break
|
||||
case 'branches/':
|
||||
case this.branchesKey:
|
||||
this.streamId = this.segments[2].replace('/', '')
|
||||
this.branchName = this.segments[4].replace('/', '')
|
||||
break
|
||||
|
||||
+3
-3
@@ -43,7 +43,9 @@ export default {
|
||||
name: 'Login',
|
||||
data: () => ({
|
||||
serverUrl:
|
||||
process.env.NODE_ENV === 'development' ? 'https://latest.speckle.dev' : 'https://speckle.xyz',
|
||||
process.env.NODE_ENV === 'development'
|
||||
? 'https://latest.speckle.systems'
|
||||
: 'https://app.speckle.systems',
|
||||
validForm: true,
|
||||
serverError: '',
|
||||
serverUrlRules: [
|
||||
@@ -53,8 +55,6 @@ export default {
|
||||
'URL must be valid, with no trailing slash'
|
||||
]
|
||||
}),
|
||||
mounted() {},
|
||||
|
||||
methods: {
|
||||
async login() {
|
||||
//when for is not visible (coming from web) don't validate
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
small
|
||||
icon
|
||||
color="primary"
|
||||
:href="`${serverUrl}/streams/${savedStream.id}`"
|
||||
:href="`${serverUrl}/${$store.state.isFE2 ? 'projects' : 'streams'}/${savedStream.id}`"
|
||||
target="_blank"
|
||||
>
|
||||
<v-icon small>mdi-open-in-new</v-icon>
|
||||
@@ -127,13 +127,15 @@ export default {
|
||||
}
|
||||
},
|
||||
apollo: {
|
||||
$client: createClient(),
|
||||
stream: {
|
||||
prefetch: true,
|
||||
query: streamQuery,
|
||||
fetchPolicy: 'network-only',
|
||||
variables() {
|
||||
return {
|
||||
id: this.streamId
|
||||
id: this.streamId,
|
||||
limit: 100
|
||||
}
|
||||
},
|
||||
result() {
|
||||
@@ -178,7 +180,6 @@ export default {
|
||||
console.log(this.error)
|
||||
}
|
||||
},
|
||||
$client: createClient(),
|
||||
$subscribe: {
|
||||
streamUpdated: {
|
||||
query: gql`
|
||||
@@ -423,7 +424,7 @@ export default {
|
||||
speckleIdRange.load('text')
|
||||
await context.sync()
|
||||
|
||||
let idsInViewer = new Array()
|
||||
let idsInViewer = []
|
||||
for (let i = 0; i < speckleIdRange.text?.length; i++) {
|
||||
for (let j = 0; j < speckleIdRange.text[i].length; j++) {
|
||||
if (speckleIdRange.text[i][j].length < 32) continue
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<v-container>
|
||||
<v-container class="pa-0">
|
||||
<v-row align="center">
|
||||
<v-col cols="12" align="center" class="mt-5">
|
||||
<v-col cols="12" align="center" class="mt-3">
|
||||
<p v-if="search" class="subtitle">No streams found 🧐</p>
|
||||
<div v-else-if="!$apollo.loading && filteredStreams && filteredStreams.length == 0">
|
||||
<p class="subtitle">
|
||||
@@ -122,7 +122,6 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
isAuthenticated() {
|
||||
console.log(this.user)
|
||||
return this.$store.getters.isAuthenticated
|
||||
},
|
||||
user() {
|
||||
@@ -132,7 +131,6 @@ export default {
|
||||
return this.$store.getters.serverUrl
|
||||
},
|
||||
filteredStreams() {
|
||||
console.log('user', this.$store.state.user.user)
|
||||
if (!this.streams.items) return null
|
||||
|
||||
let savedStreams = this.streams.items.filter(
|
||||
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||
|
||||
/* Projects */
|
||||
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
|
||||
/* Language and Environment */
|
||||
"target": "es2021" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
|
||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
||||
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||
|
||||
/* Modules */
|
||||
"module": "commonjs" /* Specify what module code is generated. */,
|
||||
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
||||
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
|
||||
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
|
||||
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
|
||||
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
|
||||
// "resolveJsonModule": true, /* Enable importing .json files. */
|
||||
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
|
||||
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
||||
|
||||
/* JavaScript Support */
|
||||
// "allowJs": true /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */,
|
||||
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
||||
|
||||
/* Emit */
|
||||
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
||||
// "outDir": "./", /* Specify an output folder for all emitted files. */
|
||||
// "removeComments": true, /* Disable emitting comments. */
|
||||
// "noEmit": true, /* Disable emitting files from a compilation. */
|
||||
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
|
||||
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
|
||||
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
|
||||
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
|
||||
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||
|
||||
/* Interop Constraints */
|
||||
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
|
||||
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
|
||||
|
||||
/* Type Checking */
|
||||
"strict": true /* Enable all strict type-checking options. */,
|
||||
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
||||
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
||||
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
|
||||
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
||||
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
|
||||
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
||||
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
|
||||
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||
|
||||
/* Completeness */
|
||||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user