How do I get a collection of files that are in 'checked-in' status at any point of time? Using plone 4.1. Checked-in is not a workflow status. It is a file that has been locked by a user while editing so that the other user cannot access the latest copy before the former has unlocked the file by 'check-in'. I want to know if I can have a collection to display a list of all the files that have been locked i.e 'check-out' or have 'check-in' status at any point of time.
Since checked-in objects are indistinguishable from "normal" published objects, there is probably no easy way to create such a collection.
A few workarounds come to mind:
Look for checked out objects by searching for objects in the private state whose ids begin with "copy_of"
Check for "published" objects.
Create a custom workflow that contains an additional "checked-in" state and (somehow) use the checked in state for objects that have been checked out and checked back in at least once.
None of these are particularly attractive so a catalog search for published items is probably your best bet:
>>> [brain.getObject().getId() for brain in portal.portal_catalog(
review_state="published")]
['front-page', 'news', 'aggregator', 'events', 'aggregator', 'Members']
Which you can compare with a list of all objects if you like:
>>> [brain.getObject().getId() for brain in portal.portal_catalog()]
['front-page', 'news', 'aggregator', 'events', 'aggregator', 'Members',
'copy_of_front-page']
You don't need to do this programmatically, just wanted to demonstrate the difference between searching for published objects vs all objects. The latter returns an additional checked out object (in the private state).
It's possible with this approach:
Add a new field 'Has workingcopy' to all ATCT's via the famous schemaextender.
Register the field in the catalog, to make it available to collections.
Listen to eventhandlers to set the field to true, when a workingcopy is created and to False when it's chekced-out or canceled.
I wrote a package for this, because I need it anyway for a project soon: adi.workingcopyflag
Since the checked-in/checked-out state is not indexed in portal_catalog there is no way to make the information available to a collection.
Related
Dear StackOverflow community,
For a project of mine I need to store (Temporary) data somewhere else than a Database. Actually its a little more complicated. I have a checkout page in NopCommerce where users can select them delivery moment or even location for example pickup. This data has to be store temporary untill the user made the payment. Only then I will request the data and store in DB. So that later I can retrieve the data and display in my dashboard, So that I know when the package is scheduled to be shipped.
Requirements:
Endurement: 12-24 Hours.
Store as user specific data.
Data has to be safed for quite a few sessions. Depends on the user. For example. If the user chooses a delivery moment but desides to look somewhere else before paying. This data has to be stored all those sessions.
If possible serverside.
I have quite a few options following Microsoft:
Session and state management in ASP.NET Core
Now I have tried storing data in Memory (Caching data) using 'MemoryCacheEntryOptions'. The problem is that its application wide. And its hard to maintain with hundreds of users.
Other option is 'Session state'.
The problem is that this data only endures a single session. I need to hold the data for atleast 12 to 24 hours.
Then we have 'Temp Data'. This seems like a promising option. Its great since it is kept until the is has been used/read. You even have 'Peek' and 'Keep' Methods to keep the data while peeking. Problem: It requires a controller. And requesting the data is a callback Method that doesnt require a Controller.
'Query Strings' Well its not much is it? This may be not user critical data BUT seems like query string isnt what Im looking for.
'Hidden Fields' Not really suitable either. It is therefore not form data.
'HttpContext.Items' Definetly not suitable. Data is only stored for single request.
'Cache' Way to hard to maintain user specific data.
So my question is. How do I save all this data temporary, if possible server side for a day atleast with hundreds of users at the same moment. And request the data later in a callback, to store it in DB until the order is shipped.
NopCommerce exposes a class called GenericAttributeService in Nop.Services.Common. This allows you to store your custom attribute data, specific to each customer.
To use it, first inject the GenericAttributeService into your class (controller, service class, etc).
private readonly IGenericAttributeService _genericAttributeService;
public MyFancyController(IGenericAttributeService genericAttributeService)
{
_genericAttributeService = genericAttributeService;
}
To save the data for current customer, use SaveAttribute and save an key-value pair you need:
_genericAttributeService.SaveAttribute<string>(_workContext.CurrentCustomer, "MyKeyName", "Value to save for this customer")
_genericAttributeService.SaveAttribute<int>(_workContext.CurrentCustomer, "My2ndKeyName", model.id)
To get the data use GetAttributesForEntity, where the entity is your key value.
var attribute = _genericAttributeService.GetAttributesForEntity(_workContext.CurrentCustomer.Id, "Customer").Where(x => x.Key == "MyKeyName").FirstOrDefault();
To delete the attribute use DeleteAttribute:
_genericAttributeService.DeleteAttribute(attribute);
Notice that we used _workContext which helps expose the current customer.
This already works well with other temp functionality already existing in the application, such as managing shopping carts, wish lists, etc, so browsing the source code for other examples can also be helpful.
I have an app using React + Redux and coupled with Firebase for the backend.
Often times, I will want to add some new attributes to existing objects.
When doing so, existing objects won't get the attribute until they're modified with the new version of the app that handles those new attributes.
For example, let's say I have a /categories/ node, in there I've got objects such as this :
{
name: "Medical"
}
Now let's say I want to add an icon field with a default of "
Is it possible to update all categories at once so that field always exists with the default value?
Or do you handle this in the client code?
Right now I'm always testing the values to see if they're here or not, but it doesn't seem like a very good way to go about it. I'd like to have one place to define defaults.
It seems like having classes for each object type would be interesting but I'm not sure how to go about this in Redux.
Do you just use the reducer to turn all categories into class instances when you fetch them for example? I'm worried this would be heavy performance wise.
Any write operation to the Firebase Database requires that you know the exact path to the node that you're writing.
There is no built-in operation to bulk update nodes with a path that is only partially known.
You can either keep your client-side code robust enough to handle the missing properties, or you can indeed run a migration script to add the new property to each relevant node. But since that script will have to know the exact path of each node to write, it will likely first have to read/query the database to determine those paths. Depending on the number of items to update, it could possibly use multi-location updates after that to update multiple nodes in one call. E.g.
firebase.database().ref("categories").update({
"idOfMedicalCategory/icon": "newIconForMedical",
"idOfCommercialCategory/icon": "newIconForCommercial"
"idOfTechCategory/icon": "newIconForTech"
})
I have a transmogrifier pipeline to insert objects to my Zope database (importing zexp files from a directory structure). This works - the objects are created; but I don't get them added to the portal_catalog.
I added a section to add the objects to the catalog explicitly, inspired by plone.app.transmogrifier.reindexobject: I call portal_catalog.catalog_object(obj) for each item.
The objects exist, and getPhysicalPath yields the correct values, but the objects are not added. There is no error message or exception whatsoever.
I tried to specify the list of indexes (the idxs argument), but this didn't change anything. If not specified, all indexes should be filled anyway, right?
Since it looks like a transaction problem to me (no errors, but nothing stored in the catalog either), I tried transaction code (begin, savepoint, commit, and in case of exceptions abort), but it didn't help. When I call the catalog immediately after the catalog_object call (portal_catalog(path='/Plonesite/full/path/to/object')), nothing has happened, and an empty list is returned.
The catalog does contain objects; even objects of my custom datatypes (AT-based). Not even the Folder objects of my imports are indexed.
Without the objects in the catalog, my import is useless. What can I do?
Thank you!
Edit: Any hint about how to get my object trees in the catalog is appreciated! Even if it can't be integrated in my process. I need the contents cataloged ...
My custom content types are contained in the Plone Catalog Tool page selection field, but I don't know whether this is sufficient.
Edit 2:
Somehow my objects have been catalogued - the unrestrictedSearchResults method shows them! However, it can't be the desired solution to use this method all over; so I need to "un-restrict" the entries somehow.
It turned out that I have a monkey:patch (xmlns:monkey="http://namespaces.plone.org/monkey") for the Products.CMFPlone.CatalogTool.CatalogTool.searchResults method; this filters the catalog for my additional field subportal unless a special value for it is given - even in the management view ... Unfortunately, I had no way to specify this special value in that view.
Thus, the solution was to weed out all wrong values (for subportals which don't exist in the other Zope tree) to have the default value take effect.
Quite specific to my setup, I'm afraid ...
I need a help for while creating the collection the below error is came in server console.How to solve the error ?
Error:
Warning: creating anonymous collection. It will not be saved or synchronized over the network. (Pass null for the collection name to turn off this warning.)
TLDR: you need to provide a collection name as an argument when you create a shared collection.
In most cases, you want to provide a name as a parameter when you define a collection:
Docs = new Meteor.Collection('docs');
When you don't, you create anonymous collection:
Items = new Meteor.Collection();
In the first case, the collection is shared and synchronized between client and server, and the name you've provided is used as a table name in order to store the collection in Mongo.
Anonymous collections are local in the place they've been created. Their contents are never synchronized. Therefore, even if you create such collection in a piece of code that will be run on the server and on the client, those two collections will be separate things: data created on the server won't be visible on client, data created on the client won't be visible on server, and both won't be stored in the database.
There are legitimate use cases for anonymous collections, mostly on the client side when you need to create some temporary data, but want to retain all the benefits of Minimongo and reactivity. However, it's one of those things that are needed rarely and you really do know when you need to do it. It's more probable that a beginner made a mistake and forget to provide the collection name when he wanted to create a typical shared collection. Therefore, the system issues a warning to make sure that you really wanted to do what you just did.
Therefore:
If your goal was to create an anonymous collection, and you know what you're doing, don't worry about that message. It's just a warning, the code will be functional and do what it's told to.
If you wanted to create a normal collection, or are just starting out and don't know what's this all about, just add a parameter to your collection definition.
I've come up with the mapping that follows while working on the REST API of a system where users are able to create and manage resources of different types.
// READ OPERATIONS
GET /objects => read collection meta
GET /objects/[id] => read single element
GET /objects/?[query] => read a number of elements
GET /objects/?all => read all elements
// CREATE / UPDATE OPERATIONS
PUT /objects => possibly create the collection and update its meta
PUT /objects/[id] => possibly create and update a single element
PUT /objects/?all => update the entire content of the collection
POST /objects => create new objects or update existing objects
PATCH /objects => partially update the collection meta
PATCH /objects/[id] => partially update a single element
PATCH /objects/?all => partially update all the elements
PATCH /objects/?[query] => partially update a number of elements
// DELETE OPERATIONS
DELETE /objects => delete the collection
DELETE /objects/[id] => delete a single element
DELETE /objects/?all => empty the collection
DELETE /objects/?[query] => delete a number of elements
Here's some more information on the system:
each resource can be either be a simple one or a collection-like one;
each resource, collection or not, has properties of its own that need to be accessed and manipulated;
the API must support bulk (not batch) operations.
I've also examined the following alternatives:
using /collection to access the collection's set of elements and /collection?meta to access the collection's own data;
using a whole new resource to access a collection's own data, such as /collections/path/to/collection.
I do not like alternative n. 1) because it feels, to me, semantically poor. By comparison, when I refer to a box I am actually referring to the box in itself and not to its content.
I do not like alternative n. 2) because a resource ends up having its own data exposed by another resource, duplicating urls and making the problem of "which url should I use" not that trivial as I'd like it to be.
Therefore, my questions:
Is the mapping I have proposed a valid, proper mapping for a REST API? Is it respectful of REST principles? I'm not asking whether it's the best mapping out there or not. I'm asking about its validity.
If not, which one of the alternatives is the better one and why?
Please excuse my english, I'm not a native speaker of the language.
I thought the API design looked OK, but then I re-read this comment of yours at the start:
where users are able to create and manage resources of different
types.
If the resources of your system are of different types, why are you exposing them with a neutral, type-less API that works only with generic objects?
The first part of RESTful API design is the identification of the nouns in your system, and those nouns should be considered strongly as candidates for exposure as URIs. I would strongly encourage you to try and get more specific than object and model the business functionality of your system with clearer URIs.
And your English is fine!
First of all, the semantics of URIs aren't relevant to REST. "RESTful URI" is almost an oxymoron. The only constraint an URI must follow to be RESTful is that it references one and only one resource.
Obviously, that doesn't mean REST URIs can be obscure. They should be as clear, intuitive and descriptive as possible, but whatever scheme you decide to use is fine, as long as its consistent. If you're so concerned with this, it means you're probably not using HATEOAS and should take a look at it.
Second, you're not considering the media types, and that's why you end up with the problem of using URIs to designate different media types. Let's say that retrieving all elements of a collection should be simply:
GET /objects
And retrieving a single element of a collection should be:
GET /objects/[id]
Now, if the client needs only the metadata for a resource, either a collection or a single element, it should specify that through the Accept header, not by going to a separate URI you point to in the documentation, or even worse, by adding query string parameters.
So, for instance, if the media type for your object is application/vnd.mycompany.myobject+json, your clients get the full object representation when using that media type in the Accept header, and get the metadata by using something like application/vnd.mycompany.myobjectmetadata+json.
I guess this probably isn't what you expected, but that's what REST is. Your documentation and design effort should be focused on your media types, not your URIs. When you use HATEOAS, URI design is irrelevant, and if you're not using HATEOAS, you're not using REST.