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

[Table] Add menu to change cell content in Table playground #1229

Merged
merged 8 commits into from
Jun 14, 2017

Conversation

cmslewis
Copy link
Contributor

@cmslewis cmslewis commented Jun 13, 2017

Changes proposed in this pull request:

  • Add <select> menu to change cell content in the entire table in one fell swoop.
    • Empty
    • Cell names (A1, J17, etc.)
    • Long text (random alphanumeric strings between 5 and 40 chars long)
  • Delete the old "Fill with random text" menu items in column headers.

Reviewers should focus on:

  • This only affects the table preview page.
  • We really need some way to force update all cells in the Table, without requiring scrolling (this goes for any Table, not just our preview). This constraint is why you have to scroll before seeing the cell content change.

Screenshot

2017-06-13 12 40 58

@blueprint-bot
Copy link

Delete 'Fill with random text' option

Preview: documentation | table
Coverage: core | datetime

const ALPHANUMERIC_CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

interface ICellContentGeneratorDictionary {
[key: string]: (rowIndex?: number, columnIndex?: number) => string;
Copy link
Contributor

Choose a reason for hiding this comment

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

key: CellContent?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Seems to require [key: number | string] :/

Copy link
Contributor

Choose a reason for hiding this comment

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

how about Record<CellContent, (signature) => string>?

Record is TS's shorthand for this, a la Pick or Partial.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Doesn't work:

[ts] Type 'CellContent' does not satisfy the constraint 'string'.
enum CellContent

Using enums as keys is a huge discussion: microsoft/TypeScript#2491. I'll just get rid of the type safety; it's only an example page.

private toCellContentLabel(cellContent: CellContent) {
if (cellContent === "CellNames") { return "Cell names"; }
if (cellContent === "Empty") { return "Empty"; }
if (cellContent === "LongText") { return "Long text"; }
Copy link
Contributor

Choose a reason for hiding this comment

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

why not just use the english string as the enum constant?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Given that I need to make way for an upcoming usage that will map TruncatedPopoverMode values to string labels, maybe I'll just change CellContent to a number-based enum too.

if (isNextStateDefined &&
nextState.cellContent === this.state.cellContent
&& nextState.numRows === this.state.numRows
&& nextState.numCols === this.state.numCols
Copy link
Contributor

Choose a reason for hiding this comment

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

inconsistent && alignment here. put all at the beginning of lines.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops


const cellContent = isNextStateDefined ? nextState.cellContent : this.state.cellContent;
const numRows = isNextStateDefined ? nextState.numRows : this.state.numRows;
const numCols = isNextStateDefined ? nextState.numCols : this.state.numCols;
Copy link
Contributor

Choose a reason for hiding this comment

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

👎 either use this.state as default value for argument, or deconstruct all at once like so:

const { ... } = isNextStateDefined ? nextState : this.state;

@@ -468,6 +528,31 @@ class MutableTable extends React.Component<{}, IMutableTableState> {
// State updates
// =============

// designed to be called from componentWillMount and componentWillUpdate, hence it expects nextProps
private syncCellContent = (nextState?: IMutableTableState) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

(nextState = this.state) => { ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That would cause the equality checks below to return on componentWillMount (because the default value would cause isNextStateDefined to never be false); I do want to go through all the content generation at that time, so I'll presumably need to know if the real nextState is defined or not.

Copy link
Contributor

Choose a reason for hiding this comment

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

you could pull that isNextStateDefined check up a level to componentWillUpdate itself, cuz it only applies to that one usage of this 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.

Nice, done

@blueprint-bot
Copy link

CR feedback

Preview: documentation | table
Coverage: core | datetime

@tgreenwatts
Copy link
Contributor

  • This has the same rendering issue, where you change the selection but have to scroll before the data shows up?
  • Next up - truncated text, wrapped text & json wrapped text??

Very exciting!

EMPTY,
CELL_NAMES,
LONG_TEXT,
};
Copy link
Contributor

Choose a reason for hiding this comment

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

logically, i'd define this immediately before CELL_CONTENTS instead of inserting this MutableTableState in the way.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

k

CellContent.EMPTY,
CellContent.CELL_NAMES,
CellContent.LONG_TEXT,
] as CellContent[];
Copy link
Contributor

Choose a reason for hiding this comment

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

is this cast necessary now that it's an enum? if so, def preferable as type declaration instead of cast.

const CELL_CONTENTS: CellContent[] = ...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

const ALPHANUMERIC_CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

interface ICellContentGeneratorDictionary {
[key: string]: (rowIndex?: number, columnIndex?: number) => string;
Copy link
Contributor

Choose a reason for hiding this comment

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

how about Record<CellContent, (signature) => string>?

Record is TS's shorthand for this, a la Pick or Partial.

if (cellContent === CellContent.CELL_NAMES) { return "Cell names"; }
if (cellContent === CellContent.EMPTY) { return "Empty"; }
if (cellContent === CellContent.LONG_TEXT) { return "Long text"; }
return "";
Copy link
Contributor

Choose a reason for hiding this comment

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

switch? 🤷‍♂️

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yep, done

@@ -468,6 +528,31 @@ class MutableTable extends React.Component<{}, IMutableTableState> {
// State updates
// =============

// designed to be called from componentWillMount and componentWillUpdate, hence it expects nextProps
private syncCellContent = (nextState?: IMutableTableState) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

you could pull that isNextStateDefined check up a level to componentWillUpdate itself, cuz it only applies to that one usage of this function.

return handleNumberChange((value: number) => {
this.setState({ [stateKey]: value });
});
}

private handleStringStateChange = (stateKey: keyof IMutableTableState) => {
return handleStringChange((value: string) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

def don't need the typing on value param in all three cases here, handle*Change does that for you.

then you could make these bodies into one-liners:

private handleNumberStateChange = (stateKey: keyof IMutableTableState) => {
    return handleNumberChange((value) => this.setState({ [stateKey]: value }));
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

private generateRandomAlphanumericString(minLength = 5, maxLength = 40) {
const randomLength = Math.floor(minLength + (Math.random() * (maxLength - minLength)));
return Utils.times(randomLength, () => {
const randomIndex = Math.floor(Math.random() * maxLength);
Copy link
Contributor

Choose a reason for hiding this comment

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

this doesn't seem safe... did you mean ALPHANUMERIC_CHARS.length?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did.

@blueprint-bot
Copy link

Respond to CR feedback

Preview: documentation | table
Coverage: core | datetime

[CellContent.CELL_NAMES]: (row: number, col: number) => Utils.toBase26Alpha(col) + (row + 1),
[CellContent.EMPTY]: () => "",
[CellContent.LONG_TEXT]: () => this.generateRandomAlphanumericString(),
};
Copy link
Contributor

Choose a reason for hiding this comment

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

seems like a good candidate for const above, no need for private member it seems. could inline generateRandomAlphanumericString for the third one.

@blueprint-bot
Copy link

More CR feedback

Preview: documentation | table
Coverage: core | datetime

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

Successfully merging this pull request may close these issues.

4 participants