From 29dc43788705acdf9f2140c4700723933bc8f05f Mon Sep 17 00:00:00 2001 From: Jorge Pinna Puissant Date: Thu, 19 Sep 2024 09:35:20 +0200 Subject: [PATCH] [IMP] playground: add a new sample --- docs/playground/playground.js | 5 + .../samples/tic_tac_toe/tic_tac_toe.css | 32 ++++++ .../samples/tic_tac_toe/tic_tac_toe.js | 105 ++++++++++++++++++ .../samples/tic_tac_toe/tic_tac_toe.xml | 43 +++++++ 4 files changed, 185 insertions(+) create mode 100644 docs/playground/samples/tic_tac_toe/tic_tac_toe.css create mode 100644 docs/playground/samples/tic_tac_toe/tic_tac_toe.js create mode 100644 docs/playground/samples/tic_tac_toe/tic_tac_toe.xml diff --git a/docs/playground/playground.js b/docs/playground/playground.js index 7230bf541..f775cced4 100644 --- a/docs/playground/playground.js +++ b/docs/playground/playground.js @@ -99,6 +99,11 @@ const SAMPLES = [ folder: "todo_app", code: ["js", "xml", "css"], }, + { + description: "Tic-Tac-Toe (with reactivity)", + folder: "tic_tac_toe", + code: ["js", "xml", "css"], + }, { description: "Responsive app", folder: "responsive_app", diff --git a/docs/playground/samples/tic_tac_toe/tic_tac_toe.css b/docs/playground/samples/tic_tac_toe/tic_tac_toe.css new file mode 100644 index 000000000..86dda114b --- /dev/null +++ b/docs/playground/samples/tic_tac_toe/tic_tac_toe.css @@ -0,0 +1,32 @@ +.square { + background: #fff; + border: 1px solid #999; + float: left; + font-size: 24px; + font-weight: bold; + line-height: 34px; + height: 34px; + margin-right: -1px; + margin-top: -1px; + padding: 0; + text-align: center; + width: 34px; +} + +.board-row:after { + clear: both; + content: ''; + display: table; +} + +.status { + margin-bottom: 10px; +} +.game { + display: flex; + flex-direction: row; +} + +.game-info { + margin-left: 20px; +} diff --git a/docs/playground/samples/tic_tac_toe/tic_tac_toe.js b/docs/playground/samples/tic_tac_toe/tic_tac_toe.js new file mode 100644 index 000000000..f90eed0cd --- /dev/null +++ b/docs/playground/samples/tic_tac_toe/tic_tac_toe.js @@ -0,0 +1,105 @@ +// This example is an implementation of the Tic-Tac-Toe game, from +// https://react.dev/learn/tutorial-tic-tac-toe. This is an easy application to start learning owl +// with some interesting user interactions. +// +// In this implementation, we use the owl reactivity mechanism. +import { Component, useState, mount } from "@odoo/owl"; + + +class Square extends Component { + static template = "Square"; +} + +class Board extends Component { + static template = "Board" + static components = { Square }; + + handleClick(i) { + if (this.calculateWinner(this.props.squares) || this.props.squares[i]) { + return; + } + const nextSquares = this.props.squares.slice(); + if (this.props.xIsNext) { + nextSquares[i] = 'X'; + } else { + nextSquares[i] = 'O'; + } + this.props.onPlay(nextSquares); + } + + get status(){ + const winner = this.calculateWinner(this.props.squares); + if (winner) { + return 'Winner: ' + winner; + } else { + if (Object.values(this.props.squares).filter((v) => v === null).length > 0) + return 'Next player: ' + (this.props.xIsNext ? 'X' : 'O'); + else + return 'Draw'; + } + } + + calculateWinner(squares) { + const lines = [ + [0, 1, 2], + [3, 4, 5], + [6, 7, 8], + [0, 3, 6], + [1, 4, 7], + [2, 5, 8], + [0, 4, 8], + [2, 4, 6], + ]; + for (let i = 0; i < lines.length; i++) { + const [a, b, c] = lines[i]; + if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) { + return squares[a]; + } + } + return null; + } +} + +class Game extends Component { + static template = "Game" + static components = { Board }; + + setup() { + this.state = useState({ + currentMove: 0, + history: [Array(9).fill(null)], + }); + } + + get currentSquares() { + return this.state.history[this.state.currentMove]; + } + + get xIsNext() { + return this.state.currentMove % 2 === 0; + } + + jumpTo(nextMove) { + this.state.currentMove = nextMove; + } + + handlePlay(nextSquares) { + const nextHistory = [...this.state.history.slice(0, this.state.currentMove + 1), nextSquares]; + this.state.history = nextHistory; + this.state.currentMove = this.state.history.length - 1; + } + + get moves() { + return this.state.history.map((_squares, move) => { + if (move > 0) { + return {id: move, description: 'Go to move #' + move}; + } else { + return {id: move, description: 'Go to game start'}; + } + }); + } + +} + +// Application setup +mount(Game, document.body, { templates: TEMPLATES, dev: true}); diff --git a/docs/playground/samples/tic_tac_toe/tic_tac_toe.xml b/docs/playground/samples/tic_tac_toe/tic_tac_toe.xml new file mode 100644 index 000000000..8228cd3a3 --- /dev/null +++ b/docs/playground/samples/tic_tac_toe/tic_tac_toe.xml @@ -0,0 +1,43 @@ + + + + +
+ +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ +
+
+ +
+
+
    + +
  1. + +
  2. +
    +
+
+
+