8 Commits

Author SHA1 Message Date
d569f35bc1
feat: implement create post functionality with dialog and API integration
Some checks failed
Frontend CI / build (push) Failing after 57s
2025-10-14 20:50:06 +08:00
13696e394f
refactor: enhance error handling and state management in auth and image modules 2025-10-14 15:34:34 +08:00
e8c5e678d5 BLOG-136 Dashboard route and frontend authentication (#137)
All checks were successful
Frontend CI / build (push) Successful in 1m23s
### Description

- Create a dashboard layout (with a navigation sidebar)
- Only logged in users are able to access (others 404)

### Package Changes

> shadcn-svelte

```json
{
  "@lucide/svelte": "^0.545.0",
  "clsx": "^2.1.1",
  "tailwind-merge": "^3.3.1",
  "tailwind-variants": "^3.1.1",
  "tw-animate-css": "^1.4.0"
}
```

### Screenshots

|Status|Screenshot|
|-|-|
|Logged in|![image.png](/attachments/5d5fc3b9-c15f-43b8-8201-dedeef3c3fb9)|
|Logged out|![image.png](/attachments/29683c9f-395c-4dd8-892f-dc21df2dd0cc)|

### Reference

Resolves #136.

### Checklist

- [x] A milestone is set
- [x] The related issuse has been linked to this branch

Reviewed-on: #137
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>
2025-10-13 20:33:36 +08:00
565df7aace BLOG-125 Get post by sementic ID (#134)
All checks were successful
Frontend CI / build (push) Successful in 1m26s
### Description

#### Backend

- String and interger can be pass as `id` to `GET` `/post/{id}`

- For the posts existed, the default `semantic_id` for them will be `_id`. (e.g. `_1`, `_2`)

- Semantic ID should follow the rules:

  1. It shouldn't be an integer

  1. It should match the pattern: `^[0-9a-zA-Z_\-]+$`

  <br>

  |Semantic ID|Result|Note|
  |-|-|-|
  |12|X|against with `i`|
  |-3|X|against with `i`|
  |3.14|X|against with `ii`|
  |hello world|X|against with `ii`|
  |*EMPTY*|X|against with `ii`|
  |12_34-56|O||

#### Frontend

- The href of post preview card becomes the semantic ID.

### Package Changes

```toml
regex = "1.12.1"
```

### Screenshots

![截圖 2025-10-12 下午6.23.12.png](/attachments/67de1cd7-f584-40ad-9bbd-27f8bf6f1894)

### Reference

Resolves #125.

### Checklist

- [x] A milestone is set
- [x] The related issuse has been linked to this branch

Reviewed-on: #134
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>
2025-10-12 18:28:58 +08:00
71528294ae BLOG-105 Implement CRUD functionality for Labels (#107)
All checks were successful
Frontend CI / build (push) Successful in 1m8s
### Description

This PR introduces full CRUD (Create, Read, Update) functionality for post labels, implemented by following the existing Clean Architecture.

#### Backend

* **New API Endpoints for Label Management:**
    * `POST /label`: Create a new label (**authentication required**).
    * `PUT /label/{id}`: Update a label by its ID (**authentication required**).
    * `GET /label`: Get all labels.

* **Architectural Implementation:**
    * **Delivery Layer**: Added `CreateLabelRequestDto`, `UpdateLabelRequestDto`, and updated `PostController` with methods to handle label-related operations.
    * **Application Layer**: Created corresponding use cases (`CreateLabelUseCase`, `UpdateLabelUseCase`, `GetAllLabelsUseCase`) to handle business logic.
    * **Gateway/Framework Layer**: Implemented `LabelRepository` and `LabelDbService` to manage database interactions, including creating, updating, and querying labels.

* **Route Adjustment:**
    * The route for fetching all post info has been changed from `GET /post/all` to `GET /post` to be more RESTful.

#### Frontend

* **API Call Update:**
    * To match the backend route change, the API path for fetching all posts is updated from `/post/all` to `/post`.

### Package Changes

_No response_

### Screenshots

_No response_

### Reference

Resolves #105

### Checklist

- [x] A milestone is set
- [x] The related issuse has been linked to this branch

Reviewed-on: #107
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>
2025-08-02 10:46:00 +08:00
3cb69f6e7c BLOG-45 Post content page (#67)
All checks were successful
Frontend CI / build (push) Successful in 1m8s
### Description

- Implement the content page
  - Parse markdown formant content to html by `markdown-it`
  - Use `sanitize-html` to prevent from XSS attack
  - Style the html with `tailwindcss-typography`
- Fix the issue when backend parse the password to url
- Fix and make the post info list from backend always sorted by id

### Package Changes

### Rust

```toml
percent-encoding = "2.3.1"
```

### Node

```json
{
  "@types/markdown-it": "^14.1.2",
  "@types/sanitize-html": "^2.16.0",
  "markdown-it": "^14.1.0",
  "sanitize-html": "^2.17.0"
}
```

### Screenshots

|Desktop|Mobile|
|-|-|
|![image.png](/attachments/0ec5718a-f804-432f-8e4b-e9dc22c080d2)|![beta.squidspirit.com_post(iPhone 12 Pro) (1).png](/attachments/b30d1b96-d4a4-4b2b-b9bd-90fd2592ab52)|

### Reference

Resolves #45

### Checklist

- [x] A milestone is set
- [x] The related issuse has been linked to this branch

Reviewed-on: #67
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>
2025-07-24 22:20:58 +08:00
4a924c1b92 BLOG-65 Establish beta environment (#66)
All checks were successful
Frontend CI / build (push) Successful in 1m4s
### Description

- Change some environment variables implementation
- Nginx configuration:

  ```nginx
  server {
      server_name beta.squidspirit.com;

      proxy_pass_request_headers on;
      proxy_set_header Host $http_host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;

      location / {
          proxy_pass http://127.0.0.1:10013/;
      }

      location /api/ {
          proxy_pass http://127.0.0.1:10014/;
      }

      listen 443 ssl; # managed by Certbot
      ssl_certificate /etc/letsencrypt/live/beta.squidspirit.com/fullchain.pem; # managed by Certbot
      ssl_certificate_key /etc/letsencrypt/live/beta.squidspirit.com/privkey.pem; # managed by Certbot
      include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
      ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
  }

  server {
      if ($host = beta.squidspirit.com) {
          return 301 https://$host$request_uri;
      } # managed by Certbot

      server_name beta.squidspirit.com;
      listen 80;
      return 404; # managed by Certbot
  }
  ```

- Podman kube configuration:

  ```yaml
    apiVersion: v1
  kind: Secret
  metadata:
    name: beta-blog-secret
  data:
    DATABASE_PASSWORD: {{BASE64_PASSWORD}}

  ---

  apiVersion: v1
  kind: Pod
  metadata:
    name: beta-blog
  spec:
    containers:
      - name: postgres
        image: docker.io/library/postgres:17-alpine
        imagePullPolicy: always
        env:
          - name: POSTGRES_PASSWORD
            valueFrom:
              secretKeyRef:
                name: beta-blog-secret
                key: DATABASE_PASSWORD
        volumeMounts:
          - name: beta-blog-postgres
            mountPath: /var/lib/postgresql/data
      - name: backend
        image: registry.squidspirit.com/squid/beta-blog-backend:latest
        imagePullPolicy: always
        env:
          - name: DATABASE_PASSWORD
            valueFrom:
              secretKeyRef:
                name: beta-blog-secret
                key: DATABASE_PASSWORD
        volumeMounts:
          - name: beta-blog-localtime
            mountPath: /etc/localtime
            readonly: true
        ports:
          - hostPort: 10014
            hostIP: 127.0.0.1
            containerPort: 8080
      - name: frontend
        image: registry.squidspirit.com/squid/beta-blog-frontend:latest
        imagePullPolicy: always
        env:
          - name: PUBLIC_API_BASE_URL
            value: https://beta.squidspirit.com/api/
        volumeMounts:
          - name: beta-blog-localtime
            mountPath: /etc/localtime
            readonly: true
        ports:
          - hostPort: 10013
            hostIP: 127.0.0.1
            containerPort: 3000
    volumes:
      - name: beta-blog-localtime
        hostPath:
          path: /etc/localtime
      - name: beta-blog-postgres
        persistentVolumeClaim:
          claimName: beta-blog-postgres
  ```

### Package Changes

_No response_

### Screenshots

_No response_

### Reference

Resolves #65

### Checklist

- [x] A milestone is set
- [x] The related issuse has been linked to this branch

Reviewed-on: #66
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>
2025-07-24 02:23:44 +08:00
c2462fe537 BLOG-44 Post overall page (#64)
All checks were successful
Frontend CI / build (push) Successful in 1m6s
### Description

- Change the format of color response

  ```json
  {
    "red": 0,
    "green": 255,
    "blue": 128,
    "alpha": 255
  }
  ```

- The relationship between the label's background color and its highlight color is calculated. The method involves first converting the RGB color value to HSL, then decreasing the L (lightness) component, and finally converting it back to RGB.

### Package Changes

```json
{
  "zod": "^4.0.5"
}
```

### Screenshots

|Desktop|Mobile|
|-|-|
|![image.png](/attachments/851450c4-0975-4b66-9bf7-606d0114c03e)|![image.png](/attachments/f263d65c-89e9-4439-8d50-ae92ae9482ac)|

### Reference

Resolves #44

### Checklist

- [x] A milestone is set
- [x] The related issuse has been linked to this branch

Reviewed-on: #64
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>
2025-07-24 00:32:20 +08:00