Skip to content

Proposed "tag sets" features

Ian Ross edited this page May 30, 2014 · 1 revision

Relevant tickets

  • #23: allow tags to be bulk edited
  • #24: keep sets of tag aliases
  • #25: translate Cabal categories to tags
  • #27: use tags in search
  • #80: tags get reset on new package uploads

Basic design

Low-level functionality

Data types

Currently, the Tag data type is a newtype for String. We can keep this representation and just record tag aliases in separate maps:

newtype TagAliases = TagAliases (Set Tag)

data TagAliases = TagAliases {
  tagAliases :: Map Tag (Set Tag),
  aliasCanonicalTag :: Map Tag Tag
} deriving (Eq, Show, Typeable)

We'll then need acidified functions:

tagToAliases :: Tag -> TagAliases -> Set Tag
tagToAliases tag tas@(TagAliases as _) =
  Map.findWithDefault Set.empty (canonicalTagName tag tas) as

canonicalTagName :: Tag -> TagAliases -> Tag
canonicalTagName tag = M.findWithDefault tag tag . aliasCanonicalTag

plus functions to alter the tag aliases (a lot like the existing alterTags, etc. functions in Distribution.Server.Features.Tags.State).

This should all go into a new TagSets feature, which will depend on the existing tags feature and will serve pages for viewing tag sets and renaming and coalescing tags. This makes data migration easier, since we'll just be adding a new TagSets component to the server state.

Renaming and coalescence

Renaming a tag will require changes to the tags aliases maps as well as the package-to-tag maps. This seems to be acceptable: there's already code in Distribution.Server.Features.Tags.State to alter tags for a set of packages, although none of those functions are exported in the Tags feature's interface, so that will need to be dealt with.

For renaming:

  • Find all packages tagged with the old tag name.
  • Update the package tags.
  • Update the canonical name for any aliases of the renamed tag.
  • If the new name is the same as an existing tag or is an alias for an existing tag, coalesce the tag aliases for the two.

and for coalescence (i.e. making an existing "from" tag be an alias of a given canonical "to" tag):

  • Add the aliases for the "from" tag to the alias set for the "to" tag.
  • Remove the alias set for the "from" tag.
  • Rename the "from" tag to the "to" tag in any package to tag maps.

Decoalescence (i.e. making an existing alias of a canonical tag into an independent canonical tag) will work similarly.

REST API

  • .../tag-sets (GET, html) Main tag sets page

  • .../tag-sets/:tag/edit (GET, html) Edit UI page for given tag

  • .../tag-sets/:tag/edit (POST) Submit edit changes for given tag

UI

  • Tag display for packages should work as now, except that only canonical tag names will appear.

  • The search UI should use all tags (canonical and aliases) when testing for search terms.

  • The "tag sets" UI will allow an admin to:

  • Rename tags, i.e. change their canonical names;

  • Coalesce tags, i.e. specify that one tag (and all its existing aliases) should become an alias for another canonical tag;

  • Decoalesce tags, i.e. specify that an existing alias for a canonical tag should become a separate tag in its own right.

  • The "tag sets" UI should have:

  • An A-Z navigation list at the top;

  • One entry per canonical tag, in alphabetical order;

  • Each tag entry should show the canonical tag name (hyperlinked to a list of packages having this tag), and a list of tag aliases;

  • Each tag entry should have a UI element ("Edit" button) to go to a page for editing the tag set definition (editing a tag set requires admin privileges).

  • Each "tag set edit" page should have:

    • For each tag alias a UI element (a ⊗ button or a checkbox?) to decoalesce the alias from its canonical name, i.e. to make the alias into an independent tag;
  • A UI element (text box) to change the canonical name of a tag;

  • A UI element (combo box/selection list?) to coalesce the tag into another as an alias. This works as: the tag selects the canonical tag whose alias it will become;

  • A "Submit" button to perform the changes to the tag set via a POST.

Tasks

  • Set up TagSets feature
  • Basic tag set manipulation code
  • Low-level tag set renaming and coalescence code
  • Export tag set API from TagSets feature
  • Main tag set list page
  • Tag set edit pages
  • Tag set edit page handler
  • Tag set backup/restore
  • Cabal categories to tags: package upload
  • Cabal categories to tags: one-off for existing packages
  • Fix #80 (tags reset on package upload)
  • Tags in search