UNPKG

@lolocompany/react-admin-lolo

Version:

A library for schema-driven web apps using [Lolo](https://lolo.company), [React Admin](https://github.com/marmelab/react-admin) and [RJSF](https://github.com/rjsf-team/react-jsonschema-form)

1,693 lines (1,438 loc) 1.1 MB
import * as React from 'react'; import React__default, { useState, useEffect, useRef, cloneElement, Component, forwardRef, useContext, Fragment } from 'react'; import * as ra from 'react-admin'; import { fetchUtils, adminReducer, USER_LOGOUT, adminSaga, useDataProvider, useRefresh, Logout, CreateButton, useLogin } from 'react-admin'; import { Provider } from 'react-redux'; import { createHashHistory } from 'history'; import Amplify, { Auth, Hub } from 'aws-amplify'; import inflection, { humanize, transform, singularize, titleize, pluralize, inflect } from 'inflection'; import Auth$1 from '@aws-amplify/auth'; import polyglotI18nProvider from 'ra-i18n-polyglot'; import englishMessages from 'ra-language-english'; import { combineReducers, compose, createStore, applyMiddleware } from 'redux'; import { connectRouter, routerMiddleware } from 'connected-react-router'; import createSagaMiddleware from 'redux-saga'; import { all, fork } from 'redux-saga/effects'; import { withRouter } from 'react-router'; import TextField$1 from '@material-ui/core/TextField'; import CircularProgress from '@material-ui/core/CircularProgress'; import Grid from '@material-ui/core/Grid'; import Button from '@material-ui/core/Button'; import CreateIcon from '@material-ui/icons/CreateOutlined'; import { withStyles, makeStyles } from '@material-ui/core/styles'; import Popper from '@material-ui/core/Popper'; import ListSubheader from '@material-ui/core/ListSubheader'; import Paper from '@material-ui/core/Paper'; import IconButton$3 from '@material-ui/core/IconButton'; import Chip from '@material-ui/core/Chip'; import { createSvgIcon, unstable_useId, useControlled, useEventCallback, setRef } from '@material-ui/core/utils'; import { Card, Box as Box$1, makeStyles as makeStyles$2, List as List$2, ListSubheader as ListSubheader$1, ListItem as ListItem$1, Divider as Divider$1, Toolbar, Typography as Typography$1 } from '@material-ui/core'; import Box from '@material-ui/core/Box'; import AddIcon from '@material-ui/icons/Add'; import ArrowUpward from '@material-ui/icons/ArrowUpward'; import ArrowDownward from '@material-ui/icons/ArrowDownward'; import Remove from '@material-ui/icons/Remove'; import Typography from '@material-ui/core/Typography'; import List$1 from '@material-ui/core/List'; import ListItem from '@material-ui/core/ListItem'; import ListItemIcon from '@material-ui/core/ListItemIcon'; import ErrorIcon from '@material-ui/icons/Error'; import ListItemText from '@material-ui/core/ListItemText'; import { makeStyles as makeStyles$1 } from '@material-ui/styles'; import Divider from '@material-ui/core/Divider'; import FormControl from '@material-ui/core/FormControl'; import FormHelperText from '@material-ui/core/FormHelperText'; import Input from '@material-ui/core/Input'; import InputLabel from '@material-ui/core/InputLabel'; import Checkbox from '@material-ui/core/Checkbox'; import FormControlLabel from '@material-ui/core/FormControlLabel'; import FormLabel from '@material-ui/core/FormLabel'; import FormGroup from '@material-ui/core/FormGroup'; import Radio from '@material-ui/core/Radio'; import RadioGroup from '@material-ui/core/RadioGroup'; import Slider from '@material-ui/core/Slider'; import MenuItem from '@material-ui/core/MenuItem'; import 'react-router-dom'; import PowerSettingsNew from '@material-ui/icons/PowerSettingsNew'; import { ImportButton as ImportButton$1 } from 'react-admin-import-csv'; import Inbox from '@material-ui/icons/Inbox'; import { useListContext, useTranslate } from 'ra-core'; import { onAuthUIStateChange, AuthState } from '@aws-amplify/ui-components'; import { AmplifyAuthenticator, AmplifySignIn } from '@aws-amplify/ui-react'; function _extends$A() { _extends$A = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$A.apply(this, arguments); } Amplify.configure({ Auth: { region: 'eu-west-1', userPoolId: 'eu-west-1_lQin10bBN', userPoolWebClientId: '2j7v5uee5qc13p6kncmlrjqq0q' } }); let authProvider = { init: async updateAuth => { let token = null; token = await (async () => { try { const session = await Auth.currentSession(); return session.idToken.jwtToken; } catch (e) { return null; } })(); Hub.listen('auth', data => { const { payload: { event, data: { signInUserSession: { idToken: { jwtToken } } } } } = data; updateAuth(event === 'signIn' ? jwtToken : null); }); updateAuth(token); }, login: params => Promise.resolve(), logout: params => { localStorage.clear(); return Auth.signOut(); }, checkAuth: params => Auth.currentSession(), checkError: error => Promise.resolve(), getPermissions: params => Promise.resolve() }; class AuthProvider { constructor(options) { if (options) { authProvider = Object.assign(authProvider, options); } } } var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; var queryString = {}; var strictUriEncode = str => encodeURIComponent(str).replace(/[!'()*]/g, x => `%${x.charCodeAt(0).toString(16).toUpperCase()}`); var token = '%[a-f0-9]{2}'; var singleMatcher = new RegExp(token, 'gi'); var multiMatcher = new RegExp('(' + token + ')+', 'gi'); function decodeComponents(components, split) { try { // Try to decode the entire string first return decodeURIComponent(components.join('')); } catch (err) { // Do nothing } if (components.length === 1) { return components; } split = split || 1; // Split the array in 2 parts var left = components.slice(0, split); var right = components.slice(split); return Array.prototype.concat.call([], decodeComponents(left), decodeComponents(right)); } function decode(input) { try { return decodeURIComponent(input); } catch (err) { var tokens = input.match(singleMatcher); for (var i = 1; i < tokens.length; i++) { input = decodeComponents(tokens, i).join(''); tokens = input.match(singleMatcher); } return input; } } function customDecodeURIComponent(input) { // Keep track of all the replacements and prefill the map with the `BOM` var replaceMap = { '%FE%FF': '\uFFFD\uFFFD', '%FF%FE': '\uFFFD\uFFFD' }; var match = multiMatcher.exec(input); while (match) { try { // Decode as big chunks as possible replaceMap[match[0]] = decodeURIComponent(match[0]); } catch (err) { var result = decode(match[0]); if (result !== match[0]) { replaceMap[match[0]] = result; } } match = multiMatcher.exec(input); } // Add `%C2` at the end of the map to make sure it does not replace the combinator before everything else replaceMap['%C2'] = '\uFFFD'; var entries = Object.keys(replaceMap); for (var i = 0; i < entries.length; i++) { // Replace all decoded components var key = entries[i]; input = input.replace(new RegExp(key, 'g'), replaceMap[key]); } return input; } var decodeUriComponent = function (encodedURI) { if (typeof encodedURI !== 'string') { throw new TypeError('Expected `encodedURI` to be of type `string`, got `' + typeof encodedURI + '`'); } try { encodedURI = encodedURI.replace(/\+/g, ' '); // Try the built in decoder first return decodeURIComponent(encodedURI); } catch (err) { // Fallback to a more advanced decoder return customDecodeURIComponent(encodedURI); } }; var splitOnFirst = (string, separator) => { if (!(typeof string === 'string' && typeof separator === 'string')) { throw new TypeError('Expected the arguments to be of type `string`'); } if (separator === '') { return [string]; } const separatorIndex = string.indexOf(separator); if (separatorIndex === -1) { return [string]; } return [ string.slice(0, separatorIndex), string.slice(separatorIndex + separator.length) ]; }; var filterObj = function (obj, predicate) { var ret = {}; var keys = Object.keys(obj); var isArr = Array.isArray(predicate); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var val = obj[key]; if (isArr ? predicate.indexOf(key) !== -1 : predicate(key, val, obj)) { ret[key] = val; } } return ret; }; (function (exports) { const strictUriEncode$1 = strictUriEncode; const decodeComponent = decodeUriComponent; const splitOnFirst$1 = splitOnFirst; const filterObject = filterObj; const isNullOrUndefined = value => value === null || value === undefined; const encodeFragmentIdentifier = Symbol('encodeFragmentIdentifier'); function encoderForArrayFormat(options) { switch (options.arrayFormat) { case 'index': return key => (result, value) => { const index = result.length; if ( value === undefined || (options.skipNull && value === null) || (options.skipEmptyString && value === '') ) { return result; } if (value === null) { return [...result, [encode(key, options), '[', index, ']'].join('')]; } return [ ...result, [encode(key, options), '[', encode(index, options), ']=', encode(value, options)].join('') ]; }; case 'bracket': return key => (result, value) => { if ( value === undefined || (options.skipNull && value === null) || (options.skipEmptyString && value === '') ) { return result; } if (value === null) { return [...result, [encode(key, options), '[]'].join('')]; } return [...result, [encode(key, options), '[]=', encode(value, options)].join('')]; }; case 'comma': case 'separator': case 'bracket-separator': { const keyValueSep = options.arrayFormat === 'bracket-separator' ? '[]=' : '='; return key => (result, value) => { if ( value === undefined || (options.skipNull && value === null) || (options.skipEmptyString && value === '') ) { return result; } // Translate null to an empty string so that it doesn't serialize as 'null' value = value === null ? '' : value; if (result.length === 0) { return [[encode(key, options), keyValueSep, encode(value, options)].join('')]; } return [[result, encode(value, options)].join(options.arrayFormatSeparator)]; }; } default: return key => (result, value) => { if ( value === undefined || (options.skipNull && value === null) || (options.skipEmptyString && value === '') ) { return result; } if (value === null) { return [...result, encode(key, options)]; } return [...result, [encode(key, options), '=', encode(value, options)].join('')]; }; } } function parserForArrayFormat(options) { let result; switch (options.arrayFormat) { case 'index': return (key, value, accumulator) => { result = /\[(\d*)\]$/.exec(key); key = key.replace(/\[\d*\]$/, ''); if (!result) { accumulator[key] = value; return; } if (accumulator[key] === undefined) { accumulator[key] = {}; } accumulator[key][result[1]] = value; }; case 'bracket': return (key, value, accumulator) => { result = /(\[\])$/.exec(key); key = key.replace(/\[\]$/, ''); if (!result) { accumulator[key] = value; return; } if (accumulator[key] === undefined) { accumulator[key] = [value]; return; } accumulator[key] = [].concat(accumulator[key], value); }; case 'comma': case 'separator': return (key, value, accumulator) => { const isArray = typeof value === 'string' && value.includes(options.arrayFormatSeparator); const isEncodedArray = (typeof value === 'string' && !isArray && decode(value, options).includes(options.arrayFormatSeparator)); value = isEncodedArray ? decode(value, options) : value; const newValue = isArray || isEncodedArray ? value.split(options.arrayFormatSeparator).map(item => decode(item, options)) : value === null ? value : decode(value, options); accumulator[key] = newValue; }; case 'bracket-separator': return (key, value, accumulator) => { const isArray = /(\[\])$/.test(key); key = key.replace(/\[\]$/, ''); if (!isArray) { accumulator[key] = value ? decode(value, options) : value; return; } const arrayValue = value === null ? [] : value.split(options.arrayFormatSeparator).map(item => decode(item, options)); if (accumulator[key] === undefined) { accumulator[key] = arrayValue; return; } accumulator[key] = [].concat(accumulator[key], arrayValue); }; default: return (key, value, accumulator) => { if (accumulator[key] === undefined) { accumulator[key] = value; return; } accumulator[key] = [].concat(accumulator[key], value); }; } } function validateArrayFormatSeparator(value) { if (typeof value !== 'string' || value.length !== 1) { throw new TypeError('arrayFormatSeparator must be single character string'); } } function encode(value, options) { if (options.encode) { return options.strict ? strictUriEncode$1(value) : encodeURIComponent(value); } return value; } function decode(value, options) { if (options.decode) { return decodeComponent(value); } return value; } function keysSorter(input) { if (Array.isArray(input)) { return input.sort(); } if (typeof input === 'object') { return keysSorter(Object.keys(input)) .sort((a, b) => Number(a) - Number(b)) .map(key => input[key]); } return input; } function removeHash(input) { const hashStart = input.indexOf('#'); if (hashStart !== -1) { input = input.slice(0, hashStart); } return input; } function getHash(url) { let hash = ''; const hashStart = url.indexOf('#'); if (hashStart !== -1) { hash = url.slice(hashStart); } return hash; } function extract(input) { input = removeHash(input); const queryStart = input.indexOf('?'); if (queryStart === -1) { return ''; } return input.slice(queryStart + 1); } function parseValue(value, options) { if (options.parseNumbers && !Number.isNaN(Number(value)) && (typeof value === 'string' && value.trim() !== '')) { value = Number(value); } else if (options.parseBooleans && value !== null && (value.toLowerCase() === 'true' || value.toLowerCase() === 'false')) { value = value.toLowerCase() === 'true'; } return value; } function parse(query, options) { options = Object.assign({ decode: true, sort: true, arrayFormat: 'none', arrayFormatSeparator: ',', parseNumbers: false, parseBooleans: false }, options); validateArrayFormatSeparator(options.arrayFormatSeparator); const formatter = parserForArrayFormat(options); // Create an object with no prototype const ret = Object.create(null); if (typeof query !== 'string') { return ret; } query = query.trim().replace(/^[?#&]/, ''); if (!query) { return ret; } for (const param of query.split('&')) { if (param === '') { continue; } let [key, value] = splitOnFirst$1(options.decode ? param.replace(/\+/g, ' ') : param, '='); // Missing `=` should be `null`: // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters value = value === undefined ? null : ['comma', 'separator', 'bracket-separator'].includes(options.arrayFormat) ? value : decode(value, options); formatter(decode(key, options), value, ret); } for (const key of Object.keys(ret)) { const value = ret[key]; if (typeof value === 'object' && value !== null) { for (const k of Object.keys(value)) { value[k] = parseValue(value[k], options); } } else { ret[key] = parseValue(value, options); } } if (options.sort === false) { return ret; } return (options.sort === true ? Object.keys(ret).sort() : Object.keys(ret).sort(options.sort)).reduce((result, key) => { const value = ret[key]; if (Boolean(value) && typeof value === 'object' && !Array.isArray(value)) { // Sort object keys, not values result[key] = keysSorter(value); } else { result[key] = value; } return result; }, Object.create(null)); } exports.extract = extract; exports.parse = parse; exports.stringify = (object, options) => { if (!object) { return ''; } options = Object.assign({ encode: true, strict: true, arrayFormat: 'none', arrayFormatSeparator: ',' }, options); validateArrayFormatSeparator(options.arrayFormatSeparator); const shouldFilter = key => ( (options.skipNull && isNullOrUndefined(object[key])) || (options.skipEmptyString && object[key] === '') ); const formatter = encoderForArrayFormat(options); const objectCopy = {}; for (const key of Object.keys(object)) { if (!shouldFilter(key)) { objectCopy[key] = object[key]; } } const keys = Object.keys(objectCopy); if (options.sort !== false) { keys.sort(options.sort); } return keys.map(key => { const value = object[key]; if (value === undefined) { return ''; } if (value === null) { return encode(key, options); } if (Array.isArray(value)) { if (value.length === 0 && options.arrayFormat === 'bracket-separator') { return encode(key, options) + '[]'; } return value .reduce(formatter(key), []) .join('&'); } return encode(key, options) + '=' + encode(value, options); }).filter(x => x.length > 0).join('&'); }; exports.parseUrl = (url, options) => { options = Object.assign({ decode: true }, options); const [url_, hash] = splitOnFirst$1(url, '#'); return Object.assign( { url: url_.split('?')[0] || '', query: parse(extract(url), options) }, options && options.parseFragmentIdentifier && hash ? {fragmentIdentifier: decode(hash, options)} : {} ); }; exports.stringifyUrl = (object, options) => { options = Object.assign({ encode: true, strict: true, [encodeFragmentIdentifier]: true }, options); const url = removeHash(object.url).split('?')[0] || ''; const queryFromUrl = exports.extract(object.url); const parsedQueryFromUrl = exports.parse(queryFromUrl, {sort: false}); const query = Object.assign(parsedQueryFromUrl, object.query); let queryString = exports.stringify(query, options); if (queryString) { queryString = `?${queryString}`; } let hash = getHash(object.url); if (object.fragmentIdentifier) { hash = `#${options[encodeFragmentIdentifier] ? encode(object.fragmentIdentifier, options) : object.fragmentIdentifier}`; } return `${url}${queryString}${hash}`; }; exports.pick = (input, filter, options) => { options = Object.assign({ parseFragmentIdentifier: true, [encodeFragmentIdentifier]: false }, options); const {url, query, fragmentIdentifier} = exports.parseUrl(input, options); return exports.stringifyUrl({ url, query: filterObject(query, filter), fragmentIdentifier }, options); }; exports.exclude = (input, filter, options) => { const exclusionFilter = Array.isArray(filter) ? key => !filter.includes(key) : (key, value) => !filter(key, value); return exports.pick(input, exclusionFilter, options); }; }(queryString)); var _dataProvider = (apiUrl => { let getToken = async () => { const session = await Auth$1.currentSession(); return session.idToken.jwtToken; }; const fetchJson = async (path, options = {}) => { if (!options.headers) { options.headers = new Headers({ Accept: 'application/json' }); } options.headers.set('Authorization', await getToken()); const accountId = localStorage.getItem('accountId'); if (accountId) { options.headers.set('Lolo-Account-Id', accountId); } return fetchUtils.fetchJson(apiUrl + path, options).catch(err => { if (err.body && err.body.error) { // 401, 403, 500 err.message = err.body.error; } else if (err.body && err.body.errors) { // 422 err.message = err.body.errors.map(item => { const field = humanize(item.dataPath.replace('.body.', '')); return `${field} ${item.message}`; }).join(', '); } throw err; }); }; const buildQs = (filter = {}) => Object.entries(filter).reduce((memo, [k, v]) => { if (v && v.constructor === Object) { for (const prop in v) { memo[`q[${k}.${prop}]`] = v[prop]; } } else { memo[`q[${k}]`] = v; } return memo; }, {}); const create = async (resource, params) => { const res = await fetchJson(`/${resource}`, { method: 'POST', body: JSON.stringify(params.data) }); return { data: res.json }; }; const getList = async (resource, params, queryOpts = {}) => { console.log('getList', resource, params, queryOpts); const { page = 1, perPage = 10 } = params.pagination || {}; const { field = 'id', order = 'ASC' } = params.sort || {}; const query = { limit: perPage, sort: `${field} ${order.toLowerCase()}`, offset: (page - 1) * perPage, ...buildQs(params.filter), ...queryOpts }; const url = `/${resource}?${queryString.stringify(query)}`; const res = await fetchJson(url); return { data: res.json[kebabToCamel(resource)], total: res.json.total }; }; return { /** * API URL */ apiUrl, /** * Custom request */ sendRequest: async (path, options) => { const res = await fetchJson(path, options); return { data: res.json }; }, /** * getList */ getList, /** * getOne */ getOne: async (resource, params) => { const res = await fetchJson(`/${resource}/${params.id}`); return { data: res.json }; }, /** * getMany */ getMany: (resource, params) => { params.filter = { id: params.ids }; return getList(resource, params, { qor: 1, qre: 0, limit: 100 }); }, /** * getManyReference */ getManyReference: (resource, params) => { params.filter[params.target] = params.id; return getList(resource, params, { qre: 0 }); }, /** * update */ update: (resource, params) => { return fetchJson(`/${resource}/${params.id}`, { method: 'PUT', body: JSON.stringify(params.data) }).then(res => { return { data: res.json }; }); }, /** * updateMany */ updateMany: (resource, params) => { throw new Error('Not implemented'); }, /** * create */ create, /** * delete */ delete: (resource, params) => { return fetchJson(`/${resource}/${params.id}`, { method: 'DELETE' }).then(() => ({ data: resource })); }, /** * deleteMany */ deleteMany: async (resource, params) => { const deletedIds = []; for (const id of params.ids) { const url = `/${resource}/${id}`; try { await fetchJson(url, { method: 'DELETE' }); deletedIds.push(id); } catch (err) { console.log('delete error', err); } } return { data: deletedIds }; }, /** * getToken */ get getToken() { return getToken; }, set getToken(fn) { getToken = fn; } }; }); function kebabToCamel(s) { return s.replace(/(-\w)/g, function (m) { return m[1].toUpperCase(); }); } var i18nProvider = polyglotI18nProvider(locale => englishMessages, 'en', { allowMissing: true }); // in src/createAdminStore.js var createAdminStore = (({ authProvider, dataProvider, history }) => { const reducer = combineReducers({ admin: adminReducer, router: connectRouter(history) // add your own reducers here }); const resettableAppReducer = (state, action) => reducer(action.type !== USER_LOGOUT ? state : undefined, action); const saga = function* rootSaga() { yield all([adminSaga(dataProvider, authProvider) // add your own sagas here ].map(fork)); }; const sagaMiddleware = createSagaMiddleware(); const composeEnhancers = process.env.NODE_ENV === 'development' && typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({ trace: true, traceLimit: 25 }) || compose; const store = createStore(resettableAppReducer, { /* set your initial state here */ }, composeEnhancers(applyMiddleware(sagaMiddleware, routerMiddleware(history) // add your own middlewares here ) // add your own enhancers here )); sagaMiddleware.run(saga); return store; }); const customlocalStorage = { setItem: (key, value) => { let event = new Event('localStorageItemUpdated'); event.key = key; event.value = value; localStorage.setItem(key, value); window.dispatchEvent(event); }, removeItem: key => { let event = new Event('localStorageItemUpdated'); localStorage.removeItem(key); window.dispatchEvent(event); }, getItem: key => { return localStorage.getItem(key); } }; function useAuth() { const [jwtToken, setJwtToken] = useState(null); useEffect(() => { authProvider.init(token => { setJwtToken(token); }); }, []); return { jwtToken }; } function useIsMountedRef() { const isMountedRef = useRef(null); useEffect(() => { isMountedRef.current = true; return () => isMountedRef.current = false; }, []); return isMountedRef; } const AdminDataContext = /*#__PURE__*/React__default.createContext({}); function useAdminContext() { const context = React__default.useContext(AdminDataContext); if (!context) { throw new Error('useAdminContext must be used within AdminContext'); } return context; } const defaultAccountsUrl = 'https://dev.lolo.company/api/accounts/all'; function AdminContext(props) { const { data } = props; const [accounts, setAccounts] = useState([]); const [selectedAccount, setSelectedAccount] = useState(null); const { jwtToken } = useAuth(); const refresh = ra.useRefresh(); useEffect(() => { const getAccounts = async () => { const headers = new Headers({ Accept: 'application/json' }); headers.set('Authorization', jwtToken); ra.fetchUtils.fetchJson(data.accountsUrl || defaultAccountsUrl, { headers }).then(({ json }) => { setAccounts(json.accounts); setSelectedAccount(getSelectedAccount(json.accounts, refresh)); }).catch(err => { if (err.status === 401) data.authProvider.logout(); throw err; }); }; if (jwtToken) { getAccounts(); } }, [jwtToken]); return /*#__PURE__*/React__default.createElement(AdminDataContext.Provider, { value: { accounts, selectedAccount, setSelectedAccount, ...data } }, props.children); } const getSelectedAccount = (accounts, refresh) => { if (accounts.length < 1) return null; const id = localStorage.getItem('accountId'); const isPrimaryAccount = accounts.find(item => item.isPrimary); if (id) { return accounts.find(item => item.id === id) || null; } else { if (isPrimaryAccount) { return isPrimaryAccount; } else { localStorage.setItem('accountId', accounts[0].id); refresh(); return accounts[0]; } } }; const ListActions = props => { const { className, exporter, filters, maxResults, hasCreate, ...rest } = props; const { currentSort, resource, displayedFilters, filterValues, basePath, showFilter, total } = ra.useListContext(); return /*#__PURE__*/React__default.createElement(ra.TopToolbar, _extends$A({ className: className }, ra.sanitizeListRestProps(rest)), filters && /*#__PURE__*/cloneElement(filters, { resource, showFilter, displayedFilters, filterValues, context: 'button' }), hasCreate ? /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(ra.CreateButton, { to: { pathname: `${basePath}/create`, search: 'source=' + JSON.stringify(filterValues) } }), /*#__PURE__*/React__default.createElement(ImportButton, props)) : null, /*#__PURE__*/React__default.createElement(ra.ExportButton, { disabled: total === 0, resource: resource, sort: currentSort, filterValues: filterValues, maxResults: maxResults })); }; const CreateActions = ({ basePath, resource }) => /*#__PURE__*/React__default.createElement(ra.TopToolbar, null, /*#__PURE__*/React__default.createElement(ra.ListButton, { basePath: basePath, resource: resource })); const EditActions = ({ basePath, resource }) => /*#__PURE__*/React__default.createElement(ra.TopToolbar, null, /*#__PURE__*/React__default.createElement(ra.ListButton, { basePath: basePath, resource: resource })); function _objectWithoutPropertiesLoose$k(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _objectWithoutProperties$j(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose$k(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _defineProperty$r(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var propTypes = {exports: {}}; var reactIs = {exports: {}}; var reactIs_production_min = {}; /** @license React v16.13.1 * react-is.production.min.js * * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var b="function"===typeof Symbol&&Symbol.for,c=b?Symbol.for("react.element"):60103,d=b?Symbol.for("react.portal"):60106,e=b?Symbol.for("react.fragment"):60107,f=b?Symbol.for("react.strict_mode"):60108,g=b?Symbol.for("react.profiler"):60114,h=b?Symbol.for("react.provider"):60109,k=b?Symbol.for("react.context"):60110,l=b?Symbol.for("react.async_mode"):60111,m=b?Symbol.for("react.concurrent_mode"):60111,n=b?Symbol.for("react.forward_ref"):60112,p=b?Symbol.for("react.suspense"):60113,q=b? Symbol.for("react.suspense_list"):60120,r=b?Symbol.for("react.memo"):60115,t=b?Symbol.for("react.lazy"):60116,v=b?Symbol.for("react.block"):60121,w=b?Symbol.for("react.fundamental"):60117,x=b?Symbol.for("react.responder"):60118,y=b?Symbol.for("react.scope"):60119; function z(a){if("object"===typeof a&&null!==a){var u=a.$$typeof;switch(u){case c:switch(a=a.type,a){case l:case m:case e:case g:case f:case p:return a;default:switch(a=a&&a.$$typeof,a){case k:case n:case t:case r:case h:return a;default:return u}}case d:return u}}}function A(a){return z(a)===m}reactIs_production_min.AsyncMode=l;reactIs_production_min.ConcurrentMode=m;reactIs_production_min.ContextConsumer=k;reactIs_production_min.ContextProvider=h;reactIs_production_min.Element=c;reactIs_production_min.ForwardRef=n;reactIs_production_min.Fragment=e;reactIs_production_min.Lazy=t;reactIs_production_min.Memo=r;reactIs_production_min.Portal=d; reactIs_production_min.Profiler=g;reactIs_production_min.StrictMode=f;reactIs_production_min.Suspense=p;reactIs_production_min.isAsyncMode=function(a){return A(a)||z(a)===l};reactIs_production_min.isConcurrentMode=A;reactIs_production_min.isContextConsumer=function(a){return z(a)===k};reactIs_production_min.isContextProvider=function(a){return z(a)===h};reactIs_production_min.isElement=function(a){return "object"===typeof a&&null!==a&&a.$$typeof===c};reactIs_production_min.isForwardRef=function(a){return z(a)===n};reactIs_production_min.isFragment=function(a){return z(a)===e};reactIs_production_min.isLazy=function(a){return z(a)===t}; reactIs_production_min.isMemo=function(a){return z(a)===r};reactIs_production_min.isPortal=function(a){return z(a)===d};reactIs_production_min.isProfiler=function(a){return z(a)===g};reactIs_production_min.isStrictMode=function(a){return z(a)===f};reactIs_production_min.isSuspense=function(a){return z(a)===p}; reactIs_production_min.isValidElementType=function(a){return "string"===typeof a||"function"===typeof a||a===e||a===m||a===g||a===f||a===p||a===q||"object"===typeof a&&null!==a&&(a.$$typeof===t||a.$$typeof===r||a.$$typeof===h||a.$$typeof===k||a.$$typeof===n||a.$$typeof===w||a.$$typeof===x||a.$$typeof===y||a.$$typeof===v)};reactIs_production_min.typeOf=z; var reactIs_development = {}; /** @license React v16.13.1 * react-is.development.js * * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ if (process.env.NODE_ENV !== "production") { (function() { // The Symbol used to tag the ReactElement-like types. If there is no native Symbol // nor polyfill, then a plain number is used for performance. var hasSymbol = typeof Symbol === 'function' && Symbol.for; var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for('react.element') : 0xeac7; var REACT_PORTAL_TYPE = hasSymbol ? Symbol.for('react.portal') : 0xeaca; var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for('react.fragment') : 0xeacb; var REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for('react.strict_mode') : 0xeacc; var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for('react.profiler') : 0xead2; var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for('react.provider') : 0xeacd; var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for('react.context') : 0xeace; // TODO: We don't use AsyncMode or ConcurrentMode anymore. They were temporary // (unstable) APIs that have been removed. Can we remove the symbols? var REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol.for('react.async_mode') : 0xeacf; var REACT_CONCURRENT_MODE_TYPE = hasSymbol ? Symbol.for('react.concurrent_mode') : 0xeacf; var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0; var REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for('react.suspense') : 0xead1; var REACT_SUSPENSE_LIST_TYPE = hasSymbol ? Symbol.for('react.suspense_list') : 0xead8; var REACT_MEMO_TYPE = hasSymbol ? Symbol.for('react.memo') : 0xead3; var REACT_LAZY_TYPE = hasSymbol ? Symbol.for('react.lazy') : 0xead4; var REACT_BLOCK_TYPE = hasSymbol ? Symbol.for('react.block') : 0xead9; var REACT_FUNDAMENTAL_TYPE = hasSymbol ? Symbol.for('react.fundamental') : 0xead5; var REACT_RESPONDER_TYPE = hasSymbol ? Symbol.for('react.responder') : 0xead6; var REACT_SCOPE_TYPE = hasSymbol ? Symbol.for('react.scope') : 0xead7; function isValidElementType(type) { return typeof type === 'string' || typeof type === 'function' || // Note: its typeof might be other than 'symbol' or 'number' if it's a polyfill. type === REACT_FRAGMENT_TYPE || type === REACT_CONCURRENT_MODE_TYPE || type === REACT_PROFILER_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || typeof type === 'object' && type !== null && (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_RESPONDER_TYPE || type.$$typeof === REACT_SCOPE_TYPE || type.$$typeof === REACT_BLOCK_TYPE); } function typeOf(object) { if (typeof object === 'object' && object !== null) { var $$typeof = object.$$typeof; switch ($$typeof) { case REACT_ELEMENT_TYPE: var type = object.type; switch (type) { case REACT_ASYNC_MODE_TYPE: case REACT_CONCURRENT_MODE_TYPE: case REACT_FRAGMENT_TYPE: case REACT_PROFILER_TYPE: case REACT_STRICT_MODE_TYPE: case REACT_SUSPENSE_TYPE: return type; default: var $$typeofType = type && type.$$typeof; switch ($$typeofType) { case REACT_CONTEXT_TYPE: case REACT_FORWARD_REF_TYPE: case REACT_LAZY_TYPE: case REACT_MEMO_TYPE: case REACT_PROVIDER_TYPE: return $$typeofType; default: return $$typeof; } } case REACT_PORTAL_TYPE: return $$typeof; } } return undefined; } // AsyncMode is deprecated along with isAsyncMode var AsyncMode = REACT_ASYNC_MODE_TYPE; var ConcurrentMode = REACT_CONCURRENT_MODE_TYPE; var ContextConsumer = REACT_CONTEXT_TYPE; var ContextProvider = REACT_PROVIDER_TYPE; var Element = REACT_ELEMENT_TYPE; var ForwardRef = REACT_FORWARD_REF_TYPE; var Fragment = REACT_FRAGMENT_TYPE; var Lazy = REACT_LAZY_TYPE; var Memo = REACT_MEMO_TYPE; var Portal = REACT_PORTAL_TYPE; var Profiler = REACT_PROFILER_TYPE; var StrictMode = REACT_STRICT_MODE_TYPE; var Suspense = REACT_SUSPENSE_TYPE; var hasWarnedAboutDeprecatedIsAsyncMode = false; // AsyncMode should be deprecated function isAsyncMode(object) { { if (!hasWarnedAboutDeprecatedIsAsyncMode) { hasWarnedAboutDeprecatedIsAsyncMode = true; // Using console['warn'] to evade Babel and ESLint console['warn']('The ReactIs.isAsyncMode() alias has been deprecated, ' + 'and will be removed in React 17+. Update your code to use ' + 'ReactIs.isConcurrentMode() instead. It has the exact same API.'); } } return isConcurrentMode(object) || typeOf(object) === REACT_ASYNC_MODE_TYPE; } function isConcurrentMode(object) { return typeOf(object) === REACT_CONCURRENT_MODE_TYPE; } function isContextConsumer(object) { return typeOf(object) === REACT_CONTEXT_TYPE; } function isContextProvider(object) { return typeOf(object) === REACT_PROVIDER_TYPE; } function isElement(object) { return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE; } function isForwardRef(object) { return typeOf(object) === REACT_FORWARD_REF_TYPE; } function isFragment(object) { return typeOf(object) === REACT_FRAGMENT_TYPE; } function isLazy(object) { return typeOf(object) === REACT_LAZY_TYPE; } function isMemo(object) { return typeOf(object) === REACT_MEMO_TYPE; } function isPortal(object) { return typeOf(object) === REACT_PORTAL_TYPE; } function isProfiler(object) { return typeOf(object) === REACT_PROFILER_TYPE; } function isStrictMode(object) { return typeOf(object) === REACT_STRICT_MODE_TYPE; } function isSuspense(object) { return typeOf(object) === REACT_SUSPENSE_TYPE; } reactIs_development.AsyncMode = AsyncMode; reactIs_development.ConcurrentMode = ConcurrentMode; reactIs_development.ContextConsumer = ContextConsumer; reactIs_development.ContextProvider = ContextProvider; reactIs_development.Element = Element; reactIs_development.ForwardRef = ForwardRef; reactIs_development.Fragment = Fragment; reactIs_development.Lazy = Lazy; reactIs_development.Memo = Memo; reactIs_development.Portal = Portal; reactIs_development.Profiler = Profiler; reactIs_development.StrictMode = StrictMode; reactIs_development.Suspense = Suspense; reactIs_development.isAsyncMode = isAsyncMode; reactIs_development.isConcurrentMode = isConcurrentMode; reactIs_development.isContextConsumer = isContextConsumer; reactIs_development.isContextProvider = isContextProvider; reactIs_development.isElement = isElement; reactIs_development.isForwardRef = isForwardRef; reactIs_development.isFragment = isFragment; reactIs_development.isLazy = isLazy; reactIs_development.isMemo = isMemo; reactIs_development.isPortal = isPortal; reactIs_development.isProfiler = isProfiler; reactIs_development.isStrictMode = isStrictMode; reactIs_development.isSuspense = isSuspense; reactIs_development.isValidElementType = isValidElementType; reactIs_development.typeOf = typeOf; })(); } if (process.env.NODE_ENV === 'production') { reactIs.exports = reactIs_production_min; } else { reactIs.exports = reactIs_development; } /* object-assign (c) Sindre Sorhus @license MIT */ /* eslint-disable no-unused-vars */ var getOwnPropertySymbols = Object.getOwnPropertySymbols; var hasOwnProperty$h = Object.prototype.hasOwnProperty; var propIsEnumerable = Object.prototype.propertyIsEnumerable; function toObject$3(val) { if (val === null || val === undefined) { throw new TypeError('Object.assign cannot be called with null or undefined'); } return Object(val); } function shouldUseNative() { try { if (!Object.assign) { return false; } // Detect buggy property enumeration order in older V8 versions. // https://bugs.chromium.org/p/v8/issues/detail?id=4118 var test1 = new String('abc'); // eslint-disable-line no-new-wrappers test1[5] = 'de'; if (Object.getOwnPropertyNames(test1)[0] === '5') { return false; } // https://bugs.chromium.org/p/v8/issues/detail?id=3056 var test2 = {}; for (var i = 0; i < 10; i++) { test2['_' + String.fromCharCode(i)] = i; } var order2 = Object.getOwnPropertyNames(test2).map(function (n) { return test2[n]; }); if (order2.join('') !== '0123456789') { return false; } // https://bugs.chromium.org/p/v8/issues/detail?id=3056 var test3 = {}; 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { test3[letter] = letter; }); if (Object.keys(Object.assign({}, test3)).join('') !== 'abcdefghijklmnopqrst') { return false; } return true; } catch (err) { // We don't expect any of the above to throw, but better to be safe. return false; } } var objectAssign = shouldUseNative() ? Object.assign : function (target, source) { var from; var to = toObject$3(target); var symbols; for (var s = 1; s < arguments.length; s++) { from = Object(arguments[s]); for (var key in from) { if (hasOwnProperty$h.call(from, key)) { to[key] = from[key]; } } if (getOwnPropertySymbols) { symbols = getOwnPropertySymbols(from); for (var i = 0; i < symbols.length; i++) { if (propIsEnumerable.call(from, symbols[i])) { to[symbols[i]] = from[symbols[i]]; } } } } return to; }; /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var ReactPropTypesSecret$3 = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'; var ReactPropTypesSecret_1 = ReactPropTypesSecret$3; /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var printWarning$1 = function() {}; if (process.env.NODE_ENV !== 'production') { var ReactPropTypesSecret$2 = ReactPropTypesSecret_1; var loggedTypeFailures = {}; var has$6 = Function.call.bind(Object.prototype.hasOwnProperty); printWarning$1 = function(text) { var message = 'Warning: ' + text; if (typeof console !== 'undefined') { console.error(message); } try { // --- Welcome to debugging React --- // This error was thrown as a convenience so that you can use this stack // to find the callsite that caused this warning to fire. throw new Error(message); } catch (x) {} }; } /** * Assert that the values match with the type specs. * Error messages are memorized and will only be shown once. * * @param {object} typeSpecs Map of name to a ReactPropType * @param {object} values Runtime values that need to be type-checked * @param {string} location e.g. "prop", "context", "child context" * @param {string} componentName Name of the component for error messages. * @param {?Function} getStack Returns the component stack. * @private */ function checkPropTypes$1(typeSpecs, values, location, componentName, getStack) { if (process.env.NODE_ENV !== 'production') { for (var typeSpecName in typeSpecs) { if (has$6(typeSpecs, typeSpecName)) { var error; // Prop type validation may throw. In case they do, we don't want to // fail the render phase where it didn't fail before. So we log it. // After these have been cleaned up, we'll let them throw. try { // This is intentionally an invariant that gets caught. It's the same // behavior as without this statement except with a better message. if (typeof typeSpecs[typeSpecName] !== 'function') { var err = Error( (componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' ); err.name = 'Invariant Violation'; throw err; } error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret$2); } catch (ex) { error = ex; } if (error && !(error instanceof Error)) { printWarning$1( (componentName || 'React class') + ': type specification of ' + location + ' `' + typeSpecName + '` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a ' + typeof error + '. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).' ); } if (error instanceof Error && !(error.message in loggedTypeFailures)) { // Only monitor this failure once because there tends to be a lot of the // same error. loggedTypeFailures[error.message] = true; var stack = getStack ? getStack() : ''; printWarning$1( 'Failed ' + location + ' type: ' + error.message + (stack != null ? stack : '') ); } } } } } /** * Resets warning cache when testing. * * @private */ checkPropTypes$1.resetWarningCache = function() { if (process.env.NODE_ENV !== 'production') { loggedTypeFailures = {}; } }; var checkPropTypes_1 = checkPropTypes$1; /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var ReactIs$1 = reactIs.exports; var assign = objectAssign; var ReactPropTypesSecret$1 = ReactPropTypesSecret_1; var checkPropTypes = checkPropTypes_1; var has$5 = Function.call.bind(Object.prototype.hasOwnProperty); var printWarning = function() {}; if (process.env.NODE_ENV !== 'production') { printWarning = function(text) { var message = 'Warning: ' + text; if (typeof console !== 'undefined') { console.error(message); } try { // --- Welcome to debugging React --- // This error was thrown as a convenience so that you can use this stack // to find the callsite that caused this warning to fire. throw new Error(message); } catch (x) {} }; } function emptyFunctionThatReturnsNull() { return null; } var factoryWithTypeCheckers = function(isValidElement, throwOnDirectAccess) { /* global Symbol */ var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec. /** * Returns the iterator method function contained on the iterable object. * * Be sure to invoke the function with the iterable as context: * * var iteratorFn = getIteratorFn(myIterable); * if (iteratorFn) { * var iterator = iteratorFn.call(myIterable); * ... * } * * @param {?object} maybeIterable * @return {?function} */ function getIteratorFn(maybeIterable) { var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]); if (typeof iteratorFn === 'function') { return iteratorFn; } } /** * Collection of methods that allow declaration and validation of props that are * supplied to React components. Example usage: * * var Props = require('ReactPropTypes'); * var MyArticle = React.createClass({ * propTypes: { * // An optional string prop named "description". * description: Props.string, * * // A required enum prop named "category". * category: Props.oneOf(['News','Photos']).isRequired, * * // A prop named "dialog" that requires an instance of Dialog. * dialog: Props.instanceOf(Dialog).isRequired * }, * render: function() { ... } * }); * * A more formal specification of how these methods are used: * * type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...) * decl := ReactPropTypes.{type}(.isRequired)? * * Each and every declaration produces a function with the same signature. This * allows the creation of custom validation functions. For example: