mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-01-22 18:30:09 +00:00
fix(sync): restore missing force upload button in new config UI
This commit is contained in:
parent
b230216e33
commit
222b3474b8
7 changed files with 502 additions and 97 deletions
36
FIX_PLAN.md
Normal file
36
FIX_PLAN.md
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# 🛠️ Fix Plan: Restore Force Upload Button
|
||||
|
||||
**Branch:** `fix/restore-force-upload-ui`
|
||||
**Base:** `upstream/master` (Latest RC)
|
||||
**Goal:** Restore the "Force Upload" button lost during the Tabbed UI migration. This is critical for resolving Sync deadlocks (e.g. WebDAV 412 Precondition Failed).
|
||||
|
||||
## 📋 Steps
|
||||
|
||||
1. [x] **Setup:**
|
||||
- Stashed personal user config.
|
||||
- Created clean branch `fix/restore-force-upload-ui`.
|
||||
|
||||
2. [ ] **Code Changes:**
|
||||
- `src/app/imex/sync/sync-wrapper.service.ts`:
|
||||
- Change `private _forceUpload()` to `public forceUpload()`.
|
||||
- `src/app/pages/config-page/config-page.component.ts`:
|
||||
- Add the "Force Upload" button to the `globalSyncConfigFormCfg` configuration array.
|
||||
- Use `btnType: 'warn'` to indicate destructive action.
|
||||
- Ensure it calls `this._syncWrapperService.forceUpload()`.
|
||||
|
||||
3. [ ] **Verification:**
|
||||
- Build locally (`npm run dist` or similar) to ensure compilation passes.
|
||||
- (Optional) Verify UI appearance if possible.
|
||||
|
||||
4. [ ] **PR Submission:**
|
||||
- Commit with convention: `fix(sync): restore missing force upload button in new config UI`.
|
||||
- Push to `origin` (mycochang/super-productivity).
|
||||
- Open PR to `super-productivity/super-productivity`.
|
||||
|
||||
5. [ ] **Cleanup:**
|
||||
- Switch back to user working branch.
|
||||
- Pop stash to restore personal context.
|
||||
|
||||
## 📝 Context & Rationale
|
||||
|
||||
The "Force Upload" button existed in v16 but was accidentally omitted during the Config Page rewrite (RC.6+). Without it, users facing "Remote file changed" errors have no in-app way to resolve the conflict, forcing manual file deletion on the server.
|
||||
509
package-lock.json
generated
509
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":";AAAA,0CAA0C;AAC1C,gEAAgE;;;AAShE,IAAY,WAYX;AAZD,WAAY,WAAW;IACrB,2CAA4B,CAAA;IAC5B,6CAA8B,CAAA;IAC9B,yCAA0B,CAAA;IAC1B,yCAA0B,CAAA;IAC1B,wDAAyC,CAAA;IACzC,uCAAwB,CAAA;IACxB,iDAAkC,CAAA;IAClC,4DAA6C,CAAA;IAC7C,gCAAiB,CAAA;IACjB,gDAAiC,CAAA;IACjC,wDAAyC,CAAA;AAC3C,CAAC,EAZW,WAAW,2BAAX,WAAW,QAYtB;AA+eD;;;GAGG;AACH,IAAY,uBAoBX;AApBD,WAAY,uBAAuB;IACjC,oBAAoB;IACpB,uDAA4B,CAAA;IAC5B,+DAAoC,CAAA;IACpC,yDAA8B,CAAA;IAE9B,cAAc;IACd,2DAAgC,CAAA;IAEhC,qBAAqB;IACrB,6EAAkD,CAAA;IAClD,mFAAwD,CAAA;IAExD,qBAAqB;IACrB,qDAA0B,CAAA;IAC1B,uEAA4C,CAAA;IAC5C,iEAAsC,CAAA;IAEtC,mBAAmB;IACnB,iDAAsB,CAAA;AACxB,CAAC,EApBW,uBAAuB,uCAAvB,uBAAuB,QAoBlC;AAED,6CAA6C;AAC7C,2EAA2E;AAC3E,mBAAmB;AACnB,uBAAuB;AACvB,4BAA4B;AAC5B,MAAM;AACN,EAAE;AACF,uDAAuD;AACvD,gCAAgC;AAChC,IAAI"}
|
||||
{"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":";AAAA,0CAA0C;AAC1C,gEAAgE;;;AAShE,IAAY,WAYX;AAZD,WAAY,WAAW;IACrB,2CAA4B,CAAA;IAC5B,6CAA8B,CAAA;IAC9B,yCAA0B,CAAA;IAC1B,yCAA0B,CAAA;IAC1B,wDAAyC,CAAA;IACzC,uCAAwB,CAAA;IACxB,iDAAkC,CAAA;IAClC,4DAA6C,CAAA;IAC7C,gCAAiB,CAAA;IACjB,gDAAiC,CAAA;IACjC,wDAAyC,CAAA;AAC3C,CAAC,EAZW,WAAW,2BAAX,WAAW,QAYtB;AAkfD;;;GAGG;AACH,IAAY,uBAoBX;AApBD,WAAY,uBAAuB;IACjC,oBAAoB;IACpB,uDAA4B,CAAA;IAC5B,+DAAoC,CAAA;IACpC,yDAA8B,CAAA;IAE9B,cAAc;IACd,2DAAgC,CAAA;IAEhC,qBAAqB;IACrB,6EAAkD,CAAA;IAClD,mFAAwD,CAAA;IAExD,qBAAqB;IACrB,qDAA0B,CAAA;IAC1B,uEAA4C,CAAA;IAC5C,iEAAsC,CAAA;IAEtC,mBAAmB;IACnB,iDAAsB,CAAA;AACxB,CAAC,EApBW,uBAAuB,uCAAvB,uBAAuB,QAoBlC;AAED,6CAA6C;AAC7C,2EAA2E;AAC3E,mBAAmB;AACnB,uBAAuB;AACvB,4BAA4B;AAC5B,MAAM;AACN,EAAE;AACF,uDAAuD;AACvD,gCAAgC;AAChC,IAAI"}
|
||||
7
packages/plugin-dev/package-lock.json
generated
7
packages/plugin-dev/package-lock.json
generated
|
|
@ -105,6 +105,7 @@
|
|||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.4.tgz",
|
||||
"integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
|
|
@ -1226,6 +1227,7 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.33.tgz",
|
||||
"integrity": "sha512-wzoocdnnpSxZ+6CjW4ADCK1jVmd1S/J3ArNWfn8FDDQtRm8dkDg7TA+mvek2wNrfCgwuZxqEOiB9B1XCJ6+dbw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
|
|
@ -1519,6 +1521,7 @@
|
|||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001718",
|
||||
"electron-to-chromium": "^1.5.160",
|
||||
|
|
@ -2136,6 +2139,7 @@
|
|||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
|
|
@ -2275,6 +2279,7 @@
|
|||
"resolved": "https://registry.npmjs.org/seroval/-/seroval-1.3.2.tgz",
|
||||
"integrity": "sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
|
|
@ -2317,6 +2322,7 @@
|
|||
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.7.tgz",
|
||||
"integrity": "sha512-/saTKi8iWEM233n5OSi1YHCCuh66ZIQ7aK2hsToPe4tqGm7qAejU1SwNuTPivbWAYq7SjuHVVYxxuZQNRbICiw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"csstype": "^3.1.0",
|
||||
"seroval": "~1.3.0",
|
||||
|
|
@ -2526,6 +2532,7 @@
|
|||
"integrity": "sha512-C/Naxf8H0pBx1PA4BdpT+c/5wdqI9ILMdwjSMILw7tVIh3JsxzZqdeTLmmdaoh5MYUEOyBnM9K3o0DzoZ/fe+w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.5.0",
|
||||
|
|
|
|||
|
|
@ -311,7 +311,7 @@ export class SyncWrapperService {
|
|||
// TODO translate
|
||||
msg: T.F.SYNC.S.ERROR_DATA_IS_CURRENTLY_WRITTEN,
|
||||
type: 'ERROR',
|
||||
actionFn: async () => this._forceUpload(),
|
||||
actionFn: async () => this.forceUpload(),
|
||||
actionStr: T.F.SYNC.S.BTN_FORCE_OVERWRITE,
|
||||
});
|
||||
return 'HANDLED_ERROR';
|
||||
|
|
@ -357,7 +357,7 @@ export class SyncWrapperService {
|
|||
}
|
||||
}
|
||||
|
||||
private async _forceUpload(): Promise<void> {
|
||||
async forceUpload(): Promise<void> {
|
||||
if (!this._c(this._translateService.instant(T.F.SYNC.C.FORCE_UPLOAD))) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -462,7 +462,7 @@ export class SyncWrapperService {
|
|||
firstValueFrom(dialogRef.afterClosed())
|
||||
.then(async (res) => {
|
||||
if (res === 'FORCE_UPDATE_REMOTE') {
|
||||
await this._forceUpload();
|
||||
await this.forceUpload();
|
||||
} else if (res === 'FORCE_UPDATE_LOCAL') {
|
||||
// Op-log architecture handles this differently
|
||||
SyncLog.log(
|
||||
|
|
@ -490,7 +490,7 @@ export class SyncWrapperService {
|
|||
firstValueFrom(dialogRef.afterClosed())
|
||||
.then(async (res) => {
|
||||
if (res === 'FORCE_UPDATE_REMOTE') {
|
||||
await this._forceUpload();
|
||||
await this.forceUpload();
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
|
|
@ -530,7 +530,7 @@ export class SyncWrapperService {
|
|||
this.sync();
|
||||
}
|
||||
if (isForceUpload) {
|
||||
this._forceUpload();
|
||||
this.forceUpload();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -368,6 +368,20 @@ export class ConfigPageComponent implements OnInit, OnDestroy {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
hideExpression: (m: any, _v: any, field: any) =>
|
||||
!m.isEnabled || !field?.form?.valid,
|
||||
type: 'btn',
|
||||
className: 'mt2 block',
|
||||
templateOptions: {
|
||||
text: T.F.SYNC.C.FORCE_UPLOAD,
|
||||
btnType: 'warn',
|
||||
required: false,
|
||||
onClick: () => {
|
||||
this._syncWrapperService.forceUpload();
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
hideExpression: (m: any) =>
|
||||
!m.isEnabled || m.syncProvider !== LegacySyncProvider.SuperSync,
|
||||
|
|
|
|||
21
~/repos/super-productivity/cto.md
Normal file
21
~/repos/super-productivity/cto.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
- [ ] <!--yaB19mxBpu-dRz8XHgirg--> Custom SP Dashboard/Waybar Integration
|
||||
- [ ] <!--XSHbiVgRKJK4wAZaTz12B--> Make GitHub -> Taiga Bidirectional
|
||||
- [ ] <!--mOq-ocqA0vf49KEP7RMOz--> Jira Integration
|
||||
- [ ] <!--TSfixg5u7FCb-MXR0z8bo--> n8n Deployment
|
||||
- [ ] <!--bFrpNPJrmLosbcqKs7PBO--> Anytype Integration
|
||||
- [ ] <!--0GNMdDkLE2JsmITTfK-Om--> Taiga <-> Trello Bidirectional Sync
|
||||
- [ ] <!--rsqeql3D49Bdgg7_LBnCV--> use 3070 as primary on cachy on omen
|
||||
- [ ] <!--gqT0eV4SAQ3qVpNVed42Y--> Test pytaiga-mcp with Claude Desktop
|
||||
- [ ] <!--bENu9iWjOkTH2uTyinjFF--> Taiga -> Discord Webhook Relay
|
||||
- [ ] <!--lA05Xk_X8uclGvUH6jD9s--> #5 nadir filtering idea for efficient hi-res orthos
|
||||
- [ ] <!--H4FDHqQk_61RL6TbXrcyK--> #4 write to db / polish thie manifest file
|
||||
- [ ] <!--l6DDlByiAr4P1Z9uo4iS9--> #2 Track which flight types have automated processing pipelines
|
||||
- [x] <!--7AcwVNz3My0m1jnogLkCP--> Vibe ADHD Coaching
|
||||
- [ ] <!--2kxhONHQgatI_yHmiqHg0--> Explore WebSocket IPC transition LATER
|
||||
Something for the backlog.
|
||||
- [x] <!--3bXFyE7jzEY3SuHdNPWEB--> Draft technical documentation for SP-MCP SOON
|
||||
Reviewing the docs for future work.
|
||||
- [ ] <!--L4lWlqCOVmg_gvIE3kcYx--> Verify MCP tag assignment
|
||||
Initial cleanup of the workspace.
|
||||
- [ ] <!--aG51kRBGjHLkz2Sm8Htfb--> Perform final security audit URGENT
|
||||
Critical system check.
|
||||
Loading…
Add table
Add a link
Reference in a new issue