mirror of
https://github.com/zhigang1992/firecms.git
synced 2026-06-15 01:58:59 +08:00
Allowing override locale (only for dates) and dates format
https://github.com/Camberi/firecms/issues/58
This commit is contained in:
42
README.md
42
README.md
@@ -54,6 +54,7 @@ yarn add @camberi/firecms
|
||||
## Features
|
||||
|
||||
### CMS
|
||||
|
||||
- [x] Real-time Collection views for entities
|
||||
- [x] Infinite scrolling in collections with optional pagination
|
||||
- [x] Collection text search integration
|
||||
@@ -66,6 +67,7 @@ yarn add @camberi/firecms
|
||||
- [ ] Allow set up of a project using a CLI create-firecms-app
|
||||
|
||||
### Entity edition
|
||||
|
||||
- [x] Create, read, update, delete views
|
||||
- [x] Form for editing entities
|
||||
- [x] Implementation of fields for every property (except Geopoint)
|
||||
@@ -86,7 +88,6 @@ you do not need a specific backend to make it run. Just build your project
|
||||
following the installation instructions and deploy it in the way you prefer. A
|
||||
very easy way is using Firebase Hosting.
|
||||
|
||||
|
||||
## Firebase requirements
|
||||
|
||||
You need to enable the Firestore database in your Firebase project. If you have
|
||||
@@ -117,8 +118,8 @@ picked up automatically.
|
||||
```yarn add @camberi/firecms @material-ui/core @material-ui/icons @material-ui/pickers firebase```
|
||||
|
||||
You can replace the content of the file App.tsx with the following sample code.
|
||||
Remember to replace the Firebase config with the one you get after creating
|
||||
a webapp in the Firebase console.
|
||||
Remember to replace the Firebase config with the one you get after creating a
|
||||
webapp in the Firebase console.
|
||||
|
||||
```tsx
|
||||
import React from "react";
|
||||
@@ -389,7 +390,15 @@ the following specs:
|
||||
- `toolbarExtraWidget` A component that gets rendered on the upper side of the
|
||||
main toolbar.
|
||||
|
||||
- `schemaResolver`:
|
||||
- `dateTimeFormat` Format of the dates in the CMS. Defaults to 'MMMM dd, yyyy,
|
||||
HH:mm:ss'
|
||||
|
||||
- `locale` Locale of the CMS, currently only affecting dates
|
||||
|
||||
- `schemaResolver` Used to override schemas based on the collection path and
|
||||
entityId. This resolver allows to override the schema for specific entities,
|
||||
or specific collections, app wide. This overrides schemas all through the app.
|
||||
You can also override schemas in place, when using `useSideEntityController`
|
||||
|
||||
## Entities configuration
|
||||
|
||||
@@ -596,14 +605,13 @@ the `CMSFieldProps` [here](https://github.com/Camberi/firecms/blob/master/src/fo
|
||||
You can also pass custom props to your custom field, which you then receive in
|
||||
the `customProps`.
|
||||
|
||||
If you are developing a custom field and need to access the values of the entity,
|
||||
you can use the `context` field in CMSFieldProps.
|
||||
If you are developing a custom field and need to access the values of the
|
||||
entity, you can use the `context` field in CMSFieldProps.
|
||||
|
||||
#### Saving callbacks
|
||||
|
||||
When you are saving an entity you can attach diff
|
||||
erent hooks before and after it
|
||||
gets saved: `onPreSave`, `onSaveSuccess` and `onSaveFailure`.
|
||||
When you are saving an entity you can attach diff erent hooks before and after
|
||||
it gets saved: `onPreSave`, `onSaveSuccess` and `onSaveFailure`.
|
||||
|
||||
```
|
||||
const productSchema = buildSchema({
|
||||
@@ -841,15 +849,13 @@ The props provided by this context are:
|
||||
* `close()` Close the last panel
|
||||
* `sidePanels` List of side entity panels currently open
|
||||
* `open (props: SideEntityPanelProps & Partial<SchemaSidePanelProps>)`
|
||||
Open a new entity sideDialog. By default, the schema and configuration
|
||||
of the view is fetched from the collections you have specified in the
|
||||
navigation.
|
||||
At least you need to pass the collectionPath of the entity you would like
|
||||
to edit. You can set an entityId if you would like to edit and existing one
|
||||
(or a new one with that id).
|
||||
If you wish, you can also override the `SchemaSidePanelProps` (such
|
||||
as schema or subcollections) and choose to override the CMSApp
|
||||
level `SchemaResolver`.
|
||||
Open a new entity sideDialog. By default, the schema and configuration of the
|
||||
view is fetched from the collections you have specified in the navigation. At
|
||||
least you need to pass the collectionPath of the entity you would like to
|
||||
edit. You can set an entityId if you would like to edit and existing one
|
||||
(or a new one with that id). If you wish, you can also override
|
||||
the `SchemaSidePanelProps` (such as schema or subcollections) and choose to
|
||||
override the CMSApp level `SchemaResolver`.
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
@@ -607,6 +607,10 @@ function SampleApp() {
|
||||
markdown: true
|
||||
}
|
||||
},
|
||||
test_date: {
|
||||
title: "Test date",
|
||||
dataType: "timestamp",
|
||||
},
|
||||
created_at: {
|
||||
title: "Created at",
|
||||
dataType: "timestamp",
|
||||
|
||||
@@ -9,7 +9,9 @@ import {
|
||||
ThemeProvider
|
||||
} from "@material-ui/core";
|
||||
import { MuiPickersUtilsProvider } from "@material-ui/pickers";
|
||||
|
||||
import DateFnsUtils from "@date-io/date-fns";
|
||||
import * as locales from "date-fns/locale";
|
||||
|
||||
import { BrowserRouter as Router } from "react-router-dom";
|
||||
|
||||
@@ -90,9 +92,10 @@ export function CMSApp(props: CMSAppProps) {
|
||||
fontFamily,
|
||||
toolbarExtraWidget,
|
||||
schemaResolver,
|
||||
locale,
|
||||
signInOptions = [
|
||||
firebase.auth.GoogleAuthProvider.PROVIDER_ID
|
||||
],
|
||||
]
|
||||
} = props;
|
||||
|
||||
const classes = useStyles();
|
||||
@@ -251,14 +254,18 @@ export function CMSApp(props: CMSAppProps) {
|
||||
signInOptions={signInOptions}/>;
|
||||
}
|
||||
|
||||
const dateUtilsLocale = locale ? locales[locale] : undefined;
|
||||
|
||||
function renderMainView() {
|
||||
return (
|
||||
<Router>
|
||||
<SchemaRegistryProvider navigation={navigation} schemaResolver={schemaResolver}>
|
||||
<SchemaRegistryProvider navigation={navigation}
|
||||
schemaResolver={schemaResolver}>
|
||||
<SideEntityProvider navigation={navigation}>
|
||||
<BreadcrumbsProvider>
|
||||
<MuiPickersUtilsProvider
|
||||
utils={DateFnsUtils}>
|
||||
utils={DateFnsUtils}
|
||||
locale={dateUtilsLocale}>
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
|
||||
<nav>
|
||||
|
||||
@@ -4,11 +4,7 @@ import "firebase/auth";
|
||||
import "firebase/storage";
|
||||
import "firebase/firestore";
|
||||
import { Authenticator, EntityCollection } from "./models";
|
||||
import {
|
||||
SchemaResolver,
|
||||
SchemaSidePanelProps,
|
||||
SideEntityPanelProps
|
||||
} from "./side_dialog/model";
|
||||
import { SchemaResolver } from "./side_dialog/model";
|
||||
|
||||
/**
|
||||
* Main entry point that defines the CMS configuration
|
||||
@@ -80,7 +76,7 @@ export interface CMSAppProps {
|
||||
primaryColor?: string;
|
||||
|
||||
/**
|
||||
* Primary color of the theme of the CMS
|
||||
* Secondary color of the theme of the CMS
|
||||
*/
|
||||
secondaryColor?: string
|
||||
|
||||
@@ -96,6 +92,17 @@ export interface CMSAppProps {
|
||||
*/
|
||||
toolbarExtraWidget?: React.ReactNode;
|
||||
|
||||
/**
|
||||
* Format of the dates in the CMS.
|
||||
* Defaults to 'MMMM dd, yyyy, HH:mm:ss'
|
||||
*/
|
||||
dateTimeFormat?: string;
|
||||
|
||||
/**
|
||||
* Locale of the CMS, currently only affecting dates
|
||||
*/
|
||||
locale?: Locale;
|
||||
|
||||
/**
|
||||
* Used to override schemas based on the collection path and entityId.
|
||||
* This resolver allows to override the schema for specific entities, or
|
||||
@@ -134,3 +141,83 @@ export interface AdditionalView {
|
||||
group?: string;
|
||||
|
||||
}
|
||||
|
||||
|
||||
export type Locale =
|
||||
"af" |
|
||||
"ar" |
|
||||
"arDZ" |
|
||||
"arMA" |
|
||||
"arSA" |
|
||||
"az" |
|
||||
"be" |
|
||||
"bg" |
|
||||
"bn" |
|
||||
"ca" |
|
||||
"cs" |
|
||||
"cy" |
|
||||
"da" |
|
||||
"de" |
|
||||
"el" |
|
||||
"enAU" |
|
||||
"enCA" |
|
||||
"enGB" |
|
||||
"enIN" |
|
||||
"enNZ" |
|
||||
"enUS" |
|
||||
"eo" |
|
||||
"es" |
|
||||
"et" |
|
||||
"eu" |
|
||||
"faIR" |
|
||||
"fi" |
|
||||
"fil" |
|
||||
"fr" |
|
||||
"frCA" |
|
||||
"frCH" |
|
||||
"gd" |
|
||||
"gl" |
|
||||
"gu" |
|
||||
"he" |
|
||||
"hi" |
|
||||
"hr" |
|
||||
"hu" |
|
||||
"hy" |
|
||||
"id" |
|
||||
"is" |
|
||||
"it" |
|
||||
"ja" |
|
||||
"ka" |
|
||||
"kk" |
|
||||
"kn" |
|
||||
"ko" |
|
||||
"lb" |
|
||||
"lt" |
|
||||
"lv" |
|
||||
"mk" |
|
||||
"ms" |
|
||||
"mt" |
|
||||
"nb" |
|
||||
"nl" |
|
||||
"nlBE" |
|
||||
"nn" |
|
||||
"pl" |
|
||||
"pt" |
|
||||
"ptBR" |
|
||||
"ro" |
|
||||
"ru" |
|
||||
"sk" |
|
||||
"sl" |
|
||||
"sr" |
|
||||
"srLatn" |
|
||||
"sv" |
|
||||
"ta" |
|
||||
"te" |
|
||||
"th" |
|
||||
"tr" |
|
||||
"ug" |
|
||||
"uk" |
|
||||
"uz" |
|
||||
"vi" |
|
||||
"zhCN" |
|
||||
"zhTW";
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
Property,
|
||||
ReferenceProperty,
|
||||
saveEntity,
|
||||
StringProperty
|
||||
StringProperty, TimestampProperty
|
||||
} from "../models";
|
||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { createStyles, makeStyles, Theme } from "@material-ui/core";
|
||||
@@ -227,6 +227,7 @@ const PropertyTableCell = <T, S extends EntitySchema<Key>, Key extends string>({
|
||||
focused={focused}
|
||||
internalValue={internalValue as Date}
|
||||
updateValue={updateValue}
|
||||
property={property as TimestampProperty}
|
||||
setPreventOutsideClick={setPreventOutsideClick}
|
||||
/>;
|
||||
allowScroll = true;
|
||||
|
||||
@@ -2,8 +2,9 @@ import React, { useState } from "react";
|
||||
import { useInputStyles } from "./styles";
|
||||
import { KeyboardDateTimePicker } from "@material-ui/pickers";
|
||||
import { Box, Typography } from "@material-ui/core";
|
||||
import { EmptyValue } from "../../preview";
|
||||
import { EmptyValue, TimestampPreview } from "../../preview";
|
||||
import CalendarTodayIcon from "@material-ui/icons/CalendarToday";
|
||||
import { TimestampProperty } from "../../models";
|
||||
|
||||
export function TableDateField(props: {
|
||||
name: string;
|
||||
@@ -12,11 +13,12 @@ export function TableDateField(props: {
|
||||
updateValue: (newValue: (Date | null)) => void;
|
||||
focused: boolean;
|
||||
disabled: boolean;
|
||||
property: TimestampProperty;
|
||||
onBlur?: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
|
||||
setPreventOutsideClick: (value: any) => void;
|
||||
}) {
|
||||
|
||||
const { disabled, error, internalValue, setPreventOutsideClick, updateValue } = props;
|
||||
const { disabled, error, internalValue, setPreventOutsideClick, updateValue, property } = props;
|
||||
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
const handleOpen = () => {
|
||||
@@ -37,7 +39,7 @@ export function TableDateField(props: {
|
||||
<Box flexGrow={1}>
|
||||
{internalValue &&
|
||||
<Typography variant={"body2"}>
|
||||
{internalValue.toLocaleString()}
|
||||
<TimestampPreview value={internalValue} property={property} size={"regular"}/>
|
||||
</Typography>}
|
||||
{!internalValue && <EmptyValue/>}
|
||||
</Box>
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import React from "react";
|
||||
import { DateTimePicker } from "@material-ui/pickers";
|
||||
|
||||
import { FieldProps } from "../../models/form_props";
|
||||
import { FieldProps } from "../../models";
|
||||
|
||||
import { FieldDescription } from "../../components";
|
||||
import { LabelWithIcon } from "../components/LabelWithIcon";
|
||||
import { useClearRestoreValue } from "../useClearRestoreValue";
|
||||
import firebase from "firebase";
|
||||
import { CMSAppProps } from "../../CMSAppProps";
|
||||
import { useAppConfigContext } from "../../contexts";
|
||||
import { defaultDateFormat } from "../../util/dates";
|
||||
|
||||
type DateTimeFieldProps = FieldProps<Date>;
|
||||
|
||||
@@ -27,6 +29,9 @@ export default function DateTimeField({
|
||||
|
||||
const internalValue = value || null;
|
||||
|
||||
const appConfig: CMSAppProps | undefined = useAppConfigContext();
|
||||
const dateFormat: string = appConfig?.dateTimeFormat ?? defaultDateFormat;
|
||||
|
||||
useClearRestoreValue({
|
||||
property,
|
||||
value,
|
||||
@@ -41,6 +46,7 @@ export default function DateTimeField({
|
||||
clearable
|
||||
autoFocus={autoFocus}
|
||||
value={internalValue}
|
||||
format={dateFormat}
|
||||
label={<LabelWithIcon scaledIcon={false} property={property}/>}
|
||||
error={showError}
|
||||
disabled={disabled}
|
||||
|
||||
@@ -42,7 +42,7 @@ export type { PreviewComponentProps } from "./preview";
|
||||
|
||||
export { CMSApp } from "./CMSApp";
|
||||
export type {
|
||||
CMSAppProps, AdditionalView
|
||||
CMSAppProps, AdditionalView, Locale
|
||||
} from "./CMSAppProps";
|
||||
|
||||
|
||||
@@ -68,11 +68,11 @@ export {
|
||||
|
||||
export {
|
||||
FieldDescription,
|
||||
ErrorBoundary,
|
||||
ErrorBoundary
|
||||
} from "./components";
|
||||
|
||||
export {
|
||||
default as EntityPreview,
|
||||
default as EntityPreview
|
||||
} from "./components/EntityPreview";
|
||||
|
||||
export {
|
||||
|
||||
@@ -1,17 +1,29 @@
|
||||
import { PreviewComponentProps } from "../../preview";
|
||||
import React from "react";
|
||||
import firebase from "firebase/app";
|
||||
|
||||
import { CMSAppProps } from "../../CMSAppProps";
|
||||
import { useAppConfigContext } from "../../contexts";
|
||||
|
||||
import format from "date-fns/format";
|
||||
import * as locales from "date-fns/locale";
|
||||
import { defaultDateFormat } from "../../util/dates";
|
||||
|
||||
export function TimestampPreview({
|
||||
name,
|
||||
value,
|
||||
property,
|
||||
size,
|
||||
}: PreviewComponentProps<firebase.firestore.Timestamp | Date>): React.ReactElement {
|
||||
size
|
||||
}: PreviewComponentProps<Date>): React.ReactElement {
|
||||
|
||||
|
||||
const appConfig: CMSAppProps | undefined = useAppConfigContext();
|
||||
const dateUtilsLocale = appConfig.locale ? locales[appConfig.locale] : undefined;
|
||||
const dateFormat: string = appConfig?.dateTimeFormat ?? defaultDateFormat;
|
||||
const formattedDate = value ? format(value, dateFormat, { locale: dateUtilsLocale }) : "";
|
||||
|
||||
return (
|
||||
<>
|
||||
{value.toLocaleString()}
|
||||
{formattedDate}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
1
src/util/dates.ts
Normal file
1
src/util/dates.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const defaultDateFormat = "MMMM dd, yyyy, HH:mm:ss";
|
||||
Reference in New Issue
Block a user