Compare commits
1 Commits
fix/issue-
...
8566b98b3b
| Author | SHA1 | Date | |
|---|---|---|---|
| 8566b98b3b |
@ -1,26 +0,0 @@
|
|||||||
# Version control & tooling
|
|
||||||
.git
|
|
||||||
.gitignore
|
|
||||||
.gitattributes
|
|
||||||
|
|
||||||
# Local task runner state & binaries
|
|
||||||
.task
|
|
||||||
bin/
|
|
||||||
tags
|
|
||||||
|
|
||||||
# Local databases & logs
|
|
||||||
*.sqlite
|
|
||||||
*.log
|
|
||||||
|
|
||||||
# Editor / IDE
|
|
||||||
.zed
|
|
||||||
.idea
|
|
||||||
.vscode
|
|
||||||
|
|
||||||
# Docs & examples not needed to build the image
|
|
||||||
*.md
|
|
||||||
htmlexamples/
|
|
||||||
|
|
||||||
# Don't send the docker metadata itself (optional, keeps context lean)
|
|
||||||
Dockerfile
|
|
||||||
.dockerignore
|
|
||||||
409
AGENTS.md
409
AGENTS.md
@ -1,250 +1,227 @@
|
|||||||
# AGENTS.md
|
# AGENTS.md
|
||||||
|
|
||||||
Guidance for AI agents (and humans) working in this repository.
|
Guidance for AI agents (and humans) working in this repository. Read this
|
||||||
|
before making changes.
|
||||||
|
|
||||||
## Project Overview
|
## Project overview
|
||||||
|
|
||||||
**kurious** (`git.loyso.art/frx/kurious`) is a course/education platform that
|
**kurious** (module `git.loyso.art/frx/kurious`) is a Go service that
|
||||||
aggregates and serves educational course listings. It scrapes/syncs course data
|
aggregates, stores, and serves educational/learning course data sourced from
|
||||||
from an external source (sravni.ru) via a rate-limited HTTP client, stores it
|
[sravni.ru](https://www.sravni.ru/kursy). It exposes a server-rendered web UI
|
||||||
locally, and exposes it through a server-rendered web UI with filtering,
|
for browsing courses and runs a background job that periodically syncs data
|
||||||
pagination, and statistics.
|
from the upstream sravni.ru API.
|
||||||
|
|
||||||
The project is written in Go and follows a hexagonal (ports & adapters)
|
Go version: **1.26** (`toolchain go1.26.4`). Builds are CGO-free
|
||||||
architecture with a CQRS-flavored application layer.
|
(`CGO_ENABLED=0`), using the pure-Go `modernc.org/sqlite` driver.
|
||||||
|
|
||||||
## Tech Stack
|
### Entry points (`cmd/`)
|
||||||
|
|
||||||
- **Language:** Go 1.26 (toolchain `go1.26.4`; see `go.mod`)
|
| Binary | Path | Purpose |
|
||||||
- **HTTP routing:** `github.com/gorilla/mux`
|
| -------------- | ----------------------- | ----------------------------------------------------------------------- |
|
||||||
- **HTTP client:** `github.com/go-resty/resty/v2` (sravni.ru scraper)
|
| `kuriousweb` | `cmd/kuriweb` | HTTP web server. Serves the course browser UI + REST endpoints. |
|
||||||
- **Database:** SQLite via `modernc.org/sqlite` (pure-Go, CGO disabled).
|
| `kuriousbg` | `cmd/background` | Background worker. Cron-scheduled sync of courses/orgs from sravni.ru. |
|
||||||
YDB was historically supported but is **no longer supported**
|
| `sravnicli` | `cmd/dev/sravnicli` | Developer/debug CLI for inspecting the sravni.ru API and redux state. |
|
||||||
(`service.NewApplication` returns an error for the YDB engine).
|
|
||||||
- **DB access:** `github.com/jmoiron/sqlx` (named queries)
|
Each binary reads a JSON config from `argv[1]` (default `config.json` for
|
||||||
- **Templating:** `github.com/a-h/templ` (`.templ` files compile to Go)
|
servers, `config_cli.json` for the CLI). Note: `*.json` is gitignored.
|
||||||
- **Observability:** OpenTelemetry (`go.opentelemetry.io/otel`) — traces and
|
|
||||||
metrics with stdout / OTLP (HTTP & gRPC) exporters
|
Build metadata (`version`, `commit`, `buildTime`) is injected via `-ldflags`
|
||||||
- **Background jobs:** `github.com/robfig/cron/v3`
|
into the root package `kurious.go` (see `Version()`, `Commit()`, `BuildTime()`).
|
||||||
- **Logging:** standard `log/slog` (text or JSON, configurable)
|
|
||||||
- **Rate limiting:** `golang.org/x/time/rate`
|
|
||||||
- **Testing:** `github.com/stretchr/testify` (assert, require, mock)
|
|
||||||
- **Mocking:** `github.com/vektra/mockery/v2` (config in `.mockery.yaml`)
|
|
||||||
- **Linting:** `golangci-lint` v1.55.2
|
|
||||||
- **Build/task runner:** [Taskfile](https://taskfile.dev) (`Taskfile.yml`)
|
|
||||||
- **Build flags:** ldflags inject `version`, `commit`, `buildTime`
|
|
||||||
(see `kurious.go`)
|
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
The codebase implements a **hexagonal architecture** (ports & adapters) with a
|
The codebase follows **Hexagonal Architecture (Ports & Adapters)** with
|
||||||
CQRS-style separation between commands (writes) and queries (reads).
|
**CQRS** (command/query separation). The domain core has no knowledge of
|
||||||
|
databases, HTTP, or external services; everything is wired together in the
|
||||||
|
composition root.
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────────────────────────────────────┐
|
cmd/ # application entrypoints (thin mains)
|
||||||
delivery │ ports/ (HTTP server, cron jobs) │
|
internal/kurious/
|
||||||
mechanisms └──────────────────────┬──────────────────────┘
|
domain/ # CORE: entities, repository interfaces, value/param types
|
||||||
│ depends on
|
app/ # application layer
|
||||||
┌──────────────────────▼──────────────────────┐
|
command/ # write-side handlers (CQRS commands)
|
||||||
application │ app/ (command/, query/) │
|
query/ # read-side handlers (CQRS queries)
|
||||||
layer │ app.Application { Commands, Queries } │
|
app.go # Application struct aggregating Commands + Queries
|
||||||
│ decorator/ (logging decorators) │
|
ports/ # DRIVING adapters (what drives the domain)
|
||||||
└──────────────────────┬──────────────────────┘
|
http/ # HTTP server (gorilla/mux + templ HTML)
|
||||||
│ depends on
|
background/ # cron job handlers
|
||||||
┌──────────────────────▼──────────────────────┐
|
background.go # cron scheduler wrapper
|
||||||
domain │ domain/ (entities, repository ports) │
|
services.go # Services aggregate
|
||||||
└──────────────────────┬──────────────────────┘
|
adapters/ # DRIVEN adapters (what the domain drives)
|
||||||
│ implemented by
|
sqlite_* # SQLite repositories (course, organization, learning category)
|
||||||
┌──────────────────────▼──────────────────────┐
|
memory_mapper.go # in-memory CourseMapper implementation
|
||||||
adapters │ adapters/ (sqlite_*, memory_mapper, │
|
ydb_course_repository.go # legacy YDB adapter (deprecated, unsupported)
|
||||||
│ ydb_* legacy stub) │
|
mocks/ # generated mockery mocks
|
||||||
└─────────────────────────────────────────────┘
|
service/ # COMPOSITION ROOT: wires adapters into app.Application
|
||||||
|
internal/common/ # cross-cutting utilities (see below)
|
||||||
|
pkg/xdefault/ # reusable helper (WithFallback)
|
||||||
|
migrations/sqlite/ # numbered *.sql migrations + embed migrator
|
||||||
|
assets/kurious/ # embedded static assets (go:embed)
|
||||||
```
|
```
|
||||||
|
|
||||||
- **`domain/`** — pure business entities (`Course`, `Organization`,
|
### Layer responsibilities
|
||||||
`LearningCategory`) and the **repository interfaces** (ports) that the
|
|
||||||
application depends on: `CourseRepository`, `OrganizationRepository`,
|
|
||||||
`LearningCategoryRepository`. No I/O or framework code lives here.
|
|
||||||
- **`app/`** — the application layer. `app.Application` aggregates a
|
|
||||||
`Commands` struct and a `Queries` struct. Handlers in `app/command/` perform
|
|
||||||
writes; handlers in `app/query/` perform reads. Each handler implements a
|
|
||||||
generic `decorator.CommandHandler[T]` or `decorator.QueryHandler[Q, U]`
|
|
||||||
interface and is wrapped with logging decorators at construction time.
|
|
||||||
- **`adapters/`** — concrete implementations of the domain repository ports.
|
|
||||||
`sqlite_course_repository.go`, `sqlite_organization_repository.go`, etc.
|
|
||||||
translate between domain types and SQL rows. `memory_mapper.go` is an
|
|
||||||
in-memory mapper translating external dictionary IDs to human-readable names.
|
|
||||||
- **`ports/`** — delivery mechanisms. `ports/http/` is the HTTP server (gorilla/mux
|
|
||||||
+ templ templates); `ports/background/` runs scheduled cron jobs (e.g.
|
|
||||||
`SyncSravniHandler`).
|
|
||||||
- **`service/`** — the **composition root**. `service.NewApplication` selects
|
|
||||||
the DB engine, constructs the SQLite connection, builds the adapters, and
|
|
||||||
wires everything into an `app.Application`. This is what binaries call.
|
|
||||||
|
|
||||||
Data flows: an HTTP request enters `ports/http`, calls a handler on
|
- **`domain/`** — Pure business types: `Course`, `Organization`,
|
||||||
`service.Application` (which delegates to `app/command` or `app/query`), which
|
`LearningCategory`, `Category`. Defines repository interfaces
|
||||||
calls a `domain` repository interface implemented by an `adapters/*` repository.
|
(`CourseRepository`, `OrganizationRepository`, `LearningCategoryRepository`)
|
||||||
|
and the `CourseMapper` interface. Each repository interface carries a
|
||||||
|
`//go:generate mockery ...` directive. Params/results are plain structs.
|
||||||
|
- **`app/`** — Use-case handlers. `app.go` defines `Application{ Commands,
|
||||||
|
Queries }`. Commands (`app/command/`) mutate state; queries (`app/query/`)
|
||||||
|
read and project. Each handler is a private struct exposed via a
|
||||||
|
`NewXxxHandler` constructor that returns a decorated
|
||||||
|
`decorator.CommandHandler[T]` / `decorator.QueryHandler[Q, U]`.
|
||||||
|
- **`adapters/`** — Implementations of `domain` interfaces. SQLite is the
|
||||||
|
active engine; `sqlite_connection.go` opens the DB and runs migrations.
|
||||||
|
`memory_mapper.go` holds dictionary name/id maps and aggregate counts.
|
||||||
|
- **`ports/`** — Inbound transports. `ports/http/server.go` renders with templ
|
||||||
|
templates and normalizes errors to HTTP status codes. `ports/background.go`
|
||||||
|
wraps `robfig/cron/v3`.
|
||||||
|
- **`service/`** — `NewApplication` is the composition root: picks the DB
|
||||||
|
engine, builds repositories, and constructs all commands/queries.
|
||||||
|
|
||||||
## Directory Structure
|
### `internal/common/` utility packages
|
||||||
|
|
||||||
```
|
| Package | Role |
|
||||||
.
|
| ------------ | ------------------------------------------------------------------------------------ |
|
||||||
├── kurious.go # Root package: version/commit/buildTime getters
|
| `config` | JSON config structs (`Log`, `HTTP`, `Sqlite`, `YDB`, `Trace`) + `NewSLogger` factory |
|
||||||
├── Taskfile.yml # Build, test, lint, generate, run task definitions
|
| `errors` | Sentinel errors (`ErrNotFound`, `ErrNotImplemented`, `ErrUnexpectedStatus` as `SimpleError`) and `ValidationError` |
|
||||||
├── .mockery.yaml # mockery config (with-expecter, keeptree)
|
| `decorator` | CQRS decorators adding slog logging + OpenTelemetry tracing around every handler |
|
||||||
├── go.mod / go.sum
|
| `xcontext` | Context-aware structured logging (`LogInfo/Debug/Error/...`) carrying request id + log fields |
|
||||||
├── cmd/ # Entry points (one package per binary)
|
| `xlog` | Log level/format enums + slog adapters (e.g. cron logger bridge) |
|
||||||
│ ├── kuriweb/ # Main HTTP web server (config.go, main.go, http.go, trace.go)
|
| `nullable` | Generic `nullable.Value[T]` for optional fields |
|
||||||
│ ├── background/ # Background sync process (cron-driven sravni sync)
|
| `xslices` | Generic slice helpers (`Map`, ...) |
|
||||||
│ └── dev/sravnicli/ # Developer CLI for inspecting the sravni source
|
| `generator` | ID generation (e.g. `RandomInt64ID` for request ids) |
|
||||||
├── internal/
|
| `client/sravni` | HTTP client for sravni.ru (resty), parses `__NEXT_DATA__` redux state, rate-limited |
|
||||||
│ ├── kurious/ # Application core (the hexagon)
|
| `xdefault` (pkg) | `WithFallback(value, default)` helper |
|
||||||
│ │ ├── domain/ # Entities + repository interface ports
|
|
||||||
│ │ ├── app/
|
|
||||||
│ │ │ ├── app.go # Application{Commands, Queries} aggregate
|
|
||||||
│ │ │ ├── command/ # Write-side handlers (Create, Delete, Update...)
|
|
||||||
│ │ │ └── query/ # Read-side handlers (List, Get, Stats...)
|
|
||||||
│ │ ├── adapters/ # Repository implementations + mocks/
|
|
||||||
│ │ ├── ports/
|
|
||||||
│ │ │ ├── http/ # HTTP server, course routes
|
|
||||||
│ │ │ │ └── bootstrap/ # templ templates (.templ) + generated _templ.go
|
|
||||||
│ │ │ ├── background/ # Cron job handlers
|
|
||||||
│ │ │ ├── background.go # BackgroundProcess (cron scheduler)
|
|
||||||
│ │ │ └── services.go # Services{HTTP, Background} aggregate
|
|
||||||
│ │ └── service/ # Composition root: NewApplication wiring
|
|
||||||
│ └── common/ # Shared, reusable utilities
|
|
||||||
│ ├── client/sravni/ # sravni.ru HTTP client + mocks/
|
|
||||||
│ ├── config/ # Config structs (HTTP, Log, Sqlite, Trace, YDB, Duration)
|
|
||||||
│ ├── decorator/ # Command/Query handler interfaces + logging decorators
|
|
||||||
│ ├── errors/ # SimpleError, ValidationError, sentinel errors
|
|
||||||
│ ├── generator/ # ID generators
|
|
||||||
│ ├── nullable/ # Generic nullable Value[T]
|
|
||||||
│ ├── xcontext/ # context helpers (request id, log fields)
|
|
||||||
│ ├── xlog/ # slog + cron logger adapters
|
|
||||||
│ └── xslices/ # slice helpers (Map, Filter, ForEach, LRU)
|
|
||||||
├── pkg/
|
|
||||||
│ └── xdefault/ # WithFallback helper (public-ish pkg)
|
|
||||||
├── migrations/
|
|
||||||
│ └── sqlite/ # SQL migrations (embed.FS) + migrator.go
|
|
||||||
├── assets/kurious/static/ # Static web assets (embedded via go:embed)
|
|
||||||
└── htmlexamples/ # Standalone HTML/templ prototyping examples
|
|
||||||
```
|
|
||||||
|
|
||||||
## Build, Test, and Lint Commands
|
## Build & test commands
|
||||||
|
|
||||||
All operations are driven by **Taskfile** (`task <name>`). The toolchain is
|
The project uses [Task](https://taskfile.dev) (`Taskfile.yml`). Install tools
|
||||||
installed into a local `bin/` (`GOBIN={{.USER_WORKING_DIR}}/bin`) and
|
first with `task install_tools` (installs `golangci-lint`, `templ`, `mockery`
|
||||||
`CGO_ENABLED=0` is enforced.
|
into `./bin`).
|
||||||
|
|
||||||
| Command | What it does |
|
| Task | What it does |
|
||||||
|--------------------------|--------------------------------------------------------------------|
|
| ----------------------- | ------------------------------------------------------------------ |
|
||||||
| `task install_tools` | Install `golangci-lint`, `templ`, `mockery` into `bin/` |
|
| `task install_tools` | Install dev tools into `./bin` |
|
||||||
| `task generate` | Run `templ generate` (compiles `.templ` → `_templ.go`) |
|
| `task generate` | Run `templ generate` for `*.templ` sources (run before build/test) |
|
||||||
| `task mocks` | Run `go generate ./internal/...` (regenerate mockery mocks) |
|
| `task mocks` | `go generate ./internal/...` (regenerate mockery mocks) |
|
||||||
| `task check` | Run `golangci-lint run ./...` (depends on `generate`) |
|
| `task check` | `golangci-lint run ./...` (depends on `generate`) |
|
||||||
| `task test` | Run `go test ./internal/...` (depends on `generate`) |
|
| `task test` | `go test ./internal/...` (depends on `generate`) |
|
||||||
| `task build_web` | Build `bin/kuriousweb` (depends on `check` + `test`) |
|
| `task build_web` | Build `kuriousweb` (depends on `check`, `test`) |
|
||||||
| `task build_background` | Build `bin/kuriousbg` (depends on `check` + `test`) |
|
| `task build_background` | Build `kuriousbg` (depends on `check`, `test`) |
|
||||||
| `task build_dev_cli` | Build `bin/sravnicli` (depends on `check` + `test`) |
|
| `task build_dev_cli` | Build `sravnicli` (depends on `check`, `test`) |
|
||||||
| `task build` | Build all three binaries |
|
| `task build` | Build all three binaries |
|
||||||
| `task run` | Build then run `bin/kuriousweb` |
|
| `task run` | Build then run `kuriousweb` |
|
||||||
|
|
||||||
Typical workflow before committing: `task check && task test`.
|
Plain Go equivalents (use when Task is unavailable):
|
||||||
|
|
||||||
### Running the binaries
|
|
||||||
|
|
||||||
Binaries read a JSON config file path as their first argument, defaulting to
|
|
||||||
`config.json` (note: `*.json` is gitignored, so configs are local). Example
|
|
||||||
fields: `log`, `sqlite`, `http.listen_addr`, `db_engine`, `tracing`.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./bin/kuriousweb path/to/config.json
|
go generate ./internal/... # regenerate mocks
|
||||||
|
templ generate # render .templ -> .go
|
||||||
|
golangci-lint run ./... # lint
|
||||||
|
go test ./... # run all tests
|
||||||
|
go build -o bin/kuriousweb ./cmd/kuriweb # build a binary
|
||||||
```
|
```
|
||||||
|
|
||||||
## Code Conventions
|
> Note: `templ generate` must run before `go build`/`go test` whenever a
|
||||||
|
> `*.templ` file changes — the generated `*_templ.go` files are committed-free
|
||||||
|
> and required for compilation.
|
||||||
|
|
||||||
### Decorators / handler pattern
|
## Code conventions
|
||||||
|
|
||||||
Command and query handlers implement generic interfaces and are wrapped with
|
|
||||||
logging decorators at construction time. When adding a new use case:
|
|
||||||
|
|
||||||
1. Define the command/query struct and a `*Handler` type alias of
|
|
||||||
`decorator.CommandHandler[T]` / `decorator.QueryHandler[Q, U]` in
|
|
||||||
`app/command/` or `app/query/`.
|
|
||||||
2. Implement a private `*Handler` struct holding its repository dependencies.
|
|
||||||
3. Expose a `New*Handler(deps..., log *slog.Logger)` constructor that returns
|
|
||||||
the decorated handler (`decorator.ApplyCommandDecorators` /
|
|
||||||
`decorator.AddQueryDecorators`).
|
|
||||||
4. Register the new handler on `app.Commands` / `app.Queries` in
|
|
||||||
`app/app.go` and wire it in `service/service.go`.
|
|
||||||
|
|
||||||
### Mock generation (mockery)
|
|
||||||
|
|
||||||
- Interfaces marked with `//go:generate mockery ...` directives (see
|
|
||||||
`domain/repository.go`, `common/client/sravni/client.go`) are mocked into
|
|
||||||
sibling `mocks/` packages (`keeptree: True`, `with-expecter: true`).
|
|
||||||
- Regenerate with `task mocks` (runs `go generate ./internal/...`).
|
|
||||||
- Mocks are committed to the repo.
|
|
||||||
|
|
||||||
### Templating (templ)
|
|
||||||
|
|
||||||
- HTML is authored as `.templ` files under
|
|
||||||
`internal/kurious/ports/http/bootstrap/`.
|
|
||||||
- `task generate` compiles them to `*_templ.go` (committed). Run it whenever a
|
|
||||||
`.templ` file changes; `task check` and `task test` both depend on it.
|
|
||||||
|
|
||||||
### Database / migrations
|
|
||||||
|
|
||||||
- SQLite migrations live in `migrations/sqlite/*.sql` and are embedded via
|
|
||||||
`go:embed`. The migrator (`migrations/sqlite/migrator.go`) applies them in
|
|
||||||
order inside a transaction.
|
|
||||||
- Repository adapters use `sqlx` named queries; domain ↔ row translation is
|
|
||||||
centralized via `AsDomain()` methods.
|
|
||||||
|
|
||||||
### Logging & observability
|
|
||||||
|
|
||||||
- Use `log/slog` with structured attributes. Request-scoped fields (e.g.
|
|
||||||
`request_id`) are propagated through `context` via `internal/common/xcontext`.
|
|
||||||
- HTTP handlers wrap requests in trace spans and record metrics
|
|
||||||
(request duration histogram). Database adapters emit spans tagged with
|
|
||||||
`db.*` attributes.
|
|
||||||
|
|
||||||
### Error handling
|
### Error handling
|
||||||
|
|
||||||
- Domain/repository errors use sentinels from `internal/common/errors`
|
- Wrap errors with context using `fmt.Errorf("<action>: %w", err)`. Preserve
|
||||||
(`ErrNotFound`, `ErrNotImplemented`) and `*ValidationError` (mapped to HTTP
|
the chain so callers can `errors.Is` / `errors.As`.
|
||||||
400/404 in `ports/http/server.go`).
|
- Use the sentinels in `internal/common/errors/error.go`:
|
||||||
- Wrap errors with `fmt.Errorf("doing X: %w", err)` to add context while
|
- `errors.ErrNotFound` / `errors.ErrNotImplemented` / `errors.ErrUnexpectedStatus`
|
||||||
preserving the underlying error for `errors.Is` / `errors.As`.
|
(these are `SimpleError`, a string-backed error type).
|
||||||
|
- `errors.NewValidationError(field, reason)` for invalid input.
|
||||||
|
- The HTTP layer (`ports/http/server.go::handleError`) maps these to status
|
||||||
|
codes: `ValidationError` → 400, `ErrNotFound` → 404, anything else → 500
|
||||||
|
(with a generic message, never leaking internals).
|
||||||
|
- Repository `Get` methods contractually return `ErrNotFound` when a row is
|
||||||
|
missing — honor this in new adapters.
|
||||||
|
|
||||||
## Testing Patterns
|
### Logging
|
||||||
|
|
||||||
- **Scope:** unit tests live next to the code they test
|
- Use `log/slog` (structured), never `fmt.Println` in library code.
|
||||||
(`*_test.go`). `task test` runs `go test ./internal/...`.
|
- Prefer the `internal/common/xcontext` helpers (`LogInfo`, `LogDebug`,
|
||||||
- **Framework:** `github.com/stretchr/testify` — `require` for fatal
|
`LogError`, `LogWithError`, `LogWithWarnError`) over raw `log.InfoContext`,
|
||||||
assertions, `assert` for non-fatal, `mock` for mock interactions.
|
because they automatically attach context-scoped fields (e.g. `request_id`,
|
||||||
- **Mocks:** generated mockery mocks with the **expecter** API:
|
`handler`).
|
||||||
```go
|
- Create loggers via `config.NewSLogger(cfg.Log)` and tag components with
|
||||||
repo.EXPECT().Create(mock.Anything, expectedParams).
|
`log.With(slog.String("component", "..."))`.
|
||||||
Return(domain.Course{ID: "c1"}, nil).Once()
|
- In tests, use a discard logger: `slog.New(slog.NewTextHandler(io.Discard, nil))`.
|
||||||
```
|
|
||||||
Note: when the generated mock does not yet implement every interface method,
|
|
||||||
tests embed the mock and add the missing methods (see the `fullRepo` pattern
|
|
||||||
in `internal/kurious/app/command/command_test.go`).
|
|
||||||
- **Logger:** tests use a `quietLogger()` helper that discards output
|
|
||||||
(`slog.New(slog.NewTextHandler(io.Discard, nil))`).
|
|
||||||
- **Adapter tests:** `internal/kurious/adapters/sqlite_*_test.go` exercise the
|
|
||||||
real SQLite repositories against an in-memory/temp database.
|
|
||||||
- **Conventions:** table-driven where appropriate; use `context.Background()`
|
|
||||||
in tests; assert on wrapped errors with `assert.ErrorIs` and message
|
|
||||||
fragments with `assert.Contains`.
|
|
||||||
|
|
||||||
## Notes for Agents
|
### CQRS & handlers
|
||||||
|
|
||||||
- Run `task generate` before linting/testing if you touched any `.templ` file.
|
- Every command/query handler is wrapped at construction time by
|
||||||
- Do not re-introduce YDB as a working engine without updating
|
`decorator.ApplyCommandDecorators` / `decorator.AddQueryDecorators`. The
|
||||||
`service.NewApplication` and the migration story (currently SQLite-only).
|
decorator adds a tracing span and start/finish log lines — **do not** add
|
||||||
- Generated files (`*_templ.go`, `mocks/*.go`) are committed — regenerate and
|
your own top-level logging inside `Handle`; rely on the decorator.
|
||||||
commit them alongside source changes.
|
- Handler signature pattern:
|
||||||
- `*.json`, `*.sqlite`, `bin/`, and `*.log` are gitignored; do not commit
|
- command: `Handle(ctx context.Context, cmd T) error`
|
||||||
local configs or databases.
|
- query: `Handle(ctx context.Context, q Q) (U, error)`
|
||||||
|
- Keep handlers thin: translate the command/query into domain params, call the
|
||||||
|
repository, and map results. Put business types in `domain/`.
|
||||||
|
|
||||||
|
### Naming & structure
|
||||||
|
|
||||||
|
- Constructors are `NewXxx`. Unexported handler struct, exported aliased type
|
||||||
|
(`decorator.CommandHandler[T]` / `decorator.QueryHandler[Q, U]`).
|
||||||
|
- Nullable fields use `nullable.Value[T]` rather than pointers.
|
||||||
|
- Exported interfaces that external code might mock get a
|
||||||
|
`//go:generate mockery --name <Interface> --output ../adapters/mocks` line
|
||||||
|
directly above the interface declaration.
|
||||||
|
|
||||||
|
### Tracing & metrics
|
||||||
|
|
||||||
|
- OpenTelemetry is wired throughout (`cmd/*/trace.go` sets up the SDK).
|
||||||
|
- DB adapters use the `adapters.db` tracer; CQRS decorators use the `api`
|
||||||
|
tracer; the HTTP layer uses the `web` tracer. Record errors on spans with
|
||||||
|
`span.RecordError(err)` and set `codes.Error` status.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
- Framework: `github.com/stretchr/testify` (`suite`, `assert`, `require`,
|
||||||
|
`mock`). Mocks are generated by mockery into `internal/kurious/adapters/mocks`
|
||||||
|
and `internal/common/client/sravni/mocks`.
|
||||||
|
- SQLite adapter tests (`internal/kurious/adapters/*_test.go`) extend
|
||||||
|
`sqliteBaseSuite`, which spins up an in-memory (`:memory:`) SQLite DB and
|
||||||
|
applies the real migrations. `TearDownTest` clears tables between cases.
|
||||||
|
- Command/query tests use mockery mocks and a discard logger.
|
||||||
|
- After changing interfaces, regenerate mocks: `go generate ./internal/...`
|
||||||
|
(or `task mocks`).
|
||||||
|
|
||||||
|
## Key dependencies
|
||||||
|
|
||||||
|
| Dependency | Role |
|
||||||
|
| --------------------------------- | ------------------------------------------------------------- |
|
||||||
|
| `github.com/gorilla/mux` | HTTP routing & middleware |
|
||||||
|
| `github.com/a-h/templ` | Type-safe HTML templates (`*.templ`) |
|
||||||
|
| `github.com/jmoiron/sqlx` | Ergonomic SQL layer over `database/sql` |
|
||||||
|
| `modernc.org/sqlite` | Pure-Go (CGO-free) SQLite driver |
|
||||||
|
| `github.com/robfig/cron/v3` | Cron scheduler for the background sync |
|
||||||
|
| `github.com/go-resty/resty/v2` | HTTP client for the sravni.ru API |
|
||||||
|
| `golang.org/x/net/html` | HTML parsing of sravni.ru `__NEXT_DATA__` redux state |
|
||||||
|
| `golang.org/x/time/rate` | Rate limiting the sravni.ru client |
|
||||||
|
| `golang.org/x/sync` | `errgroup` for goroutine lifecycle |
|
||||||
|
| `github.com/teris-io/cli` | CLI framework for `sravnicli` |
|
||||||
|
| `go.opentelemetry.io/otel` (+ exporters) | Tracing & metrics (OTLP gRPC/HTTP, stdout) |
|
||||||
|
| `github.com/stretchr/testify` | Test assertions, suites, and mocks |
|
||||||
|
| `github.com/ydb-platform/ydb-go-sdk/v3` | YDB SDK — **deprecated**, `NewApplication` returns an error for the `ydb` engine |
|
||||||
|
|
||||||
|
## Gotchas
|
||||||
|
|
||||||
|
- `*.json` is gitignored (configs contain local settings). Do not commit
|
||||||
|
config files; document config shape in `cmd/<binary>/config.go` instead.
|
||||||
|
- The `background` binary currently panics on start
|
||||||
|
(`savingOrganizationIDInternalInsteadOfExternal` guard) until the
|
||||||
|
organization-id saving semantics are fixed.
|
||||||
|
- Templ-generated files are not committed; always run `templ generate` (or
|
||||||
|
`task generate`) after pulling or before building/testing.
|
||||||
|
- The YDB engine path is dead code kept for reference — do not extend it; add
|
||||||
|
new storage work to the SQLite adapters.
|
||||||
|
|||||||
55
Dockerfile
55
Dockerfile
@ -1,55 +0,0 @@
|
|||||||
# syntax=docker/dockerfile:1
|
|
||||||
|
|
||||||
# ---- Build stage ----
|
|
||||||
FROM golang:1.26-alpine AS builder
|
|
||||||
|
|
||||||
ENV CGO_ENABLED=0 GOOS=linux
|
|
||||||
|
|
||||||
ARG VERSION=docker
|
|
||||||
ARG COMMIT=docker
|
|
||||||
ARG BUILD_TIME=unknown
|
|
||||||
ARG PROJECT=git.loyso.art/frx/kurious
|
|
||||||
|
|
||||||
WORKDIR /src
|
|
||||||
|
|
||||||
# Cache module downloads.
|
|
||||||
COPY go.mod go.sum ./
|
|
||||||
RUN go mod download
|
|
||||||
|
|
||||||
# Copy the rest of the source.
|
|
||||||
# Generated files (templ *_templ.go, mockery mocks) are committed, so no
|
|
||||||
# generation step is required here.
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Build the web server and the healthcheck probe.
|
|
||||||
RUN go build -trimpath \
|
|
||||||
-ldflags "-X ${PROJECT}.version=${VERSION} -X ${PROJECT}.commit=${COMMIT} -X ${PROJECT}.buildTime=${BUILD_TIME}" \
|
|
||||||
-o /out/kuriweb ./cmd/kuriweb \
|
|
||||||
&& go build -trimpath -o /out/healthcheck ./cmd/healthcheck
|
|
||||||
|
|
||||||
# Bake a default config into the image (config files are gitignored locally,
|
|
||||||
# so the image must be self-contained).
|
|
||||||
RUN echo '{"log":{"level":"info","format":"json"},"http":{"listen_addr":":8080","mount_live":false},"sqlite":{"dsn":"/tmp/kurious.sqlite","shutdown_timeout":"10s"},"db_engine":"sqlite","tracing":{"type":"stdout","show_metrics":false}}' > /out/config.json
|
|
||||||
|
|
||||||
# ---- Final stage ----
|
|
||||||
FROM gcr.io/distroless/static-debian12
|
|
||||||
|
|
||||||
LABEL org.opencontainers.image.title="kuriousweb" \
|
|
||||||
org.opencontainers.image.source="git.loyso.art/frx/kurious"
|
|
||||||
|
|
||||||
COPY --from=builder /out/kuriweb /kuriweb
|
|
||||||
COPY --from=builder /out/healthcheck /healthcheck
|
|
||||||
COPY --from=builder /out/config.json /etc/kurious/config.json
|
|
||||||
|
|
||||||
# static-debian12 ships a "nonroot" user (uid 65532).
|
|
||||||
USER nonroot:nonroot
|
|
||||||
|
|
||||||
EXPOSE 8080
|
|
||||||
|
|
||||||
ENTRYPOINT ["/kuriweb"]
|
|
||||||
CMD ["/etc/kurious/config.json"]
|
|
||||||
|
|
||||||
# Distroless static has no shell/curl, so probing is done via the tiny
|
|
||||||
# healthcheck binary built above.
|
|
||||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
||||||
CMD ["/healthcheck", "http://127.0.0.1:8080/healthz"]
|
|
||||||
10
Taskfile.yml
10
Taskfile.yml
@ -67,16 +67,6 @@ tasks:
|
|||||||
- task: build_background
|
- task: build_background
|
||||||
- task: build_web
|
- task: build_web
|
||||||
|
|
||||||
build_docker:
|
|
||||||
desc: "Build the kuriousweb Docker image locally (no push)"
|
|
||||||
cmds:
|
|
||||||
- >-
|
|
||||||
docker build
|
|
||||||
--build-arg VERSION={{.GIT_VERSION}}
|
|
||||||
--build-arg COMMIT={{.GIT_COMMIT}}
|
|
||||||
--build-arg BUILD_TIME={{.BUILD_TIME}}
|
|
||||||
-t kuriousweb .
|
|
||||||
|
|
||||||
run:
|
run:
|
||||||
deps: [build]
|
deps: [build]
|
||||||
cmds:
|
cmds:
|
||||||
|
|||||||
@ -1,28 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
url := "http://127.0.0.1:8080/healthz"
|
|
||||||
if len(os.Args) > 1 {
|
|
||||||
url = os.Args[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
client := &http.Client{Timeout: 3 * time.Second}
|
|
||||||
resp, err := client.Get(url)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "healthcheck error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
defer func() { _ = resp.Body.Close() }()
|
|
||||||
|
|
||||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
|
||||||
fmt.Fprintf(os.Stderr, "healthcheck failed: status %s\n", resp.Status)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -63,11 +63,6 @@ func setupHTTP(cfg config.HTTP, srv xhttp.Server, log *slog.Logger) *http.Server
|
|||||||
middlewareMetrics(),
|
middlewareMetrics(),
|
||||||
)
|
)
|
||||||
|
|
||||||
router.HandleFunc("/healthz", func(w http.ResponseWriter, _ *http.Request) {
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
_, _ = w.Write([]byte("ok"))
|
|
||||||
}).Methods(http.MethodGet)
|
|
||||||
|
|
||||||
setupCoursesHTTP(srv, router, log)
|
setupCoursesHTTP(srv, router, log)
|
||||||
|
|
||||||
if cfg.MountLive {
|
if cfg.MountLive {
|
||||||
|
|||||||
12
go.mod
12
go.mod
@ -5,12 +5,12 @@ go 1.26.0
|
|||||||
toolchain go1.26.4
|
toolchain go1.26.4
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/a-h/templ v0.3.1020
|
github.com/a-h/templ v0.2.707
|
||||||
github.com/go-resty/resty/v2 v2.13.1
|
github.com/go-resty/resty/v2 v2.13.1
|
||||||
github.com/gorilla/mux v1.8.1
|
github.com/gorilla/mux v1.8.1
|
||||||
github.com/jmoiron/sqlx v1.4.0
|
github.com/jmoiron/sqlx v1.4.0
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.9.0
|
||||||
github.com/teris-io/cli v1.0.1
|
github.com/teris-io/cli v1.0.1
|
||||||
github.com/ydb-platform/ydb-go-sdk/v3 v3.74.3
|
github.com/ydb-platform/ydb-go-sdk/v3 v3.74.3
|
||||||
github.com/ydb-platform/ydb-go-yc v0.12.1
|
github.com/ydb-platform/ydb-go-yc v0.12.1
|
||||||
@ -25,8 +25,8 @@ require (
|
|||||||
go.opentelemetry.io/otel/sdk v1.30.0
|
go.opentelemetry.io/otel/sdk v1.30.0
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.30.0
|
go.opentelemetry.io/otel/sdk/metric v1.30.0
|
||||||
go.opentelemetry.io/otel/trace v1.30.0
|
go.opentelemetry.io/otel/trace v1.30.0
|
||||||
golang.org/x/net v0.51.0
|
golang.org/x/net v0.29.0
|
||||||
golang.org/x/sync v0.19.0
|
golang.org/x/sync v0.8.0
|
||||||
golang.org/x/time v0.5.0
|
golang.org/x/time v0.5.0
|
||||||
google.golang.org/grpc v1.66.1
|
google.golang.org/grpc v1.66.1
|
||||||
modernc.org/sqlite v1.30.1
|
modernc.org/sqlite v1.30.1
|
||||||
@ -52,8 +52,8 @@ require (
|
|||||||
github.com/ydb-platform/ydb-go-genproto v0.0.0-20240528144234-5d5a685e41f7 // indirect
|
github.com/ydb-platform/ydb-go-genproto v0.0.0-20240528144234-5d5a685e41f7 // indirect
|
||||||
github.com/ydb-platform/ydb-go-yc-metadata v0.6.1 // indirect
|
github.com/ydb-platform/ydb-go-yc-metadata v0.6.1 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
||||||
golang.org/x/sys v0.41.0 // indirect
|
golang.org/x/sys v0.25.0 // indirect
|
||||||
golang.org/x/text v0.34.0 // indirect
|
golang.org/x/text v0.18.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||||
google.golang.org/protobuf v1.34.2 // indirect
|
google.golang.org/protobuf v1.34.2 // indirect
|
||||||
|
|||||||
32
go.sum
32
go.sum
@ -517,8 +517,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
|||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
|
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
github.com/a-h/templ v0.3.1020 h1:ypAT/L5ySWEnZ6Zft/5yfoWXYYkhFNvEFOeeqecg4tw=
|
github.com/a-h/templ v0.2.707 h1:T1Gkd2ugbRglZ9rYw/VBchWOSZVKmetDbBkm4YubM7U=
|
||||||
github.com/a-h/templ v0.3.1020/go.mod h1:A2DlK61v+K+NRoGnhmYbNYVmtYHcFO5/AisMvBdDxTM=
|
github.com/a-h/templ v0.2.707/go.mod h1:5cqsugkq9IerRNucNsI4DEamdHPsoGMQy99DzydLhM8=
|
||||||
github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY=
|
github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY=
|
||||||
github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk=
|
github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk=
|
||||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||||
@ -808,8 +808,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/teris-io/cli v1.0.1 h1:J6jnVHC552uqx7zT+Ux0++tIvLmJQULqxVhCid2u/Gk=
|
github.com/teris-io/cli v1.0.1 h1:J6jnVHC552uqx7zT+Ux0++tIvLmJQULqxVhCid2u/Gk=
|
||||||
github.com/teris-io/cli v1.0.1/go.mod h1:V9nVD5aZ873RU/tQXLSXO8FieVPQhQvuNohsdsKXsGw=
|
github.com/teris-io/cli v1.0.1/go.mod h1:V9nVD5aZ873RU/tQXLSXO8FieVPQhQvuNohsdsKXsGw=
|
||||||
github.com/yandex-cloud/go-genproto v0.0.0-20211115083454-9ca41db5ed9e/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE=
|
github.com/yandex-cloud/go-genproto v0.0.0-20211115083454-9ca41db5ed9e/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE=
|
||||||
@ -943,8 +943,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
|
|||||||
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
|
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||||
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
|
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@ -1004,8 +1004,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
|||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||||
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
|
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
||||||
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
|
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@ -1050,8 +1050,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -1131,8 +1131,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||||
@ -1161,8 +1161,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
|||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
@ -1231,8 +1231,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
|||||||
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
|
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||||
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
|
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
|
||||||
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
|
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,27 +1,21 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
// Code generated by templ - DO NOT EDIT.
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
// templ: version: v0.2.707
|
||||||
package bootstrap
|
package bootstrap
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
import "github.com/a-h/templ"
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
import "context"
|
||||||
|
import "io"
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
func button(title string, attributes templ.Attributes) templ.Component {
|
func button(title string, attributes templ.Attributes) templ.Component {
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
defer func() {
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
ctx = templ.InitializeContext(ctx)
|
ctx = templ.InitializeContext(ctx)
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||||
@ -29,7 +23,7 @@ func button(title string, attributes templ.Attributes) templ.Component {
|
|||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<button class=\"button\"")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<button class=\"button\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -37,7 +31,7 @@ func button(title string, attributes templ.Attributes) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, ">")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -50,28 +44,23 @@ func button(title string, attributes templ.Attributes) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</button>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</button>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
return nil
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func buttonRedirect(id, title string, linkTo string) templ.Component {
|
func buttonRedirect(id, title string, linkTo string) templ.Component {
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
defer func() {
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
ctx = templ.InitializeContext(ctx)
|
ctx = templ.InitializeContext(ctx)
|
||||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||||
@ -79,20 +68,20 @@ func buttonRedirect(id, title string, linkTo string) templ.Component {
|
|||||||
templ_7745c5c3_Var3 = templ.NopComponent
|
templ_7745c5c3_Var3 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<button class=\"button\" id=\"")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<button class=\"button\" id=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var4 string
|
var templ_7745c5c3_Var4 string
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.ResolveAttributeValue("origin-link-" + id)
|
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs("origin-link-" + id)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/common.templ`, Line: 10, Col: 26}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/common.templ`, Line: 10, Col: 26}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4)
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -105,7 +94,7 @@ func buttonRedirect(id, title string, linkTo string) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</button>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</button>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -113,7 +102,10 @@ func buttonRedirect(id, title string, linkTo string) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
return nil
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,5 +120,3 @@ func onclickRedirect(id, to string) templ.ComponentScript {
|
|||||||
CallInline: templ.SafeScriptInline(`__templ_onclickRedirect_5c43`, id, to),
|
CallInline: templ.SafeScriptInline(`__templ_onclickRedirect_5c43`, id, to),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
|
|||||||
@ -158,44 +158,6 @@ script elementScriptsLoad() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildFilterParams = () => {
|
|
||||||
const params = [];
|
|
||||||
const school_selector = document.getElementById('schoolSelect');
|
|
||||||
if (school_selector && school_selector.value) {
|
|
||||||
params.push('school_id=' + school_selector.value);
|
|
||||||
}
|
|
||||||
const order_by = document.getElementById('sortBySelect');
|
|
||||||
if (order_by && order_by.value) {
|
|
||||||
params.push('order_by=' + order_by.value);
|
|
||||||
}
|
|
||||||
const ascending = document.getElementById('sortByOrder');
|
|
||||||
if (ascending && ascending.checked) {
|
|
||||||
params.push('asc=true');
|
|
||||||
}
|
|
||||||
return params.join('&');
|
|
||||||
};
|
|
||||||
|
|
||||||
const setupPaginationLinks = () => {
|
|
||||||
document.querySelectorAll('a.page-link').forEach(link => {
|
|
||||||
link.addEventListener('click', (e) => {
|
|
||||||
const nav = link.closest('nav[data-paginated]');
|
|
||||||
if (!nav) return;
|
|
||||||
e.preventDefault();
|
|
||||||
const baseUrl = nav.getAttribute('data-base-url');
|
|
||||||
const href = link.getAttribute('href');
|
|
||||||
const pageMatch = href.match(/[?&]page=(\d+)/);
|
|
||||||
if (!pageMatch) return;
|
|
||||||
const page = pageMatch[1];
|
|
||||||
const filterParams = buildFilterParams();
|
|
||||||
let url = baseUrl + '?page=' + page;
|
|
||||||
if (filterParams) {
|
|
||||||
url += '&' + filterParams;
|
|
||||||
}
|
|
||||||
window.location.assign(url);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const formFilterOnSubmit = event => {
|
const formFilterOnSubmit = event => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
@ -218,6 +180,7 @@ script elementScriptsLoad() {
|
|||||||
const order_by = document.getElementById('sortBySelect');
|
const order_by = document.getElementById('sortBySelect');
|
||||||
const order_by_value = (order_by !== null && order_by.value !== '') ? order_by.value : '';
|
const order_by_value = (order_by !== null && order_by.value !== '') ? order_by.value : '';
|
||||||
const ascending = document.getElementById('sortByOrder');
|
const ascending = document.getElementById('sortByOrder');
|
||||||
|
|
||||||
const baseUrl = `${window.location.pathname}?`;
|
const baseUrl = `${window.location.pathname}?`;
|
||||||
|
|
||||||
params = [];
|
params = [];
|
||||||
@ -254,8 +217,6 @@ script elementScriptsLoad() {
|
|||||||
|
|
||||||
const ob = document.getElementById('sortBySelect');
|
const ob = document.getElementById('sortBySelect');
|
||||||
if (ob) ob.onchange = filterBySchool;
|
if (ob) ob.onchange = filterBySchool;
|
||||||
|
|
||||||
setupPaginationLinks();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,27 +1,21 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
// Code generated by templ - DO NOT EDIT.
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
// templ: version: v0.2.707
|
||||||
package bootstrap
|
package bootstrap
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
import "github.com/a-h/templ"
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
import "context"
|
||||||
|
import "io"
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
func head(title string) templ.Component {
|
func head(title string) templ.Component {
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
defer func() {
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
ctx = templ.InitializeContext(ctx)
|
ctx = templ.InitializeContext(ctx)
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||||
@ -29,7 +23,7 @@ func head(title string) templ.Component {
|
|||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<head><title>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<head><title>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -42,28 +36,23 @@ func head(title string) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN\" crossorigin=\"anonymous\"><link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css\"><script src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js\" integrity=\"sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL\" crossorigin=\"anonymous\">\n\t\t</script></head>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</title><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN\" crossorigin=\"anonymous\"><link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css\"><script src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js\" integrity=\"sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL\" crossorigin=\"anonymous\">\n\t\t</script></head>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
return nil
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func headerNavbar(page PageKind) templ.Component {
|
func headerNavbar(page PageKind) templ.Component {
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
defer func() {
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
ctx = templ.InitializeContext(ctx)
|
ctx = templ.InitializeContext(ctx)
|
||||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||||
@ -71,7 +60,7 @@ func headerNavbar(page PageKind) templ.Component {
|
|||||||
templ_7745c5c3_Var3 = templ.NopComponent
|
templ_7745c5c3_Var3 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<header><nav class=\"navbar navbar-expand-lg bg-body-tertiary w-auto\"><div class=\"container-fluid\"><a class=\"navbar-brand\" href=\"/htmlexamples/index.html\">Kurious</a> <button class=\"navbar-toggler\" type=\"button\" data-bs-toggle=\"collapse\" data-bs-target=\"#navbarSupportedContent\" aria-controls=\"navbarSupportedContent\" aria-expanded=\"false\" aria-label=\"Toggle navigation\"><span class=\"navbar-toggler-icon\"></span></button><div class=\"collapse navbar-collapse\" id=\"navbarSupportedContent\"><ul class=\"navbar-nav me-auto mb-2 mb-lg-0\"><li class=\"nav-item\">")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<header><nav class=\"navbar navbar-expand-lg bg-body-tertiary w-auto\"><div class=\"container-fluid\"><a class=\"navbar-brand\" href=\"/htmlexamples/index.html\">Kurious</a> <button class=\"navbar-toggler\" type=\"button\" data-bs-toggle=\"collapse\" data-bs-target=\"#navbarSupportedContent\" aria-controls=\"navbarSupportedContent\" aria-expanded=\"false\" aria-label=\"Toggle navigation\"><span class=\"navbar-toggler-icon\"></span></button><div class=\"collapse navbar-collapse\" id=\"navbarSupportedContent\"><ul class=\"navbar-nav me-auto mb-2 mb-lg-0\"><li class=\"nav-item\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -80,20 +69,20 @@ func headerNavbar(page PageKind) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<a class=\"")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var5 string
|
var templ_7745c5c3_Var5 string
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var4).String())
|
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var4).String())
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/core.templ`, Line: 1, Col: 0}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/core.templ`, Line: 1, Col: 0}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var5)
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\" aria-current=\"page\" href=\"/\">Home</a></li><li class=\"nav-item\">")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" aria-current=\"page\" href=\"/\">Home</a></li><li class=\"nav-item\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -102,20 +91,20 @@ func headerNavbar(page PageKind) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<a class=\"")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var7 string
|
var templ_7745c5c3_Var7 string
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var6).String())
|
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var6).String())
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/core.templ`, Line: 1, Col: 0}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/core.templ`, Line: 1, Col: 0}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var7)
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\" aria-current=\"page\" href=\"/courses\">Courses</a></li><li class=\"nav-item\">")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" aria-current=\"page\" href=\"/courses\">Courses</a></li><li class=\"nav-item\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -124,41 +113,36 @@ func headerNavbar(page PageKind) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<a class=\"")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var9 string
|
var templ_7745c5c3_Var9 string
|
||||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var8).String())
|
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var8).String())
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/core.templ`, Line: 1, Col: 0}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/core.templ`, Line: 1, Col: 0}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9)
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\" href=\"/about\">About us</a></li></ul></div></div></nav></header>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" href=\"/about\">About us</a></li></ul></div></div></nav></header>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
return nil
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func footer() templ.Component {
|
func footer() templ.Component {
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
defer func() {
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
ctx = templ.InitializeContext(ctx)
|
ctx = templ.InitializeContext(ctx)
|
||||||
templ_7745c5c3_Var10 := templ.GetChildren(ctx)
|
templ_7745c5c3_Var10 := templ.GetChildren(ctx)
|
||||||
@ -166,18 +150,21 @@ func footer() templ.Component {
|
|||||||
templ_7745c5c3_Var10 = templ.NopComponent
|
templ_7745c5c3_Var10 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<footer class=\"text-center text-lg-start bg-body-tertiary text-muted\"><section class=\"p-2\"><div class=\"container text-center text-md-start mt-5\"><div class=\"row mt-3\"><div class=\"col-md-3 col-lg-4 col-xl-3 mx-auto mb-4\"><h6 class=\"text-uppercase fw-bold mb-4\"><i class=\"fas fa-gem me-3\"></i>Courses</h6><p>Welcome to Courses, your gateway to learning! Explore a diverse range of courses and advance your skills with us. Join our community and transform your life through education.</p></div><div class=\"col-md-3 col-lg-2 col-xl-2 mx-auto mb-4\"><h6 class=\"text-uppercase fw-bold mb-4\">Useful links</h6><p><a href=\"#!\" class=\"text-reset\">Pricing</a></p><p><a href=\"#!\" class=\"text-reset\">Settings</a></p><p><a href=\"#!\" class=\"text-reset\">Orders</a></p><p><a href=\"#!\" class=\"text-reset\">Help</a></p></div><div class=\"col-md-4 col-lg-3 col-xl-3 mx-auto mb-md-0 mb-4\"><h6 class=\"text-uppercase fw-bold mb-4\">Contact</h6><p><i class=\"fas fa-home me-3\"></i> New York, NY 10012, US</p><p><i class=\"fas fa-envelope me-3\"></i> info@example.com</p><p><i class=\"fas fa-phone me-3\"></i> + 01 234 567 88</p><p><i class=\"fas fa-print me-3\"></i> + 01 234 567 89</p></div></div></div></section><div class=\"text-center p-4\" style=\"background-color: rgba(0, 0, 0, 0.05)\">© 2024 Copyright: <a class=\"text-reset fw-bold\" href=\"https://mdbootstrap.com/\">kursov.net</a></div></footer>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<footer class=\"text-center text-lg-start bg-body-tertiary text-muted\"><section class=\"p-2\"><div class=\"container text-center text-md-start mt-5\"><div class=\"row mt-3\"><div class=\"col-md-3 col-lg-4 col-xl-3 mx-auto mb-4\"><h6 class=\"text-uppercase fw-bold mb-4\"><i class=\"fas fa-gem me-3\"></i>Courses</h6><p>Welcome to Courses, your gateway to learning! Explore a diverse range of courses and advance your skills with us. Join our community and transform your life through education.</p></div><div class=\"col-md-3 col-lg-2 col-xl-2 mx-auto mb-4\"><h6 class=\"text-uppercase fw-bold mb-4\">Useful links</h6><p><a href=\"#!\" class=\"text-reset\">Pricing</a></p><p><a href=\"#!\" class=\"text-reset\">Settings</a></p><p><a href=\"#!\" class=\"text-reset\">Orders</a></p><p><a href=\"#!\" class=\"text-reset\">Help</a></p></div><div class=\"col-md-4 col-lg-3 col-xl-3 mx-auto mb-md-0 mb-4\"><h6 class=\"text-uppercase fw-bold mb-4\">Contact</h6><p><i class=\"fas fa-home me-3\"></i> New York, NY 10012, US</p><p><i class=\"fas fa-envelope me-3\"></i> info@example.com</p><p><i class=\"fas fa-phone me-3\"></i> + 01 234 567 88</p><p><i class=\"fas fa-print me-3\"></i> + 01 234 567 89</p></div></div></div></section><div class=\"text-center p-4\" style=\"background-color: rgba(0, 0, 0, 0.05)\">© 2024 Copyright: <a class=\"text-reset fw-bold\" href=\"https://mdbootstrap.com/\">kursov.net</a></div></footer>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
return nil
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func elementScriptsLoad() templ.ComponentScript {
|
func elementScriptsLoad() templ.ComponentScript {
|
||||||
return templ.ComponentScript{
|
return templ.ComponentScript{
|
||||||
Name: `__templ_elementScriptsLoad_1bc4`,
|
Name: `__templ_elementScriptsLoad_bfb1`,
|
||||||
Function: `function __templ_elementScriptsLoad_1bc4(){const loadInputValues = () => {
|
Function: `function __templ_elementScriptsLoad_bfb1(){const loadInputValues = () => {
|
||||||
const lt = document.getElementById('learning-type-filter');
|
const lt = document.getElementById('learning-type-filter');
|
||||||
const ct = document.getElementById('course-thematic-filter');
|
const ct = document.getElementById('course-thematic-filter');
|
||||||
|
|
||||||
@ -213,44 +200,6 @@ func elementScriptsLoad() templ.ComponentScript {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildFilterParams = () => {
|
|
||||||
const params = [];
|
|
||||||
const school_selector = document.getElementById('schoolSelect');
|
|
||||||
if (school_selector && school_selector.value) {
|
|
||||||
params.push('school_id=' + school_selector.value);
|
|
||||||
}
|
|
||||||
const order_by = document.getElementById('sortBySelect');
|
|
||||||
if (order_by && order_by.value) {
|
|
||||||
params.push('order_by=' + order_by.value);
|
|
||||||
}
|
|
||||||
const ascending = document.getElementById('sortByOrder');
|
|
||||||
if (ascending && ascending.checked) {
|
|
||||||
params.push('asc=true');
|
|
||||||
}
|
|
||||||
return params.join('&');
|
|
||||||
};
|
|
||||||
|
|
||||||
const setupPaginationLinks = () => {
|
|
||||||
document.querySelectorAll('a.page-link').forEach(link => {
|
|
||||||
link.addEventListener('click', (e) => {
|
|
||||||
const nav = link.closest('nav[data-paginated]');
|
|
||||||
if (!nav) return;
|
|
||||||
e.preventDefault();
|
|
||||||
const baseUrl = nav.getAttribute('data-base-url');
|
|
||||||
const href = link.getAttribute('href');
|
|
||||||
const pageMatch = href.match(/[?&]page=(\d+)/);
|
|
||||||
if (!pageMatch) return;
|
|
||||||
const page = pageMatch[1];
|
|
||||||
const filterParams = buildFilterParams();
|
|
||||||
let url = baseUrl + '?page=' + page;
|
|
||||||
if (filterParams) {
|
|
||||||
url += '&' + filterParams;
|
|
||||||
}
|
|
||||||
window.location.assign(url);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const formFilterOnSubmit = event => {
|
const formFilterOnSubmit = event => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
@ -273,6 +222,7 @@ func elementScriptsLoad() templ.ComponentScript {
|
|||||||
const order_by = document.getElementById('sortBySelect');
|
const order_by = document.getElementById('sortBySelect');
|
||||||
const order_by_value = (order_by !== null && order_by.value !== '') ? order_by.value : '';
|
const order_by_value = (order_by !== null && order_by.value !== '') ? order_by.value : '';
|
||||||
const ascending = document.getElementById('sortByOrder');
|
const ascending = document.getElementById('sortByOrder');
|
||||||
|
|
||||||
const baseUrl = ` + "`" + `${window.location.pathname}?` + "`" + `;
|
const baseUrl = ` + "`" + `${window.location.pathname}?` + "`" + `;
|
||||||
|
|
||||||
params = [];
|
params = [];
|
||||||
@ -309,29 +259,19 @@ func elementScriptsLoad() templ.ComponentScript {
|
|||||||
|
|
||||||
const ob = document.getElementById('sortBySelect');
|
const ob = document.getElementById('sortBySelect');
|
||||||
if (ob) ob.onchange = filterBySchool;
|
if (ob) ob.onchange = filterBySchool;
|
||||||
|
|
||||||
setupPaginationLinks();
|
|
||||||
});
|
});
|
||||||
}`,
|
}`,
|
||||||
Call: templ.SafeScript(`__templ_elementScriptsLoad_1bc4`),
|
Call: templ.SafeScript(`__templ_elementScriptsLoad_bfb1`),
|
||||||
CallInline: templ.SafeScriptInline(`__templ_elementScriptsLoad_1bc4`),
|
CallInline: templ.SafeScriptInline(`__templ_elementScriptsLoad_bfb1`),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func root(page PageKind, _ stats) templ.Component {
|
func root(page PageKind, _ stats) templ.Component {
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
defer func() {
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
ctx = templ.InitializeContext(ctx)
|
ctx = templ.InitializeContext(ctx)
|
||||||
templ_7745c5c3_Var11 := templ.GetChildren(ctx)
|
templ_7745c5c3_Var11 := templ.GetChildren(ctx)
|
||||||
@ -339,7 +279,7 @@ func root(page PageKind, _ stats) templ.Component {
|
|||||||
templ_7745c5c3_Var11 = templ.NopComponent
|
templ_7745c5c3_Var11 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<!doctype html><html lang=\"ru\">")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<!doctype html><html lang=\"ru\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -347,7 +287,7 @@ func root(page PageKind, _ stats) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<body>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<body>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -355,7 +295,7 @@ func root(page PageKind, _ stats) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<div class=\"container\">")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"container\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -363,7 +303,7 @@ func root(page PageKind, _ stats) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</div>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -371,7 +311,7 @@ func root(page PageKind, _ stats) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</body>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</body>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -379,12 +319,13 @@ func root(page PageKind, _ stats) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</html>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</html>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
return nil
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
|
|||||||
@ -1,27 +1,21 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
// Code generated by templ - DO NOT EDIT.
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
// templ: version: v0.2.707
|
||||||
package bootstrap
|
package bootstrap
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
import "github.com/a-h/templ"
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
import "context"
|
||||||
|
import "io"
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
func listCoursesByCourseThematic(params ListCoursesParams) templ.Component {
|
func listCoursesByCourseThematic(params ListCoursesParams) templ.Component {
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
defer func() {
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
ctx = templ.InitializeContext(ctx)
|
ctx = templ.InitializeContext(ctx)
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||||
@ -29,7 +23,7 @@ func listCoursesByCourseThematic(params ListCoursesParams) templ.Component {
|
|||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"container\"><h2>Здесь вы можете найти интересующие вас курсы по теме ")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"container\"><h2>Здесь вы можете найти интересующие вас курсы по теме ")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -42,25 +36,21 @@ func listCoursesByCourseThematic(params ListCoursesParams) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, ":</h2><ul class=\"list-group\">")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(":</h2><ul class=\"list-group\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
for _, courseThematic := range params.FilterForm.AvailableCourseThematics {
|
for _, courseThematic := range params.FilterForm.AvailableCourseThematics {
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<li class=\"list-group-item\"><a href=\"")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"list-group-item\"><a href=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var3 templ.SafeURL
|
var templ_7745c5c3_Var3 templ.SafeURL = templ.SafeURL("/courses/" + params.FilterForm.ActiveLearningType.ID + "/" + courseThematic.ID)
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL("/courses/" + params.FilterForm.ActiveLearningType.ID + "/" + courseThematic.ID))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var3)))
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/list_course_thematics.templ`, Line: 12, Col: 107}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\">")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -73,33 +63,28 @@ func listCoursesByCourseThematic(params ListCoursesParams) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</a></li>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</ul></div>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</ul></div>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
return nil
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListCourseThematics(pageType PageKind, s stats, params ListCoursesParams) templ.Component {
|
func ListCourseThematics(pageType PageKind, s stats, params ListCoursesParams) templ.Component {
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
defer func() {
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
ctx = templ.InitializeContext(ctx)
|
ctx = templ.InitializeContext(ctx)
|
||||||
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
|
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
|
||||||
@ -107,23 +92,17 @@ func ListCourseThematics(pageType PageKind, s stats, params ListCoursesParams) t
|
|||||||
templ_7745c5c3_Var5 = templ.NopComponent
|
templ_7745c5c3_Var5 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
templ_7745c5c3_Var6 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
templ_7745c5c3_Var6 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
defer func() {
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
}
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Err = listCoursesSectionHeader(params.FilterForm.BreadcrumbsParams).Render(ctx, templ_7745c5c3_Buffer)
|
templ_7745c5c3_Err = listCoursesSectionHeader(params.FilterForm.BreadcrumbsParams).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, " ")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -131,7 +110,7 @@ func ListCourseThematics(pageType PageKind, s stats, params ListCoursesParams) t
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, " ")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -139,14 +118,18 @@ func ListCourseThematics(pageType PageKind, s stats, params ListCoursesParams) t
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
return nil
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
})
|
})
|
||||||
templ_7745c5c3_Err = root(pageType, s).Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer)
|
templ_7745c5c3_Err = root(pageType, s).Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
return nil
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -57,33 +57,24 @@ type Pagination struct {
|
|||||||
Page int
|
Page int
|
||||||
TotalPages int
|
TotalPages int
|
||||||
BaseURL string
|
BaseURL string
|
||||||
QueryParams string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Pagination) pageURL(page int) string {
|
|
||||||
url := p.BaseURL + "?page=" + strconv.Itoa(page)
|
|
||||||
if p.QueryParams != "" {
|
|
||||||
url += "&" + p.QueryParams
|
|
||||||
}
|
|
||||||
return url
|
|
||||||
}
|
}
|
||||||
|
|
||||||
templ pagination(p Pagination) {
|
templ pagination(p Pagination) {
|
||||||
if p.Page > 0 && p.TotalPages > 0 {
|
if p.Page > 0 && p.TotalPages > 0 {
|
||||||
<nav aria-label="Page navigation" data-paginated="true" data-base-url={ p.BaseURL } data-current-page={ strconv.Itoa(p.Page) }>
|
<nav aria-label="Page navigation">
|
||||||
<ul class="pagination justify-content-center">
|
<ul class="pagination justify-content-center">
|
||||||
<li class={ "page-item" , templ.KV("disabled", p.Page==1), }>
|
<li class={ "page-item" , templ.KV("disabled", p.Page==1), }>
|
||||||
<a href={ templ.URL(p.pageURL(p.Page-1)) } class="page-link">Previous</a>
|
<a href={ templ.URL(p.BaseURL + "?page=" + strconv.Itoa(p.Page-1)) } class="page-link">Previous</a>
|
||||||
</li>
|
</li>
|
||||||
for i := max(p.Page-2, 1); i < min(p.TotalPages, 10); i++ {
|
for i := max(p.Page-2, 1); i < min(p.TotalPages, 10); i++ {
|
||||||
<li
|
<li
|
||||||
class={ "page-item" , templ.KV("active", p.Page==i), }
|
class={ "page-item" , templ.KV("active", p.Page==i), }
|
||||||
>
|
>
|
||||||
<a href={ templ.URL(p.pageURL(i)) } class="page-link">{ strconv.Itoa(i) }</a>
|
<a href={ templ.URL(p.BaseURL + "?page=" + strconv.Itoa(i)) } class="page-link">{ strconv.Itoa(i) }</a>
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
<li class={ "page-item" , templ.KV("disabled", p.Page==p.TotalPages), }>
|
<li class={ "page-item" , templ.KV("disabled", p.Page==p.TotalPages), }>
|
||||||
<a href={ templ.URL(p.pageURL(p.Page+1)) } class="page-link">Next</a>
|
<a href={ templ.URL(p.BaseURL + "?page=" + strconv.Itoa(p.Page+1)) } class="page-link">Next</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
// Code generated by templ - DO NOT EDIT.
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
// templ: version: v0.2.707
|
||||||
package bootstrap
|
package bootstrap
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
import "github.com/a-h/templ"
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
import "context"
|
||||||
|
import "io"
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
import "strconv"
|
import "strconv"
|
||||||
|
|
||||||
@ -22,19 +24,11 @@ type IndexCourseCategoryItem struct {
|
|||||||
// that holds multiple learning types. It expected to have a basic description
|
// that holds multiple learning types. It expected to have a basic description
|
||||||
// and an amount of items.
|
// and an amount of items.
|
||||||
func courseItemCard(item IndexCourseCategoryItem) templ.Component {
|
func courseItemCard(item IndexCourseCategoryItem) templ.Component {
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
defer func() {
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
ctx = templ.InitializeContext(ctx)
|
ctx = templ.InitializeContext(ctx)
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||||
@ -42,7 +36,7 @@ func courseItemCard(item IndexCourseCategoryItem) templ.Component {
|
|||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"card\"><div class=\"card-body\"><h5 class=\"card-title\">")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"card\"><div class=\"card-body\"><h5 class=\"card-title\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -55,7 +49,7 @@ func courseItemCard(item IndexCourseCategoryItem) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</h5><hr><p>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h5><hr><p>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -68,17 +62,17 @@ func courseItemCard(item IndexCourseCategoryItem) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</p>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
if len(item.ExampleThemes) > 0 {
|
if len(item.ExampleThemes) > 0 {
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<p>В данной категории вы можете найти курсы по темам:</p><ul>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<p>В данной категории вы можете найти курсы по темам:</p><ul>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
for _, exampleItem := range item.ExampleThemes {
|
for _, exampleItem := range item.ExampleThemes {
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<li><span class=\"d-inline-block text-truncate col-8\">")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li><span class=\"d-inline-block text-truncate col-8\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -91,30 +85,26 @@ func courseItemCard(item IndexCourseCategoryItem) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</span></li>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span></li>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</ul>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</ul>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<div class=\"d-flex justify-content-between align-items-center\"><a href=\"")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"d-flex justify-content-between align-items-center\"><a href=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var5 templ.SafeURL
|
var templ_7745c5c3_Var5 templ.SafeURL = templ.URL("/courses/" + item.ID)
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinURLErrs(templ.URL("/courses/" + item.ID))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var5)))
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/main.templ`, Line: 33, Col: 46}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\" class=\"btn btn-sm btn-outline-primary col-6\">Open</a> <small class=\"text-body-secondary\">")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" class=\"btn btn-sm btn-outline-primary col-6\">Open</a> <small class=\"text-body-secondary\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -127,28 +117,23 @@ func courseItemCard(item IndexCourseCategoryItem) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " items.</small></div></div></div>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" items.</small></div></div></div>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
return nil
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func courseCategory(items []IndexCourseCategoryItem) templ.Component {
|
func courseCategory(items []IndexCourseCategoryItem) templ.Component {
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
defer func() {
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
ctx = templ.InitializeContext(ctx)
|
ctx = templ.InitializeContext(ctx)
|
||||||
templ_7745c5c3_Var7 := templ.GetChildren(ctx)
|
templ_7745c5c3_Var7 := templ.GetChildren(ctx)
|
||||||
@ -156,12 +141,12 @@ func courseCategory(items []IndexCourseCategoryItem) templ.Component {
|
|||||||
templ_7745c5c3_Var7 = templ.NopComponent
|
templ_7745c5c3_Var7 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"container w-75 mb-4\"><div class=\"row g-4\">")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"container w-75 mb-4\"><div class=\"row g-4\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<div class=\"col-12 col-md-8 col-lg-4\">")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"col-12 col-md-8 col-lg-4\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -169,16 +154,19 @@ func courseCategory(items []IndexCourseCategoryItem) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</div></div>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
return nil
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,31 +174,14 @@ type Pagination struct {
|
|||||||
Page int
|
Page int
|
||||||
TotalPages int
|
TotalPages int
|
||||||
BaseURL string
|
BaseURL string
|
||||||
QueryParams string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Pagination) pageURL(page int) string {
|
|
||||||
url := p.BaseURL + "?page=" + strconv.Itoa(page)
|
|
||||||
if p.QueryParams != "" {
|
|
||||||
url += "&" + p.QueryParams
|
|
||||||
}
|
|
||||||
return url
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func pagination(p Pagination) templ.Component {
|
func pagination(p Pagination) templ.Component {
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
defer func() {
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
ctx = templ.InitializeContext(ctx)
|
ctx = templ.InitializeContext(ctx)
|
||||||
templ_7745c5c3_Var8 := templ.GetChildren(ctx)
|
templ_7745c5c3_Var8 := templ.GetChildren(ctx)
|
||||||
@ -219,158 +190,123 @@ func pagination(p Pagination) templ.Component {
|
|||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
if p.Page > 0 && p.TotalPages > 0 {
|
if p.Page > 0 && p.TotalPages > 0 {
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<nav aria-label=\"Page navigation\" data-paginated=\"true\" data-base-url=\"")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<nav aria-label=\"Page navigation\"><ul class=\"pagination justify-content-center\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var9 string
|
var templ_7745c5c3_Var9 = []any{"page-item", templ.KV("disabled", p.Page == 1)}
|
||||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.BaseURL)
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var9...)
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/main.templ`, Line: 73, Col: 83}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\" data-current-page=\"")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var10 string
|
var templ_7745c5c3_Var10 string
|
||||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.ResolveAttributeValue(strconv.Itoa(p.Page))
|
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var9).String())
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/main.templ`, Line: 73, Col: 126}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var10)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\"><ul class=\"pagination justify-content-center\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var11 = []any{"page-item", templ.KV("disabled", p.Page == 1)}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var11...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<li class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var12 string
|
|
||||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var11).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/main.templ`, Line: 1, Col: 0}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/main.templ`, Line: 1, Col: 0}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var12)
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "\"><a href=\"")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><a href=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var13 templ.SafeURL
|
var templ_7745c5c3_Var11 templ.SafeURL = templ.URL(p.BaseURL + "?page=" + strconv.Itoa(p.Page-1))
|
||||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinURLErrs(templ.URL(p.pageURL(p.Page - 1)))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var11)))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/main.templ`, Line: 76, Col: 45}
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" class=\"page-link\">Previous</a></li>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
for i := max(p.Page-2, 1); i < min(p.TotalPages, 10); i++ {
|
||||||
|
var templ_7745c5c3_Var12 = []any{"page-item", templ.KV("active", p.Page == i)}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var12...)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var13 string
|
||||||
|
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var12).String())
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/main.templ`, Line: 1, Col: 0}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "\" class=\"page-link\">Previous</a></li>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><a href=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
for i := max(p.Page-2, 1); i < min(p.TotalPages, 10); i++ {
|
var templ_7745c5c3_Var14 templ.SafeURL = templ.URL(p.BaseURL + "?page=" + strconv.Itoa(i))
|
||||||
var templ_7745c5c3_Var14 = []any{"page-item", templ.KV("active", p.Page == i)}
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var14)))
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var14...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<li class=\"")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" class=\"page-link\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var15 string
|
var templ_7745c5c3_Var15 string
|
||||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var14).String())
|
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(i))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/main.templ`, Line: 1, Col: 0}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/main.templ`, Line: 73, Col: 103}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var15)
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "\"><a href=\"")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var16 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinURLErrs(templ.URL(p.pageURL(i)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/main.templ`, Line: 82, Col: 39}
|
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
|
var templ_7745c5c3_Var16 = []any{"page-item", templ.KV("disabled", p.Page == p.TotalPages)}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var16...)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\" class=\"page-link\">")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var17 string
|
var templ_7745c5c3_Var17 string
|
||||||
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(i))
|
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var16).String())
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/main.templ`, Line: 82, Col: 77}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/main.templ`, Line: 1, Col: 0}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</a></li>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><a href=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var18 templ.SafeURL = templ.URL(p.BaseURL + "?page=" + strconv.Itoa(p.Page+1))
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var18)))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" class=\"page-link\">Next</a></li></ul></nav>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var18 = []any{"page-item", templ.KV("disabled", p.Page == p.TotalPages)}
|
if !templ_7745c5c3_IsBuffer {
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var18...)
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
if templ_7745c5c3_Err != nil {
|
}
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "<li class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var19 string
|
|
||||||
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var18).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/main.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var19)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "\"><a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var20 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinURLErrs(templ.URL(p.pageURL(p.Page + 1)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/kurious/ports/http/bootstrap/main.templ`, Line: 86, Col: 45}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "\" class=\"page-link\">Next</a></li></ul></nav>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,43 +317,29 @@ type MainPageParams struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func MainPage(pageType PageKind, s stats, params MainPageParams) templ.Component {
|
func MainPage(pageType PageKind, s stats, params MainPageParams) templ.Component {
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
defer func() {
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
ctx = templ.InitializeContext(ctx)
|
ctx = templ.InitializeContext(ctx)
|
||||||
templ_7745c5c3_Var21 := templ.GetChildren(ctx)
|
templ_7745c5c3_Var19 := templ.GetChildren(ctx)
|
||||||
if templ_7745c5c3_Var21 == nil {
|
if templ_7745c5c3_Var19 == nil {
|
||||||
templ_7745c5c3_Var21 = templ.NopComponent
|
templ_7745c5c3_Var19 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
templ_7745c5c3_Var22 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
templ_7745c5c3_Var20 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
defer func() {
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
}
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Err = listCoursesSectionHeader(params.Breadcrumbs).Render(ctx, templ_7745c5c3_Buffer)
|
templ_7745c5c3_Err = listCoursesSectionHeader(params.Breadcrumbs).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, " ")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -425,7 +347,7 @@ func MainPage(pageType PageKind, s stats, params MainPageParams) templ.Component
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, " ")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -433,14 +355,18 @@ func MainPage(pageType PageKind, s stats, params MainPageParams) templ.Component
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
return nil
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
})
|
})
|
||||||
templ_7745c5c3_Err = root(pageType, s).Render(templ.WithChildren(ctx, templ_7745c5c3_Var22), templ_7745c5c3_Buffer)
|
templ_7745c5c3_Err = root(pageType, s).Render(templ.WithChildren(ctx, templ_7745c5c3_Var20), templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
return nil
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import (
|
|||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"git.loyso.art/frx/kurious/internal/common/xslices"
|
"git.loyso.art/frx/kurious/internal/common/xslices"
|
||||||
@ -223,8 +222,6 @@ func (c courseTemplServer) List(w http.ResponseWriter, r *http.Request) {
|
|||||||
currentPage = totalPages
|
currentPage = totalPages
|
||||||
}
|
}
|
||||||
|
|
||||||
queryParams := buildListCoursesQueryParams(pathParams)
|
|
||||||
|
|
||||||
params = bootstrap.ListCoursesParams{
|
params = bootstrap.ListCoursesParams{
|
||||||
FilterForm: bootstrap.FilterFormParams{
|
FilterForm: bootstrap.FilterFormParams{
|
||||||
Render: true,
|
Render: true,
|
||||||
@ -248,7 +245,6 @@ func (c courseTemplServer) List(w http.ResponseWriter, r *http.Request) {
|
|||||||
Page: currentPage,
|
Page: currentPage,
|
||||||
TotalPages: totalPages,
|
TotalPages: totalPages,
|
||||||
BaseURL: r.URL.Path,
|
BaseURL: r.URL.Path,
|
||||||
QueryParams: queryParams,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,20 +416,3 @@ func newOrderableContainer(units ...orderableUnit) *orderableContainer {
|
|||||||
fieldByID: fieldByID,
|
fieldByID: fieldByID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildListCoursesQueryParams(p listCoursesParams) string {
|
|
||||||
var parts []string
|
|
||||||
if p.School != "" {
|
|
||||||
parts = append(parts, "school_id="+p.School)
|
|
||||||
}
|
|
||||||
if p.OrderBy != "" && p.OrderBy != "pr" {
|
|
||||||
parts = append(parts, "order_by="+p.OrderBy)
|
|
||||||
}
|
|
||||||
if p.Ascending {
|
|
||||||
parts = append(parts, "asc=true")
|
|
||||||
}
|
|
||||||
if p.PerPage > 0 && p.PerPage != 20 {
|
|
||||||
parts = append(parts, fmt.Sprintf("per_page=%d", p.PerPage))
|
|
||||||
}
|
|
||||||
return strings.Join(parts, "&")
|
|
||||||
}
|
|
||||||
|
|||||||
@ -55,14 +55,7 @@ func NewApplication(ctx context.Context, cfg ApplicationConfig, mapper domain.Co
|
|||||||
organizationrepo = sqliteConnection.Organization()
|
organizationrepo = sqliteConnection.Organization()
|
||||||
repoCloser = sqliteConnection
|
repoCloser = sqliteConnection
|
||||||
case RepositoryEngineYDB:
|
case RepositoryEngineYDB:
|
||||||
ydbConn, err := adapters.NewYDBConnection(ctx, cfg.YDB, log.With(slog.String("db", "ydb")))
|
return Application{}, errors.New("ydb is no longer supported")
|
||||||
if err != nil {
|
|
||||||
return Application{}, fmt.Errorf("making ydb connection: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
courseadapter = ydbConn.CourseRepository()
|
|
||||||
organizationrepo = ydbConn.Organization()
|
|
||||||
repoCloser = ydbConn
|
|
||||||
default:
|
default:
|
||||||
return Application{}, errors.New("unable to decide which db engine to use")
|
return Application{}, errors.New("unable to decide which db engine to use")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user