Update feature using protocol don't work in OpenLayers - protocols

I have a WMS layer and I need to update the attributes of one of its features.
So I created a protocol object using OpenLayers.Protocol.WFS.fromWMSLayer, and filtering for the feature ID; then using read() method I get the feature from the response and I have ehat I expect.
var protocol = OpenLayers.Protocol.WFS.fromWMSLayer(layerFeatureHighlighted, {
filter: currentFilter
});
Then I update the state and the attributes of the feature object:
featureObj.state = OpenLayers.State.UPDATE;
featureObj.attributes['myAttribute1'] = myValue1;
featureObj.attributes['myAttribute2'] = myValue2;
featureObj.attributes['myAttribute3'] = myValue3;
The problem is that when finally I try to save the changes, the changes are not saved into the database:
protocol.update(featureObj);
How can I save the changes?
Thank
stefano

Related

Data tracking in DocumentDB

I was trying to keep the history of data (at least one step back) of DocumentDB.
For example, if I have a property called Name in document with value "Pieter". Now I am changing that to "Sam", I have to maintain the history , it was "Pieter" previously.
As of now I am thinking of a pre-trigger. Any other solutions ?
Cosmos DB (formerly DocumentDB) now offers change tracking via Change Feed. With Change Feed, you can listen for changes on a particular collection, ordered by modification within a partition.
Change feed is accessible via:
Azure Functions
DocumentDB (SQL) SDK
Change Feed Processor Library
For example, here's a snippet from the Change Feed documentation, on reading from the Change Feed, for a given partition (full code example in the doc here):
IDocumentQuery<Document> query = client.CreateDocumentChangeFeedQuery(
collectionUri,
new ChangeFeedOptions
{
PartitionKeyRangeId = pkRange.Id,
StartFromBeginning = true,
RequestContinuation = continuation,
MaxItemCount = -1,
// Set reading time: only show change feed results modified since StartTime
StartTime = DateTime.Now - TimeSpan.FromSeconds(30)
});
while (query.HasMoreResults)
{
FeedResponse<dynamic> readChangesResponse = query.ExecuteNextAsync<dynamic>().Result;
foreach (dynamic changedDocument in readChangesResponse)
{
Console.WriteLine("document: {0}", changedDocument);
}
checkpoints[pkRange.Id] = readChangesResponse.ResponseContinuation;
}
If you're trying to make an audit log I'd suggest looking into Event Sourcing.Building your domain from events ensures a correct log. See https://msdn.microsoft.com/en-us/library/dn589792.aspx and http://www.martinfowler.com/eaaDev/EventSourcing.html

MongoDB update object and remove properties?

I have been searching for hours, but I cannot find anything about this.
Situation:
Backend, existing of NodeJS + Express + Mongoose (+ MongoDB ofcourse).
Frontend retrieves object from the Backend.
Frontend makes some changes (adds/updates/removes some attributes).
Now I use mongoose: PersonModel.findByIdAndUpdate(id, updatedPersonObject);
Result: added properties are added. Updated properties are updated. Removed properties... are still there!
Now I've been searching for an elegant way to solve this, but the best I could come up with is something like:
var properties = Object.keys(PersonModel.schema.paths);
for (var i = 0, len = properties.length; i < len; i++) {
// explicitly remove values that are not in the update
var property = properties[i];
if (typeof(updatedPersonObject[property]) === 'undefined') {
// Mongoose does not like it if I remove the _id property
if (property !== '_id') {
oldPersonDocument[property] = undefined;
}
}
}
oldPersonDocument.save(function() {
PersonModel.findByIdAndUpdate(id, updatedPersonObject);
});
(I did not even include trivial code to fetch the old document).
I have to write this for every Object I want to update. I find it hard to believe that this is the best way to handle this. Any suggestions anyone?
Edit:
Another workaround I found: to unset a value in MongoDB you have to set it to undefined.
If I set this value in the frontend, it is lost in the REST-call. So I set it to null in the frontend, and then in the backend I convert all null-values to undefined.
Still ugly though. There must be a better way.
You could use replaceOne() if you want to know how many documents matched your filter condition and how many were changed (I believe it only changes one document, so this may not be useful to know). Docs: https://mongoosejs.com/docs/api/model.html#model_Model.replaceOne
Or you could use findOneAndReplace if you want to see the document. I don't know if it is the old doc or the new doc that is passed to the callback; the docs say Finds a matching document, replaces it with the provided doc, and passes the returned doc to the callback., but you could test that on your own. Docs: https://mongoosejs.com/docs/api.html#model_Model.findOneAndReplace
So, instead of:
PersonModel.findByIdAndUpdate(id, updatedPersonObject);, you could do:
PersonModel.replaceOne({ _id: id }, updatedPersonObject);
As long as you have all the properties you want on the object you will use to replace the old doc, you should be good to go.
Also really struggling with this but I don't think your solution is too bad. Our setup is frontend -> update function backend -> sanitize users input -> save in db. For the sanitization part, we use a helper function where we integrate your approach.
private static patchModel(dbDocToUpdate: IModel, dataFromUser: Record<string, any>): IModel {
const sanitized = {};
const properties = Object.keys(PersonModel.schema.paths);
for (const key of properties) {
if (key in dbDocToUpdate) {
sanitized[key] = data[key];
}
}
Object.assign(dbDocToUpdate, sanitized);
return dbDocToUpdate;
}
That works smoothly and sets the values to undefined. Hence, they get removed from the document in the db.
The only problem that remains for us is that we wanted to allow partial updates. With that solution that's not possible and you always have to send everything to the backend.
EDIT
Another workaround we found is setting the property to an empty string in the frontend. Mongo then also removes the property in the database

Orchard background task not persisting PartRecords to the database

I'm trying to use a background task to gather Likes/Comments from the Facebook Graph APi and use that to drive our blog's trending.
Here the trendingModels have already been populated and are being used to fill in the TrendingParts.GraphId and TrendingParts.TrendingValue.
I'm not getting any exceptions and the properties on TrendingPart point to the fields in the TrendingPartRecord.
Yet nothing persists to the database, any ideas why?
_orchardsServices is IOrchardServices
var articleParts = _orchardService.ContentManager.GetMany<TrendingPart>(
trendingModels.Select(r => r.OrchardId).ToList(),
VersionOptions.Published,
QueryHints.Empty);
// Cycle through the records and update them from the matching model
foreach (var articlePart in articleParts)
{
ArticleTrendingModel trendingModel = trendingModels.Where(r => r.OrchardId == articlePart.Id).FirstOrDefault();
if(trendingModel != null)
{
// Not persisting to the database, WHY?
// What's missing?
// If I'm understanding things properly nHibernate should push this to the db autoMagically.
articlePart.GraphId = trendingModel.GraphId;
articlePart.TrendingValue = trendingModel.TrendingValue;
}
}
Edit:
It's probably worth noting that I can update and publish the fields on the TrendingPart in the admin panel but the saved changes don't appear in the MyModule_TrendingPartRecord table.
The solution was to change my Service to a transient dependency using ITransientDependency.
The service was holding a reference to the PartRecords array and because it was treated as a Singleton it never disposed and the push to the database was never made.

How to discover all Entity Types? One of each?

I need to write a service that connects to CRM, and returns with a list of all of the entity available on the server (custom or otherwise).
How can I do this? To be clear, I am not looking to return all data for all entities. Just a list of every type, regardless of whether any actually exist.
You need to use RetrieveAllEntitiesRequest
RetrieveAllEntitiesRequest request = new RetrieveAllEntitiesRequest()
{
EntityFilters = EntityFilters.Entity,
RetrieveAsIfPublished = true
};
// service is the IOrganizationService
RetrieveAllEntitiesResponse response = (RetrieveAllEntitiesResponse)service.Execute(request);
foreach (EntityMetadata currentEntity in response.EntityMetadata)
{
string logicalName = currentEntity.LogicalName;
// your logic here
}
note that you will get also system or hidden entities, like wizardpage or recordcountsnapshot
You will probably find these sections of the MSDN useful:
Customize Entity Metadata (lookout for the samples linked on that page).
Retrieve and Detect Changes to Metadata.

Saving per-user or per-document preferences in a Photoshop script

I'm working on a Photoshop script in JavaScript using ExtendScript. My script allows some user input, and I'd like to save it between uses. That is, I'm looking for a way to save a simple string or numeric value under a particular key so that I'll be able to access it on subsequent uses of the script. Simply put, I want to save a preference for my script. How do I do that?
Even better would be to be able to save at least some preferences on a per-document basis. Is that possible? That is, can I store an arbitrary bit of data with a document?
You can use put/get custom options to save preference parameters that persist across Photoshop launches:
const kMyFlag = app.stringIDToTypeID( "myFlag" );
const kMyNumber = app.stringIDToTypeID( "myNumber" );
const kMySettings = "mySettings";
function saveSettings()
{
var desc = new ActionDescriptor();
desc.putBoolean(kMyFlag, true);
desc.putInteger(kMyNumber, 42);
// "true" means setting persists across Photoshop launches.
app.putCustomOptions( kMySettings, desc, true );
}
function getSettings()
{
var desc = app.getCustomOptions( kMySettings );
return [desc.getBoolean( kMyFlag ), desc.getInteger( kMyNumber )];
}
You have some options. You can create a text file and write to it using the File object:
var prefs = new File("~/desktop/prefs.txt");
prefs.open("w"); // or "a" to append
prefs.writeln("user:lenny;favorite_color:ff6600;likes:sunsets;");
...if you wanted your preferences tied to the script itself.
If you want per-document preferences you could write a string to one of the metadata fields of the file your working on using Document.info like this (using the 'instructions' field but you could use any writable field):
var doc = app.activeDocument;
doc.info.instructions = "user:lenny;favorite_color:ff6600;likes:sunsets;";
//alert(doc.info.instructions); // see, it works!
As for how to actually format the string you could just do it like a simple config file or, if you have a complex user preferences object you could use the XML object to construct and serialize it. JSON would be great for this but there is no JSON object in Extendscript, unfortunately.
For per-document prefs I suggest the use of the XMP Metadata. You can find example snippet here: http://forums.adobe.com/thread/790973. You can leverage AdobeXMPScript library to create your own namespace like it is suggested in the link by Paul Riggott.

Resources