Skip to content

Commit d348a2e

Browse files
committed
unified devcontainer mobile app included
1 parent 0f37c56 commit d348a2e

15 files changed

Lines changed: 497 additions & 33 deletions

.devcontainer/Dockerfile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_MAJOR}.x | bash - \
134134
&& apt-get install -y --no-install-recommends nodejs \
135135
&& rm -rf /var/lib/apt/lists/* \
136136
&& mkdir -p /usr/local/share/npm-global \
137-
&& npm install -g rtlcss
137+
&& npm install -g rtlcss pnpm newman
138138

139139
# =============================================================================
140140
# User: odoo (primary user for everything, UID 1000 to match host bind mounts)
@@ -173,9 +173,9 @@ RUN python -m venv /workspaces/venv \
173173
RUN git clone --depth 1 --single-branch --branch ${ODOO_VERSION} \
174174
https://github.com/${ODOO_SOURCE}.git /workspaces/odoo
175175

176-
# Clone OpenSPP2
177-
RUN git clone --depth 1 --single-branch --branch v19.0.2.0.0 \
178-
https://github.com/openspp/OpenSPP2.git /workspaces/openspp
176+
# Clone OpenSPP2 (track latest 19.0, matching OCA addon clone pattern below)
177+
RUN git clone --depth 1 --single-branch --branch 19.0 \
178+
https://github.com/OpenSPP/OpenSPP2.git /workspaces/openspp
179179

180180
# Install Python requirements (Odoo + OpenSPP manifest deps)
181181
COPY --chown=odoo:odoo requirements.in /tmp/project-requirements.txt

.devcontainer/config/keycloak/setup-keycloak.sh

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
# =============================================================================
33
# Keycloak Dev Setup for DSWD 4PS API
44
#
5-
# Creates a "dswd4ps" realm with an "openspp-api" client for local development.
5+
# Creates a "dswd4ps" realm with "openspp-api" and "dswd-4ps-mobile" clients
6+
# for local development.
67
# Intended to run once after Keycloak starts in the devcontainer.
78
#
89
# Usage: bash setup-keycloak.sh
@@ -122,6 +123,52 @@ else
122123
fi
123124
fi
124125

126+
# --- Create Mobile Client ---
127+
MOBILE_CLIENT_ID="dswd-4ps-mobile"
128+
echo "==> Creating client '${MOBILE_CLIENT_ID}'..."
129+
EXISTING_MOBILE=$(curl -s -H "${AUTH}" "${KC_URL}/admin/realms/${REALM}/clients?clientId=${MOBILE_CLIENT_ID}")
130+
MOBILE_COUNT=$(echo "${EXISTING_MOBILE}" | python3 -c "import sys,json; print(len(json.load(sys.stdin)))")
131+
132+
MOBILE_CLIENT_JSON="{
133+
\"clientId\": \"${MOBILE_CLIENT_ID}\",
134+
\"name\": \"DSWD 4PS Mobile\",
135+
\"enabled\": true,
136+
\"protocol\": \"openid-connect\",
137+
\"publicClient\": true,
138+
\"directAccessGrantsEnabled\": true,
139+
\"standardFlowEnabled\": true,
140+
\"implicitFlowEnabled\": false,
141+
\"rootUrl\": \"http://localhost:5174\",
142+
\"baseUrl\": \"/\",
143+
\"redirectUris\": [\"http://localhost:5174/*\", \"http://localhost:11111/*\", \"com.newlogic.dswd4ps://auth/callback\"],
144+
\"webOrigins\": [\"http://localhost:5174\", \"http://localhost:11111\", \"+\"],
145+
\"attributes\": {
146+
\"pkce.code.challenge.method\": \"S256\",
147+
\"post.logout.redirect.uris\": \"http://localhost:5174/*##com.newlogic.dswd4ps://auth/callback\"
148+
}
149+
}"
150+
151+
if [ "${MOBILE_COUNT}" -gt "0" ]; then
152+
echo " Client '${MOBILE_CLIENT_ID}' already exists, updating..."
153+
MOBILE_UUID=$(echo "${EXISTING_MOBILE}" | python3 -c "import sys,json; print(json.load(sys.stdin)[0]['id'])")
154+
curl -s -o /dev/null -w "" -X PUT "${KC_URL}/admin/realms/${REALM}/clients/${MOBILE_UUID}" \
155+
-H "${AUTH}" \
156+
-H "Content-Type: application/json" \
157+
-d "${MOBILE_CLIENT_JSON}"
158+
echo " Client '${MOBILE_CLIENT_ID}' updated."
159+
else
160+
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "${KC_URL}/admin/realms/${REALM}/clients" \
161+
-H "${AUTH}" \
162+
-H "Content-Type: application/json" \
163+
-d "${MOBILE_CLIENT_JSON}")
164+
if [ "${HTTP_CODE}" = "201" ] || [ "${HTTP_CODE}" = "409" ]; then
165+
echo " Client '${MOBILE_CLIENT_ID}' created."
166+
else
167+
echo "ERROR: Failed to create mobile client (HTTP ${HTTP_CODE})"
168+
exit 1
169+
fi
170+
fi
171+
125172
# --- Create Test User ---
126173
echo "==> Creating test user '${TEST_USER}'..."
127174
EXISTING_USERS=$(curl -s -H "${AUTH}" "${KC_URL}/admin/realms/${REALM}/users?username=${TEST_USER}&exact=true")
@@ -170,8 +217,9 @@ echo " Username: ${KC_ADMIN}"
170217
echo " Password: ${KC_ADMIN_PASS}"
171218
echo ""
172219
echo " Realm: ${REALM}"
173-
echo " Client ID: ${CLIENT_ID}"
220+
echo " Client ID (API): ${CLIENT_ID}"
174221
echo " Client Secret: ${CLIENT_SECRET}"
222+
echo " Client ID (Mobile): ${MOBILE_CLIENT_ID} (public, PKCE)"
175223
echo ""
176224
echo " Test User: ${TEST_USER} / ${TEST_USER_PASS}"
177225
echo " Test User Email: ${TEST_USER_EMAIL}"

.devcontainer/devcontainer.json

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@
1313
"extensions": [
1414
"anthropic.claude-code",
1515
"ms-python.python",
16-
"eamodio.gitlens"
16+
"eamodio.gitlens",
17+
"Vue.volar",
18+
"vitest.explorer",
19+
"ms-playwright.playwright",
20+
"dbaeumer.vscode-eslint",
21+
"EditorConfig.EditorConfig",
22+
"esbenp.prettier-vscode"
1723
],
1824
"settings": {
1925
"terminal.integrated.defaultProfile.linux": "zsh"
@@ -29,6 +35,7 @@
2935
"mounts": [
3036
"source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind",
3137
"source=${localEnv:HOME}/.claude,target=/home/odoo/.claude,type=bind",
38+
"source=${localEnv:HOME}/.claude.json,target=/home/odoo/.claude.json,type=bind",
3239
"source=${localEnv:HOME}/.gitconfig,target=/home/odoo/.gitconfig-host,type=bind,readonly",
3340
"source=${localEnv:HOME}/.config/gh,target=/home/odoo/.config/gh,type=bind",
3441
"source=${localEnv:HOME}/.ssh,target=/home/odoo/.ssh-host,type=bind,readonly",
@@ -39,20 +46,24 @@
3946
"workspaceMount": "source=${localWorkspaceFolder},target=/workspaces/dswd-4ps-dp-openspp,type=bind",
4047
"workspaceFolder": "/workspaces/dswd-4ps-dp-openspp",
4148

42-
"forwardPorts": [11111, 8069, 5432, 8081, 8025, 9001],
49+
"forwardPorts": [11111, 8069, 5432, 8081, 8025, 9001, 5174, 3000, 3001, 3456],
4350
"portsAttributes": {
4451
"11111": { "label": "OpenSPP (nginx)", "onAutoForward": "notify" },
4552
"8069": { "label": "Odoo (direct)", "onAutoForward": "silent" },
4653
"5432": { "label": "PostgreSQL", "onAutoForward": "silent" },
4754
"8081": { "label": "pgweb", "onAutoForward": "notify" },
4855
"8025": { "label": "Mailpit", "onAutoForward": "notify" },
49-
"9001": { "label": "Supervisor", "onAutoForward": "silent" }
56+
"9001": { "label": "Supervisor", "onAutoForward": "silent" },
57+
"5174": { "label": "Mobile (Vue/Vite)", "onAutoForward": "notify" },
58+
"3000": { "label": "Datacollect Backend", "onAutoForward": "silent" },
59+
"3001": { "label": "Datacollect Admin", "onAutoForward": "silent" },
60+
"3456": { "label": "Mobile SQLite dev", "onAutoForward": "silent" }
5061
},
5162
"otherPortsAttributes": {
5263
"onAutoForward": "ignore"
5364
},
5465

55-
"postCreateCommand": "sudo chown -R odoo:odoo /workspaces/dswd-4ps-dp-openspp /home/odoo/.claude /home/odoo/.config 2>/dev/null; cp /home/odoo/.gitconfig-host /home/odoo/.gitconfig 2>/dev/null || true; mkdir -p /home/odoo/.ssh && cp -a /home/odoo/.ssh-host/. /home/odoo/.ssh/ 2>/dev/null || true; chmod 700 /home/odoo/.ssh && chmod 600 /home/odoo/.ssh/* 2>/dev/null; chmod 644 /home/odoo/.ssh/*.pub /home/odoo/.ssh/config /home/odoo/.ssh/known_hosts 2>/dev/null || true; cd /workspaces/dswd-4ps-dp-openspp/DSWD/dswd-4ps-dp-openspp-v2-module && pre-commit install --install-hooks 2>/dev/null || true",
66+
"postCreateCommand": "sudo chown -R odoo:odoo /workspaces/dswd-4ps-dp-openspp /home/odoo/.claude /home/odoo/.config 2>/dev/null; cp /home/odoo/.gitconfig-host /home/odoo/.gitconfig 2>/dev/null || true; mkdir -p /home/odoo/.ssh && cp -a /home/odoo/.ssh-host/. /home/odoo/.ssh/ 2>/dev/null || true; chmod 700 /home/odoo/.ssh && chmod 600 /home/odoo/.ssh/* 2>/dev/null; chmod 644 /home/odoo/.ssh/*.pub /home/odoo/.ssh/config /home/odoo/.ssh/known_hosts 2>/dev/null || true; cd /workspaces/dswd-4ps-dp-openspp/DSWD/dswd-4ps-dp-openspp-v2-module && pre-commit install --install-hooks 2>/dev/null || true; [ -f /workspaces/dswd-4ps-dp-openspp/mobile/package.json ] && (cd /workspaces/dswd-4ps-dp-openspp/mobile && git submodule update --init --recursive 2>/dev/null; pnpm install --frozen-lockfile 2>/dev/null || pnpm install) || true",
5667
"postStartCommand": "cp /home/odoo/.gitconfig-host /home/odoo/.gitconfig 2>/dev/null || true; cp -a /home/odoo/.ssh-host/. /home/odoo/.ssh/ 2>/dev/null || true; chmod 700 /home/odoo/.ssh && chmod 600 /home/odoo/.ssh/* 2>/dev/null; chmod 644 /home/odoo/.ssh/*.pub /home/odoo/.ssh/config /home/odoo/.ssh/known_hosts 2>/dev/null || true; nohup sudo /usr/bin/supervisord -c /etc/supervisor/supervisord.conf > /tmp/supervisord.log 2>&1 & sleep 2 && sudo chmod 666 /var/run/docker.sock 2>/dev/null || true",
5768
"postAttachCommand": "PUB_KEY=$(ssh-add -L 2>/dev/null | grep -E '^ssh-' | head -1); [ -n \"$PUB_KEY\" ] && git config --global user.signingkey \"key::$PUB_KEY\" && echo 'Git signing key set from SSH agent' || echo 'WARNING: SSH agent not available or no keys loaded, signing key not updated'"
5869
}

.devcontainer/initialize-host.sh

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ link_or_create() {
5050
}
5151

5252
link_or_create ".claude" d
53+
link_or_create ".claude.json" f
5354
link_or_create ".gitconfig" f
5455
link_or_create ".ssh" d
5556
# SSH requires strict permissions on key files
@@ -62,11 +63,21 @@ fi
6263
mkdir -p "$HOME/.config"
6364
link_or_create ".config/gh" d
6465

65-
# Ensure submodules are checked out (skip if already populated, don't fail the build)
66+
# Subscription auth files: always mirror from Windows so re-logins propagate.
67+
# (link_or_create uses --ignore-existing, which would otherwise leave stale auth.)
68+
if [ -n "$win_home" ]; then
69+
for f in ".claude.json" ".claude/.credentials.json"; do
70+
if [ -f "$win_home/$f" ]; then
71+
cp -f "$win_home/$f" "$HOME/$f" 2>/dev/null || true
72+
fi
73+
done
74+
fi
75+
76+
# Ensure submodules are checked out — only when something is uninitialized
77+
# (a leading '-' in `submodule status` means the submodule has no working tree).
6678
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
67-
echo "==> Checking git submodules..."
68-
git -C "$REPO_ROOT" submodule update --init --recursive 2>/dev/null || {
69-
echo " WARNING: submodule update failed — skipping."
70-
echo " If DSWD/dswd-4ps-dp-openspp-v2-module is empty, clone it manually."
71-
}
72-
echo " Submodules done."
79+
if git -C "$REPO_ROOT" submodule status --recursive 2>/dev/null | grep -q '^-'; then
80+
echo "==> Initializing missing git submodules..."
81+
git -C "$REPO_ROOT" submodule update --init --recursive 2>/dev/null || \
82+
echo " WARNING: submodule update failed — initialize manually if needed."
83+
fi

.devcontainer/supervisord.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ stopsignal=INT
2020
autostart=true
2121

2222
[program:createuser]
23-
command=/bin/sh -c "until pg_isready -q; do sleep 1; done && (createuser --superuser --echo odoo || true) && (echo \"ALTER USER odoo WITH PASSWORD 'odoo';\" | psql) && (createdb -O odoo odoo || true)"
23+
command=/bin/sh -c "until pg_isready -q; do sleep 1; done && (createuser --superuser --echo odoo || true) && (echo \"ALTER USER odoo WITH PASSWORD 'odoo';\" | psql) && (createdb -O odoo odoo || true) && (createuser --echo dswd4ps || true) && (echo \"ALTER USER dswd4ps WITH PASSWORD 'dswd4ps';\" | psql) && (createdb -O dswd4ps datacollect || true)"
2424
user=postgres
2525
environment=PGUSER="",PGPASSWORD="",PGDATABASE=""
2626
startsecs=0

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,3 +188,9 @@ mailpit.sh
188188
# Claude Code plugin directories (Windows paths accidentally created as Linux dirs in WSL)
189189
C:*
190190
scripts/restore_dev_config.sh
191+
192+
# Node / pnpm (mobile submodule may create these at outer root)
193+
node_modules/
194+
.pnpm-store/
195+
pnpm-debug.log*
196+
npm-debug.log*

.gitmodules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,7 @@
66
path = keycloak/dswd-4ps-dp-keycloak-login-theme
77
url = https://github.com/newlogic/dswd-4ps-dp-keycloak-login-theme.git
88
branch = main
9+
[submodule "mobile"]
10+
path = mobile
11+
url = git@github.com:newlogic/dswd-4ps-dp-mobile.git
12+
branch = develop

.vscode/launch.json

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
{
22
"version": "0.2.0",
3+
"compounds": [
4+
{
5+
"name": "Mobile: Run All",
6+
"configurations": [
7+
"Datacollect Backend: Dev",
8+
"Datacollect Admin: Dev",
9+
"DSWD Mobile: Dev"
10+
]
11+
}
12+
],
313
"configurations": [
414
{
515
"name": "Odoo: Server (Hot Reload)",
@@ -129,6 +139,45 @@
129139
"env": { "TZ": "UTC" },
130140
"console": "integratedTerminal",
131141
"justMyCode": false
142+
},
143+
{
144+
"name": "DSWD Mobile: Dev",
145+
"type": "node-terminal",
146+
"request": "launch",
147+
"command": "pnpm dev",
148+
"cwd": "${workspaceFolder:mobile}"
149+
},
150+
{
151+
"name": "Datacollect Backend: Dev",
152+
"type": "node-terminal",
153+
"request": "launch",
154+
"command": "pnpm dev",
155+
"env": {
156+
"POSTGRES": "postgresql://dswd4ps:dswd4ps@localhost:5432/datacollect",
157+
"ADMIN_EMAIL": "admin@datacollect.lan",
158+
"ADMIN_PASSWORD": "correct horse battery staple 42!",
159+
"JWT_SECRET": "Council of Elrond",
160+
"NODE_ENV": "development"
161+
},
162+
"cwd": "${workspaceFolder:mobile}/idpass-data-collect/packages/backend"
163+
},
164+
{
165+
"name": "Datacollect Admin: Dev",
166+
"type": "node-terminal",
167+
"request": "launch",
168+
"command": "pnpm dev --port 3001",
169+
"env": {
170+
"VITE_API_URL": "http://localhost:3000"
171+
},
172+
"cwd": "${workspaceFolder:mobile}/idpass-data-collect/packages/admin"
173+
},
174+
{
175+
"name": "Mobile: Debug in Chrome",
176+
"type": "chrome",
177+
"request": "launch",
178+
"url": "http://localhost:5174",
179+
"webRoot": "${workspaceFolder:mobile}/src",
180+
"sourceMaps": true
132181
}
133182
],
134183
"inputs": [

0 commit comments

Comments
 (0)