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
|
||||
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>
|
||||
<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>
|
||||
<version>0.0.1</version>
|
||||
<version>0.0.3</version>
|
||||
<licence>agpl</licence>
|
||||
<author>shahondin1624</author>
|
||||
<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",
|
||||
"dev": "webpack --node-env development --progress",
|
||||
"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;
|
||||
Util::addScript($appId, $appId . '-main');
|
||||
Util::addStyle($appId, 'main');
|
||||
|
||||
?>
|
||||
|
||||
<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