Polish
This commit is contained in:
+101
-19
@@ -2,45 +2,127 @@
|
||||
using Speckle.Core.Kits;
|
||||
using Speckle.Core.Credentials;
|
||||
using Speckle.Core.Api;
|
||||
using System.Threading;
|
||||
using Objects;
|
||||
using Speckle.Core.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Objects.Geometry;
|
||||
using Objects.Primitive;
|
||||
using Speckle.Core.Transports;
|
||||
using System.Linq;
|
||||
|
||||
namespace CSharpStarter
|
||||
{
|
||||
class Program
|
||||
{
|
||||
// Running this program will pull the latest commit from the main branch
|
||||
// of the specified stream and duplicate it inside a different branch.
|
||||
// (branch should exist already or the program will fail)
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Hello Speckle!");
|
||||
// The id of the stream to work with (we're assuming it already exists in your default account's server)
|
||||
var streamId = "c1800d795b";
|
||||
// The name of the branch we'll send data to.
|
||||
var branchName = "processed";
|
||||
|
||||
// Get default account on this machine
|
||||
var defaultAccount = AccountManager.GetDefaultAccount();
|
||||
// Or get all the accounts and manually choose the one you want
|
||||
// var accounts = AccountManager.GetAccounts();
|
||||
// var defaultAccount = accounts.ToList().FirstOrDefault();
|
||||
|
||||
// Create a new "base" object
|
||||
var commitObj = new Base();
|
||||
// Base objects are dynamic, so you can assign any properties just like a Dictionary
|
||||
commitObj["myProp"] = "myPropValue";
|
||||
commitObj["myOtherProp"] = new List<string> { "A", "list", "of", "values" };
|
||||
// Authenticate using the account
|
||||
var client = new Client(defaultAccount);
|
||||
|
||||
var boxes = new List<Point>();
|
||||
for (int i = 0; i < 10; i++)
|
||||
// Get the main branch with it's latest commit reference
|
||||
var branch = client.BranchGet(streamId, "main", 1).Result;
|
||||
// Get the id of the object referenced in the commit
|
||||
var hash = branch.commits.items[0].referencedObject;
|
||||
|
||||
|
||||
// Create the server transport for the specified stream.
|
||||
var transport = new ServerTransport(defaultAccount, streamId);
|
||||
// Receive the object
|
||||
var receivedBase = Operations.Receive(hash, transport).Result;
|
||||
|
||||
// Process the object however you'd like
|
||||
Console.WriteLine("Received object:" + receivedBase);
|
||||
|
||||
// Sending the object will return it's unique identifier.
|
||||
var newHash = Operations.Send(receivedBase, new List<ITransport> { transport }).Result;
|
||||
|
||||
// Create a commit in `processed` branch (it must previously exist)
|
||||
var commitId = client.CommitCreate(new CommitCreateInput()
|
||||
{
|
||||
for (int j = 0; j < 10; j++)
|
||||
{
|
||||
boxes.Add(new Point(i, j, 0));
|
||||
}
|
||||
}
|
||||
commitObj["boxes"] = boxes;
|
||||
// Send the object to Speckle, get back the commit id
|
||||
var commitId = Helpers.Send("2d9b814ed6", commitObj, "Upload from my console app", null, 0, defaultAccount, false).Result;
|
||||
branchName = branchName,
|
||||
message = "Automatic commit created by AEC Tech Demo C# console app.",
|
||||
objectId = newHash,
|
||||
streamId = streamId,
|
||||
sourceApplication = "AEC Tech C# Script"
|
||||
|
||||
// To receive the latest commit
|
||||
var receivedObj = Helpers.Receive("2d9b814ed6", defaultAccount).Result;
|
||||
Console.WriteLine(receivedObj["myProp"]);
|
||||
}).Result;
|
||||
|
||||
Console.WriteLine($"Successfully created commit with id: {commitId}");
|
||||
|
||||
// Remember to dispose of the client once you've finished with it.
|
||||
client.Dispose();
|
||||
}
|
||||
|
||||
static void ReactToCommit(string[] args)
|
||||
|
||||
{
|
||||
// Get default account on this machine
|
||||
var defaultAccount = AccountManager.GetDefaultAccount();
|
||||
var client = new Client(defaultAccount);
|
||||
var streamId = "42c06de34f";
|
||||
var branch = client.BranchGet(streamId, "main", 1).Result;
|
||||
var hash = branch.commits.items[0].referencedObject;
|
||||
|
||||
|
||||
var exit = false;
|
||||
client.OnCommitCreated += (sender, e) =>
|
||||
{
|
||||
// Ignore commits from any branch other than 'main'
|
||||
if (e.branchName != "main") return;
|
||||
|
||||
Console.WriteLine("Commit was created in Main! Processing data...");
|
||||
|
||||
// Create the server transport for the specified stream.
|
||||
var transport = new ServerTransport(defaultAccount, streamId);
|
||||
// Receive the object
|
||||
var receivedBase = Operations.Receive(hash, transport).Result;
|
||||
|
||||
var newHash = Operations.Send(receivedBase, new List<ITransport> { transport }).Result;
|
||||
|
||||
// Create a commit in `processed` branch (it must previously exist)
|
||||
var commitId = client.CommitCreate(new CommitCreateInput()
|
||||
{
|
||||
branchName = "processed",
|
||||
message = "Automatic commit created by AEC Tech Demo C# console app.",
|
||||
objectId = newHash,
|
||||
streamId = streamId,
|
||||
sourceApplication = "C#"
|
||||
|
||||
}).Result;
|
||||
Console.WriteLine($"Successfully created commit with id: {commitId}");
|
||||
exit = true;
|
||||
};
|
||||
|
||||
// Subscribe to commits created on the stream.
|
||||
client.SubscribeCommitCreated(streamId);
|
||||
|
||||
// HACK: This is a super hacky way to get a C# console app to wait for an event to happen.
|
||||
// YOU SHOULD NOT DO THIS IN A PRODUCTION APPLICATION 🤣
|
||||
Console.WriteLine("Waiting for commit created event...");
|
||||
while (!exit)
|
||||
{
|
||||
Thread.Sleep(500);
|
||||
Console.WriteLine("Still waiting...");
|
||||
}
|
||||
|
||||
// Remember to dispose of the client once you've finished with it.
|
||||
client.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-10
@@ -1,12 +1,4 @@
|
||||
# Using Speckle Core
|
||||
# AEC C# Starter
|
||||
|
||||
```
|
||||
dotnet new console -f netcoreapp3.1
|
||||
```
|
||||
|
||||
Add Speckle.Core
|
||||
|
||||
```
|
||||
dotnet add package Speckle.Core --version 2.1.22
|
||||
```
|
||||
|
||||
>
|
||||
@@ -0,0 +1,14 @@
|
||||
# AEC Tech Python Starter
|
||||
|
||||
# Usage
|
||||
|
||||
This is a demo script
|
||||
|
||||
# Prerequisites
|
||||
|
||||
Install `specklepy`
|
||||
|
||||
```
|
||||
pip install specklepy
|
||||
```
|
||||
|
||||
|
||||
+25
-20
@@ -1,51 +1,56 @@
|
||||
# Running this script will pull the latest commit from the main branch
|
||||
# of the specified stream and duplicate it inside a different branch.
|
||||
# (branch should exist already or the script will fail
|
||||
|
||||
from specklepy.api.client import SpeckleClient
|
||||
from specklepy.api.credentials import get_default_account, get_local_accounts
|
||||
from specklepy.transports.server import ServerTransport
|
||||
from specklepy.api import operations
|
||||
|
||||
# The id of the stream to work with (we're assuming it already exists in your default account's server)
|
||||
streamId = "c1800d795b"
|
||||
branchName = "processed"
|
||||
# Initialise the Speckle client pointing to your specific server.
|
||||
client = SpeckleClient(host="https://speckle.xyz")
|
||||
|
||||
# Get the default account
|
||||
# If you have more than one account, or the account is not the default, use get_local_accounts
|
||||
account = get_default_account()
|
||||
# If you have more than one account, or the account is not the default, use get_local_accounts
|
||||
# accounts = get_local_accounts()
|
||||
# account = accounts[0]
|
||||
|
||||
# Authenticate using the account token
|
||||
client.authenticate(token=account.token)
|
||||
|
||||
# Your account email
|
||||
print('Welcome!!',account.userInfo.email, account.serverInfo.url)
|
||||
|
||||
|
||||
# use that stream id to get the stream from the server
|
||||
streamId = "42c06de34f"
|
||||
# Get the main branch with it's latest commit reference
|
||||
branch = client.branch.get(streamId, "main", 1)
|
||||
# Get the id of the object referenced in the commit
|
||||
hash = branch.commits.items[0].referencedObject
|
||||
|
||||
|
||||
|
||||
|
||||
# next create a server transport - this is the vehicle through which you will send and receive
|
||||
# Create the server transport for the specified stream.
|
||||
transport = ServerTransport(client=client, stream_id=streamId)
|
||||
|
||||
# this receives the object back from the transport.
|
||||
# the received data will be deserialised back into a `Block`
|
||||
# Receive the object
|
||||
received_base = operations.receive(obj_id=hash, remote_transport=transport)
|
||||
|
||||
for list in received_base["@data"]:
|
||||
for item in list:
|
||||
item.z += 1
|
||||
|
||||
|
||||
|
||||
# The received object, process it as you wish.
|
||||
print("Received object:", received_base)
|
||||
|
||||
|
||||
|
||||
# this serialises the modified points and sends it to the transport
|
||||
hash = operations.send(base=received_base, transports=[transport])
|
||||
newHash = operations.send(base=received_base, transports=[transport])
|
||||
|
||||
# you can now create a commit on your stream with this object
|
||||
commit_id = client.commit.create(
|
||||
stream_id=streamId,
|
||||
branch_name="python",
|
||||
branch_name=branchName,
|
||||
object_id=hash,
|
||||
message="Points were modified by AECTechDemo.py script",
|
||||
message="Automatic commit created by AEC Tech Demo by AECTechDemo.py script",
|
||||
source_application="AEC Tech Python Script"
|
||||
)
|
||||
|
||||
print("Successfully created commit with id:", commit_id)
|
||||
print("Successfully created commit with id: ", commit_id)
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
# AEC Tech Presentation Repo
|
||||
# AEC Tech Speckle Repo
|
||||
|
||||
This repo contains all code and files related to
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# Starter Speckle web viewer project
|
||||
|
||||
> This is a basic `html/js/css` webpage that uses our `@speckle/viewer` package and some basic queries through our `graphQL` API.
|
||||
> If you want to know more about Speckle as a developer platform, check our [Developer Docs](https://speckle.guide/dev)
|
||||
|
||||
The app allows you to view the main geometry of a stream and combine it with different design options (which would exist as different `branches` in the stream)
|
||||
|
||||

|
||||
|
||||
The stream will be organised as follows:
|
||||
|
||||
- `main` branch: Will contain the main geometry.
|
||||
- Any other existing branches should contain the different design options to visualise along side the `main` geometry.
|
||||
|
||||

|
||||
|
||||
## Usage
|
||||
|
||||
This demo should run directly in your browser. Just double click the `index.html` file on this folder.
|
||||
|
||||
## Repo structure
|
||||
|
||||
- `index.html`: Main html file
|
||||
- `app.js`: Main `js` module for the website
|
||||
- `speckleQueries.js` contains several `graphQL` queries we'll be using.
|
||||
- `speckleUtils.js` contains the functions to interact with the Speckle API.
|
||||
- `styles.css`: Styles to used by `index.html`
|
||||
|
||||
+139
-8
@@ -1,22 +1,153 @@
|
||||
let token = "096315ee1bf8c961444b270746becd1e8474baa79e"
|
||||
let objUrl =
|
||||
"http://localhost:3000/streams/2d9b814ed6/objects/d679e6ff0efb8c9c102b8f8136b0f68a"
|
||||
import { getStreamCommits, getUserData } from "./speckleUtils.js"
|
||||
|
||||
let token = null
|
||||
let streamId = null
|
||||
let stream = null
|
||||
let mainBranch = null
|
||||
let beams = null
|
||||
let columns = null
|
||||
let selectedBeam = null
|
||||
let selectedColumn = null
|
||||
let isDropdownLoaded = false
|
||||
|
||||
document
|
||||
.getElementById("alternative-selector")
|
||||
.addEventListener("change", onBeamAlternativeSelected)
|
||||
document
|
||||
.getElementById("alternative-selector-2")
|
||||
.addEventListener("change", onColumnAlternativeSelected)
|
||||
document.getElementById("reloadButton").addEventListener("click", reload)
|
||||
|
||||
let objUrl = (streamId, objId) =>
|
||||
`https://speckle.xyz/streams/${streamId}/objects/${objId}`
|
||||
|
||||
// Create the viewer instance
|
||||
let viewer = new window.Speckle.Viewer({
|
||||
container: document.getElementById("viewer"),
|
||||
showStats: true
|
||||
showStats: false
|
||||
})
|
||||
|
||||
viewer.loadObject(objUrl, token)
|
||||
|
||||
viewer.interactions.zoomExtents(0.95, false)
|
||||
|
||||
// Handle selection events
|
||||
viewer.on("select", objects => {
|
||||
console.info(`Selection event. Current selection count: ${objects.length}.`)
|
||||
console.log(objects)
|
||||
let el = document.getElementById("selection-area")
|
||||
let jv = window["w-jsonview-tree"]
|
||||
jv(objects, el, { expanded: false })
|
||||
})
|
||||
|
||||
// Handle double click events
|
||||
viewer.on("object-doubleclicked", obj => {
|
||||
console.info("Object double click event.")
|
||||
console.log(obj ? obj : "nothing was doubleckicked.")
|
||||
})
|
||||
|
||||
async function reload() {
|
||||
document.getElementById("reloadButton").classList.add("is-loading")
|
||||
streamId = document.getElementById("stream-input").value // Get the value of the stream input
|
||||
token = document.getElementById("token-input").value // Get the value of the token input
|
||||
await fetchStreamData() // Fetch the stream data
|
||||
if (!isDropdownLoaded) {
|
||||
populateDropdown("alternative-selector", beams)
|
||||
populateDropdown("alternative-selector-2", columns) // If it's the first time, populate the dropdown too.
|
||||
}
|
||||
await reloadViewer() // Reload the viewer once the stream data has been fetched
|
||||
document.getElementById("reloadButton").classList.remove("is-loading")
|
||||
}
|
||||
|
||||
// This will add an option for each branch in the alternatives list, and bind the referenced object id as the value
|
||||
function populateDropdown(id, data) {
|
||||
let select = document.getElementById(id)
|
||||
data.forEach(alt => {
|
||||
if (alt.commits.items.length == 0) return
|
||||
var opt = document.createElement("option")
|
||||
opt.appendChild(document.createTextNode(alt.name))
|
||||
opt.value = alt.commits.items[0].referencedObject
|
||||
select.appendChild(opt)
|
||||
})
|
||||
isDropdownLoaded = true
|
||||
}
|
||||
|
||||
// Get the stream data and process it
|
||||
//
|
||||
async function fetchStreamData() {
|
||||
await getStreamCommits(streamId, 1, null, token).then(str => {
|
||||
stream = str.data.stream
|
||||
|
||||
// Split the branches into "main" and everything else
|
||||
mainBranch = stream.branches.items.find(b => b.name == "main")
|
||||
beams = stream.branches.items.filter(b => b.name.startsWith("beam"))
|
||||
columns = stream.branches.items.filter(b => b.name.startsWith("column"))
|
||||
console.log("main branch", mainBranch)
|
||||
console.log("beam options", beams)
|
||||
console.log("column options", columns)
|
||||
})
|
||||
}
|
||||
|
||||
// Reload of the viewer data, remove all objects, reload everything and zoom.
|
||||
async function reloadViewer() {
|
||||
viewer.sceneManager.removeAllObjects()
|
||||
await viewer.loadObject(
|
||||
objUrl(streamId, mainBranch.commits.items[0].referencedObject)
|
||||
)
|
||||
console.log(`Loaded latest commit from branch "${mainBranch.name}"`)
|
||||
|
||||
// Load beam if selected
|
||||
if (selectedBeam) {
|
||||
console.log("alternative is selected, should load", selectedBeam)
|
||||
await viewer.loadObject(objUrl(streamId, selectedBeam))
|
||||
console.log("loaded alternative")
|
||||
}
|
||||
|
||||
// Load column if selected
|
||||
if (selectedColumn) {
|
||||
console.log("alternative is selected, should load", selectedColumn)
|
||||
await viewer.loadObject(objUrl(streamId, selectedColumn))
|
||||
console.log("loaded alternative")
|
||||
}
|
||||
|
||||
viewer.interactions.zoomExtents(0.95, true)
|
||||
}
|
||||
|
||||
// Reload viewer every time an alternative is selected in the dropdown.
|
||||
async function onColumnAlternativeSelected(event) {
|
||||
const selection = event.target.value.substring(
|
||||
event.target.selectionStart,
|
||||
event.target.selectionEnd
|
||||
)
|
||||
selectedColumn = selection
|
||||
console.log("selected", selectedColumn)
|
||||
document.getElementById("reloadButton").classList.add("is-loading")
|
||||
await reloadViewer()
|
||||
document.getElementById("reloadButton").classList.remove("is-loading")
|
||||
}
|
||||
|
||||
async function onBeamAlternativeSelected(event) {
|
||||
const selection = event.target.value.substring(
|
||||
event.target.selectionStart,
|
||||
event.target.selectionEnd
|
||||
)
|
||||
selectedBeam = selection
|
||||
console.log("selected", selectedBeam)
|
||||
document.getElementById("reloadButton").classList.add("is-loading")
|
||||
await reloadViewer()
|
||||
document.getElementById("reloadButton").classList.remove("is-loading")
|
||||
}
|
||||
|
||||
// Hack to prevent scene from loosing current zoom.
|
||||
viewer.sceneManager._postLoadFunction = () => {
|
||||
viewer.reflectionsNeedUpdate = true
|
||||
}
|
||||
|
||||
document.getElementById("take-screenshot").addEventListener("click", () => {
|
||||
console.log("screenshot clickd")
|
||||
let data = viewer.interactions.screenshot() // transparent png.
|
||||
|
||||
let pop = window.open()
|
||||
pop.document.title = "SpeckleStreamScreenshot"
|
||||
pop.document.body.style.backgroundColor = "grey"
|
||||
|
||||
let img = new Image()
|
||||
img.src = data
|
||||
pop.document.body.appendChild(img)
|
||||
})
|
||||
|
||||
+67
-4
@@ -7,14 +7,77 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Speckle Web Starter</title>
|
||||
<script src="https://unpkg.com/@speckle/viewer"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/w-jsonview-tree@1.0.24/dist/w-jsonview-tree.umd.js"></script>
|
||||
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="viewerParent">
|
||||
<div id="viewer"></div>
|
||||
</div>
|
||||
<script src="app.js"></script>
|
||||
<div id="viewerParent" class="hero is-fullheight">
|
||||
<div id="viewer" class=""></div>
|
||||
<div class="box" id="menu">
|
||||
<div class="content">
|
||||
<h3 class="title has-text-info">Speckle - AEC Tech Demo</h3>
|
||||
<p class="subtitle is-size-7">Compare different design options on a stream</p>
|
||||
<div class="field has-addons">
|
||||
<div class="control">
|
||||
<input id="stream-input" class="input" type="text" placeholder="Your stream ID">
|
||||
</div>
|
||||
<div class="control">
|
||||
<input id="token-input" class="input" type="text" placeholder="Your auth token">
|
||||
</div>
|
||||
<div class="control">
|
||||
<button class="button is-info" id="reloadButton">Load</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field has-addons">
|
||||
<div class="control">
|
||||
<button class="button is-info" disabled>Beam options</button>
|
||||
</div>
|
||||
<div class="control is-expanded">
|
||||
<div class="select is-fullwidth">
|
||||
<select id="alternative-selector" class="is-loading">
|
||||
<option selected>Select a beam option</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field has-addons">
|
||||
<div class="control">
|
||||
<button class="button is-info" disabled>Column options</button>
|
||||
</div>
|
||||
<div class="control is-expanded">
|
||||
<span class="select is-fullwidth">
|
||||
<select id="alternative-selector-2" class="is-loading">
|
||||
<option selected>Select a column option</option>
|
||||
</select>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<button id="take-screenshot" class="button is-fullwidth is-info is-small">Take screenshot</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="box" id="selected-panel">
|
||||
<div class="content" id="selection-area-parent">
|
||||
<h3 class="title has-text-info">Selected objects
|
||||
</h3>
|
||||
<p class="subtitle is-size-7">Data from selected objects</p>
|
||||
<p id="selection-area"></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom-left">
|
||||
<a class="button is-info is-small" href="http://speckle.systems">
|
||||
<span>Powered by Speckle</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="bottom-right">
|
||||
<a class="button is-small is-info is-rounded" href="http://speckle.guide">
|
||||
<span class="icon">
|
||||
<i class="fas fa-question"></i>
|
||||
</span></a>
|
||||
</div>
|
||||
<script type="module" src="app.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,38 @@
|
||||
export const userInfoQuery = () => `query {
|
||||
user {
|
||||
name
|
||||
},
|
||||
serverInfo {
|
||||
name
|
||||
company
|
||||
}
|
||||
}`
|
||||
|
||||
export const streamCommitsQuery = (streamId, itemsPerPage, cursor) => `query {
|
||||
stream(id: "${streamId}"){
|
||||
branches {
|
||||
totalCount
|
||||
cursor
|
||||
items {
|
||||
name
|
||||
commits(limit: 1){
|
||||
items {
|
||||
referencedObject
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
export const streamSearchQuery = search => `query {
|
||||
streams(query: "${search}") {
|
||||
totalCount
|
||||
cursor
|
||||
items {
|
||||
id
|
||||
name
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
}`
|
||||
@@ -0,0 +1,39 @@
|
||||
import {
|
||||
streamCommitsQuery,
|
||||
streamSearchQuery,
|
||||
userInfoQuery
|
||||
} from "./speckleQueries.js"
|
||||
|
||||
export let SERVER_URL = "https://speckle.xyz"
|
||||
|
||||
// Calls the GraphQL endpoint of the Speckle server with a specific query.
|
||||
export async function speckleFetch(query, token) {
|
||||
console.log("fetching with token ", 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
|
||||
})
|
||||
})
|
||||
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)")
|
||||
}
|
||||
|
||||
// Fetch the current user data using the userInfoQuery
|
||||
export const getUserData = token => speckleFetch(userInfoQuery(), token)
|
||||
|
||||
// Fetch for streams matching the specified text using the streamSearchQuery
|
||||
export const searchStreams = (e, token) => speckleFetch(streamSearchQuery(e))
|
||||
|
||||
// Get commits related to a specific stream, allows for pagination by passing a cursor
|
||||
export const getStreamCommits = (streamId, itemsPerPage, cursor, token) =>
|
||||
speckleFetch(streamCommitsQuery(streamId, itemsPerPage, cursor), token)
|
||||
+36
-8
@@ -1,15 +1,43 @@
|
||||
@import "https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css";
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#viewerParent {
|
||||
min-width: 100vw;
|
||||
min-height: 100vh;
|
||||
background-color: whitesmoke !important;
|
||||
}
|
||||
|
||||
#viewer {
|
||||
min-width: 100vw;
|
||||
min-height: 80vh;
|
||||
border: 1px solid black;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
#menu {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
flex-direction: column;
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
#selected-panel {
|
||||
position: absolute;
|
||||
top: 0em;
|
||||
right: 0em;
|
||||
width: 450px !important;
|
||||
margin: 1em;
|
||||
max-height: 50% !important;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.bottom-left {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
.bottom-right {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user