Skip to content

Commit

Permalink
Merge branch 'develop' into multiInstance
Browse files Browse the repository at this point in the history
# Conflicts:
#	admin/tabs/server/ServerTab.ts
  • Loading branch information
lbwexler committed Nov 14, 2023
2 parents 5df5339 + d99defd commit 8706413
Show file tree
Hide file tree
Showing 107 changed files with 4,286 additions and 1,482 deletions.
87 changes: 72 additions & 15 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,85 @@
# Changelog

## 60.0.0-SNAPSHOT - unreleased
## 59.3.1 - 2023-11-10

### 🐞 Bug Fixes

* Ensure an unauthorized response from a proxy service endpoint does not prompt the user to refresh
and log in again on an SSO-enabled application.
* Revert change to `Panel` which affected where `className` was applied with `modalSupport` enabled

## 59.3.0 - 2023-11-09

### 🎁 New Features

* Improved Hoist support for automated testing via Playwright, Cypress, and similar tools:
* Core Hoist components now accept an optional `testId` prop, to be rendered at an appropriate
level of the DOM (within a `data-testid` HTML attribute). This can minimize the need to select
components using criteria such as CSS classes or labels that are more likely to change and
break tests.
* When given a `testId`, certain composite components will generate and set "sub-testIds" on
selected internal components. For example, a `TabContainer` will set a testId on each switcher
button (derived from its tabId), and a `Form` will set testIds on nested `FormField`
and `HoistInput` components (derived from their bound field names).
* This release represents a first step in ongoing work to facilitate automated end-to-end
testing of Hoist applications. Additional Hoist-specific utilities for writing tests in
libraries such as Cypress and Playwright are coming soon.
* Added new `ZoneGrid` component, a highly specialized `Grid` that always displays its data with
multi-line, full-width rows. Each row is broken into four zones (top/bottom and left/right),
each of which can mapped by the user to render data from one or more fields.
* Primarily intended for mobile, where horizontal scrolling can present usability issues, but
also available on desktop, where it can serve as an easily user-configurable `DataView`.
* Added `Column.sortToBottom` to force specified values to sort the bottom, regardless of sort
direction. Intended primarily to force null values to sort below all others.
* Upgraded the `RelativeTimestamp` component with a new `localDateMode` option to customize how
near-term date/time differences are rendered with regards to calendar days.

### 🐞 Bug Fixes

* Fixed bug where interacting with a `Select` within a `Popover` can inadvertently cause the
popover to close. If your app already has special handling in place to prevent this, you should
be able to unwind it after upgrading.
* Improved the behavior of the clear button in `TextInput`. Clearing a field no longer drops focus,
allowing the user to immediately begin typing in a new value.
* Fixed arguments passed to `ErrorMessageProps.actionFn` and `ErrorMessageProps.detailsFn`.
* Improved default error text in `ErrorMessage`.

### ⚙️ Technical

* Improved core `HoistComponent` performance by preventing unnecessary re-renderings triggered by
spurious model lookup changes.
* New flag `GridModel.experimental.enableFullWidthScroll` enables scrollbars to span pinned columns.
* Early test release behind the flag, expected to made the default behavior in next release.
* Renamed `XH.getActiveModels()` to `XH.getModels()` for clarity / consistency.
* API change, but not expected to impact applications.
* Added `XH.getModel()` convenience method to return the first matching model.

## 59.2.0 - 2023-10-16

### 🎁 New Features

* New `DockViewConfig.onClose` hook invoked when a user attempts to remove a `DockContainer` view
* Add `GridModel` APIs to lookup and show / hide entire column groups
* Left / right borders are now rendered along `Grid` `ColumnGroup` edges by default. Control
with new boolean property `ColumnGroupSpec.borders`
* The Cube package has been enhanced to support `Query` specific post-processing functions. See
new properties `Query.omitFn`, `Query.bucketSpecFn` and `Query.lockFn`. These properties default
to their respective properties on `Cube`.
* New `DockViewConfig.onClose` hook invoked when a user attempts to remove a `DockContainer` view.
* Added `GridModel` APIs to lookup and show / hide entire column groups.
* Left / right borders are now rendered along `Grid` `ColumnGroup` edges by default, controllable
with new `ColumnGroupSpec.borders` config.
* Enhanced the `CubeQuery` to support per-query post-processing functions
with `Query.omitFn`, `Query.bucketSpecFn` and `Query.lockFn`. These properties default to their
respective properties on `Cube`.

### 🐞 Bug Fixes

* `DashContainerModel` fixes:
* Fix bug where `addView` would throw when adding a view to a row or column
* Fix bug where `allowRemove` flag was dropped from state for containers
* Fix bug in `DockContainer` where adding / removing views would cause other views to be remounted
* Fix erroneous `GridModel` warning when using a tree column within a column group
* Fix regression to alert banners. Resume allowing elements as messages
* Fix bug where `addView` would throw when adding a view to a row or column
* Fix bug where `allowRemove` flag was dropped from state for containers
* Fix bug in `DockContainer` where adding / removing views would cause other views to be
remounted
* Fixed erroneous `GridModel` warning when using a tree column within a column group
* Fixed regression to alert banners. Resume allowing elements as messages.
* Fix `Grid` cell border styling inconsistencies.

### ⚙️ Typescript API Adjustments

* Add type for `ActionFnData.record`
* Added type for `ActionFnData.record`.

## 59.1.0 - 2023-09-20

Expand All @@ -49,7 +105,8 @@ to their respective properties on `Cube`.
* Improved styling for disabled `checkbox` inputs.

### ⚙️ Technical
* `XH.showException` has been deprecated. Use similar methods on `XH.exceptionHandler` instead.

* `XH.showException` has been deprecated. Use similar methods on `XH.exceptionHandler` instead.

### 📚 Libraries

Expand Down
2 changes: 1 addition & 1 deletion admin/AppComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const AppComponent = hoistCmp({
const tbar = hoistCmp.factory<AppModel>(({model}) =>
appBar({
icon: Icon.gears({size: '2x', prefix: 'fal'}),
leftItems: [tabSwitcher({enableOverflow: true})],
leftItems: [tabSwitcher({testId: 'tab-switcher', enableOverflow: true})],
rightItems: [
button({
icon: Icon.openExternal(),
Expand Down
2 changes: 1 addition & 1 deletion admin/tabs/activity/ActivityTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const activityTab = hoistCmp.factory(() =>
tabContainer({
modelConfig: {
route: 'default.activity',
switcher: {orientation: 'left'},
switcher: {orientation: 'left', testId: 'activity-tab-switcher'},
tabs: [
{id: 'tracking', icon: Icon.analytics(), content: activityTrackingPanel},
{id: 'clientErrors', icon: Icon.warning(), content: clientErrorsPanel},
Expand Down
4 changes: 2 additions & 2 deletions admin/tabs/general/GeneralTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import {configPanel} from '@xh/hoist/admin/tabs/general/config/ConfigPanel';
import {logLevelPanel} from '@xh/hoist/admin/tabs/general/logLevel/LogLevelPanel';
import {tabContainer} from '@xh/hoist/cmp/tab';
import {XH, hoistCmp} from '@xh/hoist/core';
import {hoistCmp, XH} from '@xh/hoist/core';
import {Icon} from '@xh/hoist/icon';
import {aboutPanel} from './about/AboutPanel';
import {alertBannerPanel} from './alertBanner/AlertBannerPanel';
Expand All @@ -17,7 +17,7 @@ export const generalTab = hoistCmp.factory(() =>
tabContainer({
modelConfig: {
route: 'default.general',
switcher: {orientation: 'left'},
switcher: {orientation: 'left', testId: 'general-tab-switcher'},
tabs: [
{id: 'about', icon: Icon.info(), content: aboutPanel},
{id: 'config', icon: Icon.settings(), content: configPanel},
Expand Down
1 change: 1 addition & 0 deletions admin/tabs/general/config/ConfigPanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const configPanel = hoistCmp.factory({
render({model}) {
return fragment(
restGrid({
testId: 'config',
extraToolbarItems: () => {
return button({
icon: Icon.diff(),
Expand Down
2 changes: 1 addition & 1 deletion admin/tabs/monitor/MonitorTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const monitorTab = hoistCmp.factory(() => {
? tabContainer({
modelConfig: {
route: 'default.monitor',
switcher: {orientation: 'left'},
switcher: {orientation: 'left', testId: 'monitor-tab-switcher'},
tabs: [
{id: 'status', icon: Icon.shieldCheck(), content: monitorResultsPanel},
{id: 'config', icon: Icon.settings(), content: monitorEditorPanel}
Expand Down
Empty file added admin/tabs/server/ServerTab.ts
Empty file.
2 changes: 1 addition & 1 deletion admin/tabs/userData/UserDataTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const userDataTab = hoistCmp.factory(() =>
tabContainer({
modelConfig: {
route: 'default.userData',
switcher: {orientation: 'left'},
switcher: {orientation: 'left', testId: 'user-data-tab-switcher'},
tabs: [
{
id: 'prefs',
Expand Down
76 changes: 51 additions & 25 deletions cmp/ag-grid/AgGrid.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
border-#{$side}: var(--xh-border-solid);
}

@mixin pinned-border {
border-right: 1px solid var(--xh-grid-pinned-column-border-color);
@mixin pinned-border($side) {
border-#{$side}: 1px solid var(--xh-grid-pinned-column-border-color);
}

// Ag-grid installs an outer div around itself.
Expand Down Expand Up @@ -128,16 +128,17 @@
}

&--no-row-borders {
.ag-row {
.ag-row,
.ag-cell {
border-bottom: none;
border-top: none;
}

// Deliberately keep border on full-width grouped rows even when we aren't adding row borders.
// Without this collapsed groups (which don't stripe) blend together in a solid block.
&.ag-row-group.ag-full-width-row {
border-bottom: 1px solid var(--xh-grid-group-border-color);
border-top: 1px solid var(--xh-grid-group-border-color);
}
// Deliberately keep border on full-width grouped rows even when we aren't adding row borders.
// Without this collapsed groups (which don't stripe) blend together in a solid block.
.ag-row.ag-row-group.ag-full-width-row {
border-bottom: 1px solid var(--xh-grid-group-border-color);
border-top: 1px solid var(--xh-grid-group-border-color);
}
}

Expand Down Expand Up @@ -197,8 +198,14 @@
}
}

.ag-cell.ag-cell-last-left-pinned:not(.ag-cell-focus) {
@include pinned-border;
.ag-cell {
&.ag-cell-last-left-pinned:not(.ag-cell-focus) {
@include pinned-border(right);
}

&.ag-cell-first-right-pinned:not(.ag-cell-focus) {
@include pinned-border(left);
}
}

// We use flexbox to consistently vertically center cell contents across
Expand Down Expand Up @@ -237,33 +244,52 @@
&--no-cell-borders {
.ag-cell,
.ag-context-menu-open .ag-cell-focus:not(.ag-cell-range-selected) {
border: none;
// Preserve left and right borders to avoid jumpiness upon cell focus
border-top: none;
border-bottom: none;
border-left-color: transparent;
border-right-color: transparent;
}
}

// Cell focus
&--no-cell-focus {
// Preserve cell borders when enabled upon "invisible" cell focus
&.xh-ag-grid--cell-borders .ag-has-focus .ag-cell-focus:not(.ag-cell-range-selected) {
border-right-color: var(--xh-grid-border-color);
}

.ag-has-focus {
.ag-cell-focus:not(.ag-cell-range-selected) {
border: none;

&.ag-cell.ag-cell-last-left-pinned {
@include pinned-border;
}

&.ag-cell.xh-cell--group-border-left {
@include group-border(left);
}

&.ag-cell.xh-cell--group-border-right {
@include group-border(right);
// Preserve left and right borders to avoid jumpiness upon cell focus
border-top: none;
border-bottom: none;
border-left-color: transparent;
border-right-color: transparent;

&.ag-cell {
&.ag-cell-last-left-pinned {
@include pinned-border(right);
}

&.ag-cell-first-right-pinned {
@include pinned-border(left);
}

&.xh-cell--group-border-left {
@include group-border(left);
}

&.xh-cell--group-border-right {
@include group-border(right);
}
}
}
}
}

&--show-cell-focus {
.ag-cell-focus {
.ag-cell-focus:focus-within {
border-color: var(--xh-grid-cell-focus-border-color) !important;
}
}
Expand Down
10 changes: 8 additions & 2 deletions cmp/ag-grid/AgGrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
HoistProps,
LayoutProps,
lookup,
TestSupportProps,
useLocalModel,
uses,
XH
Expand All @@ -23,7 +24,11 @@ import {isNil} from 'lodash';
import './AgGrid.scss';
import {AgGridModel} from './AgGridModel';

export interface AgGridProps extends HoistProps<AgGridModel>, GridOptions, LayoutProps {}
export interface AgGridProps
extends HoistProps<AgGridModel>,
GridOptions,
LayoutProps,
TestSupportProps {}

/**
* Minimal wrapper for AgGridReact, supporting direct use of the ag-Grid component with limited
Expand Down Expand Up @@ -53,7 +58,7 @@ export const [AgGrid, agGrid] = hoistCmp.withFactory<AgGridProps>({
className: 'xh-ag-grid',
model: uses(AgGridModel),

render({model, className, ...props}, ref) {
render({model, className, testId, ...props}, ref) {
if (!AgGridReact) {
console.error(
'ag-Grid has not been imported in to this application. Please import and ' +
Expand Down Expand Up @@ -90,6 +95,7 @@ export const [AgGrid, agGrid] = hoistCmp.withFactory<AgGridProps>({
hideHeaders ? 'xh-ag-grid--hide-headers' : null
),
...layoutProps,
testId,
item: createElement(AgGridReact, {
...AgGrid['DEFAULT_PROPS'],
// Default some ag-grid props, but allow overriding.
Expand Down
23 changes: 18 additions & 5 deletions cmp/badge/Badge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
*
* Copyright © 2023 Extremely Heavy Industries Inc.
*/
import {div} from '@xh/hoist/cmp/layout';
import {BoxProps, hoistCmp, HoistProps, Intent} from '@xh/hoist/core';
import {TEST_ID} from '@xh/hoist/utils/js';
import {splitLayoutProps} from '@xh/hoist/utils/react';
import classNames from 'classnames';
import {div} from '@xh/hoist/cmp/layout';
import {merge} from 'lodash';
import './Badge.scss';

export interface BadgeProps extends HoistProps, BoxProps {
Expand All @@ -26,8 +29,10 @@ export const [Badge, badge] = hoistCmp.withFactory<BadgeProps>({

className: 'xh-badge',

render({className, intent, compact = false, ...props}) {
const classes = [];
render(props, ref) {
const classes = [],
[layoutProps, {className, intent, compact, children, testId, ...restProps}] =
splitLayoutProps(props);

if (intent) {
classes.push(`xh-badge--intent-${intent}`);
Expand All @@ -37,9 +42,17 @@ export const [Badge, badge] = hoistCmp.withFactory<BadgeProps>({
classes.push('xh-badge--compact');
}

const divProps = merge(
{className: classNames(className, classes)},
{style: layoutProps},
{[TEST_ID]: testId},
restProps
);

return div({
className: classNames(className, classes),
...props
ref,
...divProps,
items: children
});
}
});
Loading

0 comments on commit 8706413

Please sign in to comment.