1 Commits

Author SHA1 Message Date
Alan Rynne 1762205e67 Removed implementations for class demo 2021-11-04 15:45:24 +01:00
8 changed files with 68 additions and 170 deletions
+1 -14
View File
@@ -55,7 +55,7 @@ The app was built using `Vue.js`, and communicates with Speckle through our `Gra
The `server/` folder contains all code related to the app's backend. The `server/` folder contains all code related to the app's backend.
We're using a [FastAPI](https://link) API framework with a Uvicorn server implementation, written in Python, as well as our Python SDK to communicate with the [public Speckle server](https://speckle.xyz). The server contains two basic routes: We're using a [FastAPI](https://link) server, written in Python, as well as our Python SDK to communicate with the [public Speckle server](https://speckle.xyz). The server contains two basic routes:
- **`diff-check/STREAM_ID/CURRENT_COMMIT_ID/PREV_COMMIT_ID`** - **`diff-check/STREAM_ID/CURRENT_COMMIT_ID/PREV_COMMIT_ID`**
@@ -94,12 +94,6 @@ Some basic familiarity with python, POST requests, and API routing is recommende
``` ```
*If you're experiencing pip install issues, check that you are running these commands as an administrator!* *If you're experiencing pip install issues, check that you are running these commands as an administrator!*
To deploy the server, open a command window in VSCode and navigate to your server folder. Run:
```shell
uvicorn main:app --reload
```
## Frontend walkthrough requirements ## Frontend walkthrough requirements
Some basic familiarity with JS and the Vue framework is recommended. Some basic familiarity with JS and the Vue framework is recommended.
@@ -108,13 +102,6 @@ Some basic familiarity with JS and the Vue framework is recommended.
- Install `vue CLI` - [Instructions here](https://cli.vuejs.org/guide/installation.html) - Install `vue CLI` - [Instructions here](https://cli.vuejs.org/guide/installation.html)
- Install `vue dev tools` for Chrome [here](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd) - Install `vue dev tools` for Chrome [here](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd)
To deploy the server, open a command window in VSCode and navigate to your frontend folder. Run:
```shell
npm install
npm run serve
```
## App testing requirements ## App testing requirements
We're using [Rhino 7](https://www.rhino3d.com/download/), Grasshopper for Rhino, and Revit 2021 for our 3D model comparisons. You can We're using [Rhino 7](https://www.rhino3d.com/download/), Grasshopper for Rhino, and Revit 2021 for our 3D model comparisons. You can
@@ -72,42 +72,17 @@ export default {
} }
}, },
methods: { methods: {
toggleDiffView(){
this.$emit("update:showDiff", !this.showDiff)
},
async doesDiffExist(){ async doesDiffExist(){
if(!this.currentCommit || !this.prevCommit) return { commit: null } console.log("Checking if diff exists...")
var backendUrl = process.env.VUE_APP_BACKEND_URL // TODO: Missing implementation
var diffUrl = `${backendUrl}/diff_check/${this.$route.params.id}/${this.currentCommit.id}/${this.prevCommit.id}` return { commit: null }
var res = await fetch(diffUrl, {
headers: {
method: "GET",
Authorisation: `Bearer ${localStorage.getItem(TOKEN)}`,
"Content-type": "application/json",
"Access-Control-Allow-Origin": "*"
}
})
return await res.json()
}, },
async requestDiff() { async requestDiff() {
this.loading = true console.log("Requesting diff...")
var backendUrl = process.env.VUE_APP_BACKEND_URL // TODO: Missing implementation
console.log("diff requested for", this.currentCommit.id, this.prevCommit.id) },
var diffUrl = `${backendUrl}/diff/${this.$route.params.id}/${this.currentCommit.id}/${this.prevCommit.id}` toggleDiffView(){
var res = await fetch(diffUrl, { this.$emit("update:showDiff", !this.showDiff)
headers: {
method: "GET",
Authorisation: `Bearer ${localStorage.getItem(TOKEN)}`,
"Content-type": "application/json",
"Access-Control-Allow-Origin": "*"
}
})
if(res.status == 200){
var body = await res.json()
console.log("diff body", res, body)
this.$emit("update:diffCommit", body.commit)
}
this.loading = false
}, },
async handleCommitChange(event, value){ async handleCommitChange(event, value){
this.loading = true this.loading = true
+2 -11
View File
@@ -14,17 +14,7 @@ const routes = [
component: Home, component: Home,
meta: { meta: {
requiresAuth: true, requiresAuth: true,
title: "Speckle AEC Tech Masterclass", title: "Speckle AEC Tech Masterclass"
metaTags: [
{
name: "description",
content: "The Speckle AEC Tech Masterclass homepage"
},
{
property: "og:description",
content: "The Speckle AEC Tech Masterclass homepage"
}
]
} }
}, },
{ {
@@ -57,6 +47,7 @@ router.beforeEach(async (to, from, next) => {
if (to.meta.title) { if (to.meta.title) {
document.title = to.meta.title document.title = to.meta.title
} }
if (to.query.access_code) { if (to.query.access_code) {
// If the route contains an access code, exchange it // If the route contains an access code, exchange it
try { try {
+12 -13
View File
@@ -1,16 +1,5 @@
export const userInfoQuery = ` // TODO: Write user + server info query
query { export const userInfoQuery = ``
user {
name
id
avatar
email
},
serverInfo {
name
company
}
}`
export const streamCommitsQuery = ` export const streamCommitsQuery = `
query($id: String!, $limit: Int, $cursor: String) { query($id: String!, $limit: Int, $cursor: String) {
@@ -50,6 +39,16 @@ export const streamSearchQuery = `
} }
}` }`
export const streamObjectQuery = `query($streamId: String!, $objectId: String!) {
stream(id: $streamId){
object(id: $objectId){
totalChildrenCount
id
speckleType
data
}
}
}`
export const latestStreamsQuery = `query { export const latestStreamsQuery = `query {
streams(limit: 10){ streams(limit: 10){
cursor cursor
+30 -47
View File
@@ -4,7 +4,7 @@ import {
streamObjectQuery, streamObjectQuery,
streamSearchQuery, streamSearchQuery,
userInfoQuery userInfoQuery
} from "@/speckleQueries"; } from "@/speckleQueries"
export const APP_NAME = process.env.VUE_APP_SPECKLE_NAME export const APP_NAME = process.env.VUE_APP_SPECKLE_NAME
export const SERVER_URL = process.env.VUE_APP_SERVER_URL export const SERVER_URL = process.env.VUE_APP_SERVER_URL
@@ -14,43 +14,21 @@ export const CHALLENGE = `${APP_NAME}.Challenge`
// Redirects to the Speckle server authentication page, using a randomly generated challenge. Challenge will be stored to compare with when exchanging the access code. // Redirects to the Speckle server authentication page, using a randomly generated challenge. Challenge will be stored to compare with when exchanging the access code.
export function goToSpeckleAuthPage() { export function goToSpeckleAuthPage() {
// Generate random challenge console.log("Redirecting to Speckle Auth page...")
var challenge = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15) // TODO: Missing implementation
// Save challenge in localStorage
localStorage.setItem(CHALLENGE, challenge)
// Send user to auth page
window.location = `${SERVER_URL}/authn/verify/${process.env.VUE_APP_SPECKLE_ID}/${challenge}`
} }
// Log out the current user. This removes the token/refreshToken pair. // Log out the current user. This removes the token/refreshToken pair.
export function speckleLogOut() { export function speckleLogOut() {
// Remove both token and refreshToken from localStorage // Remove both token and refreshToken from localStorage
localStorage.removeItem(TOKEN) console.log("Logging out user")
localStorage.removeItem(REFRESH_TOKEN) // TODO: Missing implementation
} }
// Exchanges the provided access code with a token/refreshToken pair, and saves them to local storage. // Exchanges the provided access code with a token/refreshToken pair, and saves them to local storage.
export async function exchangeAccessCode(accessCode) { export async function exchangeAccessCode(accessCode) {
var res = await fetch(`${SERVER_URL}/auth/token/`, { console.log("Exchanging access code...")
method: 'POST', // TODO: Missing implementation
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
accessCode: accessCode,
appId: process.env.VUE_APP_SPECKLE_ID,
appSecret: process.env.VUE_APP_SPECKLE_SECRET,
challenge: localStorage.getItem(CHALLENGE)
})
})
var data = await res.json()
if (data.token) {
// If retrieving the token was successful, remove challenge and set the new token and refresh token
localStorage.removeItem(CHALLENGE)
localStorage.setItem(TOKEN, data.token)
localStorage.setItem(REFRESH_TOKEN, data.refreshToken)
}
return data
} }
// Calls the GraphQL endpoint of the Speckle server with a specific query. // Calls the GraphQL endpoint of the Speckle server with a specific query.
@@ -58,36 +36,41 @@ export async function speckleFetch(query, vars) {
let token = localStorage.getItem(TOKEN) let token = localStorage.getItem(TOKEN)
if (token) if (token)
try { try {
var res = await fetch( var res = await fetch(`${SERVER_URL}/graphql`, {
`${SERVER_URL}/graphql`, method: "POST",
{ headers: {
method: 'POST', Authorization: "Bearer " + token,
headers: { "Content-Type": "application/json"
'Authorization': 'Bearer ' + token, },
'Content-Type': 'application/json' body: JSON.stringify({
}, query: query,
body: JSON.stringify({ variables: vars || null
query: query,
variables: vars || null
})
}) })
})
return await res.json() return await res.json()
} catch (err) { } catch (err) {
console.error("API call failed", err) console.error("API call failed", err)
} }
else else return Promise.reject("You are not logged in (token does not exist)")
return Promise.reject("You are not logged in (token does not exist)")
} }
// Fetch the current user data using the userInfoQuery // Fetch the current user data using the userInfoQuery
export const getUserData = () => speckleFetch(userInfoQuery) export const getUserData = () => speckleFetch(userInfoQuery)
// Fetch for streams matching the specified text using the streamSearchQuery // Fetch for streams matching the specified text using the streamSearchQuery
export const searchStreams = (e) => speckleFetch(streamSearchQuery, {searchText: e}) export const searchStreams = e =>
speckleFetch(streamSearchQuery, { searchText: e })
// Get commits related to a specific stream, allows for pagination by passing a cursor // Get commits related to a specific stream, allows for pagination by passing a cursor
export const getStreamCommits = (streamId, itemsPerPage, cursor) => speckleFetch(streamCommitsQuery, {id: streamId, cursor, limit: itemsPerPage}) export const getStreamCommits = (streamId, itemsPerPage, cursor) =>
speckleFetch(streamCommitsQuery, {
id: streamId,
cursor,
limit: itemsPerPage
})
export const getObject = (streamId, objectId) => speckleFetch(streamObjectQuery, {streamId, objectId}) export const getObject = (streamId, objectId) =>
speckleFetch(streamObjectQuery, { streamId, objectId })
export const getStreams = () => speckleFetch(latestStreamsQuery).then(res => res.data?.streams) export const getStreams = () =>
speckleFetch(latestStreamsQuery).then(res => res.data?.streams)
+5 -6
View File
@@ -1,24 +1,23 @@
import Vue from 'vue' import Vue from "vue"
import Vuex from 'vuex' import Vuex from "vuex"
import { import {
exchangeAccessCode, exchangeAccessCode,
getUserData, getUserData,
goToSpeckleAuthPage, goToSpeckleAuthPage,
speckleLogOut speckleLogOut
} from "@/speckleUtils"; } from "@/speckleUtils"
import router from "@/router"; import router from "@/router"
Vue.use(Vuex) Vue.use(Vuex)
export default new Vuex.Store({ export default new Vuex.Store({
state: { state: {
user: null, user: null,
serverInfo: null serverInfo: null
}, },
getters: { getters: {
isAuthenticated: (state) => state.user != null isAuthenticated: state => state.user != null
}, },
mutations: { mutations: {
setUser(state, user) { setUser(state, user) {
+6 -42
View File
@@ -1,37 +1,6 @@
<template lang="html"> <template lang="html">
<v-container fill-height fluid class="pa-0 grey lighten-3"> <v-container fill-height fluid class="pa-0 grey lighten-3">
<div class="float-center-top"> TODO: Code up the stream diff view!!!
<CommitPanel
v-if="stream"
:showDiff.sync="showDiff"
:diffCommit.sync="diffCommit"
:currentCommit.sync="currentCommit"
:prevCommit.sync="prevCommit"
:commits="stream.branch.commits.items"
/>
</div>
<v-row class="fill-height" no-gutters v-show="!showDiff">
<v-col cols="6">
<Renderer
:object-url="objectUrl(currentCommit)"
show-selection-helper
></Renderer>
</v-col>
<v-col cols="6">
<Renderer
:object-url="objectUrl(prevCommit)"
show-selection-helper
></Renderer>
</v-col>
</v-row>
<v-row class="fill-height" no-gutters>
<v-col fill-height :cols="12">
<Renderer
:object-url="objectUrl(diffCommit)"
show-selection-helper
></Renderer>
</v-col>
</v-row>
</v-container> </v-container>
</template> </template>
@@ -42,7 +11,7 @@ import CommitPanel from "@/components/commitSelector/CommitPanel.vue"
export default { export default {
name: "StreamView", name: "StreamView",
components: { Renderer, CommitPanel }, components: {},
data() { data() {
return { return {
stream: null, stream: null,
@@ -50,14 +19,11 @@ export default {
prevCommit: null, prevCommit: null,
diffCommit: null, diffCommit: null,
serverUrl: process.env.VUE_APP_SERVER_URL, serverUrl: process.env.VUE_APP_SERVER_URL,
showDiff: false, showDiff: false
loading: true
} }
}, },
async mounted() { async mounted() {
if (this.streamId) { //TODO: Get stream when mounting view
this.getStream()
}
}, },
computed: { computed: {
/** @return {string} */ /** @return {string} */
@@ -67,12 +33,10 @@ export default {
}, },
methods: { methods: {
async getStream() { async getStream() {
var res = await getStreamCommits(this.streamId, 10, null) //TODO: Missing implementation
this.stream = res.data.stream
}, },
objectUrl(commit) { objectUrl(commit) {
if (!commit) return null //TODO: Missing implementation
return `${this.serverUrl}/streams/${this.stream.id}/objects/${commit.referencedObject}`
} }
}, },
watch: { watch: {
+4 -4
View File
@@ -10,7 +10,8 @@ from specklepy.objects.geometry import Brep, Point, Mesh
from specklepy.objects import Base from specklepy.objects import Base
from specklepy.objects.other import RenderMaterial from specklepy.objects.other import RenderMaterial
COLORS = [-6426, -13108, -19790, -26215, -32640, -39322, -45747, -52429, -59111, -65536] COLORS = [-6426, -13108, -19790, -26215, -
32640, -39322, -45747, -52429, -59111, -65536]
WHITE = -1 WHITE = -1
@@ -69,8 +70,7 @@ class SpeckleMeshDiff:
"""Checks if a specific diff commit already exists in the diff_branch""" """Checks if a specific diff commit already exists in the diff_branch"""
branch_commits: Branch = self.client.branch.get( branch_commits: Branch = self.client.branch.get(
self.stream_id, self.diff_branch, 50) self.stream_id, self.diff_branch, 50)
if(branch_commits is None):
return None
for commit in branch_commits.commits.items: for commit in branch_commits.commits.items:
if commit.message == f"{self.commit_current}-{self.commit_prev}": if commit.message == f"{self.commit_current}-{self.commit_prev}":
return commit return commit
@@ -234,7 +234,7 @@ class SpeckleMeshDiff:
@staticmethod @staticmethod
def receive_data(client: SpeckleClient, stream_id: str, commit_id: str) -> Base: def receive_data(client: SpeckleClient, stream_id: str, commit_id: str) -> Base:
"""Get the data from a commit on the Speckle server""" """Get the data from a commit on the Speckle server"""
transport = ServerTransport(stream_id, client) transport = ServerTransport(client, stream_id)
commit = client.commit.get(stream_id, commit_id) commit = client.commit.get(stream_id, commit_id)
res = operations.receive(commit.referencedObject, transport) res = operations.receive(commit.referencedObject, transport)