Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 28aae5339e | |||
| df0428c71c | |||
| d16ac2ceae | |||
| 66f5f5c000 |
@@ -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.
|
||||
|
||||
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:
|
||||
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:
|
||||
|
||||
- **`diff-check/STREAM_ID/CURRENT_COMMIT_ID/PREV_COMMIT_ID`**
|
||||
|
||||
@@ -94,6 +94,12 @@ 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!*
|
||||
|
||||
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
|
||||
|
||||
Some basic familiarity with JS and the Vue framework is recommended.
|
||||
@@ -102,6 +108,13 @@ 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 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
|
||||
|
||||
We're using [Rhino 7](https://www.rhino3d.com/download/), Grasshopper for Rhino, and Revit 2021 for our 3D model comparisons. You can
|
||||
|
||||
@@ -72,18 +72,43 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async doesDiffExist(){
|
||||
console.log("Checking if diff exists...")
|
||||
// TODO: Missing implementation
|
||||
return { commit: null }
|
||||
},
|
||||
async requestDiff() {
|
||||
console.log("Requesting diff...")
|
||||
// TODO: Missing implementation
|
||||
},
|
||||
toggleDiffView(){
|
||||
this.$emit("update:showDiff", !this.showDiff)
|
||||
},
|
||||
async doesDiffExist(){
|
||||
if(!this.currentCommit || !this.prevCommit) return { commit: null }
|
||||
var backendUrl = process.env.VUE_APP_BACKEND_URL
|
||||
var diffUrl = `${backendUrl}/diff_check/${this.$route.params.id}/${this.currentCommit.id}/${this.prevCommit.id}`
|
||||
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() {
|
||||
this.loading = true
|
||||
var backendUrl = process.env.VUE_APP_BACKEND_URL
|
||||
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}`
|
||||
var res = await fetch(diffUrl, {
|
||||
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){
|
||||
this.loading = true
|
||||
this.$emit(event, value)
|
||||
|
||||
@@ -14,7 +14,17 @@ const routes = [
|
||||
component: Home,
|
||||
meta: {
|
||||
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"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -47,7 +57,6 @@ router.beforeEach(async (to, from, next) => {
|
||||
if (to.meta.title) {
|
||||
document.title = to.meta.title
|
||||
}
|
||||
|
||||
if (to.query.access_code) {
|
||||
// If the route contains an access code, exchange it
|
||||
try {
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
// TODO: Write user + server info query
|
||||
export const userInfoQuery = ``
|
||||
export const userInfoQuery = `
|
||||
query {
|
||||
user {
|
||||
name
|
||||
id
|
||||
avatar
|
||||
email
|
||||
},
|
||||
serverInfo {
|
||||
name
|
||||
company
|
||||
}
|
||||
}`
|
||||
|
||||
export const streamCommitsQuery = `
|
||||
query($id: String!, $limit: Int, $cursor: String) {
|
||||
@@ -39,16 +50,6 @@ 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 {
|
||||
streams(limit: 10){
|
||||
cursor
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
streamObjectQuery,
|
||||
streamSearchQuery,
|
||||
userInfoQuery
|
||||
} from "@/speckleQueries"
|
||||
} from "@/speckleQueries";
|
||||
|
||||
export const APP_NAME = process.env.VUE_APP_SPECKLE_NAME
|
||||
export const SERVER_URL = process.env.VUE_APP_SERVER_URL
|
||||
@@ -14,21 +14,43 @@ 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.
|
||||
export function goToSpeckleAuthPage() {
|
||||
console.log("Redirecting to Speckle Auth page...")
|
||||
// TODO: Missing implementation
|
||||
// Generate random challenge
|
||||
var challenge = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
|
||||
// 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.
|
||||
export function speckleLogOut() {
|
||||
// Remove both token and refreshToken from localStorage
|
||||
console.log("Logging out user")
|
||||
// TODO: Missing implementation
|
||||
localStorage.removeItem(TOKEN)
|
||||
localStorage.removeItem(REFRESH_TOKEN)
|
||||
}
|
||||
|
||||
// Exchanges the provided access code with a token/refreshToken pair, and saves them to local storage.
|
||||
export async function exchangeAccessCode(accessCode) {
|
||||
console.log("Exchanging access code...")
|
||||
// TODO: Missing implementation
|
||||
var res = await fetch(`${SERVER_URL}/auth/token/`, {
|
||||
method: 'POST',
|
||||
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.
|
||||
@@ -36,41 +58,36 @@ export async function speckleFetch(query, vars) {
|
||||
let token = localStorage.getItem(TOKEN)
|
||||
if (token)
|
||||
try {
|
||||
var res = await fetch(`${SERVER_URL}/graphql`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: "Bearer " + token,
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: query,
|
||||
variables: vars || null
|
||||
var res = await fetch(
|
||||
`${SERVER_URL}/graphql`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + token,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: query,
|
||||
variables: vars || null
|
||||
})
|
||||
})
|
||||
})
|
||||
return await res.json()
|
||||
} catch (err) {
|
||||
console.error("API call failed", err)
|
||||
}
|
||||
else return Promise.reject("You are not logged in (token does not exist)")
|
||||
else
|
||||
return Promise.reject("You are not logged in (token does not exist)")
|
||||
}
|
||||
|
||||
// Fetch the current user data using the userInfoQuery
|
||||
export const getUserData = () => speckleFetch(userInfoQuery)
|
||||
|
||||
// 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
|
||||
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)
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
import Vue from "vue"
|
||||
import Vuex from "vuex"
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
import {
|
||||
exchangeAccessCode,
|
||||
getUserData,
|
||||
goToSpeckleAuthPage,
|
||||
speckleLogOut
|
||||
} from "@/speckleUtils"
|
||||
import router from "@/router"
|
||||
} from "@/speckleUtils";
|
||||
import router from "@/router";
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
|
||||
export default new Vuex.Store({
|
||||
state: {
|
||||
user: null,
|
||||
serverInfo: null
|
||||
},
|
||||
getters: {
|
||||
isAuthenticated: state => state.user != null
|
||||
isAuthenticated: (state) => state.user != null
|
||||
},
|
||||
mutations: {
|
||||
setUser(state, user) {
|
||||
|
||||
@@ -1,6 +1,37 @@
|
||||
<template lang="html">
|
||||
<v-container fill-height fluid class="pa-0 grey lighten-3">
|
||||
TODO: Code up the stream diff view!!!
|
||||
<div class="float-center-top">
|
||||
<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>
|
||||
</template>
|
||||
|
||||
@@ -11,7 +42,7 @@ import CommitPanel from "@/components/commitSelector/CommitPanel.vue"
|
||||
|
||||
export default {
|
||||
name: "StreamView",
|
||||
components: {},
|
||||
components: { Renderer, CommitPanel },
|
||||
data() {
|
||||
return {
|
||||
stream: null,
|
||||
@@ -19,11 +50,14 @@ export default {
|
||||
prevCommit: null,
|
||||
diffCommit: null,
|
||||
serverUrl: process.env.VUE_APP_SERVER_URL,
|
||||
showDiff: false
|
||||
showDiff: false,
|
||||
loading: true
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
//TODO: Get stream when mounting view
|
||||
if (this.streamId) {
|
||||
this.getStream()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
/** @return {string} */
|
||||
@@ -33,10 +67,12 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
async getStream() {
|
||||
//TODO: Missing implementation
|
||||
var res = await getStreamCommits(this.streamId, 10, null)
|
||||
this.stream = res.data.stream
|
||||
},
|
||||
objectUrl(commit) {
|
||||
//TODO: Missing implementation
|
||||
if (!commit) return null
|
||||
return `${this.serverUrl}/streams/${this.stream.id}/objects/${commit.referencedObject}`
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
||||
+4
-4
@@ -10,8 +10,7 @@ from specklepy.objects.geometry import Brep, Point, Mesh
|
||||
from specklepy.objects import Base
|
||||
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
|
||||
|
||||
|
||||
@@ -70,7 +69,8 @@ class SpeckleMeshDiff:
|
||||
"""Checks if a specific diff commit already exists in the diff_branch"""
|
||||
branch_commits: Branch = self.client.branch.get(
|
||||
self.stream_id, self.diff_branch, 50)
|
||||
|
||||
if(branch_commits is None):
|
||||
return None
|
||||
for commit in branch_commits.commits.items:
|
||||
if commit.message == f"{self.commit_current}-{self.commit_prev}":
|
||||
return commit
|
||||
@@ -234,7 +234,7 @@ class SpeckleMeshDiff:
|
||||
@staticmethod
|
||||
def receive_data(client: SpeckleClient, stream_id: str, commit_id: str) -> Base:
|
||||
"""Get the data from a commit on the Speckle server"""
|
||||
transport = ServerTransport(client, stream_id)
|
||||
transport = ServerTransport(stream_id, client)
|
||||
|
||||
commit = client.commit.get(stream_id, commit_id)
|
||||
res = operations.receive(commit.referencedObject, transport)
|
||||
|
||||
Reference in New Issue
Block a user