Coder Social home page Coder Social logo

ellucian-developer / experience-extension-hooks Goto Github PK

View Code? Open in Web Editor NEW
1.0 3.0 0.0 99 KB

This package provides useful hooks to access the Extension properties using React Contexts

License: Apache License 2.0

JavaScript 100.00%
ellucian experience experience-toolkit toolkit hooks react

experience-extension-hooks's Introduction

Experience Extension Hooks

This package provides useful hooks to access the Extension properties using React Contexts

The several hooks provide logical groups of the properties passed by Experience to an extension as properties.

Using these hooks avoids having to pass Extension properties through layers of React Components. To use any of these hooks add code to your Extension component (at any level) like the following:

import { useCardInfo, useCache, useData } from '@ellucian/experience-extension-hooks';

...

    const cache = useCache();
    const { getExtensionJwt } = useData();
    const { configuration: {myConfigurationKey = ''} } = useCardInfo();

Installation

npm install ellucian-developer/experience-extension-hooks

Edit webpack.config.js

You will need to add this to your webpack.config.js in the "For advanced scenarios ..."

    // this is needed for @ellucian/experience-extension-hooks
    webpackConfig.module.rules.forEach( rule => {
        if (rule.loader === 'babel-loader') {
            rule.exclude = /node_modules\/(?!(@ellucian)\/)/
        }
    })

Use babel.config.js

Rename .babelrc to babel.config.js and convert to JS syntax so that is looks like:

module.exports = {
    presets: [
        '@babel/preset-env',
        '@babel/preset-react'
    ],
    plugins: [
        '@babel/plugin-proposal-class-properties',
        '@babel/transform-runtime'
    ],
    env: {
        test: {
            plugins: [
                'rewire'
            ]
        }
    }
}

The Hooks

Universal hooks

List of hooks available for all Extension component types

note: Ellucian has an internal component type of Admin which is not available to customer developers

  • useCache

const { clear, getItem, removeItem, storeItem } = useCache();
  • useData

const { getEthosQuery, getEthosQueryResourceVersions, getExtensionJwt } = useData();

getEthosQuery and _getEthosQueryResourceVersions are only used for Card and Page components

  • useExperienceInfo

const { version } = useExperienceInfo();

version is Dashboard version or Setup version for Admin components

  • useExtensionControl

const {
    navigateToPage,
    setErrorMessage,
    setExitPrompt,
    setLoadingStatus,
    setPageTitle,
    setPageToolbar
    setPreventRemove,
    setPreventRemoveMessage
} = useExtensionControl();

setExitPrompt, setPageTitle, and setPageToolbar are only used for Page components

setPreventRemove, and setPreventRemoveMessageare only used for Card components

  • useExtensionInfo

const { basePath, configuration, extensionId, type } = useExtensionInfo();

basePath is only used for Page and Admin components

configuration is only used for Page to convey extension configuration. Note for cards, the extension configuration is combined with the card configuration in useCardInfo.

  • useUserInfo

const { firstName, locale, roles, tenantId } = useUserInfo();
  • useThemeInfo

const { dashboardBackgroundColor, primaryColor, secondaryColor, ctaColors } = useThemeInfo();

Card hooks

  • useCardInfo

const { cardId, configuration } = useCardInfo()

Usage

The context needs to be wired into each card and page. To do this add similar code to each card and page as follows.

import { ExtensionProvider } from '@ellucian/experience-extension-hooks';

...

export default function CardOrPageWithProviders(props) {
    return (
        <ExtensionProvider {...props}>
            <MyCardOrPageComponent/>
        </ExtensionProvider>
    )
}

Copyright 2021โ€“2022 Ellucian Company L.P. and its affiliates.

experience-extension-hooks's People

Contributors

ellucianbret avatar kishba avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar

experience-extension-hooks's Issues

Question: Is there a better way to get extension-wide configuration in a way that works on both cards and pages?

I'm trying to write sub-components and hooks that can be used the same way between cards and pages. One potential use case is our "Wait List" card that we want to include on our "Registration" page without duplicating code.

This hooks project has already facilitated a lot of what we want to do, but we ran into an issue trying to access our extension-wide URL configuration values.

Below is our current workaround which feels a little cumbersome. Is there something in this hooks project that would make this unnecessary? Or could you recommend a more simple way to get configuration?

  // useExtensionInfo.configuration will only be defined on pages
  // don't let the awesomeness of useExtensionControl in the readme lead to assumptions about useExtensionInfo() :)
  // https://github.com/ellucian-developer/experience-extension-hooks
  const { configuration: extensionConfiguration } = useExtensionInfo();
  const { configuration: cardConfiguration } = useCardInfo();
  const configuration =
    typeof extensionConfiguration === "undefined"
      ? cardConfiguration
      : extensionConfiguration;

  const selfServiceBaseURL =
    configuration?.extensionSelfServiceBaseURL ||
    "https://self-service.schoolcraft.edu/Student";

Error when adding ExtensionProvider to existing page with version 1.0.4

Like I mentioned in my previous issue, I'm trying to take advantage of this project on a page for the first time. I was struggling in our primary extension, so I created a new extension using SDK v3.3.0, added experience-extension-hooks v1.0.4, and I am getting the same error when I try to wrap my page component with ExtensionProvider.

(My cards are working just fine.)

Here is what my src/page/index.jsx looks like:

import { ExtensionProvider } from "@ellucian/experience-extension-hooks";
// A few additional imports not shown...but note that I am not even importing/using any of the hooks yet!

const PageWrapper = () => {
  return <div>Simple page</div>;
};

function CardOrPageWithProviders(props) {
  return (
    <ExtensionProvider {...props}>
      <PageWrapper />
    </ExtensionProvider>
  );
}

export default CardOrPageWithProviders;

Here's the browser console error with devSharedModules enabled:

Uncaught TypeError: experienceInfo is undefined
    contextValue webpack-internal:///./node_modules/@ellucian/experience-extension-hooks/src/components/extension-context.js:52
    mountMemo https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:15809
    useMemo https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:16031
    useMemo https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:1682
    ExtensionProvider webpack-internal:///./node_modules/@ellucian/experience-extension-hooks/src/components/extension-context.js:41
    renderWithHooks https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:15248
    mountIndeterminateComponent https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:17482
    beginWork$1 https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:18626
    callCallback https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:343
    invokeGuardedCallbackDev https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:393
    invokeGuardedCallback https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:450
    beginWork$$1 https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:23357
    performUnitOfWork https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:22348
    workLoopSync https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:22325
    renderRoot https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:22018
    scheduleUpdateOnFiber https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:21559
    scheduleRootUpdate https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:24459
    updateContainerAtExpirationTime https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:24487
    updateContainer https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:24576
    legacyRenderSubtreeIntoContainer https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:25103
    unbatchedUpdates https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:21827
    legacyRenderSubtreeIntoContainer https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:25102
    render https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js line 68 > Function:25182
    O https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:108
    Oi https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:84
    Tl https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:84
    unstable_runWithPriority https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:92
    pa https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:84
    Ol https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:84
    Cl https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:84
    j https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:92
    z https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:92
    O https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:92
    EventHandlerNonNull* https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:92
    n https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    <anonymous> https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:84
    n https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    <anonymous> https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:84
    n https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    <anonymous> https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:21
    n https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    <anonymous> https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:63
    n https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    <anonymous> https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:68
    n https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    <anonymous> https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:30
    n https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    <anonymous> https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:76
    n https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    <anonymous> https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:1
    n https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    <anonymous> https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:76
    n https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    <anonymous> https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:76
    n https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    <anonymous> https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:23
    n https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    <anonymous> https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:76
    n https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    <anonymous> https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:68
    n https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    <anonymous> https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:76
    n https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    <anonymous> https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:68
    n https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    <anonymous> https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:68
    n https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    c https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    a https://experience-test.elluciancloud.com/assets/js/manifest-aca137e1e78596f02a82.js:1
    <anonymous> https://experience-test.elluciancloud.com/assets/js/async-browser-c232268f0399f660d05e.js:1

Is "mergedConfiguration" the intended property name in the useExtensionInfo hook?

I'm sorry for not trying this change earlier, but I am finally trying out the merged card/page configuration in one of my child components. I'm getting an error that configuration is undefined when I use this code from the README:

const { basePath, configuration, extensionId, type } = useExtensionInfo();

Here are the first few lines of the error in my browser console (with the unadvertised devSharedModules mode enabled):

error: message: configuration is undefined stack:
ChildComponent@webpack-internal:///./src/components/ChildComponent.jsx:43:23
...

When I use the React dev tools, it looks like this property is named mergedConfiguration rather than configuration. Is this intended?

2021-08-11-extensionInfo-mergedConfiguration-vs-configuration

If this is the intended name, I think a README update is in order. For now, I'm using this to rename the property:

  const { mergedConfiguration: configuration } = useExtensionInfo();

Thanks,
Brandon

Error building: Module parse failed: Unexpected token

I tried adding this hooks project to a new extension. When I start the project or npm run build-dev I get the following error:

ERROR in ./node_modules/@ellucian/experience-extension-hooks/src/components/extension-context.js 75:8
Module parse failed: Unexpected token (75:8)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| 
|     return (
>         <ExtensionContext.Provider value = { contextValue } >
|             { children }
|         </ExtensionContext.Provider>
 @ ./node_modules/@ellucian/experience-extension-hooks/index.js 1:0-11:44 1:0-11:44 1:0-11:44 1:0-11:44 1:0-11:44 1:0-11:44 1:0-11:44 1:0-11:44 1:0-11:44 1:0-11:44
 @ ./src/cards/CacheCard.jsx 10:0-73 112:42-59

This is with an existing extension as well as with a brand new extension generated with this command:

npx -p https://cdn.elluciancloud.com/assets/SDK/latest/ellucian-create-experience-extension-latest.tgz create-experience-extension name-of-extension

Since I don't have the @ellucian package registry, I installed this package from GitHub:

npm install https://github.com/ellucian-developer/experience-extension-hooks

The bottom of my CacheCard.jsx looks like this:

function CardOrPageWithProviders(props) {
    return (
        <ExtensionProvider {...props}>
            <CacheCard/>
        </ExtensionProvider>
    )
}

export default withIntl(withStyles(styles)(CardOrPageWithProviders));

Any ideas what I might need to change to get this to build? :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.