Development

bschussek

You must first sign up to be able to contribute.

Version 4 (modified by bschussek, 9 years ago)
--

Symfony 1.2 Admin Generator Development

This page serves as place where features and modifications of the admin generator in symfony 1.2 can be discussed.


Concept by Bernhard Schussek

Please note that this section does not contain official information. The text written in here is solely based on my personal concepts.

I was planning to rewrite parts of the admin generator together with a few members of the symfony usergroup vienna starting in summer '08. I developed a concept of different UI and technical enhancement that are described here. The purpose is to discuss whether some or all of these features can be integrated into the new admin generator. I am willing to spend time and probably money to develop these features, as may be some other people I know personally.

Motivation

The motivation of this rewrite was mainly to increase the usability of the admin generator, so people without much technical knowledge can easily use the interface without lots of configuration/adaption.

In the concept I tried to find generalized data representation schemes which can be used in most use cases, but still are usable enough to be used by inexperienced users.

Notes

  • Most of the ideas presented in here are based on successful applications such as Silverstripe, Jacomo (a very usable and customizable db administration tool developed by my previous employer) and Joyent (a collaboration tool with a very innovative UI).
  • I'm basing my concepts on the current syntax of configuration files. These need to be modified in case the new admin generator makes radical changes here.
  • Many of the examples are incomplete and require further discussion
  • I'm refering to inexperienced, non-technical users when talking about "users"

Besides: I was planning to develop this generator based on Doctrine because of the easier syntax and better support of relations, inheritance and nested sets.

Major Modifications

Modification of Contextual Records

Problem

In many applications the business model can be (mostly) separated in two groups:

  1. Informational Entities (valuable information), for instance
    • Article
    • Town
    • Customer
    • Booking
    • Page
  2. Contextual Entities (providing contextual information for the above, mostly "groups" or "categories"), for instance
    • Group
    • Tag
    • Category
    • Type

(of course this separation does not apply to all models, but from my experience to many of them)

The difference between is that users generally don't want to know about the second.

Example:

For instance, the model may require to define a related "AccomodationType?" for "Accomodation" records. Real users will not be interested in the type. They want to create a new accomodation, defining (and eventually creating) a type is only a burden, especially when the type has to be created in a different list view. Users will enter the accomodation creation form, fill half of the fields only to realize that the related type does not exist yet. Advanced users will open the type list in a new tab or window, but inexperienced users will just leave the form and lose all their entered data.

The only real use in such contextual entities for the user lies in filtering list views (in this example - filter accomodations by type).

So our tasks are:

  1. Make modification of contextual entities a contextual task that doesn't distract the user from doing his actual task
  2. Make filtering by those contextual records easy

Concept

I came up with the following concept when I stumbled upon Joyent Connector while analising different web applications:

  • Add contextual records through sub-forms while modifying the informational entities (solves 1.)
    Example: Create AccomodationTypes? while modifying an accomodation through subforms
  • Display, add and modify contextual entities in a tabbed sidebar in the views of the informational entities they're related to. Don't waste space by creating a dedicated list view which users will never use (solves 1.)
    Example: Display AccomodationTypes? in Accomodation list and edit views, create, delete and modify them using AJAX
  • Filter a list of informational entities when clicking on a contextual entity in the tabbed sidebar. Users know this behaviour from browsing f.i. file browsers, music applications etc.
    Example: When the user clicks on an AccomodationType? entry in the sidebar of the Accomodation list view, filter the list by this type.

Realisation

One could realise the sidebar with the following configuration:

generator:
  param:
    model_class: Accomodation
    sidebar:
      display:   [_types, _tags]                                               # Specification of order. All of these can be overridden by partials
      tabs:
        _types:  { relation: Accomodation.Type }                               # Name and title implicitly set to "Types"
        _tags:   { name: Tags, title: Your Tags, relation: Accomodation.Tags } # explicit setting of name and title

(Note: this code sample is incomplete)

Adding a contextual entity through a subform while editing an informational entity can be handled through a widget (see below).

Widgets

The generator should support widgets, meaning a generalized way of representing and modifying record data. These widgets as I speak of them are different from symfony 1.1 form widgets in that they incorporate view, model (validation) and partially business logic.

Use case 1:

The record class "Accomodation" contains a many-to-one foreign relation "AccomodationType?". When editing an accomodation, the user can select its type. Additionally he should be able to create a new type if the desired type does not exist yet. This can be done through a subform for adding the record.

generator:
  param:
    edit:
      AccomodationType: { type: SelectRelation, param: add=true } # uses SelectRelationAdminWidget, the original record and the name of the field (relation in this case) are automatically provided to the widget

The (conceptual) widget incorporates the following logic:

  • display of all available types (model, view)
  • addition of a new type (model, business logic)
  • validation of selected types (model)

Use case 2:

The record class "Accomodation" contains two fields "longitude" and "latitude". They should be modified through a Google Map with a draggable marker. These fields do also appear in other classes, so a reusable widget is needed which can be configured in all classes:

generator:
  param:
    edit:
      _coordinates: { type: GoogleMap, param: longitude=longitude_field latitude=latitude_field } # uses GoogleMapAdminWidget with the given parameters

The widget incorporates the following logic:

  • display of the map, javascript (view)
  • validation of the coordinates (model)

Simultaneous Modification

This is not as important, but useful anyway.

The user should be able to modify several objects at once by selecting them (see Enhanced List View Actions below) and pressing the button "Edit". When multiple records are modified, the form contains a checkbox "Don't modify" for each form field which is checked by default. Form fields which are the same in all selected records are filled out, the other ones are left empty. If the user changes the content of a form field, unchecks "Don't modify" and saves the record, the given property is changed to the new value on all objects.

This feature is very useful for batch editing of all sorts.

Support of Nested Sets

The generator should be able to automatically display nested sets as trees in the list view. Nested sets do always represent hierarchical data and thus can basically always be represented by trees, which are more intuitive to use for people than plain lists.

There shouldn't be any further configuration necessary to enable this feature.

Support of Inheritance

The generator should be able to automatically deal with Doctrine's inheritance schemes. I have too little experience in terms of real use cases to come up with a usable concept here though.

Support of I18N

The generator should be able to deal with translated records. How to do this in detail needs to be discussed.

Minor Modifications

The admin generator should feature the generation of a global navigation module linking to the index/list actions of different modules. This could easily be incorporated in a YAML file /apps/myapp/config/generator.yml:

generator:
  param:
    display:
      myModule:  ~                                                        # automatically links as "My module" to myModule/index
      myModule2: { name: "Site", icon: "...png", action: myModule2/edit } # further configuration

Tabs

It should be possible to group fields into tabs in the edit view. This can be done by reusing the current configuration syntax for fieldsets:

generator:
  param:
    edit:
      display:
        "Content":  [name, publish_at]
        "Details:   [...]
        "Metadata": [...]

Enhanced List View Actions

The support of custom actions in the list view should be enhanced. There should be two types of display modes:

  • normal (normal button that does something)
  • collapsible (the visibility hidden partial is toggled when the button is pressed, that could contain filters for the list view etc.

Additionally one should differ between to types of action scope:

  • none (the action does not affect a specific record) - for instance "Create", "Filter"
  • selected (the action affects only selected records) - for instance "Delete", "Edit". One or more records need to be selected using checkboxes in the list view first
generator:
  param:
    list:
      actions:
        _create:  ~                                   # default values: { name: Create, display: normal, scope: none }
        _filter:  { display: collapsible }            # The partial _filter.php is toggled open/closed when the button is pressed and contains a form used to apply specific filters
        _delete:  { scope: selected, action: delete } # The selected record identifiers will be handled to the specified action

Attachments