# TAGS specifications

Main case is 3373 https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3373

TAG-GROUP - bag of tags
    Modify the below and coded and tests and tables to now have feature for tag groups
    They will be in their own table with a dictionary table of tag ids and tag group id's to link
    They are used for read purposes, you never tag an item with a tag group, only query by group.
    If a group is deleted tags it contains are NOT deleted or changed
    If a tag is deleted it must be removed from any tag groups and if there are no other items in that tag group then the tag group must be deleted as well??
        - Or maybe is just an empty group with a warning symbol in ui
    Tag groups will become a major way to save filters for things because a lot of filtering will be by tags so this should be a solid feature.
    - RETRIEVAL / PICKLISTS: need to modify the tag picklist to optionally return TAGGROUP names as well as identify they are group so UI can feature differently

    FILTERING AND SORTING BY TAG-GROUP
        - All code that filters and sorts by tag should accept a tag group as a separate type of input and dynamically build the tag filter list from the group and individual tags separately
         rather than storing a list of tags at the moment a group is applied.  
         In this way the filters are always dynamically linked to the tags in the group and reflect the most recent changes to the group
         tl/dr: don't store the tag id's from a group in the filter, store the group id separately and build the list on query

FORMAT
=-=-=-
Copied from stack overflow
tags ...

    must be no longer than 255 characters (35 in Stack overflow, but why limit it?)
    spaces are replaced by dashes, no spaces in a tag
    always converts to lower invariant culture
    - (probably not this, utf-8 ok: must use the ascii character set a-z 0-9 + # - .)


SCHEMA
=-=-=-
4 tables:

TAGS
    - name text not null lowercase only
    - id bigserial
    - OwnerId
   
TAGMAP
    - ObjectId
    - ObjectType
    - TagId

TAGGROUP
    - name text not null lowercase only
    - id bigserial
    - OwnerId

TAGGROUPMAP
    - TagGroupId   
    - TagId   
    
INDEXES
    - Initial index is on the name of the tag as that will be searched for??
    - After some research I think it's best to just make it, populate it with a great deal of test data and then test query it and see what indexes give the best performance
    


USE-CASES
Add a tag to an object type and id, start typing and a selection list fills in to select from
    - Don't allow the same tag more than once
    - Create a tag if not present (rights?)
Show tags on an object
Find any type or specific type items by a set of tags (and/or tag groups) to include and a set of tags to exclude (i.e. has "red, yellow" but not "green")
Search for text must allow specifying tags (and/or tag groups) to refine
Reporting will require filtering sources of report data by tags (and/or tag groups)

METHODS REQUIRED IN TAG CONTROLLER

- GET tag text by id
- GET tag id by tag text 
- CREATE tag for tagging something
- REMOVE tag (and all tagmap entities)


- GET TAGMAPS LIST (get all object/id entities with this tag)
- CREATE TAGMAP Apply tag to an object / id 
- REMOVE TAGMAP remove tag from object/id
- GET TAGS for object (name id list, main display route)


ROLES / RIGHTS
- Limited roles can tag stuff and remove tags as per their rights to the object type in question but can't make new tags or change existing tags 
- Full roles can make new tags and can edit or delete existing tags
    

RETRIEVAL

Will need to query tags as follows:

ObjectType and Id list of tags (most common)
Objects with one or more tags
Objects that have a set of tags but do not have another set of tags
Objects of a certain type but any id that have a certain tag

V7IMPORT
See case 3373 for a list of things that will become tags



