FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

feat(Table): support inline editing in PF4 by atiratree · Pull Request #1227 · patternfly/patternfly-react · GitHub

feat(Table): support inline editing in PF4 - #1227

Merged
jschuler merged 2 commits into
patternfly:masterfrom
atiratree:pf4-table-inline-edit
Mar 25, 2019
Merged

feat(Table): support inline editing in PF4#1227
jschuler merged 2 commits into
patternfly:masterfrom
atiratree:pf4-table-inline-edit

Conversation

atiratree commented Jan 22, 2019
edited
Loading

Copy link
Copy Markdown

Hi, I tried to tackle inline editing with reactabular. But it is still not perfect and a bit hacky.

My main goal was to prevent this behavior: kubevirt/web-ui-components#9, but other issues are still present.

  • inability to set a cursor to other edited cell (the cursor will firstly appear at the end and then it can be moved)
  • no possibility for real time validation (char by char)

This is a due to the reactabular architecture, where we cannot expect our cells to behave in react-like way and have to implement workarounds introduced by this PR. It is inspired by https://github.com/reactabular/react-edit and uses onBlur and autoFocus on input elements

There is one issue with gatsby? where the whole table page is refreshed and the table component is called by costructor. This happens on a dropdown selection in Editable table With Inline Edit Row

live site: https://1227-pr-patternfly-react-patternfly.surge.sh/patternfly-4/components/inlineedit

TODO:

  • finish styles
  • move hardcoded styles to pf-next
  • move to separate package
  • add component extensibility
  • add typescript support
  • tests

Current Issues:

@priley86 @karelhala

isReadOnly: false,
type: 'text',
value: null,
value: undefined,

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

to allow uncontrolled components like TableTextInput

@@ -0,0 +1,8 @@
// TODO: better sharing util components between modules

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

this is copied from @react-core internal. Does someone have any recommendations how to share utility classes between modules?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

added #1232 for this. If it merges you can:

import { debounce } from '@patternfly/react-core';

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

thanks

onClick: (event) => onRowClick(event, row, props)
row,
rowProps: props,
onMouseDown: (event) => {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

onMouseDown is needed to register clicks before onChange/onBlur changes the row (which discards the onClick)

priley86 Jan 22, 2019
edited
Loading

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

this seems like kind of a hack, but works. I wonder if proposing an upstream PR to reactabular in parallel to allow hooks into onChange onBlur would be a good idea?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Where would the hooks be? I am not sure something like this would help.
The idea of this is to get ahead of cell onBlur callbacks. Because of the cell's onBlur callback, the cell will be scrapped and then constructed again. And then we get a chance to fire callbacks (captured here) on our new instance.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

it is a hack nevertheless :)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

One note, can this function be moved outside of this component? So it would be easier to read the component when debugging?

};

export const TableEditConfirmation = {
NONE: 'NONE', // TODO: do edit buttons make sense on the left?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Should we include more combinations of edit buttons? E.g. on the left?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

This question is better to be asked any UX person @mcarrano any thoughts on this?

};

// TODO: shouldComponentUpdate?
// TableConfirmButtonsRow.shouldComponentUpdate = true;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

not really sure yet if shouldComponentUpdate is needed? It was present in the pf3 component

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

As long as you are not trying to calculate re-renders for you we don't really need to use shouldComponentUpdate

privateRepo: false
}
// isEditing: true,
// activeEditCell: 3

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

possibility to select editing programatically

coveralls commented Jan 22, 2019
edited
Loading

Copy link
Copy Markdown

Pull Request Test Coverage Report for Build 4563

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • 31 unchanged lines in 3 files lost coverage.
  • Overall coverage increased (+2.08%) to 81.212%

Files with Coverage Reduction New Missed Lines %
packages/patternfly-4/react-core/src/components/Dropdown/Separator.js 1 80.0%
packages/patternfly-4/react-core/src/components/Dropdown/DropdownItem.js 4 34.52%
packages/patternfly-4/react-core/src/helpers/util.ts 26 14.29%
Totals
Change from base Build 4547: 2.08%
Covered Lines: 3670
Relevant Lines: 4239

💛 - Coveralls

karelhala self-requested a review January 22, 2019 13:38

Copy link
Copy Markdown
Member

Added issue 1228 for this.

case TableEditConfirmation.ROW:
if (isEditing) {
editStyle = {
background: '#def3ff',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

can you replace all color references with actual color tokens from @patternfly/react-tokens (ex consumption here )?

you can also find these and their default mappings here:
http://patternfly-react.surge.sh/patternfly-4/styles/tokens/

If these colors don't exist, maybe we can subtitute an existing pf-next color?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

yes, I am planning to do the css cleanup

dgutride commented Jan 22, 2019
edited
Loading

Copy link
Copy Markdown
Member

This seems like a great idea; however, we are avoiding adding anything to react-core or the core packages (which include react-table) that do not have backing PatternFly patterns and documentation. Would it be possible to move this to a new @ patternfly / {name of packaqge} - extension package so we can consider including it into core PatternFly at a later date?

import { Body } from 'reactabular-table';
import PropTypes from 'prop-types';
import { TableContext } from './Table';
import '../../../internal/closestPolyfill';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

This is a sideEffect and will break webpack 4 (well not be imported in production)., It is also generally a bad idea to pollute prototypes for the user. This should be an opt-in pollyfill by the consumer. We can still export it and if they want/need it they can use it. Also since by default PF4 is excluding IE support (a workaround is coming for consumers needing it) the closest polyfill is not needed.

If we do for sure want to keep this in the lib it would be better to do something like:

function closest(element, selector) {
  if (typeof element.closest === 'function') {
    return element.closest(selector);
  }

  if (document.documentElement.contains(el)) {
    while (el && el.nodeType === 1) {
      if (el.matches(selector)) return el;
      el = el.parentElement || el.parentNode;
    }
  }
  return null;
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Good to know. I just assumed it would be the same as PF3 so I copied it from there. Removed

export const matches =
Element.prototype.matches || Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;

if (!Element.prototype.matches) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Not needed at all. This is supported by all major browsers including IE9+

return null;
}

if (!Element.prototype.closest) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

See comment in packages/patternfly-4/react-table/src/components/Table/Body.js

onRowClick(event, row, props);
if (onEditCellChanged) {
// edit cell after rerender
setTimeout(onEditCellChanged, 0);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

This seems kind of "hacky" with upcoming react releases it is possible that the rerender may not have actually taken place here. will that be ok? I can't tell from the code if that will cause issues or not.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

In that case we would really have to contribute to reactabular and fix these issues. Yup it is hacky, but there are not many other solutions.

Copy link
Copy Markdown
Author

This seems like a great idea; however, we are avoiding adding anything to react-core or the core packages (which include react-table) that do not have backing PatternFly patterns and documentation. Would it be possible to move this to a new @ patternfly / {name of packaqge} - extension package so we can consider including it into core PatternFly at a later date?

Sorry for late response because of the PTO.

I get the idea of putting bigger features to separate packages.
Nevertheless, I think inline editing is quite integral part of the table and it would be less complicated for the user to not use multiple packages. It is possible, but it would be quite cumbersome and not quite worth it in my opinion.

Btw, do you mean patternfly next patterns or https://www.patternfly.org/pattern-library/forms-and-controls/inline-edit/ ?

atiratree force-pushed the pf4-table-inline-edit branch 2 times, most recently from ac5c96e to f8864c5 Compare February 1, 2019 17:16

karelhala left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Really nice extension! I like how you are passing different editors for different edits. That is really great approach. Few nitpicks, but overall good PR!

onClick: (event) => onRowClick(event, row, props)
row,
rowProps: props,
onMouseDown: (event) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

One note, can this function be moved outside of this component? So it would be easier to read the component when debugging?

hidden={isExpanded !== undefined && !isExpanded}
/>
);
const hasConfirmationButtons = (editConfirmationType, { isEditing, isTableEditing, isFirst, isLast }) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

These function with switch can be converted to object, this approach is much more extensible.

const tableMapper = {
  [TableEditConfirmation.TABLE_TOP]: ({ isTableEditing, isFirst }) => isTableEditing && isFirst,
  [TableEditConfirmation.TABLE_BOTTOM]: ({ isTableEditing, isFirst }) => isTableEditing && isLast,
  [TableEditConfirmation.ROW]: ({ isEditing }) => isEditing,
  [TableEditConfirmation.NONE]: () => false
}

You would then use it like

const hasConfirmationButtons = (editConfirmationType, props) => {
  tableMapper[editConfirmationType] && tableMapper[editConfirmationType](props);
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

you are right, it looks much cleaner now

}
};

export const areButtonsOnTop = (editConfirmationType, { isLast }) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Similiar approach as with the previous function.

let editStyle;

if (isTableEditing) {
switch (editConfirmationType) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Honestly I don't really like switches, they tend to be really complex, hard to read and even harder to extend. Please consider using object literal with functions.

}
const { editConfirmationType, onEditConfirmed, onEditCanceled } = editConfig;

let confirmButtons;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

No need to assign to variable if we are not gonna do anything with it and just return it. It's much cleaner to just return from if statement. When the if is not satisfied function will return undefined nevertheless.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I would rather remove it too, but I kept that because of eslint/prettier. I am not sure how do we stand on that?

};

export const TableEditConfirmation = {
NONE: 'NONE', // TODO: do edit buttons make sense on the left?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

This question is better to be asked any UX person @mcarrano any thoughts on this?

};

// TODO: shouldComponentUpdate?
// TableConfirmButtonsRow.shouldComponentUpdate = true;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

As long as you are not trying to calculate re-renders for you we don't really need to use shouldComponentUpdate

) => {
const { rowData, columnIndex } = additionalData;

let result;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

No need to assign to result if we are only returning it. You can add return instead of assign to each if statements and it wil be the same.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

you are right, thanks

Copy link
Copy Markdown
Contributor

@suomiy what @dgutride is proposing is kinda understandable. We want to ship table component as pure as possible with only few enhancers and if consumers want to use inline edit they'd import @patternfly/react-table-inline-edit for instance. Inside of this package there would be few functions and components reponsible for edits. The code would still be part of this repository, it would just be moved into special folder and a bit of config is needed. If you want I can help you by moving it there or you can get inspired by @priley86 #1250 about virtualized scroll.

atiratree force-pushed the pf4-table-inline-edit branch from f8864c5 to 18067b4 Compare February 4, 2019 11:02

Copy link
Copy Markdown
Author

@suomiy what @dgutride is proposing is kinda understandable. We want to ship table component as pure as possible with only few enhancers and if consumers want to use inline edit they'd import @patternfly/react-table-inline-edit for instance. Inside of this package there would be few functions and components reponsible for edits. The code would still be part of this repository, it would just be moved into special folder and a bit of config is needed. If you want I can help you by moving it there or you can get inspired by @priley86 #1250 about virtualized scroll.

Ok, I guess it makes sense to separate it. I will look into that.
Nevertheless I think there will still be some overlap of the code. I will discuss this with @priley86.

Copy link
Copy Markdown
Collaborator

PatternFly-React preview: https://1227-pr-patternfly-react-patternfly.surge.sh

Copy link
Copy Markdown
Contributor

@suomiy if you need some special variables to be passed to core implementation that is fine, that code won't be used. But if we split this into another package we have really great way of importing custom packages and promote other teams to contribute and use some other packages (even written outside of PF world)

tlabaj added the PF4 label Feb 4, 2019
atiratree force-pushed the pf4-table-inline-edit branch 4 times, most recently from 645f600 to e2ce121 Compare February 15, 2019 13:15
atiratree force-pushed the pf4-table-inline-edit branch 3 times, most recently from 18a037b to 47b70e6 Compare February 15, 2019 14:57

Copy link
Copy Markdown
Contributor

I've removed the Do not merge label since it's in its own package now @dgutride
@priley86 @karelhala please review again :)

atiratree force-pushed the pf4-table-inline-edit branch 4 times, most recently from dd96fd9 to 1d8b7f2 Compare March 21, 2019 19:38

Copy link
Copy Markdown
Author

Fixed TS and added support for rendering NO_CONFIRM_ROW type.

This PR is ready for final reviews (sibling #1520 was merged).

Copy link
Copy Markdown
Member

great job on this @suomiy! I know you are eager to iterate on this extension downstream. I filed my follow-up issue just now in #1628. I am happy to see this merge when others are.

jschuler previously approved these changes Mar 22, 2019

Copy link
Copy Markdown
Member

getting these here locally now...can we fix them first?

@patternfly/react-docs: error There was a problem parsing component metadata for file: "components/InlineEdit/editableRowWrapper.js"
@patternfly/react-docs: 
@patternfly/react-docs:   TypeError: Property name must be an Identifier or a Literal
@patternfly/react-docs:   
@patternfly/react-docs:   - getPropertyName.js:36 getPropertyName

Copy link
Copy Markdown
Author

getting these here locally now...can we fix them first?

fixed, seems like we can't have dynamic object keys (reactjs/react-docgen#317 (comment))

+ added a comment about this issue to the code as the constants are now hardcoded

priley86 previously approved these changes Mar 22, 2019

priley86 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

react-docs look good and tests pass locally. Please just update the patternfly dependency, but will go ahead and approve. nice work!

karelhala self-requested a review March 25, 2019 08:11
karelhala previously approved these changes Mar 25, 2019

karelhala left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Looks really good! Thank you for this PR!

atiratree dismissed stale reviews from karelhala and priley86 via 21ca9d8 March 25, 2019 10:22
atiratree force-pushed the pf4-table-inline-edit branch from 931e249 to 21ca9d8 Compare March 25, 2019 10:22
atiratree force-pushed the pf4-table-inline-edit branch from 21ca9d8 to dfb18fd Compare March 25, 2019 12:09

Copy link
Copy Markdown
Author

updated @patternfly/patternfly dependency

jschuler left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Thanks @suomiy , great work on this!

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
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.


Back | FazBrowse Home | New Git URL