Interesting concept for a module... subscribing and will take a closer look.

Comments

donquixote’s picture

Title: Interesting... Subscribing » Feedback + Brainstorming (Multicrud module)

Ok, let's make this a general purpose brainstorm thread, so it's not a one-shot message :)

giorgio79’s picture

I just installed the module and played around with the demo form. Massively fantastic and simple.

1. Do you have a dev server where you could post a live demo showing the capabilites of the module?
2. What plans do you have?
The following would definitely get a wide adoption:
2a. Release a CCK plugin (just like Multigroup but with this cool JS interface)
2b. Perhaps release a Views style plugin as well, like editview. This would need pagination though. :)

donquixote’s picture

1. Good idea. I will let you know when it's running.
2. Some of the plans are explained on the module page.
2a. Yes, it's definitely meant to be used for CCK, but this is going to be more work. Maybe there will be some field types where this thing won't work (thinking of imagefield and filefield with ajax/ahah mechanics). Multicrud does not define anything on the storage layer, so it would rather be an alternative interface for flexifield or content multigroup, or for reverse nodereference editing.
2b. I need to learn a lot about views before I can do this..

2*: "What plans do you have"
Ok, now a bit more detail.
One day I noticed that Drupal's capabilities for modeling relations are not really satisfactory:
- Consider a person with multiple phone numbers. For each phone number, you can store an additional comment. You would need a custom CCK type for that, or a flexifield.
- Consider a person that can be related to a company, and with this many-to-many relation, we also store if this person is an employee, or the boss, etc. We want to edit this relation both from the person form and the company form.

Existing solutions:
- There is nodereference, with the overhead of everything being a node. Furthermore, there is no nice widget to bulk edit/create referrer nodes.
- there is multiple value flexifield, where values are stored in serialized arrays instead of dedicated table columns. And there is again no way to edit this thing from the foreign node, if you create a flexifield with a nodereference.
- there are multiple value CCK fields. You need to write a custom field whenever you need to combine fields.
- With anything multiple value, you need to wait for slow ahah callbacks. Sometimes you have too many empty fields (2 instead of 1), and they are by default not arranged in a table.

So, my plans are (for nodes / CCK):
- Something based on nodereference, where you can bulk edit, create and delete dependent nodes. Ideally, these nodes should only have simple field types such as select and textfield. Textareas get a resize / tabindex mechanic similar to the one in menu_editor.
- Have a look why content_multigroup is taking so long, and if I can build an alternative.

Other plans outside of CCK:
- Use this module for editing date formats.
- Add tabledrag mechanics and use this thing for menu_editor
- Add pagination and search, and use it for bulk editing of url aliases. Maybe this will be a totally independent widget delivered in the same package, so I can keep the basic one simple.
- Add something like unique value fields.
- And more stuff.

The version that I'm currently playing with already looks quite different from alpha1 (in code). I will commit soon.

giorgio79’s picture

Awesome!

For the "CCK" plans if field attributes like this could be preserved when in Multicrud would be great:
http://drupal.org/project/maxlength
and
http://drupal.org/project/checkall
for fields.

About the "add more stuff" part:
I notice currently at form submit the module outputs a nice array, which I could already store as serialized array in a CCK Computed Field...
I love that the entire form table can be saved in a single field instead of as a node through node reference. I hope this will be an option. (this is how CCK Tablefield works http://drupal.org/project/tablefield)

--rant--
I think being able to store the form in a single field is important, because from my part I believe that CCK storage is not the most db friendly. I dislike in CCK that it spews out tables left and right for each content type and field...With a successful and large site one will soon find a need for a db admin and separate db servers with all the JOINs needed. This is only useful if those values are needed in Views for example. But this is not necessary.
For example, recently for a node I needed dozens of checkboxes and I was worried that CCK creates a separate table and saves each checkbox in a separate db row. Hence I created a solution where checked items are stored as comma separated values: http://drupal.org/node/782974 inside the main content type table
:) This way no SQL JOINs are needed to output it at node view and edit...
--rant--

donquixote’s picture

Last time I checked, it worked like this:
- in addition to the node table,
- there is one cck table for every content type, with columns for all the single value fields. Some of the single-value fields can even have multiple columns (such as date), and still be all in the same table.
- there is a separate table for every multiple value field.

I think this is totally fine and reasonable, and much better than the serialize() stuff that flexifield does. The overhead is with the node table, which means that every node has one table row in the node table, and another in the content type table.

dozens of checkboxes

I think this depends if you have separate checkbox fields or one multi-value option field.

Anyway, if you are not happy with the db storage of a CCK field, you should write your own.

I love that the entire form table can be saved in a single field instead of as a node through node reference. I hope this will be an option.

Multicrud is primarily a form element, not a CCK field. I will probably add some CCK stuff into the package, but others can create their own CCK fields that use the multicrud form element, no matter how they store the values.

giorgio79’s picture

Sounds great.

(Regarding my storage rant, yes the overhead is in the additional node row plus the additional table to multi instance fields... :) )

Thanks.

daglow’s picture

What if the form could be generated by Admin with information for specific users and sent to their account page with a option box and sent back to admin in their user's list.

OFF’s picture

How do I see the module work?

This example is very good: http://drupal.org/node/791448

But I do not understand how to add multicrud form for node add page..

I'd like to see step by step instruction to use the module, I do not understand how to see in action multicrud_example module

MBroberg’s picture

This looks interesting and I wonder if it would work for my purpose. Since this is listed as "brainstorming and feedback" I hope this is the right place.

I am developing a student PE sports site with players and teams.

There are over 50 park locations currently in several states, with more coming.
Each location has 2-5 levels of players (age groups), each with its own coach, depending on total players at that location.
Each month there is a new sport, so each player can be on a new team each month, and could sign up for as many as 9 sports in a year.
So there are 50x9x4 or close to 2000 possible teams in a year.
Each player is a node, with over 2000 players currently registered in several states, more coming.

I need a quick easy way to add a player to a team as the orders come in.
I could go to the player node and node reference each team if each team were also a node, but creating 2000+ nodes is huge.

Having a table makes sense.
I could pull down a player nodereference in column 1 (autocomplete for simplicity?)
Column 2 would be location (also a node)
Column 3 would be sport (taxonomy term?CCK select field?)
Column 4 would be level. (just a single digit number is fine)
This would create a row that places a student at a location for a single sport at a certain level. Up to 9 rows would be created per student.

Obviously the number of rows in the table would be huge and growing. (expired ones could be deleted)
The table would need a filter so that I am not looking at all the rows at once.
Also in the end, rosters must be created, so something has to be stored and exposed to Views so that I can print a roster for each team.
I would like to be able to go to the student node and see a list of teams they are on, and edit there if possible. If not, at least attach a View in a block or something like that.
Also to go to a team page (or filter the table) and see a list of students and move them to other teams if necessary.

Does any of this make sense?

donquixote’s picture

Multicrud just covers the UI part of the problem.
What do you want to store in the database?

> I could go to the player node and node reference each team if each team were also a node, but creating 2000+ nodes is huge.

500.000 nodes is huge.
2.000 is quite normal.
The id of this issue is 785440 !!
Whether any of these numbers is a threat for performance, probably depends on a lot of things. As long as you don't display them all on one page, it should be ok.

EDIT: There might be other reasons not to make this a node type. I just want to say, don't be scared by 2.000.

MBroberg’s picture

Thanks for your reply - I guess I am just thinking about the practicality of creating all of those nodes, especially when more are coming. I need some sort of autocreate I guess.
In the end, the team probably does need to be a node, perhaps with a team code that can be stored, but doing the data entry for team assignments has to be really easy. Even going to each student node and assigning a team (up to 9 times per year) could be tedious. How much better to have a table!
If I create all of those 2000+ nodes, it would be hard to use the list in a nodereference field. Imagine searching through 2000 nodes! So I need to filter the node reference fields. I am just starting to find modules that play with that idea, but how much easier if I can go to a table, pull down "student", "location", "sport", "level" just like I would with a views filter, and then have the single team that matches all 3 shows up!
Perhaps in a 5th column the team code shows up and that gets stored?
Storing the relationship "student node ID - team node ID" would be enough. It's the method of creating those records that puzzles me.

donquixote’s picture

I think more important than "team" is a "team assignment" content type, with
- student id (is this nid or uid?)
- start date (or month) of the assignment
- end date (or month), this can be empty.
- level
- location
with some constraints so that a student can not be in the same team twice at the same time.

The level + location implicitly defines the team.

You can make "team assignment" a node type, or you could make it a custom table - your choice.

You can make "team" a node type, or just leave it as something implicit.
If team is a node type (or custom table), then for "team assignment" you would have
- student id
- start and end date
- team id (instead of level + location)

The team node type would have fields for
- coach
- location
- level
and you would need some constraints so that only one team per level can exist at one location.
You can use the auto_nodetitle module to automatically create a title from location + level.

You can provide a per-student multicrud form to edit team assignments for this one student.
You can also provide (in addition to that) a per-location / per-level multicrud form to edit / create team assignments for this specific team.

Btw, autocomplete is your friend!
Instead of the drilldown select elements, you can make an autocomplete text field for the team selection, _if_ "team" is a node type or custom table.
For user ("player") selection, you can also use an autocomplete.
You could even write your own custom autocomplete, that will search for cck field values and not just node titles.

donquixote’s picture

And yes, "team assignment" would be tons of nodes!! (or rows in a custom table)

btw, afaik in Drupal 7 you could create an entity type with student id + location + level as the primary key .. might be something to consider.

MBroberg’s picture

Thank you, I have done as you suggested and created a team assignment that figures out the team from a combination of 3 columns. There is no actual "team" node, so filters must be used in cooperation to get a roster. That works well using Views.

Perhaps this is beyond the scope of your module, but 2 questions:
1 - Is there a way to set default data in the fields based on the filters, so that the default value can change based on what is selected in the filters?
So if you are doing data for a certain team, the 3 fields autofill and all you have to do is autocomplete for the student?

2 - Also, if the data is entered with Multicrud table, and several rows (nodes) are created at once, what would be the effect on UC Node Checkout module, which places created nodes in the cart for checkout?
Would that require custom code to make sure all of the new nodes go into the cart when the "save" button is pressed, which is automatic when nodes are added from the traditional form?

Thank you for your time.

donquixote’s picture

Re #14:

You are doing this with views? Did you define a custom display handler or something?

1. Yes.
I assume you have the filter params available in the your form builder function.
If you use the 2.x branch, you write your own MulticrudValueHandler class (unfortunately, the only working example atm is the menu one, afaik, and that is quite complex). You pass the filter parameters to that class as constructor params. Then in that class you implement the getDefaultValue() method, which should return the filtered rows.

2. In the same MulticrudValueHandler class, you implement the deleteItem() and updateItem() and insertItem() methods, which are called for every row to update / insert / delete. Devel dpm() is your friend. In theory, it will also call validateItem() for each of them, but turns out you need to do that yourself (the _validateItem()) in menu_multicrud is the one that does something, and it's quite naive atm)

For every node to insert, you will receive the raw data the user entered for that table row. You need to convert / massage this data into something suitable for node_save(). You should study other modules that do node_save().

For your specific ubercart-related question, this is something you need to try yourself.
Anything that goes into the database is because you do a node_save(). Like in any custom module where you save a node, just that multicrud helps to save a bunch of them in one form submit, one after the other.