-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Master js training revamp ged solutions dafl #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
fdardenne
wants to merge
69
commits into
master-js-training-revamp-ged-solutions
from
master-js-training-revamp-ged-solutions-dafl
Closed
Changes from all commits
Commits
Show all changes
69 commits
Select commit
Hold shift + click to select a range
18b94f4
[ADD] Discover the JavaScript framework
ged-odoo 5b999b0
[SOLUTION] 1.1 Displaying a counter
ged-odoo 483b01b
[SOLUTION] 1.2 Extract counter in a sub component
ged-odoo d55533a
[Solution] 1.3 A simple Card component
ged-odoo 4481e46
[Solution] 1.4 Using markup to display html
ged-odoo b03addb
[Solution] 1.5 Props validation
ged-odoo 180bbc2
[Solution] 1.6 The sum of two Counter
ged-odoo 5772656
[Solution] 1.7 A todo list
ged-odoo 2e9c9d7
[Solution] 1.8 Use dynamic attribute
ged-odoo 558c4f1
[Solution] 1.9 Adding a todo
ged-odoo 313518d
[Solution] 1.10 Focusing the input
ged-odoo 1297916
[Solution] 1.11 Toggling todos
ged-odoo 69f8d86
[Solution] 1.12 Deleting todos
ged-odoo 2017aff
[Solution] 1.13 Generic card with slots
ged-odoo 3d3e7c8
[Solution] 1.14 Minimizing card content
ged-odoo ae5b825
[Solution] 2.1 A new Layout
ged-odoo 92bd224
[Solution] 2.2 Add some buttons for quick navigation
ged-odoo 68212f6
[Solution] 2.3 Add a DashboardItem
ged-odoo de2ca57
[Solution] 2.4 Call the server, add some statistics
ged-odoo f4ffaac
[Solution] 2.5 Cache network calls, create a service
ged-odoo 7dc93c6
[Solution] 2.6 Display a pie chart
ged-odoo c8416e2
[Solution] 2.7 Real life update
ged-odoo b9c09ae
[Solution] 2.8 Lazy loading the dashboard
fdardenne f11304a
[Solution] 2.9 Making our dashboard generic
fdardenne 7540452
[Solution] 2.10 Making our dashboard extensible
fdardenne d7d44a1
[Solution] 2.11 Add and remove dashboard items
fdardenne e421221
[Solution] 3.1 Create a systray item
fdardenne 2fc331e
[Solution] 3.2 Count external clicks
fdardenne d8c6ce8
[Solution] 3.3 Create a client action
fdardenne 9325593
[Solution] 3.4 Move the state to a service
fdardenne 8d17775
[Solution] 3.5 Use a custom hook
fdardenne 8946523
[Solution] 3.6 Humanize the displayed value
fdardenne ab573c9
[Solution] 3.7 Add a tooltip in ClickValue component
fdardenne b54d8a5
[Solution] 3.8 Buy ClickBots
fdardenne 7ab2433
[Solution] 3.9 Refactor to a class model
fdardenne 95aa12e
[Solution] 3.10 Notify when a milestone is reached
fdardenne 5319268
Solution] 3.11 Add BigBots
fdardenne cf18b0a
[Solution] 3.12 Add a new type of resource: power
fdardenne 496878b
[Solution] 3.13 Define some random rewards
fdardenne d78c12b
[Solution] 3.14 Provide a reward when opening a form view
fdardenne fbaf0da
[Solution] 3.15 Add commands in command palette
fdardenne 3b0ecff
[Solution] 3.16 Add yet another resource: trees
fdardenne 4249878
[Solution] 3.17 Use a dropdown menu for the systray item
fdardenne f4a5071
[Solution] 3.18 Use a Notebook component
fdardenne cea4fde
[Solution] 3.19 Persist the game state
fdardenne b7d16ea
[Solution] 3.20 Introduce state migration system
fdardenne b5fb6dd
[Solution] 3.21 Add another type of trees
fdardenne 3cca348
[Solution] 4.1 Make a hello world view
fdardenne b1d6f57
[Solution] 4.2 Use the Layout component
fdardenne 9dcdbce
[Solution] 4.3 Parse the arch
fdardenne a58611d
[Solution] 4.4 Load some data
fdardenne 67caf39
[Solution] 4.5 Solve the concurrency problem
fdardenne 77f9ad0
[Solution] 4.6 Reorganize code
fdardenne 3016eee
[Solution] 4.7 Make the view extensible
fdardenne efe62c0
[Solution] 4.8 Display images
fdardenne ac465ad
[Solution] 4.9 Switch to form view on click
fdardenne d3e9035
[Solution] 4.10 Add an optional tooltip
fdardenne d85d203
[Solution] 4.11 Add pagination
fdardenne 90d7ad8
[Solution] 4.12 Validating views
fdardenne d5d4d74
[Solution] 4.13 Upload button on images
fdardenne dba2e62
[Solution] 4.14 Advanced tooltip template
fdardenne 651d92a
[Solution] 5.1: Create a new kanban view
fdardenne a2e866e
[Solution] 5.2: Create a CustomerList component
fdardenne 76f4b4b
[Solution] 5.3: Load and display data
fdardenne 9085cf3
[Solution] 5.4: Update the main kanban view
fdardenne 3c61c54
[Solution] 5.5: Only display customers which have an active order
fdardenne 0b949e5
[Solution] 5.6. Add a search bar to the customer list
fdardenne f2f8d99
[Solution] 5.7: Refactor the code to use t-model
fdardenne 5e9d4bd
[Solution] 5.8: Paginate customers!
fdardenne File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| # -*- coding: utf-8 -*- |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # -*- coding: utf-8 -*- | ||
| { | ||
| 'name': "Awesome Clicker", | ||
|
|
||
| 'summary': """ | ||
| Starting module for "Master the Odoo web framework, chapter 1: Build a Clicker game" | ||
| """, | ||
|
|
||
| 'description': """ | ||
| Starting module for "Master the Odoo web framework, chapter 1: Build a Clicker game" | ||
| """, | ||
|
|
||
| 'author': "Odoo", | ||
| 'website': "https://www.odoo.com/", | ||
| 'category': 'Tutorials/AwesomeClicker', | ||
| 'version': '0.1', | ||
| 'application': True, | ||
| 'installable': True, | ||
| 'depends': ['base', 'web'], | ||
|
|
||
| 'data': [], | ||
| 'assets': { | ||
| 'web.assets_backend': [ | ||
| 'awesome_clicker/static/src/**/*', | ||
| ], | ||
|
|
||
| }, | ||
| 'license': 'AGPL-3' | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| /** @odoo-module */ | ||
|
|
||
| export const rewards = [ | ||
| { | ||
| description: "Get 1 click bot", | ||
| apply(clicker) { | ||
| clicker.increment(1); | ||
| }, | ||
| maxLevel: 3, | ||
| }, | ||
| { | ||
| description: "Get 10 click bot", | ||
| apply(clicker) { | ||
| clicker.increment(10); | ||
| }, | ||
| minLevel: 3, | ||
| maxLevel: 4, | ||
| }, | ||
| { | ||
| description: "Increase bot power!", | ||
| apply(clicker) { | ||
| clicker.multipler += 1; | ||
| }, | ||
| minLevel: 3, | ||
| }, | ||
| ]; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| /** @odoo-module */ | ||
|
|
||
| import { useService } from "@web/core/utils/hooks"; | ||
| import { useState } from "@odoo/owl"; | ||
|
|
||
| export function useClicker() { | ||
| return useState(useService("awesome_clicker.clicker")); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| /** @odoo-module */ | ||
|
|
||
| export const CURRENT_VERSION = 2.0; | ||
| export const migrations = [ | ||
| { | ||
| fromVersion: 1.0, | ||
| toVersion: 2.0, | ||
| apply: (state) => { | ||
| state.trees.peachTree = { | ||
| price: 1500000, | ||
| level: 4, | ||
| produce: "peach", | ||
| purchased: 0, | ||
| }; | ||
| state.fruits.peach = 0; | ||
| }, | ||
| }, | ||
| ]; | ||
|
|
||
| export function migrate(localState) { | ||
| if (localState?.version < CURRENT_VERSION) { | ||
| for (const migration of migrations) { | ||
| if (localState.version === migration.fromVersion) { | ||
| migration.apply(localState); | ||
| localState.version = migration.toVersion | ||
| } | ||
| } | ||
| localState.version = CURRENT_VERSION; | ||
| } | ||
| return localState; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,149 @@ | ||
| /** @odoo-module */ | ||
|
|
||
| import { Reactive } from "@web/core/utils/reactive"; | ||
| import { EventBus } from "@odoo/owl"; | ||
| import { rewards } from "./click_rewards"; | ||
| import { choose } from "./utils"; | ||
| import { CURRENT_VERSION } from "./clicker_migration"; | ||
|
|
||
| export class ClickerModel extends Reactive { | ||
| constructor() { | ||
| super(); | ||
| this.version = CURRENT_VERSION; | ||
| this.clicks = 0; | ||
| this.level = 0; | ||
| this.bus = new EventBus(); | ||
| this.bots = { | ||
| clickbot: { | ||
| price: 1000, | ||
| level: 1, | ||
| increment: 10, | ||
| purchased: 0, | ||
| }, | ||
| bigbot: { | ||
| price: 5000, | ||
| level: 2, | ||
| increment: 100, | ||
| purchased: 0, | ||
| } | ||
| } | ||
| this.trees = { | ||
| pearTree: { | ||
| price: 1000000, | ||
| level: 4, | ||
| produce: "pear", | ||
| purchased: 0, | ||
| }, | ||
| cherryTree: { | ||
| price: 1000000, | ||
| level: 4, | ||
| produce: "cherry", | ||
| purchased: 0, | ||
| }, | ||
| peachTree: { | ||
| price: 1500000, | ||
| level: 4, | ||
| produce: "peach", | ||
| purchased: 0, | ||
| }, | ||
| } | ||
| this.fruits = { | ||
| pear: 0, | ||
| cherry: 0, | ||
| peach: 0, | ||
| }, | ||
| this.multiplier = 1 | ||
|
|
||
|
|
||
| document.addEventListener("click", () => this.increment(1), true); | ||
| setInterval(() => { | ||
| for (const bot in this.bots) { | ||
| this.clicks += this.bots[bot].increment * this.bots[bot].purchased * this.multiplier; | ||
| } | ||
| }, 10000); | ||
|
|
||
| setInterval(() => { | ||
| for (const tree in this.trees) { | ||
| this.fruits[this.trees[tree].produce] += this.trees[tree].purchased; | ||
| } | ||
| }, 30000); | ||
| } | ||
|
|
||
| buyMultiplier() { | ||
| if (this.clicks < 50000) { | ||
| return false; | ||
| } | ||
| this.clicks -= 50000; | ||
| this.multiplier++; | ||
| } | ||
|
|
||
| increment(inc) { | ||
| this.clicks += inc; | ||
| if ( | ||
| this.milestones[this.level] && | ||
| this.clicks >= this.milestones[this.level].clicks | ||
| ) { | ||
| this.bus.trigger("MILESTONE", this.milestones[this.level]); | ||
| this.level += 1; | ||
| } | ||
| } | ||
|
|
||
| buyBot(name) { | ||
| if (!Object.keys(this.bots).includes(name)) { | ||
| throw new Error(`Invalid bot name ${name}`); | ||
| } | ||
| if (this.clicks < this.bots[name].price) { | ||
| return false; | ||
| } | ||
|
|
||
| this.clicks -= this.bots[name].price; | ||
| this.bots[name].purchased += 1; | ||
| } | ||
|
|
||
| giveReward() { | ||
| const availableReward = []; | ||
| for (const reward of rewards) { | ||
| if (reward.minLevel <= this.level || !reward.minLevel) { | ||
| if (reward.maxLevel >= this.level || !reward.maxLevel) { | ||
| availableReward.push(reward); | ||
| } | ||
| } | ||
| } | ||
| const reward = choose(availableReward); | ||
| this.bus.trigger("REWARD", reward); | ||
| return choose(availableReward); | ||
| } | ||
|
|
||
| buyTree(name) { | ||
| if (!Object.keys(this.trees).includes(name)) { | ||
| throw new Error(`Invalid tree name ${name}`); | ||
| } | ||
| if (this.clicks < this.trees[name].price) { | ||
|
fdardenne marked this conversation as resolved.
|
||
| return false; | ||
| } | ||
| this.clicks -= this.trees[name].price; | ||
| this.trees[name].purchased += 1; | ||
| } | ||
|
|
||
| toJSON() { | ||
| const json = Object.assign({}, this); | ||
| delete json["bus"]; | ||
| return json; | ||
|
|
||
| } | ||
|
|
||
| static fromJSON(json) { | ||
| const clicker = new ClickerModel(); | ||
| const clickerInstance = Object.assign(clicker, json); | ||
| return clickerInstance; | ||
| } | ||
|
|
||
| get milestones() { | ||
| return [ | ||
| { clicks: 1000, unlock: "clickBot" }, | ||
| { clicks: 5000, unlock: "bigBot" }, | ||
| { clicks: 100000, unlock: "power multiplier" }, | ||
| { clicks: 1000000, unlock: "pear tree & cherry tree" }, | ||
| ]; | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| /** @odoo-module **/ | ||
|
|
||
| import { registry } from "@web/core/registry"; | ||
|
|
||
| const commandProviderRegistry = registry.category("command_provider"); | ||
|
|
||
| commandProviderRegistry.add("clicker", { | ||
| provide: (env, options) => { | ||
| return [ | ||
| { | ||
| name: "Buy 1 click bot", | ||
| action() { | ||
| env.services["awesome_clicker.clicker_service"].buyBot("clickbot"); | ||
| }, | ||
| }, | ||
| { | ||
| name: "Open Clicker Game", | ||
| action() { | ||
| env.services.action.doAction({ | ||
| type: "ir.actions.client", | ||
| tag: "awesome_clicker.client_action", | ||
| target: "new", | ||
| name: "Clicker Game", | ||
| }); | ||
| }, | ||
| } | ||
| ] | ||
| }, | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| /** @odoo-module */ | ||
|
|
||
| import { registry } from "@web/core/registry"; | ||
| import { ClickerModel } from "./clicker_model"; | ||
| import { browser } from "@web/core/browser/browser"; | ||
| import { migrate } from "./clicker_migration"; | ||
|
|
||
| const clickerService = { | ||
| dependencies: ["action", "effect", "notification"], | ||
| start(env, services) { | ||
| const localState = migrate(JSON.parse(browser.localStorage.getItem("clickerState"))); | ||
| const clickerModel = localState ? ClickerModel.fromJSON(localState): new ClickerModel(); | ||
|
|
||
|
fdardenne marked this conversation as resolved.
|
||
| setInterval(() => { | ||
| browser.localStorage.setItem("clickerState", JSON.stringify(clickerModel)) | ||
| }, 10000); | ||
|
|
||
| const bus = clickerModel.bus | ||
| bus.addEventListener("MILESTONE", (ev) => { | ||
| services.effect.add({ | ||
| message: `Milestone reached! You can now buy ${ev.detail.unlock}`, | ||
| type: "rainbow_man", | ||
| }); | ||
| }); | ||
|
|
||
| bus.addEventListener("REWARD", (ev) => { | ||
| const reward = ev.detail; | ||
| const closeNotification = services.notification.add( | ||
| `Congrats you won a reward: "${reward.description}"`, | ||
| { | ||
| type: "success", | ||
| sticky: true, | ||
| buttons: [ | ||
| { | ||
| name: "Collect", | ||
| onClick: () => { | ||
| reward.apply(clickerModel); | ||
| closeNotification(); | ||
| services.action.doAction({ | ||
| type: "ir.actions.client", | ||
| tag: "awesome_clicker.client_action", | ||
| target: "new", | ||
| name: "Clicker Game" | ||
| }); | ||
| }, | ||
| }, | ||
| ], | ||
| } | ||
| ); | ||
| }) | ||
| return clickerModel; | ||
| }, | ||
| }; | ||
|
|
||
| registry.category("services").add("awesome_clicker.clicker", clickerService); | ||
50 changes: 50 additions & 0 deletions
50
awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| /** @odoo-module */ | ||
|
|
||
| import { Component } from "@odoo/owl"; | ||
| import { registry } from "@web/core/registry"; | ||
| import { useService } from "@web/core/utils/hooks"; | ||
| import { useClicker } from "../clicker_hook"; | ||
| import { ClickerValue } from "../clicker_value/clicker_value"; | ||
| import { Dropdown } from "@web/core/dropdown/dropdown"; | ||
| import { DropdownItem } from "@web/core/dropdown/dropdown_item"; | ||
|
|
||
| export class ClickerSystray extends Component { | ||
| static template = "awesome_clicker.ClickerSystray"; | ||
| static components = { ClickerValue, Dropdown, DropdownItem }; | ||
|
|
||
| setup() { | ||
| this.action = useService("action"); | ||
| this.clicker = useClicker(); | ||
| } | ||
|
|
||
| openClientAction() { | ||
| this.action.doAction({ | ||
| type: "ir.actions.client", | ||
| tag: "awesome_clicker.client_action", | ||
| target: "new", | ||
| name: "Clicker Game" | ||
| }); | ||
| } | ||
|
|
||
| get numberTrees() { | ||
| let sum = 0; | ||
| for (const tree in this.clicker.trees) { | ||
| sum += this.clicker.trees[tree].purchased; | ||
| } | ||
| return sum; | ||
| } | ||
|
|
||
| get numberFruits() { | ||
| let sum = 0; | ||
| for (const fruit in this.clicker.fruits) { | ||
| sum += this.clicker.fruits[fruit]; | ||
| } | ||
| return sum; | ||
| } | ||
| } | ||
|
|
||
| export const systrayItem = { | ||
| Component: ClickerSystray, | ||
| }; | ||
|
|
||
| registry.category("systray").add("awesome_clicker.ClickerSystray", systrayItem, { sequence: 1000 }); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.