Skip to content

Commit

Permalink
Merge pull request #918 from ae-utbm/taiste
Browse files Browse the repository at this point in the history
Ajax search input enhancement, promo 25 logo and small improvements
  • Loading branch information
imperosol authored Nov 12, 2024
2 parents e6f25fb + c7a8a1a commit 0a5ddce
Show file tree
Hide file tree
Showing 74 changed files with 1,774 additions and 1,014 deletions.
10 changes: 2 additions & 8 deletions .github/actions/setup_project/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,9 @@ runs:
- name: Install apt packages
uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: gettext
packages: gettext pipx
version: 1.0 # increment to reset cache

- name: Install dependencies
run: |
sudo apt update
sudo apt install gettext
shell: bash

- name: Set up python
uses: actions/setup-python@v5
with:
Expand All @@ -30,7 +24,7 @@ runs:
- name: Install Poetry
if: steps.cached-poetry.outputs.cache-hit != 'true'
shell: bash
run: curl -sSL https://install.python-poetry.org | python3 -
run: pipx install poetry

- name: Check pyproject.toml syntax
shell: bash
Expand Down
7 changes: 3 additions & 4 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:

steps:
- name: SSH Remote Commands
uses: appleboy/ssh-action@dce9d565de8d876c11d93fa4fe677c0285a66d78
uses: appleboy/ssh-action@v1.1.0
with:
# Proxy
proxy_host : ${{secrets.PROXY_HOST}}
Expand All @@ -33,16 +33,15 @@ jobs:

# See https://github.com/ae-utbm/sith/wiki/GitHub-Actions#deployment-action
script: |
export PATH="/home/sith/.local/bin:$PATH"
pushd ${{secrets.SITH_PATH}}
cd ${{secrets.SITH_PATH}}
git fetch
git reset --hard origin/master
poetry install --with prod --without docs,tests
npm install
poetry run ./manage.py install_xapian
poetry run ./manage.py migrate
poetry run ./manage.py collectstatic --clear --clear-generated --noinput
poetry run ./manage.py collectstatic --clear --noinput
poetry run ./manage.py compilemessages
sudo systemctl restart uwsgi
7 changes: 3 additions & 4 deletions .github/workflows/taiste.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:

steps:
- name: SSH Remote Commands
uses: appleboy/ssh-action@dce9d565de8d876c11d93fa4fe677c0285a66d78
uses: appleboy/ssh-action@v1.1.0
with:
# Proxy
proxy_host : ${{secrets.PROXY_HOST}}
Expand All @@ -32,16 +32,15 @@ jobs:

# See https://github.com/ae-utbm/sith/wiki/GitHub-Actions#deployment-action
script: |
export PATH="$HOME/.poetry/bin:$PATH"
pushd ${{secrets.SITH_PATH}}
cd ${{secrets.SITH_PATH}}
git fetch
git reset --hard origin/taiste
poetry install --with prod --without docs,tests
npm install
poetry run ./manage.py install_xapian
poetry run ./manage.py migrate
poetry run ./manage.py collectstatic --clear --clear-generated --noinput
poetry run ./manage.py collectstatic --clear --noinput
poetry run ./manage.py compilemessages
sudo systemctl restart uwsgi
23 changes: 23 additions & 0 deletions accounting/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from typing import Annotated

from annotated_types import MinLen
from ninja_extra import ControllerBase, api_controller, paginate, route
from ninja_extra.pagination import PageNumberPaginationExtra
from ninja_extra.schemas import PaginatedResponseSchema

from accounting.models import ClubAccount, Company
from accounting.schemas import ClubAccountSchema, CompanySchema
from core.api_permissions import CanAccessLookup


@api_controller("/lookup", permissions=[CanAccessLookup])
class AccountingController(ControllerBase):
@route.get("/club-account", response=PaginatedResponseSchema[ClubAccountSchema])
@paginate(PageNumberPaginationExtra, page_size=50)
def search_club_account(self, search: Annotated[str, MinLen(1)]):
return ClubAccount.objects.filter(name__icontains=search).values()

@route.get("/company", response=PaginatedResponseSchema[CompanySchema])
@paginate(PageNumberPaginationExtra, page_size=50)
def search_company(self, search: Annotated[str, MinLen(1)]):
return Company.objects.filter(name__icontains=search).values()
15 changes: 15 additions & 0 deletions accounting/schemas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from ninja import ModelSchema

from accounting.models import ClubAccount, Company


class ClubAccountSchema(ModelSchema):
class Meta:
model = ClubAccount
fields = ["id", "name"]


class CompanySchema(ModelSchema):
class Meta:
model = Company
fields = ["id", "name"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { AjaxSelect } from "#core:core/components/ajax-select-base";
import { registerComponent } from "#core:utils/web-components";
import type { TomOption } from "tom-select/dist/types/types";
import type { escape_html } from "tom-select/dist/types/utils";
import {
type ClubAccountSchema,
type CompanySchema,
accountingSearchClubAccount,
accountingSearchCompany,
} from "#openapi";

@registerComponent("club-account-ajax-select")
export class ClubAccountAjaxSelect extends AjaxSelect {
protected valueField = "id";
protected labelField = "name";
protected searchField = ["code", "name"];

protected async search(query: string): Promise<TomOption[]> {
const resp = await accountingSearchClubAccount({ query: { search: query } });
if (resp.data) {
return resp.data.results;
}
return [];
}

protected renderOption(item: ClubAccountSchema, sanitize: typeof escape_html) {
return `<div class="select-item">
<span class="select-item-text">${sanitize(item.name)}</span>
</div>`;
}

protected renderItem(item: ClubAccountSchema, sanitize: typeof escape_html) {
return `<span>${sanitize(item.name)}</span>`;
}
}

@registerComponent("company-ajax-select")
export class CompanyAjaxSelect extends AjaxSelect {
protected valueField = "id";
protected labelField = "name";
protected searchField = ["code", "name"];

protected async search(query: string): Promise<TomOption[]> {
const resp = await accountingSearchCompany({ query: { search: query } });
if (resp.data) {
return resp.data.results;
}
return [];
}

protected renderOption(item: CompanySchema, sanitize: typeof escape_html) {
return `<div class="select-item">
<span class="select-item-text">${sanitize(item.name)}</span>
</div>`;
}

protected renderItem(item: CompanySchema, sanitize: typeof escape_html) {
return `<span>${sanitize(item.name)}</span>`;
}
}
8 changes: 4 additions & 4 deletions accounting/templates/accounting/operation_edit.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@
<script>
$( function() {
var target_type = $('#id_target_type');
var user = $('#id_user_wrapper');
var club = $('#id_club_wrapper');
var club_account = $('#id_club_account_wrapper');
var company = $('#id_company_wrapper');
var user = $('user-ajax-select');
var club = $('club-ajax-select');
var club_account = $('club-account-ajax-select');
var company = $('company-ajax-select');
var other = $('#id_target_label');
var need_link = $('#id_need_link_full');
function update_targets () {
Expand Down
45 changes: 37 additions & 8 deletions accounting/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

import collections

from ajax_select.fields import AutoCompleteSelectField
from django import forms
from django.conf import settings
from django.core.exceptions import PermissionDenied, ValidationError
Expand All @@ -39,6 +38,13 @@
Operation,
SimplifiedAccountingType,
)
from accounting.widgets.select import (
AutoCompleteSelectClubAccount,
AutoCompleteSelectCompany,
)
from club.models import Club
from club.widgets.select import AutoCompleteSelectClub
from core.models import User
from core.views import (
CanCreateMixin,
CanEditMixin,
Expand All @@ -47,6 +53,7 @@
TabedViewMixin,
)
from core.views.forms import SelectDate, SelectFile
from core.views.widgets.select import AutoCompleteSelectUser
from counter.models import Counter, Product, Selling

# Main accounting view
Expand Down Expand Up @@ -334,12 +341,30 @@ class Meta:
"invoice": SelectFile,
}

user = AutoCompleteSelectField("users", help_text=None, required=False)
club_account = AutoCompleteSelectField(
"club_accounts", help_text=None, required=False
user = forms.ModelChoiceField(
help_text=None,
required=False,
widget=AutoCompleteSelectUser,
queryset=User.objects.all(),
)
club_account = forms.ModelChoiceField(
help_text=None,
required=False,
widget=AutoCompleteSelectClubAccount,
queryset=ClubAccount.objects.all(),
)
club = forms.ModelChoiceField(
help_text=None,
required=False,
widget=AutoCompleteSelectClub,
queryset=Club.objects.all(),
)
company = forms.ModelChoiceField(
help_text=None,
required=False,
widget=AutoCompleteSelectCompany,
queryset=Company.objects.all(),
)
club = AutoCompleteSelectField("clubs", help_text=None, required=False)
company = AutoCompleteSelectField("companies", help_text=None, required=False)
need_link = forms.BooleanField(
label=_("Link this operation to the target account"),
required=False,
Expand Down Expand Up @@ -817,8 +842,12 @@ def get_success_url(self):


class CloseCustomerAccountForm(forms.Form):
user = AutoCompleteSelectField(
"users", label=_("Refound this account"), help_text=None, required=True
user = forms.ModelChoiceField(
label=_("Refound this account"),
help_text=None,
required=True,
widget=AutoCompleteSelectUser,
queryset=User.objects.all(),
)


Expand Down
39 changes: 39 additions & 0 deletions accounting/widgets/select.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from pydantic import TypeAdapter

from accounting.models import ClubAccount, Company
from accounting.schemas import ClubAccountSchema, CompanySchema
from core.views.widgets.select import AutoCompleteSelect, AutoCompleteSelectMultiple

_js = ["webpack/accounting/components/ajax-select-index.ts"]


class AutoCompleteSelectClubAccount(AutoCompleteSelect):
component_name = "club-account-ajax-select"
model = ClubAccount
adapter = TypeAdapter(list[ClubAccountSchema])

js = _js


class AutoCompleteSelectMultipleClubAccount(AutoCompleteSelectMultiple):
component_name = "club-account-ajax-select"
model = ClubAccount
adapter = TypeAdapter(list[ClubAccountSchema])

js = _js


class AutoCompleteSelectCompany(AutoCompleteSelect):
component_name = "company-ajax-select"
model = Company
adapter = TypeAdapter(list[CompanySchema])

js = _js


class AutoCompleteSelectMultipleCompany(AutoCompleteSelectMultiple):
component_name = "company-ajax-select"
model = Company
adapter = TypeAdapter(list[CompanySchema])

js = _js
22 changes: 22 additions & 0 deletions club/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from typing import Annotated

from annotated_types import MinLen
from ninja_extra import ControllerBase, api_controller, paginate, route
from ninja_extra.pagination import PageNumberPaginationExtra
from ninja_extra.schemas import PaginatedResponseSchema

from club.models import Club
from club.schemas import ClubSchema
from core.api_permissions import CanAccessLookup


@api_controller("/club")
class ClubController(ControllerBase):
@route.get(
"/search",
response=PaginatedResponseSchema[ClubSchema],
permissions=[CanAccessLookup],
)
@paginate(PageNumberPaginationExtra, page_size=50)
def search_club(self, search: Annotated[str, MinLen(1)]):
return Club.objects.filter(name__icontains=search).values()
Loading

0 comments on commit 0a5ddce

Please sign in to comment.