2017-07-09 17:27:29 +00:00
// @flow
2020-08-09 05:53:59 +00:00
import { intersection } from "lodash" ;
2020-06-20 20:59:15 +00:00
import { observable } from "mobx" ;
import { inject , observer } from "mobx-react" ;
2020-08-09 05:53:59 +00:00
import * as React from "react" ;
2020-11-30 04:04:58 +00:00
import { withTranslation , type TFunction } from "react-i18next" ;
2020-08-09 05:53:59 +00:00
import { withRouter , type RouterHistory } from "react-router-dom" ;
import CollectionsStore from "stores/CollectionsStore" ;
import UiStore from "stores/UiStore" ;
import Collection from "models/Collection" ;
2020-06-20 20:59:15 +00:00
import Button from "components/Button" ;
2020-08-09 05:53:59 +00:00
import Flex from "components/Flex" ;
import HelpText from "components/HelpText" ;
import IconPicker , { icons } from "components/IconPicker" ;
2020-06-20 20:59:15 +00:00
import Input from "components/Input" ;
import InputRich from "components/InputRich" ;
2020-08-09 05:53:59 +00:00
import Switch from "components/Switch" ;
2017-07-09 17:27:29 +00:00
2017-07-10 03:56:36 +00:00
type Props = {
2019-08-09 06:09:09 +00:00
history : RouterHistory ,
2018-12-05 06:24:30 +00:00
ui : UiStore ,
2017-07-10 03:56:36 +00:00
collections : CollectionsStore ,
2017-08-29 15:37:17 +00:00
onSubmit : ( ) => void ,
2020-11-30 04:04:58 +00:00
t : TFunction ,
2017-07-10 03:56:36 +00:00
} ;
2017-07-10 03:02:10 +00:00
2017-11-10 22:14:30 +00:00
@ observer
2018-05-05 23:16:08 +00:00
class CollectionNew extends React . Component < Props > {
2020-06-20 20:59:15 +00:00
@ observable name : string = "" ;
@ observable description : string = "" ;
@ observable icon : string = "" ;
@ observable color : string = "#4E5C6E" ;
2019-01-05 21:37:33 +00:00
@ observable private : boolean = false ;
2017-07-10 06:53:35 +00:00
@ observable isSaving : boolean ;
2020-06-20 00:18:03 +00:00
hasOpenedIconPicker : boolean = false ;
2017-07-10 03:56:36 +00:00
2019-08-09 06:09:09 +00:00
handleSubmit = async ( ev : SyntheticEvent < > ) => {
2017-07-09 17:27:29 +00:00
ev . preventDefault ( ) ;
2017-07-10 06:53:35 +00:00
this . isSaving = true ;
2018-12-05 06:24:30 +00:00
const collection = new Collection (
{
name : this . name ,
description : this . description ,
2020-06-20 00:18:03 +00:00
icon : this . icon ,
2018-12-05 06:24:30 +00:00
color : this . color ,
2019-01-05 21:37:33 +00:00
private : this . private ,
2018-12-05 06:24:30 +00:00
} ,
this . props . collections
) ;
2017-07-10 03:56:36 +00:00
2018-12-05 06:24:30 +00:00
try {
await collection . save ( ) ;
2017-08-29 15:37:17 +00:00
this . props . onSubmit ( ) ;
2018-12-05 06:24:30 +00:00
this . props . history . push ( collection . url ) ;
} catch ( err ) {
this . props . ui . showToast ( err . message ) ;
} finally {
this . isSaving = false ;
2017-07-10 03:56:36 +00:00
}
2017-07-09 17:27:29 +00:00
} ;
2018-05-05 23:16:08 +00:00
handleNameChange = ( ev : SyntheticInputEvent < * > ) => {
2017-07-10 06:53:35 +00:00
this . name = ev . target . value ;
2020-06-20 00:18:03 +00:00
// If the user hasn't picked an icon yet, go ahead and suggest one based on
// the name of the collection. It's the little things sometimes.
if ( ! this . hasOpenedIconPicker ) {
const keys = Object . keys ( icons ) ;
for ( const key of keys ) {
const icon = icons [ key ] ;
2020-06-20 20:59:15 +00:00
const keywords = icon . keywords . split ( " " ) ;
const namewords = this . name . toLowerCase ( ) . split ( " " ) ;
2020-06-20 00:18:03 +00:00
const matches = intersection ( namewords , keywords ) ;
if ( matches . length > 0 ) {
this . icon = key ;
return ;
}
}
2020-06-20 20:59:15 +00:00
this . icon = "collection" ;
2020-06-20 00:18:03 +00:00
}
} ;
handleIconPickerOpen = ( ) => {
this . hasOpenedIconPicker = true ;
2017-07-09 17:27:29 +00:00
} ;
2020-11-30 04:04:58 +00:00
handleDescriptionChange = ( getValue : ( ) => string ) => {
2018-11-20 07:04:55 +00:00
this . description = getValue ( ) ;
} ;
2019-01-05 21:37:33 +00:00
handlePrivateChange = ( ev : SyntheticInputEvent < * > ) => {
this . private = ev . target . checked ;
} ;
2020-06-20 00:18:03 +00:00
handleChange = ( color : string , icon : string ) => {
2017-10-30 06:22:46 +00:00
this . color = color ;
2020-06-20 00:18:03 +00:00
this . icon = icon ;
2017-10-30 06:22:46 +00:00
} ;
2017-07-09 17:27:29 +00:00
render ( ) {
2020-11-30 04:04:58 +00:00
const { t } = this . props ;
2017-07-09 17:27:29 +00:00
return (
< form onSubmit = { this . handleSubmit } >
2017-07-10 03:02:10 +00:00
< HelpText >
2020-11-30 04:04:58 +00:00
{ t (
"Collections are for grouping your knowledge base. They work best when organized around a topic or internal team — Product or Engineering for example."
) }
2017-07-10 03:02:10 +00:00
< / H e l p T e x t >
2019-08-24 05:24:06 +00:00
< Flex >
< Input
type = "text"
2020-11-30 04:04:58 +00:00
label = { t ( "Name" ) }
2019-08-24 05:24:06 +00:00
onChange = { this . handleNameChange }
value = { this . name }
required
autoFocus
flex
/ >
2020-06-20 00:18:03 +00:00
& nbsp ;
< IconPicker
onOpen = { this . handleIconPickerOpen }
onChange = { this . handleChange }
color = { this . color }
icon = { this . icon }
/ >
2019-08-24 05:24:06 +00:00
< / F l e x >
2018-11-20 07:04:55 +00:00
< InputRich
2020-11-30 04:04:58 +00:00
label = { t ( "Description" ) }
2018-11-20 07:04:55 +00:00
onChange = { this . handleDescriptionChange }
2020-06-20 20:59:15 +00:00
defaultValue = { this . description || "" }
2020-11-30 04:04:58 +00:00
placeholder = { t ( "More details about this collection…" ) }
2018-11-20 07:04:55 +00:00
minHeight = { 68 }
maxHeight = { 200 }
/ >
2019-01-05 21:37:33 +00:00
< Switch
id = "private"
2020-11-30 04:04:58 +00:00
label = { t ( "Private collection" ) }
2019-01-05 21:37:33 +00:00
onChange = { this . handlePrivateChange }
checked = { this . private }
/ >
< HelpText >
2020-11-30 04:04:58 +00:00
{ t (
"A private collection will only be visible to invited team members."
) }
2019-01-05 21:37:33 +00:00
< / H e l p T e x t >
2017-07-10 06:53:35 +00:00
< Button type = "submit" disabled = { this . isSaving || ! this . name } >
2020-11-30 04:04:58 +00:00
{ this . isSaving ? t ( "Creating…" ) : t ( "Create" ) }
2017-07-09 17:27:29 +00:00
< / B u t t o n >
< / f o r m >
) ;
}
}
2020-11-30 04:04:58 +00:00
export default withTranslation ( ) < CollectionNew > (
inject ( "collections" , "ui" ) ( withRouter ( CollectionNew ) )
) ;