├── .gitignore ├── LICENSE ├── README.md ├── css └── main.css ├── img ├── GitHub-Mark-32px.png ├── GitHub-Mark-Light-32px.png └── favicon.ico ├── index.html └── js ├── ForgeTree.js └── ForgeViewer.js /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Autodesk Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # learn.forge.viewmodels 2 | 3 | # Description 4 | 5 | This sample is part of the [Learn Forge](http://learnforge.autodesk.io) tutorials. 6 | 7 | # Live Demo 8 | 9 | https://autodesk-forge.github.io/learn.forge.viewmodels/ ([Demo Screencast](https://tiny.cc/dbgmmz)) 10 | 11 | ### Languages 12 | 13 | The `master` branch contains the client-side UI: `html`, `js` and `css` files. To download the project for each language, please use: 14 | 15 | - [Nodejs](//github.com/Autodesk-Forge/learn.forge.viewmodels/tree/nodejs) 16 | - [.NET Framework](//github.com/Autodesk-Forge/learn.forge.viewmodels/tree/net) 17 | - [.NET Core](//github.com/Autodesk-Forge/learn.forge.viewmodels/tree/netcore) 18 | - [Go](//github.com/Autodesk-Forge/learn.forge.viewmodels/tree/go) 19 | - [PHP](//github.com/Autodesk-Forge/learn.forge.viewmodels/tree/php) 20 | - [Java](//github.com/Autodesk-Forge/learn.forge.viewmodels/tree/java) 21 | - [Serverless Live Demo](//github.com/Autodesk-Forge/learn.forge.viewmodels/tree/gh-pages) 22 | -------------------------------------------------------------------------------- /css/main.css: -------------------------------------------------------------------------------- 1 | html, body{ 2 | min-height: 100%; 3 | height: 100%; 4 | } 5 | 6 | .fill{ 7 | height: calc(100vh - 100px); 8 | } 9 | 10 | body { 11 | padding-top: 60px; /* space for the top nav bar */ 12 | margin-right: 30px; 13 | } 14 | 15 | #appBuckets { 16 | overflow: auto; 17 | width: 100%; 18 | height: calc(100vh - 150px); 19 | } 20 | 21 | #forgeViewer { 22 | width: 100%; 23 | } 24 | -------------------------------------------------------------------------------- /img/GitHub-Mark-32px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/learn.forge.viewmodels/98d22f5ab1d90088344993d4ff88d6ba2be5784c/img/GitHub-Mark-32px.png -------------------------------------------------------------------------------- /img/GitHub-Mark-Light-32px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/learn.forge.viewmodels/98d22f5ab1d90088344993d4ff88d6ba2be5784c/img/GitHub-Mark-Light-32px.png -------------------------------------------------------------------------------- /img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Autodesk-Forge/learn.forge.viewmodels/98d22f5ab1d90088344993d4ff88d6ba2be5784c/img/favicon.ico -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Autodesk Forge Tutorial 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 43 | 44 |
45 |
46 |
47 |
48 |
49 | Buckets & Objects 50 | 51 | 54 |
55 |
56 | tree here 57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | 67 |
68 | 69 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /js/ForgeTree.js: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Autodesk, Inc. All rights reserved 3 | // Written by Forge Partner Development 4 | // 5 | // Permission to use, copy, modify, and distribute this software in 6 | // object code form for any purpose and without fee is hereby granted, 7 | // provided that the above copyright notice appears in all copies and 8 | // that both that copyright notice and the limited warranty and 9 | // restricted rights notice below appear in all supporting 10 | // documentation. 11 | // 12 | // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 13 | // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 14 | // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. 15 | // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 16 | // UNINTERRUPTED OR ERROR FREE. 17 | ///////////////////////////////////////////////////////////////////// 18 | 19 | $(document).ready(function () { 20 | prepareAppBucketTree(); 21 | $('#refreshBuckets').click(function () { 22 | $('#appBuckets').jstree(true).refresh(); 23 | }); 24 | 25 | $('#createNewBucket').click(function () { 26 | createNewBucket(); 27 | }); 28 | 29 | $('#createBucketModal').on('shown.bs.modal', function () { 30 | $("#newBucketKey").focus(); 31 | }) 32 | 33 | $('#hiddenUploadField').change(function () { 34 | var node = $('#appBuckets').jstree(true).get_selected(true)[0]; 35 | var _this = this; 36 | if (_this.files.length == 0) return; 37 | var file = _this.files[0]; 38 | switch (node.type) { 39 | case 'bucket': 40 | var formData = new FormData(); 41 | formData.append('fileToUpload', file); 42 | formData.append('bucketKey', node.id); 43 | 44 | $.ajax({ 45 | url: '/api/forge/oss/objects', 46 | data: formData, 47 | processData: false, 48 | contentType: false, 49 | type: 'POST', 50 | success: function (data) { 51 | $('#appBuckets').jstree(true).refresh_node(node); 52 | _this.value = ''; 53 | } 54 | }); 55 | break; 56 | } 57 | }); 58 | }); 59 | 60 | function createNewBucket() { 61 | var bucketKey = $('#newBucketKey').val(); 62 | var policyKey = $('#newBucketPolicyKey').val(); 63 | 64 | const regex = /^[\-_.a-z0-9]{3,128}$/g; 65 | if (!bucketKey.match(regex)) { 66 | alert('The bucket name can only contain characters -_.a-z0-9 and it must be between 3 and 128 characters long.'); 67 | return; 68 | } 69 | 70 | jQuery.post({ 71 | url: '/api/forge/oss/buckets', 72 | contentType: 'application/json', 73 | data: JSON.stringify({ 'bucketKey': bucketKey, 'policyKey': policyKey }), 74 | success: function (res) { 75 | $('#appBuckets').jstree(true).refresh(); 76 | $('#createBucketModal').modal('toggle'); 77 | }, 78 | error: function (err) { 79 | if (err.status == 409) 80 | alert('Bucket already exists - 409: Duplicated') 81 | console.log(err); 82 | } 83 | }); 84 | } 85 | 86 | function prepareAppBucketTree() { 87 | $('#appBuckets').jstree({ 88 | 'core': { 89 | 'themes': { "icons": true }, 90 | 'data': { 91 | "url": '/api/forge/oss/buckets', 92 | "dataType": "json", 93 | 'multiple': false, 94 | "data": function (node) { 95 | return { "id": node.id }; 96 | } 97 | } 98 | }, 99 | 'types': { 100 | 'default': { 101 | 'icon': 'glyphicon glyphicon-question-sign' 102 | }, 103 | '#': { 104 | 'icon': 'glyphicon glyphicon-cloud' 105 | }, 106 | 'bucket': { 107 | 'icon': 'glyphicon glyphicon-folder-open' 108 | }, 109 | 'object': { 110 | 'icon': 'glyphicon glyphicon-file' 111 | } 112 | }, 113 | "plugins": ["types", "state", "sort", "contextmenu"], 114 | contextmenu: { items: autodeskCustomMenu } 115 | }).on('loaded.jstree', function () { 116 | $('#appBuckets').jstree('open_all'); 117 | }).bind("activate_node.jstree", function (evt, data) { 118 | if (data != null && data.node != null && data.node.type == 'object') { 119 | $("#forgeViewer").empty(); 120 | var urn = data.node.id; 121 | getForgeToken(function (access_token) { 122 | jQuery.ajax({ 123 | url: 'https://developer.api.autodesk.com/modelderivative/v2/designdata/' + urn + '/manifest', 124 | headers: { 'Authorization': 'Bearer ' + access_token }, 125 | success: function (res) { 126 | if (res.progress === 'success' || res.progress === 'complete') launchViewer(urn); 127 | else $("#forgeViewer").html('The translation job still running: ' + res.progress + '. Please try again in a moment.'); 128 | }, 129 | error: function (err) { 130 | var msgButton = 'This file is not translated yet! ' + 131 | '' 133 | $("#forgeViewer").html(msgButton); 134 | } 135 | }); 136 | }) 137 | } 138 | }); 139 | } 140 | 141 | function autodeskCustomMenu(autodeskNode) { 142 | var items; 143 | 144 | switch (autodeskNode.type) { 145 | case "bucket": 146 | items = { 147 | uploadFile: { 148 | label: "Upload file", 149 | action: function () { 150 | uploadFile(); 151 | }, 152 | icon: 'glyphicon glyphicon-cloud-upload' 153 | } 154 | }; 155 | break; 156 | case "object": 157 | items = { 158 | translateFile: { 159 | label: "Translate", 160 | action: function () { 161 | var treeNode = $('#appBuckets').jstree(true).get_selected(true)[0]; 162 | translateObject(treeNode); 163 | }, 164 | icon: 'glyphicon glyphicon-eye-open' 165 | } 166 | }; 167 | break; 168 | } 169 | 170 | return items; 171 | } 172 | 173 | function uploadFile() { 174 | $('#hiddenUploadField').click(); 175 | } 176 | 177 | function translateObject(node) { 178 | $("#forgeViewer").empty(); 179 | if (node == null) node = $('#appBuckets').jstree(true).get_selected(true)[0]; 180 | var bucketKey = node.parents[0]; 181 | var objectKey = node.id; 182 | jQuery.post({ 183 | url: '/api/forge/modelderivative/jobs', 184 | contentType: 'application/json', 185 | data: JSON.stringify({ 'bucketKey': bucketKey, 'objectName': objectKey }), 186 | success: function (res) { 187 | $("#forgeViewer").html('Translation started! Please try again in a moment.'); 188 | }, 189 | }); 190 | } -------------------------------------------------------------------------------- /js/ForgeViewer.js: -------------------------------------------------------------------------------- 1 | var viewer; 2 | 3 | function launchViewer(urn) { 4 | var options = { 5 | env: 'AutodeskProduction', 6 | getAccessToken: getForgeToken, 7 | }; 8 | 9 | Autodesk.Viewing.Initializer(options, () => { 10 | viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('forgeViewer')); 11 | viewer.start(); 12 | var documentId = 'urn:' + urn; 13 | Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure); 14 | }); 15 | } 16 | 17 | function onDocumentLoadSuccess(doc) { 18 | var viewables = doc.getRoot().getDefaultGeometry(); 19 | viewer.loadDocumentNode(doc, viewables).then(i => { 20 | // documented loaded, any action? 21 | }); 22 | } 23 | 24 | function onDocumentLoadFailure(viewerErrorCode, viewerErrorMsg) { 25 | console.error('onDocumentLoadFailure() - errorCode:' + viewerErrorCode + '\n- errorMessage:' + viewerErrorMsg); 26 | } 27 | 28 | function getForgeToken(callback) { 29 | fetch('/api/forge/oauth/token').then(res => { 30 | res.json().then(data => { 31 | callback(data.access_token, data.expires_in); 32 | }); 33 | }); 34 | } 35 | --------------------------------------------------------------------------------