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

PTV-1620/PTV-1845 fix kbaseTabs #3117

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
Open

Conversation

eapearson
Copy link
Contributor

@eapearson eapearson commented Oct 21, 2022

Description of PR purpose/changes

PR IN PROGRESS

Note that this PR builds upon #3116, so some of those changes will disappear from the file changes when that one is merged - so this should not be reviewed until #3116 is merged.

The venerable "kbaseTabs" widget is behaving incorrectly in the kbaseExpressionConditionsetBaseWIdget.

Specifically, it is not showing the previous tab when a dynamic tab is closed, as is done when clicking on a cluster.

While fixing the kbaseTabs widget, and expanding the tests to cover additional use case, I discovered at least one additional latent bug (or at least unexpected behavior), a failure to activate the first tab if no tabs are set explicitly as active.

In addition, there were several features in this already rather complex widget that are not used anywhere in the codebase, and have been removed. They may have been used in the past, but I suspect they were "nice to have" features that were simply added for future utility. However, retaining them would require adding tests to cover them, yet yield no benefit as they are unused.

Finally, tests were expanded to cover common use cases, including the primary issue fixed by this PR.

Jira Ticket / Issue

Testing Instructions

have broken tests for kbaseTabs, working on it.

New tests were added to test/unit/spec/widgets/kbaseTabs-spec.js to cover the use case of closing a dynamically added tab.

To evaluate this manually, spin up a narrative from this PR, create a narrative, add a FeatureClusters object, and open the viewer.

There is also a gallery demonstrating usage of kbaseTabs. This is a new feature in the narrative, but "out of the way" - it does not change the actual narrative runtime. It is a set of static html pages with support for building gallery demo pages. Each gallery demo page imports code it wants to demonstrate. In a running narrative it is available at url like:

https://ci.kbase.us/narrative/static/kbase/gallery/index.html

  • Tests pass locally and in GitHub Actions
  • Changes available by spinning up a local narrative and navigating to X to see Y

Dev Checklist:

  • [-] My code follows the guidelines at https://sites.google.com/lbl.gov/trussresources/home?authuser=0
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • [-] I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • (JavaScript) I have run Prettier and ESLint on changed code manually or with a git precommit hook
  • [-] (Python) I have run Black and Flake8 on changed Python code manually or with a git precommit hook
  • [-] Any dependent changes have been merged and published in downstream modules

Updating Version and Release Notes (if applicable)

@eapearson eapearson marked this pull request as ready for review October 21, 2022 20:25
@eapearson
Copy link
Contributor Author

Still in progress, but it looks like draft PRs don't invoke GHA, and I need to iterate on tests and code quality too!

@codecov
Copy link

codecov bot commented Oct 21, 2022

Codecov Report

Merging #3117 (c5c6a11) into develop (a198ed2) will not change coverage.
The diff coverage is n/a.

❗ Current head c5c6a11 differs from pull request most recent head dbce801. Consider uploading reports for the commit dbce801 to get more accurate results

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff            @@
##           develop    #3117   +/-   ##
========================================
  Coverage    73.37%   73.37%           
========================================
  Files           36       36           
  Lines         3917     3917           
========================================
  Hits          2874     2874           
  Misses        1043     1043           

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 21d9e03...dbce801. Read the comment docs.

@sonarqubecloud
Copy link

SonarCloud Quality Gate failed.    Quality Gate failed

Bug C 8 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 3 Code Smells

No Coverage information No Coverage information
0.1% 0.1% Duplication

'use strict';
return KBWidget({
name: 'kbaseTabs',

version: '1.0.0',

_accessors: ['tabsHeight'],
Copy link
Contributor Author

Choose a reason for hiding this comment

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

tabsHeight not used anywhere, so removed.

canDelete: false,
borderColor: 'lightgray',
Copy link
Contributor Author

Choose a reason for hiding this comment

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

borderColor not used anywhere, so removed.


options: {
tabPosition: 'top',
Copy link
Contributor Author

Choose a reason for hiding this comment

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

tabPosition not used anywhere, endnote actually implemented in the widget, and not supported by bootstrap 3 afaik, so removed.

@@ -64,167 +64,208 @@ define(['kbwidget', 'bootstrap', 'jquery', 'kbaseDeletePrompt'], (
},

appendUI: function ($elem, tabs) {
if (tabs == undefined) {
if (typeof tabs === 'undefined') {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

safer test for undefinedness.

}
},

addTab: function (tab) {
if (tab.canDelete == undefined) {
if (typeof tab.canDelete === 'undefined') {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

safer undefinedness test

const $tab = $('<div role="tabpanel"></div>').addClass('tab-pane fade');

$tab.hasContent = false;
const $tabPanel = $('<div role="tabpanel"></div>').addClass('tab-pane fade');
Copy link
Contributor Author

Choose a reason for hiding this comment

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

chose a better name; with all the "tab"s floating around (including "tab.tab"!), it is important to be more specific in naming things.

}

if (this.options.border) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

removing border feature, as unused.

const $widget = this;

// Create the tab button itself.
const $navButton = $('<a>')
Copy link
Contributor Author

Choose a reason for hiding this comment

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

in order to make debugging and understanding the code construction better, I refactored out some large swathes of independent code like this.

},

removeTab: function (tabName) {
const $tab = this.data('tabs')[tabName];
const $nav = this.data('nav')[tabName];
const deleteNav = () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

extracted the deletion tab nav and panel as they are re-used, and also used separately.

$nav.remove();

this.data('tabs')[tabName] = undefined;
this.data('nav')[tabName] = undefined;
},

deletePrompt: function (tabName) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

simplified as there was no need to have an anonymous callback function call a method.

},

deletePrompt: function (tabName) {
const $deleteModal = new kbaseDeletePrompt($('<div></div>'), {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

simplified node creation like this in several places.

@ialarmedalien ialarmedalien changed the base branch from develop to PTV-1620-browser-freeze October 25, 2022 16:04

The primary customizations are:
- tabs can be set as deletable
-
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is that the only customisation?

var $tabs = new kbaseTabs($('#tabs'), {
tabPosition : 'bottom', //or left or right or top. Defaults to 'top'
canDelete : true, //whether or not the tab can be removed. Defaults to false.
tabPosition : 'bottom', // or 'left' or 'right' or 'top'. Defaults to 'top'
Copy link
Collaborator

Choose a reason for hiding this comment

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

looks like this was removed below


renderDeleteTabButton: function (tab) {
return $('<button>')
.addClass('btn btn-default btn-xs')
Copy link
Collaborator

Choose a reason for hiding this comment

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

can you give this button a unique class (btn-delete?) and add all the css there, rather than having it hardcoded here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not really hard coded is it? These are "standard" bootstrap button classes, meant to be combined like this.
Maybe I'm not understanding your point.

Base automatically changed from PTV-1620-browser-freeze to develop October 25, 2022 16:13
Comment on lines +25 to +28
expect($host.text()).toContain('Foo');
expect($host.text()).toContain('BAR');
expect($host.text()).toContain('Baz');
expect($host.text()).not.toContain('Fuzz');
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you make these tests more specific so they differentiate between what's in the tab label vs what's in the tab content?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes! There is actually a change after this which narrows the scope to the nav tabs and pane separately, not in the PR yet.

Comment on lines +80 to +96
const $host = $(document.createElement('div'));
new KBaseTabs($host, {
tabs: [
{
tab: 'Foo',
content: 'BAR',
},
{
tab: 'Baz',
content: 'Fuzz',
},
],
});
expect($host.text()).toContain('Foo');
expect($host.text()).toContain('BAR');
expect($host.text()).toContain('Baz');
expect($host.text()).not.toContain('Fuzz');
Copy link
Collaborator

Choose a reason for hiding this comment

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

since this is repeated several times, can you extract it out into a function?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you look closely you'll see that each test case configures the tabs differently.

@@ -0,0 +1,44 @@
# Demos

These demos are static html pages which demonstrate some relatively simple and isolatable aspect of the Narrative. This simple demo system is particularly suitable for ui components.
Copy link
Member

Choose a reason for hiding this comment

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

This looks a whole lot like Storybook. So why not just use Storybook?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just wanted something simple to be able to preview components w/out having to fire up the narrative and without having to introduce something like storybook to the codebase. I'll just remove this. It is useful for me, and I thought it might be for others as well.

Copy link
Member

Choose a reason for hiding this comment

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

I'm definitely not against something like this for the Narrative, this does seem a bit out of scope for this PR, though, and could use some discussion.

Thanks for removing for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No problem. It was the only way I could actually use the tab control with all combinations of options, since they don't actually all exist in the codebase; so it served its purpose for me at least :)

@eapearson
Copy link
Contributor Author

Back onto this PR - which BTW was in "fake draft" status, i.e. not ready for review. (The reason for not being in official draft status is that the GHA doesn't run for drafts, and I need to be able to iterate on the code quality, etc. before releasing it for review, as well as fold in changes from PR 3116...)
In any case, I'll respond to the points raised above after I catch it up from master and get the dev environment up and running happily.

@eapearson eapearson changed the title PTV-1620 fix kbaseTabs PTV-1620/PTV-1845 fix kbaseTabs Dec 20, 2022
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.

3 participants