Skip to content
Browse files

Support arbitary annotations for fields.

Move `default`, `required`, `dictionaryName`, `invisible` and
`readonly` to meta field. Meta field is a hash of any keys and values
which are transparently served back to client which may make special
use of them.
  • Loading branch information...
1 parent a0abc57 commit 87b9c1c6ca59934266fbd8912988880d91146ce9 @dzhus committed Mar 22, 2012
Showing with 67 additions and 62 deletions.
  1. +60 −40 README.org
  2. +1 −1 src/Snap/Snaplet/Redson/Permissions.hs
  3. +6 −21 src/Snap/Snaplet/Redson/Snapless/Metamodel.hs
View
100 README.org
@@ -76,15 +76,12 @@
**** Valid field keys
***** name
+
Field object must include `name` key which is the internal name of
the field.
`class` cannot be used as a field name.
-***** /default/
- Specifies the default value of field. Must somehow match the
- field type, currently processed on client side only (so any
- JavaScript value is valid).
-
+
***** /type/
Type system currently matches HTML input element types, with
@@ -133,27 +130,11 @@
and does not expect unreadable fields in server response.
-
***** /groupName/
`groupName` key must be present if field type is `group`,
and must be equal to name of one of the complex field groups as
described in group fields file (see below). Client must render
`group` field as a group of fields.
-***** /dictionaryName/
- When field type is `dictionary`, `dictionaryName` key must be
- present in field description as well. Client should provide
- certain mapping between stored field contents and displayed
- value using the name of dictionary. No checks on server side are
- performed.
-***** IN_PROGRESS /referencables/
- `referencables` key must be present if field type is
- `reference`, and holds list of models referencable from this
- field. Client may use this field to provide chooser interface to
- pick a specific model to store reference to. Empty list is the
- same as null.
-
- The server does not check if actual field value matches any of
- referencable models.
***** /index/
Boolean which instructs server to create or update exact reverse
index on that field on create/update/delete operations.
@@ -169,17 +150,42 @@
user-provided strings.
This flag may be removed in the upcoming releases.
-***** /requried/
- Boolean field to indicate that field is required. Client may
- provide custom checks in UI for such fields. Unused on server
- yet.
-***** /readonly/
- Boolean field to indicate that client must render field as
- disabled. This flag does *not* actually affect how server treats
- access to the field.
-***** /invisible/
- Boolean field to indicate that field should not be rendered on
- UI (or not handled by client at all).
+***** /meta/
+ A hash of arbitary keys and values which are *not* treated by
+ server in any way. These may be used by a client for
+ field-specific behaviour or templating.
+
+****** Suggested meta annotations
+******* default
+ Specifies the default value of field. (Will possibly move out
+ of meta if server will enforce default values upon creation
+ some day).
+
+******* dictionaryName
+ When field type is `dictionary`, `dictionaryName` key must be
+ present in field description as well. Client should provide
+ certain mapping between stored field contents and displayed
+ value using the name of dictionary.
+
+******* invisible
+ Boolean field to indicate that field should not be rendered on
+ UI (or not handled by client at all).
+******* label
+ Human-readable field label.
+******* readonly
+ Boolean field to indicate that client must render field as
+ disabled.
+******* requried
+ Boolean field to indicate that field is required. Client may
+ provide custom checks in UI for such fields. (Will possibly
+ move out of meta)
+
+******* IN_PROGRESS referencables
+ `referencables` key must be present if field type is
+ `reference`, and holds list of models referencable from this
+ field. Client may use this field to provide chooser interface to
+ pick a specific model to store reference to. Empty list is the
+ same as null.
**** Sample form definition
(As described in [[http://scp-wiki.wikidot.com/][The SCP Foundation]] archives)
@@ -193,38 +199,50 @@
"fields": [
{
"name": "code",
- "label": "Code",
+ "meta": {
+ "label": "Code"
+ },
"canWrite": ["front", "back"]
},
{
"name": "title",
- "label": "Title",
+ "meta": {
+ "label": "Title"
+ },
"canWrite": ["front", "back"]
},
{
"name": "foundAt",
- "label": "Original location",
+ "meta": {
+ "label": "Original location"
+ },
"canWrite": ["front", "back"]
},
{
"name": "dangerClass",
+ "meta": {
+ "label": "Danger class",
+ "dictionaryName": "DangerClasses",
+ "default": "lev0"
+ },
"type": "dictionary",
- "dictionaryName": "DangerClasses",
- "default": "lev0",
- "label": "Class",
"canRead": ["front"]
"canWrite": ["back"]
},
{
"name": "conditions",
+ "meta": {
+ "label": "Special Containment Procedures"
+ },
"type": "textarea",
- "label": "Special Containment Procedures",
"canWrite": ["back"]
},
{
"name": "description",
"type": "textarea",
- "label": "Description",
+ "meta": {
+ "label": "Description"
+ },
"canWrite": ["back"]
}
]
@@ -299,6 +317,8 @@
permissions. Served form will also contain `indices` field which is a
list of index fields of model.
+ `meta` for every field as served as-is without any changes.
+
Every field with type `group` is spliced into list of actual group
members in served model, and `groupName` property is attached to
every field in splice result. Client may use this data to
View
2 src/Snap/Snaplet/Redson/Permissions.hs
@@ -21,7 +21,7 @@ import qualified Data.Map as M
import Snap.Core (Method(..))
import Snap.Snaplet.Auth
-import Snap.Snaplet.Redson.Snapless.Metamodel hiding (required)
+import Snap.Snaplet.Redson.Snapless.Metamodel
-- | User who has all permissions (used in security-disabled mode).
data SuperUser = SuperUser
View
27 src/Snap/Snaplet/Redson/Snapless/Metamodel.hs
@@ -41,20 +41,17 @@ data Permissions = Roles [B.ByteString]
| Nobody
deriving Show
+-- | Map of field annotations which are transparently handled by
+-- server without any logic.
+type FieldMeta = M.Map FieldName Value
-- | Form field object.
data Field = Field { name :: FieldName
, fieldType :: B.ByteString
- , label :: Maybe B.ByteString
- , defaultVal :: Maybe Value
, index :: Bool
, indexCollate :: Bool
- , required :: Maybe Bool
- , dictionaryName :: Maybe B.ByteString
, groupName :: Maybe B.ByteString
- , invisible :: Maybe Bool
- , readonly :: Maybe Bool
- , referencables :: Maybe [ModelName]
+ , meta :: Maybe FieldMeta
, canRead :: Permissions
, canWrite :: Permissions
}
@@ -126,16 +123,10 @@ instance FromJSON Field where
parseJSON (Object v) = Field <$>
v .: "name" <*>
v .:? "type" .!= defaultFieldType <*>
- v .:? "label" <*>
- v .:? "default" <*>
v .:? "index" .!= False <*>
v .:? "indexCollate" .!= False <*>
- v .:? "required" <*>
- v .:? "dictionaryName" <*>
v .:? "groupName" <*>
- v .:? "invisible" <*>
- v .:? "readonly" <*>
- v .:? "referencables" <*>
+ v .:? "meta" <*>
v .:? "canRead" .!= Nobody <*>
v .:? "canWrite" .!= Nobody
parseJSON _ = error "Could not parse field properties"
@@ -144,18 +135,12 @@ instance ToJSON Field where
toJSON f = object
[ "name" .= name f
, "type" .= fieldType f
- , "label" .= label f
- , "default" .= defaultVal f
, "index" .= index f
, "indexCollate" .= indexCollate f
- , "required" .= required f
- , "dictionaryName".= dictionaryName f
, "groupName" .= groupName f
- , "invisible" .= invisible f
- , "readonly" .= readonly f
, "canRead" .= canRead f
, "canWrite" .= canWrite f
- , "referencables" .= referencables f
+ , "meta" .= meta f
]

0 comments on commit 87b9c1c

Please sign in to comment.
Something went wrong with that request. Please try again.