Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plugin does not work from nextjs v14.1.2 and onwards #4

Open
arnoBruynseels opened this issue Mar 26, 2024 · 11 comments
Open

Plugin does not work from nextjs v14.1.2 and onwards #4

arnoBruynseels opened this issue Mar 26, 2024 · 11 comments

Comments

@arnoBruynseels
Copy link

The plugin works perfectly on nextjs v14.1.1 but once you install nextjs v14.1.2 everything breaks.

Nextjs complains that I need to use the 'use client' directive for the external component library I added to the plugin config.

Any fixes?

@coder-xiaotian
Copy link
Owner

coder-xiaotian commented Mar 26, 2024

The plugin works perfectly on nextjs v14.1.1 but once you install nextjs v14.1.2 everything breaks.

Nextjs complains that I need to use the 'use client' directive for the external component library I added to the plugin config.

Any fixes?

I did not reproduce this issue in my repo used nextjsv14.1.4. Please provide your code to better reproduce the issue.

@arnoBruynseels
Copy link
Author

The plugin works perfectly on nextjs v14.1.1 but once you install nextjs v14.1.2 everything breaks.
Nextjs complains that I need to use the 'use client' directive for the external component library I added to the plugin config.
Any fixes?

I did not reproduce this issue in my repo used nextjsv14.1.4. Please provide your code to better reproduce the issue.

In your provided repo you don't have any swcPlugins defined.

This is how we use the plugin:

image

@coder-xiaotian
Copy link
Owner

The plugin works perfectly on nextjs v14.1.1 but once you install nextjs v14.1.2 everything breaks.
Nextjs complains that I need to use the 'use client' directive for the external component library I added to the plugin config.
Any fixes?

I did not reproduce this issue in my repo used nextjsv14.1.4. Please provide your code to better reproduce the issue.

In your provided repo you don't have any swcPlugins defined.

This is how we use the plugin:

image

I can start success in my repo with antd. I think it's probably an issue with the directory structure of your component library. The export directory structure of antd is as follows:
image
I can't find @spot/ui-components in npm. Please provide more information about it. And you can provide the error logs.

@tjones4701
Copy link

Hey, this no longer works with next 14.2.0, any chance of a fix for this?
: failed to run Wasm plugin transform. Please ensure the version of swc_core used by the plugin is compatible with the host runtime.

@coder-xiaotian
Copy link
Owner

Hey, this no longer works with next 14.2.0, any chance of a fix for this? : failed to run Wasm plugin transform. Please ensure the version of swc_core used by the plugin is compatible with the host runtime.

I get it. What is your OS version useing.

@coder-xiaotian
Copy link
Owner

Hey, this no longer works with next 14.2.0, any chance of a fix for this?嘿,这不再适用于下一个 14.2.0,有修复这个问题的机会吗? : failed to run Wasm plugin transform. Please ensure the version of swc_core used by the plugin is compatible with the host runtime.:无法运行 Wasm 插件转换。请确保插件使用的 swc_core 版本与主机运行时兼容。

I fixed it. You can update use-client to 1.2.0.

@arnoBruynseels
Copy link
Author

Hi it's me again.

I'm trying to up our Nextjs version from 14.1.1 to to lastest (14.2.6).

Steps I took:

  1. Install Nextjs version 14.2.6
  2. Install use-client version 1.2.0
  3. Applied following config:

image

NOTE: all the @spot packages are private internal repositories. We create our own component library. This component library is build using React and Vite where all components are exported in an index.js file

Below is what it looks like:

image

  1. Run the Nextjs application
  2. Following error occurs:

image

Where does it go wrong?
Did we implement or use this package wrong?
Did we implement or expose our UI library the wrong way?

Please help, we can't seem to find the source of the problem.

Thanks!

@coder-xiaotian
Copy link
Owner

Hi it's me again.

I'm trying to up our Nextjs version from 14.1.1 to to lastest (14.2.6).

Steps I took:

  1. Install Nextjs version 14.2.6
  2. Install use-client version 1.2.0
  3. Applied following config:

image

NOTE: all the @spot packages are private internal repositories. We create our own component library. This component library is build using React and Vite where all components are exported in an index.js file

Below is what it looks like:

image

  1. Run the Nextjs application
  2. Following error occurs:

image

Where does it go wrong? Did we implement or use this package wrong? Did we implement or expose our UI library the wrong way?

Please help, we can't seem to find the source of the problem.

Thanks!

Please provide the [local]/users page code and this file code.
image

@arnoBruynseels
Copy link
Author

``> > Hi it's me again.

I'm trying to up our Nextjs version from 14.1.1 to to lastest (14.2.6).
Steps I took:

  1. Install Nextjs version 14.2.6
  2. Install use-client version 1.2.0
  3. Applied following config:

image
NOTE: all the @spot packages are private internal repositories. We create our own component library. This component library is build using React and Vite where all components are exported in an index.js file
Below is what it looks like:
image

  1. Run the Nextjs application
  2. Following error occurs:

image
Where does it go wrong? Did we implement or use this package wrong? Did we implement or expose our UI library the wrong way?
Please help, we can't seem to find the source of the problem.
Thanks!

Please provide the [local]/users page code and this file code. image

[local]/users page code:

image

UserPageContent code:

image

'use client';

import { AgGrid, BooleanText, agGridCssClasses } from '@spot/ui-components';
import type { AgGridProps } from '@spot/ui-components';
import type { ICellRendererParams, RowClassParams } from 'ag-grid-community';
import { useTranslations } from 'next-intl';
import type { ReactNode } from 'react';
import { useCallback, useMemo } from 'react';
import { useState } from 'react';

import UserModalContent from '@/app/[locale]/users/_components/users-page-content/components/user-modal-content/UserModalContent';
import UserModalFooter from '@/app/[locale]/users/_components/users-page-content/components/user-modal-footer/UserModalFooter';
import type { UserModalContentTabKey } from '@/app/[locale]/users/_components/users-page-content/components/user-modal-header/UserModalHeader';
import UserModalHeader from '@/app/[locale]/users/_components/users-page-content/components/user-modal-header/UserModalHeader';
import type { User } from '@/generated/graphql/types';
import { useSelector } from '@/lib/redux/redux-store';
import { selectUsersData } from '@/lib/redux/slices/user-management/selectors';

const UsersPageContent = () => {
  const t = useTranslations();

  const users = useSelector(selectUsersData);

  const [modalActiveTabKey, setModalActiveTabKey] = useState<UserModalContentTabKey>('generalTab');

  const modalTitle = useCallback(
    (selectedRecord: unknown): ReactNode => {
      return (
        <UserModalHeader
          user={selectedRecord as User}
          selectedTabKey={modalActiveTabKey}
          setSelectedTabKey={setModalActiveTabKey}
        />
      );
    },
    [modalActiveTabKey],
  );

  const modalContent = useCallback(
    (selectedRecord: unknown): ReactNode => {
      return <UserModalContent user={selectedRecord as User} selectedTabKey={modalActiveTabKey} />;
    },
    [modalActiveTabKey],
  );

  const modalFooter = useCallback(
    (selectedRecord: unknown): ReactNode => {
      return <UserModalFooter isCopyVisible={modalActiveTabKey === 'debugTab'} user={selectedRecord as User} />;
    },
    [modalActiveTabKey],
  );

  const columnDefs: AgGridProps['columnDefs'] = useMemo(() => {
    return [
      {
        headerName: t('application-common.user'),
        children: [
          {
            field: 'user',
            headerName: t('application-common.userID'),
          },
          {
            field: 'firstName',
            headerName: t('application-common.firstName'),
          },
          {
            field: 'lastName',
            headerName: t('application-common.lastName'),
          },
          {
            field: 'email',
            headerName: t('application-common.email'),
          },
          {
            field: 'department',
            headerName: t('application-common.department'),
          },

          {
            field: 'organisation',
            headerName: t('application-common.organisation'),
          },
        ],
      },
      {
        headerName: t('application-common.privileges'),
        children: [
          {
            field: 'hasAccess',
            headerName: t('application-common.access'),
            cellRenderer: (params: ICellRendererParams) => {
              return (
                <BooleanText
                  value={params.value}
                  variant={params.value ? 'success' : 'danger'}
                  trueText="Normal"
                  falseText="Blocked"
                />
              );
            },
            filterValueGetter: (params) => {
              return params.data.hasAccess ? t('application-common.normal') : t('application-common.blocked');
            },
          },
          {
            field: 'isAdmin',
            headerName: t('application-common.admin'),
            cellRenderer: (params: ICellRendererParams) => {
              return <BooleanText value={params.value} variant={params.value ? 'success' : 'danger'} />;
            },
            filterValueGetter: (params) => {
              return params.data.isAdmin ? t('application-common.yes') : t('application-common.no');
            },
            minWidth: 115,
            columnGroupShow: 'open',
          },
          {
            field: 'isWyreUser',
            headerName: t('application-common.wyreUser'),
            cellRenderer: (params: ICellRendererParams) => {
              return <BooleanText value={params.value} variant={params.value ? 'success' : 'danger'} />;
            },
            filterValueGetter: (params) => {
              return params.data.isWyreUser ? t('application-common.yes') : t('application-common.no');
            },
            minWidth: 115,
            columnGroupShow: 'open',
          },
          {
            field: 'isBusinessExpert',
            headerName: t('application-common.businessExpert'),
            cellRenderer: (params: ICellRendererParams) => {
              return <BooleanText value={params.value} variant={params.value ? 'success' : 'danger'} />;
            },
            filterValueGetter: (params) => {
              return params.data.isBusinessExpert ? t('application-common.yes') : t('application-common.no');
            },
            minWidth: 115,
            columnGroupShow: 'open',
          },
        ],
      },
      {
        headerName: t('application-common.usage'),
        children: [
          {
            field: 'lastSeen',
            headerName: t('application-common.lastName'),
          },
          {
            field: 'firstSeen',
            headerName: t('application-common.firstSeen'),
            minWidth: 115,
            columnGroupShow: 'open',
          },
        ],
      },
    ];
  }, [t]);

  const getRowClass: AgGridProps['getRowClass'] = useCallback((params: RowClassParams) => {
    return params.data.hasAccess === false ? agGridCssClasses.DangerBackground : '';
  }, []);

  const defaultColDef: AgGridProps['defaultColDef'] = useMemo(() => {
    return {
      sortable: true,
      resizable: true,
      filter: true,
    };
  }, []);

  const onCloseLogic: AgGridProps['onCloseLogic'] = useCallback(() => {
    setModalActiveTabKey('generalTab');
  }, []);

  const dataViewModalConfig: AgGridProps['dataViewModalConfig'] = useMemo(() => {
    return {
      hasSlideTabs: true,
      title: modalTitle,
      customContent: modalContent,
      customFooter: modalFooter,
    };
  }, [modalContent, modalFooter, modalTitle]);

  const columnsState: AgGridProps['columnsState'] = useMemo(() => {
    return [
      {
        colId: 'lastSeen',
        sort: 'desc',
      },
    ];
  }, []);

  return (
    <AgGrid
      showRecordCount
      enableGlobalFilter
      enableDataViewModal
      rowData={users}
      columnDefs={columnDefs}
      getRowClass={getRowClass}
      defaultColDef={defaultColDef}
      onCloseLogic={onCloseLogic}
      dataViewModalConfig={dataViewModalConfig}
      columnsState={columnsState}
    />
  );
};

export default UsersPageContent;

TimestampRefreshButton code:

Transpiled & Compiled:

image

Actual Component code:

import type { ButtonProps } from '@lib/inputs/button/Button';
import Button from '@lib/inputs/button/Button';
import Icon from '@lib/utilities/icon/Icon';
import IntervalIndication from '@lib/utilities/timestamp-refresh-button/components/interval-indication/IntervalIndication';
import TimeIndication from '@lib/utilities/timestamp-refresh-button/components/time-indication/TimeIndication';
import clsx from 'clsx';
import { addWeeks, isAfter, isSameDay, isSameWeek, isTomorrow, isYesterday } from 'date-fns';
import type { Moment } from 'moment';
import type { CSSProperties, PropsWithChildren } from 'react';

import styles from './TimestampRefreshButton.module.css';

export interface TimestampRefreshButtonProps {
  /**
   * Optional styling
   */
  style?: CSSProperties;
  /**
   * Optional className
   */
  className?: string;
  /**
   * Optional buttonText
   */
  buttonText?: string;
  /**
   * Optional plainDateFormat
   */
  plainDateFormat?: boolean;
  /**
   * Optional intervalSeparator
   */
  intervalSeparator?: string;
  /**
   * Optional onClick
   */
  handleClick: ButtonProps['handleClick'];
  /**
   * Optional time
   */
  time?: Date | Moment | null;
  /**
   * Optional timeFormat
   */
  timeFormat?: string;
  /**
   * Optional timeTo
   */
  timeTo?: Date | Moment;
  /**
   * Optional timeToFormat
   */
  timeToFormat?: string;
}

/**
 * TimestampRefreshButton component
 */
const TimestampRefreshButton = ({
  style,
  className,
  buttonText = 'Refresh',
  plainDateFormat = false,
  intervalSeparator = ' ... ',
  handleClick,
  time = new Date(),
  timeFormat = 'yyyy-MM-dd HH:mm',
  timeTo,
  timeToFormat = 'yyyy-MM-dd HH:mm',
}: PropsWithChildren<TimestampRefreshButtonProps>) => {
  let validTime: Date | null = null;

  if (time) {
    validTime = time instanceof Date ? time : time.toDate();
  }

  const today = new Date();

  let validTimeTo = timeTo;

  let relativeTimeFormat = 'yyyy-MM-dd HH:mm';

  if (timeTo) {
    validTimeTo = timeTo instanceof Date ? timeTo : timeTo.toDate();
  }

  if (!plainDateFormat && validTime !== null) {
    if (isSameDay(today, validTime)) {
      relativeTimeFormat = "'Today' HH:mm";
    } else if (isTomorrow(validTime)) {
      relativeTimeFormat = "'Tomorrow' HH:mm";
    } else if (isSameWeek(addWeeks(today, 1), validTime)) {
      relativeTimeFormat = 'yyyy-MM-dd HH:mm';
    } else if (isSameWeek(addWeeks(today, -1), validTime)) {
      relativeTimeFormat = 'yyyy-MM-dd HH:mm';
    } else if (isYesterday(validTime)) {
      relativeTimeFormat = "'Yesterday' HH:mm";
    } else if (isAfter(validTime, addWeeks(today, 1))) {
      relativeTimeFormat = 'yyyy-MM-dd HH:mm';
    }
  }

  const renderTime = () => {
    if (validTime === null) {
      return null;
    }

    if (timeTo) {
      return (
        <IntervalIndication
          time={validTime}
          timeFormat={timeFormat}
          timeTo={validTimeTo as Date}
          timeToFormat={timeToFormat}
          intervalSeparator={intervalSeparator}
          plainDateFormat={plainDateFormat}
          relativeTimeFormat={relativeTimeFormat}
        />
      );
    }

    return (
      <TimeIndication
        time={validTime}
        timeFormat={timeFormat}
        plainDateFormat={plainDateFormat}
        relativeTimeFormat={relativeTimeFormat}
      />
    );
  };

  return (
    <div className={clsx(className, [styles.timestampRefreshButton])} style={style}>
      {renderTime()}
      <Button handleClick={handleClick} variant="success" size="extra-small" className={styles.refreshButton}>
        <Icon icon="cached" size={15} className={styles.refreshIcon} />
        {buttonText}
      </Button>
    </div>
  );
};

export default TimestampRefreshButton;

@coder-xiaotian
Copy link
Owner

@arnoBruynseels You can try these two ways.

  1. add "@lib/" to config like this include: ["@lib/", ...];
  2. you can change change the import way from @spot/ui-components, for example change import { AgGrid } from '@spot/ui-components' to import AgGrid from '@spot/ui-components/your-component-path'.

@arnoBruynseels
Copy link
Author

@arnoBruynseels You can try these two ways.

  1. add "@lib/" to config like this include: ["@lib/", ...];
  2. you can change change the import way from @spot/ui-components, for example change import { AgGrid } from '@spot/ui-components' to import AgGrid from '@spot/ui-components/your-component-path'.

Thanks, I will try this and keep you posted!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants