1import {gameEditor} from '/views/gameEditor.js'; 2import {textEditor} from '/views/textEditor.js'; 3import {searchMixin} from '/mixins/searchMixin.js'; 4 5export const pitch = { 6 mixins: [searchMixin], 7 template: ` 8<div class="flexrow"> 9 <div v-if="pitch.gameTimes" class="fixedleft flexrow pitch" style="z-index: 1000"> 10 <div class="card"> 11 <div class="cardheader"></div> 12 <table id="game-times" class="selectable"> 13 <thead> 14 <tr><th>Time</th></tr> 15 </thead> 16 <tbody> 17 <template v-if="maxGameCount() > 0"> 18 <template v-for="(value, index) in maxGameCount()"> 19 <tr v-on:click="selectGame($event)" v-on:mouseover="hoverGame($event)" v-on:mouseout="hoverGame(null)" :style="getTimeCellStyle(index, $root.$data.searchText)"> 20 <td><template v-if="pitch.gameTimes && pitch.gameTimes.length > index">{{ pitch.gameTimes[index] }}</template></td> 21 </tr> 22 </template> 23 </template> 24 </tbody> 25 </table> 26 </div> 27 </div> 28 <div class="pitch card"> 29 <div class="cardheader flexrow flexcenter"> 30 <h3>{{ pitch.name }}</h3> 31 <div v-if="tournament.canEdit" class="dropdown"> 32 <svg v-on:click="localShowDropdown($event, 'pitchDropdown' + pitch.id.value)" class="dropdown-button"><use xlink:href="/html/icons.svg/#menu"></use></svg> 33 <div :id="'pitchDropdown' + pitch.id.value" class="dropdown-content"> 34 <a v-on:click="pasteGames">Paste Games</a> 35 <a v-on:click="editName">Edit Name</a> 36 <a v-on:click="pasteGameTimes">Paste Game Times</a> 37 <a v-on:click="clearGameTimes">Clear Game Times</a> 38 <div class="dropdown-text">Only add game times if different from main times.</div> 39 </div> 40 </div> 41 </div> 42 <div> 43 <table id="games" class="selectable"> 44 <thead> 45 <tr> 46 <th>Group</th> 47 <th>Team 1</th> 48 <th></th> 49 <th>Team 2</th> 50 <th>Duty</th> 51 <td v-if="tournament.canEdit"></td> 52 </tr> 53 </thead> 54 <tbody> 55 <template v-if="maxGameCount() > 0"> 56 <template v-for="(value, index) in maxGameCount()"> 57 <template v-for="game in [pitch.games[index]]"> 58 <tr v-on:click="selectGame($event)" v-on:mouseover="hoverGame($event)" v-on:mouseout="hoverGame(null)" v-on:dblclick="editGame(pitch, game)" :style="getRowStyle(index, $root.$data.searchText)"> 59 <template v-if="game"> 60 <td :style="getCellStyle(game.group, $root.$data.searchText)">{{ game.group }}</td> 61 <td :style="getCellStyle(game.team1, $root.$data.searchText)">{{ game.team1 }}</td> 62 <td class="score-cell" v-on:click="editGame(pitch, game)"> 63 <div class="score-content flexrow flexcenter"> 64 <template v-if="game.status !== 'pending' && game.team1 && game.team2">
65 <div :class="{ scoreactive: game.status === 'active', scorewin: game.status === 'complete' && game.team1Score > game.team2Score, scoredraw: game.status === 'complete' && game.team1Score === game.team2Score, scorelose: game.status === 'complete' && game.team1Score < game.team2Score }">{{ game.team1Score }}</div> 66 <div :class="{ scoreactive: game.status === 'active' }"> - </div> 67 <div :class="{ scoreactive: game.status === 'active', scorewin: game.status === 'complete' && game.team2Score > game.team1Score, scoredraw: game.status === 'complete' && game.team2Score === game.team1Score, scorelose: game.status === 'complete' && game.team2Score < game.team1Score }">{{ game.team2Score }}</div> 68 </template> 69 </div> 70 </td> 71 <td :style="getCellStyle(game.team2, $root.$data.searchText)">{{ game.team2 }}</td> 72 <td :style="getCellStyle(game.dutyTeam, $root.$data.searchText)">{{ game.dutyTeam }}</td> 73 <td v-if="tournament.canEdit"> 74 <svg v-on:click="editGame(pitch, game)" class="edit-button"><use xlink:href="/html/icons.svg/#edit-circle"></use></svg> 75 </td> 76 </template> 77 <template v-else> 78 <td colspan="5"></td> 79 </template> 80 </tr> 81 </template> 82 </template> 83 </template> 84 </tbody> 85 </table> 86 </div> 87 </div> 88</div> 89`, 90 props: ['tournament', 'gameDate', 'pitch', 'searchText'], 91 data () { 92 return { 93 loading: false, 94 } 95 }, 96 created () { 97 98 }, 99 methods: 100 { 101 refresh: function() { 102 this.$parent.refresh(); 103 }, 104 sendData: function(route, data, refresh) { 105 var _this = this 106 if (_this.pitch != undefined) 107 { 108 fetch('/data/tournament/' + _this.tournament.id.value + '/date/' + _this.gameDate.id.value + '/pitch/' + _this.pitch.id.value + '/' + route, { 109 method: 'PUT', 110 body: JSON.stringify(data) 111 }) 112 .then(function(tournament) 113 { 114 if (refresh) 115 { 116 _this.refresh(); 117 } 118 }) 119 .catch(function(error) { 120 console.log(error); 121 alert('Oops. Something went wrong.'); 122 }); 123 } 124 }, 125 pasteGames: function(pitchId) 126 { 127 navigator.clipboard.readText() 128 .then(clipboardText => { 129 var data = { 'mode': 'replace', 'clipboardText': clipboardText }; 130 this.sendData('paste', data, true); 131 }) 132 .catch(error => { 133 alert('Error reading from the clipboard:\n ' + error.message + '\nCheck the site settings from the url bar.'); 134 }); 135 }, 136 pasteGameTimes: function(pitchId) 137 { 138 navigator.clipboard.readText().then(clipboardText => { 139 var data = { 'clipboardText': clipboardText }; 140 this.sendData('pastegametimes', data, true); 141 }) 142 .catch(error => { 143 alert('Error reading from the clipboard:\n ' + error.message + '\nCheck the site settings from the url bar.'); 144 }); 145 }, 146 editName: function(pitchId) 147 { 148 if (this.tournament.canEdit) { 149 var _this = this; 150 const instance = Vue.createApp(textEditor, { text: _this.pitch.name 151 , onSave: function(text) { 152 var data = { 'name': text }; 153 _this.sendData('editname', data, true); 154 }}); 155 instance.config.globalProperties.$googleUser = this.$googleUser; 156 instance.config.compilerOptions.whitespace = 'codense' 157 instance.mount('#modal-parent'); 158 } 159 }, 160 clearGameTimes: function(pitchId) { 161 navigator.clipboard.readText().then(clipboardText => { 162 var data = { }; 163 this.sendData('cleargametimes', data, true); 164 }) 165 .catch(error => { 166 alert('Error reading from the clipboard:\n ' + error.message + '\nCheck the site settings from the url bar.'); 167 }); 168 }, 169 putGame: function(pitch, game) { 170 var data = { "group": game.group, 171 "team1": game.team1, 172 "team1Score": game.team1Score, 173 "team2": game.team2, 174 "team2Score": game.team2Score, 175 "dutyTeam": game.dutyTeam,
176 "status": game.status 177 }; 178 this.sendData('game/' + game.id.value, data, false); 179 }, 180 localShowDropdown: function(event, name) { 181 showDropdown(event, name) 182 }, 183 maxGameCount: function() 184 { 185 var count = 0 186 if (this.gameDate) { 187 if (this.gameDate.gameTimes) { 188 count = this.gameDate.gameTimes.length 189 }; 190 this.gameDate.pitches.forEach(pitch => { 191 if (pitch.games.length > count) count = pitch.games.length; 192 if (pitch.gameTimes && pitch.gameTimes.length > count) count = pitch.gameTimes.length; 193 }); 194 } 195 return count; 196 }, 197 selectGame: function(event) { 198 var index = event.currentTarget.rowIndex; 199 this.gameDate['selectedIndex'] = index - 1; 200 }, 201 hoverGame: function(event) { 202 var index = 0; 203 if (event) index = event.currentTarget.rowIndex; 204 this.gameDate['hoverIndex'] = index - 1; 205 }, 206 rowSearchMatches: function(index, searchText) { 207 let result = 0 208 if (searchText) { 209 for (let pitch of this.gameDate.pitches) { 210 let game = pitch.games[index]; 211 if (game) { 212 result = result | this.searchMatches(game.group, searchText); 213 result = result | this.searchMatches(game.team1, searchText); 214 result = result | this.searchMatches(game.team2, searchText); 215 result = result | this.searchMatches(game.dutyTeam, searchText); 216 } 217 } 218 } 219 return result; 220 }, 221 getRowStyle: function(index, searchText) { 222 if (this.gameDate.hoverIndex == index) { 223 return "background-color: #eeeeff;"; 224 } 225 if (this.gameDate.selectedIndex == index) { 226 return "background-color: #eeeeff;"; 227 } 228 return ""; 229 }, 230 getTimeCellStyle: function(index, searchText) { 231 let result = this.rowSearchMatches(index, searchText); 232 233 let color = "#ffffff"; 234 235 let c1 = "#FDF0CA"; 236 let c2 = "#E4CBD6"; 237 let c3 = "#D4E5CE"; 238 let c4 = "#D4E5F0"; 239 240 if (this.gameDate.hoverIndex == index) 241 { 242 color = "#eeeeff 100%"; 243 } 244 else if (result >= 8) { 245 color = c4; 246 } 247 else if ((result & 1) == 1) { 248 color = c1; 249 } 250 else if ((result & 2) == 2) { 251 color = c2; 252 } 253 else if ((result & 4) == 4) { 254 color = c3; 255 } 256 else if (this.gameDate.selectedIndex == index) 257 { 258 color = "#eeeeff 100%"; 259 } 260 261 return "background-color: " + color + ";"; 262 }, 263 getCellStyle: function(text, searchText) { 264 let result = this.searchMatches(text, searchText); 265 if (result > 0) { 266 if ((result & 1) == 1) { 267 return "background-color: #FDF0CA; font-weight: bold;"; 268 } 269 if ((result & 2) == 2) { 270 return "background-color: #E4CBD6; font-weight: bold;"; 271 } 272 if ((result & 4) == 4) { 273 return "background-color: #D4E5CE; font-weight: bold;"; 274 } 275 if (result >= 8) { 276 return "background-color: #D4E5F0; font-weight: bold;"; 277 } 278 } 279 return ""; 280 }, 281 editGame(pitch, game) { 282 const instance = Vue.createApp(gameEditor, { tournament: this.tournament, gameDate: this.gameDate, pitch: this.pitch, game: game }); 283 instance.config.globalProperties.$googleUser = this.$googleUser; 284 instance.config.compilerOptions.whitespace = 'codense' 285 instance.mount('#modal-parent'); 286 }, 287 saveGame(pitch, game) { 288 this.putGame(pitch, game); 289 }, 290 cancelGame(pitch, game) { 291 this.refresh(); 292 } 293 } 294};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.