Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/7.3' into 8.0
Browse files Browse the repository at this point in the history
  • Loading branch information
mhsdesign committed Mar 31, 2023
2 parents d2125f2 + 9f588ba commit 006800d
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 9 deletions.
6 changes: 3 additions & 3 deletions Classes/Controller/BackendServiceController.php
Original file line number Diff line number Diff line change
Expand Up @@ -533,13 +533,13 @@ function ($envelope) {
$result = [];
switch ($finisher['type']) {
case 'get':
$result = $nodeInfoHelper->renderNodes($flowQuery->get(), $this->getControllerContext());
$result = $nodeInfoHelper->renderNodes(array_filter($flowQuery->get()), $this->getControllerContext());
break;
case 'getForTree':
$result = $nodeInfoHelper->renderNodes($flowQuery->get(), $this->getControllerContext(), true);
$result = $nodeInfoHelper->renderNodes(array_filter($flowQuery->get()), $this->getControllerContext(), true);
break;
case 'getForTreeWithParents':
$result = $nodeInfoHelper->renderNodesWithParents($flowQuery->get(), $this->getControllerContext());
$result = $nodeInfoHelper->renderNodesWithParents(array_filter($flowQuery->get()), $this->getControllerContext());
break;
}

Expand Down
76 changes: 76 additions & 0 deletions cssVariables.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* see https://github.com/neos/neos-ui/pull/3438 as to why we have in NeosUi 7.3 - 8.2 two declarations of the same set of css variables.
*/

/** Global CSS variables for Neos.Ui */

/**
* They are compiled into the source code via our buildstack, and additionally exposed on the Host, to be consumed at runtime by plugins
*
* We currently dont use runtime variables in the NeosUi see: https://github.com/neos/neos-ui/issues/3201
* This approach would work for the Host frame, but we inject some rendered html and css (the inline toolbar) into the guest frame where we also rely on css variables.
* To not collide with consumer css variables in the iframe, we keep them compiled.
*
* While we do make sure that plugins are working who use the variable names, they are not marked as @api but only available for unplanned extensibility.
* In the future we plan to transform the names to lowercase and might get rid of some unused/odd variables (like all the --zIndex- ones).
*/
:root {
--spacing-GoldenUnit: 40px;
--spacing-Full: 16px;
--spacing-Half: 8px;
--spacing-Quarter: 4px;
--size-SidebarWidth: 320px;
--transition-Fast: .1s;
--transition-Default: .25s;
--transition-Slow: .5s;
--zIndex-SecondaryToolbar-LinkIconButtonFlyout: 1;
--zIndex-FlashMessageContainer: 60;
--zIndex-LoadingIndicatorContainer: 50;
--zIndex-SecondaryInspector-Context: 1;
--zIndex-SecondaryInspector-Iframe: 2;
--zIndex-SecondaryInspector-Close: 3;
--zIndex-SecondaryInspectorElevated-Context: 1;
--zIndex-SecondaryInspectorElevated-DropdownContents: 2;
--zIndex-Dialog-Context: 1;
--zIndex-FullScreenClose-Context: 1;
--zIndex-Drawer: 45;
--zIndex-Bar-Context: 1;
--zIndex-PrimaryToolbar: 40;
--zIndex-CheckboxInput-Context: 1;
--zIndex-DropdownContents-Context: 1;
--zIndex-SelectBoxContents: 40;
--zIndex-NotInlineEditableOverlay-Context: 1;
--zIndex-CalendarFakeInputMirror-Context: 1;
--zIndex-RdtPicker-Context: 1;
--zIndex-SideBar-DropTargetBefore: 1;
--zIndex-SideBar-DropTargetAfter: 2;
--zIndex-WrapperDropdown-Context: 1;
--zIndex-UnappliedChangesOverlay-Context: 1;
--zIndex-NodeToolBar: 2147483646;
--fontSize-Base: 14px;
--fontSize-Small: 12px;
--fontsHeadings-Family: "Noto Sans";
--fontsHeadings-Style: "Regular";
--fontsHeadings-CssWeight: 400;
--fontsCopy-Family: "Noto Sans";
--fontsCopy-Style: "Regular";
--fontsCopy-CssWeight: 400;
--colors-PrimaryViolet: #26224C;
--colors-PrimaryVioletHover: #342f5f;
--colors-PrimaryBlue: #00ADEE;
--colors-PrimaryBlueHover: #35c3f8;
--colors-ContrastDarkest: #141414;
--colors-ContrastDarker: #222;
--colors-ContrastDark: #3f3f3f;
--colors-ContrastNeutral: #323232;
--colors-ContrastBright: #999;
--colors-ContrastBrighter: #adadad;
--colors-ContrastBrightest: #FFF;
--colors-Success: #00a338;
--colors-SuccessHover: #0bb344;
--colors-Warn: #ff8700;
--colors-WarnHover: #fda23d;
--colors-Error: #ff460d;
--colors-ErrorHover: #ff6a3c;
--colors-UncheckedCheckboxTick: #5B5B5B;
}
1 change: 1 addition & 0 deletions packages/neos-ui/src/styleHostOnly.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@import 'normalize.css';
@import '../../../cssVariables.css';

@font-face {
font-family: 'Noto Sans';
Expand Down
5 changes: 5 additions & 0 deletions packages/react-ui-components/src/Tabs/panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ export interface PanelProps {
* An optional css theme to be injected.
*/
readonly theme?: PanelTheme;

/**
* An optional string id used by `<Tabs />` for communicating the "activeTab" instead of using the index.
*/
readonly id?: string;
}

export default class Panel extends PureComponent<PanelProps> {
Expand Down
86 changes: 85 additions & 1 deletion packages/react-ui-components/src/Tabs/tabs.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import {shallow} from 'enzyme';
import {shallow, mount} from 'enzyme';
import toJson from 'enzyme-to-json';
import Tabs, {TabMenuItem, TabsProps, tabsDefaultProps} from './tabs';
import {PanelProps} from './panel';
Expand Down Expand Up @@ -28,6 +28,90 @@ describe('<Tabs/>', () => {
children: [<div key={'foo'}>'Foo children'</div>]
};

it('should use the activeTab prop when initializing.', () => {
const wrapper = shallow(
<Tabs {...props} activeTab={2}>
<Tabs.Panel {...panelProps} title="foo 1" icon="level-up">Foo 1</Tabs.Panel>
<Tabs.Panel {...panelProps} title="foo 2" icon="level-down">Foo 2</Tabs.Panel>
<Tabs.Panel {...panelProps} title="foo 3" icon="mobile">Foo 3</Tabs.Panel>
</Tabs>
);

expect(wrapper.state('activeTab')).toBe(2);
});

it('should update the state when a tab menu item is clicked.', () => {
const wrapper = mount(
<Tabs {...props}>
<Tabs.Panel {...panelProps} title="foo 1" icon="level-up">Foo 1</Tabs.Panel>
<Tabs.Panel {...panelProps} title="foo 2" icon="level-down">Foo 2</Tabs.Panel>
<Tabs.Panel {...panelProps} title="foo 3" icon="mobile">Foo 3</Tabs.Panel>
</Tabs>
);

const tabMenuItems = wrapper.find(TabMenuItem);

const buttonOfFirstTabMenuItem = tabMenuItems.at(2).find('button').at(0);

buttonOfFirstTabMenuItem.simulate('click');

expect(wrapper.state('activeTab')).toBe(2);
});

it('should trigger the hook, when a tab menu item is clicked.', () => {
const onActiveTabChange = jest.fn();

const wrapper = mount(
<Tabs {...props} onActiveTabChange={onActiveTabChange}>
<Tabs.Panel {...panelProps} title="foo 1" icon="level-up">Foo 1</Tabs.Panel>
<Tabs.Panel {...panelProps} title="foo 2" icon="level-down">Foo 2</Tabs.Panel>
<Tabs.Panel {...panelProps} title="foo 3" icon="mobile">Foo 3</Tabs.Panel>
</Tabs>
);

const tabMenuItems = wrapper.find(TabMenuItem);

const buttonOfFirstTabMenuItem = tabMenuItems.at(2).find('button').at(0);

buttonOfFirstTabMenuItem.simulate('click');

expect(onActiveTabChange).toHaveBeenCalledTimes(1);
expect(onActiveTabChange).toBeCalledWith(2);
});

it('activeTab as string: should use the activeTab prop when initializing.', () => {
const wrapper = shallow(
<Tabs {...props} activeTab="zwei">
<Tabs.Panel {...panelProps} id="eins" title="foo 1" icon="level-up">Foo 1</Tabs.Panel>
<Tabs.Panel {...panelProps} id="zwei" title="foo 2" icon="level-down">Foo 2</Tabs.Panel>
<Tabs.Panel {...panelProps} id="drei" title="foo 3" icon="mobile">Foo 3</Tabs.Panel>
</Tabs>
);
expect(wrapper.state('activeTab')).toBe('zwei');
});

it('activeTab as string: should update the state & trigger the hook when a tab menu item is clicked.', () => {
const onActiveTabChange = jest.fn();

const wrapper = mount(
<Tabs {...props} onActiveTabChange={onActiveTabChange}>
<Tabs.Panel {...panelProps} id="eins" title="foo 1" icon="level-up">Foo 1</Tabs.Panel>
<Tabs.Panel {...panelProps} id="zwei" title="foo 2" icon="level-down">Foo 2</Tabs.Panel>
<Tabs.Panel {...panelProps} id="drei" title="foo 3" icon="mobile">Foo 3</Tabs.Panel>
</Tabs>
);

const tabMenuItems = wrapper.find(TabMenuItem);

const buttonOfFirstTabMenuItem = tabMenuItems.at(2).find('button').at(0);

buttonOfFirstTabMenuItem.simulate('click');

expect(wrapper.state('activeTab')).toBe('drei');
expect(onActiveTabChange).toHaveBeenCalledTimes(1);
expect(onActiveTabChange).toBeCalledWith('drei');
});

it('should render correctly.', () => {
const wrapper = shallow(
<Tabs {...props}>
Expand Down
19 changes: 14 additions & 5 deletions packages/react-ui-components/src/Tabs/tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ export interface TabsProps {
*/
readonly activeTab?: string | number;

/**
* Callback when the active tab id changes.
*/
readonly onActiveTabChange?: (activeTab: string | number) => void;

/**
* An optional className to render on the wrapping div.
*/
Expand Down Expand Up @@ -45,19 +50,23 @@ interface TabsState {
export default class Tabs extends PureComponent<TabsProps> {
public static Panel = Panel;
public state: TabsState = {
activeTab: 0,
activeTab: this.props.activeTab ?? 0
};

public static defaultProps = tabsDefaultProps;

private updateActiveTab(activeTab: string | number): void {
this.setState({ activeTab }, () => {
this.props.onActiveTabChange?.(activeTab);
});
}

public UNSAFE_componentWillReceiveProps(newProps: TabsProps): void {
const newactiveTab = newProps.activeTab;
const {activeTab} = this.state;

if (newactiveTab && newactiveTab !== activeTab) {
this.setState({
activeTab: newactiveTab
});
this.updateActiveTab(newactiveTab);
}
}

Expand Down Expand Up @@ -104,7 +113,7 @@ export default class Tabs extends PureComponent<TabsProps> {
}

public handleTabNavItemClick = (id: string | number) => {
this.setState({activeTab: id});
this.updateActiveTab(id);
}

public renderPanels(): JSX.Element {
Expand Down

0 comments on commit 006800d

Please sign in to comment.