วันศุกร์ที่ 10 พฤศจิกายน พ.ศ. 2566

Filament Disable Button Create Edit Delete

   
    public static function canCreate(): bool
    {
        return false;
    }
   
    public static function canEdit(Model $record): bool
    {
        return false;
    }
   
    public static function canDelete(Model $record): bool
    {
        return false;
    }
   
    public static function canDeleteAny(): bool
    {
        return false;
    }

 

วันอังคารที่ 31 ตุลาคม พ.ศ. 2566

Filament infolist view On Resource

 use Filament\Infolists\Infolist;

use Filament\Infolists\Components;

use Filament\Infolists\Components\TextEntry;


    public static function infolist(Infolist $infolist): Infolist
    {
        return $infolist
            ->schema([
              Components\Section::make()
               ->schema([
                Components\TextEntry::make('contrct_no')
               ])

            ]);
    }

Filament Modal slideOver left

 

 ->actions([
              Tables\Actions\ViewAction::make()->slideOver(),

select field first_name and last name show data concat field

 

Select::make('people_id')             
  ->searchable()
  ->getSearchResultsUsing(fn (string $search): array =>
    Peoples::select(DB::raw('CONCAT(first_name ," ", last_name) AS name'), 'id')
   ->where('first_name', 'like', "%{$search}%")->limit(50)->pluck('name', 'id')
->toArray())
  ->getOptionLabelUsing(fn ($value): ?string => Peoples::find($value)->FullName ),

วันศุกร์ที่ 13 ตุลาคม พ.ศ. 2566

Filament Image upload

 php artisan storage:link

 INFO  The [public/storage] link has been connected to [storage/app/public].


          Forms\Components\FileUpload::make('images')
                ->image()
                ->preserveFilenames()
                ->directory('customer-image')
                ->storeFileNamesIn('customers-image')
                ->imageEditor()    
                ->label('รูป') ,
                   ])
               

วันพฤหัสบดีที่ 12 ตุลาคม พ.ศ. 2566

Group Action View Edit Delete Table with :::

 

       
        ->actions([
        Tables\Actions\ActionGroup::make([
                    Tables\Actions\ViewAction::make(),    
                    Tables\Actions\EditAction::make(),
                    Tables\Actions\DeleteBulkAction::make(),
                ])
            ])

วันอังคารที่ 10 ตุลาคม พ.ศ. 2566

Filament error duplicate on edit record

 using ignoreRecord: true


    TextInput::make('name')->required()->unique(ignoreRecord: true)->label('ชื่อห้อง'),

   

วันเสาร์ที่ 7 ตุลาคม พ.ศ. 2566

collapse navigation bar left filament

class AdminPanelProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->default()
            ->id('admin')
            ->path('admin')
            ->login()
            ->colors([
                'primary' => Color::Amber,
            ])
          ->sidebarCollapsibleOnDesktop() 

         

เพิ่ม Dropdown Navigation Dashboard Filament

 

protected static ?string $navigationGroup = 'ข้อมูลหลัก';   
protected static ?string $modelLabel = 'ข้อมูลจังหวัด ';
   
    protected static ?int $navigationSort = 3;

เปลี่ยน Dashboard ภาษาไทย

 

   
protected static ?string $modelLabel = 'ข้อมูลห้องเช่า ';

Filament fix unique() for editing

 

public static function form(Form $form): Form

    {     
  return $form
            ->schema([
                Card::make()
                ->schema([
     TextInput::make('room_no')->required()->unique(ignoreRecord: true)->label('รหัส'),
    TextInput::make('name')->required()->unique(ignoreRecord: true)->label('ชื่อห้อง'),
      TextInput::make('electric_no')->label('เลขมาตรไฟฟ้า'),
      TextInput::make('water_no')->label('เลขมาตรน้ำ'),
      TextInput::make('electric_unit')->label('หน่วยไฟฟ้าล่าสุด'),
      TextInput::make('water_unit')->label('หน่วยน้ำประปาล่าสุด'),
      TextInput::make('price')->numeric()->label('ราคาห้อง'),
      TextInput::make('price_tax')->numeric()->label('ราคาห้อง ส่งภาษี'),
                        ])->columns(2),
                   
            ]);
    }

วันจันทร์ที่ 31 กรกฎาคม พ.ศ. 2566

Raspbery pi play mp3 file

 import time
import board
import digitalio

from audiomp3 import MP3Decoder

try:
    from audioio import AudioOut
except ImportError:
    try:
        from audiopwmio import PWMAudioOut as AudioOut
    except ImportError:
        pass  
   
button1 = digitalio.DigitalInOut(board.GP20)
button1.switch_to_input(pull=digitalio.Pull.UP)

mp3files = ["bell1.mp3", "bell2.mp3"]

mp3 = open(mp3files[0], "rb")
decoder = MP3Decoder(mp3)
#audio = AudioOut(board.A0)
audio = AudioOut(board.GP18)

while True:
    for filename in mp3files:
     
        decoder.file = open(filename, "rb")
        audio.play(decoder)
        print("playing", filename)

        while audio.playing:
            pass

        print("Waiting for button press to continue!")
        while button.value:
            pass

Raspbery pi Cytrol read write scCard

 

from board import *
from time import *
import busio
import sdcardio
import storage


spi = busio.SPI(GP10, MOSI=GP11, MISO=GP12)
cs = GP15
sd = sdcardio.SDCard(spi, cs)

vfs = storage.VfsFat(sd)
storage.mount(vfs, '/sd')

with open("/sd/test1.txt", "w") as file:
    file.write("1. Hello, world!\r\n")

with open("/sd/test1.txt", "a") as file:
    file.write("2. This is another line!\r\n")

with open("/sd/test1.txt", "a") as file:
    file.write("3. Last but not least!")

with open("/sd/test1.txt", "r") as file:
    print("Printing lines in file:")
    for line in file:
        print(line, end='')

วันพฤหัสบดีที่ 27 กรกฎาคม พ.ศ. 2566

raspberry pi pico first run

#blink led
import machine
import time

led= machine.Pin('LED', machine.Pin.OUT)

while (True):
    led.on()
    time.sleep(0.5)
    led.off()
    time.sleep(0.5

Scan AccessPoints 
import network
wlan=network.WLAN(network.STA_IF)
wlan.active(True)

accesspoints = wlan.scan()
for ap in accesspoints:
        print(ap)

วันจันทร์ที่ 10 กรกฎาคม พ.ศ. 2566

Javascript fetch api Alpine js

 

 
 async function fetchInsert(url,rowitem) {

       const Responses = await fetch(url, {
            method: 'POST',
            headers: {
               'Content-Type': 'application/json',
               'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                   },
            body: JSON.stringify(rowitem)
            })
        const Res =  await  Responses.json();
        return  Res;
        }

Paginate Alpine json data


          document.addEventListener('alpine:init', () => {
            Alpine.data('aData', () => ({
                search: "",
                pageNumber: 0,
                start: '',
                end: '',
                size: 15,
                total: '',
                rowData: 'https://api/...',
                rowItems: '',
                pages: null,
                sortAsc: '',
                sortCol: '',
                  listData() {

                    this.start = this.pageNumber * this.size,
                    this.end = this.start + this.size;
                    this.rowItems = this.rowData;
                    let data = null;
               if (this.search == "") {
                        this.rowItems = this.rowData;
                        this.total = this.rowItems.length;
                        let p = Math.ceil(this.rowItems.length / this.size);
                        this.pages = p;
                        let data = this.rowItems.slice(this.start, this.end);
                        return data;
               } else {
                        const data = this.rowItems.filter((item) => {
                          return (
                                    item.room_no
                                ).toLowerCase()
                                .includes(this.search.toLowerCase())

                        })

                            this.total = data.length;
                            let p = Math.ceil(data.length / this.size);
                            this.pages = p;
                            this.viewPage(0);
                        return data.slice(this.start, this.end);


                    }

                }

Sort Data from json Alpine

 sort data json

    rowitem: 'https://api',
    sortcol: '',
    sortAsc: '',
sortRow() {  
    if(this.sortCol === col) this.sortAsc = !this.sortAsc;
      this.sortCol = col;
      this.rowItems.sort((a, b) => {
        if(a[this.sortCol] < b[this.sortCol]) return this.sortAsc?1:-1;
        if(a[this.sortCol] > b[this.sortCol]) return this.sortAsc?-1:1;
        return 0;
      });
    }

วันจันทร์ที่ 3 กรกฎาคม พ.ศ. 2566

Search text in table with Alpine js

  <div class="row mt-2 no-gutters" x-init="appInit" x-data="rowData">

                         <input x-model="search" class="form-control" type="search" placeholder="ค้นหา...">

 width:100%;  height:450px; overflow:auto; position:relative; resize: vertical;">

                     <table id="myTable" class="table table-sm table-bordered table-striped table-hover">

                         <thead>

                             <tr>

                                <th>#</th>    <th>ชื่อสกุล</th>

                          </tr>

                         </thead>

                         <tbody>

                             <template x-for="row,index in  items.data">

                                  <tr x-show="searchtext($el)" >

                                    <td x-text="++index"></td>

                                    <td x-text="row.name"></td>

                                 </tr>

                             </template>

                         </tbody>

                     </table>

         </div>

     <script>

         document.addEventListener('alpine:init', () => {

              Alpine.data('rowData', () => ({

                 search: '',

                items: {},

                appInit() {

            const url = 'https://....'

                this.items =  fetch(url)

            },

            searchtext(el) {

                     return this.search === '' || el.textContent.includes(this.search)

                 },

                    }))

    })



</script>