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

Add 'toHierarchy()' method equivalent to 'toArray()' method #1790

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

LavaSlider
Copy link

I was using nested Sortable elements and needed a way to easily dump the hierarchy. The added method is analogous to 'toArray()' except that it includes both ids of the Sortable element and all its nested lists.

This is only new code, three new options and three new methods so should not change other functionality.

'npm audit fix' and 'npm audit' preparing for building.
Such as missing closing parenthases, forgotten commas, wrong
assignments, etc.
@waynevanson
Copy link
Contributor

Could you please write some tests for this? We shouldn't accept PR's without tests.

I think that instead of recursive arrays, we should have this as recursive object-arrays.

This way the data type will always be the same, instead of the array element being of type string[] | null.

const hierarchy = [
  { value: "a", children: [ { value: "b", children: [ ] } ] },
  { value: "b", children: [ /* we could go on forever... */ ] },
  { value: "c", children: [ ] },
  { value: "d", children: [ ]}
]

Copy link
Contributor

@waynevanson waynevanson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The package-lock.json file looks like it hasn't been gitted correctly.

We can fix this later. Focus on the comments I mentioned earlier instead.

@owen-m1
Copy link
Member

owen-m1 commented Apr 14, 2020

@waynevanson @LavaSlider I wrote the code for what Wayne suggested in the answer to a question on stack overflow:
https://stackoverflow.com/a/56589385/6088312

I also think it would be a less confusing approach.
Also we need to update the README.

@LavaSlider
Copy link
Author

I considered using an array of objects but went with the way it is implemented because it is most consistent with the current functionality of 'toArray'. It is also much lighter weight. The array types are either String or Array, no null's.

I am happy to add another method that would loop through the current return and convert it to the structure you describe. What would you suggest the name for that method?

I have seen both structures of return from other Sortable/Draggable packages.

I will work on developing some tests and updating the README file as well.

@owen-m1
Copy link
Member

owen-m1 commented Apr 14, 2020

@LavaSlider I think it is less confusing to just use one method, and to me the object with children property makes the most sense for persisting data, because it causes the least confusion.

Sortable is a big library with a lot of users and it isn't a library that doesn't requires much programming experience to use, so inevitably there will be lots of questions over any bit of possible confusion.

@LavaSlider
Copy link
Author

I am attempting to write tests but when I run npn run test it only reports FAILED COUNT 1 without giving the test name or the message from the actual assertion. At the end the screen contains:

sortablejs@1.10.2 test /.../Sortable
node ./scripts/test.js

FAILED COUNT 1
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! sortablejs@1.10.2 test: node ./scripts/test.js
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the sortablejs@1.10.2 test script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR! /.../.npm/_logs/2020-04-15T21_47_29_550Z-debug.log

I've looked in the -debug.log file in the _logs directory but it does not have the information. Any suggestions?

@waynevanson
Copy link
Contributor

Not sure what to do. I'll write a more helpful test runner soon.

@waynevanson
Copy link
Contributor

@LavaSlider If you commit your test to the repo, we can have a look

This method is similar to a recursive 'toString'. It has
three modes of operation. Mode 2 is most similar to 'toString'
and returns an array of 'id's with interspersed arrays of 'id's
for the sublists. The default, mode 0, returns an array of
object with 'id' and 'children' properties. Mode 1 is similar
to mode 0 except omits the 'children' property if there are
no children.
These tests piggy-back on the already existing 'nested'
tests by assessing the output of 'toHierarchy()' after
the row-dragging. This is done by adding an 'onEnd' event
handler to update the DOM based on current row structure
and then compare that text to the expected text.
@LavaSlider
Copy link
Author

Ok, it is your library and you can do what you want but I whole heartedly disagree about the structure and think your statement is inconsistent with how the toArray works.

Users will use what is provided and want their tools to do what they say they do as efficiently and effectively as possible. Changing to objects with children more than quadruples the data size.

To me they seem virtually identical in use. Below is the same function written for each data array format:

toHTML( arr ) {
    let str = "<ul>\n",
        n = arr.length;
    for( let i = 0; i < n; ++i ) {
        str += '<li data-id="' + arr[i] + ">" + fetch( arr[i] ).toString();
        if( i+1 < n && Array.isArray( arr[i+1] ) ) {
            str += "\n" + toHTML( arr[++i] );
        }
        str += "</li>\n";
    }
    str += "</ul>\n";
    return str;
}
toHTML( arr ) {
    let str = "<ul>\n",
        n = arr.length;
    for( let i = 0; i < n; ++i ) {
        str += '<li data-id="' + arr[i].id + ">" + fetch( arr[i].id ).toString();
        if( arr[i].children.length > 0 ) {
            str += "\n" + toHTML( arr[i].children );
        }
        str += "</li>\n";
    }
    str += "</ul>\n";
    return str;
}

To compromise I have merged them into one method that I renamed to getHierarchy() with an optional "mode" parameter and set the default mode to the maximally verbose method with an 'id' and a 'children' property for every node. Mode 1 will strip the 'children' property if there are no children and mode 2 will just return the id strings and arrays as I originally implemented it.

I implemented tests as part of the current nested test suite by putting the stringified version of the returned values into the DOM and comparing that to the expected strings. This will fail if JSON.stringify() changes its output (such as changes in white space, quotes used, etc.) but works now.

I also added the sections to the README.md file describing the operations.

@LavaSlider
Copy link
Author

Oops, had forgot to remove a 60 second delay in the test script I had added for figuring out what was going on.

@waynevanson
Copy link
Contributor

I whole heartedly disagree about the structure and think your statement is inconsistent with how the toArray works

toArray is not toHierarchy. If we want to use objects other than arrays, we have the flexibility to.

Sometimes specific use cases should transform the data to a structure they need with a single function of their own.

Changing to objects with children more than quadruples the data size.

I'd rather have more data and a clear way of navigating it than trying to navigate nested arrays.

To compromise I have merged them into one method

I'd recommend that we get the hierarchy using one method only, then transform that data to it's various different 'shapes'. That way if any changes are made in future, there will only have to be one 'getter' function from the DOM.

type Hierarchy = { id: string, children: Hierarchy[] }

function getHierarchy() :Hierarchy 

I will do a review in more detail when I get the time over the next week. I need more time to process the code.

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

Successfully merging this pull request may close these issues.

None yet

3 participants