Skip to content

Commit

Permalink
#2088 Include actions in properties title editor (#2089)
Browse files Browse the repository at this point in the history
Signed-off-by: Carita Ou <[email protected]>
  • Loading branch information
caritaou authored Aug 7, 2024
1 parent bd46e16 commit b57c7cf
Show file tree
Hide file tree
Showing 11 changed files with 168 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2023 Elyra Authors
* Copyright 2017-2024 Elyra Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -21,9 +21,12 @@ import { expect } from "chai";
import { expect as expectJest } from "@jest/globals";
import sinon from "sinon";
import { renderWithIntl } from "../../_utils_/intl-utils";
import { fireEvent } from "@testing-library/react";
import { fireEvent, within } from "@testing-library/react";

const controller = new Controller();
import propertyUtilsRTL from "../../_utils_/property-utilsRTL";
import ACTION_PARAMDEF from "../../test_resources/paramDefs/action_paramDef.json";

let controller = new Controller();
controller.setTitle("test title");
const form = {
componentId: "test-id"
Expand Down Expand Up @@ -400,3 +403,32 @@ describe("title-editor renders correctly", () => {
expect(titleEditor).to.have.length(0);
});
});

describe("Title editor actions", () => {
let renderedObject;
beforeEach(() => {
renderedObject = propertyUtilsRTL.flyoutEditorForm(ACTION_PARAMDEF);
controller = new Controller();
});

it("title editor should render actions if defined", () => {
const spyPropertyActionHandler = sinon.spy();
renderedObject = propertyUtilsRTL.flyoutEditorForm(ACTION_PARAMDEF, null, { actionHandler: spyPropertyActionHandler }, { appData: appData });
const { container } = renderedObject.wrapper;
const actions = container.querySelector(".properties-title-editor-actions");
const buttons = within(actions).getAllByRole("button");
expect(buttons.length).to.equal(2);

expect(buttons[0].textContent).to.equal("Increment");
expect(buttons[1].textContent).to.equal("Decrement");

fireEvent.click(buttons[0]);

expect(spyPropertyActionHandler.calledOnce).to.equal(true);
expect(spyPropertyActionHandler.calledWith(
ACTION_PARAMDEF.uihints.title_info.action_refs[0],
appData,
{ parameter_ref: "number" }
)).to.be.true;
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,12 @@
"label": {
"default": "Action Test"
},
"title_info": {
"action_refs": [
"increment",
"decrement"
]
},
"parameter_info": [
{
"parameter_ref": "number",
Expand Down Expand Up @@ -360,7 +366,6 @@
}
],
"action_info": [

{
"id": "increment",
"label": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class ButtonAction extends React.Component {
kind={actionButtonKind}
onClick={this.applyAction}
disabled={disabled}
title={this.props.action.label.text}
>
{this.props.action.label.text}
</Button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2023 Elyra Authors
* Copyright 2017-2024 Elyra Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -17,14 +17,16 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { setTitle } from "./../../actions";
import Isvg from "react-inlinesvg";
import { get } from "lodash";
import classNames from "classnames";
import { Help, Edit, Close } from "@carbon/react/icons";
import { TextInput, Button, Layer } from "@carbon/react";

import { setTitle } from "./../../actions";
import { MESSAGE_KEYS, CONDITION_MESSAGE_TYPE } from "./../../constants/constants";
import * as PropertyUtils from "./../../util/property-utils";
import classNames from "classnames";
import { Help, Edit, Close } from "@carbon/react/icons";
import ActionFactory from "../../actions/action-factory.js";


class TitleEditor extends Component {
Expand Down Expand Up @@ -92,6 +94,24 @@ class TitleEditor extends Component {
this.props.setTitle(newTitle);
}

createTitleActions() {
if (this.props.titleInfo && this.props.titleInfo.Title.actionIds().length > 0) {
this.actionFactory = new ActionFactory(this.props.controller);
const actions = [];
this.props.titleInfo.Title.actionIds().forEach((actionRef, idx) => {
const actionMetadata = this.props.controller.getAction({ name: actionRef });
const action = this.actionFactory.generateAction(`${actionRef}-${idx}`, actionMetadata);
actions.push(<div className="cds--css-grid-column cds--col-span-50" key={`${actionRef}-${idx}`}>
{action}
</div>);
});
return (<div className="properties-title-editor-actions cds--css-grid cds--css-grid--narrow">
{actions}
</div>);
}
return null;
}

render() {
if (this.props.title === null) {
return null;
Expand Down Expand Up @@ -204,6 +224,7 @@ class TitleEditor extends Component {
{titleValidationTypes.includes(get(this.state.titleValidation, "type")) ? null : propertiesTitleEdit}
</div>
{!this.headingEnabled && !titleValidationTypes.includes(get(this.state.titleValidation, "type")) ? helpButton : null}
{this.createTitleActions()}
</div>
);
}
Expand All @@ -219,6 +240,7 @@ TitleEditor.propTypes = {
heading: PropTypes.string,
showHeading: PropTypes.bool,
rightFlyoutTabsView: PropTypes.bool,
titleInfo: PropTypes.object,
title: PropTypes.string, // set by redux
setTitle: PropTypes.func // set by redux
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2023 Elyra Authors
* Copyright 2017-2024 Elyra Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,6 +18,32 @@
font-size: 0;
padding: $spacing-05 0;
border-bottom: 1px $layer-accent-01 solid;

.properties-title-editor-actions {
padding: $spacing-05 0 0 $spacing-05;

.properties-action-button {
padding-bottom: $spacing-05;
width: 100%;

button {
width: 100%;
overflow: hidden;
white-space: nowrap;
display: block;
text-overflow: ellipsis;
}

.cds--btn { // Override Carbon padding within a button to allow more text to display
--cds-layout-density-padding-inline-local: 0;
padding: 6px 15px;
}
}

.properties-action-image {
padding: 0;
}
}
}

.properties-title-right-flyout-tabs-view {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { Size } from "../constants/form-constants";
import { CONTAINER_TYPE } from "../constants/constants";

export default class Form {
constructor(componentId, label, labelEditable, help, editorSize, pixelWidth, uiItems, buttons, data, conditions, resources, icon, heading) {
constructor(componentId, label, labelEditable, help, editorSize, pixelWidth, uiItems, buttons, data, conditions, resources, icon, heading, title) {
this.componentId = componentId;
this.label = label;
this.labelEditable = labelEditable;
Expand All @@ -38,6 +38,9 @@ export default class Form {
this.resources = resources;
this.icon = icon;
this.heading = heading;
if (title) {
this.title = title;
}
}

/**
Expand Down Expand Up @@ -79,7 +82,8 @@ export default class Form {
translateMessages(conditions, l10nProvider),
resources,
propDef.icon,
l10nProvider.l10nResource(propDef.heading)
l10nProvider.l10nResource(propDef.heading),
propDef.titleMetadata
);
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/

import { TitleMetadata } from "./TitleInfo";
import { GroupMetadata } from "./GroupInfo";
import { ActionMetadata } from "./ActionInfo";
import { ParameterMetadata } from "./ParameterInfo";
Expand All @@ -24,7 +25,9 @@ import { ResourceDef } from "../util/L10nProvider";
import { propertyOf } from "lodash";

export class PropertyDef {
constructor(cname, icon, editorSize, pixelWidth, label, labelEditable, help, description, structureMetadata, parameterMetadata, groupMetadata, actionMetadata, heading) {
constructor(cname, icon, editorSize, pixelWidth, label, labelEditable, help,
description, structureMetadata, parameterMetadata, groupMetadata,
actionMetadata, heading, titleMetadata) {
this.name = cname;
this.icon = icon;
this.editorSize = editorSize;
Expand All @@ -38,6 +41,7 @@ export class PropertyDef {
this.groupMetadata = groupMetadata;
this.actionMetadata = actionMetadata;
this.heading = heading;
this.titleMetadata = titleMetadata;
}

/**
Expand All @@ -61,6 +65,7 @@ export class PropertyDef {
propertyOf(uihints)("parameter_info"), propertyOf(uihints)("ui_parameters"));
const actionMetadata = ActionMetadata.makeActionMetadata(propertyOf(uihints)("action_info"));
const groupMetadata = GroupMetadata.makeGroupMetadata(propertyOf(uihints)("group_info"), parameterMetadata.getParameters());
const titleMetadata = TitleMetadata.makeTitleMetadata(propertyOf(uihints)("title_info"));

const label = titleDefinition && titleDefinition.title ? titleDefinition.title : null;
const labelEditable = titleDefinition && typeof titleDefinition.editable !== "undefined" ? titleDefinition.editable : DEFAULT_LABEL_EDITABLE;
Expand All @@ -78,7 +83,8 @@ export class PropertyDef {
parameterMetadata,
groupMetadata,
actionMetadata,
propertyOf(uihints)("label")
propertyOf(uihints)("label"),
titleMetadata
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2024 Elyra Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { propertyOf } from "lodash";

class Title {
constructor(title) {
this.actions = title.action_refs || [];
}

static makeTitle(uiGroup) {
if (uiGroup) {
return new Title(
propertyOf(uiGroup)("action_refs")
);
}
return null;
}

actionIds() {
return this.actions;
}
}

export class TitleMetadata {
constructor(title) {
this.Title = title;
}

static makeTitleMetadata(title) {
if (title) {
return new TitleMetadata(new Title(title));
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,7 @@ class PropertiesMain extends React.Component {
icon={formData.icon}
heading={formData.heading}
showHeading={this.props.propertiesConfig.heading}
titleInfo={formData.title}
rightFlyoutTabsView={this.props.propertiesConfig.categoryView === CATEGORY_VIEW.TABS}
/>);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ $properties-modal-buttons-height: $spacing-10;
overflow: hidden;
border-left: 1px solid $layer-accent-01;
outline: none;
display: flex;
flex-direction: column;

&.properties-small {
width: $common-properties-small-flyout-width;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,12 @@
"label": {
"default": "Action Test"
},
"title_info": {
"action_refs": [
"increment",
"decrement"
]
},
"parameter_info": [
{
"parameter_ref": "number",
Expand Down Expand Up @@ -360,7 +366,6 @@
}
],
"action_info": [

{
"id": "increment",
"label": {
Expand Down

0 comments on commit b57c7cf

Please sign in to comment.