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 @@ -