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

Introducing react icons! #10247

Closed
wants to merge 6 commits into from
Closed

Conversation

stacey-gammon
Copy link
Contributor

@stacey-gammon stacey-gammon commented Feb 8, 2017

The very first introduction of embedded react in our angular apps.

Starting very simple with components that have no props passed from angular, or state. I've confirmed it's possible, just decided to start very small.

@stacey-gammon stacey-gammon force-pushed the react-icons branch 2 times, most recently from 78c23f8 to 43c4c60 Compare February 8, 2017 18:21

import uiModules from 'ui/modules';
const app = uiModules.get('app/visualize', ['react']);
app.value('PlusIcon', PlusIcon);
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if we can come up with a naming convention that distinguishes react components from all other other values in the injector... maybe XYZComponent?

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'd be down with that.

Copy link
Contributor

@cjcenizal cjcenizal left a comment

Choose a reason for hiding this comment

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

Functionality and UI looks good! This is awesome. Just had a couple suggestions.

import 'ngreact';

import { PlusIcon } from 'ui_framework/components/icon/plus_icon';
import { TrashIcon } from 'ui_framework/components/icon/trash_icon';
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we implement an index.js file in ui_framework/components which imports and re-exports the components?

export { PlusIcon } from './icon/plus_icon';
export { TrashIcon } from './icon/trash_icon';

And then we can import them here, like this:

import {
  PlusIcon,
  TrashIcon,
} from 'ui_framework/components';

I think this is an improvement because then we can treat the UI Framework like a module, and we'll have the ability to rearrange things internally by renaming folders and moving files without changing the interface. We can also write tests for this interface for immediate notification of when we break it by accident.


export function KuiIcon({ className }) {
const classNames = ['kuiButton__icon', 'kuiIcon', className];
return <span aria-hidden="true" className={ classNames.join(' ') }/>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we add the classnames dependency and use it here instead of using join? It will become more useful when we have more complex logic for adding class names, e.g. setting a special "clickable" class to labels if they're associated with an input via the for attribute.

import classNames from 'classnames';

const classes = classNames('kuiButton__icon kuiIcon', classname);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

coooool

Copy link

Choose a reason for hiding this comment

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

it's yet another dependency just for a single function... we can copy the function, put it in our utils and maintain it ourselves.

Copy link
Contributor

@spalger spalger left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@cjcenizal cjcenizal left a comment

Choose a reason for hiding this comment

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

LGTM!

Copy link
Member

@weltenwort weltenwort left a comment

Choose a reason for hiding this comment

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

So glad to see react in the package.json! 🎉

@@ -39,7 +39,7 @@
ng-click="listingController.deleteSelectedItems()"
tooltip="Delete selected visualizations"
>
<span aria-hidden="true" class="kuiButton__icon kuiIcon fa-trash"></span>
<react-component name="TrashIconComponent"></react-component>
Copy link
Member

Choose a reason for hiding this comment

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

Was a conscious choice made here about using <react-component> over the reactDirective Service? The latter seems to allow more control over the way bindings are converted to props.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nope, just unaware of that, very cool!! Switched over.

Copy link
Contributor

Choose a reason for hiding this comment

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

Nice! Love the change

Copy link
Member

@weltenwort weltenwort left a comment

Choose a reason for hiding this comment

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

LGTM, love the use of stateless components there 👍

@stacey-gammon
Copy link
Contributor Author

Jenkins error:

16:01:01.169: Taking screenshot "/var/lib/jenkins/workspace/elastic+kibana+pull-request+multijob-selenium/test/screenshots/failure/failure_1486656061169_discover app_discover app.png"
SUITE ERROR
Error: [mapper_parsing_exception] [include_in_all] is not allowed for indices created on or after version 6.0.0 as [_all] is deprecated. As a replacement, you can use an [copy_to] on mapping fields to create your own catch all field.
  at  :: {"path":"/logstash-2015.09.20","query":{},"body":"{\"settings\":{\"index\":{\"number_of_shards\":1,\"number_of_replicas\":0},\"analysis\":{\"analyzer\":{\"url\":{\"type\":\"standard\",\"tokenizer\":\"uax_url_email\",\"max_token_length\":1000}}}},\"mappings\":{\"_default_\":{\"dynamic_templates\":[{\"string_fields\":{\"mapping\":{\"type\":\"text\",\"fields\":{\"raw\":{\"type\":\"keyword\"}}},\"match_mapping_type\":\"string\",\"match\":\"*\"}}],\"properties\":{\"  <timestamp\":{\"type\":\"date\"},\"id\":{\"type\":\"integer\",\"index\":true,\"include_in_all\":false},\"clientip\":{\"type\":\"ip\"},\"ip\":{\"type\":\"ip\"},\"memory\":{\"type\":\"double\"},\"referer\":{\"type\":\"keyword\"},\"geo\":{\"properties\":{\"srcdest\":{\"type\":\"keyword\"},\"dest\":{\"type\":\"keyword\"},\"src\":{\"type\":\"keyword\"},\"coordinates\":{\"type\":\"geo_point\"}}},\"meta\":{\"properties\":{\"related\":{\"type\":\"text\"},\"char\":{\"type\":\"keyword\"},\"user\":{\"properties\":{\"firstname\":{\"type\":\"text\"},\"lastname\":{\"type\":\"integer\",\"index\":true}}}}}}}}}","statusCode":400,"response":"{\"error\":{\"root_cause\":[{\"type\":\"mapper_parsing_exception\",\"reason\":\"[include_in_all] is not allowed for indices created on or after version 6.0.0 as [_all] is deprecated. As a replacement, you can use an [copy_to] on mapping fields to create your own catch all field.\"}],\"type\":\"mapper_parsing_exception\",\"reason\":\"Failed to parse mapping [_default_]: [include_in_all] is not allowed for indices created on or after version 6.0.0 as [_all] is deprecated. As a replacement, you can use an [copy_to] on mapping fields to create your own catch all field.\",\"caused_by\":{\"type\":\"mapper_parsing_exception\",\"reason\":\"[include_in_all] is not allowed for indices created on or after version 6.0.0 as [_all] is deprecated. As a replacement, you can use an [copy_to] on mapping fields to create your own catch all field.\"}},\"status\":400}"}>
    at respond (/var/lib/jenkins/workspace/elastic+kibana+pull-request+multijob-selenium/node_modules/elasticsearch/src/lib/transport.js:289:15)
    at checkRespForFailure (/var/lib/jenkins/workspace/elastic+kibana+pull-request+multijob-selenium/node_modules/elasticsearch/src/lib/transport.js:248:7)
    at HttpConnector.<anonymous> (/var/lib/jenkins/workspace/elastic+kibana+pull-request+multijob-selenium/node_modules/elasticsearch/src/lib/connectors/http.js:164:7)
    at IncomingMessage.wrapper (/var/lib/jenkins/workspace/elastic+kibana+pull-request+multijob-selenium/node_modules/elasticsearch/node_modules/lodash/lodash.js:4968:19)
    at emitNone (events.js:91:20)
    at IncomingMessage.emit (events.js:185:7)
    at endReadableNT (_stream_readable.js:974:12)
    at _combinedTickCallback (internal/process/next_tick.js:74:11)
    at process._tickCallback (internal/process/next_tick.js:98:9)
>> 19/19 tests failed

looks unrelated. Trying again.

jenkins test this

@stacey-gammon stacey-gammon mentioned this pull request Feb 9, 2017
2 tasks
@@ -39,7 +39,7 @@
ng-click="listingController.deleteSelectedItems()"
tooltip="Delete selected visualizations"
>
<span aria-hidden="true" class="kuiButton__icon kuiIcon fa-trash"></span>
<trash-icon-component></trash-icon-component>
Copy link
Contributor

Choose a reason for hiding this comment

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

So... this is pretty different than it was so I think we should rethink this naming convention :) <kui-trash-icon>?

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 like that idea, but keep in mind not all react components will be coming from the ui framework. I think that's a great idea for ui framework components, but what about other components? E.g. <visualize-landing-table></visualize-landing-table>

Copy link
Member

Choose a reason for hiding this comment

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

I agree that the component names should not contain "Component". IHMO <visualize-landing-table> sounds ok as does <kui-trash-icon>.

Copy link
Contributor

Choose a reason for hiding this comment

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

Personally, I don't think there is any reason to indicate that these angular directives are backed by react components. When the react components were sitting in the angular $injector, it was a different story, but now I think it makes more sense to hide that detail and just treat them like every other directive

@thomasneirynck
Copy link
Contributor

rebasing with master should get CI to pass again (cf. 0d9e51f)

@stacey-gammon
Copy link
Contributor Author

@kjbekkelund This was my first PR (not to be checked in) that tackled react components in their simplest form - that didn't require props or state at all. Feel free to comment on this PR, or just go straight to the next PR: #10257 which consumes this one and adds on to it.

import { KuiIcon } from './kui_icon';

export function DeleteIcon() {
return <KuiIcon className="fa-trash"/>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpick: As these become a whole lot of tiny files, I think I'd personally go for starting with adding them to ui_framework/components/icon/index.js like this:

import React from 'react';
import { KuiIcon } from './kui_icon';

export const DeleteIcon = () => <KuiIcon className="fa-trash"/>

export const CreateIcon = () => <KuiIcon className="fa-plus"/>

etc, and in ui_framework/components/index.js:

export * from './icon';

then later on extract even further if needed. That would also make it easy to extract one icon into it's own file and do something like this:

export { UserIcon } from './user_icon'

instead of defining it in the same file.

Copy link

Choose a reason for hiding this comment

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

As these become a whole lot of tiny files, I think I'd personally go for starting with adding them to ui_framework/components/icon/index.js like this:

Personally I don't mind separate files (as you can guess... I like consistency).

Also, I wonder if we should use CamelCasing for the component file names (will clearly indicate that a file contains a component). In this example, DeleteIcon.js, CreateIcon.js, KuiIcon.js, etc...

then later on extract even further if needed. That would also make it easy to extract one icon into it's own file and do something like this:

How about just always using named imports?

Copy link
Contributor

Choose a reason for hiding this comment

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

What does the exports have to do with named imports? You'd still import them in the same way as before, this would just be an "implementation detail" within the ui_framework/components/icon folder.

Copy link

Choose a reason for hiding this comment

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

What does the exports have to do with named imports? You'd still import them in the same way as before, this would just be an "implementation detail" within the ui_framework/components/icon folder.

Oops, sorry... I thought you showed imports.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, I wonder if we should use CamelCasing for the component file names (will clearly indicate that a file contains a component). In this example, DeleteIcon.js, CreateIcon.js, KuiIcon.js, etc...

I much prefer CamelCasing file names, but I think there may have been a reason we use underscore? I was chatting with... I think @cjcenizal about this. Case sensitivity on different OS's or something? Anyway I am totally in favor of that, if there are no relevant objections. Just want to pull the right people in who have more background then me. @spalger?

++ @kjbekkelund on the exports suggestion.

Copy link

Choose a reason for hiding this comment

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

aha.. .found it :)

in any case… for me everything is open a part the move to React…. if we feel that it’s more appropriate to use CamelCasing names for react components… it’s something we can open. Also, if we do want to follow airbnb style guilde as close as possible, that’s what they recommend as well (https://github.com/airbnb/javascript/tree/master/react#naming) (note though, that we should avoid using .jsx extensions, as React is moving away from those too).

Copy link
Contributor

Choose a reason for hiding this comment

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

We made a decision many months ago to switch all file names to underscores regardless of purpose, and I think we should stick with that decision in the context of this PR. For one, it wasn't arbitrary: file name case sensitive used to bite us (well, developers on windows) with at least some regularity. I seem to recall that same issue happening recently on one of our dependencies that we don't force this constraint on... maybe the ui framework?

Changing file name conventions is also disruptive to anyone doing development on Kibana since JS imports are explicit. There's no autoloader or anything like that for us to use to help mask the nature of the change to consuming code. The shift to the current file names across the codebase was a pretty unpopular change initially as it broke a ton of stuff in the wild.

Given the difficulties around undoing file name conventions, I'm concerned about the idea that our dependencies dictate our file naming conventions.

Copy link

Choose a reason for hiding this comment

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

@epixa these are all valid points

As for platform issues with camel casing. I've been developing Java for many years not, within small and large teams, on many platforms... never encounter an issue when it comes to camel casing file names. The only problems I encountered relate to Git, when needed to change the casing of the file - Git doesn't handle it well, but there are ways around that. The only reason that can come to mind why one would say that case insensitive platforms are a problem is the a case where you have two files with the same name yet different casing... but that is just plain wrong to even be applicable as a reason.

I also find it interesting that while many follow the CamelCasing convention for file names, we find it unworkable due to platform compatibility.

Given the difficulties around undoing file name conventions, I'm concerned about the idea that our dependencies dictate our file naming conventions.

nothing dictates anything here. If there are common conventions its a good practice to follow them. If we decide to move away from common conventions, that's fine too... but ideally we shouldn't IMO...

that said, I get your point around the effort for it... but big efforts should not hold us back from doing the right thing (if we decide it's the right thing that is)

Copy link
Contributor

Choose a reason for hiding this comment

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

Let's talk about this in person. There's going to be a ton of back and forth here, and we have that opportunity coming up in March. For now, let's not block this react progress on it. We can always do a small code shift to fix these new changes in March if that's what we decide.

Copy link
Contributor

Choose a reason for hiding this comment

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

The only reason that can come to mind why one would say that case insensitive platforms are a problem is the a case where you have two files with the same name yet different casing... but that is just plain wrong to even be applicable as a reason.

Just to note, I've wasted hours debugging this exact issue before. It does happen, so it is a valid argument.

@stacey-gammon stacey-gammon force-pushed the react-icons branch 2 times, most recently from 973c52f to 3ff05bd Compare February 14, 2017 19:05
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.

9 participants