<commit_before>#+SEQ_TODO: MAYBE SOMEDAY BLOCKED TODO WAITING | DONE

* Overview
  We provide generic CRUD web interface for forms, which are defined
  as collections of fields of different types. Templating is done
  completely on client side using JavaScript. Server backend is
  powered by snaplet-redson.

** Metamodels

   Form definitions (metamodels) use JSON syntax and basically
   enumerate fields present in the form. Homebrew basic type system is
   used (currently view widget for field is rendered with regard to
   field type; form validation, when implemented, could use type
   information as well).

   Metamodels are stored in `.js` files under `resources/models/`
   directory.

   Required object fields for metamodel are `title` (readable form
   title) and `fields`, which is in turn a list of objects each
   describing model field. 

   Field object must include `name` key which is the internal name of
   the field. `default` key specifies the default value of field.
   Field may include any other fields which may be used further in
   templates.
   
*** Valid field names
    
    `class` cannot be used as a field name.

*** Valid types
    
    Type system currently matches HTML input element types, with
    following values valid for `type`:

    - "text"
    - "textarea"
    - "checkbox"
    - "select"
    
*** Field permissions
    Any field may include "canRead" and "canWrite" properties which
    are lists of user roles which allow reading and writing to field,
    respectively. They can be boolean values as well. Implementation
    generally follows these rules:

    - If field is unreadable, then client must not render it. 
    
    - If field is not writable by user, then form input element must
      be inactive.

    - If field is writable, then it's readable even if user role is
      not listed among "canRead".

    - If permission property is boolean, then "true" means any role
      applies has the permission and "false" means none of roles does.
      "false" value is the same as empty list.

    - Client does not attempt to write inaccessible fields to server
      and does not expect unreadable fields in server response.
*** Sample form definition
    (As described in [[http://scp-wiki.wikidot.com/][The SCP Foundation]] archives)
    
    #+BEGIN_SRC javascript
      {
          "name": "SCP",
          "fields": [
              {
                  "name": "code",
                  "label": "Code",
                  "canEdit": ["front", "back"]
              },
              {
                  "name": "title",
                  "label": "Title",
                  "canEdit": ["front", "back"]
              },
              {
                  "name": "foundAt",
                  "label": "Original location",
                  "canEdit": ["front", "back"]
              },
              {
                  "name": "dangerClass",
                  "type": "select",
                  "default": "Euclid",
                  "choice": ["Safe", "Euclid", "Keter"],
                  "label": "Class",
                  "canRead": ["front"]
                  "canEdit": ["back"]
              },
              {
                  "name": "conditions",
                  "type": "textarea",
                  "label": "Special Containment Procedures",
                  "canEdit": ["back"]
              },
              {
                  "name": "description",
                  "type": "textarea",
                  "label": "Description",
                  "canEdit": ["back"]
              }
          ]
      }
      
    #+END_SRC
*** Form id
    Consider a metamodel is stored in `scp.js` file; we define
    formid as filename without extension (`scp`), which is used in URL
    to access forms built from this metamodel.

** Frontend
   
   Our frontend code uses form defintion to build form model and view.
   [[http://documentcloud.github.com/backbone/][Backbone]] JavaScript framework is used to implement binding model to
   view and making automatic server requests to restore/save form
   instance on server (see `/resources/static/js/metamodel.js`). Upon
   loading the page, metamodel JSON is requested from server, and
   processed into Backbone model definition. Backbone model provides
   fetch(), save() and destroy() methods which result in appropriate
   requests being sent to server.

   `/_/<formid>/` serves title page (which is in fact the same for any
   <formid>) with all the code required to process metamodels on
   client side. Client JavaScript further requests metamodel
   description in bare JSON using `/_/<formid>/model/` URL, from which
   the server picks `<formid>.js` metamodel and sends it back to
   client. Redson snaplet is nested under `_/` URL, which provides
   server API compatible to Backbone.sync.

   `renderFormView` function builds an HTML form for model fields,
   which is rendered to page. [[http://knockoutjs.com][Knockout]] is used to keep model data in
   sync with form contents. [[https://github.com/kmalakoff/knockback][Knockback]] is used to bind Backbone model
   to form.

   Render function uses [[https://github.com/janl/mustache.js][Mustache.js]] coupled with templates served<commit_msg>snaplet-redson is now crucial for serving model, mention it. Also rename metamodel → model<commit_after>#+SEQ_TODO: MAYBE SOMEDAY BLOCKED TODO WAITING | DONE

* Overview
  We provide generic CRUD web interface for forms, which are defined
  as collections of fields of different types. Templating is done
  completely on client side using JavaScript. Server backend is
  powered by [[https://github.com/dzhus/snaplet-redson][snaplet-redson]].

** Models

   Form definitions (models) use JSON syntax defined by [[https://github.com/dzhus/snaplet-redson][snaplet-redson]]
   and basically enumerate fields present in the form. Homebrew basic
   type system is used (currently view widget for field is rendered
   with regard to field type; form validation, when implemented, could
   use type information as well).

   Models are stored in `.js` files under `resources/models/`
   directory.

   Required object fields for model are `title` (readable form
   title) and `fields`, which is in turn a list of objects each
   describing model field. 

   Field object must include `name` key which is the internal name of
   the field. `default` key specifies the default value of field.
   
*** Valid field names
    
    `class` cannot be used as a field name.

*** Valid types
    
    Type system currently matches HTML input element types, with
    following values valid for `type`:

    - "text"
    - "textarea"
    - "checkbox"
    - "select"
    
*** Field permissions
    Any field may include "canRead" and "canWrite" properties which
    are lists of user roles which allow reading and writing to field,
    respectively. They can be boolean values as well. Implementation
    generally follows these rules:

    - If field is unreadable, then client must not render it. 
    
    - If field is not writable by user, then form input element must
      be inactive.

    - If field is writable, then it's readable even if user role is
      not listed among "canRead".

    - If permission property is boolean, then "true" means any role
      applies has the permission and "false" means none of roles does.
      "false" value is the same as empty list.

    - Client does not attempt to write inaccessible fields to server
      and does not expect unreadable fields in server response.
*** Sample form definition
    (As described in [[http://scp-wiki.wikidot.com/][The SCP Foundation]] archives)
    
    #+BEGIN_SRC javascript
      {
          "name": "SCP",
          "fields": [
              {
                  "name": "code",
                  "label": "Code",
                  "canEdit": ["front", "back"]
              },
              {
                  "name": "title",
                  "label": "Title",
                  "canEdit": ["front", "back"]
              },
              {
                  "name": "foundAt",
                  "label": "Original location",
                  "canEdit": ["front", "back"]
              },
              {
                  "name": "dangerClass",
                  "type": "select",
                  "default": "Euclid",
                  "choice": ["Safe", "Euclid", "Keter"],
                  "label": "Class",
                  "canRead": ["front"]
                  "canEdit": ["back"]
              },
              {
                  "name": "conditions",
                  "type": "textarea",
                  "label": "Special Containment Procedures",
                  "canEdit": ["back"]
              },
              {
                  "name": "description",
                  "type": "textarea",
                  "label": "Description",
                  "canEdit": ["back"]
              }
          ]
      }
      
    #+END_SRC
*** Form id
    Consider a model is stored in `scp.js` file; we define
    formid as filename without extension (`scp`), which is used in URL
    to access forms built from this model.

** Frontend
   
   Our frontend code uses form defintion to build form model and view.
   [[http://documentcloud.github.com/backbone/][Backbone]] JavaScript framework is used to implement binding model to
   view and making automatic server requests to restore/save form
   instance on server (see `/resources/static/js/metamodel.js`). Upon
   loading the page, model JSON is requested from [[https://github.com/dzhus/snaplet-redson][snaplet-redson]] at
   `/_/<formid>/model/` URL, and processed into Backbone model
   definition. Backbone model provides fetch(), save() and destroy()
   methods which result in appropriate requests being sent to server.

   `/_/<formid>/` serves title page (which is in fact the same for any
   <formid>) with all the code required to process metamodels on
   client side. Redson snaplet is nested under `_/` URL, which
   provides server API compatible to Backbone.sync.

   `renderFormView` function builds an HTML form for model fields,
   which is rendered to page. [[http://knockoutjs.com][Knockout]] is used to keep model data in
   sync with form contents. [[https://github.com/kmalakoff/knockback][Knockback]] is used to bind Backbone model
   to form.

   Render function uses [[https://github.com/janl/mustache.js][Mustache.js]] coupled with templates served
{'fraction_non_alphanumeric': 0.09023059994258922, 'fraction_numerical': 0.0, 'mean_word_length': 2.2140221402214024, 'pattern_counts': {'":': 52, '<': 10, '<?xml version=': 0, '>': 10, 'https://': 7, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '161805', 'n_tokens_mistral': 2777, 'n_tokens_neox': 2619, 'n_words': 1150}