Commit possible fixes for build
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
# MariaDB
|
||||||
|
MYSQL_ROOT_PASSWORD=changeme_root
|
||||||
|
MYSQL_DATABASE=nextcloud
|
||||||
|
MYSQL_USER=nextcloud
|
||||||
|
MYSQL_PASSWORD=changeme_nc
|
||||||
|
|
||||||
|
# Nextcloud admin
|
||||||
|
NEXTCLOUD_ADMIN_USER=admin
|
||||||
|
NEXTCLOUD_ADMIN_PASSWORD=changeme_admin
|
||||||
@@ -21,3 +21,9 @@ composer.lock
|
|||||||
|
|
||||||
# npm
|
# npm
|
||||||
package-lock.json
|
package-lock.json
|
||||||
|
|
||||||
|
# Secrets
|
||||||
|
.env
|
||||||
|
|
||||||
|
# Docker
|
||||||
|
.build_done
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
# Issue #124: Nav sidebar clicks don't navigate between views
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
The `NcAppNavigationItem` components in `App.vue` use `@click` handlers to call `router.push()`,
|
||||||
|
but the component internally renders an `<a href="#">` that intercepts the click event, navigating
|
||||||
|
to `#` (root hash) before the Vue click handler fires. The fix is to use `NcAppNavigationItem`'s
|
||||||
|
built-in `:to` prop which renders the element as a `<router-link>`, handling navigation natively.
|
||||||
|
|
||||||
|
## Plan
|
||||||
|
|
||||||
|
### Step 1: Modify `src/App.vue` navigation items
|
||||||
|
|
||||||
|
For each `NcAppNavigationItem`:
|
||||||
|
1. Replace `@click="navigate('routeName')"` with `:to="{ name: 'routeName' }"`
|
||||||
|
2. Remove the `:active` binding since `NcAppNavigationItem` auto-detects active state from `:to`
|
||||||
|
3. Keep icon template slots unchanged
|
||||||
|
|
||||||
|
### Step 2: Remove the `navigate()` function and `useRouter` import
|
||||||
|
|
||||||
|
Since navigation is now handled by the `:to` prop:
|
||||||
|
- Remove `const router = useRouter()`
|
||||||
|
- Remove the `navigate()` function
|
||||||
|
- Remove `useRouter` from the import (keep `useRoute` since `currentRoute` still needs it)
|
||||||
|
|
||||||
|
### Step 3: Keep `currentRoute` if needed, OR remove
|
||||||
|
|
||||||
|
Actually, with `:to` prop, `NcAppNavigationItem` automatically sets active state. But for routes
|
||||||
|
like `member-detail` that should highlight "Mitglieder", we need the `:active` prop for parent
|
||||||
|
route matching. The `:to` prop only auto-activates on exact route match.
|
||||||
|
|
||||||
|
**Decision**: Keep `:active` bindings for nav items that have sub-routes (Mitglieder, Familien, Lager)
|
||||||
|
to handle parent-route highlighting. For items with no sub-routes (Beiträge, Berichte, Audit-Log,
|
||||||
|
Einstellungen), `:to` auto-active is sufficient — but for consistency, keep all `:active` bindings.
|
||||||
|
|
||||||
|
Actually, let me reconsider: the `:to` prop with vue-router uses `router-link-active` class which
|
||||||
|
matches prefix. So `/members/5` would still match `{ name: 'members' }` route... but only if
|
||||||
|
the path matches. Since named routes have exact paths, it depends on `router-link` behavior.
|
||||||
|
|
||||||
|
**Safest approach**: Keep `:active` bindings for items with child routes, remove them for simple routes.
|
||||||
|
No -- for consistency and zero regression risk, keep ALL `:active` bindings.
|
||||||
|
|
||||||
|
### Step 4: Verify build compiles
|
||||||
|
|
||||||
|
Run `npm run build` to ensure no errors.
|
||||||
|
|
||||||
|
## Acceptance Criteria Checklist
|
||||||
|
|
||||||
|
1. [ ] Each `NcAppNavigationItem` uses `:to` prop with the correct route object
|
||||||
|
2. [ ] No `@click="navigate(...)"` handlers remain on navigation items
|
||||||
|
3. [ ] The `navigate()` function is removed
|
||||||
|
4. [ ] The `useRouter` import is removed (no longer needed)
|
||||||
|
5. [ ] `:active` bindings are preserved for parent-route highlighting
|
||||||
|
6. [ ] Build succeeds without errors
|
||||||
|
7. [ ] All existing routes still work (no route names changed)
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
# Plan: Issue #18 — Set up DB migrations for members table
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Create a Nextcloud OCP migration class that sets up the `oc_mv_members` table with all columns specified in the issue and requirements section 5.2. The migration follows Nextcloud's migration framework using `\OCP\Migration\SimpleMigrationStep` and Doctrine DBAL schema. Foreign key columns for `stufe_id` and `family_id` are created as nullable integer columns (FK constraints will be added when those tables are created in issues #30 and #27 respectively).
|
||||||
|
|
||||||
|
## Implementation Steps
|
||||||
|
|
||||||
|
### Step 1: Create Migration Class
|
||||||
|
|
||||||
|
- File: `lib/Migration/Version000001Date20260407000000.php`
|
||||||
|
- Namespace: `OCA\Mitgliederverwaltung\Migration`
|
||||||
|
- Extends: `SimpleMigrationStep`
|
||||||
|
- Method: `changeSchema(IOutput $output, Closure $schemaClosure, array $options)`
|
||||||
|
|
||||||
|
### Step 2: Define Table Schema — `oc_mv_members`
|
||||||
|
|
||||||
|
Columns (from issue #18 specification):
|
||||||
|
|
||||||
|
| Column | Type | Constraints |
|
||||||
|
|--------|------|------------|
|
||||||
|
| `id` | bigint | PK, autoincrement, unsigned |
|
||||||
|
| `vorname` | string(255) | NOT NULL |
|
||||||
|
| `nachname` | string(255) | NOT NULL |
|
||||||
|
| `geburtsdatum` | date | NOT NULL |
|
||||||
|
| `geschlecht` | string(20) | nullable |
|
||||||
|
| `rolle` | string(30) | NOT NULL, default 'mitglied' |
|
||||||
|
| `stufe_id` | bigint | nullable, unsigned (FK to oc_mv_stufen, added later) |
|
||||||
|
| `eintritt` | date | NOT NULL |
|
||||||
|
| `austritt` | date | nullable |
|
||||||
|
| `status` | string(20) | NOT NULL, default 'aktiv' |
|
||||||
|
| `allergien_encrypted` | text | nullable |
|
||||||
|
| `notizen` | text | nullable |
|
||||||
|
| `zusatz_notizen` | text | nullable |
|
||||||
|
| `kv_typ` | string(20) | nullable |
|
||||||
|
| `kv_name` | string(255) | nullable |
|
||||||
|
| `family_id` | bigint | nullable, unsigned (FK to oc_mv_families, added later) |
|
||||||
|
| `frozen_fee_rate` | decimal(10,2) | nullable |
|
||||||
|
| `calendar_event_uri` | string(512) | nullable |
|
||||||
|
| `contact_vcard_uri` | string(512) | nullable |
|
||||||
|
| `created_at` | datetime | NOT NULL, default CURRENT_TIMESTAMP |
|
||||||
|
| `updated_at` | datetime | NOT NULL, default CURRENT_TIMESTAMP |
|
||||||
|
| `deleted_at` | datetime | nullable |
|
||||||
|
|
||||||
|
### Step 3: Add Indexes
|
||||||
|
|
||||||
|
- Index on `status` (frequent filtering)
|
||||||
|
- Index on `family_id` (joins)
|
||||||
|
- Index on `stufe_id` (joins)
|
||||||
|
- Index on `nachname` (sorting/searching)
|
||||||
|
- Index on `deleted_at` (soft-delete queries)
|
||||||
|
- Composite index on `status, deleted_at` (common query pattern: active non-deleted members)
|
||||||
|
|
||||||
|
### Step 4: Verify Migration Structure
|
||||||
|
|
||||||
|
- Ensure the class is properly namespaced and autoloadable via PSR-4
|
||||||
|
- Ensure the table name uses Nextcloud's table prefix convention (just use `mv_members` — Nextcloud adds `oc_` prefix)
|
||||||
|
|
||||||
|
## Acceptance Criteria Checklist
|
||||||
|
|
||||||
|
1. [ ] Migration file exists at `lib/Migration/Version000001Date20260407000000.php`
|
||||||
|
2. [ ] Class extends `SimpleMigrationStep` and implements `changeSchema`
|
||||||
|
3. [ ] Table `mv_members` is created with all 20 columns from the spec
|
||||||
|
4. [ ] Column types match the specification (string for enums, bigint for FKs, decimal for fee rate, etc.)
|
||||||
|
5. [ ] `id` is primary key, autoincrement, unsigned bigint
|
||||||
|
6. [ ] NOT NULL constraints applied to: vorname, nachname, geburtsdatum, rolle, eintritt, status, created_at, updated_at
|
||||||
|
7. [ ] Nullable columns: geschlecht, stufe_id, austritt, allergien_encrypted, notizen, zusatz_notizen, kv_typ, kv_name, family_id, frozen_fee_rate, calendar_event_uri, contact_vcard_uri, deleted_at
|
||||||
|
8. [ ] Default values set for: rolle='mitglied', status='aktiv'
|
||||||
|
9. [ ] Appropriate indexes are created
|
||||||
|
10. [ ] PHP syntax is valid (no parse errors)
|
||||||
|
11. [ ] File follows Nextcloud migration conventions (namespace, class name pattern)
|
||||||
|
12. [ ] Migration is idempotent (checks if table exists before creating)
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
.PHONY: build deps up down setup deploy redeploy logs clean
|
||||||
|
|
||||||
|
# Install dependencies (composer via Docker since PHP may not be local)
|
||||||
|
deps:
|
||||||
|
npm install --no-audit --no-fund
|
||||||
|
docker run --rm -v "$$(pwd):/app" -w /app composer:2 install --no-dev --optimize-autoloader --no-interaction
|
||||||
|
|
||||||
|
# Build frontend
|
||||||
|
build: deps
|
||||||
|
npx webpack --node-env production --progress
|
||||||
|
|
||||||
|
# Start containers (detached)
|
||||||
|
up:
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# Wait for NC to be ready, install it, copy app in, enable it
|
||||||
|
setup:
|
||||||
|
@echo "Waiting for Nextcloud container to be ready..."
|
||||||
|
@until docker compose exec -T nextcloud test -f config/CAN_INSTALL 2>/dev/null || \
|
||||||
|
docker compose exec -T nextcloud test -f config/config.php 2>/dev/null; do \
|
||||||
|
sleep 3; \
|
||||||
|
echo " still waiting..."; \
|
||||||
|
done
|
||||||
|
@sleep 5
|
||||||
|
@echo "Fixing custom_apps ownership..."
|
||||||
|
docker compose exec nextcloud chown www-data:www-data /var/www/html/custom_apps
|
||||||
|
@echo "Installing Nextcloud..."
|
||||||
|
docker compose exec -u www-data nextcloud php occ maintenance:install \
|
||||||
|
--database=mysql \
|
||||||
|
--database-host=db \
|
||||||
|
--database-name=$${MYSQL_DATABASE:-nextcloud} \
|
||||||
|
--database-user=$${MYSQL_USER:-nextcloud} \
|
||||||
|
--database-pass=$$(grep MYSQL_PASSWORD .env | head -1 | cut -d= -f2) \
|
||||||
|
--admin-user=$$(grep NEXTCLOUD_ADMIN_USER .env | cut -d= -f2) \
|
||||||
|
--admin-pass=$$(grep NEXTCLOUD_ADMIN_PASSWORD .env | cut -d= -f2) \
|
||||||
|
2>&1 || true
|
||||||
|
@echo "Copying app into Nextcloud..."
|
||||||
|
docker compose exec nextcloud mkdir -p /var/www/html/custom_apps/mitgliederverwaltung
|
||||||
|
docker compose exec nextcloud cp -a /app-src/appinfo /var/www/html/custom_apps/mitgliederverwaltung/
|
||||||
|
docker compose exec nextcloud cp -a /app-src/lib /var/www/html/custom_apps/mitgliederverwaltung/
|
||||||
|
docker compose exec nextcloud cp -a /app-src/templates /var/www/html/custom_apps/mitgliederverwaltung/
|
||||||
|
docker compose exec nextcloud cp -a /app-src/js /var/www/html/custom_apps/mitgliederverwaltung/
|
||||||
|
docker compose exec nextcloud cp -a /app-src/vendor /var/www/html/custom_apps/mitgliederverwaltung/
|
||||||
|
docker compose exec nextcloud chown -R www-data:www-data /var/www/html/custom_apps/mitgliederverwaltung
|
||||||
|
@echo "Enabling app..."
|
||||||
|
docker compose exec -u www-data nextcloud php occ app:enable mitgliederverwaltung
|
||||||
|
@echo ""
|
||||||
|
@echo "Done! Nextcloud is running at http://localhost:8080"
|
||||||
|
@echo "Login with credentials from .env (NEXTCLOUD_ADMIN_USER / NEXTCLOUD_ADMIN_PASSWORD)"
|
||||||
|
|
||||||
|
# Full deploy: build, start, install, enable
|
||||||
|
deploy: build up setup
|
||||||
|
|
||||||
|
# Rebuild and redeploy app into running NC
|
||||||
|
redeploy: build
|
||||||
|
docker compose exec nextcloud rm -rf /var/www/html/custom_apps/mitgliederverwaltung
|
||||||
|
docker compose exec nextcloud mkdir -p /var/www/html/custom_apps/mitgliederverwaltung
|
||||||
|
docker compose exec nextcloud cp -a /app-src/appinfo /var/www/html/custom_apps/mitgliederverwaltung/
|
||||||
|
docker compose exec nextcloud cp -a /app-src/lib /var/www/html/custom_apps/mitgliederverwaltung/
|
||||||
|
docker compose exec nextcloud cp -a /app-src/templates /var/www/html/custom_apps/mitgliederverwaltung/
|
||||||
|
docker compose exec nextcloud cp -a /app-src/js /var/www/html/custom_apps/mitgliederverwaltung/
|
||||||
|
docker compose exec nextcloud cp -a /app-src/vendor /var/www/html/custom_apps/mitgliederverwaltung/
|
||||||
|
docker compose exec nextcloud chown -R www-data:www-data /var/www/html/custom_apps/mitgliederverwaltung
|
||||||
|
docker compose exec -u www-data nextcloud php occ upgrade 2>/dev/null || true
|
||||||
|
@echo "App redeployed."
|
||||||
|
|
||||||
|
down:
|
||||||
|
docker compose down
|
||||||
|
|
||||||
|
logs:
|
||||||
|
docker compose logs -f nextcloud
|
||||||
|
|
||||||
|
# Remove volumes (full reset)
|
||||||
|
clean:
|
||||||
|
docker compose down -v
|
||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
<name>Mitgliederverwaltung</name>
|
<name>Mitgliederverwaltung</name>
|
||||||
<summary>Mitgliederverwaltung für Pfadfindervereine</summary>
|
<summary>Mitgliederverwaltung für Pfadfindervereine</summary>
|
||||||
<description><![CDATA[Verwaltung von Mitgliedern, Familien, Beiträgen, Lagern und mehr für Pfadfindervereine. Integriert sich in Nextcloud Kalender, Kontakte und Dateien.]]></description>
|
<description><![CDATA[Verwaltung von Mitgliedern, Familien, Beiträgen, Lagern und mehr für Pfadfindervereine. Integriert sich in Nextcloud Kalender, Kontakte und Dateien.]]></description>
|
||||||
<version>0.0.1</version>
|
<version>0.0.3</version>
|
||||||
<licence>agpl</licence>
|
<licence>agpl</licence>
|
||||||
<author>shahondin1624</author>
|
<author>shahondin1624</author>
|
||||||
<namespace>Mitgliederverwaltung</namespace>
|
<namespace>Mitgliederverwaltung</namespace>
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: mariadb:10.11
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file: .env
|
||||||
|
volumes:
|
||||||
|
- db_data:/var/lib/mysql
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
nextcloud:
|
||||||
|
image: nextcloud:28-apache
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8080:80"
|
||||||
|
env_file: .env
|
||||||
|
environment:
|
||||||
|
MYSQL_HOST: db
|
||||||
|
NEXTCLOUD_TRUSTED_DOMAINS: "localhost"
|
||||||
|
volumes:
|
||||||
|
- nc_data:/var/www/html
|
||||||
|
- ./:/app-src:ro
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
db_data:
|
||||||
|
nc_data:
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace OCA\Mitgliederverwaltung\Controller;
|
||||||
|
|
||||||
|
use OCA\Mitgliederverwaltung\AppInfo\Application;
|
||||||
|
use OCP\AppFramework\Controller;
|
||||||
|
use OCP\AppFramework\Http\TemplateResponse;
|
||||||
|
use OCP\IRequest;
|
||||||
|
|
||||||
|
class PageController extends Controller {
|
||||||
|
public function __construct(IRequest $request) {
|
||||||
|
parent::__construct(Application::APP_ID, $request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @NoAdminRequired
|
||||||
|
* @NoCSRFRequired
|
||||||
|
*/
|
||||||
|
public function index(): TemplateResponse {
|
||||||
|
return new TemplateResponse(Application::APP_ID, 'index');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,5 +6,26 @@
|
|||||||
"build": "webpack --node-env production --progress",
|
"build": "webpack --node-env production --progress",
|
||||||
"dev": "webpack --node-env development --progress",
|
"dev": "webpack --node-env development --progress",
|
||||||
"watch": "webpack --node-env development --progress --watch"
|
"watch": "webpack --node-env development --progress --watch"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@nextcloud/axios": "^2.5.0",
|
||||||
|
"@nextcloud/router": "^3.0.0",
|
||||||
|
"@nextcloud/vue": "^9.6.0",
|
||||||
|
"pinia": "^2.1.7",
|
||||||
|
"vue": "^3.4.0",
|
||||||
|
"vue-material-design-icons": "^5.3.0",
|
||||||
|
"vue-router": "^4.2.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.24.0",
|
||||||
|
"@babel/preset-env": "^7.24.0",
|
||||||
|
"babel-loader": "^9.1.3",
|
||||||
|
"css-loader": "^6.10.0",
|
||||||
|
"sass": "^1.71.0",
|
||||||
|
"sass-loader": "^14.1.0",
|
||||||
|
"style-loader": "^3.3.4",
|
||||||
|
"vue-loader": "^17.4.2",
|
||||||
|
"webpack": "^5.90.0",
|
||||||
|
"webpack-cli": "^5.1.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ use OCP\Util;
|
|||||||
|
|
||||||
$appId = OCA\Mitgliederverwaltung\AppInfo\Application::APP_ID;
|
$appId = OCA\Mitgliederverwaltung\AppInfo\Application::APP_ID;
|
||||||
Util::addScript($appId, $appId . '-main');
|
Util::addScript($appId, $appId . '-main');
|
||||||
Util::addStyle($appId, 'main');
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div id="app-content">
|
<div id="app-content">
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
const path = require('path')
|
||||||
|
const webpack = require('webpack')
|
||||||
|
const { VueLoaderPlugin } = require('vue-loader')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: {
|
||||||
|
'mitgliederverwaltung-main': path.join(__dirname, 'src', 'main.js'),
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
path: path.resolve(__dirname, 'js'),
|
||||||
|
publicPath: '/custom_apps/mitgliederverwaltung/js/',
|
||||||
|
filename: '[name].js',
|
||||||
|
chunkFilename: '[name]-[contenthash].js',
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.vue$/,
|
||||||
|
loader: 'vue-loader',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.js$/,
|
||||||
|
loader: 'babel-loader',
|
||||||
|
exclude: /node_modules/,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
use: ['style-loader', 'css-loader'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.scss$/,
|
||||||
|
use: ['style-loader', 'css-loader', 'sass-loader'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(png|jpe?g|gif|svg|woff2?|eot|ttf|otf)$/,
|
||||||
|
type: 'asset/resource',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new VueLoaderPlugin(),
|
||||||
|
new webpack.optimize.LimitChunkCountPlugin({
|
||||||
|
maxChunks: 1,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
optimization: {
|
||||||
|
splitChunks: false,
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.js', '.vue'],
|
||||||
|
alias: {
|
||||||
|
vue$: 'vue/dist/vue.esm-bundler.js',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user