Notes component built with React using Fabric, and styled-components.
Name | Type | Required | Default | Description |
---|---|---|---|---|
notes | Object | Yes | Notes object containing all notes | |
onSubmit | Function | Yes | Function that fires when submitting a new note. Takes in input string and selected Note type | |
showReloadIcon | boolean | No | false | Show Reload Icon in the title section, should come with notesReloadAction |
noteReloadAction | Function | No | Function that fires when click reload button. | |
showPrintIcon | boolean | No | false | Show Print Icon in the title section, print current notes when click the button |
showMergedNotes | boolean | No | true | Merge notes with same user/time |
showUserInfoIcon | boolean | No | false | Show info icon near the username, when hover will show user's information, includes user fullname, email, homeYard, and userId. N.B. fetchUserInfo needed & crt_user_id key should be present! |
fetchUserInfo | Promise | No | Should return as a promise. Takes in input string of userIds. Please check examples at the end of the table. N.B. fetchUserInfo needed & crt_user_id key should be present! |
|
showCopyIcon | boolean | No | true | Show or hide copyIcon in the title section. |
defaultNotesOpen | boolean | No | true | Open notes if there is table, or additional information |
notesFormatter | Function | No | Use to format single note, Takes in input string | |
timeZone | string | No | moment.tz.guess() | Current timezone to correctly display timestamps through moment-timezone (by default will try to guess user's timezone based on browser) |
onOpen | Function | No | Function that fires whenever the notes module is opened | |
onClose | Function | No | Function that fires whenever the notes module is closed | |
loadingNotes | boolean | No | false | Pass true when loading notes and false when finished, for spinner |
title | string | No | '00000000' | Title for the header following the prefix |
titlePrefix | string | No | 'Lot#' | Prefix for the header |
searchTypeKey | string | No | 'lotNotes' | Default search key for searchbar dropdown. (Must match a key on the object passed to the notes prop) |
buttonText | string | No | 'Notes' | Text for the closed notes button |
keyboardShortcut | string | No | 'F6' | Keyboard key to open the notes modules |
bounds | string | No | 'body' | Restriction for the draggable area of the open notes module |
autoSearch | boolean | No | true | Automatically search notes every time user types in searchbox rather than on search button click |
stickyHeader | boolean | No | true | Enable sticky headers for every note to help user maintain context on long notes |
defaultOpen | boolean | No | false | Whether or not notes are open by default on component load |
disableNewNote | boolean | No | false | Whether or not to show new note input |
translations | Object | No | Translations for localization | |
handleScrollEnd | Function | No | Function to handle the end of scroll in notes | |
onChangeNote | Function | No | Function to handle change of note | |
reverseList | boolean | No | true | Flag to determine if the list has to be reversed |
loadNextPage | boolean | No | false | Flag to determine if the next page list needs to be fetched |
disabled | boolean | No | false | Disables the note button |
dateTimeFormat | boolean | No | 'MMM Do [']YY h:mma z' | Change the format of the date and time (use moment supported formats: https://momentjs.com/docs/#/parsing/string-format/ ) |
openInDialog | boolean | No | false | Pass the prop in if put notes in the Dialog component, check sandbox example |
overWriteTitle | Object | No | Pass the prop in if want to over write title, check sandbox example | |
showExpandIcon | boolean | No | true | Show or hide the Expand Icon in the title section, when openInDialog is false |
fetchUserInfo and input
const userIds='yilin,BATUL,Tom'
const fetchUserInfo = (userData) =>
fetcher.post('url', { userAccount: userData })
const response = await fetchUserInfo(userIds)
/*
Order doesn't matter, must have name, userEmail, accountName, failityId
response =
[
{
"name": "Tom Hanks",
"userEmail": "tom.hanks@gmail.com",
"accountName": "yiln",
"facilityId": "700",
....
},
{
"name": "Peter Harris",
"userEmail": "peter.Harris@gmail.com",
"accountName": "Peterh",
"facilityId": "12",
....
},
{...}
]
*/
// notesFormatter example
export const notesFormatter = (note) => {
const newNote = note
? note.slice(0, 5) +
note
.slice(5)
.replace(/\*AUTO/g, '\n*AUTO')
.replace(/\*FILE/g, '\n*FILE')
: ''
return newNote
}
Component
import React from 'react'
import Notes from '@copart/notes-component'
// Refer below for example data structure
import { exampleNotes } from './exampleNotes'
import exampleTranslationsMap from './exampleTranslationsMap'
class App extends React.Component {
state = {
id: '12345678',
notes: {},
loading: false,
}
onOpen = () => {
this.setState({ loading: true })
// Mock async call to retrieve notes
setTimeout(() => {
this.setState({ loading: false, notes: exampleNotes })
}, 1000)
}
onSubmit = (newNoteText) => {
// async POST request goes here
const newNotes = { ...exampleNotes }
newNotes.lotNotes.data.push({
crt_dt: '2018-08-27T07:41:04.000Z',
crt_user: 'username',
note_desc: newNoteText,
})
// on async response with new notes
this.setState({ loading: false, notes: newNotes })
}
render() {
const { notes, loading, id } = this.state
return (
<Notes
titlePrefix="ID#"
title={id}
notes={notes}
onOpen={this.onOpen}
onSubmit={this.onSubmit}
loadingNotes={loading}
searchTypeKey="noteTypeKey2"
timeZone="Europe/Berlin"
translations={exampleTranslationsMap}
// dateTimeFormat={'MM/DD/YYYY HH:mm:ss z'}
// disabled={true}
/>
)
}
}
export default App
Notes Object Example
// Import map and translation data for tables
import { EXAMPLE_PATHS as examplePaths, EXAMPLE_FIELD_MAP as exampleFieldMap } from './examplePaths'
import exampleStages from './exampleStages'
// Example notes object
export const exampleNotes = {
// Keys in this object will be used for the dropdown menu
noteTypeKey1: {
display: 'NOTE TYPE 1', // send the translated version here, if applicable
format: 'table', // only 'table' or 'text' format supported
servicePaths: examplePaths, // service paths for finding correct data to show
stages: exampleStages, // translate stages to readable text
fieldMap: exampleFieldMap, // link field key provided to correct key in translations
data: [
{
crt_user: 'username1',
crt_dt: '2018-08-22T07:41:04.000Z',
// 'table' format must have json property
json: {
previous_lot: {
field_1: 'value',
// field can contain another object (must provide path in service paths)
field_2: {
inner_prop_1: null,
inner_prop_2: 'abc',
},
field_3: 123,
},
current_lot: {
field_1: 'other_value',
field_2: {
inner_prop_1: null,
inner_prop_2: 'cba',
},
field_3: 321,
},
},
},
{
crt_user: 'username2',
crt_dt: '2018-08-23T07:41:04.000Z',
// 'table' format must have json property
json: {
previous_lot: {
field_1: 'value',
},
current_lot: {
field_1: 'other_value',
},
},
},
],
},
noteTypeKey2: {
display: 'NOTE TYPE 2', // send the translated version here, if applicable
format: 'text', // only 'table' or 'text' format supported
enableAddNote: true, // enables text input for new notes
data: [
{
crt_user: 'username1',
crt_dt: '2018-08-22T07:41:04.000Z',
// 'text' format must have 'notes' or 'note_desc' property
notes: 'Note text 1',
},
{
crt_user: 'username2',
crt_dt: '2018-08-23T07:41:04.000Z',
notes: 'Note text 2',
},
],
},
noteTypeKey3: {
display: 'NOTE TYPE 3', // send the translated version here, if applicable
format: 'text', // only 'table' or 'text' format supported
data: [
{
crt_user: 'username1',
crt_dt: '2018-08-22T07:41:04.000Z',
// 'text' format must have 'notes' or 'note_desc' property
note_desc: 'Note description text 1',
},
{
crt_user: 'username2',
crt_dt: '2018-08-23T07:41:04.000Z',
note_desc: 'Note description text 2',
},
],
},
}
Service Paths Example
export const EXAMPLE_PATHS = {
field_1: ['field_1'],
field_2: ['field_2', 'inner_prop_2'],
field_3: ['field_3'],
}
export const EXAMPLE_FIELD_MAP = {
field_1: 'field1',
field_2: 'field2',
field_3: 'field3',
}
Stages Example
const exampleStages = {
value: 'Readable value', // send translated versions here
other_value: 'Other readable value', // send translated versions here
}
export default exampleStages
Translations Map Example
const exampleTranslationsMap = {
field1: 'Field One', // send translated versions here
field2: 'Field Two', // send translated versions here
field3: 'Field Three', // send translated versions here
}
Contributions are welcome, create a Pull Request for any improvements/fixes.
2.0.1 Add overWriteTitle to over write notes dialog title
const overWriteTitle = {
buyerNotes: {
text: 'Buyer#',
value: '123123123',
},
sellerNotes: {
text: 'Seller#',
value: '456456456',
},
}
2.0.2 Fix timeDate display issue.
2.0.3 New notesComponent supports all existing notes. If adding new notes with/without customized table, etc. Follow the below format. Checkout sandbox if need examples.
// for adding new note type, use the following format
notes = {
abcNotes: {
display: 'ABC NOTES',
format: 'text',
data: [
{
note_desc: 'Another C stack format notes 6',
crt_user: 'Jason Wesson',
crt_dt: '2022-10-23T08:34:43Z',
crt_user_id: 'JASON', // need this for showing info icon and hovercard
}
]
},
anotherNewNote: {
display: 'NEW NOTE',
format: 'history',
data: [
{
note_desc: 'Another C stack format notes 7',
crt_user: 'Shirin Herman',
crt_dt: '2021-10-23T08:34:43Z',
renderItemFooter: () => (<div>Render FooterItem/table here...</div>)
},
]
}
}
2.0.4 Optimize Merged notes, upgrade core-component version