diff --git a/.vscode/settings.json b/.vscode/settings.json
index 59f74348e..c5090157f 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,91 +1,82 @@
{
- "window.openFilesInNewWindow": "off",
- "explorer.confirmDelete": false,
- // "[vue]": {
- // "editor.formatOnSave": true,
- // },
- "files.associations": {
- "*.vue": "vue"
+ "window.openFilesInNewWindow": "off",
+ "explorer.confirmDelete": false,
+ // "[vue]": {
+ // "editor.formatOnSave": true,
+ // },
+ "files.associations": {
+ "*.vue": "vue"
+ },
+ "editor.formatOnPaste": true,
+ "editor.multiCursorModifier": "ctrlCmd",
+ "editor.snippetSuggestions": "top",
+ "eslint.format.enable": true,
+ "editor.formatOnSave": true,
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": true
+ },
+ "[javascript]": {
+ "editor.defaultFormatter": "dbaeumer.vscode-eslint"
+ },
+ "[jsonc]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "vetur.format.defaultFormatterOptions": {
+ "js-beautify-html": {
+ "wrap_attributes": "force-expand-multiline"
},
- "editor.formatOnPaste": true,
- "editor.multiCursorModifier": "ctrlCmd",
- "editor.snippetSuggestions": "top",
- "workbench.colorTheme": "Monokai",
- "eslint.format.enable": true,
- "editor.formatOnSave": true,
- "editor.codeActionsOnSave": {
- "source.fixAll.eslint": true
- },
- "[javascript]": {
- "editor.defaultFormatter": "dbaeumer.vscode-eslint"
- },
- "[jsonc]": {
- "editor.defaultFormatter": "esbenp.prettier-vscode"
- },
- "vetur.format.defaultFormatterOptions": {
- "js-beautify-html": {
- "wrap_attributes": "force-expand-multiline"
- },
- "prettyhtml": {
- "printWidth": 100,
- "singleQuote": false,
- "wrapAttributes": false,
- "sortAttributes": false
- }
- },
- "cSpell.enableFiletypes": [
- "vue-html",
- "vue-postcss"
- ],
- "[vue]": {
- "editor.defaultFormatter": "dbaeumer.vscode-eslint"
- },
- "cSpell.userWords": [
- "Matomo",
- "SUPPRESSMSGBOXES",
- "matomo"
- ],
- "[json]": {
- "editor.defaultFormatter": "esbenp.prettier-vscode"
+ "prettyhtml": {
+ "printWidth": 100,
+ "singleQuote": false,
+ "wrapAttributes": false,
+ "sortAttributes": false
}
-
- // "[javascript]": {
- // "editor.defaultFormatter": "dbaeumer.vscode-eslint"
- // },
- // "[jsonc]": {
- // "editor.defaultFormatter": "esbenp.prettier-vscode"
- // }
- // "eslint.codeAction.showDocumentation": {
- // "enable": true
- // },
- // "eslint.validate": ["vue"],
- // "[js]": {
- // "editor.defaultFormatter": "dbaeumer.vscode-eslint"
- // },
- // "vetur.format.defaultFormatterOptions": {
- // "prettier": {
- // // Prettier option here
- // "semi": false,
- // "trailingComma": "es5",
- // "tabWidth": 2,
- // "bracketSpacing": true,
- // "vueIndentScriptAndStyle": true,
- // "eslintIntegration": true
- // }
- // },
- // "[javascript]": {
- // "editor.defaultFormatter": "dbaeumer.vscode-eslint"
- // },
- // "[vue]": {
- // //"editor.defaultFormatter": "octref.vetur"
- // "editor.defaultFormatter": "dbaeumer.vscode-eslint"
- // },
- // "cSpell.userWords": [
- // "vetur",
- // "vuetify"
- // ],
- // "[jsonc]": {
- // "editor.defaultFormatter": "esbenp.prettier-vscode"
- // }
+ },
+ "cSpell.enableFiletypes": ["vue-html", "vue-postcss"],
+ "[vue]": {
+ "editor.defaultFormatter": "dbaeumer.vscode-eslint"
+ },
+ "cSpell.userWords": ["Matomo", "SUPPRESSMSGBOXES", "matomo"],
+ "[json]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
}
-
\ No newline at end of file
+
+ // "[javascript]": {
+ // "editor.defaultFormatter": "dbaeumer.vscode-eslint"
+ // },
+ // "[jsonc]": {
+ // "editor.defaultFormatter": "esbenp.prettier-vscode"
+ // }
+ // "eslint.codeAction.showDocumentation": {
+ // "enable": true
+ // },
+ // "eslint.validate": ["vue"],
+ // "[js]": {
+ // "editor.defaultFormatter": "dbaeumer.vscode-eslint"
+ // },
+ // "vetur.format.defaultFormatterOptions": {
+ // "prettier": {
+ // // Prettier option here
+ // "semi": false,
+ // "trailingComma": "es5",
+ // "tabWidth": 2,
+ // "bracketSpacing": true,
+ // "vueIndentScriptAndStyle": true,
+ // "eslintIntegration": true
+ // }
+ // },
+ // "[javascript]": {
+ // "editor.defaultFormatter": "dbaeumer.vscode-eslint"
+ // },
+ // "[vue]": {
+ // //"editor.defaultFormatter": "octref.vetur"
+ // "editor.defaultFormatter": "dbaeumer.vscode-eslint"
+ // },
+ // "cSpell.userWords": [
+ // "vetur",
+ // "vuetify"
+ // ],
+ // "[jsonc]": {
+ // "editor.defaultFormatter": "esbenp.prettier-vscode"
+ // }
+}
diff --git a/packages/frontend/nginx/nginx.conf b/packages/frontend/nginx/nginx.conf
index 88f5c59c8..374c86c85 100644
--- a/packages/frontend/nginx/nginx.conf
+++ b/packages/frontend/nginx/nginx.conf
@@ -8,6 +8,11 @@ server {
try_files $uri $uri/ /app.html;
}
+ location /embed {
+ default_type text/html;
+ alias /usr/share/nginx/html/embedApp.html;
+ }
+
location ~ ^/streams/.* {
default_type text/html;
content_by_lua_block {
diff --git a/packages/frontend/public/embedApp.html b/packages/frontend/public/embedApp.html
new file mode 100644
index 000000000..f576e58b8
--- /dev/null
+++ b/packages/frontend/public/embedApp.html
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+
+
+
+
+ <%= htmlWebpackPlugin.options.title %>
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
\ No newline at end of file
diff --git a/packages/frontend/src/components/Renderer.vue b/packages/frontend/src/components/Renderer.vue
index 061b59fc9..3789abd95 100644
--- a/packages/frontend/src/components/Renderer.vue
+++ b/packages/frontend/src/components/Renderer.vue
@@ -352,9 +352,15 @@ export default {
async getPreviewImage(angle) {
angle = angle || 0
let previewUrl = this.objectUrl.replace('streams', 'preview') + '/' + angle
+ let token = undefined
+ try {
+ token = localStorage.getItem('AuthToken')
+ }catch (e) {
+ console.warn("Sanboxed mode, only public streams will fetch properly.")
+ }
const res = await fetch(previewUrl, {
- headers: localStorage.getItem('AuthToken')
- ? { Authorization: `Bearer ${localStorage.getItem('AuthToken')}` }
+ headers: token
+ ? { Authorization: `Bearer ${token}` }
: {}
})
const blob = await res.blob()
diff --git a/packages/frontend/src/embed/EmbedApp.vue b/packages/frontend/src/embed/EmbedApp.vue
new file mode 100644
index 000000000..9ed260791
--- /dev/null
+++ b/packages/frontend/src/embed/EmbedApp.vue
@@ -0,0 +1,8 @@
+
+
+
+
diff --git a/packages/frontend/src/embed/embedApp.js b/packages/frontend/src/embed/embedApp.js
new file mode 100644
index 000000000..0de4b582e
--- /dev/null
+++ b/packages/frontend/src/embed/embedApp.js
@@ -0,0 +1,11 @@
+import Vue from 'vue'
+import App from './EmbedApp.vue'
+import vuetify from './embedVuetify'
+import router from './embedRouter'
+Vue.config.productionTip = false
+
+new Vue({
+ router,
+ vuetify,
+ render: (h) => h(App)
+}).$mount('#app')
diff --git a/packages/frontend/src/embed/embedRouter.js b/packages/frontend/src/embed/embedRouter.js
new file mode 100644
index 000000000..15d4cb666
--- /dev/null
+++ b/packages/frontend/src/embed/embedRouter.js
@@ -0,0 +1,22 @@
+import Vue from 'vue'
+import VueRouter from 'vue-router'
+
+Vue.use(VueRouter)
+
+const routes = [
+ {
+ path: '*',
+ meta: {
+ title: 'Embed View | Speckle'
+ },
+ component: () => import('@/views/EmbedViewer.vue')
+ }
+]
+
+const router = new VueRouter({
+ mode: 'history',
+ // base: process.env.BASE_URL,
+ routes
+})
+
+export default router
diff --git a/packages/frontend/src/embed/embedVuetify.js b/packages/frontend/src/embed/embedVuetify.js
new file mode 100644
index 000000000..525f633f4
--- /dev/null
+++ b/packages/frontend/src/embed/embedVuetify.js
@@ -0,0 +1,39 @@
+import '@mdi/font/css/materialdesignicons.css'
+import Vue from 'vue'
+import Vuetify from 'vuetify/lib'
+
+Vue.use(Vuetify)
+
+let darkMediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
+export default new Vuetify({
+ icons: {
+ iconfont: 'mdi'
+ },
+ theme: {
+ options: { customProperties: true },
+ dark: darkMediaQuery ? 'dark' : null,
+ themes: {
+ light: {
+ primary: '#047EFB', //blue
+ secondary: '#7BBCFF', //light blue
+ accent: '#FCF25E', //yellow
+ error: '#FF5555', //red
+ warning: '#FF9100', //orange
+ info: '#313BCF', //dark blue
+ success: '#4caf50',
+ background: '#eeeeee',
+ text: '#FFFFFF'
+ },
+ dark: {
+ primary: '#047EFB', //blue
+ secondary: '#7BBCFF', //light blue
+ accent: '#FCF25E', //yellow
+ error: '#FF5555', //red
+ warning: '#FF9100', //orange
+ info: '#313BCF', //dark blue
+ success: '#4caf50',
+ background: '#3a3b3c'
+ }
+ }
+ }
+})
diff --git a/packages/frontend/src/embed/speckleQueries.js b/packages/frontend/src/embed/speckleQueries.js
new file mode 100644
index 000000000..94eb1320c
--- /dev/null
+++ b/packages/frontend/src/embed/speckleQueries.js
@@ -0,0 +1,44 @@
+import gql from "graphql-tag";
+
+export const serverInfoQuery = `
+ query ServerInfo {
+ serverInfo {
+ name
+ }
+ }
+`
+
+export const streamCommitQuery = `
+ query Stream($id: String!, $commit: String!) {
+ stream(id: $id) {
+ id
+ name
+ description
+ isPublic
+ commit(id: $commit) {
+ referencedObject
+ }
+ }
+ }
+`
+
+export const branchLastCommitQuery = `
+ query Stream($id: String!, $branch: String!) {
+ stream(id: $id) {
+ id
+ name
+ description
+ isPublic
+ branch(name: $branch) {
+ commits(limit: 1) {
+ totalCount
+ items {
+ referencedObject
+ }
+ }
+ }
+ }
+ }
+`
+
+
diff --git a/packages/frontend/src/embed/speckleUtils.js b/packages/frontend/src/embed/speckleUtils.js
new file mode 100644
index 000000000..afbda3932
--- /dev/null
+++ b/packages/frontend/src/embed/speckleUtils.js
@@ -0,0 +1,30 @@
+import {
+ branchLastCommitQuery,
+ serverInfoQuery,
+ streamCommitQuery
+} from "./speckleQueries.js";
+
+export let SERVER_URL = window.location.origin;
+
+// Unauthorised fetch, without token to prevent use of localStorage or exposing elsewhere.
+export async function speckleFetch(query, variables) {
+ try {
+ var res = await fetch(`${SERVER_URL}/graphql`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json"
+ },
+ body: JSON.stringify({
+ query: query,
+ variables: variables
+ })
+ });
+ return await res.json();
+ } catch (err) {
+ console.error("API call failed", err);
+ }
+}
+
+export const getServerInfo = () => speckleFetch(serverInfoQuery);
+export const getLatestBranchCommit = (id, branch) => speckleFetch(branchLastCommitQuery, { id, branch });
+export const getCommit = (id, commit) => speckleFetch(streamCommitQuery, { id, commit });
diff --git a/packages/frontend/src/router/index.js b/packages/frontend/src/router/index.js
index 373d7d64e..71a4bce92 100644
--- a/packages/frontend/src/router/index.js
+++ b/packages/frontend/src/router/index.js
@@ -239,11 +239,6 @@ const routes = [
},
component: () => import('@/views/GettingStartedView.vue')
},
- {
- path: '/embed',
- name: 'Embeded Viewer',
- component: () => import('@/views/EmbedViewer.vue')
- },
{
path: '*',
name: 'notfound',
diff --git a/packages/frontend/src/views/EmbedViewer.vue b/packages/frontend/src/views/EmbedViewer.vue
index 65fec73bb..711afd59f 100644
--- a/packages/frontend/src/views/EmbedViewer.vue
+++ b/packages/frontend/src/views/EmbedViewer.vue
@@ -1,4 +1,4 @@
-
+
@@ -87,9 +87,10 @@