OrchardCMS / Orchard

Orchard is a free, open source, community-focused Content Management System built on the ASP.NET MVC platform.
https://orchardproject.net
BSD 3-Clause "New" or "Revised" License
2.37k stars 1.12k forks source link

Use dynamic forms for edit content on the front-end #6163

Open sebastienros opened 8 years ago

sebastienros commented 8 years ago

Not sure if this is doable today. A usage would be to edit a profile for a user. It need edit rights management, a custom url to find the content item. And a part to select which form is used to edit, per type.

sebastienros commented 8 years ago

Apparently dynamic forms doesn't support editing existing data, just submitting an empty form.

sfmskywalker commented 8 years ago

Correct, we would need to add support for this. Currently the form bindings works in one direction (form field -> content part/field). But I made this API awesome so it will be easy to make it two-way.

mattcowen commented 8 years ago

@sebastienros don't know if it helps but I have successfully used tokens to update existing data via a dynamic form. In my case, the tokens wrapped a web service request to update user profile related info but it could easily pull in existing content items. I found it relatively easy to do. @sfmskywalker it was indeed awesome :+1:

Just as an aside, one thing I couldn't get working was binding an enumeration field to a collection of data e.g. list of countries. Don't suppose you know of a working example of that?

sfmskywalker commented 8 years ago

@mattcowen Actually, if that list of countries are content items, you could use the Query element (which is like the Enumeration element, but uses a Query as its source of items). Or, if your countries are Taxonomy terms, you could use the Taxonomy element, which also serves the same purpose the Enumeration element but using a Taxonomy's terms as the source for the list of items. And if your countries are stored in a regular database table, the Query and Taxonomy elements should be good examples of how to build your own element that feeds from that table.

mattcowen commented 8 years ago

Thanks for the pointers. My plan was to grab the countries from the .NET globalization namespace.

Just out of interest, do we want to make tokens work for binding collections? If I wanted to submit a PR for getting tokens to work for this, can you advise where best to do it? I've spent a bit of time looking into it and I am thinking that it would be done in the EnumerationElementDriver.OnDisplaying method however that seemed to be the token text such as "{Countries}" instead of a collection of select items (which is what you get if you create the options in the normal manual way). If you can point me in the right direction I don't mind giving the implementation a go.

remesq commented 8 years ago

There doesn't seem to be a way to upvote proposed changes. So please consider this an upvote. :)

jersiovic commented 8 years ago

I have just finished a modification of DynamicForms module to support edition of an existing content item from a dynamic form. In order to do so I have extended BindingDescriptor to support two way bindings adding a getter. It also adds extra permissions for configuring dynamic forms to allow add or edit actions independently. This extension is also aware of EditContent/EditOwnerContent permissions of the edited content. In that way admin can limit the edition of contents for a user for only those contents owned by the user.

I have made this changes on 1.10 branch but I have avoided to introduce any breaking change so it could be merged on 1.10.x. Can I send a PR for 1.10.x or is it better I submit it to dev?

jersiovic commented 8 years ago

Here it is the commit in our repository that still is on 1.10 branch (not 1.10.x) https://github.com/xkproject/Orchard/commit/01e5e5f50732c23beff6c0a0b3802a8e8ba5686e

sebastienros commented 8 years ago

We need a demo first, you'll already get some feedback.

jersiovic commented 8 years ago

Ok, great. I'm improving things after last commit. I will ask for the demo as soon as it is ready.

jersiovic commented 8 years ago

Well, I have implemented it but I have some doubts I would like to clarify before demo it. So next you have and explanation of what I have done and some doubts related with it.

How it works?

In the properties of the form you have to have checked the checkbox Add/Edit Content Item (it is the same property used previously, I only have changed the label to avoid breaking changes.

Showing values in the form for edition

  1. FormElementDriver expects a Query string param: {formName}Form_edit={contentId}
  2. The form template adds a hidden field with that content id.
  3. Load content item to a NameValueCollection of named values expected by the form. In order to do so I have added a new getter property to BindingDescriptor.
  4. Next steps are the same as when a content item is added.

Submitting

  1. Get id from hidden field, and instead of creating a new content item, it is loaded from db
  2. Next steps are the same as when a content item is added

What is checked?

Permissions doubts and solutions developed for the PR:

Permissions at form level?

Do we need permissions at site level, content type level, content item level and form level? Or maybe at form level is a bit too much? SOLUTION PROVIDED: I have provided permissions at all four levels (A typical developer sin ;) : to do it because it can be done, but it is really needed?). It is useful if you have multiple forms in the same page and they require different permissions e.g: one form for subscribing to a newsletter and another for editing data of a content item.

How to separate permissions for adding and edit?

I see two options to separate permissions for adding and for editing a content item:

FIRST OPTION

  1. To have permission specifically for forms separated from the core ones: Submit Form, Submit Form For Modify Data Owned by Others, Submit Form for Modify Own Data.

SECOND OPTION

  1. To have permission Submit Form related to content types/content items with a layout part.
  2. Instead of having Add and Edit permission together in EditContent Permission we would need to split it in two adding an extra permission AddContent to core permissions. In that way we will control permissions for edit or add a content item based on the permissions established for the type we are going to add or edit through the form. So, we will need to set Permission for submitting the form and also permission related to the content item for adding or editing.
  3. Take into account that neither EditContent nor Edit Own Permission won't imply permission for add as it was till now.

Doubts

I have implemented the FIRST OPTION, but now I think it will be cleaner second one. Why?, Well this is my current scenario: I'm adding a Delete button in my forms when they are in edition mode. Furthermore, next to each item shown in a projection I show also a link to delete content items. I will need to offer a controller in a custom module for delete action (if it doesn't exist). In this context, I will set core Delete or Delete Own Permission for content types I'm interested in. The point is sometimes using core permissions and sometimes form related ones doesn't seem a clean solution. So I'm thinking on changing to SECOND SOLUTION. Even for a future PR even offer a Delete Button Element for layouts. When it will be rendered to the user it only will be shown when form is editing a content item, and by the way it will offer an action through a controller for deleting content items related to a form that can be harnessed in other situation like a delete link for each content item in a projection.

What do you think? Permissions at Form Level is too much? Do we split EditContent Permission or do we maintain parallel permissions: forms & core? Take into account we will need to add a migration for avoiding unexpected behaviours with permission after upgrade to this Orchard version Is interesting to add to dynamic form module support for delete a content item shown by a form?

Cheers

Skrypt commented 8 years ago

An example of this kind of implementation would be to me a POS (Point of Sale). Normally, you would just post form elements to create content items. Editing them afterward would be done in the background admin "wich already implements permissions".

I want to see a demo to understand better what you did first. But, it sounds like you could almost rebuild the entire admin interfaces from the Layouts, wich sounds nice. I'm a little worried about security and it is true that it needs to be implemented right "I understand your doubts".

I would go with the second implementation wich seems more fine tuned.

jersiovic commented 8 years ago

Thank you for the comment.

I will make an attempt of demo today in the meeting if comittee agrees. I say an attempt because on previous attempts I wasn't able to share my screen in the meeting through Skype for business app due to some unknown limitation on my home internet connection. I have changed some settings to try to fix the problem ... so I will make a try.

jersiovic commented 8 years ago

After demo it an after a conversation with @sebastienros just for the record this is the state of the feature:

My requirements and scenario were a bit different from the original ones from @sebastienros . His scenario was to have a way for modifying user data (profile) though dynamic form. My requirements was to have different dynamic forms that allow user to add/modify/delete content items with permissions related to the form. In my scenario I have for example a type boat editable with two different dynamic forms, one provides access to some fields, and the other form to other fields. Each dynamic form is accessible to different roles so the permissions for accessing the form is who determine what can be done with the content item not the permissions for accessing the content item itself. Depending on how it is implemented second scenario can solve also first scenario.

Current changes proposed to implement the feature, https://github.com/OrchardCMS/Orchard/compare/1.10.x...xkproject:%236163editDynForms

Code for sure will need a refactor. Furthermore it is not very elegant because current Orchard permissions system doesn't fit with the permissions need for the feature: different permissions for read/edit/create a content item depending on the dynamic form used to access to that content item.

Related to the original issue description of @sebastienros "edit a profile for a user" I faced a problem in the case I want only the user itself can edit its user profile, because User is a special type for which I cannot get attached a CommonPart to have an Owner (I receive an exception). So you will find workarounds for that specific case in the code.

In the demo two questions arose:

MattPil29 commented 6 years ago

Hi, we are trying to find a CMS with a dynamic form that allows role-based editing after creation. IT sounds like the steps taken above would be essential for us (I don't think I'm the only one). Whats the current status and is anyone able to complete this work.

As a follow-up I've not found any documentation that describes how the content created by these forms is saved in the DB, i.e. as a json blob or something else. Can anyone describe this and maybe suggest a method for producing reports on the data i.e plotting registration data like user age against gender...

Thanks, Matt

jean commented 6 years ago

We'd also love to have this working. @jersiovic are you still using your implementation?

HengzheLi commented 6 years ago

@jersiovic Can this feature be a PR now?