├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── CODEOWNERS ├── LICENSE ├── README.md ├── demo ├── App.tsx ├── index.html └── index.tsx ├── package.json ├── src └── index.tsx ├── tsconfig.demo.json ├── tsconfig.json ├── webpack.demo.config.js ├── webpack.development.config.js ├── yarn-error.log └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | end_of_line = lf 10 | max_line_length = null -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | dist-demo 3 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | extends: [ 4 | 'plugin:@typescript-eslint/recommended', 5 | ], 6 | rules: { 7 | 'no-use-before-define': 'off', 8 | 'import/extensions': 'off', 9 | 'react/prop-types': 'off', 10 | }, 11 | settings: { 12 | 'import/resolver': { 13 | node: { 14 | extensions: ['.js', '.jsx', '.ts', '.tsx'], 15 | }, 16 | }, 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | package-lock.json 4 | dist 5 | dist-demo 6 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @jacobsfletch 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) TRBL, LLC 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 | # This repo has moved! 2 | 3 | This repo has been merged into the [Packages Directory](https://github.com/payloadcms/payload/tree/main/packages) of the [Payload Monorepo](https://github.com/payloadcms/payload). Please refer to the new location of the [Payload Admin Bar](https://github.com/payloadcms/payload/tree/main/packages/admin-bar) for all future updates, issues, and pull requests. 4 | -------------------------------------------------------------------------------- /demo/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { PayloadAdminBar } from '../src'; 3 | 4 | const AppDemo: React.FC = () => ( 5 |
6 | 14 |
15 | ); 16 | 17 | export default AppDemo; 18 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Payload Admin Bar 4 | 5 | 6 | 7 |
8 | 9 | 10 | -------------------------------------------------------------------------------- /demo/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from 'react-dom'; 3 | import AppDemo from './App'; 4 | 5 | render(, document.getElementById('root')); 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "payload-admin-bar", 3 | "version": "1.0.7", 4 | "main": "dist/index.js", 5 | "types": "dist/index.d.ts", 6 | "repository": "git@github.com:jacobsfletch/payload-admin-bar.git", 7 | "description": "An admin bar for React apps using Payload CMS", 8 | "author": "jacobsfletch@gmail.com", 9 | "license": "MIT", 10 | "keywords": [ 11 | "payload", 12 | "cms", 13 | "admin", 14 | "plugin", 15 | "typescript", 16 | "react" 17 | ], 18 | "scripts": { 19 | "build": "yarn lint && tsc", 20 | "build-demo": "yarn lint && webpack --config webpack.demo.config.js", 21 | "dev": "webpack-dev-server --hot --inline --config webpack.development.config.js", 22 | "lint": "eslint ." 23 | }, 24 | "peerDependencies": { 25 | "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", 26 | "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 27 | }, 28 | "devDependencies": { 29 | "@types/react": "^17.0.0", 30 | "@typescript-eslint/eslint-plugin": "^5.3.1", 31 | "@typescript-eslint/parser": "^4.11.1", 32 | "eslint": "^8.1.0", 33 | "eslint-webpack-plugin": "^2.4.1", 34 | "html-webpack-plugin": "^3.2.0", 35 | "react": "^17.0.0", 36 | "react-dom": "^17.0.0", 37 | "react-hot-loader": "^4.12.19", 38 | "ts-loader": "^8.0.14", 39 | "typescript": "^4.1.3", 40 | "webpack": "^4.41.4", 41 | "webpack-cli": "^3.3.10", 42 | "webpack-dev-server": "^3.10.1" 43 | }, 44 | "files": [ 45 | "dist" 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | import React, { 3 | CSSProperties, 4 | ReactElement, 5 | useEffect, 6 | useState 7 | } from 'react'; 8 | 9 | const dummyUser = { 10 | email: 'dev@email.com', 11 | id: '12345' 12 | } 13 | 14 | export type PayloadMeUser = { 15 | email: string 16 | id: string 17 | } | null | undefined 18 | 19 | export type PayloadAdminBarProps = { 20 | cmsURL?: string 21 | adminPath?: string 22 | apiPath?: string 23 | collection?: string 24 | authCollection?: string 25 | collectionLabels?: { 26 | singular?: string, 27 | plural?: string 28 | } 29 | id?: string 30 | logo?: ReactElement 31 | className?: string 32 | classNames?: { 33 | user?: string, 34 | logo?: string, 35 | create?: string, 36 | logout?: string, 37 | controls?: string, 38 | edit?: string, 39 | preview?: string 40 | } 41 | logoProps?: { 42 | style?: CSSProperties 43 | [key: string]: unknown 44 | } 45 | divProps?: { 46 | style?: CSSProperties 47 | [key: string]: unknown 48 | } 49 | editProps?: { 50 | style?: CSSProperties 51 | [key: string]: unknown 52 | } 53 | createProps?: { 54 | style?: CSSProperties 55 | [key: string]: unknown 56 | } 57 | userProps?: { 58 | style?: CSSProperties 59 | [key: string]: unknown 60 | } 61 | logoutProps?: { 62 | style?: CSSProperties 63 | [key: string]: unknown 64 | } 65 | previewProps?: { 66 | style?: CSSProperties 67 | [key: string]: unknown 68 | } 69 | style?: CSSProperties 70 | unstyled?: boolean 71 | onAuthChange?: (user: PayloadMeUser) => void 72 | devMode?: boolean 73 | preview?: boolean 74 | onPreviewExit?: () => void 75 | } 76 | 77 | export const PayloadAdminBar: React.FC = (props) => { 78 | const { 79 | cmsURL = 'http://localhost:8000', 80 | apiPath = '/api', 81 | adminPath = '/admin', 82 | authCollection = 'users', 83 | collection, 84 | collectionLabels, 85 | id, 86 | logo, 87 | className, 88 | logoProps, 89 | editProps, 90 | createProps, 91 | userProps, 92 | logoutProps, 93 | divProps, 94 | style, 95 | unstyled, 96 | onAuthChange, 97 | classNames, 98 | devMode, 99 | preview, 100 | onPreviewExit, 101 | previewProps 102 | } = props; 103 | 104 | const [user, setUser] = useState(); 105 | 106 | useEffect(() => { 107 | const fetchMe = async () => { 108 | try { 109 | const meRequest = await fetch(`${cmsURL}${apiPath}/${authCollection}/me`, { 110 | method: 'get', 111 | credentials: 'include', 112 | }); 113 | const meResponse = await meRequest.json(); 114 | const { user } = meResponse; 115 | 116 | if (user) { 117 | setUser(user); 118 | } else { 119 | if (devMode !== true) { 120 | setUser(null) 121 | } else { 122 | setUser(dummyUser) 123 | } 124 | } 125 | } catch (err) { 126 | console.warn(err) 127 | if (devMode === true) { 128 | setUser(dummyUser) 129 | } 130 | } 131 | } 132 | fetchMe(); 133 | }, [ 134 | cmsURL, 135 | adminPath, 136 | apiPath 137 | ]) 138 | 139 | useEffect(() => { 140 | if (typeof onAuthChange === 'function') { 141 | onAuthChange(user) 142 | } 143 | }, [ 144 | user, 145 | onAuthChange 146 | ]) 147 | 148 | if (user) { 149 | const { 150 | email, 151 | id: userID 152 | } = user; 153 | 154 | return ( 155 |
177 | 196 | {logo || 'Payload CMS'} 197 | 198 | 220 | 229 | {email || 'Profile'} 230 | 231 | 232 |
249 | {collection && id && ( 250 | 272 | 281 | {`Edit ${collectionLabels?.singular || 'page'}`} 282 | 283 | 284 | )} 285 | {collection && ( 286 | 307 | 316 | {`New ${collectionLabels?.singular || 'page'}`} 317 | 318 | 319 | )} 320 | {preview && ( 321 | 343 | )} 344 |
345 | 366 | 375 | Logout 376 | 377 | 378 |
379 | ) 380 | } 381 | 382 | return null; 383 | } 384 | -------------------------------------------------------------------------------- /tsconfig.demo.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "target": "es5", 5 | "module": "commonjs", 6 | "sourceMap": true, 7 | "jsx": "react", 8 | "esModuleInterop": true, 9 | }, 10 | "include": [ 11 | "demo/**/*" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "allowJs": true, 5 | "target": "es5", 6 | "module": "commonjs", 7 | "sourceMap": true, 8 | "jsx": "react", 9 | "esModuleInterop": true, 10 | "declaration": true, 11 | "declarationDir": "./dist", 12 | }, 13 | "include": [ 14 | "src/**/*" 15 | ], 16 | "exclude": [ 17 | "**/*.test.js" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /webpack.demo.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-var-requires */ 2 | const path = require('path'); 3 | const HtmlWebPackPlugin = require('html-webpack-plugin'); 4 | 5 | module.exports = [ 6 | { 7 | devtool: 'source-map', 8 | mode: 'production', 9 | entry: './demo/index.tsx', 10 | output: { 11 | filename: 'demo.bundle.js', 12 | path: path.resolve(__dirname, 'dist-demo'), 13 | }, 14 | module: { 15 | rules: [ 16 | { 17 | test: /\.(js|jsx|ts|tsx)$/, 18 | exclude: /node_modules/, 19 | use: [{ 20 | loader: 'ts-loader', 21 | options: { 22 | configFile: 'tsconfig.demo.json', 23 | }, 24 | }], 25 | }, 26 | ], 27 | }, 28 | resolve: { 29 | extensions: ['.js', '.jsx', '.ts', '.tsx'], 30 | }, 31 | plugins: [ 32 | new HtmlWebPackPlugin({ 33 | template: 'demo/index.html', 34 | }), 35 | ], 36 | }, 37 | ]; 38 | -------------------------------------------------------------------------------- /webpack.development.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-var-requires */ 2 | const path = require('path'); 3 | const HtmlWebPackPlugin = require('html-webpack-plugin'); 4 | const ESLintPlugin = require('eslint-webpack-plugin'); 5 | 6 | module.exports = { 7 | devtool: 'inline-source-map', 8 | mode: 'development', 9 | entry: './demo/index.tsx', 10 | output: { 11 | filename: 'demo.bundle.js', 12 | path: path.resolve(__dirname, 'demo'), 13 | }, 14 | module: { 15 | rules: [ 16 | { 17 | test: /\.(js|jsx|ts|tsx)$/, 18 | exclude: /node_modules/, 19 | loaders: [ 20 | 'react-hot-loader/webpack', 21 | 'ts-loader', 22 | ], 23 | }, 24 | ], 25 | }, 26 | resolve: { 27 | extensions: ['.js', '.jsx', '.ts', '.tsx'], 28 | }, 29 | plugins: [ 30 | new HtmlWebPackPlugin({ 31 | // html to duplicate 32 | template: 'demo/index.html', 33 | }), 34 | new ESLintPlugin({ 35 | fix: true, 36 | emitWarning: true, 37 | }), 38 | ], 39 | devServer: { 40 | port: 3000, 41 | host: '0.0.0.0', 42 | }, 43 | }; 44 | --------------------------------------------------------------------------------