/**
 * Copyright 2019 Google Inc. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ import { h , Component , FunctionalComponent } from 'preact' ; import { Result , Topics , Champions } from 'shared/state' ; import { getResultLabel , getResultTopic , getResultChampionName , fetchJSON , escapePatchPathComponent , } from 'client/utils' ; import Select from '../../select' ; interface Props { topics : Topics ; champions : Champions ; path : string ; result ? : Result ; onShowSlides : ( url : string ) => void ; onCreateVote : ( ) => void ; } const AdminSelectedBracketWrapper = ( { children } ) => ( < section > < h1 > Selected bracket < /h1> { children } < /section>); const TopicsSelect = ( { onInput , topics , value } ) => { const sortedTopics = Object . entries ( topics ) . sort ( ( a , b ) => a [ 1 ] . label > b [ 1 ] . label ? 1 : - 1 ) ; return ( < Select onInput = { onInput } value = { value } > < option value = "" > < /option> { sortedTopics . map ( ( [ id , topic ] ) => ( < option value = { id } > { topic . label } < /option>))} < /Select>); } ; export default class AdminSelectedBracket extends Component < Props > { private _onTopicSelect = ( event ) => { const el = event . currentTarget as HTMLSelectElement ; const container = el . closest ( '.admin-form-item' ) as HTMLElement ; fetchJSON ( '/admin/patch' , { method : 'PATCH' , body : [ { op : 'replace' , path : `/results${ this . props . path }/items/${ Number ( container . dataset . itemIndex ) }` , value : el . value , } , ] , } ) ; } ; private _onChampionSelect = ( event ) => { const el = event . currentTarget as HTMLSelectElement ; const container = el . closest ( '.admin-form-item' ) as HTMLElement ; const topicId = this . props . result ! . items [ Number ( container . dataset . itemIndex ) ] ; fetchJSON ( '/admin/patch' , { method : 'PATCH' , body : [ { op : 'replace' , path : `/topics/${ escapePatchPathComponent ( topicId as string ) }/championId` , value : el . value , } , ] , } ) ; } ; private _setWinner ( index ) { const path = this . props . path === '/' ? '' : this . props . path ; fetchJSON ( '/admin/patch' , { method : 'PATCH' , body : [ { op : 'replace' , path : `/results${ path }/winningIndex` , value : index , } , ] , } ) ; } private _onWinnerSelect = ( event ) => { const el = event . currentTarget as HTMLSelectElement ; const container = el . closest ( '.admin-form-item' ) as HTMLElement ; this . _setWinner ( Number ( container . dataset . itemIndex ) ) ; } ; private _onShowSlides = ( event ) => { const el = event . currentTarget as HTMLSelectElement ; const container = el . closest ( '.admin-form-item' ) as HTMLElement ; const index = Number ( container . dataset . itemIndex ) ; const topic = getResultTopic ( this . props . topics , this . props . result ! . items [ index ] ) ; this . props . onShowSlides ( topic ! . slidesURL ) ; } ; private _onClearWinner = ( ) => { this . _setWinner ( - 1 ) ; } ; private _onCreateVote = ( ) => { this . props . onCreateVote ( ) ; } ; private _onZoomHere = ( ) => { let toHighlight ; if ( this . props . path === '/' ) { toHighlight = [ '0' , '1' ] ; } else { const parentPath = this . props . path . split ( '/items/' ) . slice ( 1 ) . join ( '-' ) ; toHighlight = [ parentPath , parentPath + '-0' , parentPath + '-1' ] ; } fetchJSON ( '/admin/patch' , { method : 'PATCH' , body : [ { op : 'replace' , path : `/bracketZoom` , value : toHighlight , } , ] , } ) ; } ; render ( { result , topics , champions } ) { if ( ! result ) { return ( < AdminSelectedBracketWrapper > < p > No bracket item selected < /p> < /AdminSelectedBracketWrapper>); } return ( < AdminSelectedBracketWrapper > < div class = "admin-form-items" > { result . items . map ( ( item , i ) => { const isLeaf = typeof item === 'string' ; const topic = getResultTopic ( topics , item ) ; const topicAndChamp = isLeaf ? [ < div > < label > < span class = "label" > Topic < /span> < TopicsSelect value = { item as string } topics = { topics } onInput = { this . _onTopicSelect } / > < /label> < /div>, < div > < label > < span class = "label" > Champion < /span> < Select disabled = { ! topic } value = { topic ? topic . championId : '' } onInput = { this . _onChampionSelect } > < option value = "" > { topic ? 'None' : '' } < /option> { Object . entries ( champions ) . map ( ( [ id , champion ] ) => ( < option value = { id } > { champion . name } < /option>))} < /Select> < /label> < /div>, ] : [ < div > < span class = "label" > Topic < /span>{' '} < span class = "prefilled-input" > { getResultLabel ( topics , item ) || 'Pending' } < /span> < /div>, < div > < span class = "label" > Champion < /span>{' '} < span class = "prefilled-input" > { getResultChampionName ( topics , item , champions ) || 'Pending' } < /span> < /div>, ] ; return ( < div class = "admin-form-item" data - item - index = { i } > { topicAndChamp } < div > < button class = "button" disabled = { result . winningIndex === i } onClick = { this . _onWinnerSelect } > Set as winner < /button>{' '} { topic && topic . slidesURL && ( < button class = "button" onClick = { this . _onShowSlides } > Show slides < /button>)} < /div> < /div>); } ) } < div class = "admin-form-extras" > < div class = "label" > Actions < /div> < div > < button class = "button" disabled = { result . winningIndex === - 1 } onClick = { this . _onClearWinner } > Clear winner < /button>{' '} < button class = "button" onClick = { this . _onCreateVote } > Create vote < /button>{' '} < button class = "button" onClick = { this . _onZoomHere } > Zoom here < /button> < /div> < /div> < /div> < /AdminSelectedBracketWrapper>); } }