Giter Club home page Giter Club logo

next-admin's People

Contributors

baptadn avatar cregourd avatar doob9p avatar foyarash avatar github-actions[bot] avatar ogoldberg avatar tlenclos avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

next-admin's Issues

Only using DataTable

Hi, thanks for this awesome library!

Would it be possible to have an option to only export the data table so that it can be integrated with existing UIs a bit nicer? I'm interested in using this for an application that has an admin view as well as a normal view, but this would require the normal view to look identical to the styling of this library (ie: sidebar, logo, colors), and it would be amazing if we can directly place data tables in existing UIs.

Responsive layout for form

How about to implement a new option to make the form layout responsive, you could use grid and add tailwind breakpoints to set number of columns in the grid, example:

 edit: {  
    gridColumns: {
       sm: 1, // 640px
       md: 2, // 768px
       lg: 3, // 1024px
       xl: 4, // 1280px
    },
    display: ["field1", "field2", "field_n"]
}

Create a plugin system for inputs

To reduce core dependencies, allow plugin system for input.
A new plugin added should provide a format and an input, all fields containing that format should be that input.

Create other packages for specific internally developed inputs

Data validation

Today there is no server side validation except for Prisma exception that can get thrown when saving the data (for example when saving an incorrect type or a mandatory column).

This is not enough and the library should provide a way to add validation for a specific fields, for example if we want to validate an email.

Proposed API

import { z } from "zod";

const options: NextAdminOptions = {
  model: {
    user: {
      list: {
        fields: {
          email: {
            search: true,
            display: true,
            validate: email => z.string().email().parse(email),
          }
        }
      }
    }
  }
};

Errors should be displayed under each invalid fields.

Dynamic admin base path

Currently we use a constant to determine base path, this should be either automatic if possible or an option to pass to the library.

Showing related fields in a Select input

Showing related fields in a Select input

For example we have two tables Country and City, the City table has foreign key countryId,
In toString property we could specify a related field like: (city) => ${city.name} - ${city.country.name},

The same in the formatter property.

options.tsx

....
model: {
      City: {
         title: "Cities",
         toString: (city) => `${city.name} (${city.country.name})`,
         list: {
            display: ["name", "country"],
            fields: {
               country: {
                  formatter: (country) => {
                     return <strong>{country?.name}</strong>;
                  },
               }
            }         
         },
         edit: {
            display: ["name", "latitude", "longitude", "country"]   
         }
      },
}

Columns can be formatted

Add the possibility of adding a function to fields in the options for formatting columns:

model: {
  user: {
    list: {
      fields: {
        id: {
          formatColumn: (id) => id
        }
      }
    }
  }
}

The function must be typed, using the field type

A table can't show Decimal fields

A table can't show Decimal fields (latitude, longitude) - MySQL
I'm getting warning in console:

Warning: Only plain objects can be passed to Client Components from Server Components. Decimal objects are not supported.
  {id: ..., name: ..., country: ..., latitude: Decimal}

Model:

model City {
    id        Int     @id @default(autoincrement())
    name      String
    latitude  Decimal @db.Decimal(10, 8)
    longitude Decimal @db.Decimal(10, 8)
    countryId Int
    country   Country @relation(fields: [countryId], references: [id])
}

Formatting relationships in columns

Linked to ticket #14

Provide for relationships to be able to format the linked object, not just the id.
In One-to-Many relationships, the side carrying the relationship doesn't need to display the link (usually the id) but the object, so that it can be formatted.

The type of the formatColumn function must be overloaded to tolerate objects of type Collection.

Delete the fields carrying the relationship to display only the relationship to the object

In the example :

model Post {
  author User @relation("author", fields: [authorId], references: [id])
  authorId Int
}

Remove from the json-schema the authorId field for the formatted version of the author object, if there is no formatting function return only the id

Explore the possibility of Prisma extensions: https://www.prisma.io/docs/concepts/components/prisma-client/client-extensions/model#example. This would avoid having to modify the schema manually

File upload

A user should be able to use a file input, handle upload and return a blob or file to save in the form.

Update/Create doesn't work when on form present Select for relation field

I'm using MySQL. After update (3.2.0) update/create doesn't work when on form present Select input for related field

It's works only if I remove "class" field from edit.display array

When I'm editing a record and didn't choose any value in Select input ("class" field), I'm getting error:

Invalid prisma.timetable.update()invocation: { where: { id: "clradekj60001uyo099jqa6vw" }, data: { start: "2024-01-08T07:00:00.000Z", end: "2024-01-08T08:30:00.000Z", class: { disconnect: true, ~~~~~~~~~~ ? create?: ClassCreateWithoutTimetableInput | ClassUncheckedCreateWithoutTimetableInput, ? connectOrCreate?: ClassCreateOrConnectWithoutTimetableInput, ? upsert?: ClassUpsertWithoutTimetableInput, ? connect?: ClassWhereUniqueInput, ? update?: ClassUpdateToOneWithWhereWithoutTimetableInput | ClassUpdateWithoutTimetableInput | ClassUncheckedUpdateWithoutTimetableInput } } } Unknown argumentdisconnect. Did you mean connect? Available options are marked with ?.

If I chose some value in Select input and try to save record, I'm getting another error:

Unhandled Runtime Error
Error: Unexpected token 'c', "cvb9xc7v8b" is not valid JSON

 ⨯ node_modules\@premieroctet\next-admin\dist\utils\server.js (292:56) @ parse
 ⨯ SyntaxError: Unexpected token 'c', "cvb9xc7v8b" is not valid JSON

options,tsx:

   model: {
      Timetable: { 
         list: {
            display: ["start", "end", "class"],
            fields: {                
               "class": {
                  formatter: (classObj) => {
                     return <strong>{classObj.name}</strong>;
                  },                  
               }             
            }
         },
         edit: {
            display: ["id", "start", "end", "class"]
         }
      },
   },

prisma

model Timetable {
    id      String   @id @default(cuid())
    start   DateTime
    end     DateTime
    note    String?
    classId String
    class   Class    @relation(fields: [classId], references: [id], onDelete: Cascade)

    @@index([classId], name: "idx_classId")
}

model Class {
    id              String        @id @default(cuid())
    name            String
    schoolAddreesId String
    schoolAddress   SchoolAddress @relation(fields: [schoolAddreesId], references: [id])
    Timetable       Timetable[]
    User            User[]

    @@index([schoolAddreesId], name: "idx_class_schoolAddressId")
}

Custom name for fields

Looks like there is no ability to customize names for columns in a table and labels of fields in a form.

Include the possibility of overriding inputs

Include the possibility of overriding inputs, for example if you just want to display the date instead of a disabled input, or an image instead of a text field... etc.

 const options : NextAdminOptions = {
    modelOptions : {
      user : {
        toString : (user : User) => `${user.name} (${user.email})`,
        list : {
          fields : {
            id : {
              search : true,
            },
            name : {
              search : true,
            },
            email : {
              search : true,
            },
            role : {},
            createdAt : {
              formatter : (createdAt) => user.createdAt.toLocaleDateString(),
            }
          }
        },
        edit : {
          fields : {
            createdAt : {
              input : (createdAt) => {
                return <input type="date" value={ createdAt.toString() } />
              }
            }
          }
        }
      },
    }
  } ;

Enum support

Does next-admin supports enums?

enum Sex {
man
woman
}

Delete button doesn't work

I'm using MySQL.

When I'm trying to delete record, I'm getting message in console of next.js app:
deleteAction not provided. Delete buttons will have no effect

Allow multiple prisma clients

First of all, great work on making this next admin, works really good.

I was wondering if it's possible to handle more than one prisma client? Right now we have multiple prisma clients that connect to different dbs, and would be really nice to be able to spin up different next admins with these connections within the same next project (so /prisma-1 would use 1 connection + types and /prisma-2 would use another one and so on).

Is this something feasible?
Thanks in advance

Improve the release process

Currently the release process is a bit messy, since merging a PR on main triggers a deploy on the production documentation and example.

The idea would be the following:

  • when merging a non-release PR on main, we deploy the example and documentation in a beta environment
  • when merging a release PR on main, we deploy the example and documentation in the production environment

Edit page crash if no field in set for display

Given the following edit configuration:

edit: {
          fields: {
            id: {
              display: false,
            },
            email: {
              display: false,
            },
            name: {
              display: false,
            },
          },
        },

Current behavior

Accessing the ressource edit form makes the app crash with a Prisma error because the select statement is empty

Expected behavior

Accessing the ressource edit form should not crash and we should see at least one field, for example the id

Hide models

Based on the template field system, add the ability to hide templates:

  • If no configuration is present, show all models
  • If there is a configuration about a template, show only configured templates

Note that if the user wants to display a template without making a configuration, he can enter the template as follows:
session: {}

format: "textarea" - looks bad

Hi.

Can you check textarea in form, something wrong with styles.

example:

      ModelName: {
         edit: {
            display: ["name", "info"],
            fields: {
               info: {
                  format: "textarea",
               }
            } 
         }
      },

image

Translation

Is there a way to translate the terms used in the GUI?

Error handling in handler.upload

Looks like there is not way to show an user that uploading of file was failed. I'm talking about this example:

          avatar: {
            format: "file",
            handler: {
              /*
               * Include your own upload handler here,
               * for example you can upload the file to an S3 bucket.
               * Make sure to return a string.
               */
              upload: async (file: Buffer) => {
                return "https://www.gravatar.com/avatar/00000000000000000000000000000000";
              },
            },

Changing order of fields on a form

A form for creating and updating does not keeping order of fields which were specified in edit.display property

     edit: {
        display: [
           "id",
           "field1",
           "field2",
        ],

Bug in search

I'm using MySQL and I'm getting error when I try to search.

Invalid prisma.user.findMany()invocation: { select: { id: true, name: true, role: true, dob: true, city: true, slug: true }, where: { OR: [ { name: { contains: "pizza", mode: "insensitive" } }, { email: { contains: "pizza", mode: "insensitive" } } ] }, orderBy: {}, skip: 0, take: 10 } Unknown argumentmode. Did you mean lte? Available options are marked with ?.

Looks like the problem in: mode: "insensitive"

According prisma doc
MySQL uses case-insensitive collation by default. Therefore, filtering with Prisma Client and MySQL is case-insensitive by default.
mode: 'insensitive' property is not required and therefore not available in the generated Prisma Client API.

One to many relations should be ignored in lists

Given the following list fields config

list: {
          fields: {
            id: {
              search: true,
              display: true,
            },
            name: {
              search: true,
              display: true,
            },
            team: {
              search: true,
              display: true,
            },
            accounts: {
              display: true,
            },
          },
        },

Current behavior

The list page is correctly working, however it is giving a Prisma error because it tries to count team, which is a One-to-Many relation, therefore not possible to apply a count on it.

Expected behavior

The One-to-Many relation should simply be ignored, eventually a warning should pop in dev environment. But it should be removed from the select statement for the count.

ID field mandatory in fields list configuration

Given the following model config

User: {
        toString: (user) => user.name!,
        list: {
          fields: {
            name: {
              search: true,
              display: true,
            },
            team: {
              search: true,
              display: true,
            },
            accounts: {
              display: true,
            },
          },
        },
      },

Expected behavior

Clicking on a row in the users list should navigate to the user edition form

Current behavior

Navigation leads to an error as is navigates to an undefined id. The URL we navigate to is http://localhost:3000/admin/User/undefined.

Adding id in the fields list fixes the issue

Html editor fields

Possibility of using some html editor library (Rich text editor) in fields configuration

Custom pages

Add the possibility to add pages to the menu and assign components to them.

image

Can't create a record if optional Select field (related) is empty

Can't create a record if optional Select field (related) on a form is empty.
I'm getting error:
Invalid prisma.school.create()invocation: { data: { name: "test name", info: "test info", slug: "test-slug", ownerUser: false ~~~~~ } } ArgumentownerUser: Invalid value provided. Expected UserCreateNestedOneWithoutSchoolInput, provided Boolean.

At the same time I can update a record when Select field is empty.

Linked comboboxes

There is pretty common pattern, when we have to select values sequentially in comboboxes, for example:
Country > State > City
or
Category > Subcategory

then save into the table last chosen item (id of a city or subcategory)

So what about to make it possible via options.ts, something like this in display section:

model: {
   user: {
         edit: {  
            display: [               
               "name",
               "email",
               ["Country", "State", "City"]          
            ],
            fields: {
               Country: {
                  formatter: (Country) => {
                     return <strong>{Country.name}</strong>;
                  },                     
              },      
               State: {
                  formatter: (State) => {
                     return <strong>{State.name}</strong>;
                  },                     
              },  
               City: {
                  formatter: (City) => {
                     return <strong>{City.name}</strong>;
                  },                     
              },      
   }
}

Search UUID fields

Hi, first of all thank you for all the work you've put into this.

I'm having trouble with the search bar since some of the fields I have are UUIDs in a Postgres database and the contains keyword is incompatible with that native type. Is there a way to be able to search through these fields so far? I'm using the latest version 3.2.6.

Invalid `prisma.user.findMany()` invocation:

{
  select: undefined,
  where: {
    OR: [
      {
        id: {
          contains: "A",
          mode: "insensitive"
        }
      },
      {
        externalUserId: {
          contains: "A",
          mode: "insensitive"
        }
      },
      {
        personId: {
          contains: "A",
          mode: "insensitive"
        }
      }
    ]
  },
  orderBy: {},
  skip: 0,
  take: 10
}

Unknown argument `contains`. Available options are marked with ?.
image

This is what my Prisma schema looks like:

model User {
  id        String     @id @default(uuid()) @db.Uuid
  status    UserStatus @default(CREATED)
  externalUserId String     @unique @map("external_user_id")
  personId  String     @map("person_id") @db.Uuid
  createdAt DateTime   @default(now()) @map("created_at") @db.Timestamptz
  updatedAt DateTime   @updatedAt @map("updated_at") @db.Timestamptz

  person              Person                      @relation(fields: [personId], references: [id])
 
  @@map("user")
}

And this is the table definition:

CREATE TABLE "user" (
    "id" UUID NOT NULL,
    "status" "user_status_enum" NOT NULL DEFAULT 'active',
    "external_user_id" TEXT NOT NULL,
    "person_id" UUID NOT NULL,
    "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updated_at" TIMESTAMPTZ NOT NULL,

    CONSTRAINT "user_pkey" PRIMARY KEY ("id")
);

Also, if I specify which fields to search through (i.e. name) I get console logs of SQL queries containing a WHERE 1=0 clause with no results. Any idea what could be the source of this problem?

model: {
    User: {
      list: {
        display: ["id", "status", "externalUserId", "personId", "createdAt", "updatedAt"],
        search: ["status"],
      },
      edit: {
        display: ['id', 'status', 'personId', 'createdAt'],
      },
    },
}
> prisma:query SELECT "public"."user"."id", "public"."user"."status"::text, "public"."user"."external_user_id", "public"."user"."person_id", "public"."user"."created_at", "public"."user"."updated_at" FROM "public"."user" WHERE 1=0 ORDER BY "public"."user"."id" ASC LIMIT $1 OFFSET $2
> prisma:query SELECT COUNT(*) FROM (SELECT "public"."user"."id" FROM "public"."user" WHERE 1=0 OFFSET $1) AS "sub"
image

Thank you very much.

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.