import { Element , ElementContent } from '../element' ; import * as _ from 'lodash' ; import * as Mobx from 'mobx' ; import { Project } from '../project' ; import * as Types from '@meetalva/types' ; import * as uuid from 'uuid' ; import { PatternLibrary } from '../pattern-library' ; import { PlaceholderPosition } from '@meetalva/components' ; export interface PageInit { active : boolean ; focused : boolean ; id : string ; name : string ; rootId : string ; } export interface PageCreateInit { active : boolean ; id : string ; name : string ; } export interface PageContext { project : Project ; } /**
 * UI Interface to define where a drag drop
 * should take place.
 */ export interface DroppablePageIndex { back : boolean ; next : boolean ; } export class Page { public readonly model = Types . ModelName . Page ; @ Mobx . observable private focused : boolean ; @ Mobx . observable private editedName : string = '' ; @ Mobx . observable private id : string ; @ Mobx . observable private name : string = 'Page' ; @ Mobx . observable public nameState : Types . EditableTitleState = Types . EditableTitleState . Neutral ; /**
     * UI property flags to highlight the area
     * where the page can be dropped.
     */ @ Mobx . observable private droppablePageIndex : DroppablePageIndex = { back : false , next : false } ; private project : Project ; private rootId : string ; public constructor ( init , context ) { this . project = context . project ; this . id = init . id ; this . active = init . active ; this . rootId = init . rootId ; this . name = init . name ; this . focused = init . focused ; } @ Mobx . computed private get active ( ) : boolean { return ( this . project . getUserStore ( ) . getPageProperty ( ) . getValue ( ) === this . id ) ; } private set active ( active ) { if ( active ) { this . project . getUserStore ( ) . getPageProperty ( ) . setValue ( this . id ) ; } } @ Mobx . action public static create ( init , context ) { const patternLibrary = context . project . getBuiltinPatternLibrary ( ) ; const rootPattern = patternLibrary . getPatternByType ( Types . PatternType . SyntheticPage ) ; const rootContents = rootPattern . getSlots ( ) . map ( slot => new ElementContent ( { elementIds : [ ] , forcedOpen : false , highlighted : false , id : uuid . v4 ( ) , open : false , slotId : slot . getId ( ) } , context ) ) ; rootContents . forEach ( rootContent => context . project . addElementContent ( rootContent ) ) ; const rootElement = new Element ( { highlighted : false , name : init . name , contentIds : rootContents . map ( c => c . getId ( ) ) , dragged : false , open : true , forcedOpen : false , focused : false , patternId : rootPattern . getId ( ) , placeholderHighlighted : PlaceholderPosition . None , propertyValues : [ ] , role : Types . ElementRole . Root , setDefaults : true , selected : false } , { project : context . project } ) ; rootContents . forEach ( rootContent => rootContent . setParentElement ( rootElement ) ) ; context . project . addElement ( rootElement ) ; return new Page ( { active : init . active , focused : false , id : init . id , name : init . name , rootId : rootElement . getId ( ) } , context ) ; } public static from ( serializedPage , context ) { const page = new Page ( { active : serializedPage . active , focused : serializedPage . focused , id : serializedPage . id , name : serializedPage . name , rootId : serializedPage . rootId } , context ) ; return page ; } public clone ( opts ? ) { const target = opts ? opts . target : this . project ; const withState = Boolean ( opts && opts . withState ) ; const rootElement = this . getRoot ( ) ; const rootClone = rootElement ? rootElement . clone ( { target , withState } ) : undefined ; const page = new Page ( { active : false , focused : false , id : uuid . v4 ( ) , name : this . name , rootId : rootClone ? rootClone . getId ( ) : '' } , { project : this . project } ) ; if ( rootClone ) { this . project . importElement ( rootClone ) ; } return page ; } public equals ( b ) { return _ . isEqual ( this . toJSON ( ) , b . toJSON ( ) ) ; } public getActive ( ) { return this . active ; } public getContentById ( id ) { const rootElement = this . getRoot ( ) ; if ( ! rootElement ) { return ; } return rootElement . getContentById ( id ) ; } /**
     * It return an object containing the states of
     * of the back and next page drag areas.
     */ public getPageDropState ( ) { return this . droppablePageIndex ; } public getFocused ( ) { return this . focused ; } public getEditableName ( ) { return this . editedName ; } public getEditableState ( ) { if ( ! this . focused ) { return Types . EditableTitleState . Neutral ; } return this . focused && this . nameState === Types . EditableTitleState . Editing ? Types . EditableTitleState . Editing : Types . EditableTitleState . Editable ; } public setEditableState ( state ) { this . nameState = state ; } public getElementById ( id ) { const rootElement = this . getRoot ( ) ; if ( ! rootElement ) { return ; } return rootElement . getElementById ( id ) ; } public getId ( ) { return this . id ; } public getIndex ( ) { return this . project . getPages ( ) . indexOf ( this ) ; } public getName ( options ? ) { if ( ( ! options || ! options . unedited ) && this . nameState === Types . EditableTitleState . Editing ) { return this . editedName ; } return this . name ; } public getNameState ( ) { return this . nameState ; } public getRoot ( ) { return this . project . getElementById ( this . rootId ) ; } public hasElement ( element ) { const rootElement = this . getRoot ( ) ; if ( ! rootElement ) { return false ; } return rootElement . getDescendants ( ) . some ( desc => desc . getId ( ) === element . getId ( ) ) ; } @ Mobx . action public setActive ( active ) { this . active = active ; } @ Mobx . action public setDroppableBackState ( droppable ) { this . droppablePageIndex . back = droppable ; } @ Mobx . action public setDroppableNextState ( droppable ) { this . droppablePageIndex . next = droppable ; } @ Mobx . action public setEditableName ( name ) { this . editedName = name ; } @ Mobx . action public setFocused ( focused ) { this . focused = focused ; } @ Mobx . action public setName ( name ) { this . name = name ; this . editedName = name ; } @ Mobx . action public setNameState ( state ) { this . editedName = this . name ; this . nameState = state ; } public setProject ( project ) { this . project = project ; } public toDisk ( ) { const serialized = this . toJSON ( ) ; serialized . active = false ; return serialized ; } public toJSON ( ) { return { model : this . model , active : this . getActive ( ) , focused : this . getFocused ( ) , id : this . getId ( ) , name : this . getName ( ) , rootId : this . rootId } ; } public update ( b ) { this . active = b . active ; this . name = b . name ; this . rootId = b . rootId ; } public getLibraryDependencies ( ) { const rootElement = this . getRoot ( ) ; return rootElement ? rootElement . getLibraryDependencies ( ) : [ ] ; } }