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

Provide a more explanatory example project #6

Open
humbkr opened this issue Oct 28, 2020 · 13 comments
Open

Provide a more explanatory example project #6

humbkr opened this issue Oct 28, 2020 · 13 comments

Comments

@humbkr
Copy link

humbkr commented Oct 28, 2020

Hi, thanks for your work.

I spent hours trying to customise a property in the list without any success, and I'd like some pointers.

My project uses

  • nest.js
  • typescript
  • adminBro

I'm following the docs to the letter.
In the configuration I added:

{ resource: styleModel, options: {
          properties: {
            parentId: {
              components: {
                list: AdminBro.bundle('./components/reference-in-list'),
              },
            }
          }
        } },

My ./components/reference-in-list is defined as the following:

import React from 'react'
import { InputGroup, Label } from '@admin-bro/design-system'
import { BasePropertyProps } from 'admin-bro'

const ReferenceInList: React.FC<BasePropertyProps> = (props) => {
  const { record, property } = props
  const value = record.params[property.name]

  return (
    <InputGroup>
      <Label>{property.name}</Label>
      {value}
    </InputGroup>
    )
}

export default ReferenceInList

All I got is an error:

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Is there any special configuration to add when using adminBro with nest.js?
There are no docs on your website for using your product with nest.js and the example-app is very basic.

@SimonB407
Copy link
Contributor

We have encountered this problem and I think it's not related to this plugin, but rather to AdminBro. Try changing component path from ./components/reference-in-list to path that goes back to main directory and then to component, for example: ../../../src/your/path/to/component/components/reference-in-list.

@humbkr
Copy link
Author

humbkr commented Oct 29, 2020

@SimonB407 Thanks for your help, but unfortunately it doesn't seem too work in my case :(

@wojtek-krysiak
Copy link
Contributor

@humbkr which versions (admin-bro and plugins), do you use?

@humbkr
Copy link
Author

humbkr commented Oct 29, 2020

"dependencies": {
    "@admin-bro/express": "^3.0.1",
    "@admin-bro/mongoose": "^1.0.2",
    "@admin-bro/nestjs": "^1.0.0",
    "@nestjs/common": "^7.0.0",
    "@nestjs/config": "^0.5.0",
    "@nestjs/core": "^7.0.0",
    "@nestjs/mongoose": "^7.0.2",
    "@nestjs/platform-express": "^7.0.0",
    "admin-bro": "^3.2.5",
    "class-transformer": "^0.3.1",
    "class-validator": "^0.12.2",
    "express": "^4.17.1",
    "express-formidable": "^1.2.0",
    "express-session": "^1.17.1",
    "mongoose": "^5.10.9",
    "reflect-metadata": "^0.1.13",
    "rimraf": "^3.0.2",
    "rxjs": "^6.5.4"
  },

@Celtian
Copy link

Celtian commented Dec 14, 2020

Hi, I would like to also see some example using some async chain like this:

import { AdminModule } from '@admin-bro/nestjs';
import { Database, Resource } from '@admin-bro/typeorm';
import { GraphqlService, TypeOrmService } from '@config';
import * as Models from '@models';
import { User } from '@models';
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ServeStaticModule } from '@nestjs/serve-static';
import { getRepositoryToken, TypeOrmModule } from '@nestjs/typeorm';
import AdminBro from 'admin-bro';
import { join } from 'path';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import * as Resolvers from './resolvers';

AdminBro.registerAdapter({ Database, Resource });

@Module({
  imports: [
    ServeStaticModule.forRoot({
      renderPath: '/',
      rootPath: join(__dirname, 'static'),
      exclude: ['/graphql', '/admin'],
      serveStaticOptions: {
        redirect: true
      }
    }),
    GraphQLModule.forRootAsync({
      useClass: GraphqlService
    }),
    TypeOrmModule.forRootAsync({
      useClass: TypeOrmService
    }),
    TypeOrmModule.forFeature([...Object.values(Models)]), // probably wrong
    AdminModule.createAdminAsync({
      imports: [TypeOrmModule.forFeature([...Object.values(Models)])],
      inject: [getRepositoryToken(User)], // not working
      useFactory: (adminModel: User) => ({
        adminBroOptions: {
          rootPath: '/admin',
          resources: [{ resource: adminModel }]
        }
      })
    })
  ],
  controllers: [AppController],
  providers: [...Object.values(Resolvers), AppService]
})
export class AppModule {}

If I am using async I am not able to use your package.

Thanks.

@maxpeterson
Copy link

We have encountered this problem and I think it's not related to this plugin, but rather to AdminBro. Try changing component path from ./components/reference-in-list to path that goes back to main directory and then to component, for example: ../../../src/your/path/to/component/components/reference-in-list.

Thanks @SimonB407 after spending an unbelievable amount of time trying to get a simple component to work this fixed the issue ...

  component: AdminBro.bundle('./components/company-index')

to

  component: AdminBro.bundle('../../src/admin-panel/components/company-index')

This is very unintuitive, especially when the first case "appears" to "build".

This is a great library, please find a way to include this in the documentation!

FYI: The error I got was

TypeError: Cannot read property 'createElement' of undefined

image

The origin was calling createElement on react_1.default which was undefiend.

My compiled js was:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = require("react");
const MyNewAction = (props) => {
    return (react_1.default.createElement("div", null, "Test"));
};
exports.default = MyNewAction;
//# sourceMappingURL=company-index.js.map

My typescript was:

import React from 'react';

const MyNewAction = (props) => {
  return (
    <div>Test</div>
  );
};

export default MyNewAction;

@maxpeterson
Copy link

maxpeterson commented Jan 29, 2021

After a bit more investigation I figured out why this wasn't woking and how to get it to work.

What I originally failed to realise is that AdminBro.bundle expects the uncompiled component (in my case the .tsx file). I will say that again as it is not what I expected:

AdminBro.bundle expects the uncompiled component files

By using component: AdminBro.bundle('./components/company-index') it was finding the files in the dist folder where the tsx has been compiled by nestjs / tsc into js - this resulting js is not compatible with AdminBro.bundle. It is trying to use the version of react from the server not the browser!

By using component: AdminBro.bundle('../../../src/components/company-index') it was finding the files in the src folder where the uncompiled tsx file can be found and can be compiled and bundled byAdminBro.bundle. This is fine on my local dev environment .... but not so good on the server (where src does not exist).

To fix this I had to setup nestjs to copy the tsx component files to the dist folder without compiling them, that way AdminBro.bundle can compile them and bundle them up correctly for use in the browser.

Here are the steps I followed to achieve this:

Update nest-cli.json compilerOptions.assets to copy the tsx component files from my admin-panel/components folder in src:

  "compilerOptions": {
    "assets": [
       "admin-panel/components/**"
    ]
  }

Updated tsconfig to exclude src/admin-panel/components (you need do this in tsconfig.build.json tsconfig.json depending on your setup )

 "exclude": [
    "src/admin-panel/components",
  ]

You also don't need "jsx": "react", in the tsconfig compilerOptions if you are not compiling any tsx files with nestjs,

Finally I updated my AdminBro.bundle paths to be relative (without ../../src as suggested by @SimonB407 - which although it didn’t work I would never have figured this out without this hint so thanks again)

            components: {
              show: AdminBro.bundle('./components/resource-list-link'),
            }

Hope this helps someone else.

@OoDeLally
Copy link

OoDeLally commented Mar 12, 2021

I didn't manage to make NestJS's asset feature work. It simply didn't copy anything.
So I ended up adding a script to create a symlink.

{
  "link-admin-components-assets": "ln -s $PWD/apps/server/src/admin-module/components $PWD/dist/apps/server/components"
}

and then

// __dirname = /path/to/myProject/dist/apps/server
components: {
          list: AdminBro.bundle(path.join(__dirname, './components/EnumArray')),
        },

@kevseroz
Copy link

Hi, I have same problem but my project uses
-express.js
-javascript
I'm not sure what to do. I really confused. Can you please help me, thank you!

@dklymenk
Copy link

dklymenk commented May 8, 2022

Thanks to @maxpeterson , I resolved the issue I had with user components not being bundled in prod build.

If anyone else is struggling with bundling of custom components in production, you can use my commit here as a reference.

If you're struggling with nestjs+adminjs setup in general, I guess, you can use my repo for reference too. It's not very clean and there is only one entity hooked up, but it should clear some things up, if you're struggling.

@dklymenk
Copy link

dklymenk commented May 8, 2022

Hi, I have same problem but my project uses -express.js -javascript I'm not sure what to do. I really confused. Can you please help me, thank you!

If you're using bare express.js (without any frameworks built on top if it), you should use https://github.com/SoftwareBrothers/adminjs-expressjs instead.

@zhjch05
Copy link

zhjch05 commented Jul 21, 2022

Thank you all of the above comments, I learned a lot from them (especially dklymenk's commit diff view) and here are some more steps I configured on my nestjs repo to get it work:

my nest-cli.json

"compilerOptions": {
    "assets": [
      {
        "include": "admin/components/*.tsx",
        "outDir": "dist/src"
      }
    ]
  }

I made this tweak to make sure the bundling matches the dir in dist

And I manually deleted .adminjs folder, otherwise sometimes it won't get overwritten and therefore the newly bundled component metadata is not added there, and causing some undefined errors when getting components.

@ahmadalfy
Copy link

Thanks to @maxpeterson this solved our problem in the latest version of Adminjs. This works as well with the new API

componentLoader.add('showImages', './components/images.show.tsx')

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

10 participants