import * as React from 'react' ; import { TemplateProps } from '../customization/props' ; import { ElementModel } from '../data/model' ; import { DiagramView } from '../diagram/view' ; import { PaperAreaContextTypes , PaperAreaContextWrapper , } from '../diagram/paperArea' ; import { Cancellation , CancellationToken } from '../viewUtils/async' ; import { Listener } from '../viewUtils/events' ; import { WorkspaceContextTypes , WorkspaceContextWrapper , } from '../workspace/workspaceContext' ; import { AuthoringState , AuthoringKind } from './authoringState' ; import { EditorController , EditorEvents } from './editorController' ; export interface AuthoredEntityProps { templateProps : TemplateProps ; children : ( context : AuthoredEntityContext ) => React . ReactElement < any > ; } export interface AuthoredEntityContext { editor : EditorController ; editedIri ? : string ; view : DiagramView ; canEdit : boolean | undefined ; canDelete : boolean | undefined ; onEdit : ( ) => void ; onDelete : ( ) => void ; } export interface State { canEdit ? : boolean ; canDelete ? : boolean ; } /**
 * Component to simplify tracking changes in validation messages (property and link type labels).
 */ export class AuthoredEntity extends React . Component < AuthoredEntityProps , State > { static contextTypes = { ... PaperAreaContextTypes , ... WorkspaceContextTypes } ; context : PaperAreaContextWrapper & WorkspaceContextWrapper ; private queryCancellation = new Cancellation ( ) ; constructor ( props , context ) { super ( props , context ) ; this . state = { } ; } componentDidMount ( ) { const { editor } = this . context . workspace ; editor . events . on ( 'changeAuthoringState' , this . onChangeAuthoringState ) ; this . queryAllowedActions ( ) ; } componentDidUpdate ( prevProps ) { const shouldUpdateAllowedActions = ! ( this . props . templateProps . data === prevProps . templateProps . data && this . props . templateProps . isExpanded === prevProps . templateProps . isExpanded ) ; if ( shouldUpdateAllowedActions ) { this . queryAllowedActions ( ) ; } } componentWillUnmount ( ) { const { editor } = this . context . workspace ; editor . events . off ( 'changeAuthoringState' , this . onChangeAuthoringState ) ; this . queryCancellation . abort ( ) ; } private onChangeAuthoringState : Listener < EditorEvents , 'changeAuthoringState' > = ( e ) => { const { source : editor , previous } = e ; const iri = this . props . templateProps . data . id ; const current = editor . authoringState ; if ( current . elements . get ( iri ) !== previous . elements . get ( iri ) ) { this . queryAllowedActions ( ) ; } } ; private queryAllowedActions ( ) { const { isExpanded , data } = this . props . templateProps ; if ( ! isExpanded ) { return ; } this . queryCancellation . abort ( ) ; this . queryCancellation = new Cancellation ( ) ; const { editor } = this . context . workspace ; if ( ! editor . metadataApi || AuthoringState . isDeletedElement ( editor . authoringState , data . id ) ) { this . setState ( { canEdit : false , canDelete : false } ) ; } else { this . queryCanEdit ( data ) ; this . queryCanDelete ( data ) ; } } private queryCanEdit ( data ) { const { editor } = this . context . workspace ; const signal = this . queryCancellation . signal ; this . setState ( { canEdit : undefined } ) ; CancellationToken . mapCancelledToNull ( signal , editor . metadataApi . canEditElement ( data , signal ) ) . then ( ( canEdit ) => { if ( canEdit === null ) { return ; } this . setState ( { canEdit } ) ; } ) ; } private queryCanDelete ( data ) { const { editor } = this . context . workspace ; const signal = this . queryCancellation . signal ; this . setState ( { canDelete : undefined } ) ; CancellationToken . mapCancelledToNull ( signal , editor . metadataApi . canDeleteElement ( data , signal ) ) . then ( ( canDelete ) => { if ( canDelete === null ) { return ; } this . setState ( { canDelete } ) ; } ) ; } render ( ) { const { children : renderTemplate } = this . props ; const { view } = this . context . paperArea ; const { editor } = this . context . workspace ; const { canEdit , canDelete } = this . state ; const iri = this . props . templateProps . iri ; const elementEvent = editor . authoringState . elements . get ( iri ) ; const editedIri = elementEvent && elementEvent . type === AuthoringKind . ChangeElement ? elementEvent . newIri : undefined ; return renderTemplate ( { editor , view , canEdit , canDelete , editedIri , onEdit : this . onEdit , onDelete : this . onDelete , } ) ; } private onEdit = ( ) => { const { editor } = this . context . workspace ; const { elementId } = this . props . templateProps ; const element = editor . model . getElement ( elementId ) ; editor . showEditEntityForm ( element ) ; } ; private onDelete = ( ) => { const { editor } = this . context . workspace ; const { data } = this . props . templateProps ; editor . deleteEntity ( data . id ) ; } ; }