Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Tree FieldType #555

Open
MKwenhua opened this issue Feb 21, 2018 · 4 comments
Open

Refactor Tree FieldType #555

MKwenhua opened this issue Feb 21, 2018 · 4 comments

Comments

@MKwenhua
Copy link
Contributor

MKwenhua commented Feb 21, 2018

We need to create a data structure that could support saving and rendering data for UI elements like:
http://experiments.wemakesites.net/css3-treeview-with-multiple-node-selection.html

Current Tree Field Type Data Structure:

Categories Field:

 name: "Categories",
 name_id: "categories",
 field_type: "tree_field_type",
 metadata:
  {"allowed_values"=>
    {"data"=>
      {"tree_array"=>
        [{"id"=>1, "node"=>{"id"=>1, "name"=>"Product News", "children"=>[]}, "children"=>[], "parent_id"=>nil},
         {"id"=>2, "node"=>{"id"=>2, "name"=>"Company News, Research and Trends", "children"=>[]}, "children"=>[], "parent_id"=>nil},
         {"id"=>3, "node"=>{"id"=>3, "name"=>"Client Success Stories", "children"=>[]}, "children"=>[], "parent_id"=>nil},
         {"id"=>4, "node"=>{"id"=>4, "name"=>"Recruiting Solutions", "children"=>[]}, "children"=>[], "parent_id"=>nil},
         {"id"=>5, "node"=>{"id"=>5, "name"=>"Employment Screening", "children"=>[]}, "children"=>[], "parent_id"=>nil},
         {"id"=>6, "node"=>{"id"=>6, "name"=>"Human Capital Management", "children"=>[]}, "children"=>[], "parent_id"=>nil}]}}},

Research Field:

  name: "Research",
  name_id: "research",
  field_type: "tree_field_type",
  metadata:
   {"allowed_values"=>
     {"data"=>
       {"tree_array"=>
         [{"id"=>1, "node"=>{"id"=>1, "name"=>"CB Research", "children"=>[]}, "children"=>[], "parent_id"=>nil},
          {"id"=>2, "node"=>{"id"=>2, "name"=>"Third Party Research", "children"=>[]}, "children"=>[], "parent_id"=>nil}]}}},
@MKwenhua
Copy link
Contributor Author

MKwenhua commented Feb 21, 2018

@toastercup I thought of two general approaches that both support multidimensional storage but vary in shape and traversal complexity:

Rough Drafts

Multi Dimensional Array

{
  head: [
    { id: "0",  value: "accountant" },
    {id: "1",  value: "human resources" },
    { id: "2",  value: "software engineer",
      children: [
         {id: "2_0", value: "DBA"},
         {id: "2_1", value: "Gaming" },
         {id: "2_2", value: "Web", 
             children: [
                {id: "2_2_0", value: "Front End"},
                {id: "2_2_1", value: "Back End"},
                {id: "2_2_2", value: "Full Stack"}
             ]
          }
      ]
    }
  ]
}

Pros
With this structure you have the advantage of easily traversing and having access to all ancestor nodes using the id which is made of their array index.
Cons

  • Rendering may be more challenging
  • Extracting the value from the node may also be more complex since you would have to do a traversal from the head. This could be mitigated though if there also is a flat id lookup table
  • Parent Child relationships and order are baked into the id indexes making reorganizing more complex.

Honestly in a half finished example of how to traverse I realized that the above is clearly the inferior data structure.

Flat Normalized Lookup Tree

{
   head: [
    "gvghvs",
    "nuewe",
    "uwuwu"
   ],
   tree_fields: {
     gvghvs: {value: "accountant"},
     nuewe: {value: "human resources" },
     uwuwu: {
         value: "software engineer",
         children:  ['zuzuz', 'dbdbd', 'gsgsg']
     },
    zuzuz: {value: "DBA"},
    dbdbd: { value: "Gaming" },
    gsgsg: {
      value: "Web",
      children: ["qqqq", "dddd", "oooo"]
    },
   qqqq: {
      value: "Front End"
    },
   dddd: { 
     value: "Back End"
    },
   oooo: {
     value: "Full Stack"
   }   
}

Pros

  • Easy to look up a value or update a node given it's flat structure.
  • Easier to rearrange

Cons

  • Parent of the nested Tree Field item is not obvious but is fixable by either changing the id's to be separated by depth uwuwu_gsgsg_qqqq this has a disadvantage of reorganization needs

here values on FieldItem could be either just the ids ["uwuwu", "qqqq"] or an array of objects with the key value pair.

@MKwenhua
Copy link
Contributor Author

@toastercup I was thinking that I should build either a Gem To Handle this new logic that would be owned by cbdr. Or just build a singleton class within Cortex.

Which do you think I should do?

@toastercup
Copy link
Member

toastercup commented Feb 23, 2018

@MKwenhua I definitely like the flat tree approach - it definitely has some big advantages. However, both approaches suffer from the same problem - they require custom logic to create and parse the tree. Getting away from this is my top priority in this story - complexity of the data structure is secondary, but also important.

To this end, I'd like you to dig into the fully-tested RubyTree library and see if it's appropriate for our needs. It requires a single root node, but I think there are easy workarounds for this - either using the second level of the tree as the 'root level', or by initializing multiple root TreeNodes for each root node and putting together some simple logic to juggle them.

I'd also like to know what weakness in the frontend realm initially prompted your concern. Let me know what you think!

@MKwenhua
Copy link
Contributor Author

@toastercup Ok I will look into RubyTree

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants