Skip to content

Commit

Permalink
Merge pull request #36 from Cybrarist/v3.3
Browse files Browse the repository at this point in the history
V3.3
  • Loading branch information
Cybrarist authored Jan 16, 2025
2 parents 0ae953c + 822fecb commit a91a9ba
Show file tree
Hide file tree
Showing 67 changed files with 1,621 additions and 1,026 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public/hot
public_html/storage
public_html/hot

vendor/
storage/*.key
.env
Homestead.yaml
Expand Down
38 changes: 38 additions & 0 deletions .github/workflows/build-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Publish Docker image

on:
push:
branches:
- '*'
# release:
# types: [published]

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout the codebase
uses: actions/checkout@v4
- name: Login to the Container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/discount-bandit
flavor: |
latest=true
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: ./
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
7 changes: 5 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ RUN apt update && apt install -y supervisor \
ENV CHROME_BIN="/usr/bin/chromium-browser"
ENV CHROME_OPTS=" --disable-dev-shm-usage --headless --disable-gpu --no-sandbox --enable-features=ConversionMeasurement --remote-debugging-port=9222 "

RUN install-php-extensions @composer

RUN docker-php-ext-install pcntl \
opcache \
pdo_mysql \
Expand All @@ -48,8 +50,10 @@ RUN docker-php-ext-install pcntl \
bcmath \
calendar \
pdo_mysql \
sockets \
zip


COPY ./docker/base_supervisord.conf /etc/supervisor/conf.d/supervisord.conf

COPY . /app
Expand All @@ -58,12 +62,11 @@ WORKDIR /app

EXPOSE 80 443 2019 8080


RUN chmod +x /app/*

RUN mkdir -p /config/chromium


ENV DISPLAY=:99


ENTRYPOINT ["docker/entrypoint.sh"]
25 changes: 18 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ Feel free to access the up-to-date documentation from [Here](https://discount-ba

## Deployment
Discount Bandit uses a web interface, so you need to install some dependencies first:
- php (https://www.php.net)
- composer (https://getcomposer.org)
- [php](https://www.php.net)
- [composer](https://getcomposer.org)
- apache or nginx (https://httpd.apache.org , https://www.nginx.com)
- mysql (https://www.mysql.com)
- [mysql](https://www.mysql.com)
- sqlite (Default Option)

or you can install something like MAMP instead of installing each one alone. (https://www.mamp.info/en/windows/)
or you can install something like [MAMP](https://www.mamp.info/en/windows/) instead of installing each one alone.


first, you need to install the packages with composer
Expand Down Expand Up @@ -47,11 +47,22 @@ If you want to update the code, after installing the new version run the followi
php artisan discount:update
```
## Connect
If you are coming outside github or don't like to use it, feel free to join my discord.
https://discord.gg/VBMHvH8tuR
If you are coming outside github or don't like to use it, feel free to join [Discord](https://discord.gg/VBMHvH8tuR).


## Docker
There is no docker image for beta, since i might need the flexibility to push updates or fix bugs.
Please check the docker repos to pull the image you prefer [Docker](https://hub.docker.com/r/cybrarist/discount-bandit)

# docker-compose

If you run docker-compose before creating a .env file, it will have created a '.env'.
To fix it, just delete the .env folder and make sure you create your own .env file before running:
```
rm -rf .env
cp .env.example .env
```

Don't forget to also populate the .env file with your own APP_KEY (a random 32 characters string).

## Sponsors
![Jetbrains](https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg)
206 changes: 148 additions & 58 deletions app/Filament/Resources/ProductResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
use App\Helpers\CurrencyHelper;
use App\Helpers\ProductHelper;
use App\Helpers\StoreHelper;
use App\Helpers\StoresAvailable\Noon;
use App\Helpers\URLHelper;
use App\Models\Product;
use App\Models\Store;
use Archilex\ToggleIconColumn\Columns\ToggleIconColumn;
use Filament\Forms;
use Filament\Forms\Components\DatePicker;
Expand All @@ -23,23 +25,26 @@
use Filament\Notifications\Notification;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\Layout\Grid;
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\Filter;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\HtmlString;
use Illuminate\Support\Str;

class ProductResource extends Resource
{
protected static ?string $model = Product::class;
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
protected static ?string $navigationIcon = 'heroicon-o-shopping-bag';
protected static ?int $navigationSort=1;

protected static ?string $recordTitleAttribute="name";

protected static bool $isGloballySearchable=true;

public static function form(Form $form): Form
Expand Down Expand Up @@ -171,59 +176,145 @@ public static function table(Table $table): Table

$stores=StoreHelper::get_stores_with_active_products();
$currencies=CurrencyHelper::get_currencies();


return $table
->modifyQueryUsing(function ($query){
$query->with([
"product_stores:id,product_id,store_id,price,notify_price,updated_at,highest_price,lowest_price",
"product_stores:id,product_id,store_id,price,notify_price,updated_at,highest_price,lowest_price,key,updated_at",
]);
})
->recordUrl( null)
->columns([
ImageColumn::make('image')->alignCenter(),

TextColumn::make('name')
->words(5)
->limit(50)
->searchable()
->sortable(),

TextColumn::make('status')
->badge()
->color(fn ($state) => StatusEnum::get_badge($state)),

TextColumn::make('product_stores.store_id')
->formatStateUsing(function ($state) use($stores){
return $stores[$state]["name"];
})
->listWithLineBreaks(),

TextColumn::make('product_stores.price')
->formatStateUsing(function ($record) use ($currencies, $stores) {
return ProductHelper::prepare_multiple_prices_in_table($record, $currencies, $stores);
})->label('Prices'),

TextColumn::make('product_stores.notify_price')
->formatStateUsing(function ($record) use ($currencies, $stores) {
return ProductHelper::prepare_multiple_notify_prices_in_table($record, $currencies, $stores);
})->label('Notify at'),


TextColumn::make('product_stores.highest_price')
->label("Highest Price")
->listWithLineBreaks()
->color('danger'),

TextColumn::make('product_stores.lowest_price')
->label("Lowest Price")
->listWithLineBreaks()
->color('success'),

ToggleIconColumn::make('favourite')
->onIcon("heroicon-s-star")
->offIcon("heroicon-o-star"),

TextColumn::make('product_stores.updated_at')
->listWithLineBreaks()
->label('Last Update'),
Grid::make([
'lg' => 10,
])
->schema([
ImageColumn::make('image')
->verticallyAlignCenter()
->alignCenter()
->height('100%')
->width('100%')
->extraImgAttributes(['style'=>'max-height:200px; '])
->columnSpan(3)
->url(fn ($record): string =>
route('filament.admin.resources.products.edit',
['record' => $record])
),

Grid::make([
'lg' => 8,
'md'=>4
])
->schema([

TextColumn::make('name')
->columnSpan(4)
->searchable()
->words(10)
->url(fn ($record): string =>
route('filament.admin.resources.products.edit',
['record' => $record])
)
->sortable(),

TextColumn::make('status')
->columnSpan(2)
->badge()
->verticallyAlignCenter()
->alignEnd()
->color(fn ($state) => StatusEnum::get_badge($state)),

ToggleIconColumn::make('favourite')
->columnSpan(1)
->alignEnd()
->onIcon("heroicon-s-star")
->offIcon("heroicon-o-star"),



IconColumn::make('delete')
->getStateUsing(fn() => true)
->columnSpan(1)

->alignEnd()
->icon(fn(bool $state): string => 'heroicon-m-trash')
->color('danger')
->action(Tables\Actions\DeleteAction::make()),


])->columnSpan(7),

Stack::make([

Tables\Columns\Layout\Panel::make([
Grid::make([
'lg'=> 7,
'sm'=>1
])->schema([
TextColumn::make('product_stores')
->formatStateUsing(function ($state, $record) use($stores){

$store = new Store();
$store->fill($stores[$state->store_id]);

$final_class_name="App\Helpers\StoresAvailable\\" . Str::ucfirst( explode(".", $store->domain)[0]);
$url= call_user_func($final_class_name . '::prepare_url' , $store->domain, $state->key , $store );

return new HtmlString("<a class='underline text-primary-400' href='$url' target='_blank'>{$stores[$state->store_id]["name"]}</a>");
})
->columnSpan([
'md'=> 2,
'sm'=> 7
])
->html()
->listWithLineBreaks(),

TextColumn::make('product_stores.highest_price')
->listWithLineBreaks()
->columnSpan([
'md'=> 1,
'sm'=> 7
])
->color('danger'),

TextColumn::make('product_stores.price')
->columnSpan([
'md'=> 1,
'sm'=> 2
])
->formatStateUsing(function ($record) use ($currencies, $stores) {
return ProductHelper::prepare_multiple_prices_in_table($record, $currencies, $stores);
})
->label('Prices'),

TextColumn::make('product_stores.lowest_price')
->columnSpan([
'md'=> 1,
'sm'=> 2
])
->listWithLineBreaks()
->color('success'),

TextColumn::make('product_stores.updated_at')
->columnSpan([
'md'=> 2,
'sm'=> 3
])
->listWithLineBreaks(),
])
])
->columnSpanFull(),


])
->space(3)
->columnSpanFull(),

])
])
->contentGrid([
'md' => 2,
])
->defaultSort('favourite' , 'desc')
->filters([
Expand Down Expand Up @@ -283,24 +374,23 @@ public static function table(Table $table): Table
"
);


$product_ids= Arr::pluck($products_with_lowest_price_within_x , 'product_id');

$query->wherein('id', $product_ids);
}) ->indicateUsing(function (array $data): ?string {
})->indicateUsing(function (array $data): ?string {
if (! $data['lowest_within_x']) {
return null;
}

return "Lowest in {$data['lowest_within_x']} Days" ;
})
}),


SelectFilter::make('category')
->relationship('categories','name')
->multiple()
->searchable()
->preload(),

])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Expand Down
Loading

0 comments on commit a91a9ba

Please sign in to comment.