Skip to content
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

Develop #260

Merged
merged 28 commits into from
Jan 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9bcf5c5
Add menu resource
karlomikus Jan 19, 2024
072cf59
Add public resource
karlomikus Jan 20, 2024
ec09cc2
Merge pull request #258 from karlomikus/menu
karlomikus Jan 20, 2024
c7dc76f
Update deps
karlomikus Jan 20, 2024
f456254
Merge branch 'develop' of github.com:karlomikus/bar-assistant into de…
karlomikus Jan 20, 2024
293bac8
Show only enabled menus
karlomikus Jan 20, 2024
3f8f256
Cast to boolean
karlomikus Jan 21, 2024
5f905a2
Remove slug saving on bar create/update
karlomikus Jan 21, 2024
c3a68a6
Enable mass assignment for menu models
karlomikus Jan 21, 2024
800c0e4
Update readme
karlomikus Jan 21, 2024
941b785
Update spec
karlomikus Jan 21, 2024
51cb670
Pull sqlite
karlomikus Jan 24, 2024
617a5e9
Build arm image for dev
karlomikus Jan 24, 2024
38d3f3c
Fix sqlite build image
karlomikus Jan 25, 2024
530cfe5
Revert sqlite changes
karlomikus Jan 25, 2024
527a0ae
Improve bar slug generation
karlomikus Jan 26, 2024
f7b19f7
Bump meilisearch
karlomikus Jan 26, 2024
3b3f122
Update deps
karlomikus Jan 26, 2024
081eefd
Save timestamps when importing and exporting recipes
karlomikus Jan 26, 2024
d12af29
Set bar slug only on create
karlomikus Jan 26, 2024
86d4f94
Skip tests on fail
karlomikus Jan 27, 2024
47f0d38
Dont scrape private networks
karlomikus Jan 27, 2024
449ac95
Log scraping errors
karlomikus Jan 27, 2024
bc825f3
Fix missing check on collection import
karlomikus Jan 27, 2024
8314246
Update changelog
karlomikus Jan 27, 2024
a502ff2
Merge branch 'master' into develop
karlomikus Jan 27, 2024
3e45166
Fix callable syntax
karlomikus Jan 27, 2024
09090cb
csfix
karlomikus Jan 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/build-dev-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,26 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
-
name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
-
name: Login to Docker Hub
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ secrets.HUB_BASS_USERNAME }}
password: ${{ secrets.HUB_BASS_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v3
uses: docker/build-push-action@v5
with:
context: .
target: dist
platforms: linux/amd64
platforms: linux/amd64,linux/arm64
push: true
tags: barassistant/server:dev
build-args: BAR_ASSISTANT_VERSION=develop
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/build-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
-
name: Docker meta
id: meta
Expand All @@ -27,10 +27,10 @@ jobs:
type=semver,pattern=v{{major}}
-
name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
-
name: Login to Docker Hub
uses: docker/login-action@v2
Expand All @@ -39,7 +39,7 @@ jobs:
password: ${{ secrets.HUB_BASS_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v3
uses: docker/build-push-action@v5
with:
context: .
target: dist
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# v3.9.0
## New
- Added `slug` column to `bars` table
- Added a simple bar menu
- Added POST and GET `/menu` endpoints
- Added GET `/explore/menus/{barSlug}` public endpoint
- This is a simple menu implementation, more features are coming in future
- When exporting and importing recipe data, timestamps are also imported

# v3.8.0
## New
- Added `favorite_tags` to stats endpoint
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ This repository only contains the API server, if you are looking for easy to use
- Support for cocktail and ingredient notes
- Supports sharing recipes by public links, custom recipe images and printing

## Cloud

Visit [barassistant.app](https://barassistant.app/) for more information about our cloud offering.

![Cloud offering screenshot](/resources/art/art1.png)

## Documentation

[Documentation is available here.](https://bar-assistant.github.io/docs/)
Expand Down
14 changes: 14 additions & 0 deletions app/Http/Controllers/BarController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Kami\Cocktail\Http\Controllers;

use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Kami\Cocktail\Models\Bar;
Expand Down Expand Up @@ -50,6 +51,10 @@ public function store(BarRequest $request): JsonResponse
abort(403, 'You can not create anymore bars');
}

$request->validate([
'slug' => 'nullable|unique:bars,slug',
]);

$inviteEnabled = (bool) $request->post('enable_invites', '1');
$barOptions = $request->post('options', []);

Expand All @@ -59,6 +64,11 @@ public function store(BarRequest $request): JsonResponse
$bar->description = $request->post('description');
$bar->created_user_id = $request->user()->id;
$bar->invite_code = $inviteEnabled ? (string) new Ulid() : null;
if ($request->post('slug')) {
$bar->slug = Str::slug($request->post('slug'));
} else {
$bar->generateSlug();
}
$bar->save();

$request->user()->joinBarAs($bar, UserRoleEnum::Admin);
Expand All @@ -79,6 +89,10 @@ public function update(int $id, BarRequest $request): JsonResource
abort(403);
}

$request->validate([
'slug' => 'nullable|unique:bars,slug,' . $bar->id,
]);

Cache::forget('ba:bar:' . $bar->id);

$inviteEnabled = (bool) $request->post('enable_invites', '1');
Expand Down
64 changes: 64 additions & 0 deletions app/Http/Controllers/MenuController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

declare(strict_types=1);

namespace Kami\Cocktail\Http\Controllers;

use Illuminate\Http\Request;
use Kami\Cocktail\Models\Menu;
use Kami\Cocktail\Http\Requests\MenuRequest;
use Kami\Cocktail\Http\Resources\MenuResource;
use Illuminate\Http\Resources\Json\JsonResource;
use Kami\Cocktail\Http\Resources\MenuPublicResource;

class MenuController extends Controller
{
public function index(Request $request): JsonResource
{
if ($request->user()->cannot('view', Menu::class)) {
abort(403);
}

$bar = bar();
if (!$bar->slug) {
$bar->generateSlug();
$bar->save();
}

$menu = Menu::with('menuCocktails.cocktail.ingredients.ingredient')->firstOrCreate(['bar_id' => $bar->id]);

return new MenuResource($menu);
}

public function show(string $barSlug): MenuPublicResource
{
$menu = Menu::select('menus.*')
->where(['slug' => $barSlug])
->where('menus.is_enabled', true)
->join('bars', 'bars.id', '=', 'menus.bar_id')
->join('menu_cocktails', 'menu_cocktails.menu_id', '=', 'menus.id')
->orderBy('menu_cocktails.sort', 'asc')
->with('menuCocktails.cocktail')
->firstOrFail();

return new MenuPublicResource($menu);
}

public function update(MenuRequest $request): MenuResource
{
if ($request->user()->cannot('update', Menu::class)) {
abort(403);
}

$menu = Menu::firstOrCreate(['bar_id' => bar()->id]);
$menu->is_enabled = (bool) $request->post('is_enabled');
if (!$menu->created_at) {
$menu->created_at = now();
}
$menu->updated_at = now();
$menu->syncCocktails($request->post('cocktails', []));
$menu->save();

return new MenuResource($menu);
}
}
4 changes: 2 additions & 2 deletions app/Http/Filters/FilterNameSearch.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ public function __invoke(Builder $query, $value, string $property)
return $searchTerm;
}, $value);

if (count(array_filter($value, 'strlen')) === 0) {
if (count(array_filter($value, fn ($val) => strlen($val) > 0)) === 0) {
return $query;
}

$query->where(function ($query) use ($value) {
foreach (array_filter($value, 'strlen') as $partialValue) {
foreach (array_filter($value, fn ($val) => strlen($val) > 0) as $partialValue) {
$query->whereRaw('LOWER(name) LIKE ?', ['%' . $partialValue . '%'])
->orWhereRaw('slug LIKE ?', ['%' . Str::slug($partialValue) . '%']);
}
Expand Down
35 changes: 35 additions & 0 deletions app/Http/Requests/MenuRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace Kami\Cocktail\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class MenuRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}

/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'is_enabled' => 'required|boolean',
'cocktails' => 'required|array',
'cocktails.*.cocktail_id' => 'required',
'cocktails.*.sort' => 'required|integer',
];
}
}
1 change: 1 addition & 0 deletions app/Http/Resources/BarResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public function toArray($request)

return [
'id' => $this->id,
'slug' => $this->slug,
'name' => $this->name,
'subtitle' => $this->subtitle,
'description' => $this->description,
Expand Down
49 changes: 49 additions & 0 deletions app/Http/Resources/MenuPublicResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace Kami\Cocktail\Http\Resources;

use Kami\Cocktail\Models\MenuCocktail;
use Illuminate\Http\Resources\Json\JsonResource;

/**
* @mixin \Kami\Cocktail\Models\Menu
*/
class MenuPublicResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array<string, mixed>
*/
public function toArray($request)
{
return [
'bar' => [
'name' => $this->bar->name,
'subtitle' => $this->bar->subtitle,
'description' => $this->bar->description,
],
'categories' => $this->menuCocktails->groupBy('category_name')->map(function ($categoryCocktails, $name) {
return [
'name' => $name,
'cocktails' => $categoryCocktails->map(function (MenuCocktail $menuCocktail) {
return [
'sort' => $menuCocktail->sort,
'price' => [
'full' => $menuCocktail->price,
'formatted' => number_format($menuCocktail->price / 100, 2),
],
'currency' => $menuCocktail->currency,
'name' => $menuCocktail->cocktail->name,
'short_ingredients' => $menuCocktail->cocktail->getShortIngredients(),
'image' => $menuCocktail->cocktail->getMainImageUrl(),
];
}),
];
})->values()
];
}
}
46 changes: 46 additions & 0 deletions app/Http/Resources/MenuResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace Kami\Cocktail\Http\Resources;

use Kami\Cocktail\Models\MenuCocktail;
use Illuminate\Http\Resources\Json\JsonResource;

/**
* @mixin \Kami\Cocktail\Models\Menu
*/
class MenuResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array<string, mixed>
*/
public function toArray($request)
{
return [
'id' => $this->id,
'is_enabled' => (bool) $this->is_enabled,
'created_at' => $this->created_at->toJson(),
'updated_at' => $this->updated_at?->toJson(),
'categories' => $this->menuCocktails->groupBy('category_name')->map(function ($categoryCocktails, $name) {
return [
'name' => $name,
'cocktails' => $categoryCocktails->map(function (MenuCocktail $menuCocktail) {
return [
'id' => $menuCocktail->cocktail_id,
'slug' => $menuCocktail->cocktail->slug,
'sort' => $menuCocktail->sort,
'price' => number_format($menuCocktail->price / 100, 2),
'currency' => $menuCocktail->currency,
'name' => $menuCocktail->cocktail->name,
'short_ingredients' => $menuCocktail->cocktail->getShortIngredients(),
];
}),
];
})->values()
];
}
}
20 changes: 13 additions & 7 deletions app/Import/FromArray.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public function process(

// Match glass
$glassId = null;
if ($sourceData['glass']) {
if ($sourceData['glass'] ?? null) {
$glassNameLower = strtolower($sourceData['glass']);
if ($dbGlasses->has($glassNameLower)) {
$glassId = $dbGlasses->get($glassNameLower)->id;
Expand All @@ -92,7 +92,7 @@ public function process(

// Match method
$methodId = null;
if ($sourceData['method']) {
if ($sourceData['method'] ?? null) {
$methodNameLower = strtolower($sourceData['method']);
if ($dbMethods->has($methodNameLower)) {
$methodId = $dbMethods->get($methodNameLower)->id;
Expand Down Expand Up @@ -122,17 +122,23 @@ public function process(

$substitutes = [];
if (array_key_exists('substitutes', $scrapedIngredient) && !empty($scrapedIngredient['substitutes'])) {
foreach ($scrapedIngredient['substitutes'] as $substituteName) {
if ($dbIngredients->has(strtolower($substituteName))) {
$substitutes[] = new SubstituteDTO($dbIngredients->get(strtolower($substituteName))->id);
foreach ($scrapedIngredient['substitutes'] as $substituteData) {
if (is_array($substituteData)) {
$substituteIngredientName = mb_strtolower($substituteData['name']);
} else {
$substituteIngredientName = mb_strtolower($substituteData);
}

if ($dbIngredients->has($substituteIngredientName)) {
$substitutes[] = new SubstituteDTO($dbIngredients->get($substituteIngredientName)->id);
} else {
$ingredientDTO = new IngredientDTO(
$barId,
ucfirst($substituteName),
ucfirst($substituteData),
$userId,
);
$newIngredient = $this->ingredientService->createIngredient($ingredientDTO);
$dbIngredients->put(strtolower($substituteName), $newIngredient);
$dbIngredients->put($substituteIngredientName, $newIngredient);
$substitutes[] = new SubstituteDTO($newIngredient->id);
}
}
Expand Down
Loading
Loading