2016-02-25 20:40:35 -08:00
import { OrderedMap , fromJS } from 'immutable' ;
2016-11-11 17:54:58 -02:00
import consoleError from '../lib/consoleError' ;
2016-02-25 12:31:21 -08:00
import { CONFIG _SUCCESS } from '../actions/config' ;
2016-10-21 20:42:14 -02:00
import { FILES , FOLDER } from '../constants/collectionTypes' ;
2016-11-23 16:23:32 -02:00
import { INFERABLE _FIELDS } from '../constants/fieldInference' ;
2016-10-21 20:42:14 -02:00
const hasProperty = ( config , property ) => ( { } . hasOwnProperty . call ( config , property ) ) ;
2016-02-25 00:45:56 -08:00
2016-06-10 00:16:01 -03:00
const collections = ( state = null , action ) => {
2016-11-11 17:54:58 -02:00
const configCollections = action . payload && action . payload . collections ;
2016-02-25 00:45:56 -08:00
switch ( action . type ) {
2016-02-25 12:31:21 -08:00
case CONFIG _SUCCESS :
2016-02-25 20:40:35 -08:00
return OrderedMap ( ) . withMutations ( ( map ) => {
2016-10-21 20:42:14 -02:00
( configCollections || [ ] ) . forEach ( ( configCollection ) => {
if ( hasProperty ( configCollection , 'folder' ) ) {
configCollection . type = FOLDER ; // eslint-disable-line no-param-reassign
} else if ( hasProperty ( configCollection , 'files' ) ) {
configCollection . type = FILES ; // eslint-disable-line no-param-reassign
2016-11-11 17:54:58 -02:00
} else {
throw new Error ( 'Unknown collection type. Collections can be either Folder based or File based. Please verify your site configuration' ) ;
2016-10-21 20:42:14 -02:00
}
map . set ( configCollection . name , fromJS ( configCollection ) ) ;
2016-02-25 00:45:56 -08:00
} ) ;
} ) ;
default :
return state ;
}
2016-06-18 12:29:03 -07:00
} ;
2016-06-10 00:16:01 -03:00
2016-11-11 17:54:58 -02:00
const formatToExtension = format => ( {
markdown : 'md' ,
yaml : 'yml' ,
json : 'json' ,
html : 'html' ,
} [ format ] ) ;
const selectors = {
[ FOLDER ] : {
entryExtension ( collection ) {
return collection . get ( 'extension' ) || formatToExtension ( collection . get ( 'format' ) || 'markdown' ) ;
} ,
fields ( collection ) {
return collection . get ( 'fields' ) ;
} ,
entryPath ( collection , slug ) {
return ` ${ collection . get ( 'folder' ) } / ${ slug } . ${ this . entryExtension ( collection ) } ` ;
} ,
entrySlug ( collection , path ) {
return path . split ( '/' ) . pop ( ) . replace ( /\.[^\.]+$/ , '' ) ;
} ,
listMethod ( ) {
return 'entriesByFolder' ;
} ,
allowNewEntries ( collection ) {
return collection . get ( 'create' ) ;
} ,
templateName ( collection ) {
return collection . get ( 'name' ) ;
} ,
} ,
[ FILES ] : {
fileForEntry ( collection , slug ) {
const files = collection . get ( 'files' ) ;
return files . filter ( f => f . get ( 'name' ) === slug ) . get ( 0 ) ;
} ,
fields ( collection , slug ) {
const file = this . fileForEntry ( collection , slug ) ;
return file && file . get ( 'fields' ) ;
} ,
entryPath ( collection , slug ) {
const file = this . fileForEntry ( collection , slug ) ;
return file && file . get ( 'file' ) ;
} ,
entrySlug ( collection , path ) {
const file = collection . get ( 'files' ) . filter ( f => f . get ( 'file' ) === path ) . get ( 0 ) ;
return file && file . get ( 'name' ) ;
} ,
listMethod ( ) {
return 'entriesByFiles' ;
} ,
allowNewEntries ( ) {
return false ;
} ,
templateName ( collection , slug ) {
return slug ;
} ,
} ,
} ;
export const selectFields = ( collection , slug ) => selectors [ collection . get ( 'type' ) ] . fields ( collection , slug ) ;
export const selectEntryPath = ( collection , slug ) => selectors [ collection . get ( 'type' ) ] . entryPath ( collection , slug ) ;
export const selectEntrySlug = ( collection , path ) => selectors [ collection . get ( 'type' ) ] . entrySlug ( collection , path ) ;
export const selectListMethod = collection => selectors [ collection . get ( 'type' ) ] . listMethod ( ) ;
export const selectAllowNewEntries = collection => selectors [ collection . get ( 'type' ) ] . allowNewEntries ( collection ) ;
export const selectTemplateName = ( collection , slug ) => selectors [ collection . get ( 'type' ) ] . templateName ( collection , slug ) ;
export const selectInferedField = ( collection , fieldName ) => {
2016-11-23 16:23:32 -02:00
const inferableField = INFERABLE _FIELDS [ fieldName ] ;
2016-11-11 17:54:58 -02:00
const fields = collection . get ( 'fields' ) ;
let field ;
// If colllection has no fields or fieldName is not defined within inferables list, return null
if ( ! fields || ! inferableField ) return null ;
// Try to return a field of the specified type with one of the synonyms
2017-01-19 15:50:26 -02:00
const mainTypeFields = fields . filter ( f => f . get ( 'widget' , 'string' ) === inferableField . type ) . map ( f => f . get ( 'name' ) ) ;
2016-11-11 17:54:58 -02:00
field = mainTypeFields . filter ( f => inferableField . synonyms . indexOf ( f ) !== - 1 ) ;
if ( field && field . size > 0 ) return field . first ( ) ;
// Try to return a field for each of the specified secondary types
2017-01-19 15:50:26 -02:00
const secondaryTypeFields = fields . filter ( f => inferableField . secondaryTypes . indexOf ( f . get ( 'widget' , 'string' ) ) !== - 1 ) . map ( f => f . get ( 'name' ) ) ;
2016-11-11 17:54:58 -02:00
field = secondaryTypeFields . filter ( f => inferableField . synonyms . indexOf ( f ) !== - 1 ) ;
if ( field && field . size > 0 ) return field . first ( ) ;
// Try to return the first field of the specified type
if ( inferableField . fallbackToFirstField && mainTypeFields . size > 0 ) return mainTypeFields . first ( ) ;
// Coundn't infer the field. Show error and return null.
if ( inferableField . showError ) {
consoleError (
` The Field ${ fieldName } is missing for the collection “ ${ collection . get ( 'name' ) } ” ` ,
` Netlify CMS tries to infer the entry ${ fieldName } automatically, but one couldn \' t be found for entries of the collection “ ${ collection . get ( 'name' ) } ”. Please check your site configuration. `
) ;
}
return null ;
} ;
2016-06-10 00:16:01 -03:00
export default collections ;