Skip to content

Commit

Permalink
Merge pull request #199 from mwiraszka/v4.0.6
Browse files Browse the repository at this point in the history
v4.0.6
  • Loading branch information
mwiraszka authored Aug 4, 2024
2 parents 0214a51 + 34d04e9 commit de63ad2
Show file tree
Hide file tree
Showing 17 changed files with 646 additions and 179 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ Welcome to the source code repository for the new LCC website! Here you'll find
| 🐛 | Bug fixes |
| 🔧 | Behind-the-scenes changes |

<details>
<summary style="cursor: pointer">
v4.0.6 - August 4th, 2024
</summary>

- 🚀 Display scores next to players' names in the PGN viewer component
- 🚀 Add the ability to filter games in the Game Archives page by first/last name, whether the player was White or Black, and the number of moves

</details>

<details>
<summary style="cursor: pointer">
v4.0.5 - July 5th, 2024
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lcc-angular",
"version": "4.0.5",
"version": "4.0.6",
"description": "Frontend for the London Chess Club website, built with Angular",
"author": "Michal Wiraszka (https://wiraszka.com)",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion src/app/components/pgn-viewer/pgn-viewer.component.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<div [id]="'pgn-viewer-' + index"></div>
<div [id]="viewerId"></div>
Empty file.
81 changes: 71 additions & 10 deletions src/app/components/pgn-viewer/pgn-viewer.component.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,87 @@
import LichessPgnViewer from 'lichess-pgn-viewer';

import { DOCUMENT } from '@angular/common';
import { AfterViewInit, Component, Inject, Input } from '@angular/core';
import { AfterViewInit, Component, Inject, Input, OnInit } from '@angular/core';

import { getPlayerName, getScore } from '@app/utils/pgn-utils';

@Component({
selector: 'lcc-pgn-viewer',
templateUrl: './pgn-viewer.component.html',
styleUrls: ['./pgn-viewer.component.scss'],
})
export class PgnViewerComponent implements AfterViewInit {
@Input() pgn?: string;
@Input() index!: number;
export class PgnViewerComponent implements OnInit, AfterViewInit {
viewerId!: string;

container: HTMLElement | null = null;
@Input() index!: number;
@Input() label!: string;
@Input() pgn!: string;

constructor(@Inject(DOCUMENT) private _document: Document) {}

ngOnInit(): void {
this.viewerId = `pgn-viewer--${this.label}--${this.index}`;
}

ngAfterViewInit(): void {
this.container = this._document.getElementById(`pgn-viewer-${this.index}`);
if (this.container) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const _ = LichessPgnViewer(this.container, { pgn: this.pgn });
const container = this._document.getElementById(this.viewerId);

if (container) {
const _ = LichessPgnViewer(container, {
classes: this.viewerId, // Required for query selectors below
initialPly: 'last',
orientation: 'white',
pgn: this.pgn,
showClocks: false,
});

const whiteName = getPlayerName(this.pgn, 'White');
if (!whiteName) {
console.error(
'[LCC] A game with no defined White player was found: \n',
this.pgn,
);
return;
}

const blackName = getPlayerName(this.pgn, 'Black');
if (!blackName) {
console.error(
'[LCC] A game with no defined Black player was found: \n',
this.pgn,
);
return;
}

const whiteScore = getScore(this.pgn, 'White');
if (!whiteScore) {
console.error(
'[LCC] A game with no valid score for White was found: \n',
this.pgn,
);
return;
}

const blackScore = getScore(this.pgn, 'Black');
if (!blackScore) {
console.error(
'[LCC] A game with no valid score for Black was found: \n',
this.pgn,
);
return;
}

const whitePlayerElement = this._document.querySelector(
`.${this.viewerId} .lpv__player--bottom > .lpv__player__person`,
);
const blackPlayerElement = this._document.querySelector(
`.${this.viewerId} .lpv__player--top > .lpv__player__person`,
);

whitePlayerElement?.setAttribute('data-name', whiteName);
whitePlayerElement?.setAttribute('data-score', whiteScore);

blackPlayerElement?.setAttribute('data-name', blackName);
blackPlayerElement?.setAttribute('data-score', blackScore);
}
}
}
185 changes: 143 additions & 42 deletions src/app/screens/game-archives/game-archives-screen.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ <h3>A little piece of history...</h3>
<p>
Here you will find a collection of games played by London Chess Club members from
a variety of events dating as far back as 1974. All game PGNs meticulously
transcribed and compiled over the years by our very own Gerry Litchfield &mdash;
thank you, Gerry!
transcribed and compiled over the years by Gerry Litchfield.
</p>
<p>
Want to submit a game or make a correction? Email us at
Expand All @@ -28,49 +27,151 @@ <h3>A little piece of history...</h3>
</div>
</section>

<div class="game-filter-container">
<span class="filter-games-text">Filter games:</span>
<form
class="lcc-form game-filter-form"
[formGroup]="form">
<section class="lcc-form-fields filter-section player-filter-section">
<label for="name-input">Player name</label>
<input
id="name-input"
type="text"
name="name"
formControlName="name"
maxlength="50" />

<label for="as-white-input">as White</label>
<input
id="as-white-input"
type="checkbox"
name="as-white"
formControlName="asWhite" />

<label for="as-black-input">as Black</label>
<input
id="as-black-input"
type="checkbox"
name="as-black"
formControlName="asBlack" />
</section>

<section class="lcc-form-fields filter-section moves-filter-section">
<label for="name-input">Moves (min)</label>
<input
id="moves-min-input"
type="text"
name="moves-min"
formControlName="movesMin"
maxlength="3" />
<div class="lcc-form-error-container">
@if (hasError(form.controls['movesMin'])) {
<i-feather
name="alert-triangle"
class="lcc-form-error-icon validation-alert-icon"
[tooltip]="getErrorMessage()">
</i-feather>
}
</div>

<label for="name-input">Moves (max)</label>
<input
id="moves-max-input"
type="text"
name="moves-max"
formControlName="movesMax"
maxlength="3" />
<div class="lcc-form-error-container">
@if (hasError(form.controls['movesMax'])) {
<i-feather
name="alert-triangle"
class="lcc-form-error-icon validation-alert-icon"
[tooltip]="getErrorMessage()">
</i-feather>
}
</div>
</section>

<section class="lcc-form-fields filter-section result-filter-section">
<label for="result-white-won-input">White won</label>
<input
id="result-white-won-input"
type="checkbox"
name="result-white-won"
formControlName="resultWhiteWon" />

<label for="result-draw-input">Draw</label>
<input
id="result-draw-input"
type="checkbox"
name="result-draw"
formControlName="resultDraw" />

<label for="result-black-won-input">Black won</label>
<input
id="result-black-won-input"
type="checkbox"
name="result-black-won-input"
formControlName="resultBlackWon" />

<label for="result-inconclusive-input">Inconclusive</label>
<input
id="result-inconclusive-input"
type="checkbox"
name="result-inconclusive-input"
formControlName="resultInconclusive" />
</section>
</form>

<span class="result-summary-text">{{ searchResultSummaryMessage }}</span>
</div>

<div class="panels-container">
@for (panel of expansionPanels; track panel.label) {
<div class="panel-content">
<lcc-expansion-panel
[headerTemplate]="headerTemplateRef"
[contentTemplate]="contentTemplateRef"
[isOpen]="panel.label === '2023'">
</lcc-expansion-panel>
@for (group of filteredGames | keyvalue: originalOrder; track group.key) {
@if (group.value.length) {
<div class="panel-content">
<lcc-expansion-panel
[headerTemplate]="headerTemplateRef"
[contentTemplate]="contentTemplateRef"
[isOpen]="group.key === '2023'">
</lcc-expansion-panel>

<ng-template #headerTemplateRef>
<div class="header-content">
<span>{{ panel.label }}</span>
<span>
{{ panel.pgns.length }}
{{ panel.pgns.length > 1 ? 'games' : 'game' }}
</span>
</div>
</ng-template>
<ng-template #headerTemplateRef>
<div class="header-content">
<span>{{ group.key }}</span>
<span>
{{ group.value.length }}
{{ group.value.length > 1 ? 'games' : 'game' }}
</span>
</div>
</ng-template>

<ng-template #contentTemplateRef>
<div class="games-container">
@defer {
<cdk-virtual-scroll-viewport
[itemSize]="436"
[minBufferPx]="1000"
[maxBufferPx]="2000"
orientation="horizontal">
<lcc-pgn-viewer
*cdkVirtualFor="
let pgn of panel.pgns;
let index = index;
templateCacheSize: 0
"
[index]="index"
[pgn]="pgn">
</lcc-pgn-viewer>
</cdk-virtual-scroll-viewport>
} @placeholder {
<span class="loading-text">Loading...</span>
}
</div>
</ng-template>
</div>
<ng-template #contentTemplateRef>
<div class="games-container">
@defer {
<cdk-virtual-scroll-viewport
[itemSize]="436"
[minBufferPx]="1000"
[maxBufferPx]="2000"
orientation="horizontal">
<lcc-pgn-viewer
*cdkVirtualFor="
let gameDetails of group.value;
let index = index;
templateCacheSize: 0
"
[index]="index"
[label]="group.key"
[pgn]="gameDetails.pgn">
</lcc-pgn-viewer>
</cdk-virtual-scroll-viewport>
} @placeholder {
<span class="loading-text">Loading...</span>
}
</div>
</ng-template>
</div>
}
}
</div>
</div>
64 changes: 64 additions & 0 deletions src/app/screens/game-archives/game-archives-screen.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,70 @@ $container-max-width: calc($pgn-viewer-width * 3 + 4px * 6);
}
}

.game-filter-container {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
max-width: $container-max-width;
background-color: var(--lcc-color--gameArchivesScreen-filterContainerBackground);
border-radius: var(--lcc-borderRadius--large);
padding: 8px;

.filter-games-text {
align-self: start;
padding: 8px;
color: var(--lcc-color--gameArchivesScreen-headerText);
}

.game-filter-form {
display: grid;
grid-template-columns: auto 1fr;
grid-template-areas:
'player player'
'moves result';
gap: 2px;
align-items: stretch;

@include respond-to('gt-xs') {
gap: 8px;
}

@include respond-to('gt-md') {
grid-template-columns: 4fr 1fr 1fr;
grid-template-areas: 'player moves result';
}

.filter-section {
border: 1px solid var(--lcc-color--gameArchivesScreen-filterSectionBorder);
border-radius: var(--lcc-borderRadius--large);
padding: 8px;
gap: 4px 8px;

&.player-filter-section {
grid-area: player;
}

&.moves-filter-section {
grid-area: moves;

input {
max-width: 50px;
}
}

&.result-filter-section {
grid-area: result;
}
}
}

.result-summary-text {
padding: 8px;
color: var(--lcc-color--gameArchivesScreen-text);
}
}

.panels-container {
display: flex;
flex-direction: column;
Expand Down
Loading

0 comments on commit de63ad2

Please sign in to comment.