pnp / sp-dev-fx-controls-react

Reusable React controls for SPFx solutions
https://pnp.github.io/sp-dev-fx-controls-react/
MIT License
380 stars 380 forks source link

How to properly use the adaptive card designer control in spfx 1.16.1 #1825

Open JonoSuave opened 1 month ago

JonoSuave commented 1 month ago

Thank you for reporting an issue, suggesting an enhancement, or asking a question. We appreciate your feedback - to help the team understand your needs please complete the below template to ensure we have the details to help. Thanks!

Please check out the documentation to see if your question is already addressed there. This will help us ensure our documentation is up to date.

Category

[ ] Enhancement

[ ] Bug

[ x] Question

Version

spfx 1.16.1

Please specify what version of the library you are using: [ ] v3 If you are not using the latest release, please update and see if the issue is resolved before submitting an issue.

Question

I'm trying to update a previous solution from Angular to React. I've gotten pretty far but am now stuck on the Adaptive Card portion. I'm thinking I need to be referencing a different adaptive card node module, but would like guidance on which pnp control to pull from and how to properly convert it.

Observed Behavior

import as ACDesigner from "@pnp/spfx-controls-react/node_modules/adaptivecards-designer" doesn't appear to be the correct module to reference, nor is import as AC from "@pnp/spfx-controls-react/node_modules/adaptivecards".

Steps to Reproduce

Here's what my current AdaptiveCardIcon.tsx file looks:

import * as ACDesigner from "@pnp/spfx-controls-react/node_modules/adaptivecards-designer";
import * as AC from "@pnp/spfx-controls-react/node_modules/adaptivecards";
import * as ReactDOM from "react-dom";
import * as React from "react";
import { ActionButton } from "office-ui-fabric-react/lib/Button";
import { UserSearchService } from "../../services/UserSearchService/UserSearchService";

const internalRender = (renderReact: () => JSX.Element): HTMLElement => {
    const div = document.createElement("div");
    ReactDOM.render(renderReact(), div); // eslint-disable-line @microsoft/spfx/pair-react-dom-render-unmount
    return div;
};

export class AdaptiveCardIconPeer extends ACDesigner.TypedCardElementPeer<AdaptiveCardIcon> {
    public static readonly iconNameProperty = new ACDesigner.StringPropertyEditor(
        AC.Versions.v1_0,
        "iconName",
        "Icon Name"
    );

    public static readonly textProperty = new ACDesigner.StringPropertyEditor(
        AC.Versions.v1_0,
        "text",
        "Text",
        true
    );

    public static readonly urlProperty = new ACDesigner.StringPropertyEditor(
        AC.Versions.v1_0,
        "url",
        "URL",
        true
    );

    public static readonly formatAsPhoneProperty = new ACDesigner.BooleanPropertyEditor(
        AC.Versions.v1_0,
        "formatAsPhone",
        "Format as Phone Number",
        true
    );

    public populatePropertySheet(
        propertySheet: ACDesigner.PropertySheet,
        defaultCategory: string = "Action Link"
    ): void {
        super.populatePropertySheet(propertySheet, defaultCategory);
        propertySheet.add(defaultCategory, AdaptiveCardIconPeer.textProperty);
        propertySheet.add(defaultCategory, AdaptiveCardIconPeer.urlProperty);
        propertySheet.add(defaultCategory, AdaptiveCardIconPeer.iconNameProperty);
        propertySheet.add(defaultCategory, AdaptiveCardIconPeer.formatAsPhoneProperty);
    }
    public initializeCardElement(): void {
        //super.initializeCardElement();
        console.log(this);
        const el = this.cardElement;
        el.iconName = "Link";
    }
}

export class AdaptiveCardIcon extends AC.CardElement {
    static readonly JsonTypeName = "ActionLink";
    static readonly iconNameProperty = new AC.StringProperty(AC.Versions.v1_0, "iconName", true);
    static readonly textProperty = new AC.StringProperty(AC.Versions.v1_0, "text", true);
    static readonly urlProperty = new AC.StringProperty(AC.Versions.v1_0, "url", true);
    static readonly formatAsPhoneProperty = new AC.BoolProperty(
        AC.Versions.v1_0,
        "formatAsPhone",
        false
    );
    @AC.property(AdaptiveCardIcon.iconNameProperty)
    get iconName(): string {
        return this.getValue(AdaptiveCardIcon.iconNameProperty);
    }

    set iconName(value: string) {
        if (this.iconName !== value) {
            this.setValue(AdaptiveCardIcon.iconNameProperty, value);

            this.updateLayout();
        }
    }

    @AC.property(AdaptiveCardIcon.textProperty)
    get text(): string {
        return this.getValue(AdaptiveCardIcon.textProperty);
    }
    set text(value: string) {
        if (this.text !== value) {
            this.setValue(AdaptiveCardIcon.textProperty, value);
            this.updateLayout();
        }
    }

    @AC.property(AdaptiveCardIcon.formatAsPhoneProperty)
    get url(): string {
        return this.getValue(AdaptiveCardIcon.urlProperty);
    }
    set url(value: string) {
        if (this.url !== value) {
            this.setValue(AdaptiveCardIcon.urlProperty, value);
            this.updateLayout();
        }
    }

    @AC.property(AdaptiveCardIcon.formatAsPhoneProperty)
    get formatAsPhone(): boolean {
        return this.getValue(AdaptiveCardIcon.formatAsPhoneProperty);
    }
    set formatAsPhone(value: boolean) {
        if (this.formatAsPhone !== value) {
            this.setValue(AdaptiveCardIcon.formatAsPhoneProperty, value);
            this.updateLayout();
        }
    }
    protected internalRender(): HTMLElement {
        const text = this.formatAsPhone ? UserSearchService.formatPhoneNumber(this.text) : this.text;
        const control = () => (
            <div onClick={(ev) => ev.stopPropagation()}>
                <ActionButton
                    styles={{ root: { height: "auto" } }}
                    iconProps={{ iconName: this.iconName }}
                    text={text}
                    href={this.url}
                />
            </div>
        );
        const el = internalRender(control);
        return el;
    }

    getJsonTypeName(): string {
        return AdaptiveCardIcon.JsonTypeName;
    }
}

Here's my package.json:

{
  "name": "jt-sp-directory",
  "version": "0.0.1",
  "private": true,
  "engines": {
    "node": ">=16.13.0 <17.0.0"
  },
  "main": "lib/index.js",
  "scripts": {
    "build": "gulp bundle",
    "clean": "gulp clean",
    "test": "gulp test",
    "ship": "gulp clean && gulp --ship && gulp package-solution --ship",
    "serve": "gulp bundle --custom-serve --max_old_space_size=4096 && fast-serve"
  },
  "dependencies": {
    "@journeyteam/directory-extensions": "0.0.6",
    "@microsoft/microsoft-graph-types": "^2.26.0",
    "@microsoft/sp-client-base": "^1.0.0",
    "@microsoft/sp-component-base": "^1.16.1",
    "@microsoft/sp-core-library": "1.16.1",
    "@microsoft/sp-dynamic-data": "^1.16.1",
    "@microsoft/sp-http": "^1.16.1",
    "@microsoft/sp-loader": "^1.16.1",
    "@microsoft/sp-lodash-subset": "1.16.1",
    "@microsoft/sp-office-ui-fabric-core": "1.16.1",
    "@microsoft/sp-page-context": "1.16.1",
    "@microsoft/sp-property-pane": "1.16.1",
    "@microsoft/sp-webpart-base": "1.16.1",
    "@monaco-editor/loader": "^1.3.1",
    "@pnp/graph": "^3.11.0",
    "@pnp/sp": "^3.11.0",
    "@pnp/spfx-controls-react": "^3.12.0",
    "@pnp/spfx-property-controls": "^3.11.0",
    "@types/lodash": "^4.14.191",
    "handlebars": "^4.7.7",
    "libphonenumber-js": "^1.10.18",
    "lodash": "^4.17.21",
    "office-ui-fabric-react": "^7.204.0",
    "pnpm": "^9.1.4",
    "react": "17.0.1",
    "react-dom": "17.0.1",
    "tslib": "2.3.1"
  },
  "devDependencies": {
    "@microsoft/eslint-config-spfx": "1.16.1",
    "@microsoft/eslint-plugin-spfx": "1.16.1",
    "@microsoft/rush-stack-compiler-4.5": "0.2.2",
    "@microsoft/sp-build-web": "1.16.1",
    "@microsoft/sp-module-interfaces": "1.16.1",
    "@rushstack/eslint-config": "2.5.1",
    "@types/react": "17.0.45",
    "@types/react-dom": "17.0.17",
    "@types/webpack-env": "~1.15.2",
    "ajv": "^6.12.5",
    "eslint-plugin-react-hooks": "4.3.0",
    "gulp": "4.0.2",
    "spfx-fast-serve-helpers": "^1.16.1",
    "typescript": "4.5.5"
  },
  "volta": {
    "node": "16.19.0"
  }
}

Attached are the errors I'm getting. Screenshot 2024-05-30 at 6 07 07 PM Screenshot 2024-05-30 at 6 07 45 PM Screenshot 2024-05-30 at 6 07 57 PM

github-actions[bot] commented 1 month ago

Thank you for submitting your first issue to this project.