From 1287f766b46427a80a3bca832f6ad7b7180c6078 Mon Sep 17 00:00:00 2001 From: rshen91 Date: Mon, 22 Aug 2022 15:34:39 -0600 Subject: [PATCH 01/21] initial commit --- package.json | 2 ++ packages/BUILD.bazel | 2 ++ yarn.lock | 8 ++++++++ 3 files changed, 12 insertions(+) diff --git a/package.json b/package.json index 62e4361441794..75f2adb6f2b75 100644 --- a/package.json +++ b/package.json @@ -306,6 +306,7 @@ "@kbn/server-route-repository": "link:bazel-bin/packages/kbn-server-route-repository", "@kbn/shared-svg": "link:bazel-bin/packages/kbn-shared-svg", "@kbn/shared-ux-avatar-solution": "link:bazel-bin/packages/shared-ux/avatar/solution", + "@kbn/shared-ux-avatar-user-profile-components": "link:bazel-bin/packages/shared-ux/avatar/user_profile/impl", "@kbn/shared-ux-button-exit-full-screen": "link:bazel-bin/packages/shared-ux/button/exit_full_screen/impl", "@kbn/shared-ux-button-exit-full-screen-mocks": "link:bazel-bin/packages/shared-ux/button/exit_full_screen/mocks", "@kbn/shared-ux-button-exit-full-screen-types": "link:bazel-bin/packages/shared-ux/button/exit_full_screen/types", @@ -986,6 +987,7 @@ "@types/kbn__server-route-repository": "link:bazel-bin/packages/kbn-server-route-repository/npm_module_types", "@types/kbn__shared-svg": "link:bazel-bin/packages/kbn-shared-svg/npm_module_types", "@types/kbn__shared-ux-avatar-solution": "link:bazel-bin/packages/shared-ux/avatar/solution/npm_module_types", + "@types/kbn__shared-ux-avatar-user-profile-components": "link:bazel-bin/packages/shared-ux/avatar/user_profile/impl/npm_module_types", "@types/kbn__shared-ux-button-exit-full-screen": "link:bazel-bin/packages/shared-ux/button/exit_full_screen/impl/npm_module_types", "@types/kbn__shared-ux-button-exit-full-screen-mocks": "link:bazel-bin/packages/shared-ux/button/exit_full_screen/mocks/npm_module_types", "@types/kbn__shared-ux-button-exit-full-screen-types": "link:bazel-bin/packages/shared-ux/button/exit_full_screen/types/npm_module_types", diff --git a/packages/BUILD.bazel b/packages/BUILD.bazel index b084fa8617929..19c833f19e150 100644 --- a/packages/BUILD.bazel +++ b/packages/BUILD.bazel @@ -242,6 +242,7 @@ filegroup( "//packages/kbn-utils:build", "//packages/kbn-yarn-lock-validator:build", "//packages/shared-ux/avatar/solution:build", + "//packages/shared-ux/avatar/user_profile/impl:build", "//packages/shared-ux/button_toolbar:build", "//packages/shared-ux/button/exit_full_screen/impl:build", "//packages/shared-ux/button/exit_full_screen/mocks:build", @@ -502,6 +503,7 @@ filegroup( "//packages/kbn-utils:build_types", "//packages/kbn-yarn-lock-validator:build_types", "//packages/shared-ux/avatar/solution:build_types", + "//packages/shared-ux/avatar/user_profile/impl:build_types", "//packages/shared-ux/button_toolbar:build_types", "//packages/shared-ux/button/exit_full_screen/impl:build_types", "//packages/shared-ux/button/exit_full_screen/mocks:build_types", diff --git a/yarn.lock b/yarn.lock index 1c92135bf60bc..80a323aefe03d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3749,6 +3749,10 @@ version "0.0.0" uid "" +"@kbn/shared-ux-avatar-user-profile-components@link:bazel-bin/packages/shared-ux/avatar/user_profile/impl": + version "0.0.0" + uid "" + "@kbn/shared-ux-button-exit-full-screen-mocks@link:bazel-bin/packages/shared-ux/button/exit_full_screen/mocks": version "0.0.0" uid "" @@ -7715,6 +7719,10 @@ version "0.0.0" uid "" +"@types/kbn__shared-ux-avatar-user-profile-components@link:bazel-bin/packages/shared-ux/avatar/user_profile/impl/npm_module_types": + version "0.0.0" + uid "" + "@types/kbn__shared-ux-button-exit-full-screen-mocks@link:bazel-bin/packages/shared-ux/button/exit_full_screen/mocks/npm_module_types": version "0.0.0" uid "" From f584010deb166e09b2de0f27254790d027f4f4c5 Mon Sep 17 00:00:00 2001 From: rshen91 Date: Mon, 22 Aug 2022 15:46:55 -0600 Subject: [PATCH 02/21] update --- .../avatar/user_profile/impl/BUILD.bazel | 144 ++++++++ .../avatar/user_profile/impl/README.md | 3 + .../avatar/user_profile/impl/index.ts | 11 + .../avatar/user_profile/impl/jest.config.js | 13 + .../avatar/user_profile/impl/package.json | 8 + .../avatar/user_profile/impl/src/index.ts | 15 + .../impl/src/user_avatar.test.tsx | 94 ++++++ .../user_profile/impl/src/user_avatar.tsx | 79 +++++ .../user_profile/impl/src/user_profile.ts | 145 ++++++++ .../impl/src/user_profiles_popover.test.tsx | 124 +++++++ .../impl/src/user_profiles_popover.tsx | 48 +++ .../src/user_profiles_selectable.test.tsx | 203 ++++++++++++ .../impl/src/user_profiles_selectable.tsx | 311 ++++++++++++++++++ .../avatar/user_profile/impl/tsconfig.json | 20 ++ 14 files changed, 1218 insertions(+) create mode 100644 packages/shared-ux/avatar/user_profile/impl/BUILD.bazel create mode 100644 packages/shared-ux/avatar/user_profile/impl/README.md create mode 100644 packages/shared-ux/avatar/user_profile/impl/index.ts create mode 100644 packages/shared-ux/avatar/user_profile/impl/jest.config.js create mode 100644 packages/shared-ux/avatar/user_profile/impl/package.json create mode 100644 packages/shared-ux/avatar/user_profile/impl/src/index.ts create mode 100644 packages/shared-ux/avatar/user_profile/impl/src/user_avatar.test.tsx create mode 100644 packages/shared-ux/avatar/user_profile/impl/src/user_avatar.tsx create mode 100644 packages/shared-ux/avatar/user_profile/impl/src/user_profile.ts create mode 100644 packages/shared-ux/avatar/user_profile/impl/src/user_profiles_popover.test.tsx create mode 100644 packages/shared-ux/avatar/user_profile/impl/src/user_profiles_popover.tsx create mode 100644 packages/shared-ux/avatar/user_profile/impl/src/user_profiles_selectable.test.tsx create mode 100644 packages/shared-ux/avatar/user_profile/impl/src/user_profiles_selectable.tsx create mode 100644 packages/shared-ux/avatar/user_profile/impl/tsconfig.json diff --git a/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel b/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel new file mode 100644 index 0000000000000..d13036a3afb93 --- /dev/null +++ b/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel @@ -0,0 +1,144 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "impl" +PKG_REQUIRE_NAME = "@kbn/shared-ux-avatar-user-profile-components" + +SOURCE_FILES = glob( + [ + "**/*.ts", + "**/*.tsx", + ], + exclude = [ + "**/*.config.js", + "**/*.mock.*", + "**/*.test.*", + "**/*.stories.*", + "**/__snapshots__", + "**/integration_tests", + "**/mocks", + "**/scripts", + "**/storybook", + "**/test_fixtures", + "**/test_helpers", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +# In this array place runtime dependencies, including other packages and NPM packages +# which must be available for this code to run. +# +# To reference other packages use: +# "//repo/relative/path/to/package" +# eg. "//packages/kbn-utils" +# +# To reference a NPM package use: +# "@npm//name-of-package" +# eg. "@npm//lodash" +RUNTIME_DEPS = [ + "@npm//react", + "@npm//@elastic/eui", + "//packages/kbn-i18n-react", + "//packages/kbn-i18n", + "//packages/kbn-shared-ux-utility", +] + +# In this array place dependencies necessary to build the types, which will include the +# :npm_module_types target of other packages and packages from NPM, including @types/* +# packages. +# +# To reference the types for another package use: +# "//repo/relative/path/to/package:npm_module_types" +# eg. "//packages/kbn-utils:npm_module_types" +# +# References to NPM packages work the same as RUNTIME_DEPS +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "@npm//@types/react", + "@npm//@elastic/eui", + "//packages/kbn-i18n-react:npm_module_types", + "//packages/kbn-i18n:npm_module_types", + "//packages/kbn-shared-ux-utility:npm_module_types", + +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + declaration_map = True, + emit_declaration_only = True, + out_dir = "target_types", + root_dir = ".", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/shared-ux/avatar/user_profile/impl/README.md b/packages/shared-ux/avatar/user_profile/impl/README.md new file mode 100644 index 0000000000000..437586b2b3346 --- /dev/null +++ b/packages/shared-ux/avatar/user_profile/impl/README.md @@ -0,0 +1,3 @@ +# @kbn/shared-ux-avatar-user-profile-components + +Empty package generated by @kbn/generate diff --git a/packages/shared-ux/avatar/user_profile/impl/index.ts b/packages/shared-ux/avatar/user_profile/impl/index.ts new file mode 100644 index 0000000000000..b6e7485e36ab2 --- /dev/null +++ b/packages/shared-ux/avatar/user_profile/impl/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export function foo() { + return 'hello world'; +} diff --git a/packages/shared-ux/avatar/user_profile/impl/jest.config.js b/packages/shared-ux/avatar/user_profile/impl/jest.config.js new file mode 100644 index 0000000000000..111a2a8105057 --- /dev/null +++ b/packages/shared-ux/avatar/user_profile/impl/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../../..', + roots: ['/packages/shared-ux/avatar/user_profile/impl'], +}; diff --git a/packages/shared-ux/avatar/user_profile/impl/package.json b/packages/shared-ux/avatar/user_profile/impl/package.json new file mode 100644 index 0000000000000..4621591d690cb --- /dev/null +++ b/packages/shared-ux/avatar/user_profile/impl/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/shared-ux-avatar-user-profile-components", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "browser": "./target_web/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/packages/shared-ux/avatar/user_profile/impl/src/index.ts b/packages/shared-ux/avatar/user_profile/impl/src/index.ts new file mode 100644 index 0000000000000..e36215e36896a --- /dev/null +++ b/packages/shared-ux/avatar/user_profile/impl/src/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export type { UserAvatarProps, UserProfileWithAvatar } from './user_avatar'; +export type { UserProfilesSelectableProps } from './user_profiles_selectable'; +export type { UserProfilesPopoverProps } from './user_profiles_popover'; +export { UserAvatar } from './user_avatar'; +export { UserProfilesSelectable } from './user_profiles_selectable'; +export { UserProfilesPopover } from './user_profiles_popover'; +export type { UserProfile, UserProfileUserInfo, UserProfileAvatarData } from './user_profile'; diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_avatar.test.tsx b/packages/shared-ux/avatar/user_profile/impl/src/user_avatar.test.tsx new file mode 100644 index 0000000000000..9c654d25f70fe --- /dev/null +++ b/packages/shared-ux/avatar/user_profile/impl/src/user_avatar.test.tsx @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { shallow } from 'enzyme'; +import React from 'react'; + +import { UserAvatar } from './user_avatar'; + +describe('UserAvatar', () => { + it('should render `EuiAvatar` correctly with image avatar', () => { + const wrapper = shallow( + + ); + expect(wrapper).toMatchInlineSnapshot(` + + `); + }); + + it('should render `EuiAvatar` correctly with initials avatar', () => { + const wrapper = shallow( + + ); + expect(wrapper).toMatchInlineSnapshot(` + + `); + }); + + it('should render `EuiAvatar` correctly without avatar data', () => { + const wrapper = shallow( + + ); + expect(wrapper).toMatchInlineSnapshot(` + + `); + }); + + it('should render `EuiAvatar` correctly without user data', () => { + const wrapper = shallow(); + expect(wrapper).toMatchInlineSnapshot(` + + `); + }); +}); diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_avatar.tsx b/packages/shared-ux/avatar/user_profile/impl/src/user_avatar.tsx new file mode 100644 index 0000000000000..2413694317c27 --- /dev/null +++ b/packages/shared-ux/avatar/user_profile/impl/src/user_avatar.tsx @@ -0,0 +1,79 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { EuiAvatarProps } from '@elastic/eui'; +import { EuiAvatar, useEuiTheme } from '@elastic/eui'; +import type { FunctionComponent } from 'react'; +import React from 'react'; + +import type { UserProfile, UserProfileUserInfo, UserProfileAvatarData } from './user_profile'; +import { + getUserAvatarColor, + getUserAvatarInitials, + getUserDisplayName, + USER_AVATAR_MAX_INITIALS, +} from './user_profile'; + +/** + * Convenience type for a {@link UserProfile} with avatar data + */ +export type UserProfileWithAvatar = UserProfile<{ avatar?: UserProfileAvatarData }>; + +/** + * Props of {@link UserAvatar} component + */ +export interface UserAvatarProps + extends Omit< + EuiAvatarProps, + | 'initials' + | 'initialsLength' + | 'imageUrl' + | 'iconType' + | 'iconSize' + | 'iconColor' + | 'name' + | 'color' + | 'type' + > { + /** + * User to be rendered + */ + user?: UserProfileUserInfo; + + /** + * Avatar data of user to be rendered + */ + avatar?: UserProfileAvatarData; +} + +/** + * Renders an avatar given a user profile + */ +export const UserAvatar: FunctionComponent = ({ user, avatar, ...rest }) => { + const { euiTheme } = useEuiTheme(); + + if (!user) { + return ; + } + + const displayName = getUserDisplayName(user); + + if (avatar?.imageUrl) { + return ; + } + + return ( + + ); +}; diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_profile.ts b/packages/shared-ux/avatar/user_profile/impl/src/user_profile.ts new file mode 100644 index 0000000000000..eb6f67f1d25ca --- /dev/null +++ b/packages/shared-ux/avatar/user_profile/impl/src/user_profile.ts @@ -0,0 +1,145 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { VISUALIZATION_COLORS } from '@elastic/eui'; + +/** + * IMPORTANT: + * + * The types in this file have been imported from + * `x-pack/plugins/security/common/model/user_profile.ts` + * + * When making changes please ensure to keep both files in sync. + */ + +/** + * Describes basic properties stored in user profile. + */ +export interface UserProfile { + /** + * Unique ID for of the user profile. + */ + uid: string; + + /** + * Indicates whether user profile is enabled or not. + */ + enabled: boolean; + + /** + * Information about the user that owns profile. + */ + user: UserProfileUserInfo; + + /** + * User specific data associated with the profile. + */ + data: Partial; +} + +/** + * Basic user information returned in user profile. + */ +export interface UserProfileUserInfo { + /** + * Username of the user. + */ + username: string; + /** + * Optional email of the user. + */ + email?: string; + /** + * Optional full name of the user. + */ + full_name?: string; + /** + * Optional display name of the user. + */ + display_name?: string; +} + +/** + * Placeholder for data stored in user profile. + */ +export type UserProfileData = Record; + +/** + * Avatar stored in user profile. + */ +export interface UserProfileAvatarData { + /** + * Optional initials (two letters) of the user to use as avatar if avatar picture isn't specified. + */ + initials?: string; + /** + * Background color of the avatar when initials are used. + */ + color?: string; + /** + * Base64 data URL for the user avatar image. + */ + imageUrl?: string; +} + +export const USER_AVATAR_FALLBACK_CODE_POINT = 97; // code point for lowercase "a" +export const USER_AVATAR_MAX_INITIALS = 2; + +/** + * Determines the color for the provided user profile. + * If a color is present on the user profile itself, then that is used. + * Otherwise, a color is provided from EUI's Visualization Colors based on the display name. + * + * @param {UserProfileUserInfo} user User info + * @param {UserProfileAvatarData} avatar User avatar + */ +export function getUserAvatarColor( + user: Pick, + avatar?: UserProfileAvatarData +) { + if (avatar && avatar.color) { + return avatar.color; + } + + const firstCodePoint = getUserDisplayName(user).codePointAt(0) || USER_AVATAR_FALLBACK_CODE_POINT; + + return VISUALIZATION_COLORS[firstCodePoint % VISUALIZATION_COLORS.length]; +} + +/** + * Determines the initials for the provided user profile. + * If initials are present on the user profile itself, then that is used. + * Otherwise, the initials are calculated based off the words in the display name, with a max length of 2 characters. + * + * @param {UserProfileUserInfo} user User info + * @param {UserProfileAvatarData} avatar User avatar + */ +export function getUserAvatarInitials( + user: Pick, + avatar?: UserProfileAvatarData +) { + if (avatar && avatar.initials) { + return avatar.initials; + } + + const words = getUserDisplayName(user).split(' '); + const numInitials = Math.min(USER_AVATAR_MAX_INITIALS, words.length); + + words.splice(numInitials, words.length); + + return words.map((word) => word.substring(0, 1)).join(''); +} + +/** + * Determines the display name for the provided user profile. + * + * @param {UserProfileUserInfo} user User info + */ +export function getUserDisplayName(user: Pick) { + return user.full_name || user.username; +} diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_popover.test.tsx b/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_popover.test.tsx new file mode 100644 index 0000000000000..13604fcfeb36f --- /dev/null +++ b/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_popover.test.tsx @@ -0,0 +1,124 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { shallow } from 'enzyme'; +import React from 'react'; + +import { UserProfilesPopover } from './user_profiles_popover'; + +const userProfiles = [ + { + uid: 'u_BOulL4QMPSyV9jg5lQI2JmCkUnokHTazBnet3xVHNv0_0', + enabled: true, + data: {}, + user: { + username: 'delighted_nightingale', + email: 'delighted_nightingale@profiles.elastic.co', + full_name: 'Delighted Nightingale', + }, + }, + { + uid: 'u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0', + enabled: true, + data: {}, + user: { + username: 'damaged_raccoon', + email: 'damaged_raccoon@profiles.elastic.co', + full_name: 'Damaged Raccoon', + }, + }, + { + uid: 'u_A_tM4n0wPkdiQ9smmd8o0Hr_h61XQfu8aRPh9GMoRoc_0', + enabled: true, + data: {}, + user: { + username: 'physical_dinosaur', + email: 'physical_dinosaur@profiles.elastic.co', + full_name: 'Physical Dinosaur', + }, + }, + { + uid: 'u_9xDEQqUqoYCnFnPPLq5mIRHKL8gBTo_NiKgOnd5gGk0_0', + enabled: true, + data: {}, + user: { + username: 'wet_dingo', + email: 'wet_dingo@profiles.elastic.co', + full_name: 'Wet Dingo', + }, + }, +]; + +describe('UserProfilesPopover', () => { + it('should render `EuiPopover` and `UserProfilesSelectable` correctly', () => { + const [firstOption, secondOption] = userProfiles; + const wrapper = shallow( + Toggle} + closePopover={jest.fn()} + selectableProps={{ + selectedOptions: [firstOption], + defaultOptions: [secondOption], + }} + /> + ); + expect(wrapper).toMatchInlineSnapshot(` + + Toggle + + } + closePopover={[MockFunction]} + display="inline-block" + hasArrow={true} + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > + + + + + `); + }); +}); diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_popover.tsx b/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_popover.tsx new file mode 100644 index 0000000000000..9fc553d9be689 --- /dev/null +++ b/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_popover.tsx @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { EuiPopoverProps, EuiContextMenuPanelProps } from '@elastic/eui'; +import type { FunctionComponent } from 'react'; +import React from 'react'; +import { EuiPopover, EuiContextMenuPanel } from '@elastic/eui'; + +import { UserProfilesSelectable, UserProfilesSelectableProps } from './user_profiles_selectable'; + +/** + * Props of {@link UserProfilesPopover} component + */ +export interface UserProfilesPopoverProps extends EuiPopoverProps { + /** + * Title of the popover + * @see EuiContextMenuPanelProps + */ + title?: EuiContextMenuPanelProps['title']; + + /** + * Props forwarded to selectable component + * @see UserProfilesSelectableProps + */ + selectableProps: UserProfilesSelectableProps; +} + +/** + * Renders a selectable component inside a popover given a list of user profiles + */ +export const UserProfilesPopover: FunctionComponent = ({ + title, + selectableProps, + ...popoverProps +}) => { + return ( + + + + + + ); +}; diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_selectable.test.tsx b/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_selectable.test.tsx new file mode 100644 index 0000000000000..bdb0be25ce9cf --- /dev/null +++ b/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_selectable.test.tsx @@ -0,0 +1,203 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { mount } from 'enzyme'; +import React from 'react'; + +import { UserProfilesSelectable } from './user_profiles_selectable'; + +const userProfiles = [ + { + uid: 'u_BOulL4QMPSyV9jg5lQI2JmCkUnokHTazBnet3xVHNv0_0', + enabled: true, + data: {}, + user: { + username: 'delighted_nightingale', + email: 'delighted_nightingale@profiles.elastic.co', + full_name: 'Delighted Nightingale', + }, + }, + { + uid: 'u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0', + enabled: true, + data: {}, + user: { + username: 'damaged_raccoon', + email: 'damaged_raccoon@profiles.elastic.co', + full_name: 'Damaged Raccoon', + }, + }, + { + uid: 'u_A_tM4n0wPkdiQ9smmd8o0Hr_h61XQfu8aRPh9GMoRoc_0', + enabled: true, + data: {}, + user: { + username: 'physical_dinosaur', + email: 'physical_dinosaur@profiles.elastic.co', + full_name: 'Physical Dinosaur', + }, + }, + { + uid: 'u_9xDEQqUqoYCnFnPPLq5mIRHKL8gBTo_NiKgOnd5gGk0_0', + enabled: true, + data: {}, + user: { + username: 'wet_dingo', + email: 'wet_dingo@profiles.elastic.co', + full_name: 'Wet Dingo', + }, + }, +]; + +describe('UserProfilesSelectable', () => { + it('should render `selectedOptions` before `defaultOptions` separated by a group label', () => { + const [firstOption, secondOption, thirdOption] = userProfiles; + const wrapper = mount( + + ); + expect(wrapper.find('EuiSelectable').prop('options')).toEqual([ + expect.objectContaining({ + key: firstOption.uid, + checked: 'on', + }), + expect.objectContaining({ + isGroupLabel: true, + label: 'Suggested', + }), + expect.objectContaining({ + key: secondOption.uid, + checked: undefined, + }), + expect.objectContaining({ + key: thirdOption.uid, + checked: undefined, + }), + ]); + }); + + it('should hide `selectedOptions` and `defaultOptions` when `options` has been provided', () => { + const [firstOption, secondOption, thirdOption] = userProfiles; + const wrapper = mount( + + ); + expect(wrapper.find('EuiSelectable').prop('options')).toEqual([ + expect.objectContaining({ + key: thirdOption.uid, + checked: undefined, + }), + ]); + }); + + it('should hide `selectedOptions` and `defaultOptions` when `options` gets updated', () => { + const [firstOption, secondOption, thirdOption] = userProfiles; + const wrapper = mount( + + ); + expect(wrapper.find('EuiSelectable').prop('options')).toEqual([ + expect.objectContaining({ + key: firstOption.uid, + checked: 'on', + }), + expect.objectContaining({ + isGroupLabel: true, + label: 'Suggested', + }), + expect.objectContaining({ + key: secondOption.uid, + checked: undefined, + }), + ]); + + wrapper.setProps({ options: [thirdOption] }).update(); + + expect(wrapper.find('EuiSelectable').prop('options')).toEqual([ + expect.objectContaining({ + key: thirdOption.uid, + checked: undefined, + }), + ]); + }); + + it('should render `options` with correct checked status', () => { + const [firstOption, secondOption] = userProfiles; + const wrapper = mount( + + ); + expect(wrapper.find('EuiSelectable').prop('options')).toEqual([ + expect.objectContaining({ + key: firstOption.uid, + checked: 'on', + }), + expect.objectContaining({ + key: secondOption.uid, + checked: undefined, + }), + ]); + }); + + it('should trigger `onChange` callback when selection changes', () => { + const onChange = jest.fn(); + const [firstOption, secondOption] = userProfiles; + const wrapper = mount( + + ); + wrapper.find('EuiSelectableListItem').last().simulate('click'); + expect(onChange).toHaveBeenCalledWith( + expect.arrayContaining([ + expect.objectContaining({ + uid: firstOption.uid, + }), + expect.objectContaining({ + uid: secondOption.uid, + }), + ]) + ); + }); + + it('should continue to display `selectedOptions` when getting unchecked', () => { + const onChange = jest.fn(); + const [firstOption] = userProfiles; + const wrapper = mount( + + ); + expect(wrapper.find('EuiSelectable').prop('options')).toEqual([ + expect.objectContaining({ + key: firstOption.uid, + checked: 'on', + }), + ]); + wrapper.setProps({ selectedOptions: [] }).update(); + expect(wrapper.find('EuiSelectable').prop('options')).toEqual([ + expect.objectContaining({ + key: firstOption.uid, + checked: undefined, + }), + ]); + }); + + it('should trigger `onSearchChange` callback when search term changes', () => { + const onSearchChange = jest.fn(); + const wrapper = mount(); + wrapper.find('input[type="search"]').simulate('change', { target: { value: 'search' } }); + expect(onSearchChange).toHaveBeenCalledWith('search', []); + }); +}); diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_selectable.tsx b/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_selectable.tsx new file mode 100644 index 0000000000000..14a44f66650aa --- /dev/null +++ b/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_selectable.tsx @@ -0,0 +1,311 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { EuiSelectableOption, EuiSelectableProps } from '@elastic/eui'; +import { + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiPanel, + EuiSelectable, + EuiSpacer, + EuiText, + EuiTextColor, +} from '@elastic/eui'; +import type { FunctionComponent, ReactNode } from 'react'; +import React, { useEffect, useState } from 'react'; + +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; + +import { getUserDisplayName } from './user_profile'; +import type { UserProfileWithAvatar } from './user_avatar'; +import { UserAvatar } from './user_avatar'; + +/** + * Props of {@link UserProfilesSelectable} component + */ +export interface UserProfilesSelectableProps + extends Pick< + EuiSelectableProps, + | 'height' + | 'singleSelection' + | 'loadingMessage' + | 'noMatchesMessage' + | 'emptyMessage' + | 'errorMessage' + > { + /** + * List of users to be rendered as suggestions. + */ + defaultOptions?: UserProfileWithAvatar[]; + + /** + * List of selected users. + */ + selectedOptions?: UserProfileWithAvatar[]; + + /** + * List of users from search results. Should be updated based on the search term provided by `onSearchChange` callback. + */ + options?: UserProfileWithAvatar[]; + + /** + * Passes back the list of selected users. + * @param options List of selected users + */ + onChange?(options: UserProfileWithAvatar[]): void; + + /** + * Passes back the search term. + * @param searchTerm Search term + */ + onSearchChange?(searchTerm: string): void; + + /** + * Loading indicator for asynchronous search operations. + */ + isLoading?: boolean; + + /** + * Placeholder text for search box. + */ + searchPlaceholder?: string; + + /** + * Returns text for selected status. + * @param selectedCount Number of selected users + */ + selectedStatusMessage?(selectedCount: number): ReactNode; + + /** + * Text for label of clear button. + */ + clearButtonLabel?: ReactNode; +} + +/** + * Renders a selectable component given a list of user profiles + */ +export const UserProfilesSelectable: FunctionComponent = ({ + selectedOptions, + defaultOptions, + options, + onChange, + onSearchChange, + isLoading = false, + singleSelection = false, + height, + loadingMessage, + noMatchesMessage, + emptyMessage, + errorMessage, + searchPlaceholder, + selectedStatusMessage, + clearButtonLabel, +}) => { + const [displayedOptions, setDisplayedOptions] = useState([]); + + // Resets all displayed options + const resetDisplayedOptions = () => { + if (options) { + setDisplayedOptions(options.map(toSelectableOption)); + return; + } + + setDisplayedOptions([]); + updateDisplayedOptions(); + }; + + const ensureSeparator = (values: SelectableOption[]) => { + let index = values.findIndex((option) => option.isGroupLabel); + if (index === -1) { + const length = values.push({ + label: i18n.translate('userProfileComponents.userProfilesSelectable.suggestedLabel', { + defaultMessage: 'Suggested', + }), + isGroupLabel: true, + } as SelectableOption); + index = length - 1; + } + return index; + }; + + // Updates displayed options without removing or resorting exiting options + const updateDisplayedOptions = () => { + if (options) { + return; + } + + setDisplayedOptions((values) => { + // Copy all displayed options + const nextOptions: SelectableOption[] = [...values]; + + // Get any newly added selected options + const selectedOptionsToAdd: SelectableOption[] = selectedOptions + ? selectedOptions + .filter((profile) => !nextOptions.find((option) => option.key === profile.uid)) + .map(toSelectableOption) + : []; + + // Get any newly added default options + const defaultOptionsToAdd: SelectableOption[] = defaultOptions + ? defaultOptions + .filter( + (profile) => + !nextOptions.find((option) => option.key === profile.uid) && + !selectedOptionsToAdd.find((option) => option.key === profile.uid) + ) + .map(toSelectableOption) + : []; + + // Merge in any new options and add group separator if necessary + if (defaultOptionsToAdd.length) { + const separatorIndex = ensureSeparator(nextOptions); + nextOptions.splice(separatorIndex, 0, ...selectedOptionsToAdd); + nextOptions.push(...defaultOptionsToAdd); + } else { + nextOptions.push(...selectedOptionsToAdd); + } + + return nextOptions; + }); + }; + + // Marks displayed options as checked or unchecked depending on `props.selectedOptions` + const updateCheckedStatus = () => { + setDisplayedOptions((values) => + values.map((option) => { + if (selectedOptions) { + const match = selectedOptions.find((p) => p.uid === option.key); + return { ...option, checked: match ? 'on' : undefined }; + } + return { ...option, checked: undefined }; + }) + ); + }; + + useEffect(resetDisplayedOptions, [options]); // eslint-disable-line react-hooks/exhaustive-deps + useEffect(updateDisplayedOptions, [defaultOptions, selectedOptions]); // eslint-disable-line react-hooks/exhaustive-deps + useEffect(updateCheckedStatus, [options, defaultOptions, selectedOptions]); + + const selectedCount = selectedOptions ? selectedOptions.length : 0; + + return ( + >) => { + if (!onChange) { + return; + } + + // Take all selected options from `nextOptions` unless already in `props.selectedOptions` + const values: UserProfileWithAvatar[] = nextOptions + .filter((option) => { + if (option.isGroupLabel || option.checked !== 'on') { + return false; + } + if (selectedOptions && selectedOptions.find((p) => p.uid === option.key)) { + return false; + } + return true; + }) + .map((option) => option.data); + + // Add all options from `props.selectedOptions` unless they have been deselected in `nextOptions` + if (selectedOptions && !singleSelection) { + selectedOptions.forEach((profile) => { + const match = nextOptions.find((o) => o.key === profile.uid); + if (!match || match.checked === 'on') { + values.push(profile); + } + }); + } + + onChange(values); + }} + style={{ maxHeight: height }} + singleSelection={singleSelection} + searchable + searchProps={{ + placeholder: + searchPlaceholder ?? + i18n.translate('userProfileComponents.userProfilesSelectable.searchPlaceholder', { + defaultMessage: 'Search', + }), + onChange: onSearchChange, + isLoading, + isClearable: !isLoading, + }} + isPreFiltered + listProps={{ onFocusBadge: false }} + loadingMessage={loadingMessage} + noMatchesMessage={noMatchesMessage} + emptyMessage={emptyMessage} + errorMessage={errorMessage} + > + {(list, search) => ( + <> + + {search} + + + + + {selectedStatusMessage ? ( + selectedStatusMessage(selectedCount) + ) : ( + + )} + + + + {selectedCount ? ( + onChange?.([])} + style={{ height: '1rem' }} + > + {clearButtonLabel ?? ( + + )} + + ) : undefined} + + + + + {list} + + )} + + ); +}; + +type SelectableOption = EuiSelectableOption; + +function toSelectableOption(userProfile: UserProfileWithAvatar): SelectableOption { + // @ts-ignore: `isGroupLabel` is not required here but TS complains + return { + key: userProfile.uid, + prepend: , + label: getUserDisplayName(userProfile.user), + append: {userProfile.user.email}, + data: userProfile, + }; +} diff --git a/packages/shared-ux/avatar/user_profile/impl/tsconfig.json b/packages/shared-ux/avatar/user_profile/impl/tsconfig.json new file mode 100644 index 0000000000000..dc96ec41f9035 --- /dev/null +++ b/packages/shared-ux/avatar/user_profile/impl/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "rootDir": "src", + "stripInternal": false, + "types": [ + "jest", + "node", + "react" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ] +} From 051c6202aa936e1ac03950ac1203a083095e23bc Mon Sep 17 00:00:00 2001 From: rshen91 Date: Mon, 22 Aug 2022 16:10:01 -0600 Subject: [PATCH 03/21] fix namespace issue --- .../impl/src/user_profiles_selectable.tsx | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_selectable.tsx b/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_selectable.tsx index 14a44f66650aa..4d8ff7f5ca9af 100644 --- a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_selectable.tsx +++ b/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_selectable.tsx @@ -127,9 +127,12 @@ export const UserProfilesSelectable: FunctionComponent option.isGroupLabel); if (index === -1) { const length = values.push({ - label: i18n.translate('userProfileComponents.userProfilesSelectable.suggestedLabel', { - defaultMessage: 'Suggested', - }), + label: i18n.translate( + 'sharedUXPackages.userProfileComponents.userProfilesSelectable.suggestedLabel', + { + defaultMessage: 'Suggested', + } + ), isGroupLabel: true, } as SelectableOption); index = length - 1; @@ -237,9 +240,12 @@ export const UserProfilesSelectable: FunctionComponent @@ -280,7 +286,7 @@ export const UserProfilesSelectable: FunctionComponent {clearButtonLabel ?? ( )} From dac121ecb740494866577ddbed2811f5591ba5da Mon Sep 17 00:00:00 2001 From: rshen91 Date: Tue, 23 Aug 2022 07:29:10 -0600 Subject: [PATCH 04/21] tsconfig --- packages/shared-ux/avatar/user_profile/impl/tsconfig.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/shared-ux/avatar/user_profile/impl/tsconfig.json b/packages/shared-ux/avatar/user_profile/impl/tsconfig.json index dc96ec41f9035..74250e305e41f 100644 --- a/packages/shared-ux/avatar/user_profile/impl/tsconfig.json +++ b/packages/shared-ux/avatar/user_profile/impl/tsconfig.json @@ -14,7 +14,6 @@ ] }, "include": [ - "**/*.ts", - "**/*.tsx", + "src/**/*" ] } From e1ce125c7460befa0ff1a796f82512cf46f7be33 Mon Sep 17 00:00:00 2001 From: rshen91 Date: Tue, 23 Aug 2022 08:42:39 -0600 Subject: [PATCH 05/21] fix build --- .../shared-ux/avatar/user_profile/impl/BUILD.bazel | 12 ++---------- .../user_profile/impl/{README.md => README.mdx} | 0 packages/shared-ux/avatar/user_profile/impl/index.ts | 11 ----------- 3 files changed, 2 insertions(+), 21 deletions(-) rename packages/shared-ux/avatar/user_profile/impl/{README.md => README.mdx} (100%) delete mode 100644 packages/shared-ux/avatar/user_profile/impl/index.ts diff --git a/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel b/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel index d13036a3afb93..dce2a9be7fe09 100644 --- a/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel +++ b/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel @@ -9,19 +9,11 @@ SOURCE_FILES = glob( [ "**/*.ts", "**/*.tsx", + "**/*.mdx", ], exclude = [ - "**/*.config.js", - "**/*.mock.*", "**/*.test.*", "**/*.stories.*", - "**/__snapshots__", - "**/integration_tests", - "**/mocks", - "**/scripts", - "**/storybook", - "**/test_fixtures", - "**/test_helpers", ], ) @@ -105,7 +97,7 @@ ts_project( declaration_map = True, emit_declaration_only = True, out_dir = "target_types", - root_dir = ".", + root_dir = "src", tsconfig = ":tsconfig", ) diff --git a/packages/shared-ux/avatar/user_profile/impl/README.md b/packages/shared-ux/avatar/user_profile/impl/README.mdx similarity index 100% rename from packages/shared-ux/avatar/user_profile/impl/README.md rename to packages/shared-ux/avatar/user_profile/impl/README.mdx diff --git a/packages/shared-ux/avatar/user_profile/impl/index.ts b/packages/shared-ux/avatar/user_profile/impl/index.ts deleted file mode 100644 index b6e7485e36ab2..0000000000000 --- a/packages/shared-ux/avatar/user_profile/impl/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export function foo() { - return 'hello world'; -} From d8dc044c853a679da88ed462739a1b93ec10878c Mon Sep 17 00:00:00 2001 From: rshen91 Date: Wed, 31 Aug 2022 09:03:24 -0600 Subject: [PATCH 06/21] add to story --- .../avatar/user_profile/impl/BUILD.bazel | 2 +- .../user_profile/impl/src/user_avatar.tsx | 2 +- .../impl/src/user_profiles.stories.tsx | 40 +++++++++++++++++++ .../avatar/user_profile/impl/tsconfig.json | 3 +- 4 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx diff --git a/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel b/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel index dce2a9be7fe09..5958f71922d4f 100644 --- a/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel +++ b/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel @@ -63,7 +63,7 @@ TYPES_DEPS = [ "//packages/kbn-i18n-react:npm_module_types", "//packages/kbn-i18n:npm_module_types", "//packages/kbn-shared-ux-utility:npm_module_types", - + "//packages/kbn-ambient-ui-types", ] jsts_transpiler( diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_avatar.tsx b/packages/shared-ux/avatar/user_profile/impl/src/user_avatar.tsx index 2413694317c27..7ff6cda7689f1 100644 --- a/packages/shared-ux/avatar/user_profile/impl/src/user_avatar.tsx +++ b/packages/shared-ux/avatar/user_profile/impl/src/user_avatar.tsx @@ -64,7 +64,7 @@ export const UserAvatar: FunctionComponent = ({ user, avatar, . const displayName = getUserDisplayName(user); if (avatar?.imageUrl) { - return ; + return ; } return ( diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx b/packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx new file mode 100644 index 0000000000000..93f941e03c308 --- /dev/null +++ b/packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { UserAvatar, UserAvatarProps } from './user_avatar'; +import mdx from '../README.mdx' + +export default { + title: 'Avatar/User Profile', + description: '', + parameters: { + docs: { + page: mdx, + }, + }, +}; + + + +export const userAvatar = ({ user, ...rest }: UserAvatarProps) => { + return ; +}; + + + +userAvatar.argTypes = { + username: { + control: 'text', + defaultValue: 'Peggy', + }, +}; + +console.log(userAvatar.argTypes.username) + + diff --git a/packages/shared-ux/avatar/user_profile/impl/tsconfig.json b/packages/shared-ux/avatar/user_profile/impl/tsconfig.json index 74250e305e41f..cb0254e24fee7 100644 --- a/packages/shared-ux/avatar/user_profile/impl/tsconfig.json +++ b/packages/shared-ux/avatar/user_profile/impl/tsconfig.json @@ -10,7 +10,8 @@ "types": [ "jest", "node", - "react" + "react", + "@kbn/ambient-ui-types" ] }, "include": [ From 7227b6952cbab9db7a213ad1ba75908b78224200 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 31 Aug 2022 15:29:49 +0000 Subject: [PATCH 07/21] [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' --- .../avatar/user_profile/impl/src/user_avatar.tsx | 2 +- .../user_profile/impl/src/user_profiles.stories.tsx | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_avatar.tsx b/packages/shared-ux/avatar/user_profile/impl/src/user_avatar.tsx index 7ff6cda7689f1..2413694317c27 100644 --- a/packages/shared-ux/avatar/user_profile/impl/src/user_avatar.tsx +++ b/packages/shared-ux/avatar/user_profile/impl/src/user_avatar.tsx @@ -64,7 +64,7 @@ export const UserAvatar: FunctionComponent = ({ user, avatar, . const displayName = getUserDisplayName(user); if (avatar?.imageUrl) { - return ; + return ; } return ( diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx b/packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx index 93f941e03c308..b4eb969bb9465 100644 --- a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx +++ b/packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { UserAvatar, UserAvatarProps } from './user_avatar'; -import mdx from '../README.mdx' +import mdx from '../README.mdx'; export default { title: 'Avatar/User Profile', @@ -20,14 +20,10 @@ export default { }, }; - - export const userAvatar = ({ user, ...rest }: UserAvatarProps) => { return ; }; - - userAvatar.argTypes = { username: { control: 'text', @@ -35,6 +31,4 @@ userAvatar.argTypes = { }, }; -console.log(userAvatar.argTypes.username) - - +console.log(userAvatar.argTypes.username); From 68c0521d77dac8207abd2f5538e6590c2eb0e736 Mon Sep 17 00:00:00 2001 From: rshen91 Date: Wed, 31 Aug 2022 11:34:48 -0600 Subject: [PATCH 08/21] story --- .../impl/src/user_profiles.stories.tsx | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx b/packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx index 93f941e03c308..81167287d7063 100644 --- a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx +++ b/packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx @@ -8,33 +8,32 @@ import React from 'react'; import { UserAvatar, UserAvatarProps } from './user_avatar'; -import mdx from '../README.mdx' +// import mdx from '../README.mdx' export default { title: 'Avatar/User Profile', description: '', parameters: { - docs: { - page: mdx, - }, + // docs: { + // page: mdx, + // }, }, }; +type userAvatarNameParams = Pick -export const userAvatar = ({ user, ...rest }: UserAvatarProps) => { - return ; +export const userAvatar = (params: userAvatarNameParams) => { + return ; }; - userAvatar.argTypes = { - username: { + user: { control: 'text', defaultValue: 'Peggy', }, }; -console.log(userAvatar.argTypes.username) From bdb18759673eba765df72d694f63ab4684f4607f Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 31 Aug 2022 18:02:06 +0000 Subject: [PATCH 09/21] [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' --- .../impl/src/user_profiles.stories.tsx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx b/packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx index 81167287d7063..0566204e2b63f 100644 --- a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx +++ b/packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx @@ -20,20 +20,22 @@ export default { }, }; -type userAvatarNameParams = Pick - +type userAvatarNameParams = Pick; export const userAvatar = (params: userAvatarNameParams) => { - return ; + return ( + + ); }; - userAvatar.argTypes = { user: { control: 'text', defaultValue: 'Peggy', }, }; - - - From 706bba1485e54d758ddd3ccbc88d95c5b8dc3583 Mon Sep 17 00:00:00 2001 From: rshen91 Date: Wed, 31 Aug 2022 15:08:19 -0600 Subject: [PATCH 10/21] remove srcdirectory --- .../shared-ux/avatar/user_profile/impl/BUILD.bazel | 11 ++++++----- .../avatar/user_profile/impl/{src => }/index.ts | 0 .../shared-ux/avatar/user_profile/impl/tsconfig.json | 4 ++-- .../user_profile/impl/{src => }/user_avatar.test.tsx | 0 .../user_profile/impl/{src => }/user_avatar.tsx | 0 .../user_profile/impl/{src => }/user_profile.ts | 0 .../impl/{src => }/user_profiles.stories.tsx | 12 ++++++------ .../impl/{src => }/user_profiles_popover.test.tsx | 0 .../impl/{src => }/user_profiles_popover.tsx | 0 .../impl/{src => }/user_profiles_selectable.test.tsx | 0 .../impl/{src => }/user_profiles_selectable.tsx | 0 11 files changed, 14 insertions(+), 13 deletions(-) rename packages/shared-ux/avatar/user_profile/impl/{src => }/index.ts (100%) rename packages/shared-ux/avatar/user_profile/impl/{src => }/user_avatar.test.tsx (100%) rename packages/shared-ux/avatar/user_profile/impl/{src => }/user_avatar.tsx (100%) rename packages/shared-ux/avatar/user_profile/impl/{src => }/user_profile.ts (100%) rename packages/shared-ux/avatar/user_profile/impl/{src => }/user_profiles.stories.tsx (79%) rename packages/shared-ux/avatar/user_profile/impl/{src => }/user_profiles_popover.test.tsx (100%) rename packages/shared-ux/avatar/user_profile/impl/{src => }/user_profiles_popover.tsx (100%) rename packages/shared-ux/avatar/user_profile/impl/{src => }/user_profiles_selectable.test.tsx (100%) rename packages/shared-ux/avatar/user_profile/impl/{src => }/user_profiles_selectable.tsx (100%) diff --git a/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel b/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel index 5958f71922d4f..0f8a7f71df6b1 100644 --- a/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel +++ b/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel @@ -19,10 +19,10 @@ SOURCE_FILES = glob( SRCS = SOURCE_FILES -filegroup( - name = "srcs", - srcs = SRCS, -) +# filegroup( +# name = "srcs", +# srcs = SRCS, +# ) NPM_MODULE_EXTRA_FILES = [ "package.json", @@ -44,6 +44,7 @@ RUNTIME_DEPS = [ "//packages/kbn-i18n-react", "//packages/kbn-i18n", "//packages/kbn-shared-ux-utility", + "//packages/kbn-ambient-ui-types", ] # In this array place dependencies necessary to build the types, which will include the @@ -97,7 +98,7 @@ ts_project( declaration_map = True, emit_declaration_only = True, out_dir = "target_types", - root_dir = "src", + root_dir = ".", tsconfig = ":tsconfig", ) diff --git a/packages/shared-ux/avatar/user_profile/impl/src/index.ts b/packages/shared-ux/avatar/user_profile/impl/index.ts similarity index 100% rename from packages/shared-ux/avatar/user_profile/impl/src/index.ts rename to packages/shared-ux/avatar/user_profile/impl/index.ts diff --git a/packages/shared-ux/avatar/user_profile/impl/tsconfig.json b/packages/shared-ux/avatar/user_profile/impl/tsconfig.json index cb0254e24fee7..20ed512bdbf21 100644 --- a/packages/shared-ux/avatar/user_profile/impl/tsconfig.json +++ b/packages/shared-ux/avatar/user_profile/impl/tsconfig.json @@ -5,7 +5,6 @@ "declarationMap": true, "emitDeclarationOnly": true, "outDir": "target_types", - "rootDir": "src", "stripInternal": false, "types": [ "jest", @@ -15,6 +14,7 @@ ] }, "include": [ - "src/**/*" + "**/*.ts", + "**/*.mdx", ] } diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_avatar.test.tsx b/packages/shared-ux/avatar/user_profile/impl/user_avatar.test.tsx similarity index 100% rename from packages/shared-ux/avatar/user_profile/impl/src/user_avatar.test.tsx rename to packages/shared-ux/avatar/user_profile/impl/user_avatar.test.tsx diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_avatar.tsx b/packages/shared-ux/avatar/user_profile/impl/user_avatar.tsx similarity index 100% rename from packages/shared-ux/avatar/user_profile/impl/src/user_avatar.tsx rename to packages/shared-ux/avatar/user_profile/impl/user_avatar.tsx diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_profile.ts b/packages/shared-ux/avatar/user_profile/impl/user_profile.ts similarity index 100% rename from packages/shared-ux/avatar/user_profile/impl/src/user_profile.ts rename to packages/shared-ux/avatar/user_profile/impl/user_profile.ts diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx b/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx similarity index 79% rename from packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx rename to packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx index 81167287d7063..d44c848b34a9a 100644 --- a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles.stories.tsx +++ b/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx @@ -8,22 +8,22 @@ import React from 'react'; import { UserAvatar, UserAvatarProps } from './user_avatar'; -// import mdx from '../README.mdx' +import mdx from './README.mdx'; export default { title: 'Avatar/User Profile', description: '', parameters: { - // docs: { - // page: mdx, - // }, + docs: { + page: mdx, + }, }, }; -type userAvatarNameParams = Pick +type UserAvatarParams = Pick -export const userAvatar = (params: userAvatarNameParams) => { +export const userAvatar = (params: UserAvatarParams) => { return ; }; diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_popover.test.tsx b/packages/shared-ux/avatar/user_profile/impl/user_profiles_popover.test.tsx similarity index 100% rename from packages/shared-ux/avatar/user_profile/impl/src/user_profiles_popover.test.tsx rename to packages/shared-ux/avatar/user_profile/impl/user_profiles_popover.test.tsx diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_popover.tsx b/packages/shared-ux/avatar/user_profile/impl/user_profiles_popover.tsx similarity index 100% rename from packages/shared-ux/avatar/user_profile/impl/src/user_profiles_popover.tsx rename to packages/shared-ux/avatar/user_profile/impl/user_profiles_popover.tsx diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_selectable.test.tsx b/packages/shared-ux/avatar/user_profile/impl/user_profiles_selectable.test.tsx similarity index 100% rename from packages/shared-ux/avatar/user_profile/impl/src/user_profiles_selectable.test.tsx rename to packages/shared-ux/avatar/user_profile/impl/user_profiles_selectable.test.tsx diff --git a/packages/shared-ux/avatar/user_profile/impl/src/user_profiles_selectable.tsx b/packages/shared-ux/avatar/user_profile/impl/user_profiles_selectable.tsx similarity index 100% rename from packages/shared-ux/avatar/user_profile/impl/src/user_profiles_selectable.tsx rename to packages/shared-ux/avatar/user_profile/impl/user_profiles_selectable.tsx From 5e7bd525497ff4f060bf8d462550c4cfce69a334 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 31 Aug 2022 21:35:43 +0000 Subject: [PATCH 11/21] [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' --- .../user_profile/impl/user_profiles.stories.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx b/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx index 9e44ab2279913..167779cf4b951 100644 --- a/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx +++ b/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx @@ -20,11 +20,17 @@ export default { }, }; -type UserAvatarParams = Pick - +type UserAvatarParams = Pick; export const userAvatar = (params: UserAvatarParams) => { - return ; + return ( + + ); }; userAvatar.argTypes = { From 808a84caa454b58071c2ea3ac0c21efbfebb1522 Mon Sep 17 00:00:00 2001 From: rshen91 Date: Thu, 1 Sep 2022 08:37:57 -0600 Subject: [PATCH 12/21] update --- .../impl/user_profiles.stories.tsx | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx b/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx index 9e44ab2279913..b51f175610c6f 100644 --- a/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx +++ b/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx @@ -8,28 +8,32 @@ import React from 'react'; import { UserAvatar, UserAvatarProps } from './user_avatar'; -import mdx from './README.mdx'; +// import mdx from './README.mdx'; +import { UserProfileUserInfo } from './user_profile'; export default { title: 'Avatar/User Profile', description: '', parameters: { docs: { - page: mdx, + // page: mdx, }, }, }; -type UserAvatarParams = Pick +type UserAvatarParams = Pick; - -export const userAvatar = (params: UserAvatarParams) => { - return ; +export const userAvatar = ( + params: Pick, + rest: UserAvatarParams +) => { + return ; }; userAvatar.argTypes = { - user: { - control: 'text', + username: { + control: { type: 'radio' }, + options: ['Peggy', 'Burt', 'Leonardo DiCaprio'], defaultValue: 'Peggy', }, }; From bf459116cc0b0039043810d003a097de058eae8a Mon Sep 17 00:00:00 2001 From: rshen91 Date: Thu, 1 Sep 2022 10:04:25 -0600 Subject: [PATCH 13/21] flesh out readme --- .../shared-ux/avatar/user_profile/impl/BUILD.bazel | 3 +-- .../shared-ux/avatar/user_profile/impl/README.mdx | 13 +++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel b/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel index 0f8a7f71df6b1..447bd41d39788 100644 --- a/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel +++ b/packages/shared-ux/avatar/user_profile/impl/BUILD.bazel @@ -2,7 +2,7 @@ load("@npm//@bazel/typescript:index.bzl", "ts_config") load("@build_bazel_rules_nodejs//:index.bzl", "js_library") load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") -PKG_DIRNAME = "impl" +PKG_DIRNAME = "avatar-user-profile" PKG_REQUIRE_NAME = "@kbn/shared-ux-avatar-user-profile-components" SOURCE_FILES = glob( @@ -98,7 +98,6 @@ ts_project( declaration_map = True, emit_declaration_only = True, out_dir = "target_types", - root_dir = ".", tsconfig = ":tsconfig", ) diff --git a/packages/shared-ux/avatar/user_profile/impl/README.mdx b/packages/shared-ux/avatar/user_profile/impl/README.mdx index 437586b2b3346..1522cec340b9b 100644 --- a/packages/shared-ux/avatar/user_profile/impl/README.mdx +++ b/packages/shared-ux/avatar/user_profile/impl/README.mdx @@ -1,3 +1,12 @@ -# @kbn/shared-ux-avatar-user-profile-components +--- +id: sharedUX/Components/UserProfileAvatar +slug: /shared-ux/components/user-profile-avatar +title: User Profile Avatar +description: A wrapper around `EuiAvatar` +tags: ['shared-ux', 'component'] +date: 2022-09-01 +--- -Empty package generated by @kbn/generate +## Description + +A wrapper around `EuiAvatar` tailored for user profiles From 3224aaa7a72435acd715d575cc88177e1349565a Mon Sep 17 00:00:00 2001 From: rshen91 Date: Thu, 1 Sep 2022 11:00:13 -0600 Subject: [PATCH 14/21] tsconfig --- packages/shared-ux/avatar/user_profile/impl/tsconfig.json | 4 +++- .../avatar/user_profile/impl/user_profiles.stories.tsx | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/shared-ux/avatar/user_profile/impl/tsconfig.json b/packages/shared-ux/avatar/user_profile/impl/tsconfig.json index 20ed512bdbf21..5f12c69172930 100644 --- a/packages/shared-ux/avatar/user_profile/impl/tsconfig.json +++ b/packages/shared-ux/avatar/user_profile/impl/tsconfig.json @@ -14,7 +14,9 @@ ] }, "include": [ + "*ts*", + "*.md*", "**/*.ts", - "**/*.mdx", + "**/*.md*", ] } diff --git a/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx b/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx index b51f175610c6f..72f56c3ec1a26 100644 --- a/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx +++ b/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { UserAvatar, UserAvatarProps } from './user_avatar'; -// import mdx from './README.mdx'; +import mdx from './README.mdx'; import { UserProfileUserInfo } from './user_profile'; export default { @@ -16,7 +16,7 @@ export default { description: '', parameters: { docs: { - // page: mdx, + page: mdx, }, }, }; From d27abd2157d6e1e96473ec5b1998c2613e8ada2f Mon Sep 17 00:00:00 2001 From: rshen91 Date: Tue, 6 Sep 2022 11:35:58 -0600 Subject: [PATCH 15/21] fix story --- .../impl/user_profiles.stories.tsx | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx b/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx index 72f56c3ec1a26..6171ecab78b95 100644 --- a/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx +++ b/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx @@ -22,18 +22,37 @@ export default { }; type UserAvatarParams = Pick; +const sampleUsers = [{ + username: 'Peggy', + email: 'test@email.com', + full_name: 'Peggy Simms', + display_name: 'Peggy' +}, +{ + username: 'Martin', + email: 'test@email.com', + full_name: 'Martin Gatsby', + display_name: 'Martin' +}, +{ + username: 'Leonardo DiCaprio', + email: 'test@email.com', + full_name: 'Leonardo DiCaprio', + display_name: 'Leonardo DiCaprio' +}]; export const userAvatar = ( params: Pick, rest: UserAvatarParams ) => { - return ; + let username = params; + return ; }; userAvatar.argTypes = { username: { control: { type: 'radio' }, - options: ['Peggy', 'Burt', 'Leonardo DiCaprio'], - defaultValue: 'Peggy', + options: sampleUsers.map(({username}) => username), + defaultValue: sampleUsers.map(({username}) => username)[0], }, }; From f08bab4092469115d2d5fea51f550efe2bf69944 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 6 Sep 2022 18:04:55 +0000 Subject: [PATCH 16/21] [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' --- .../impl/user_profiles.stories.tsx | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx b/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx index 6171ecab78b95..b16efe7a94bcc 100644 --- a/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx +++ b/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx @@ -22,37 +22,39 @@ export default { }; type UserAvatarParams = Pick; -const sampleUsers = [{ - username: 'Peggy', - email: 'test@email.com', - full_name: 'Peggy Simms', - display_name: 'Peggy' -}, -{ - username: 'Martin', - email: 'test@email.com', - full_name: 'Martin Gatsby', - display_name: 'Martin' -}, -{ - username: 'Leonardo DiCaprio', - email: 'test@email.com', - full_name: 'Leonardo DiCaprio', - display_name: 'Leonardo DiCaprio' -}]; +const sampleUsers = [ + { + username: 'Peggy', + email: 'test@email.com', + full_name: 'Peggy Simms', + display_name: 'Peggy', + }, + { + username: 'Martin', + email: 'test@email.com', + full_name: 'Martin Gatsby', + display_name: 'Martin', + }, + { + username: 'Leonardo DiCaprio', + email: 'test@email.com', + full_name: 'Leonardo DiCaprio', + display_name: 'Leonardo DiCaprio', + }, +]; export const userAvatar = ( params: Pick, rest: UserAvatarParams ) => { - let username = params; - return ; + const username = params; + return ; }; userAvatar.argTypes = { username: { control: { type: 'radio' }, - options: sampleUsers.map(({username}) => username), - defaultValue: sampleUsers.map(({username}) => username)[0], + options: sampleUsers.map(({ username }) => username), + defaultValue: sampleUsers.map(({ username }) => username)[0], }, }; From 45aa4b98aca28e812d906c57a733886fb8661213 Mon Sep 17 00:00:00 2001 From: rshen91 Date: Mon, 19 Sep 2022 10:14:15 -0600 Subject: [PATCH 17/21] update --- packages/shared-ux/avatar/user_profile/impl/user_profile.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/shared-ux/avatar/user_profile/impl/user_profile.ts b/packages/shared-ux/avatar/user_profile/impl/user_profile.ts index eb6f67f1d25ca..31db50ae5f184 100644 --- a/packages/shared-ux/avatar/user_profile/impl/user_profile.ts +++ b/packages/shared-ux/avatar/user_profile/impl/user_profile.ts @@ -123,16 +123,12 @@ export function getUserAvatarInitials( user: Pick, avatar?: UserProfileAvatarData ) { - if (avatar && avatar.initials) { - return avatar.initials; - } - const words = getUserDisplayName(user).split(' '); const numInitials = Math.min(USER_AVATAR_MAX_INITIALS, words.length); words.splice(numInitials, words.length); - return words.map((word) => word.substring(0, 1)).join(''); + return avatar?.initials ?? words.map((word) => word.substring(0, 1)).join(''); } /** From 1e5076c7a20b80a90d7ee94c436caef4a0c1562e Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Mon, 19 Sep 2022 16:22:30 +0000 Subject: [PATCH 18/21] [CI] Auto-commit changed files from 'node scripts/generate packages_build_manifest' --- packages/BUILD.bazel | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/BUILD.bazel b/packages/BUILD.bazel index f400eaf27a6a6..f55c3c39befb1 100644 --- a/packages/BUILD.bazel +++ b/packages/BUILD.bazel @@ -280,7 +280,6 @@ filegroup( "//packages/kbn-utils:build", "//packages/kbn-yarn-lock-validator:build", "//packages/shared-ux/avatar/solution:build", - "//packages/shared-ux/avatar/user_profile/impl:build", "//packages/shared-ux/button_toolbar:build", "//packages/shared-ux/button/exit_full_screen/impl:build", "//packages/shared-ux/button/exit_full_screen/mocks:build", @@ -580,7 +579,6 @@ filegroup( "//packages/kbn-utils:build_types", "//packages/kbn-yarn-lock-validator:build_types", "//packages/shared-ux/avatar/solution:build_types", - "//packages/shared-ux/avatar/user_profile/impl:build_types", "//packages/shared-ux/button_toolbar:build_types", "//packages/shared-ux/button/exit_full_screen/impl:build_types", "//packages/shared-ux/button/exit_full_screen/mocks:build_types", From b448ed964fc7ea20546b4e23180bff4253eaa96b Mon Sep 17 00:00:00 2001 From: rshen91 Date: Mon, 19 Sep 2022 10:29:46 -0600 Subject: [PATCH 19/21] update to camelcase --- .../user_profile/impl/user_avatar.test.tsx | 6 +++--- .../avatar/user_profile/impl/user_profile.ts | 18 +++++++----------- .../impl/user_profiles.stories.tsx | 12 ++++++------ .../impl/user_profiles_popover.test.tsx | 12 ++++++------ .../impl/user_profiles_selectable.test.tsx | 8 ++++---- 5 files changed, 26 insertions(+), 30 deletions(-) diff --git a/packages/shared-ux/avatar/user_profile/impl/user_avatar.test.tsx b/packages/shared-ux/avatar/user_profile/impl/user_avatar.test.tsx index 9c654d25f70fe..6a62d14c75642 100644 --- a/packages/shared-ux/avatar/user_profile/impl/user_avatar.test.tsx +++ b/packages/shared-ux/avatar/user_profile/impl/user_avatar.test.tsx @@ -18,7 +18,7 @@ describe('UserAvatar', () => { user={{ username: 'delighted_nightingale', email: 'delighted_nightingale@elastic.co', - full_name: 'Delighted Nightingale', + fullName: 'Delighted Nightingale', }} avatar={{ color: '#09e8ca', @@ -42,7 +42,7 @@ describe('UserAvatar', () => { user={{ username: 'delighted_nightingale', email: 'delighted_nightingale@elastic.co', - full_name: 'Delighted Nightingale', + fullName: 'Delighted Nightingale', }} avatar={{ color: '#09e8ca', @@ -67,7 +67,7 @@ describe('UserAvatar', () => { user={{ username: 'delighted_nightingale', email: 'delighted_nightingale@elastic.co', - full_name: 'Delighted Nightingale', + fullName: 'Delighted Nightingale', }} /> ); diff --git a/packages/shared-ux/avatar/user_profile/impl/user_profile.ts b/packages/shared-ux/avatar/user_profile/impl/user_profile.ts index 31db50ae5f184..f82816df3d3e3 100644 --- a/packages/shared-ux/avatar/user_profile/impl/user_profile.ts +++ b/packages/shared-ux/avatar/user_profile/impl/user_profile.ts @@ -57,11 +57,11 @@ export interface UserProfileUserInfo { /** * Optional full name of the user. */ - full_name?: string; + fullName?: string; /** * Optional display name of the user. */ - display_name?: string; + displayName?: string; } /** @@ -99,16 +99,12 @@ export const USER_AVATAR_MAX_INITIALS = 2; * @param {UserProfileAvatarData} avatar User avatar */ export function getUserAvatarColor( - user: Pick, + user: Pick, avatar?: UserProfileAvatarData ) { - if (avatar && avatar.color) { - return avatar.color; - } - const firstCodePoint = getUserDisplayName(user).codePointAt(0) || USER_AVATAR_FALLBACK_CODE_POINT; - return VISUALIZATION_COLORS[firstCodePoint % VISUALIZATION_COLORS.length]; + return avatar?.color ?? VISUALIZATION_COLORS[firstCodePoint % VISUALIZATION_COLORS.length]; } /** @@ -120,7 +116,7 @@ export function getUserAvatarColor( * @param {UserProfileAvatarData} avatar User avatar */ export function getUserAvatarInitials( - user: Pick, + user: Pick, avatar?: UserProfileAvatarData ) { const words = getUserDisplayName(user).split(' '); @@ -136,6 +132,6 @@ export function getUserAvatarInitials( * * @param {UserProfileUserInfo} user User info */ -export function getUserDisplayName(user: Pick) { - return user.full_name || user.username; +export function getUserDisplayName(user: Pick) { + return user.fullName || user.username; } diff --git a/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx b/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx index b16efe7a94bcc..e7a7fa719f2e8 100644 --- a/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx +++ b/packages/shared-ux/avatar/user_profile/impl/user_profiles.stories.tsx @@ -26,20 +26,20 @@ const sampleUsers = [ { username: 'Peggy', email: 'test@email.com', - full_name: 'Peggy Simms', - display_name: 'Peggy', + fullName: 'Peggy Simms', + displayName: 'Peggy', }, { username: 'Martin', email: 'test@email.com', - full_name: 'Martin Gatsby', - display_name: 'Martin', + fullName: 'Martin Gatsby', + displayName: 'Martin', }, { username: 'Leonardo DiCaprio', email: 'test@email.com', - full_name: 'Leonardo DiCaprio', - display_name: 'Leonardo DiCaprio', + fullName: 'Leonardo DiCaprio', + displayName: 'Leonardo DiCaprio', }, ]; diff --git a/packages/shared-ux/avatar/user_profile/impl/user_profiles_popover.test.tsx b/packages/shared-ux/avatar/user_profile/impl/user_profiles_popover.test.tsx index 13604fcfeb36f..ecdd455adedd4 100644 --- a/packages/shared-ux/avatar/user_profile/impl/user_profiles_popover.test.tsx +++ b/packages/shared-ux/avatar/user_profile/impl/user_profiles_popover.test.tsx @@ -19,7 +19,7 @@ const userProfiles = [ user: { username: 'delighted_nightingale', email: 'delighted_nightingale@profiles.elastic.co', - full_name: 'Delighted Nightingale', + fullName: 'Delighted Nightingale', }, }, { @@ -29,7 +29,7 @@ const userProfiles = [ user: { username: 'damaged_raccoon', email: 'damaged_raccoon@profiles.elastic.co', - full_name: 'Damaged Raccoon', + fullName: 'Damaged Raccoon', }, }, { @@ -39,7 +39,7 @@ const userProfiles = [ user: { username: 'physical_dinosaur', email: 'physical_dinosaur@profiles.elastic.co', - full_name: 'Physical Dinosaur', + fullName: 'Physical Dinosaur', }, }, { @@ -49,7 +49,7 @@ const userProfiles = [ user: { username: 'wet_dingo', email: 'wet_dingo@profiles.elastic.co', - full_name: 'Wet Dingo', + fullName: 'Wet Dingo', }, }, ]; @@ -96,7 +96,7 @@ describe('UserProfilesPopover', () => { "uid": "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0", "user": Object { "email": "damaged_raccoon@profiles.elastic.co", - "full_name": "Damaged Raccoon", + "fullName": "Damaged Raccoon", "username": "damaged_raccoon", }, }, @@ -110,7 +110,7 @@ describe('UserProfilesPopover', () => { "uid": "u_BOulL4QMPSyV9jg5lQI2JmCkUnokHTazBnet3xVHNv0_0", "user": Object { "email": "delighted_nightingale@profiles.elastic.co", - "full_name": "Delighted Nightingale", + "fullName": "Delighted Nightingale", "username": "delighted_nightingale", }, }, diff --git a/packages/shared-ux/avatar/user_profile/impl/user_profiles_selectable.test.tsx b/packages/shared-ux/avatar/user_profile/impl/user_profiles_selectable.test.tsx index bdb0be25ce9cf..d17e70c566f43 100644 --- a/packages/shared-ux/avatar/user_profile/impl/user_profiles_selectable.test.tsx +++ b/packages/shared-ux/avatar/user_profile/impl/user_profiles_selectable.test.tsx @@ -19,7 +19,7 @@ const userProfiles = [ user: { username: 'delighted_nightingale', email: 'delighted_nightingale@profiles.elastic.co', - full_name: 'Delighted Nightingale', + fullName: 'Delighted Nightingale', }, }, { @@ -29,7 +29,7 @@ const userProfiles = [ user: { username: 'damaged_raccoon', email: 'damaged_raccoon@profiles.elastic.co', - full_name: 'Damaged Raccoon', + fullName: 'Damaged Raccoon', }, }, { @@ -39,7 +39,7 @@ const userProfiles = [ user: { username: 'physical_dinosaur', email: 'physical_dinosaur@profiles.elastic.co', - full_name: 'Physical Dinosaur', + fullName: 'Physical Dinosaur', }, }, { @@ -49,7 +49,7 @@ const userProfiles = [ user: { username: 'wet_dingo', email: 'wet_dingo@profiles.elastic.co', - full_name: 'Wet Dingo', + fullName: 'Wet Dingo', }, }, ]; From 702fb2e4725f60d47cc2989e440b98053b042a7f Mon Sep 17 00:00:00 2001 From: rshen91 Date: Mon, 19 Sep 2022 11:32:29 -0600 Subject: [PATCH 20/21] update code review --- .../impl/user_profiles_selectable.tsx | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/shared-ux/avatar/user_profile/impl/user_profiles_selectable.tsx b/packages/shared-ux/avatar/user_profile/impl/user_profiles_selectable.tsx index 4d8ff7f5ca9af..e9a96cce079e9 100644 --- a/packages/shared-ux/avatar/user_profile/impl/user_profiles_selectable.tsx +++ b/packages/shared-ux/avatar/user_profile/impl/user_profiles_selectable.tsx @@ -200,6 +200,15 @@ export const UserProfilesSelectable: FunctionComponent )} - ) : undefined} + ) : null} From 91bfc6a13ecc361e88e2e291e9f7c7559064dc68 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Mon, 19 Sep 2022 18:01:18 +0000 Subject: [PATCH 21/21] [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' --- .../impl/user_profiles_selectable.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/shared-ux/avatar/user_profile/impl/user_profiles_selectable.tsx b/packages/shared-ux/avatar/user_profile/impl/user_profiles_selectable.tsx index e9a96cce079e9..ea0e2260f44fd 100644 --- a/packages/shared-ux/avatar/user_profile/impl/user_profiles_selectable.tsx +++ b/packages/shared-ux/avatar/user_profile/impl/user_profiles_selectable.tsx @@ -200,14 +200,14 @@ export const UserProfilesSelectable: FunctionComponent