I've an issue with the Forge viewer I'm developping : Im' trying to host it using Github-page, but it doesn't seem to work correctly.
The issue is on the File tree : when I load the viewer page from the Github pages, the file tree seems stuck on "Loading...". However, it correctly loads when I load the page from localhost.
The code of the File tree :
$(document).ready(function () {
prepareAppBucketTree();
$('#refreshBuckets').click(function () {
$('#appBuckets').jstree(true).refresh();
});
$('#createNewBucket').click(function () {
createNewBucket();
});
$('#createBucketModal').on('shown.bs.modal', function () {
$("#newBucketKey").focus();
})
$('#hiddenUploadField').change(function () {
var node = $('#appBuckets').jstree(true).get_selected(true)[0];
var _this = this;
if (_this.files.length == 0) return;
var file = _this.files[0];
switch (node.type) {
case 'bucket':
var formData = new FormData();
formData.append('fileToUpload', file);
formData.append('bucketKey', node.id);
$.ajax({
url: '/api/forge/oss/objects',
data: formData,
processData: false,
contentType: false,
type: 'POST',
success: function (data) {
$('#appBuckets').jstree(true).refresh_node(node);
_this.value = '';
}
});
break;
}
});
});
function createNewBucket() {
var bucketKey = $('#newBucketKey').val();
var policyKey = $('#newBucketPolicyKey').val();
console.log(bucketKey)
jQuery.post({
url: '/api/forge/oss/buckets',
contentType: 'application/json',
data: JSON.stringify({ 'bucketKey': bucketKey, 'policyKey': policyKey }),
success: function (res) {
$('#appBuckets').jstree(true).refresh();
$('#createBucketModal').modal('toggle');
},
error: function (err) {
if (err.status == 409)
alert('Bucket already exists - 409: Duplicated')
console.log(err);
}
});
}
function prepareAppBucketTree() {
$('#appBuckets').jstree({
'core': {
'themes': { "icons": true },
'data': {
"url": '/api/forge/oss/buckets',
"dataType": "json",
'multiple': false,
"data": function (node) {
return { "id": node.id };
}
}
},
'types': {
'default': {
'icon': 'glyphicon glyphicon-question-sign'
},
'#': {
'icon': 'glyphicon glyphicon-cloud'
},
'bucket': {
'icon': 'glyphicon glyphicon-folder-open'
},
'object': {
'icon': 'glyphicon glyphicon-file'
}
},
"plugins": ["types", "state", "sort", "contextmenu"],
contextmenu: { items: autodeskCustomMenu }
}).on('loaded.jstree', function () {
$('#appBuckets').jstree('open_all');
}).bind("activate_node.jstree", function (evt, data) {
if (data != null && data.node != null && data.node.type == 'object') {
// $("#MyViewerDiv").empty();
var urn = data.node.id;
getForgeToken(function (access_token) {
jQuery.ajax({
url: 'https://developer.api.autodesk.com/modelderivative/v2/designdata/' + urn + '/manifest',
headers: { 'Authorization': 'Bearer ' + access_token },
success: function (res) {
if (res.status === 'success') callByUrn('urn:'+urn);
else $("#MyViewerDiv").html('The translation job still running: ' + res.progress + '. Please try again in a moment.');
},
error: function (err) {
var msgButton = 'This file is not translated yet! ' +
'<button class="btn btn-xs btn-info" onclick="translateObject()"><span class="glyphicon glyphicon-eye-open"></span> ' +
'Start translation</button>'
$("#MyViewerDiv").html(msgButton);
}
});
})
}
});
}
function autodeskCustomMenu(autodeskNode) {
var items;
switch (autodeskNode.type) {
case "bucket":
items = {
uploadFile: {
label: "Upload file",
action: function () {
uploadFile();
},
icon: 'glyphicon glyphicon-cloud-upload'
}
};
break;
case "object":
items = {
translateFile: {
label: "Translate",
action: function () {
var treeNode = $('#appBuckets').jstree(true).get_selected(true)[0];
translateObject(treeNode);
},
icon: 'glyphicon glyphicon-eye-open'
}
};
break;
}
return items;
}
function uploadFile() {
$('#hiddenUploadField').click();
}
function translateObject(node) {
$("#MyViewerDiv").empty();
if (node == null) node = $('#appBuckets').jstree(true).get_selected(true)[0];
var bucketKey = node.parents[0];
var objectKey = node.id;
jQuery.post({
url: '/api/forge/modelderivative/jobs',
contentType: 'application/json',
data: JSON.stringify({ 'bucketKey': bucketKey, 'objectName': objectKey }),
success: function (res) {
$("#MyViewerDiv").html('Translation started! Please try again in a moment.');
},
});
}
Please note that Github Pages are used for serving static pages without any special server-side logic. Your Forge application requires a server to talk to as well, for example, to obtain a list of buckets for the tree view (by making a request to /api/forge/oss/buckets).
You could potentially host your application's server-side logic on something like Heroku, and then have your static HTML/CSS/JavaScript page on Github talk to that server (for example, https://my-forge-app.herokuapp.com/api/forge/oss/buckets). Just be careful about CORS.
Related
i'm working on app witch i need to send multiple images,
and i wonder if there is any way to send multiple images via file transfer plugin,
this my code:
const options: CameraOptions = {
quality: 100,
destinationType: this.camera.DestinationType.FILE_URI,
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY
}
this.camera.getPicture(options).then((imageData2) => {
this.imageURI2 = imageData2;
}, (err) => {
console.log(err);
});
upload
const fileTransfer: FileTransferObject = this.transfer.create();
let options: FileUploadOptions = {
fileKey: 'file',
fileName: 'name.jpg',
headers: {
Connection: "close"
}
}
options.chunkedMode = false;
if(this.imageURI1 != null){
fileTransfer.upload(this.imageURI1,
'https://test.test.com/uplaodphoto.php', options)
.then((data) => {
alert("success");
this.imageFileName1 =
"https://test.test.com/images/name.jpg"
}, (err) => {
alert("error"+JSON.stringify(err));
});
User Image Picker Plugin Cordova Image Picker
Usage:
import { ImagePicker } from '#ionic-native/image-picker';
constructor(private imagePicker: ImagePicker) { }
export class YourPage {
pickImages(){
this.imagePicker.getPictures(options).then((results) => {
for (var i = 0; i < results.length; i++) {
console.log('Image URI: ' + results[i]);
this.imageUpload(results[i])
}
}, (err) => { });
}
// Upload Image function.
imageUpload(path) {
const fileTransfer: FileTransferObject = this.transfer.create();
let options: FileUploadOptions = {
fileKey: 'image',
fileName: '.png',
chunkedMode: false,
//mimeType: "image/jpeg",
}
fileTransfer.upload(path, 'https://api.com/image-upload', options)
.then((data) => {
console.log(data+" Uploaded Successfully");
let res = JSON.parse(data.response);
if (res.success == true) {
}
this.loader.dismiss();
}, (err) => {
console.log(err);
});
}
}
I want to parse the below JavaScript array for using in Autocomplete control.
The requirement is to display the value field in autocomplete textbox and store the key field as itemID.
{"Key":9886,"Value":"xxx"},{"Key":9887,"Value":"yyy"},{"Key":5634,"Value":"zzz"},{"Key":9888,"Value":"abcd"}
I tried the below code to map this array as source for my textbox:
var itemID;
$("#txtbox").autocomplete({
source: function (request, response) {
$.ajax({
type: 'POST',
url: 'controller/Getdata',
data:JSON.stringify({'term' :request.term}),
dataType: 'json',
contentType: 'application/json',
success: function(data) {
response(
$.map(data,
function(object) {
return {
label: object.value,
value: object.key
}
})
)
},
error: function(xhr, status, error) {
alert(error);
}
});
},
minLength: 2,
select: function (e, ui) {
e.preventDefault();
$("#txtbox").val(ui.item.value);
itemID = ui.item.key;
}
});```
Appreciate any help on this.
The below code worked to map autocomplete source to dictionary array:
$("#txtbox").autocomplete({
source: function (request, response) {
$.ajax({
type: 'POST',
url: 'controller/Getdata',
data: JSON.stringify({ 'term': request.term }),
dataType: 'json',
contentType: 'application/json',
success: function (data) {
var parsedData = JSON.parse(data);
var arr = $.map(parsedData,
function (item) {
return {
label:item.Value,
value:item.Key
}}
);
response(arr);
},
error: function (xhr, status, error) {
alert('here');
var array = [];
response(array);
}
});
},
minLength: 3,
select: function (e, ui) {
e.preventDefault();
$("#txtbox").val(ui.item.label);
userID = ui.item.value;
}
});
The controller code which returns dictionary was this:
public ActionResult Getdata(string term)
{
var itemList= Provider.GetAllItems();
var filteredItems = itemList.Where(x => x.Value.Contains(term));
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
string result = javaScriptSerializer.Serialize(filteredItems );
return Json(result, JsonRequestBehavior.AllowGet);
}
I'm trying to figure out how to stub mongoDB in hapi js to allow testing but I have no idea how to do it. I've tried checking out Sinonjs but I have no idea how to apply it in this particular case.
Here's some of the code:
// index.js
'use strict';
const Hapi = require('hapi');
const MongoJS = require('mongojs');
const server = new Hapi.Server();
server.connection({ host: 'localhost', port: 11001 });
server.app.db = MongoJS('crunchbase', ['companies']);
server.register([
{
register: require('./lib/plugins')
},
{
register: require('./lib/modules/companies'),
options: {
baseUrl: '/v1/companies'
}
}
], (err) => {
if (err) {
throw err;
}
server.start((err) => {
if (err) {
throw err;
}
server.log('info', `Server listening on ${server.info.uri}`);
});
});
module.exports = server;
Here's are the routes:
// companies.js
'use strict';
const Boom = require('boom');
const Joi = require('joi');
const error = Joi.object().keys({
statusCode: Joi.number(),
error: Joi.string(),
message: Joi.string()
});
const schema = Joi.object().keys({
_id: Joi.object(),
permalink: Joi.string(),
name: Joi.string(),
homepage_url: Joi.string(),
category_list: Joi.string(),
funding_total_usd: Joi.alternatives().try(Joi.number(), Joi.string()),
status: Joi.string(),
country_code: Joi.string().allow(''),
state_code: Joi.alternatives().try(Joi.string(), Joi.number()).allow(''),
region: Joi.string().allow(''),
city: Joi.string().allow(''),
funding_rounds: Joi.number(),
founded_at: Joi.string().allow(''),
first_funding_at: Joi.string(),
last_funding_at: Joi.string()
});
exports.register = (server, options, next) => {
const db = server.app.db;
const { baseUrl } = options;
server.route([
{
method: 'GET',
path: baseUrl,
config: {
description: 'companies',
notes: 'Get a list of companies from the database',
tags: ['api'],
validate: {
query: {
limit: Joi.number().min(1).max(20).default(5)
}
},
response: {
status: {
200: Joi.array().items(schema),
400: error,
500: error
}
}
},
handler: (request, reply) => {
db.companies.find().limit(request.query.limit, (err, docs) => {
if (err) {
return reply(Boom.wrap(err, 'Internal MongoDB error.'));
}
reply(docs);
});
}
}
]);
return next();
};
exports.register.attributes = {
pkg: require('./package.json')
};
And here's the test suite:
// companies.test.js
'use strict';
const Code = require('code');
const Lab = require('lab');
const lab = exports.lab = Lab.script();
const { describe, it } = lab;
const expect = Code.expect;
const Server = require('../../');
describe('Companies module test suite', () => {
const baseUrl = '/v1/companies';
it('should return array of 5 companies by default', (done) => {
Server.inject({
method: 'GET',
url: baseUrl
}, (response) => {
expect(response.statusCode).to.equal(200);
expect(response.result).to.be.an.array().and.have.length(5);
done();
});
});
it('should return array of 3 companies', (done) => {
Server.inject({
method: 'GET',
url: baseUrl + '?limit=3'
}, (response) => {
expect(response.statusCode).to.equal(200);
expect(response.result).to.be.an.array().and.have.length(3);
done();
});
});
it('should throw an error', (done) => {
Server.inject({
method: 'GET',
url: baseUrl + '?limit=me'
}, (response) => {
expect(response.statusCode).to.equal(400);
expect(response.result.error).to.equal('Bad Request');
done();
});
});
});
It works but only if there's a connection to the db which I want to decouple. Any help would be appreciated.
Here's a solution courtesy of devinivy
One approach I've taken is to place queries in server methods, then
stub out the server methods (server.methods.x = stubX) in my tests.
You could also check out proxyquire as suggested by timcosta
Here's the brief github discussion
If I want to configure the binaryMediaTypes [ 'image/jpg', 'text/html' ] for an API through nodejs. What is the right API to use? It looks like the below is not working.
const config = JSON.stringify({
"swagger": "2.0",
"info": {
"title": this.apiName
},
"x-amazon-apigateway-binary-media-types": [ 'image/jpg', 'text/html' ]
});
return new Promise((resolve, reject) => {
var params = {
restApiId: apiId, /* required */
mode: 'merge',
body: config
};
this.apiGatewaySDK.putRestApi(params, (err, data) => {
if (err) {
reject(err);
}
else {
resolve('binary set successfully');
}
});
});
we end up using updateRestApi(). Pls note the patchOpertions part, it is very unintuitive (sth aws sdk could improve? )
let patchOperationsArray = [];
patchOperationsArray.push(
{
op: 'add',
path: '/binaryMediaTypes/'+ e.replace("/", "~1")
}
);
const params = {
restApiId: apiId, /* required */
patchOperations:patchOperationsArray
};
this.apiGatewaySDK.updateRestApi(params, (err, data) => {
if (err) {
reject(err);
}
else {
this.serverless.cli.log('API Gateway Configuring: Binary support are set correctly');
resolve('binary set successfully');
}
});
I have the following code that stage the canvas image and then create object to share it using FB.ui. Staging the image and create the object are working without problem but the share dialog not displayed. If I replaced the image parameter in create object with an image url it is working.
is there any wrong in my code:
var userAccessToken = $("#user_access_token").val();
var appAccessToken = $("#app_access_token").val();
try {
blob = dataURItoBlob(dataURL);
} catch (e) {
console.log(e);
}
var fd = new FormData();
fd.append("access_token", userAccessToken);
fd.append("file", blob);
try {
var imageURI;
$.ajax({
url: "https://graph.facebook.com/me/staging_resources",
type: "POST",
data: fd,
processData: false,
contentType: false,
cache: false,
success: function (data) {
console.log("success " + data['uri']);
imageURI = data['uri'];
},
error: function (shr, status, data) {
console.log("error " + data + " Status " + shr.status);
},
complete: function () {
FB.api(
'https://graph.facebook.com/app/objects/myappnamespace:myobject',
'post',
{
access_token : appAccessToken,
object:{
app_id: myappid,
url: "myappurl",
title: "Sample Photo",
image: {
url:imageURI,
user_generated:true
},
description: ""
}
},
function(response) {
var objectId = response['id'];
FB.ui({
method: 'share_open_graph',
action_type: 'myappnamespace:myaction',
action_properties: JSON.stringify({
myobject:objectId
})
}, function(response){});
}
);
}
});
} catch (e) {
console.log(e);
}
finally I found the solution by changing user_generated parameter from true to false
now the code for creating object looks like below:
FB.api(
'https://graph.facebook.com/app/objects/myappnamespace:myobject',
'post',
{
access_token : appAccessToken,
object:{
app_id: myappid,
url: "myappurl",
title: "Sample Photo",
image: {
url:imageURI,
user_generated:false
},
description: ""
}
}