Unable to create datacontext object for IndexedDB provider using JayData Framework 1.3.1 - jaydata

I'm unable to create datacontext object for IndexedDb provider using Jaydata framework 1.3.1 and getting "FailedProvider fallback failed!" message for $todo.context.onReady().
What is the syntax to define dataprovider for IndexedDB? I found below code in Jaydata documentation, but it doesn't work because " $data.types.storageProviders" API doesn't showing up "indexedDb" class in it.
$news.context = new $news.Types.NewsContext({ name: "indexedDb", databaseName: "NewsReader", dbCreation: $data.types.storageProviders.indexedDb.DbCreationType.DropStoreIfOlderVersion, version: 1 });
<script src="Scripts/jquery-1.7.2.min.js" type="text/javascript"></script>
<script src="Scripts/jaydata.js" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
$data.Entity.extend('$todo.Types.ToDoEntry', {
Id: { type: 'int', key: true, computed: true },
Value: { type: 'string' },
CreatedAt: { type: 'datetime' },
ModifiedAt: { type: 'datetime' },
Done: { type: 'bool' }
});
$data.EntityContext.extend('$todo.Types.ToDoContext', {
TodoEntries: { type: $data.EntitySet, elementType: $todo.Types.ToDoEntry }
});
$('#Button1').click(function (e) {
var provider = "indexedDb";
var options = { name: provider, databaseName: 'todo'};
loadContext(options);
return false;
});
$('#btnAdd').click(function () {
var value = 'ravi';
if (!value) return;
var now = new Date();
var entity = new $todo.Types.ToDoEntry({ Value: value, CreatedAt: now, ModifiedAt: now });
try {
$todo.context.TodoEntries.add(entity);
}
catch (Error) {
alert(Error.Message);
}
$todo.context.saveChanges(updateView);
});
return false;
});
function loadContext(options) {
$todo.context = new $todo.Types.ToDoContext(options);
try {
$todo.context.onReady({
success: function () {
alert("Sucessfully");
},
error: function (error) {
alert("Failed" + error);
$todo.context = null;
},
notify: function (e) {
var result = e.value;
alert('Notify');
}
});
}
catch (Error) {
alert(Error.Message);
}
}
</script>

This happens when you use the library referenced from a local file system and the jaydataproviders folder (and the providers in it) next to jaydata.js. You will need the IndexedDbProvider.js and the InMemory one. These files can be found in the released packages. Package of the latest release

Related

required mongoose validator not working for insertMany?

Model schema:
let mySchema = new mongoose.Schema({
area: {
type: String,
required: true
},
dateUpdated: {
type: Date,
required: true
},
data: {
type: Object,
required: true
},
fileName: {
type: String,
required: true
},
datetimeCreated: {
type: Date,
default: new Date()
},
dateTimeDeleted: {
type: Date
}
}, {
collection: 'my_collection'
});
Sample data to insert:
[{
area: 'Some Area',
// I'm forcing it to be undefined if the data was not provided in attempt to fix the problem,
// but it just gets stored as null
dateUpdated: undefined,
data: {
key1: 1,
key2: 2
},
fileName: 'sample-file.xlsx',
datetimeCreated: 2021-03-03T09:10:51.966Z,
}
];
Insert:
let myModel = new MyModel();
return new Promise((resolve, reject) => {
myModel.collection.insertMany(sortedData, (err) => { ... } });
The process is that you upload an Excel file and there's a column for dateUpdated but if the user left that blank it should return an error when they try to upload the file.
What happens right now is the whole thing still gets uploaded, with dateUpdated just set to null.
Honest mistake.
Instead of using:
let myModel = new MyModel();
return new Promise((resolve, reject) => {
myModel.collection.insertMany(sortedData, (err) => { ... } });
I had to do:
// Not needed --> let myModel = new MyModel();
return new Promise((resolve, reject) => {
// Remove .collection
myModel.insertMany(sortedData, (err) => { ... } });

Hosting a Forge Autodesk viewer on Github

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.

How to make querys when tou have many to many relationships between models?

i am trying to make a game. I need tu create a Match. I think the problem on this Way. The User create a Match. In a third table I save playerId and gameId. When another user join the match, I save again, playerId and gameId. Then, I make a query with player with gameId in common, and start the game.
first, One User may have many Games. second, One Match may have many Games. this is the Match model:
module.exports = {
attributes: {
name: {
type: 'string'
},
description: {
type: 'string'
},
game: {
collection: 'game',
via: 'gameId',
}
}
};
This is the User model:
var bcrypt = require('bcrypt');
module.exports = {
attributes: {
name: {
type:'string'
},
email: {
type: 'email',
required: true,
unique: true
},
password: {
type: 'string',
},
passwordConfirmation: {
type: 'string'
},
passwordEncrypted: {
type: 'string'
},
creator: {
collection: 'game',
via: 'playerId'
},
toJSON: function(){
var obj = this.toObject();
delete obj.password;
delete obj.passwordConfirmation;
delete obj._csrf;
return obj;
}
}, beforeCreate: function(values, next){
console.log("Acabo de entrar a eforeCreate");
var password = values.password;
var passwordConfirmation = values.passwordConfirmation;
if(!password || !passwordConfirmation || password != values.passwordConfirmation) {
var passwordDoesNotMatchError = [{
name: 'passwordDoesNotMatchError',
message: 'Las contraseñas deben coincidir'
}]
return next({
err: passwordDoesNotMatchError
});
}
require('bcrypt').hash(values.password, 10, function passwordEncrypted(err, EncryptedPassword){
values.EncryptedPassword = EncryptedPassword;
next();
});
}
};
This is the Game model:
module.exports = {
attributes: {
gameId: {
model: 'match'
},
playerId: {
model: 'user'
}
}
};
finally, this is my controller:
module.exports = {
createMatch: function(req,res){
var matchObj = {
name: req.param('name'),
description: req.param('description'),
}
Match.create(matchObj, function(err, match){
if(err){
console.log("el error fue: " + err);
return res.send(err);
} console.log("Entro en create");
return res.json(match);
})
var gameObj = {
gameId: 'aclaration: I dont know how do I get the match.id',
playerId: req.session.me
}
Game.create(gameObj,function(err,game){
console.log("entro a GameCreate");
if(err){
return res.send(err);
} return res.json(game);
})
}
};
I can create the Match, but Game.create send this error:
_http_outgoing.js:344 throw new Error('Can\'t set headers after they are sent.'); ^
Error: Can't set headers after they are sent.
Somebody can help me? probably, I have many errors. Thanks.
Couple of things here:
Having an explicit Game model is not required in Sails. It can manage it implicitly, unless you want to store more information than just gameId and userId. So, you can just do away with Game model.
Please refer for async programming: How do I return the response from an asynchronous call?
Below code should work for you. Hope it helps.
module.exports = {
createMatch: function(req, res) {
var matchObj = {
name: req.param('name'),
description: req.param('description'),
};
Match.create(matchObj, function(err, match) {
if (err) {
console.log("el error fue: " + err);
return res.send(err);
}
console.log("Entro en create");
var gameObj = {
gameId: match.id,
playerId: req.session.me
};
Game.create(gameObj, function(err, game) {
console.log("entro a GameCreate");
if (err) {
return res.send(err);
}
return res.json(game);
// return res.json(match);
});
});
}
};

Get slug from object in view won't work

I have created a new object named Project, that contains a gallery and some other fields in it. In the view, I'm showing some data from it and I want to put a link to previous and next project. I already managed to get the previous project but when I try to get the slug from it, somehow it doesn't work.
This is the Project model:
var keystone = require('keystone');
var Types = keystone.Field.Types;
/**
* Project Model
* ==========
*/
var Project = new keystone.List('Project', {
map: { name: 'title' },
autokey: { path: 'slug', from: 'title', unique: true }
});
Project.add({
title: { type: String, required: true },
state: { type: Types.Select, options: 'draft, published, archived', default: 'draft', index: true },
author: { type: Types.Relationship, ref: 'User', index: true },
publishedDate: { type: Types.Date, index: true, dependsOn: { state: 'published' } },
category: { type: String, required: false },
description: { type: Types.Html, wysiwyg: true, height: 150 },
shortDescription: { type: Types.Html, wysiwyg: true, height: 100 },
credits: { type: Types.Html, wysiwyg: true, height: 100 },
galleries: { type: Types.Relationship, ref: 'Gallery', many: false },
color: { type: String, required: false }
});
Project.schema.virtual('content.full').get(function() {
return this.content.extended || this.content.brief;
});
Project.defaultColumns = 'title, state|20%, author|20%, publishedDate|20%';
Project.register();
This is the controller:
var keystone = require('keystone');
exports = module.exports = function(req, res) {
var view = new keystone.View(req, res);
var locals = res.locals;
// Set locals
locals.section = 'projects';
locals.filters = {
project: req.params.project
};
locals.data = {
projects: [],
previousProject: []
};
// Load the current project
view.on('init', function(next) {
var q = keystone.list('Project').model.findOne({
state: 'published',
slug: locals.filters.project
}).populate('galleries');
q.exec(function(err, result) {
locals.data.project = result;
next(err);
});
});
//Load other projects
view.on('init', function(next) {
var q = keystone.list('Project').model.find({state: "published", publishedDate: {$lt: locals.data.project.publishedDate}}).sort('-publishedDate').limit(1);
q.exec(function(err, results) {
locals.data.previousProject = results;
next(err);
});
});
// Render the view
view.render('project');
};
And this is the view:
<div class="container">
<p>{{{data.project.title}}}</p>
<p>—</p>
<p>{{{data.project.category}}}</p>
{{#if data.project.galleries}}
{{#each data.project.galleries.images}}
<img src="{{url}}" />
{{/each}}
{{/if}}
<p>full project: {{data.previousProject}}</p>
<p>slug: {{data.previousProject.slug}}</p>
{{#if data.previousProject}}
<a href="/projects/{{data.previousProject.slug}}" >Previous project</a>
{{/if}}
</div>
Somehow, {{data.previousProject}} shows the correct record info but when I do {{data.previousProject.slug}} it returns nothing at all. I've been scratching my head against this for hours but I can't find where is the issue. Thanks in advance!!
I finally found what the issue was: in the controller I'm using model.find whereas I should be using model.findOne if I know I only need one record and I want to directly get the values from it with .slug. Using limit(1) was not enough.

ng-repeat showing functions names and data

I'm a beginner with angularjs and mongolab ..
I have this code, to edit a record in mongolab :
function EditCtrl($scope, $location, $routeParams, Project) {
var self = this;
Project.get({id: $routeParams.projetId}, function(projet) {
self.original = projet;
$scope.projet = new Project(self.original);
});
$scope.save = function() {
$scope.projet.update(function() {
$location.path('/list');
});
};
}
It works perfectly.
I wanted to display all the keys and values from the record, this is the code :
<div ng-repeat="(key, val) in projet">
<div>{{key}}:{{val}}</div>
</div>
And this is the result :
_id:{}
destroy:
name:Test test
rang:4
update:
In my record, i only have the _id, name and rang. I don't know why "destroy:" dans "update:" are displayed! probably because i use this code to connect to mongolab :
angular.module('mongolab', ['ngResource']).
factory('Project', function($resource) {
var Project = $resource('https://api.mongolab.com/api/1/databases' +
'/_____/collections/_________/:id',
{apiKey: '___________________'}, {
update: {method: 'PUT'}
}
);
Project.prototype.update = function(cb) {
return Project.update({id: this._id.$oid},
angular.extend({}, this, {_id: undefined}), cb);
};
Project.prototype.destroy = function(cb) {
return Project.remove({id: this._id.$oid}, cb);
};
return Project;
});
What should i do to only display the record data ?
thanks
Return a service and pass the item you receive from get() back to update and destroy.
factory('Project', function($resource) {
return {
get: function() {
return $resource('https://api.mongolab.com/api/1/databases' +
'/_____/collections/_________/:id',
{apiKey: '___________________'}, {
update: {method: 'PUT'}
},
update : function(itm, cb) {
return item.update({id: item._id.$oid},
angular.extend({}, item, {_id: undefined}), cb);
},
destroy : function(item, cb) {
return item.remove({id: item._id.$oid}, cb);
};
Otherwise you can instantiate only one and reference it
factory('Project', function($resource) {
var item =$resource('https://api.mongolab.com/api/1/databases' +
'/_____/collections/_________/:id',
{apiKey: '___________________'}, {
update: {method: 'PUT'}
return {
update : function(cb) {
return item.update({id: item._id.$oid},
angular.extend({}, item, {_id: undefined}), cb);
},
destroy : function(cb) {
return item.remove({id: item._id.$oid}, cb);
};