├── .DS_Store ├── .gitignore ├── LICENSE ├── README.md ├── lerna.json ├── package.json └── packages ├── .DS_Store ├── ra-audit-log ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── ra-auth0 ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── ra-calendar ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── ra-editor ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── ra-firebase-auth ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── ra-firebase-provider ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── ra-form-layout ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── ra-language-spanish ├── .gitignore ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── ra-layout ├── .babelrc ├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── src │ ├── index.ts │ └── layout │ │ ├── components │ │ ├── collapsible-menu │ │ │ ├── index.tsx │ │ │ └── styles.ts │ │ ├── header │ │ │ ├── index.tsx │ │ │ └── styles.ts │ │ ├── nested-menu │ │ │ ├── index.tsx │ │ │ └── styles.ts │ │ ├── side-drawer │ │ │ ├── index.tsx │ │ │ └── styles.ts │ │ └── user-profile │ │ │ ├── index.tsx │ │ │ └── styles.ts │ │ ├── index.tsx │ │ └── styles.ts └── tsconfig.json ├── ra-ldap-auth ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── ra-messaging ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── ra-navigation ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── ra-notifications ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── ra-preferences ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── ra-rbac ├── .babelrc ├── README.md ├── package-lock.json ├── package.json ├── src │ ├── components │ │ ├── rbac-fields │ │ │ ├── index.tsx │ │ │ └── rbac-field.tsx │ │ ├── rbac-inputs │ │ │ ├── index.tsx │ │ │ └── rbac-input.tsx │ │ ├── rbac-provider │ │ │ └── index.tsx │ │ └── rbac-resource │ │ │ └── index.tsx │ ├── contexts │ │ └── rbac │ │ │ └── index.ts │ ├── hooks │ │ ├── use-get-can-activate.ts │ │ ├── use-is-create-or-edit.ts │ │ └── use-is-list-or-show.ts │ ├── index.ts │ └── types │ │ └── index.ts └── tsconfig.json ├── ra-realtime ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── ra-relationships ├── .babelrc ├── README.md ├── package-lock.json ├── package.json ├── src │ ├── components │ │ ├── many-to-many-reference-context-provider │ │ │ └── index.tsx │ │ ├── many-to-many-reference-field-view │ │ │ └── index.tsx │ │ ├── many-to-many-reference-field │ │ │ └── index.tsx │ │ └── many-to-many-reference-input │ │ │ └── index.tsx │ ├── contexts │ │ └── many-to-many │ │ │ └── index.ts │ ├── hooks │ │ ├── use-reference-many-to-many-field-controller.ts │ │ └── use-reference-many-to-many-input-controller.ts │ └── index.ts └── tsconfig.json ├── ra-search ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── ra-tour ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── ra-version ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ └── index.ts └── tsconfig.json └── storybook ├── .gitignore ├── .storybook ├── main.js ├── manager-head.html ├── preview-head.html └── preview.js ├── README.md ├── db.json ├── package-lock.json ├── package.json ├── src ├── components │ └── Layout │ │ └── index.tsx ├── menu.ts ├── pages │ └── Users │ │ ├── List │ │ └── index.tsx │ │ └── index.tsx ├── providers │ ├── authProvider.ts │ └── dataProvider.ts └── theme │ └── index.ts └── stories ├── ra-layout.stories.mdx └── ra-relationships.stories.mdx /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackBoxVision/react-admin-extensions/4c5a5dd31ae7bca5f6598e121a1f23e4b86dc195/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | pkg -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 BlackBox Vision 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RA Extensions 2 | 3 | At [BlackBox Vision](https://www.blackbox-vision.tech) we use a lot `React Admin` as a tool for building internal systems and back offices. 4 | 5 | We're pretty grateful for the work done behind `React Admin`. 6 | 7 | This repository contains some internal libraries that we've used in our projects and decided to release as a part of our `OSS initiative`. 8 | 9 | ## Packages 10 | 11 | We've packages to support different needs. 12 | 13 | ### UI/UX 14 | 15 | - [**RA Tour (WIP)**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-tour): Add support to guide new comers in your app. 16 | - [**RA Layout**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-layout): Add a custom Layout that really improves UX. 17 | - [**RA Search (WIP)**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-search): Add support for searching over all the entities. 18 | - [**RA Navigation (WIP)**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-navigation): Add support for improving navigation in your app. 19 | - [**RA Preferences (WIP)**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-preferences): Add support for persisting user preferences. 20 | 21 | ### Forms 22 | 23 | - [**RA Form Layout (WIP)**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-form-layout): Add support for different form variants. 24 | 25 | ### Entities 26 | 27 | - [**RA Version (WIP)**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-version): Add support for versioning entities and see the history of changes. 28 | - [**RA Relationships (WIP)**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-relationships): Add support for many-to-many relationships through entities. 29 | 30 | ### Realtime 31 | 32 | - [**RA Realtime (WIP)**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-realtime): Add support for realtime data. 33 | - [**RA Messaging (WIP)**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-messaging): Add support for an internal chat in your app. 34 | - [**RA Notifications (WIP)**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-notifications): Add support for push notifications. 35 | 36 | ### Input/Fields 37 | 38 | - [**RA Editor Input (WIP)**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-editor): Add support for a block-based text editor. 39 | - [**RA Calendar Input (WIP)**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-calendar): Add support for a Google Calendar like Calendar input. 40 | 41 | ### Translations 42 | 43 | - [**RA Language Spanish**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-language-spanish): Add support for ES translations. 44 | 45 | ### Permissions 46 | 47 | - [**RA RBAC**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-rbac): Add support for fine grained permissions into your app. 48 | - [**RA Audit Log (WIP)**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-audit-log): Add support for auditing user events, and a timeline view to visualize all the user actions. 49 | 50 | ### Auth Providers 51 | 52 | - [**RA Auth0 (WIP)**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-auth0): Add support for Auth0 as an Auth Provider. 53 | - [**RA LDAP Auth (WIP)**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-ldap-auth): Add support LDAP as an Auth Provider. 54 | - [**RA Firebase Auth (WIP)**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-firebase-auth): Add support for Firebase as an Auth Provider. 55 | 56 | ### Data Providers 57 | 58 | - [**RA Firebase Provider (WIP)**](https://github.com/BlackBoxVision/react-admin-extensions/tree/main/packages/ra-firebase-provider): Add support for Firebase as a Data Provider 59 | 60 | > Those packages marked with (WIP) are packages under development. -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | "packages/*" 4 | ], 5 | "version": "0.0.0" 6 | } 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "root", 3 | "private": true, 4 | "devDependencies": { 5 | "lerna": "^3.13.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackBoxVision/react-admin-extensions/4c5a5dd31ae7bca5f6598e121a1f23e4b86dc195/packages/.DS_Store -------------------------------------------------------------------------------- /packages/ra-audit-log/README.md: -------------------------------------------------------------------------------- 1 | # RA Audit Log [![License: MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT) 2 | 3 | An audit log for `React Admin`. 4 | 5 | ## Install 6 | 7 | You can install this library via NPM or YARN. 8 | 9 | ### NPM 10 | 11 | ```bash 12 | npm i @blackbox-vision/ra-audit-log 13 | ``` 14 | 15 | ### YARN 16 | 17 | ```bash 18 | yarn add @blackbox-vision/ra-audit-log 19 | ``` 20 | 21 | ## Use case 22 | 23 | You need to track user events over your `React Admin` app. 24 | 25 | ## Usage 26 | 27 | The usage is really simple: 28 | 29 | Define your `dataProvider` function like the following: 30 | 31 | ```typescript 32 | import { addEventsForMutations } from "@blackbox-vision/ra-audit-log"; 33 | import simpleRestProvider from "ra-data-simple-rest"; 34 | import authProvider from "./authProvider"; 35 | 36 | const dataProvider = addEventsForMutations( 37 | simpleRestProvider("http://path.to.my.api/"), 38 | authProvider 39 | ); 40 | ``` 41 | 42 | The `addEventsForMutations` function accepts the following options: 43 | 44 | - `name`: the name of the event logs resource (defaults to events) 45 | 46 | ```typescript 47 | import { addEventsForMutations } from "@blackbox-vision/ra-audit-log"; 48 | import simpleRestProvider from "ra-data-simple-rest"; 49 | import authProvider from "./authProvider"; 50 | 51 | const dataProvider = addEventsForMutations( 52 | simpleRestProvider("http://path.to.my.api/"), 53 | authProvider, 54 | { name: "events" } 55 | ); 56 | ``` 57 | 58 | - `resources`: the resources and mutations you want to track with events. It can be an array of resource names or an array of arrays defining both the resource and the dataProvider calls to track 59 | 60 | ```typescript 61 | import { addEventsForMutations } from "@blackbox-vision/ra-audit-log"; 62 | import simpleRestProvider from "ra-data-simple-rest"; 63 | import authProvider from "./authProvider"; 64 | 65 | const dataProvider = addEventsForMutations( 66 | simpleRestProvider("http://path.to.my.api/"), 67 | authProvider, 68 | { 69 | resources: [ 70 | // create an event for all known mutations on posts 71 | "posts", 72 | // create an event only for create and update on comments, but not for delete, deleteMany or updateMany 73 | ["comments", ["create", "update"]], 74 | ], 75 | } 76 | ); 77 | ``` 78 | 79 | - `shouldAudit`: as an alternative to resources, you can specify a function which, given a dataProvider method name (create, update, etc.) and the arguments it was called with, should return true to create an event. This allows to target custom dataProvider methods: 80 | 81 | ```typescript 82 | import { addEventsForMutations } from "@react-admin/ra-audit-log"; 83 | import simpleRestProvider from "ra-data-simple-rest"; 84 | import authProvider from "./authProvider"; 85 | 86 | const dataProvider = addEventsForMutations( 87 | simpleRestProvider("http://path.to.my.api/"), 88 | authProvider, 89 | { 90 | shouldAudit: (action, ...args) => { 91 | if (action === "myCustomMethod") { 92 | return true; 93 | } 94 | }, 95 | } 96 | ); 97 | ``` 98 | 99 | ## Issues 100 | 101 | Please, open an [issue](https://github.com/BlackBoxVision/react-admin-extensions/issues) following one of the issues templates. We will do our best to fix them. 102 | 103 | ## Contributing 104 | 105 | If you want to contribute to this project see [contributing](https://github.com/BlackBoxVision/react-admin-extensions/blob/master/CONTRIBUTING.md) for more information. 106 | 107 | ## License 108 | 109 | Distributed under the **MIT license**. See [LICENSE](https://github.com/BlackBoxVision/react-admin-extensions/blob/master/LICENSE) for more information. 110 | -------------------------------------------------------------------------------- /packages/ra-audit-log/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ["@babel/preset-typescript", "@babel/preset-react"], 6 | plugins: [ 7 | "@babel/plugin-proposal-object-rest-spread", 8 | "@babel/plugin-proposal-class-properties", 9 | ], 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ra-audit-log/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-audit-log", 3 | "version": "4.0.0", 4 | "description": "> TODO: description", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/preset-react": "^7.10.4", 22 | "@babel/preset-typescript": "^7.10.4", 23 | "@pika/pack": "^0.5.0", 24 | "@pika/plugin-build-types": "^0.9.2", 25 | "@pika/plugin-build-web": "^0.9.2", 26 | "@pika/plugin-standard-pkg": "^0.9.2", 27 | "@types/react": "^16.9.48", 28 | "react": "^16.13.1", 29 | "react-admin": "^4.5.0", 30 | "rimraf": "^3.0.2", 31 | "typescript": "^3.9.7" 32 | }, 33 | "peerDependencies": { 34 | "react": "*", 35 | "react-admin": "*" 36 | }, 37 | "@pika/pack": { 38 | "pipeline": [ 39 | [ 40 | "@pika/plugin-standard-pkg" 41 | ], 42 | [ 43 | "@pika/plugin-build-web" 44 | ] 45 | ] 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /packages/ra-audit-log/src/index.ts: -------------------------------------------------------------------------------- 1 | import { AuthProvider, DataProvider, UserIdentity } from "react-admin"; 2 | 3 | export type AddEventsForMutationsOptions = { 4 | name: string; 5 | resources?: any[]; 6 | shouldAudit?: (action: string, ...args) => boolean; 7 | }; 8 | 9 | let defaultOptions: AddEventsForMutationsOptions = { 10 | name: "events", 11 | }; 12 | 13 | let blackListedActions: string[] = [ 14 | "getList", 15 | "getOne", 16 | "getMany", 17 | "getManyReference", 18 | ]; 19 | 20 | function isBlackListedAction(action: string): Boolean { 21 | return blackListedActions.includes(action); 22 | } 23 | 24 | async function createNewEvent( 25 | authProvider: AuthProvider, 26 | dataProvider: DataProvider, 27 | action: string, 28 | resource: string, 29 | params: any, 30 | options: AddEventsForMutationsOptions 31 | ): Promise { 32 | let { resources, shouldAudit } = options; 33 | let canAudit = null; 34 | 35 | if (!!shouldAudit && !!resources) { 36 | console.warn( 37 | `[ra-audit-log] You can't use both "shouldAudit" and "resources" options at the same time. "shouldAudit" will be ignored.` 38 | ); 39 | 40 | let resourceToAudit = resources?.find?.((auditResource) => { 41 | if (typeof auditResource === "string") { 42 | return auditResource === resource; 43 | } 44 | 45 | if (Array.isArray(auditResource)) { 46 | return auditResource?.[0] === resource; 47 | } 48 | }); 49 | 50 | if (Array.isArray(resourceToAudit)) { 51 | canAudit = resourceToAudit?.[1]?.includes?.(action); 52 | } else { 53 | canAudit = !!resourceToAudit; 54 | } 55 | } else { 56 | canAudit = shouldAudit?.(action, resource, params); 57 | } 58 | 59 | if (!canAudit) { 60 | return; 61 | } 62 | 63 | try { 64 | let author: UserIdentity = await authProvider.getIdentity(); 65 | 66 | await dataProvider.create(options.name, { 67 | data: { 68 | action, 69 | author, 70 | resource, 71 | date: new Date(), 72 | payload: JSON.stringify(params), 73 | }, 74 | }); 75 | } catch (err) { 76 | console.info(`[ra-audit-log] Error while creating new event: ${err}`); 77 | } 78 | } 79 | 80 | function enhanceWithEventTracking( 81 | authProvider: AuthProvider, 82 | dataProvider: DataProvider, 83 | action: string, 84 | options: AddEventsForMutationsOptions 85 | ): (resource: string, params: any) => Promise { 86 | if (isBlackListedAction(action)) { 87 | return dataProvider?.[action]; 88 | } 89 | 90 | return async function (resource: string, params: any) { 91 | let response = await dataProvider?.[action]?.(resource, params); 92 | let newParams = params; 93 | 94 | if (!params.id) { 95 | newParams = { 96 | ...params, 97 | id: response?.data?.id, 98 | }; 99 | } 100 | 101 | await createNewEvent( 102 | authProvider, 103 | dataProvider, 104 | action, 105 | resource, 106 | newParams, 107 | options 108 | ); 109 | 110 | return response; 111 | }; 112 | } 113 | 114 | export function addEventsForMutations( 115 | dataProvider: DataProvider, 116 | authProvider: AuthProvider, 117 | options: AddEventsForMutationsOptions = defaultOptions 118 | ): DataProvider { 119 | return Object.keys(dataProvider).reduce((newDataProvider, action) => { 120 | newDataProvider[action] = enhanceWithEventTracking( 121 | authProvider, 122 | dataProvider, 123 | action, 124 | options 125 | ); 126 | 127 | return newDataProvider; 128 | }, {}) as DataProvider; 129 | } 130 | -------------------------------------------------------------------------------- /packages/ra-audit-log/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true 25 | }, 26 | "include": ["src/**/*"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/ra-auth0/README.md: -------------------------------------------------------------------------------- 1 | # `ra-auth0` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const raAuth0 = require('ra-auth0'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/ra-auth0/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ["@babel/preset-typescript", "@babel/preset-react"], 6 | plugins: [ 7 | "@babel/plugin-proposal-object-rest-spread", 8 | "@babel/plugin-proposal-class-properties", 9 | ], 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ra-auth0/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-auth0", 3 | "version": "0.0.0", 4 | "description": "> TODO: description", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/preset-react": "^7.10.4", 22 | "@babel/preset-typescript": "^7.10.4", 23 | "@pika/pack": "^0.5.0", 24 | "@pika/plugin-build-types": "^0.9.2", 25 | "@pika/plugin-build-web": "^0.9.2", 26 | "@pika/plugin-standard-pkg": "^0.9.2", 27 | "@types/react": "^16.9.48", 28 | "react": "^16.13.1", 29 | "rimraf": "^3.0.2", 30 | "typescript": "^3.9.7" 31 | }, 32 | "peerDependencies": { 33 | "react": "^16.11.0" 34 | }, 35 | "@pika/pack": { 36 | "pipeline": [ 37 | [ 38 | "@pika/plugin-standard-pkg" 39 | ], 40 | [ 41 | "@pika/plugin-build-web" 42 | ], 43 | [ 44 | "@pika/plugin-build-types" 45 | ] 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/ra-auth0/src/index.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = raAuth0; 4 | 5 | function raAuth0() { 6 | // TODO 7 | } 8 | -------------------------------------------------------------------------------- /packages/ra-auth0/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true 25 | }, 26 | "include": ["src/**/*"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/ra-calendar/README.md: -------------------------------------------------------------------------------- 1 | # `ra-calendar` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const raCalendar = require('ra-calendar'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/ra-calendar/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ["@babel/preset-typescript", "@babel/preset-react"], 6 | plugins: [ 7 | "@babel/plugin-proposal-object-rest-spread", 8 | "@babel/plugin-proposal-class-properties", 9 | ], 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ra-calendar/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-calendar", 3 | "version": "0.0.0", 4 | "description": "> TODO: description", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/preset-react": "^7.10.4", 22 | "@babel/preset-typescript": "^7.10.4", 23 | "@pika/pack": "^0.5.0", 24 | "@pika/plugin-build-types": "^0.9.2", 25 | "@pika/plugin-build-web": "^0.9.2", 26 | "@pika/plugin-standard-pkg": "^0.9.2", 27 | "@types/react": "^16.9.48", 28 | "react": "^16.13.1", 29 | "rimraf": "^3.0.2", 30 | "typescript": "^3.9.7" 31 | }, 32 | "peerDependencies": { 33 | "react": "^16.11.0" 34 | }, 35 | "@pika/pack": { 36 | "pipeline": [ 37 | [ 38 | "@pika/plugin-standard-pkg" 39 | ], 40 | [ 41 | "@pika/plugin-build-web" 42 | ], 43 | [ 44 | "@pika/plugin-build-types" 45 | ] 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/ra-calendar/src/index.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = raCalendar; 4 | 5 | function raCalendar() { 6 | // TODO 7 | } 8 | -------------------------------------------------------------------------------- /packages/ra-calendar/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true 25 | }, 26 | "include": ["src/**/*"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/ra-editor/README.md: -------------------------------------------------------------------------------- 1 | # `ra-editor` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const raEditor = require('ra-editor'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/ra-editor/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ["@babel/preset-typescript", "@babel/preset-react"], 6 | plugins: [ 7 | "@babel/plugin-proposal-object-rest-spread", 8 | "@babel/plugin-proposal-class-properties", 9 | ], 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ra-editor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-editor", 3 | "version": "0.0.0", 4 | "description": "> TODO: description", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/preset-react": "^7.10.4", 22 | "@babel/preset-typescript": "^7.10.4", 23 | "@pika/pack": "^0.5.0", 24 | "@pika/plugin-build-types": "^0.9.2", 25 | "@pika/plugin-build-web": "^0.9.2", 26 | "@pika/plugin-standard-pkg": "^0.9.2", 27 | "@types/react": "^16.9.48", 28 | "react": "^16.13.1", 29 | "rimraf": "^3.0.2", 30 | "typescript": "^3.9.7" 31 | }, 32 | "peerDependencies": { 33 | "react": "^16.11.0" 34 | }, 35 | "@pika/pack": { 36 | "pipeline": [ 37 | [ 38 | "@pika/plugin-standard-pkg" 39 | ], 40 | [ 41 | "@pika/plugin-build-web" 42 | ], 43 | [ 44 | "@pika/plugin-build-types" 45 | ] 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/ra-editor/src/index.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = raEditor; 4 | 5 | function raEditor() { 6 | // TODO 7 | } 8 | -------------------------------------------------------------------------------- /packages/ra-editor/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true 25 | }, 26 | "include": ["src/**/*"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/ra-firebase-auth/README.md: -------------------------------------------------------------------------------- 1 | # `ra-firebase-auth` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const raFirebaseAuth = require('ra-firebase-auth'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/ra-firebase-auth/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ["@babel/preset-typescript", "@babel/preset-react"], 6 | plugins: [ 7 | "@babel/plugin-proposal-object-rest-spread", 8 | "@babel/plugin-proposal-class-properties", 9 | ], 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ra-firebase-auth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-firebase-auth", 3 | "version": "0.0.0", 4 | "description": "> TODO: description", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/preset-react": "^7.10.4", 22 | "@babel/preset-typescript": "^7.10.4", 23 | "@pika/pack": "^0.5.0", 24 | "@pika/plugin-build-types": "^0.9.2", 25 | "@pika/plugin-build-web": "^0.9.2", 26 | "@pika/plugin-standard-pkg": "^0.9.2", 27 | "@types/react": "^16.9.48", 28 | "react": "^16.13.1", 29 | "rimraf": "^3.0.2", 30 | "typescript": "^3.9.7" 31 | }, 32 | "peerDependencies": { 33 | "react": "^16.11.0" 34 | }, 35 | "@pika/pack": { 36 | "pipeline": [ 37 | [ 38 | "@pika/plugin-standard-pkg" 39 | ], 40 | [ 41 | "@pika/plugin-build-web" 42 | ], 43 | [ 44 | "@pika/plugin-build-types" 45 | ] 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/ra-firebase-auth/src/index.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = raFirebaseAuth; 4 | 5 | function raFirebaseAuth() { 6 | // TODO 7 | } 8 | -------------------------------------------------------------------------------- /packages/ra-firebase-auth/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true 25 | }, 26 | "include": ["src/**/*"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/ra-firebase-provider/README.md: -------------------------------------------------------------------------------- 1 | # `ra-firebase-provider` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const raFirebaseProvider = require('ra-firebase-provider'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/ra-firebase-provider/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ["@babel/preset-typescript", "@babel/preset-react"], 6 | plugins: [ 7 | "@babel/plugin-proposal-object-rest-spread", 8 | "@babel/plugin-proposal-class-properties", 9 | ], 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ra-firebase-provider/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-firebase-provider", 3 | "version": "0.0.0", 4 | "description": "> TODO: description", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/preset-react": "^7.10.4", 22 | "@babel/preset-typescript": "^7.10.4", 23 | "@pika/pack": "^0.5.0", 24 | "@pika/plugin-build-types": "^0.9.2", 25 | "@pika/plugin-build-web": "^0.9.2", 26 | "@pika/plugin-standard-pkg": "^0.9.2", 27 | "@types/react": "^16.9.48", 28 | "react": "^16.13.1", 29 | "rimraf": "^3.0.2", 30 | "typescript": "^3.9.7" 31 | }, 32 | "peerDependencies": { 33 | "react": "^16.11.0" 34 | }, 35 | "@pika/pack": { 36 | "pipeline": [ 37 | [ 38 | "@pika/plugin-standard-pkg" 39 | ], 40 | [ 41 | "@pika/plugin-build-web" 42 | ], 43 | [ 44 | "@pika/plugin-build-types" 45 | ] 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/ra-firebase-provider/src/index.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = raFirebaseProvider; 4 | 5 | function raFirebaseProvider() { 6 | // TODO 7 | } 8 | -------------------------------------------------------------------------------- /packages/ra-firebase-provider/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true 25 | }, 26 | "include": ["src/**/*"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/ra-form-layout/README.md: -------------------------------------------------------------------------------- 1 | # `ra-form-layout` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const raFormLayout = require('ra-form-layout'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/ra-form-layout/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ["@babel/preset-typescript", "@babel/preset-react"], 6 | plugins: [ 7 | "@babel/plugin-proposal-object-rest-spread", 8 | "@babel/plugin-proposal-class-properties", 9 | ], 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ra-form-layout/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-form-layout", 3 | "version": "0.0.0", 4 | "description": "> TODO: description", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/preset-react": "^7.10.4", 22 | "@babel/preset-typescript": "^7.10.4", 23 | "@pika/pack": "^0.5.0", 24 | "@pika/plugin-build-types": "^0.9.2", 25 | "@pika/plugin-build-web": "^0.9.2", 26 | "@pika/plugin-standard-pkg": "^0.9.2", 27 | "@types/react": "^16.9.48", 28 | "react": "^16.13.1", 29 | "rimraf": "^3.0.2", 30 | "typescript": "^3.9.7" 31 | }, 32 | "peerDependencies": { 33 | "react": "^16.11.0" 34 | }, 35 | "@pika/pack": { 36 | "pipeline": [ 37 | [ 38 | "@pika/plugin-standard-pkg" 39 | ], 40 | [ 41 | "@pika/plugin-build-web" 42 | ], 43 | [ 44 | "@pika/plugin-build-types" 45 | ] 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/ra-form-layout/src/index.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = raFormLayout; 4 | 5 | function raFormLayout() { 6 | // TODO 7 | } 8 | -------------------------------------------------------------------------------- /packages/ra-form-layout/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true 25 | }, 26 | "include": ["src/**/*"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/ra-language-spanish/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /packages/ra-language-spanish/README.md: -------------------------------------------------------------------------------- 1 | # RA Language Spanish [![License: MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT) 2 | 3 | Spanish translations for `React Admin`. 4 | 5 | ## Install 6 | 7 | You can install this library via NPM or YARN. 8 | 9 | ### NPM 10 | 11 | ```bash 12 | npm i @blackbox-vision/ra-language-spanish 13 | ``` 14 | 15 | ### YARN 16 | 17 | ```bash 18 | yarn add @blackbox-vision/ra-language-spanish 19 | ``` 20 | 21 | ## Use case 22 | 23 | You need to have spanish translations in your `React Admin` app. 24 | 25 | ## Usage 26 | 27 | The usage is really simple: 28 | 29 | 1. Define your `i18nProvider`: 30 | 31 | ```ts 32 | // i18nProvider.ts 33 | import polyglotI18nProvider from "ra-i18n-polyglot"; 34 | import spanishMessages from "@blackbox-vision/ra-language-spanish"; 35 | 36 | const messages = { 37 | es: spanishMessages, 38 | }; 39 | 40 | export const i18nProvider = polyglotI18nProvider((locale) => messages[locale]); 41 | ``` 42 | 43 | 2. Pass your custom `i18nProvider` to your `React Admin` instance: 44 | 45 | ```tsx 46 | // App.tsx 47 | import React from "react"; 48 | import { Admin, Resource } from "react-admin"; 49 | import jsonServerProvider from "ra-data-json-server"; 50 | 51 | export const App = () => { 52 | const dataProvider = jsonServerProvider( 53 | "https://jsonplaceholder.typicode.com" 54 | ); 55 | 56 | return ( 57 | 58 | 59 | 60 | ); 61 | }; 62 | 63 | App.displayName = "App"; 64 | ``` 65 | 66 | ## Issues 67 | 68 | Please, open an [issue](https://github.com/BlackBoxVision/react-admin-extensions/issues) following one of the issues templates. We will do our best to fix them. 69 | 70 | ## Contributing 71 | 72 | If you want to contribute to this project see [contributing](https://github.com/BlackBoxVision/react-admin-extensions/blob/master/CONTRIBUTING.md) for more information. 73 | 74 | ## License 75 | 76 | Distributed under the **MIT license**. See [LICENSE](https://github.com/BlackBoxVision/react-admin-extensions/blob/master/LICENSE) for more information. 77 | -------------------------------------------------------------------------------- /packages/ra-language-spanish/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ["@babel/preset-typescript", "@babel/preset-react"], 6 | plugins: [ 7 | "@babel/plugin-proposal-object-rest-spread", 8 | "@babel/plugin-proposal-class-properties", 9 | ], 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ra-language-spanish/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-language-spanish", 3 | "version": "4.11.3", 4 | "description": "Spanish messages for react-admin, the frontend framework for building admin applications on top of REST/GraphQL services", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/preset-react": "^7.10.4", 22 | "@babel/preset-typescript": "^7.10.4", 23 | "@pika/pack": "^0.5.0", 24 | "@pika/plugin-build-types": "^0.9.2", 25 | "@pika/plugin-build-web": "^0.9.2", 26 | "@pika/plugin-standard-pkg": "^0.9.2", 27 | "@types/react": "^16.9.48", 28 | "ra-core": "^4.4.0", 29 | "react": "^16.13.1", 30 | "rimraf": "^3.0.2", 31 | "typescript": "^3.9.7" 32 | }, 33 | "peerDependencies": { 34 | "ra-core": "^4.4.0", 35 | "react": "*" 36 | }, 37 | "@pika/pack": { 38 | "pipeline": [ 39 | [ 40 | "@pika/plugin-standard-pkg" 41 | ], 42 | [ 43 | "@pika/plugin-build-web" 44 | ] 45 | ] 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /packages/ra-language-spanish/src/index.ts: -------------------------------------------------------------------------------- 1 | import { TranslationMessages } from "ra-core"; 2 | 3 | const spanishMessages: Required = { 4 | ra: { 5 | action: { 6 | add_filter: "Añadir filtro", 7 | add: "Añadir", 8 | back: "Ir atrás", 9 | bulk_actions: "1 item seleccionado |||| %{smart_count} items seleccionados", 10 | cancel: "Cancelar", 11 | clear_array_input: "Limpiar la lista", 12 | clear_input_value: "Limpiar valor", 13 | clone: "Clonar", 14 | confirm: "Confirmar", 15 | create: "Crear", 16 | create_item: "Crear %{item}", 17 | delete: "Eliminar", 18 | edit: "Editar", 19 | export: "Exportar", 20 | list: "Listar", 21 | refresh: "Refrescar", 22 | remove_filter: "Borrar filtro", 23 | remove_all_filters: "Remover todos los filtros", 24 | remove: "Borrar", 25 | save: "Guardar", 26 | search: "Buscar", 27 | select_all: "Seleccionar todo", 28 | select_row: "Seleccionar esta fila", 29 | show: "Mostrar", 30 | sort: "Ordenar", 31 | undo: "Deshacer", 32 | unselect: "Deseleccionar", 33 | expand: "Expandir", 34 | close: "Cerrar", 35 | open_menu: "Abrir menú", 36 | close_menu: "Cerrar menú", 37 | update: "Actualizar", 38 | move_up: "Mover arriba", 39 | move_down: "Mover abajo", 40 | open:"Abrir", 41 | toggle_theme: "Alternar tema", 42 | select_columns: "Columnas", 43 | update_application: 'Recargar Aplicación', 44 | }, 45 | boolean: { 46 | true: "Sí", 47 | false: "No", 48 | null: " ", 49 | }, 50 | page: { 51 | create: "Crear %{name}", 52 | dashboard: "Tablero", 53 | edit: "%{name} #%{id}", 54 | error: "Algo salió mal", 55 | list: "Lista de %{name}", 56 | loading: "Cargando", 57 | not_found: "No encontrado", 58 | show: "%{name} #%{id}", 59 | empty: "Sin %{name} todavía.", 60 | invite: "¿Quiere agregar una?", 61 | }, 62 | input: { 63 | file: { 64 | upload_several: 65 | "Arrastre algunos archivos para subir o haga clic para seleccionarlos.", 66 | upload_single: "Arrastre un archivo para subir o haga clic para seleccionarlo.", 67 | }, 68 | image: { 69 | upload_several: 70 | "Arrastre algunas imagénes para subir o haga clic para seleccionarlas.", 71 | upload_single: 72 | "Arrastre alguna imagen para subir o haga clic para seleccionarla.", 73 | }, 74 | references: { 75 | all_missing: "No se pueden encontrar datos de referencias.", 76 | many_missing: 77 | "Al menos una de las referencias asociadas parece no estar disponible.", 78 | single_missing: "La referencia asociada no parece estar disponible.", 79 | }, 80 | password: { 81 | toggle_visible: "Ocultar contraseña", 82 | toggle_hidden: "Mostrar contraseña", 83 | }, 84 | }, 85 | message: { 86 | about: "Acerca de", 87 | are_you_sure: "¿Está seguro?", 88 | auth_error: 89 | "Ocurrió un error al validar el token de autenticación.", 90 | bulk_delete_content: 91 | "¿Seguro que quiere eliminar este %{name}? |||| ¿Seguro que quiere eliminar estos %{smart_count} items?", 92 | bulk_delete_title: 93 | "Eliminar %{name} |||| Eliminar %{smart_count} %{name} items", 94 | bulk_update_content: 95 | "¿Seguro que quiere actualizar este %{name}? |||| ¿Seguro que quiere actualizar estos %{smart_count} items?", 96 | bulk_update_title: 97 | "Actualizar %{name} |||| Actualizar %{smart_count} %{name} items", 98 | clear_array_input: "¿Estás seguro de que quieres borrar toda la lista?", 99 | delete_content: "¿Seguro que quiere eliminar este item?", 100 | delete_title: "Eliminar %{name} #%{id}", 101 | details: "Detalles", 102 | error: 103 | "Se produjo un error en el cliente y su solicitud no se pudo completar", 104 | invalid_form: 105 | "El formulario no es válido. Por favor verifique si hay errores", 106 | loading: "La página se está cargando, espere un momento por favor", 107 | no: "No", 108 | not_found: 109 | "O bien escribió una URL incorrecta o siguió un enlace incorrecto.", 110 | yes: "Sí", 111 | unsaved_changes: 112 | "Algunos de sus cambios no se guardaron. ¿Está seguro que quiere ignorarlos?", 113 | }, 114 | navigation: { 115 | no_results: "No se han encontrado resultados", 116 | no_more_results: 117 | "El número de página %{page} está fuera de los límites. Pruebe la página anterior.", 118 | page_out_of_boundaries: "Número de página %{page} fuera de los límites", 119 | page_out_from_end: "No puede ir después de la última página", 120 | page_out_from_begin: "No puede ir antes de la página 1", 121 | page_range_info: "%{offsetBegin} - %{offsetEnd} de %{total}", 122 | partial_page_range_info: "%{offsetBegin}-%{offsetEnd} de mas de %{offsetEnd}", 123 | current_page: "Página %{page}", 124 | page: "Ir a la página %{page}", 125 | first : "Ir a la primera página", 126 | last: "Ir a la última página", 127 | next: "Siguiente", 128 | previous: "Ir a la página anterior", 129 | page_rows_per_page: "Filas por página:", 130 | skip_nav: "Saltar al contenido", 131 | }, 132 | sort: { 133 | sort_by: "Ordenar por %{field} %{order}", 134 | ASC: "ascendente", 135 | DESC: "descendente", 136 | }, 137 | auth: { 138 | auth_check_error: "Por favor inicie sesión para continuar", 139 | user_menu: "Perfil", 140 | username: "Usuario", 141 | password: "Contraseña", 142 | sign_in: "Acceder", 143 | sign_in_error: "La autenticación falló, por favor, vuelva a intentarlo", 144 | logout: "Cerrar Sesión", 145 | }, 146 | notification: { 147 | updated: "Elemento actualizado |||| %{smart_count} elementos actualizados", 148 | created: "Elemento creado", 149 | deleted: "Elemento borrado |||| %{smart_count} elementos borrados.", 150 | bad_item: "Elemento incorrecto", 151 | item_doesnt_exist: "El elemento no existe", 152 | http_error: "Error de comunicación con el servidor", 153 | data_provider_error: 154 | "Error del proveedor de datos. Consulte la consola para más detalles.", 155 | i18n_error: 156 | "No se pudieron cargar las traducciones para el idioma especificado", 157 | canceled: "Acción cancelada", 158 | logged_out: "Su sesión ha finalizado, vuelva a conectarse.", 159 | not_authorized: "No tiene autorización para acceder a este recurso.", 160 | application_update_available: 'Una nueva versión está disponible.', 161 | }, 162 | validation: { 163 | required: "Requerido", 164 | minLength: "Debe contener %{min} caracteres al menos", 165 | maxLength: "Debe contener %{max} caracteres o menos", 166 | minValue: "Debe ser al menos %{min}", 167 | maxValue: "Debe ser %{max} o menos", 168 | number: "Debe ser un número", 169 | email: "Debe ser un correo electrónico válido", 170 | oneOf: "Debe ser uno de: %{options}", 171 | regex: "Debe coincidir con un formato específico (regexp): %{pattern}", 172 | }, 173 | saved_queries:{ 174 | label: "Consultas guardadas", 175 | query_name: "Nombre de la consulta", 176 | new_label: "Guardar la consulta actual...", 177 | new_dialog_title: "Guardar la consulta actual como", 178 | remove_label: "Eliminar la consulta guardada", 179 | remove_label_with_name: "Eliminar la consulta '%{name}'", 180 | remove_dialog_title: "¿Eliminar la consulta guardada?", 181 | remove_message: "¿Estás seguro de que quieres eliminar ese elemento de tu lista de consultas guardadas?", 182 | help: "Filtrar la lista y guardar esta consulta para más tarde", 183 | }, 184 | configurable:{ 185 | customize: "Personalizar", 186 | configureMode: "Configurar esta página", 187 | inspector:{ 188 | title: "Inspector", 189 | content: "Pase el ratón por los elementos de la interfaz de usuario de la aplicación para configurarlos", 190 | reset: "Restablecer la configuración", 191 | hideAll: "Esconder Todos", 192 | showAll: "Mostrar Todos", 193 | }, 194 | Datagrid: { 195 | title: "Table Datos", 196 | unlabeled: "Columna #%{column} sin etiqueta", 197 | }, 198 | SimpleForm: { 199 | title: "Formulario", 200 | unlabeled: "Entrada #%{input} sin etiqueta", 201 | }, 202 | SimpleList:{ 203 | title: "Lista", 204 | primaryText: "Texto principal", 205 | secondaryText: "Texto secundario", 206 | tertiaryText: "Texto terciario" 207 | }, 208 | }, 209 | }, 210 | }; 211 | 212 | export default spanishMessages; 213 | -------------------------------------------------------------------------------- /packages/ra-language-spanish/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true, 25 | "skipLibCheck": true 26 | }, 27 | "include": ["src/**/*"], 28 | "exclude": ["node_modules"] 29 | } 30 | -------------------------------------------------------------------------------- /packages/ra-layout/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-typescript", "@babel/preset-react"], 3 | "plugins": [ 4 | "@babel/plugin-proposal-object-rest-spread", 5 | "@babel/plugin-proposal-class-properties", 6 | "@babel/plugin-proposal-optional-chaining" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /packages/ra-layout/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /packages/ra-layout/README.md: -------------------------------------------------------------------------------- 1 | # RA Layout [![License: MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT) 2 | 3 | Revamped React Admin UI. 4 | 5 | ## Install 6 | 7 | You can install this library via NPM or YARN. 8 | 9 | ### NPM 10 | 11 | ```bash 12 | npm i @blackbox-vision/ra-layout 13 | ``` 14 | 15 | ### YARN 16 | 17 | ```bash 18 | yarn add @blackbox-vision/ra-layout 19 | ``` 20 | 21 | ## Use case 22 | 23 | You're tired of the defacto React Admin UI and want to renew the look and feel. 24 | 25 | ## Usage 26 | 27 | The usage is really simple: 28 | 29 | 1. Define your menu as a JSON structure like the following: 30 | 31 | ```typescript 32 | // menu.ts 33 | import { 34 | LocalAtm, 35 | PermContactCalendar, 36 | } from '@material-ui/icons'; 37 | 38 | export const items = [{ 39 | type: 'group', 40 | label: 'Architects', 41 | items: [ 42 | { 43 | type: 'resource', 44 | name: 'architects', 45 | label: 'Information', 46 | icon: PermContactCalendar, 47 | }, 48 | { 49 | type: 'resource', 50 | name: 'commissions', 51 | label: 'Commissions', 52 | icon: LocalAtm, 53 | }, 54 | ], 55 | }] 56 | ``` 57 | 58 | 2. Import `Layout` pass props to it and you're ready: 59 | 60 | ```typescript 61 | // App.tsx 62 | import React from 'react'; 63 | import { Admin } from 'react-admin'; 64 | import jsonServerProvider from 'ra-data-json-server'; 65 | 66 | import { Layout } from '@blackbox-vision/ra-layout'; 67 | 68 | import { items } from './menu'; 69 | 70 | const dataProvider = jsonServerProvider('https://jsonplaceholder.typicode.com'); 71 | 72 | export const App = () => { 73 | return ( 74 | } 77 | > 78 | 79 | 80 | ); 81 | }; 82 | 83 | App.displayName = "App"; 84 | ``` 85 | 86 | ## Props 87 | 88 | `Layout` has the following props: 89 | 90 | | Properties | Types | Default Value | Description | 91 | | ---------- | ------- | ------------- | ----------------------------------------------- | 92 | | items | Array | [] | The menu items to render | 93 | 94 | ## Issues 95 | 96 | Please, open an [issue](https://github.com/BlackBoxVision/react-admin-extensions/issues) following one of the issues templates. We will do our best to fix them. 97 | 98 | ## Contributing 99 | 100 | If you want to contribute to this project see [contributing](https://github.com/BlackBoxVision/react-admin-extensions/blob/master/CONTRIBUTING.md) for more information. 101 | 102 | ## License 103 | 104 | Distributed under the **MIT license**. See [LICENSE](https://github.com/BlackBoxVision/react-admin-extensions/blob/master/LICENSE) for more information. 105 | -------------------------------------------------------------------------------- /packages/ra-layout/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-layout", 3 | "version": "0.0.29", 4 | "description": "Custom layout for React Admin", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "build": "npm run clean && pika build", 11 | "publish": "pika publish --any-branch", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/plugin-proposal-optional-chaining": "^7.13.8", 22 | "@babel/preset-react": "^7.10.4", 23 | "@babel/preset-typescript": "^7.10.4", 24 | "@material-ui/core": "^4.11.3", 25 | "@pika/pack": "^0.5.0", 26 | "@pika/plugin-build-types": "^0.9.2", 27 | "@pika/plugin-build-web": "^0.9.2", 28 | "@pika/plugin-standard-pkg": "^0.9.2", 29 | "@types/react": "^16.9.48", 30 | "core-js": "^3.9.1", 31 | "qs": "^6.9.6", 32 | "react": "^16.13.1", 33 | "react-admin": "^3.13.4", 34 | "rimraf": "^3.0.2", 35 | "typescript": "^3.9.7" 36 | }, 37 | "peerDependencies": { 38 | "qs": "^6.9.6", 39 | "react": "^16.8.0", 40 | "react-admin": "^3.13.4" 41 | }, 42 | "@pika/pack": { 43 | "pipeline": [ 44 | [ 45 | "@pika/plugin-standard-pkg" 46 | ], 47 | [ 48 | "@pika/plugin-build-web" 49 | ], 50 | [ 51 | "@pika/plugin-build-types" 52 | ] 53 | ] 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /packages/ra-layout/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./layout"; 2 | -------------------------------------------------------------------------------- /packages/ra-layout/src/layout/components/collapsible-menu/index.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | import React, { useState } from "react"; 3 | import List from "@material-ui/core/List"; 4 | import Tooltip from "@material-ui/core/Tooltip"; 5 | import MenuItem from "@material-ui/core/MenuItem"; 6 | import Collapse from "@material-ui/core/Collapse"; 7 | import Typography from "@material-ui/core/Typography"; 8 | import ListItemIcon from "@material-ui/core/ListItemIcon"; 9 | 10 | import ExpandMore from "@material-ui/icons/ExpandMore"; 11 | import ChevronRight from "@material-ui/icons/ChevronRight"; 12 | 13 | import { useStyles } from "./styles"; 14 | 15 | export type CollapsibleMenuProps = { 16 | label: string; 17 | isSidebarOpen: boolean; 18 | children: React.ReactElement[]; 19 | layoutStyles: any; 20 | iconStyle: any; 21 | }; 22 | 23 | export const CollapsibleMenu: React.FC = ({ 24 | isSidebarOpen, 25 | children, 26 | label, 27 | layoutStyles, 28 | iconStyle, 29 | }) => { 30 | const [isOpen, setIsOpen] = useState(false); 31 | 32 | const styles = useStyles(); 33 | 34 | const MenuItemContainer = ({ children }) => { 35 | if (isSidebarOpen || isOpen) { 36 | return children; 37 | } 38 | 39 | return ( 40 | 41 | {children} 42 | 43 | ); 44 | }; 45 | 46 | return ( 47 | <> 48 | 49 | setIsOpen(!isOpen)} 53 | > 54 | 55 | {isOpen ? : } 56 | 57 | 62 | {label} 63 | 64 | 65 | 66 | 67 | 75 | {children} 76 | 77 | 78 | 79 | ); 80 | }; 81 | 82 | CollapsibleMenu.displayName = "CollapsibleMenu"; 83 | -------------------------------------------------------------------------------- /packages/ra-layout/src/layout/components/collapsible-menu/styles.ts: -------------------------------------------------------------------------------- 1 | import { Theme } from "@material-ui/core"; 2 | import { makeStyles } from "@material-ui/core/styles"; 3 | 4 | export const useStyles = makeStyles((theme: Theme) => ({ 5 | icon: { 6 | minWidth: theme.spacing(5), 7 | }, 8 | listItem: { 9 | minHeight: "48px !important", 10 | }, 11 | listWhenSidebarOpen: { 12 | "& a": { 13 | [theme.breakpoints.up("xs")]: { 14 | paddingLeft: theme.spacing(4), 15 | transition: "padding-left 195ms cubic-bezier(0.4, 0, 0.6, 1) 0ms", 16 | }, 17 | }, 18 | }, 19 | listWhenSidebarClosed: { 20 | "& a": { 21 | [theme.breakpoints.up("xs")]: { 22 | paddingLeft: theme.spacing(2), 23 | transition: "padding-left 195ms cubic-bezier(0.4, 0, 0.6, 1) 0ms", 24 | }, 25 | }, 26 | }, 27 | })); 28 | -------------------------------------------------------------------------------- /packages/ra-layout/src/layout/components/header/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { AppBar } from "react-admin"; 3 | import { Typography } from "@material-ui/core"; 4 | 5 | import { useStyles } from "./styles"; 6 | 7 | // TODO: improve typings 8 | export type HeaderProps = { 9 | logo?: string 10 | logoStyle?: any 11 | }; 12 | 13 | export const Header: React.FC = ({ logo, logoStyle, ...props }) => { 14 | const styles = useStyles(); 15 | 16 | return ( 17 | 18 | 24 | {logo ? logo : null} 25 | 26 | ); 27 | }; 28 | 29 | Header.displayName = "Header"; 30 | 31 | Header.defaultProps = {}; 32 | -------------------------------------------------------------------------------- /packages/ra-layout/src/layout/components/header/styles.ts: -------------------------------------------------------------------------------- 1 | import { makeStyles } from "@material-ui/core/styles"; 2 | 3 | export const useStyles = makeStyles((theme) => ({ 4 | title: { 5 | flexGrow: 2 6 | }, 7 | })); 8 | -------------------------------------------------------------------------------- /packages/ra-layout/src/layout/components/nested-menu/index.tsx: -------------------------------------------------------------------------------- 1 | import qs from "qs"; 2 | import clsx from "clsx"; 3 | import React, { useCallback } from "react"; 4 | import { useSelector } from "react-redux"; 5 | import { MenuItemLink } from "react-admin"; 6 | 7 | import DefaultIcon from "@material-ui/icons/ViewList"; 8 | 9 | import { CollapsibleMenu } from "../collapsible-menu"; 10 | 11 | import { useStyles } from "./styles"; 12 | 13 | // TODO: improve typings 14 | export type NestedMenuProps = { 15 | items: any[]; 16 | layoutStyles: any; 17 | iconStyle: any; 18 | }; 19 | 20 | export const NestedMenu: React.FC = React.memo( 21 | ({ items = [], layoutStyles, iconStyle }) => { 22 | const isSidebarOpen = useSelector((state) => state.admin.ui.sidebarOpen); 23 | 24 | const styles = useStyles(); 25 | 26 | const renderItems = useCallback( 27 | ({ type, name, search, label, filter, icon: Icon, items: subItems }) => { 28 | if (type === "group") { 29 | return ( 30 | 37 | {subItems.map(renderItems)} 38 | 39 | ); 40 | } 41 | 42 | return ( 43 | 58 | ) : ( 59 | 60 | ) 61 | } 62 | /> 63 | ); 64 | }, 65 | [isSidebarOpen] 66 | ); 67 | 68 | return ; 69 | } 70 | ); 71 | 72 | NestedMenu.displayName = "NestedMenu"; 73 | -------------------------------------------------------------------------------- /packages/ra-layout/src/layout/components/nested-menu/styles.ts: -------------------------------------------------------------------------------- 1 | import { makeStyles } from "@material-ui/core/styles"; 2 | 3 | export const useStyles = makeStyles((theme) => ({ 4 | listItem: { 5 | minHeight: "48px !important", 6 | }, 7 | })); 8 | -------------------------------------------------------------------------------- /packages/ra-layout/src/layout/components/side-drawer/index.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | import React from "react"; 3 | import { useSelector } from "react-redux"; 4 | import Divider from "@material-ui/core/Divider"; 5 | import { Sidebar, MenuItemLink, useLogout } from "react-admin"; 6 | 7 | import LogoutIcon from "@material-ui/icons/PowerSettingsNewOutlined"; 8 | 9 | import { UserProfile as DefaultUserProfile } from "../user-profile"; 10 | import { useStyles } from "./styles"; 11 | 12 | export type SideDrawerProps = { 13 | UserProfile: any; 14 | layoutStyles: any; 15 | iconStyle: any; 16 | sidebarOpenWidth: number; 17 | sidebarClosedWidth: number; 18 | sidebarElevation: number 19 | showDividers: boolean 20 | }; 21 | 22 | export const SideDrawer: React.FC = ({ 23 | children, 24 | UserProfile, 25 | layoutStyles, 26 | iconStyle, 27 | sidebarOpenWidth, 28 | sidebarClosedWidth, 29 | sidebarElevation, 30 | showDividers 31 | }) => { 32 | const isSidebarOpen = useSelector((state) => state.admin.ui.sidebarOpen); 33 | const logout: any = useLogout(); 34 | 35 | const styles = useStyles(); 36 | 37 | return ( 38 | 63 | <> 64 | 65 | {showDividers && } 66 | {children} 67 | {showDividers && } 68 | } 73 | className={clsx( 74 | styles.listItem, 75 | layoutStyles.listItem, 76 | layoutStyles.logoutButton 77 | )} 78 | primaryText="Cerrar Sesión" 79 | sidebarIsOpen={isSidebarOpen} 80 | /> 81 | 82 | 83 | ); 84 | }; 85 | 86 | SideDrawer.displayName = "SideDrawer"; 87 | 88 | SideDrawer.defaultProps = { 89 | UserProfile: DefaultUserProfile, 90 | }; 91 | -------------------------------------------------------------------------------- /packages/ra-layout/src/layout/components/side-drawer/styles.ts: -------------------------------------------------------------------------------- 1 | import { makeStyles } from "@material-ui/core/styles"; 2 | 3 | export const useStyles = makeStyles((theme) => ({ 4 | listItem: { 5 | minHeight: "48px !important", 6 | }, 7 | })); 8 | -------------------------------------------------------------------------------- /packages/ra-layout/src/layout/components/user-profile/index.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | import React from "react"; 3 | import Avatar from "@material-ui/core/Avatar"; 4 | import Tooltip from "@material-ui/core/Tooltip"; 5 | import { MenuItemLink, useGetIdentity } from "react-admin"; 6 | 7 | import PersonOutlined from "@material-ui/icons/PersonOutlined"; 8 | 9 | import { useStyles } from "./styles"; 10 | 11 | // TODO: improve typings 12 | export type UserProfileProps = { 13 | layoutStyles?: any; 14 | }; 15 | 16 | // TODO: improve component 17 | export const UserProfile: React.FC = ({ layoutStyles }) => { 18 | const { loading, identity: user } = useGetIdentity(); 19 | 20 | const styles = useStyles(); 21 | 22 | if (!loading && !!user) { 23 | const firstLetters = user?.fullName 24 | ?.split(" ") 25 | .map((parts: any) => parts[0]) 26 | .join("") 27 | .toUpperCase(); 28 | 29 | return ( 30 | 31 | 34 | {!!user && user.avatar && ( 35 | 40 | )} 41 | {(!user || (!!user && !user.avatar)) && ( 42 | 43 | {firstLetters} 44 | 45 | )} 46 | 47 | } 48 | primaryText={user?.fullName} 49 | className={clsx(styles.menuLink, layoutStyles.menuLink)} 50 | to="/" 51 | sidebarIsOpen 52 | /> 53 | 54 | ); 55 | } 56 | 57 | return ( 58 | } 63 | sidebarIsOpen 64 | /> 65 | ); 66 | }; 67 | 68 | UserProfile.displayName = "UserProfile"; 69 | -------------------------------------------------------------------------------- /packages/ra-layout/src/layout/components/user-profile/styles.ts: -------------------------------------------------------------------------------- 1 | import { makeStyles } from "@material-ui/core/styles"; 2 | 3 | export const useStyles = makeStyles((theme) => ({ 4 | root: { 5 | display: "flex", 6 | }, 7 | small: { 8 | width: theme.spacing(3), 9 | height: theme.spacing(3), 10 | fontSize: "0.75rem", 11 | }, 12 | menuLink: { 13 | // TODO: improve overrides 14 | minHeight: "56px !important", 15 | fontWeight: "bold", 16 | textTransform: "none", 17 | }, 18 | })); 19 | -------------------------------------------------------------------------------- /packages/ra-layout/src/layout/index.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | import React, { useEffect } from "react"; 3 | import { useSelector, useDispatch } from "react-redux"; 4 | import { Notification, setSidebarVisibility } from "react-admin"; 5 | 6 | import { Header } from "./components/header"; 7 | import { SideDrawer } from "./components/side-drawer"; 8 | import { NestedMenu } from "./components/nested-menu"; 9 | 10 | import { useStyles } from "./styles"; 11 | 12 | export type LayoutStylesProps = { 13 | /** 14 | * Styles applied to root container 15 | */ 16 | root?: any; 17 | /** 18 | * Styles applied to second container 19 | */ 20 | container?: any; 21 | /** 22 | * Styles applied to appBar 23 | */ 24 | appBar?: any; 25 | /** 26 | * Styles applied to sidebar when is open 27 | */ 28 | sidebarWhenOpen?: any; 29 | /** 30 | * Styles applied to sidebar when is closed 31 | */ 32 | sidebarWhenClosed?: any; 33 | /** 34 | * Styles applied to menu list items 35 | */ 36 | listItem?: any; 37 | /** 38 | * Styles applied to user profile menu link 39 | */ 40 | menuLink?: any; 41 | /** 42 | * Styles applied to logout button 43 | */ 44 | logoutButton?: any; 45 | /** 46 | * Styles applied to user profile avatar 47 | */ 48 | avatar?: any 49 | }; 50 | 51 | // TODO: improve typings 52 | export type LayoutProps = { 53 | Menu?: any; 54 | AppBar?: any; 55 | Sidebar?: any; 56 | items: any[]; 57 | title?: string; 58 | dashboard?: any; 59 | layoutStyles?: LayoutStylesProps; 60 | iconStyle?: any; 61 | sidebarOpenWidth?: number; 62 | sidebarClosedWidth?: number; 63 | sidebarElevation?: number 64 | showDividers?: boolean 65 | logo?: string 66 | logoStyle: any 67 | }; 68 | 69 | export const Layout: React.FC = ({ 70 | title, 71 | items, 72 | children, 73 | dashboard, 74 | AppBar = Header, 75 | Menu = NestedMenu, 76 | Sidebar = SideDrawer, 77 | layoutStyles, 78 | iconStyle, 79 | sidebarOpenWidth, 80 | sidebarClosedWidth, 81 | sidebarElevation = 2, 82 | showDividers = true, 83 | logo, 84 | logoStyle 85 | }) => { 86 | const isSidebarOpen = useSelector((state) => state.admin.ui.sidebarOpen); 87 | const dispatch = useDispatch(); 88 | 89 | const styles = useStyles(); 90 | 91 | useEffect(() => { 92 | dispatch(setSidebarVisibility(true)); 93 | 94 | // eslint-disable-next-line react-hooks/exhaustive-deps 95 | }, [setSidebarVisibility]); 96 | 97 | return ( 98 |
99 |
100 | 112 |
113 | 121 | 127 | 128 |
133 | {children} 134 |
135 |
136 | 137 |
138 |
139 | ); 140 | }; 141 | 142 | Layout.displayName = "Layout"; 143 | 144 | Layout.defaultProps = { 145 | sidebarOpenWidth: 240, 146 | sidebarClosedWidth: 55, 147 | layoutStyles: { 148 | root: {}, 149 | container: {}, 150 | appBar: {}, 151 | sidebarWhenOpen: {}, 152 | sidebarWhenClosed: {}, 153 | listItem: {}, 154 | menuLink: {}, 155 | logoutButton: {}, 156 | }, 157 | }; 158 | -------------------------------------------------------------------------------- /packages/ra-layout/src/layout/styles.ts: -------------------------------------------------------------------------------- 1 | import { makeStyles } from "@material-ui/core/styles"; 2 | 3 | // TODO: add support to configure appBarHeight, sidebarMinWidth, sidebarMaxWidth 4 | export const useStyles = makeStyles((theme) => ({ 5 | root: { 6 | zIndex: 1000, 7 | display: "flex", 8 | minHeight: "100vh", 9 | position: "relative", 10 | flexDirection: "column", 11 | backgroundColor: theme.palette.background.default, 12 | }, 13 | container: { 14 | display: "flex", 15 | overflowX: "auto", 16 | flexDirection: "column", 17 | height: "100vh", 18 | }, 19 | appBar: { 20 | height: 56, 21 | }, 22 | appBarWhenSidebarOpen: { 23 | width: "calc(100% - 240px)", 24 | }, 25 | appBarWhenSidebarClosed: { 26 | width: "calc(100% - 55px)", 27 | }, 28 | contentWithSidebar: { 29 | display: "flex", 30 | flexGrow: 1, 31 | }, 32 | content: { 33 | flexGrow: 2, 34 | display: "flex", 35 | marginTop: "3em", 36 | flexDirection: "column", 37 | padding: theme.spacing(3), 38 | }, 39 | })); 40 | -------------------------------------------------------------------------------- /packages/ra-layout/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true, 25 | "skipLibCheck": true 26 | }, 27 | "include": ["src/**/*"], 28 | "exclude": ["node_modules"] 29 | } 30 | -------------------------------------------------------------------------------- /packages/ra-ldap-auth/README.md: -------------------------------------------------------------------------------- 1 | # `ra-ldap-auth` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const raLdapAuth = require('ra-ldap-auth'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/ra-ldap-auth/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ["@babel/preset-typescript", "@babel/preset-react"], 6 | plugins: [ 7 | "@babel/plugin-proposal-object-rest-spread", 8 | "@babel/plugin-proposal-class-properties", 9 | ], 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ra-ldap-auth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-ldap-auth", 3 | "version": "0.0.0", 4 | "description": "> TODO: description", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/preset-react": "^7.10.4", 22 | "@babel/preset-typescript": "^7.10.4", 23 | "@pika/pack": "^0.5.0", 24 | "@pika/plugin-build-types": "^0.9.2", 25 | "@pika/plugin-build-web": "^0.9.2", 26 | "@pika/plugin-standard-pkg": "^0.9.2", 27 | "@types/react": "^16.9.48", 28 | "react": "^16.13.1", 29 | "rimraf": "^3.0.2", 30 | "typescript": "^3.9.7" 31 | }, 32 | "peerDependencies": { 33 | "react": "^16.11.0" 34 | }, 35 | "@pika/pack": { 36 | "pipeline": [ 37 | [ 38 | "@pika/plugin-standard-pkg" 39 | ], 40 | [ 41 | "@pika/plugin-build-web" 42 | ], 43 | [ 44 | "@pika/plugin-build-types" 45 | ] 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/ra-ldap-auth/src/index.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = raLdapAuth; 4 | 5 | function raLdapAuth() { 6 | // TODO 7 | } 8 | -------------------------------------------------------------------------------- /packages/ra-ldap-auth/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true 25 | }, 26 | "include": ["src/**/*"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/ra-messaging/README.md: -------------------------------------------------------------------------------- 1 | # `ra-messaging` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const raMessaging = require('ra-messaging'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/ra-messaging/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ["@babel/preset-typescript", "@babel/preset-react"], 6 | plugins: [ 7 | "@babel/plugin-proposal-object-rest-spread", 8 | "@babel/plugin-proposal-class-properties", 9 | ], 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ra-messaging/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-messaging", 3 | "version": "0.0.0", 4 | "description": "> TODO: description", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/preset-react": "^7.10.4", 22 | "@babel/preset-typescript": "^7.10.4", 23 | "@pika/pack": "^0.5.0", 24 | "@pika/plugin-build-types": "^0.9.2", 25 | "@pika/plugin-build-web": "^0.9.2", 26 | "@pika/plugin-standard-pkg": "^0.9.2", 27 | "@types/react": "^16.9.48", 28 | "react": "^16.13.1", 29 | "rimraf": "^3.0.2", 30 | "typescript": "^3.9.7" 31 | }, 32 | "peerDependencies": { 33 | "react": "^16.11.0" 34 | }, 35 | "@pika/pack": { 36 | "pipeline": [ 37 | [ 38 | "@pika/plugin-standard-pkg" 39 | ], 40 | [ 41 | "@pika/plugin-build-web" 42 | ], 43 | [ 44 | "@pika/plugin-build-types" 45 | ] 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/ra-messaging/src/index.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = raMessaging; 4 | 5 | function raMessaging() { 6 | // TODO 7 | } 8 | -------------------------------------------------------------------------------- /packages/ra-messaging/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true 25 | }, 26 | "include": ["src/**/*"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/ra-navigation/README.md: -------------------------------------------------------------------------------- 1 | # `ra-navigation` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const raNavigation = require('ra-navigation'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/ra-navigation/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ["@babel/preset-typescript", "@babel/preset-react"], 6 | plugins: [ 7 | "@babel/plugin-proposal-object-rest-spread", 8 | "@babel/plugin-proposal-class-properties", 9 | ], 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ra-navigation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-navigation", 3 | "version": "0.0.0", 4 | "description": "> TODO: description", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/preset-react": "^7.10.4", 22 | "@babel/preset-typescript": "^7.10.4", 23 | "@pika/pack": "^0.5.0", 24 | "@pika/plugin-build-types": "^0.9.2", 25 | "@pika/plugin-build-web": "^0.9.2", 26 | "@pika/plugin-standard-pkg": "^0.9.2", 27 | "@types/react": "^16.9.48", 28 | "react": "^16.13.1", 29 | "rimraf": "^3.0.2", 30 | "typescript": "^3.9.7" 31 | }, 32 | "peerDependencies": { 33 | "react": "^16.11.0" 34 | }, 35 | "@pika/pack": { 36 | "pipeline": [ 37 | [ 38 | "@pika/plugin-standard-pkg" 39 | ], 40 | [ 41 | "@pika/plugin-build-web" 42 | ], 43 | [ 44 | "@pika/plugin-build-types" 45 | ] 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/ra-navigation/src/index.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = raNavigation; 4 | 5 | function raNavigation() { 6 | // TODO 7 | } 8 | -------------------------------------------------------------------------------- /packages/ra-navigation/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true 25 | }, 26 | "include": ["src/**/*"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/ra-notifications/README.md: -------------------------------------------------------------------------------- 1 | # `ra-notifications` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const raNotifications = require('ra-notifications'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/ra-notifications/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ["@babel/preset-typescript", "@babel/preset-react"], 6 | plugins: [ 7 | "@babel/plugin-proposal-object-rest-spread", 8 | "@babel/plugin-proposal-class-properties", 9 | ], 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ra-notifications/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-notifications", 3 | "version": "0.0.0", 4 | "description": "> TODO: description", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/preset-react": "^7.10.4", 22 | "@babel/preset-typescript": "^7.10.4", 23 | "@pika/pack": "^0.5.0", 24 | "@pika/plugin-build-types": "^0.9.2", 25 | "@pika/plugin-build-web": "^0.9.2", 26 | "@pika/plugin-standard-pkg": "^0.9.2", 27 | "@types/react": "^16.9.48", 28 | "react": "^16.13.1", 29 | "rimraf": "^3.0.2", 30 | "typescript": "^3.9.7" 31 | }, 32 | "peerDependencies": { 33 | "react": "^16.11.0" 34 | }, 35 | "@pika/pack": { 36 | "pipeline": [ 37 | [ 38 | "@pika/plugin-standard-pkg" 39 | ], 40 | [ 41 | "@pika/plugin-build-web" 42 | ], 43 | [ 44 | "@pika/plugin-build-types" 45 | ] 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/ra-notifications/src/index.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = raNotifications; 4 | 5 | function raNotifications() { 6 | // TODO 7 | } 8 | -------------------------------------------------------------------------------- /packages/ra-notifications/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true 25 | }, 26 | "include": ["src/**/*"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/ra-preferences/README.md: -------------------------------------------------------------------------------- 1 | # `ra-preferences` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const raPreferences = require('ra-preferences'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/ra-preferences/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ["@babel/preset-typescript", "@babel/preset-react"], 6 | plugins: [ 7 | "@babel/plugin-proposal-object-rest-spread", 8 | "@babel/plugin-proposal-class-properties", 9 | ], 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ra-preferences/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-preferences", 3 | "version": "0.0.0", 4 | "description": "> TODO: description", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/preset-react": "^7.10.4", 22 | "@babel/preset-typescript": "^7.10.4", 23 | "@pika/pack": "^0.5.0", 24 | "@pika/plugin-build-types": "^0.9.2", 25 | "@pika/plugin-build-web": "^0.9.2", 26 | "@pika/plugin-standard-pkg": "^0.9.2", 27 | "@types/react": "^16.9.48", 28 | "react": "^16.13.1", 29 | "rimraf": "^3.0.2", 30 | "typescript": "^3.9.7" 31 | }, 32 | "peerDependencies": { 33 | "react": "^16.11.0" 34 | }, 35 | "@pika/pack": { 36 | "pipeline": [ 37 | [ 38 | "@pika/plugin-standard-pkg" 39 | ], 40 | [ 41 | "@pika/plugin-build-web" 42 | ], 43 | [ 44 | "@pika/plugin-build-types" 45 | ] 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/ra-preferences/src/index.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = raPreferences; 4 | 5 | function raPreferences() { 6 | // TODO 7 | } 8 | -------------------------------------------------------------------------------- /packages/ra-preferences/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true 25 | }, 26 | "include": ["src/**/*"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/ra-rbac/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-typescript", "@babel/preset-react"], 3 | "plugins": [ 4 | "@babel/plugin-proposal-object-rest-spread", 5 | "@babel/plugin-proposal-class-properties" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/ra-rbac/README.md: -------------------------------------------------------------------------------- 1 | # RA RBAC [![License: MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT) 2 | 3 | Role based Access Control for `React Admin`. 4 | 5 | ## Install 6 | 7 | You can install this library via NPM or YARN. 8 | 9 | ### NPM 10 | 11 | ```bash 12 | npm i @blackbox-vision/ra-rbac 13 | ``` 14 | 15 | ### YARN 16 | 17 | ```bash 18 | yarn add @blackbox-vision/ra-rbac 19 | ``` 20 | 21 | ## Use case 22 | 23 | You need to have fine grained permissions over your `React Admin` app. 24 | 25 | ## Usage 26 | 27 | The usage is really simple: 28 | 29 | 1. Define your `canActivate` function like the following: 30 | 31 | ```typescript 32 | // canActivate.ts 33 | import { Permission } from "@blackbox-vision/ra-rbac"; 34 | 35 | export const canActivate = ( 36 | permissions: Permission[] | any, 37 | resource: string, 38 | action: string, 39 | field?: string 40 | ) => { 41 | // Your can activate logic 42 | return true; 43 | }; 44 | ``` 45 | 46 | 2. Import `RbacProvider` and `RbacResource` and wrap your `React Admin` with it: 47 | 48 | ```typescript 49 | // App.tsx 50 | import React from "react"; 51 | import { Admin } from "react-admin"; 52 | import jsonServerProvider from "ra-data-json-server"; 53 | import { 54 | RbacProvider, 55 | RbacResource as Resource, 56 | } from "@blackbox-vision/ra-rbac"; 57 | 58 | import { canActivate } from "./canActivate"; 59 | 60 | export const App = () => { 61 | const dataProvider = jsonServerProvider( 62 | "https://jsonplaceholder.typicode.com" 63 | ); 64 | 65 | return ( 66 | 67 | 68 | 69 | 70 | 71 | ); 72 | }; 73 | 74 | App.displayName = "App"; 75 | ``` 76 | 77 | ## Props 78 | 79 | ### RbacProvider 80 | 81 | `RbacProvider` has the following props: 82 | 83 | | Properties | Types | Default Value | Description | 84 | | ------------- | ---------- | ---------------------- | ------------------------------------------------------------------------------------- | 85 | | `canActivate` | `Function` | `(p, r, a, f) => true` | Logic to test if a user can perform an specific action or visualize an specific field | 86 | 87 | ### RbacResource 88 | 89 | `RbacResource` has the same props as `RA Resource`. 90 | 91 | ## Issues 92 | 93 | Please, open an [issue](https://github.com/BlackBoxVision/react-admin-extensions/issues) following one of the issues templates. We will do our best to fix them. 94 | 95 | ## Contributing 96 | 97 | If you want to contribute to this project see [contributing](https://github.com/BlackBoxVision/react-admin-extensions/blob/master/CONTRIBUTING.md) for more information. 98 | 99 | ## License 100 | 101 | Distributed under the **MIT license**. See [LICENSE](https://github.com/BlackBoxVision/react-admin-extensions/blob/master/LICENSE) for more information. 102 | -------------------------------------------------------------------------------- /packages/ra-rbac/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-rbac", 3 | "version": "4.0.0", 4 | "description": "RBAC support for React Admin", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/preset-react": "^7.10.4", 22 | "@babel/preset-typescript": "^7.10.4", 23 | "@pika/pack": "^0.5.0", 24 | "@pika/plugin-build-types": "^0.9.2", 25 | "@pika/plugin-build-web": "^0.9.2", 26 | "@pika/plugin-standard-pkg": "^0.9.2", 27 | "@types/react": "^16.9.48", 28 | "react": "^16.13.1", 29 | "react-admin": "^4.4.0", 30 | "react-dom": "^18.2.0", 31 | "rimraf": "^3.0.2", 32 | "typescript": "^3.9.7" 33 | }, 34 | "peerDependencies": { 35 | "react": "^16.8.0" 36 | }, 37 | "@pika/pack": { 38 | "pipeline": [ 39 | [ 40 | "@pika/plugin-standard-pkg" 41 | ], 42 | [ 43 | "@pika/plugin-build-web" 44 | ] 45 | ] 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /packages/ra-rbac/src/components/rbac-fields/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { 3 | BooleanField as RaBooleanFiled, 4 | ChipField as RaChipField, 5 | DateField as RaDateField, 6 | EmailField as RaEmailField, 7 | ImageField as RaImageField, 8 | FileField as RaFileField, 9 | NumberField as RaNumberField, 10 | RichTextField as RaRichTextField, 11 | TextField as RaTextField, 12 | UrlField as RaUrlField, 13 | SelectField as RaSelectField, 14 | ArrayField as RaArrayField, 15 | ReferenceField as RaReferenceField, 16 | ReferenceManyField as RaReferenceManyField, 17 | ReferenceArrayField as RaReferenceArrayField, 18 | } from "react-admin"; 19 | 20 | import { RbacField } from "./rbac-field"; 21 | import { ComponentProps } from "../../types"; 22 | 23 | export const BooleanField: React.FC> = ( 24 | props 25 | ) => ; 26 | 27 | export const ChipField: React.FC> = ( 28 | props 29 | ) => ; 30 | 31 | export const DateField: React.FC> = ( 32 | props 33 | ) => ; 34 | 35 | export const EmailField: React.FC> = ( 36 | props 37 | ) => ; 38 | 39 | export const ImageField: React.FC> = ( 40 | props 41 | ) => ; 42 | 43 | export const FileField: React.FC> = ( 44 | props 45 | ) => ; 46 | 47 | export const NumberField: React.FC> = ( 48 | props 49 | ) => ; 50 | 51 | export const RichTextField: React.FC> = ( 52 | props 53 | ) => ; 54 | 55 | export const TextField: React.FC> = ( 56 | props 57 | ) => ; 58 | 59 | export const UrlField: React.FC> = ( 60 | props 61 | ) => ; 62 | 63 | export const SelectField: React.FC> = ( 64 | props 65 | ) => ; 66 | 67 | export const ArrayField: React.FC> = ( 68 | props 69 | ) => ; 70 | 71 | export const ReferenceField: React.FC< 72 | ComponentProps 73 | > = (props) => ; 74 | 75 | export const ReferenceManyField: React.FC< 76 | ComponentProps 77 | > = (props) => ; 78 | 79 | export const ReferenceArrayField: React.FC< 80 | ComponentProps 81 | > = (props) => ; 82 | -------------------------------------------------------------------------------- /packages/ra-rbac/src/components/rbac-fields/rbac-field.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { useIsListOrShow } from "../../hooks/use-is-list-or-show"; 4 | import { useGetCanActivate } from "../../hooks/use-get-can-activate"; 5 | 6 | export type RbacFieldProps = { 7 | component: any; 8 | [key: string]: any; 9 | }; 10 | 11 | export const RbacField: React.FC = ({ 12 | component: Field, 13 | resource, 14 | source, 15 | ...props 16 | }) => { 17 | const { loaded, canActivate } = useGetCanActivate(); 18 | const { action } = useIsListOrShow(); 19 | 20 | if (!loaded && !canActivate) { 21 | return null; 22 | } 23 | 24 | if (!source) { 25 | return ( 26 | 33 | ); 34 | } 35 | 36 | if (canActivate(resource, action, source)) { 37 | return ( 38 | 45 | ); 46 | } 47 | 48 | return null; 49 | }; 50 | 51 | RbacField.displayName = "RbacField"; 52 | -------------------------------------------------------------------------------- /packages/ra-rbac/src/components/rbac-inputs/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { 3 | TextInput as RaTextInput, 4 | BooleanInput as RaBooleanInput, 5 | NullableBooleanInput as RaNullableBooleanInput, 6 | DateInput as RaDateInput, 7 | DateTimeInput as RaDateTimeInput, 8 | ImageInput as RaImageInput, 9 | FileInput as RaFileInput, 10 | NumberInput as RaNumberInput, 11 | PasswordInput as RaPasswordInput, 12 | AutocompleteInput as RaAutocompleteInput, 13 | RadioButtonGroupInput as RaRadioButtonGroupInput, 14 | SelectInput as RaSelectInput, 15 | ArrayInput as RaArrayInput, 16 | AutocompleteArrayInput as RaAutocompleteArrayInput, 17 | CheckboxGroupInput as RaCheckboxGroupInput, 18 | SelectArrayInput as RaSelectArrayInput, 19 | ReferenceArrayInput as RaReferenceArrayInput, 20 | ReferenceInput as RaReferenceInput, 21 | } from "react-admin"; 22 | 23 | import { RbacInput } from "./rbac-input"; 24 | import { ComponentProps } from "../../types"; 25 | 26 | export const TextInput: React.FC> = ( 27 | props 28 | ) => ; 29 | 30 | export const BooleanInput: React.FC> = ( 31 | props 32 | ) => ; 33 | 34 | export const NullableBooleanInput: React.FC< 35 | ComponentProps 36 | > = (props) => ; 37 | 38 | export const DateInput: React.FC> = ( 39 | props 40 | ) => ; 41 | 42 | export const DateTimeInput: React.FC> = ( 43 | props 44 | ) => ; 45 | 46 | export const ImageInput: React.FC> = ( 47 | props 48 | ) => ; 49 | 50 | export const FileInput: React.FC> = ( 51 | props 52 | ) => ; 53 | 54 | export const NumberInput: React.FC> = ( 55 | props 56 | ) => ; 57 | 58 | export const PasswordInput: React.FC> = ( 59 | props 60 | ) => ; 61 | 62 | export const AutocompleteInput: React.FC< 63 | ComponentProps 64 | > = (props) => ; 65 | 66 | export const RadioButtonGroupInput: React.FC< 67 | ComponentProps 68 | > = (props) => ; 69 | 70 | export const SelectInput: React.FC> = ( 71 | props 72 | ) => ; 73 | 74 | export const ArrayInput: React.FC> = ( 75 | props 76 | ) => ; 77 | 78 | export const AutocompleteArrayInput: React.FC< 79 | ComponentProps 80 | > = (props) => ; 81 | 82 | export const CheckboxGroupInput: React.FC< 83 | ComponentProps 84 | > = (props) => ; 85 | 86 | export const SelectArrayInput: React.FC< 87 | ComponentProps 88 | > = (props) => ; 89 | 90 | export const ReferenceArrayInput: React.FC< 91 | ComponentProps 92 | > = (props) => ; 93 | 94 | export const ReferenceInput: React.FC< 95 | ComponentProps 96 | > = (props) => ; 97 | -------------------------------------------------------------------------------- /packages/ra-rbac/src/components/rbac-inputs/rbac-input.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { useIsCreateOrEdit } from "../../hooks/use-is-create-or-edit"; 4 | import { useGetCanActivate } from "../../hooks/use-get-can-activate"; 5 | 6 | export type RbacInputProps = { 7 | component: any; 8 | [key: string]: any; 9 | }; 10 | 11 | // TODO: review how to type this component 12 | export const RbacInput: React.FC = ({ 13 | component: Input, 14 | resource, 15 | source, 16 | ...props 17 | }) => { 18 | const { loaded, canActivate } = useGetCanActivate(); 19 | const { action } = useIsCreateOrEdit(); 20 | 21 | if (!loaded && !canActivate) { 22 | return null; 23 | } 24 | 25 | if (!source) { 26 | return ( 27 | 34 | ); 35 | } 36 | 37 | if (canActivate(resource, action, source)) { 38 | return ( 39 | 46 | ); 47 | } 48 | 49 | return null; 50 | }; 51 | 52 | RbacInput.displayName = "RbacInput"; 53 | -------------------------------------------------------------------------------- /packages/ra-rbac/src/components/rbac-provider/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { RbacContext, CanActivateFunction } from "../../contexts/rbac"; 4 | 5 | export type RbacProviderProps = { 6 | canActivate?: CanActivateFunction; 7 | }; 8 | 9 | export const RbacProvider: React.FC = ({ 10 | canActivate, 11 | children, 12 | }) => { 13 | return ( 14 | {children} 15 | ); 16 | }; 17 | 18 | RbacProvider.displayName = "RbacProvider"; 19 | RbacProvider.defaultProps = { 20 | // This let's any route pass by setting canActivate return value to true 21 | canActivate: (p, r, a, f) => true, 22 | }; 23 | -------------------------------------------------------------------------------- /packages/ra-rbac/src/components/rbac-resource/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Resource, ResourceProps } from "react-admin"; 3 | 4 | import { useGetCanActivate } from "../../hooks/use-get-can-activate"; 5 | 6 | export const RbacResource: React.FC = ({ 7 | name, 8 | list, 9 | edit, 10 | show, 11 | create, 12 | ...rest 13 | }) => { 14 | const { loaded, canActivate } = useGetCanActivate(); 15 | 16 | if (!loaded && !canActivate) { 17 | return null; 18 | } 19 | 20 | return ( 21 | 29 | ); 30 | }; 31 | 32 | RbacResource.displayName = "RbacResource"; 33 | -------------------------------------------------------------------------------- /packages/ra-rbac/src/contexts/rbac/index.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export type Permission = { 4 | resource: string; 5 | action: string; 6 | fields?: string[]; 7 | }; 8 | 9 | export type CanActivateFunction = ( 10 | permissions: Permission[] | any, 11 | resource: string, 12 | action: string, 13 | field?: string 14 | ) => boolean; 15 | 16 | export type ReducedCanActivateFunction = ( 17 | resource: string, 18 | action: string, 19 | field?: string 20 | ) => boolean; 21 | 22 | export const RbacContext = React.createContext(null); 23 | -------------------------------------------------------------------------------- /packages/ra-rbac/src/hooks/use-get-can-activate.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from "react"; 2 | import { usePermissions } from "react-admin"; 3 | 4 | import { RbacContext, ReducedCanActivateFunction } from "../contexts/rbac"; 5 | 6 | export type UseGetCanActivateReturn = { 7 | canActivate: ReducedCanActivateFunction | null; 8 | loaded: boolean; 9 | }; 10 | 11 | export const useGetCanActivate = (): UseGetCanActivateReturn => { 12 | const canActivate = useContext(RbacContext); 13 | 14 | const { isLoading, permissions } = usePermissions(); 15 | 16 | return { 17 | canActivate: !!permissions 18 | ? (resource: string, action: string, field?: string) => 19 | canActivate(permissions, resource, action, field) 20 | : null, 21 | loaded: !isLoading && !!permissions, 22 | }; 23 | }; 24 | -------------------------------------------------------------------------------- /packages/ra-rbac/src/hooks/use-is-create-or-edit.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from "react"; 2 | import { CreateContext, EditContext } from "react-admin"; 3 | 4 | export const useIsCreateOrEdit = () => { 5 | const create = useContext(CreateContext); 6 | const edit = useContext(EditContext); 7 | 8 | if (!!create.resource) { 9 | return { 10 | action: "create", 11 | }; 12 | } 13 | 14 | if (!!edit.resource) { 15 | return { 16 | action: "edit", 17 | }; 18 | } 19 | 20 | return { 21 | action: null, 22 | }; 23 | }; 24 | -------------------------------------------------------------------------------- /packages/ra-rbac/src/hooks/use-is-list-or-show.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from "react"; 2 | import { ListContext, ShowContext } from "react-admin"; 3 | 4 | export const useIsListOrShow = () => { 5 | const list = useContext(ListContext); 6 | const show = useContext(ShowContext); 7 | 8 | if (!!list.resource) { 9 | return { 10 | action: "list", 11 | }; 12 | } 13 | 14 | if (!!show.resource) { 15 | return { 16 | action: "show", 17 | }; 18 | } 19 | 20 | return { 21 | action: null, 22 | }; 23 | }; 24 | -------------------------------------------------------------------------------- /packages/ra-rbac/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./contexts/rbac"; 2 | 3 | export * from "./components/rbac-fields"; 4 | export * from "./components/rbac-inputs"; 5 | export * from "./components/rbac-provider"; 6 | export * from "./components/rbac-resource"; 7 | export * from "./components/rbac-fields/rbac-field"; 8 | export * from "./components/rbac-inputs/rbac-input"; 9 | 10 | export * from "./hooks/use-get-can-activate"; 11 | -------------------------------------------------------------------------------- /packages/ra-rbac/src/types/index.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export type ComponentProps = T extends 4 | | React.ComponentType 5 | | React.Component 6 | ? JSX.LibraryManagedAttributes 7 | : never; 8 | -------------------------------------------------------------------------------- /packages/ra-rbac/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true, 25 | "skipLibCheck": true 26 | }, 27 | "include": ["src/**/*"], 28 | "exclude": ["node_modules"] 29 | } 30 | -------------------------------------------------------------------------------- /packages/ra-realtime/README.md: -------------------------------------------------------------------------------- 1 | # `ra-realtime` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const raRealtime = require('ra-realtime'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/ra-realtime/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ["@babel/preset-typescript", "@babel/preset-react"], 6 | plugins: [ 7 | "@babel/plugin-proposal-object-rest-spread", 8 | "@babel/plugin-proposal-class-properties", 9 | ], 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ra-realtime/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-realtime", 3 | "version": "0.0.0", 4 | "description": "> TODO: description", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/preset-react": "^7.10.4", 22 | "@babel/preset-typescript": "^7.10.4", 23 | "@pika/pack": "^0.5.0", 24 | "@pika/plugin-build-types": "^0.9.2", 25 | "@pika/plugin-build-web": "^0.9.2", 26 | "@pika/plugin-standard-pkg": "^0.9.2", 27 | "@types/react": "^16.9.48", 28 | "react": "^16.13.1", 29 | "rimraf": "^3.0.2", 30 | "typescript": "^3.9.7" 31 | }, 32 | "peerDependencies": { 33 | "react": "^16.11.0" 34 | }, 35 | "@pika/pack": { 36 | "pipeline": [ 37 | [ 38 | "@pika/plugin-standard-pkg" 39 | ], 40 | [ 41 | "@pika/plugin-build-web" 42 | ], 43 | [ 44 | "@pika/plugin-build-types" 45 | ] 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/ra-realtime/src/index.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = raRealtime; 4 | 5 | function raRealtime() { 6 | // TODO 7 | } 8 | -------------------------------------------------------------------------------- /packages/ra-realtime/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true 25 | }, 26 | "include": ["src/**/*"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/ra-relationships/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-typescript", "@babel/preset-react"], 3 | "plugins": [ 4 | "@babel/plugin-proposal-object-rest-spread", 5 | "@babel/plugin-proposal-optional-chaining", 6 | "@babel/plugin-proposal-class-properties" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /packages/ra-relationships/README.md: -------------------------------------------------------------------------------- 1 | # `ra-relationships` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const raRelationships = require('ra-relationships'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/ra-relationships/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-relationships", 3 | "version": "0.0.4", 4 | "description": "> TODO: description", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/plugin-proposal-optional-chaining": "^7.14.2", 22 | "@babel/preset-react": "^7.10.4", 23 | "@babel/preset-typescript": "^7.10.4", 24 | "@pika/pack": "^0.5.0", 25 | "@pika/plugin-build-types": "^0.9.2", 26 | "@pika/plugin-build-web": "^0.9.2", 27 | "@pika/plugin-standard-pkg": "^0.9.2", 28 | "@types/react": "^16.9.48", 29 | "react": "^16.13.1", 30 | "react-admin": "^3.13.5", 31 | "rimraf": "^3.0.2", 32 | "typescript": "^3.9.7" 33 | }, 34 | "peerDependencies": { 35 | "react": "^16.11.0" 36 | }, 37 | "@pika/pack": { 38 | "pipeline": [ 39 | [ 40 | "@pika/plugin-standard-pkg" 41 | ], 42 | [ 43 | "@pika/plugin-build-web" 44 | ] 45 | ] 46 | }, 47 | "dependencies": { 48 | "lodash.get": "^4.4.2", 49 | "lodash.isequal": "^4.5.0" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /packages/ra-relationships/src/components/many-to-many-reference-context-provider/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { ManyToManyContext } from "../../contexts/many-to-many"; 4 | 5 | export type ManyToManyReferenceContextProviderProps = {}; 6 | 7 | export const ManyToManyReferenceContextProvider: React.FC = ({ 8 | children, 9 | }) => { 10 | // TODO: define value to pass and logic 11 | return ( 12 | 13 | {children} 14 | 15 | ); 16 | }; 17 | 18 | ManyToManyReferenceContextProvider.displayName = "ManyToManyReferenceContextProvider"; 19 | -------------------------------------------------------------------------------- /packages/ra-relationships/src/components/many-to-many-reference-field-view/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { 3 | useListContext, 4 | LinearProgress, 5 | ListControllerProps, 6 | sanitizeFieldRestProps, 7 | } from "react-admin"; 8 | import { makeStyles } from "@material-ui/core/styles"; 9 | 10 | import { ReferenceManyToManyFieldProps } from "../many-to-many-reference-field"; 11 | 12 | export type ReferenceManyToManyFieldViewProps = Omit< 13 | ReferenceManyToManyFieldProps, 14 | "basePath" | "resource" | "page" | "perPage" 15 | > & 16 | ListControllerProps & { 17 | classes?: any; 18 | }; 19 | 20 | export const ReferenceManyToManyFieldView: React.FC = ( 21 | props 22 | ) => { 23 | const { 24 | children, 25 | pagination, 26 | className, 27 | resource, 28 | reference, 29 | ...rest 30 | } = props; 31 | 32 | const classes = useStyles(props); 33 | const { loaded } = useListContext(props); 34 | 35 | if (!loaded) { 36 | return ; 37 | } 38 | 39 | return ( 40 | <> 41 | {React.cloneElement(React.Children.only(children) as any, { 42 | ...sanitizeFieldRestProps(rest), 43 | className, 44 | resource, 45 | })}{" "} 46 | {pagination && 47 | props.total !== undefined && 48 | React.cloneElement(pagination, sanitizeFieldRestProps(rest))} 49 | 50 | ); 51 | }; 52 | 53 | ReferenceManyToManyFieldView.displayName = "ReferenceManyToManyFieldView"; 54 | 55 | const useStyles = makeStyles( 56 | (theme) => ({ 57 | progress: { 58 | marginTop: theme.spacing(2), 59 | }, 60 | }), 61 | { 62 | name: "RaReferenceManyToManyField", 63 | } 64 | ); 65 | -------------------------------------------------------------------------------- /packages/ra-relationships/src/components/many-to-many-reference-field/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { 3 | ResourceContextProvider, 4 | ListContextProvider, 5 | useRecordContext, 6 | } from "react-admin"; 7 | 8 | import { useReferenceManyToManyFieldController } from "../../hooks/use-reference-many-to-many-field-controller"; 9 | 10 | import { ReferenceManyToManyFieldView } from "../many-to-many-reference-field-view"; 11 | 12 | export type ReferenceManyToManyFieldProps = { 13 | reference: string; 14 | through: string; 15 | using?: string; 16 | source?: string; 17 | page?: number; 18 | perPage?: number; 19 | pagination?: React.ReactElement; 20 | sort?: any; 21 | filter?: any; 22 | [key: string]: any; 23 | }; 24 | 25 | const PureReferenceManyToManyFieldView = React.memo( 26 | ReferenceManyToManyFieldView 27 | ); 28 | 29 | export const ReferenceManyToManyField: React.FC = ( 30 | props 31 | ) => { 32 | const { 33 | target, 34 | basePath, 35 | resource, 36 | reference, 37 | through, 38 | using, 39 | page, 40 | source, 41 | perPage, 42 | sort, 43 | filter, 44 | children, 45 | } = props; 46 | 47 | const record = useRecordContext(props); 48 | 49 | if (React.Children.count(children) !== 1) { 50 | throw new Error( 51 | " only accepts a single child (like )" 52 | ); 53 | } 54 | 55 | const controllerProps: any = useReferenceManyToManyFieldController({ 56 | basePath, 57 | filter, 58 | target, 59 | page, 60 | perPage, 61 | record, 62 | reference, 63 | resource, 64 | sort, 65 | source, 66 | through, 67 | using, 68 | }); 69 | 70 | return ( 71 | 72 | 73 | 74 | 75 | 76 | ); 77 | }; 78 | 79 | ReferenceManyToManyField.displayName = "ManyToManyReferenceField"; 80 | ReferenceManyToManyField.defaultProps = { 81 | source: "id", 82 | page: 1, 83 | perPage: 25, 84 | }; 85 | -------------------------------------------------------------------------------- /packages/ra-relationships/src/components/many-to-many-reference-input/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export type ReferenceManyToManyInputProps = { 4 | reference: string; 5 | through: string; 6 | using?: string; 7 | source?: string; 8 | sort?: any; 9 | filter?: any; 10 | }; 11 | 12 | export const ReferenceManyToManyInput: React.FC = ({ 13 | reference, 14 | through, 15 | using, 16 | source, 17 | sort, 18 | filter, 19 | children, 20 | }) => { 21 | return null; 22 | }; 23 | 24 | ReferenceManyToManyInput.displayName = "ReferenceManyToManyInput"; 25 | -------------------------------------------------------------------------------- /packages/ra-relationships/src/contexts/many-to-many/index.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | // TODO: define typings 4 | export const ManyToManyContext = React.createContext(null); 5 | -------------------------------------------------------------------------------- /packages/ra-relationships/src/hooks/use-reference-many-to-many-field-controller.ts: -------------------------------------------------------------------------------- 1 | import get from "lodash.get"; 2 | import isEqual from "lodash.isequal"; 3 | import { 4 | useGetMany, 5 | useGetManyReference, 6 | useNotify, 7 | usePaginationState, 8 | useResourceContext, 9 | useSafeSetState, 10 | useSelectionState, 11 | useSortState, 12 | removeEmpty, 13 | Record, 14 | RecordMap, 15 | SortPayload, 16 | } from "ra-core"; 17 | import { useCallback, useEffect, useRef } from "react"; 18 | 19 | interface Options { 20 | basePath?: string; 21 | data?: RecordMap; 22 | filter?: any; 23 | ids?: any[]; 24 | loaded?: boolean; 25 | page?: number; 26 | perPage?: number; 27 | record?: Record; 28 | reference: string; 29 | resource: string; 30 | sort?: SortPayload; 31 | source?: string; 32 | target: string; 33 | total?: number; 34 | through?: string; 35 | using?: string; 36 | } 37 | 38 | const defaultFilter = {}; 39 | 40 | export const useReferenceManyToManyFieldController = (props: Options) => { 41 | const { 42 | through, 43 | using = `${props.resource}_id,${props.reference}_id`, 44 | reference, 45 | record, 46 | filter = defaultFilter, 47 | source, 48 | basePath, 49 | page: initialPage, 50 | perPage: initialPerPage, 51 | sort: initialSort = { field: "id", order: "DESC" }, 52 | } = props; 53 | 54 | const resource = useResourceContext(props); 55 | const notify = useNotify(); 56 | 57 | // pagination logic 58 | const { page, setPage, perPage, setPerPage } = usePaginationState({ 59 | page: initialPage, 60 | perPage: initialPerPage, 61 | }); 62 | 63 | // sort logic 64 | const { sort, setSort: setSortObject } = useSortState(initialSort); 65 | const setSort = useCallback( 66 | (field: string, order: string = "ASC") => { 67 | setSortObject({ field, order }); 68 | setPage(1); 69 | }, 70 | [setPage, setSortObject] 71 | ); 72 | 73 | // selection logic 74 | const { selectedIds, onSelect, onToggleItem, onUnselectItems } = 75 | useSelectionState(); 76 | 77 | // filter logic 78 | const filterRef = useRef(filter); 79 | 80 | const [displayedFilters, setDisplayedFilters] = useSafeSetState<{ 81 | [key: string]: boolean; 82 | }>({}); 83 | 84 | const [filterValues, setFilterValues] = 85 | useSafeSetState<{ 86 | [key: string]: any; 87 | }>(filter); 88 | 89 | const hideFilter = useCallback( 90 | (filterName: string) => { 91 | setDisplayedFilters((previousState) => { 92 | const { [filterName]: _, ...newState } = previousState; 93 | return newState; 94 | }); 95 | setFilterValues((previousState) => { 96 | const { [filterName]: _, ...newState } = previousState; 97 | return newState; 98 | }); 99 | }, 100 | [setDisplayedFilters, setFilterValues] 101 | ); 102 | 103 | const showFilter = useCallback( 104 | (filterName: string, defaultValue: any) => { 105 | setDisplayedFilters((previousState) => ({ 106 | ...previousState, 107 | [filterName]: true, 108 | })); 109 | setFilterValues((previousState) => ({ 110 | ...previousState, 111 | [filterName]: defaultValue, 112 | })); 113 | }, 114 | [setDisplayedFilters, setFilterValues] 115 | ); 116 | 117 | const setFilters = useCallback( 118 | (filters, displayedFilters) => { 119 | setFilterValues(removeEmpty(filters)); 120 | setDisplayedFilters(displayedFilters); 121 | setPage(1); 122 | }, 123 | [setDisplayedFilters, setFilterValues, setPage] 124 | ); 125 | 126 | // handle filter prop change 127 | useEffect(() => { 128 | if (!isEqual(filter, filterRef.current)) { 129 | filterRef.current = filter; 130 | setFilterValues(filter); 131 | } 132 | }); 133 | 134 | const [target, relation] = using.split(","); 135 | const referenceId = get(record, source); 136 | 137 | const state = useGetManyReference( 138 | through, 139 | target, 140 | referenceId, 141 | { page, perPage }, 142 | sort, 143 | filterValues, 144 | resource, 145 | { 146 | onFailure: (error) => 147 | notify( 148 | typeof error === "string" 149 | ? error 150 | : error.message || "ra.notification.http_error", 151 | "warning", 152 | { 153 | _: 154 | typeof error === "string" 155 | ? error 156 | : error && error.message 157 | ? error.message 158 | : undefined, 159 | } 160 | ), 161 | } 162 | ); 163 | 164 | let ids = []; 165 | 166 | if (state.loaded) { 167 | ids = state.ids.map((id) => get(state.data[id], relation)); 168 | } 169 | 170 | const { data, error, loaded, loading } = useGetMany(reference, ids, { 171 | enabled: state.loaded && ids.length > 0, 172 | }); 173 | 174 | return { 175 | basePath: basePath 176 | ? basePath.replace(resource, reference) 177 | : `/${reference}`, 178 | currentSort: sort, 179 | data: data 180 | ?.filter((r) => typeof r !== "undefined") 181 | ?.reduce((prev, current) => { 182 | prev[current.id] = current; 183 | return prev; 184 | }, {}), 185 | defaultTitle: null, 186 | displayedFilters, 187 | error, 188 | filterValues, 189 | hasCreate: false, 190 | hideFilter, 191 | ids, 192 | loaded, 193 | loading, 194 | onSelect, 195 | onToggleItem, 196 | onUnselectItems, 197 | page, 198 | perPage, 199 | resource: reference, 200 | selectedIds, 201 | setFilters, 202 | setPage, 203 | setPerPage, 204 | setSort, 205 | showFilter, 206 | total: data?.length, 207 | }; 208 | }; 209 | -------------------------------------------------------------------------------- /packages/ra-relationships/src/hooks/use-reference-many-to-many-input-controller.ts: -------------------------------------------------------------------------------- 1 | export const useReferenceManyToManyInputController = (props: any) => {}; 2 | -------------------------------------------------------------------------------- /packages/ra-relationships/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./contexts/many-to-many"; 2 | 3 | export * from "./components/many-to-many-reference-field"; 4 | export * from "./components/many-to-many-reference-input"; 5 | export * from "./components/many-to-many-reference-context-provider"; 6 | -------------------------------------------------------------------------------- /packages/ra-relationships/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true 25 | }, 26 | "include": ["src/**/*"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/ra-search/README.md: -------------------------------------------------------------------------------- 1 | # `ra-search` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const raSearch = require('ra-search'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/ra-search/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ["@babel/preset-typescript", "@babel/preset-react"], 6 | plugins: [ 7 | "@babel/plugin-proposal-object-rest-spread", 8 | "@babel/plugin-proposal-class-properties", 9 | ], 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ra-search/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-search", 3 | "version": "0.0.0", 4 | "description": "> TODO: description", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/preset-react": "^7.10.4", 22 | "@babel/preset-typescript": "^7.10.4", 23 | "@pika/pack": "^0.5.0", 24 | "@pika/plugin-build-types": "^0.9.2", 25 | "@pika/plugin-build-web": "^0.9.2", 26 | "@pika/plugin-standard-pkg": "^0.9.2", 27 | "@types/react": "^16.9.48", 28 | "react": "^16.13.1", 29 | "rimraf": "^3.0.2", 30 | "typescript": "^3.9.7" 31 | }, 32 | "peerDependencies": { 33 | "react": "^16.11.0" 34 | }, 35 | "@pika/pack": { 36 | "pipeline": [ 37 | [ 38 | "@pika/plugin-standard-pkg" 39 | ], 40 | [ 41 | "@pika/plugin-build-web" 42 | ], 43 | [ 44 | "@pika/plugin-build-types" 45 | ] 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/ra-search/src/index.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = raSearch; 4 | 5 | function raSearch() { 6 | // TODO 7 | } 8 | -------------------------------------------------------------------------------- /packages/ra-search/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true 25 | }, 26 | "include": ["src/**/*"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/ra-tour/README.md: -------------------------------------------------------------------------------- 1 | # `ra-tour` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const raTour = require('ra-tour'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/ra-tour/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ["@babel/preset-typescript", "@babel/preset-react"], 6 | plugins: [ 7 | "@babel/plugin-proposal-object-rest-spread", 8 | "@babel/plugin-proposal-class-properties", 9 | ], 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ra-tour/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-tour", 3 | "version": "0.0.0", 4 | "description": "> TODO: description", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/preset-react": "^7.10.4", 22 | "@babel/preset-typescript": "^7.10.4", 23 | "@pika/pack": "^0.5.0", 24 | "@pika/plugin-build-types": "^0.9.2", 25 | "@pika/plugin-build-web": "^0.9.2", 26 | "@pika/plugin-standard-pkg": "^0.9.2", 27 | "@types/react": "^16.9.48", 28 | "react": "^16.13.1", 29 | "rimraf": "^3.0.2", 30 | "typescript": "^3.9.7" 31 | }, 32 | "peerDependencies": { 33 | "react": "^16.11.0" 34 | }, 35 | "@pika/pack": { 36 | "pipeline": [ 37 | [ 38 | "@pika/plugin-standard-pkg" 39 | ], 40 | [ 41 | "@pika/plugin-build-web" 42 | ], 43 | [ 44 | "@pika/plugin-build-types" 45 | ] 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/ra-tour/src/index.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = raTour; 4 | 5 | function raTour() { 6 | // TODO 7 | } 8 | -------------------------------------------------------------------------------- /packages/ra-tour/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true 25 | }, 26 | "include": ["src/**/*"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/ra-version/README.md: -------------------------------------------------------------------------------- 1 | # `ra-version` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const raVersion = require('ra-version'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/ra-version/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ["@babel/preset-typescript", "@babel/preset-react"], 6 | plugins: [ 7 | "@babel/plugin-proposal-object-rest-spread", 8 | "@babel/plugin-proposal-class-properties", 9 | ], 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/ra-version/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blackbox-vision/ra-version", 3 | "version": "0.0.0", 4 | "description": "> TODO: description", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "clean": "rimraf pkg", 10 | "publish": "pika publish", 11 | "build": "npm run clean && pika build", 12 | "version": "npm run build" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.11.4", 19 | "@babel/plugin-proposal-class-properties": "^7.10.4", 20 | "@babel/plugin-proposal-object-rest-spread": "^7.11.0", 21 | "@babel/preset-react": "^7.10.4", 22 | "@babel/preset-typescript": "^7.10.4", 23 | "@pika/pack": "^0.5.0", 24 | "@pika/plugin-build-types": "^0.9.2", 25 | "@pika/plugin-build-web": "^0.9.2", 26 | "@pika/plugin-standard-pkg": "^0.9.2", 27 | "@types/react": "^16.9.48", 28 | "react": "^16.13.1", 29 | "rimraf": "^3.0.2", 30 | "typescript": "^3.9.7" 31 | }, 32 | "peerDependencies": { 33 | "react": "^16.11.0" 34 | }, 35 | "@pika/pack": { 36 | "pipeline": [ 37 | [ 38 | "@pika/plugin-standard-pkg" 39 | ], 40 | [ 41 | "@pika/plugin-build-web" 42 | ], 43 | [ 44 | "@pika/plugin-build-types" 45 | ] 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/ra-version/src/index.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = raVersion; 4 | 5 | function raVersion() { 6 | // TODO 7 | } 8 | -------------------------------------------------------------------------------- /packages/ra-version/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "/dist", 4 | "rootDirs": ["src"], 5 | "baseUrl": "src", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es5", "es6", "es7", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "jsx": "react", 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": false, 15 | "noImplicitThis": false, 16 | "noImplicitAny": false, 17 | "strictNullChecks": false, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "noUnusedLocals": false, 20 | "declaration": true, 21 | "allowSyntheticDefaultImports": true, 22 | "experimentalDecorators": true, 23 | "emitDecoratorMetadata": true, 24 | "esModuleInterop": true 25 | }, 26 | "include": ["src/**/*"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/storybook/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /packages/storybook/.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stories: [ 3 | "../stories/**/*.stories.mdx", 4 | "../stories/**/*.stories.@(js|jsx|ts|tsx)", 5 | ], 6 | addons: ["@storybook/addon-links", "@storybook/addon-essentials"], 7 | }; 8 | -------------------------------------------------------------------------------- /packages/storybook/.storybook/manager-head.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 11 | -------------------------------------------------------------------------------- /packages/storybook/.storybook/preview-head.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 11 | -------------------------------------------------------------------------------- /packages/storybook/.storybook/preview.js: -------------------------------------------------------------------------------- 1 | 2 | export const parameters = { 3 | actions: { argTypesRegex: "^on[A-Z].*" }, 4 | } -------------------------------------------------------------------------------- /packages/storybook/README.md: -------------------------------------------------------------------------------- 1 | # `storybook` 2 | 3 | > TODO: description 4 | 5 | ## Usage 6 | 7 | ``` 8 | const storybook = require('storybook'); 9 | 10 | // TODO: DEMONSTRATE API 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/storybook/db.json: -------------------------------------------------------------------------------- 1 | { 2 | "performances": [ 3 | { 4 | "id": 8, 5 | "band_id": 4, 6 | "venue_id": 3, 7 | "date": "2017-08-06" 8 | }, 9 | { 10 | "id": 7, 11 | "band_id": 1, 12 | "venue_id": 3, 13 | "date": "2018-01-17" 14 | }, 15 | { 16 | "id": 6, 17 | "band_id": 2, 18 | "venue_id": 3, 19 | "date": "2016-04-23" 20 | }, 21 | { 22 | "id": 5, 23 | "band_id": 3, 24 | "venue_id": 3, 25 | "date": "2019-07-28" 26 | } 27 | ], 28 | "venues": [ 29 | { 30 | "id": 5, 31 | "name": "Barclays Center", 32 | "location": "Brooklyn" 33 | }, 34 | { 35 | "id": 4, 36 | "name": "Bridgestone Arena", 37 | "location": "Nashville" 38 | }, 39 | { 40 | "id": 7, 41 | "name": "Fenway Park", 42 | "location": "Boston" 43 | }, 44 | { 45 | "id": 1, 46 | "name": "Madison Square Garden", 47 | "location": "New York" 48 | }, 49 | { 50 | "id": 2, 51 | "name": "Staples Center", 52 | "location": "Los Angeles" 53 | }, 54 | { 55 | "id": 6, 56 | "name": "Wrigley Field", 57 | "location": "Chicago" 58 | }, 59 | { 60 | "id": 3, 61 | "name": "Yankee Stadium", 62 | "location": "New York" 63 | } 64 | ], 65 | "bands": [ 66 | { 67 | "id": 1, 68 | "name": "Radiohead" 69 | }, 70 | { 71 | "id": 2, 72 | "name": "Coldplay" 73 | }, 74 | { 75 | "id": 3, 76 | "name": "Foo Fighters" 77 | }, 78 | { 79 | "id": 4, 80 | "name": "Green Day" 81 | }, 82 | { 83 | "id": 7, 84 | "name": "LCD Soundsystem" 85 | } 86 | ] 87 | } 88 | -------------------------------------------------------------------------------- /packages/storybook/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "storybook", 3 | "version": "0.0.0", 4 | "description": "> TODO: description", 5 | "author": "JonatanSalas ", 6 | "homepage": "https://github.com/BlackBoxVision/react-admin-extensions#readme", 7 | "license": "MIT", 8 | "scripts": { 9 | "test": "echo \"Error: run tests from root\" && exit 1", 10 | "storybook": "start-storybook -p 6006", 11 | "build-storybook": "build-storybook" 12 | }, 13 | "bugs": { 14 | "url": "https://github.com/BlackBoxVision/react-admin-extensions/issues" 15 | }, 16 | "devDependencies": { 17 | "@babel/core": "^7.13.10", 18 | "@babel/runtime-corejs3": "^7.13.10", 19 | "@storybook/addon-actions": "^6.1.21", 20 | "@storybook/addon-essentials": "^6.1.21", 21 | "@storybook/addon-links": "^6.1.21", 22 | "@storybook/react": "^6.1.21", 23 | "babel-loader": "^8.2.2", 24 | "core-js": "^3.9.1", 25 | "ra-data-json-server": "^3.13.4", 26 | "react-admin": "^3.13.4" 27 | }, 28 | "dependencies": { 29 | "@blackbox-vision/ra-layout": "0.0.23", 30 | "json-server": "^0.16.3", 31 | "react": "^17.0.1", 32 | "react-dom": "^17.0.1" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/storybook/src/components/Layout/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Layout } from "@blackbox-vision/ra-layout"; 3 | import { makeStyles } from "@material-ui/styles"; 4 | 5 | const useStyles = makeStyles({ 6 | root: { 7 | backgroundColor: "lightgreen", 8 | }, 9 | container: { 10 | backgroundColor: "lightyellow", 11 | }, 12 | appBar: { 13 | backgroundColor: "lightblue", 14 | }, 15 | sidebarWhenClosed: { 16 | backgroundColor: "violet", 17 | }, 18 | sidebarWhenOpen: { 19 | backgroundColor: "violet", 20 | }, 21 | listItem: { 22 | color: "#FFF", 23 | }, 24 | menuLink: { 25 | color: "#FFF", 26 | }, 27 | logoutBtn: { 28 | backgroundColor: "blue", 29 | }, 30 | }); 31 | 32 | const MyLayout = (props) => { 33 | const classes = useStyles(); 34 | 35 | return ( 36 | 50 | ); 51 | }; 52 | 53 | MyLayout.displayName = "MyLayout"; 54 | 55 | export default MyLayout; 56 | -------------------------------------------------------------------------------- /packages/storybook/src/menu.ts: -------------------------------------------------------------------------------- 1 | export const items = [ 2 | { 3 | type: "group", 4 | label: "Users and Permissions", 5 | items: [ 6 | { 7 | type: "resource", 8 | name: "users", 9 | label: "Users", 10 | icon: null, 11 | }, 12 | { 13 | type: "resource", 14 | name: "permissions", 15 | label: "Permissions", 16 | icon: null, 17 | }, 18 | ], 19 | }, 20 | ]; 21 | -------------------------------------------------------------------------------- /packages/storybook/src/pages/Users/List/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { List, Datagrid, TextField, DateField, EmailField } from "react-admin"; 3 | 4 | const ListUsers = (props) => { 5 | return ( 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | ); 14 | }; 15 | 16 | ListUsers.displayName = "ListUsers"; 17 | 18 | export default ListUsers; 19 | -------------------------------------------------------------------------------- /packages/storybook/src/pages/Users/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const properties = { 4 | list: React.lazy(() => 5 | import(/* webpackChunkName: "Users.list" */ "./List") 6 | ), 7 | // create: React.lazy(() => 8 | // import(/* webpackChunkName: "Users.create" */ "./Create") 9 | // ), 10 | // edit: React.lazy(() => import(/* webpackChunkName: "Users.edit" */ "./Edit")), 11 | options: {}, 12 | }; 13 | 14 | export default properties; 15 | -------------------------------------------------------------------------------- /packages/storybook/src/providers/authProvider.ts: -------------------------------------------------------------------------------- 1 | export const authProvider = { 2 | login: (params) => { 3 | localStorage.setItem("token", "demo"); 4 | return Promise.resolve(); 5 | }, 6 | checkError: (error) => { 7 | return Promise.resolve(); 8 | }, 9 | checkAuth: (params) => { 10 | return localStorage.getItem("token") ? Promise.resolve() : Promise.reject(); 11 | }, 12 | logout: () => { 13 | localStorage.removeItem("token"); 14 | return Promise.resolve(); 15 | }, 16 | getIdentity: () => { 17 | return Promise.resolve({ 18 | id: "0", 19 | avatar: "", 20 | fullName: "John Doe", 21 | }); 22 | }, 23 | getPermissions: (params) => { 24 | return Promise.resolve(); 25 | }, 26 | }; 27 | -------------------------------------------------------------------------------- /packages/storybook/src/providers/dataProvider.ts: -------------------------------------------------------------------------------- 1 | import jsonServerProvider from "ra-data-json-server"; 2 | 3 | export const dataProvider = jsonServerProvider( 4 | "https://jsonplaceholder.typicode.com" 5 | ); 6 | 7 | // export const jsonServerProvider = jsonServerProvider("http://localhost:3000"); 8 | -------------------------------------------------------------------------------- /packages/storybook/src/theme/index.ts: -------------------------------------------------------------------------------- 1 | import { createMuiTheme } from '@material-ui/core/styles'; 2 | 3 | export const theme = createMuiTheme({ 4 | palette: { 5 | type: 'light', 6 | }, 7 | } as any); 8 | -------------------------------------------------------------------------------- /packages/storybook/stories/ra-layout.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta, Story, Canvas } from '@storybook/addon-docs/blocks'; 2 | import { createMuiTheme } from "@material-ui/core"; 3 | import { ThemeProvider } from "@material-ui/styles"; 4 | import { Admin, Resource, ListGuesser } from "react-admin"; 5 | 6 | import { authProvider } from "../src/providers/authProvider"; 7 | import { dataProvider } from "../src/providers/dataProvider"; 8 | import Layout from "../src/components/Layout"; 9 | import { items } from "../src/menu"; 10 | import { theme } from "../src/theme"; 11 | 12 | 13 | 14 | # RA Layout 15 | 16 | Revamped React Admin UI. 17 | 18 | ## Install 19 | 20 | You can install this library via NPM or YARN. 21 | 22 | ### NPM 23 | 24 | ```bash 25 | npm i @blackbox-vision/ra-layout 26 | ``` 27 | 28 | ### YARN 29 | 30 | ```bash 31 | yarn add @blackbox-vision/ra-layout 32 | ``` 33 | 34 | ## Use case 35 | 36 | You're tired of the defacto React Admin UI and want to renew the look and feel. 37 | 38 | ## Usage 39 | 40 | The usage is really simple: 41 | 42 | 1. Define your menu as a JSON structure like the following: 43 | 44 | ```typescript 45 | // menu.ts 46 | import { 47 | LocalAtm, 48 | PermContactCalendar, 49 | } from '@material-ui/icons'; 50 | 51 | export const items = [{ 52 | type: 'group', 53 | label: 'Architects', 54 | items: [ 55 | { 56 | type: 'resource', 57 | name: 'architects', 58 | label: 'Information', 59 | icon: PermContactCalendar, 60 | }, 61 | { 62 | type: 'resource', 63 | name: 'commissions', 64 | label: 'Commissions', 65 | icon: LocalAtm, 66 | }, 67 | ], 68 | }] 69 | ``` 70 | 71 | 2. Import `Layout` pass props to it and you're ready: 72 | 73 | ```typescript 74 | // App.tsx 75 | import React from 'react'; 76 | import { Admin, Resource } from 'react-admin'; 77 | import jsonServerProvider from 'ra-data-json-server'; 78 | import { Layout } from '@blackbox-vision/ra-layout'; 79 | 80 | import { authProvider } from "providers/authProvider"; 81 | import { dataProvider } from "providers/dataProvider"; 82 | import { items } from './menu'; 83 | 84 | const dataProvider = jsonServerProvider('https://jsonplaceholder.typicode.com'); 85 | 86 | export const App = () => ( 87 | } 91 | > 92 | 93 | 94 | ); 95 | 96 | App.displayName = "App"; 97 | ``` 98 | 99 | 100 | 101 | } 105 | > 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /packages/storybook/stories/ra-relationships.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta, Story, Canvas } from "@storybook/addon-docs/blocks"; 2 | import { createMuiTheme } from "@material-ui/core"; 3 | import { ThemeProvider } from "@material-ui/styles"; 4 | import { Admin, Resource, ListGuesser, EditGuesser } from "react-admin"; 5 | import jsonServerProvider from "ra-data-json-server"; 6 | 7 | import { dataProvider } from "../src/providers/dataProvider"; 8 | import Layout from "../src/components/Layout"; 9 | import { items } from "../src/menu"; 10 | import { theme } from "../src/theme"; 11 | 12 | 13 | 14 | # RA Relationships 15 | 16 | React Admin Relationships components. 17 | 18 | ## Install 19 | 20 | You can install this library via NPM or YARN. 21 | 22 | ### NPM 23 | 24 | ```bash 25 | npm i @blackbox-vision/ra-relationships 26 | ``` 27 | 28 | ### YARN 29 | 30 | ```bash 31 | yarn add @blackbox-vision/ra-relationships 32 | ``` 33 | 34 | ## Use case 35 | 36 | TODO: complete description 37 | 38 | ## Usage 39 | 40 | The usage is really simple: 41 | 42 | 1. Define your menu as a JSON structure like the following: 43 | 44 | ```typescript 45 | // menu.ts 46 | import { LocalAtm, PermContactCalendar } from "@material-ui/icons"; 47 | 48 | export const items = [ 49 | { 50 | type: "group", 51 | label: "Architects", 52 | items: [ 53 | { 54 | type: "resource", 55 | name: "architects", 56 | label: "Information", 57 | icon: PermContactCalendar, 58 | }, 59 | { 60 | type: "resource", 61 | name: "commissions", 62 | label: "Commissions", 63 | icon: LocalAtm, 64 | }, 65 | ], 66 | }, 67 | ]; 68 | ``` 69 | 70 | 2. Import `Layout` pass props to it and you're ready: 71 | 72 | ```typescript 73 | // App.tsx 74 | import React from "react"; 75 | import { Admin, Resource } from "react-admin"; 76 | import jsonServerProvider from "ra-data-json-server"; 77 | 78 | import { dataProvider } from "providers/dataProvider"; 79 | import { items } from "./menu"; 80 | 81 | // You need run "npx json-server db.json" to show the resources data from local API 82 | const dataProvider = jsonServerProvider("http://localhost:3000"); 83 | 84 | export const App = () => ( 85 | 86 | 87 | 88 | ); 89 | 90 | App.displayName = "App"; 91 | ``` 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | --------------------------------------------------------------------------------