diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 1c1d829..c8c4999 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -79,13 +79,13 @@ quasar build # Office-specific commands npm run office-start # Start debugging in Excel npm run office-stop # Stop debugging session -npm run office-validate # Validate manifest.xml +npm run office-validate # Validate `ExpLens.Excel-AddIn.Manifest.Local.xml` ``` ### Environment & Configuration - Quasar config in `quasar.config.ts` with custom build env vars from `package.json` (version, name, etc.) -- Dev server runs on `http://localhost:9000` (referenced in `manifest.xml`) +- Dev server runs on `http://localhost:9000` (referenced in `ExpLens.Excel-AddIn.Manifest.Local.xml`) - Vue Router uses **hash mode** to avoid Office.js history issues - TypeScript with strict mode enabled diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cb3c11a..b23a6fd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -75,12 +75,42 @@ jobs: mkdir -p "docs/app/current/excel" cp -r dist/spa/* "docs/app/current/excel/" + - name: Prepare Manifest for the Current dir + continue-on-error: true + run: | + # Copy manifest file + if [ ! -f "ExpLens.Excel-AddIn.Manifest.Local.xml" ]; then + echo "Error: Source manifest file not found: ExpLens.Excel-AddIn.Manifest.Local.xml" + exit 1 + fi + + cp "ExpLens.Excel-AddIn.Manifest.Local.xml" "docs/app/current/excel/ExpLens.Excel-AddIn.Manifest.xml" + + if [ ! -f "docs/app/current/excel/ExpLens.Excel-AddIn.Manifest.xml" ]; then + echo "Error: Failed to copy manifest file to 'docs/app/current/excel/ExpLens.Excel-AddIn.Manifest.xml'" + exit 1 + fi + + # Replace localhost URL with production URL + sed -i 's|http://localhost:9000|https://explens.app|g' "docs/app/current/excel/ExpLens.Excel-AddIn.Manifest.xml" + + echo "Manifest for 'current' deployment prepared successfully" + + - name: Upload Manifest Artifact for the Current dir + continue-on-error: true + uses: actions/upload-artifact@v4 + with: + name: ExpLens.Excel-AddIn.Manifest.xml + path: docs/app/current/excel/ExpLens.Excel-AddIn.Manifest.xml + retention-days: 90 + compression-level: 0 + - name: Build project for Version Dir run: | VERSION=${{ steps.version.outputs.version }} npm run build --qPublicBasePath=app/$VERSION/excel - - name: Release to version dir + - name: Release to Version dir run: | VERSION=${{ steps.version.outputs.version }} # Create version directory @@ -91,6 +121,40 @@ jobs: # Copy dist/spa to docs/app/version/excel cp -r dist/spa/* "docs/app/$VERSION/excel/" + - name: Prepare Manifest for the Version dir + continue-on-error: true + run: | + VERSION=${{ steps.version.outputs.version }} + # Copy manifest file + if [ ! -f "ExpLens.Excel-AddIn.Manifest.Local.xml" ]; then + echo "Error: Source manifest file not found: ExpLens.Excel-AddIn.Manifest.Local.xml" + exit 1 + fi + + cp "ExpLens.Excel-AddIn.Manifest.Local.xml" "docs/app/$VERSION/excel/ExpLens.Excel-AddIn.Manifest.v_$VERSION.xml" + + if [ ! -f "docs/app/$VERSION/excel/ExpLens.Excel-AddIn.Manifest.v_$VERSION.xml" ]; then + echo "Error: Failed to copy manifest file to 'docs/app/$VERSION/excel/ExpLens.Excel-AddIn.Manifest.v_$VERSION.xml'" + exit 1 + fi + + # Replace localhost URL with production URL + sed -i 's|http://localhost:9000|https://explens.app|g' "docs/app/$VERSION/excel/ExpLens.Excel-AddIn.Manifest.v_$VERSION.xml" + + # Replace 'current' path with version-specific path + sed -i "s|app/current/|app/$VERSION/|g" "docs/app/$VERSION/excel/ExpLens.Excel-AddIn.Manifest.v_$VERSION.xml" + + echo "Manifest for 'version' deployment ($VERSION) prepared successfully" + + - name: Upload Manifest Artifact for the Version dir + continue-on-error: true + uses: actions/upload-artifact@v4 + with: + name: ExpLens.Excel-AddIn.Manifest.v_${{steps.version.outputs.version}}.xml + path: docs/app/${{steps.version.outputs.version}}/excel/ExpLens.Excel-AddIn.Manifest.v_${{steps.version.outputs.version}}.xml + retention-days: 90 + compression-level: 0 + - name: Commit and push changes env: PUSH_BRANCH: ${{ github.event.workflow_run.head_branch || github.ref_name }} diff --git a/manifest.xml b/ExpLens.Excel-AddIn.Manifest.Local.xml similarity index 71% rename from manifest.xml rename to ExpLens.Excel-AddIn.Manifest.Local.xml index 9bf5f25..c8539dd 100644 --- a/manifest.xml +++ b/ExpLens.Excel-AddIn.Manifest.Local.xml @@ -6,28 +6,26 @@ xmlns:ov="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="TaskPaneApp"> CC923F2C-0638-4F36-9E18-A4910CD71B74 - 0.1.0.0 - macrogreg + 1.0.0 + Advanced Personal Finance en-US - - - 500 - - - - - ReadWriteDocument - - - - + + + + + + https://explens.app https://lunchmoney.app https://github.com + + + + ReadWriteDocument EL.Taskpain-Id - <SourceLocation resid="Taskpane-Url"/> </Action> </Control> @@ -77,24 +74,24 @@ </Hosts> <Resources> <bt:Images> - <bt:Image id="Icon.16x16" DefaultValue="http://localhost:9000/icons/favicon-16x16.png"/> - <bt:Image id="Icon.32x32" DefaultValue="http://localhost:9000/icons/favicon-32x32.png"/> - <bt:Image id="Icon.80x80" DefaultValue="http://localhost:9000/icons/favicon-80x80.png"/> + <bt:Image id="Icon.16x16" DefaultValue="https://explens.app/images/favicon-16x16.png"/> + <bt:Image id="Icon.32x32" DefaultValue="https://explens.app/images/favicon-32x32.png"/> + <bt:Image id="Icon.80x80" DefaultValue="https://explens.app/images/favicon-80x80.png"/> </bt:Images> <bt:Urls> - <bt:Url id="GetStarted-LearnMoreUrl" DefaultValue="https://ToDo"/> - <bt:Url id="Taskpane-Url" DefaultValue="http://localhost:9000/index.html"/> + <bt:Url id="GetStarted-LearnMoreUrl" DefaultValue="https://explens.app"/> + <bt:Url id="Taskpane-Url" DefaultValue="http://localhost:9000/app/current/excel/index.html"/> </bt:Urls> <bt:ShortStrings> - <bt:String id="GetStarted-Title" DefaultValue="Bank Transactions Sync"/> - <bt:String id="TabGroup-Label" DefaultValue="ExpLens"/> - <bt:String id="ShowPaneButton-Label" DefaultValue="Show Pane"/> + <bt:String id="GetStarted-Title" DefaultValue="ExpLens"/> + <bt:String id="TabGroup-Label" DefaultValue="Finances"/> + <bt:String id="ShowPaneButton-Label" DefaultValue="ExpLens"/> <bt:String id="ShowPaneButton-Tip-Title" DefaultValue="Show ExpLens Task Pane"/> <bt:String id="Taskpain-Title" DefaultValue="ExpLens"/> </bt:ShortStrings> <bt:LongStrings> - <bt:String id="ShowPaneButton-Tip-Description" DefaultValue="Click to show the ExpLens task pane. Synchronize your Bank Transactions from there."/> - <bt:String id="GetStarted-Description" DefaultValue="Analyze your finances. Synchronize Bank Transactions with Lunch Money. To view: [HOME tab] > [ExpLens] > [Show Pane]."/> + <bt:String id="GetStarted-Description" DefaultValue="Analyze your finances. Import 2+ years of bank transactions. To view: [HOME tab] > [Finances] > [ExpLens]."/> + <bt:String id="ShowPaneButton-Tip-Description" DefaultValue="Click to show the ExpLens task pane. Synchronize your Bank Transactions from there."/> </bt:LongStrings> </Resources> </VersionOverrides> diff --git a/README.md b/README.md index 12d1561..51fed91 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,8 @@ ExpLens Excel-AddIn ### Intent -This project enables people to work with their financial data freely and effectively, without restrictions. However, to protect the effort invested in building and maintaining it, commercial/competitive use is restricted. +This project enables people to work with their financial data freely and effectively, without restrictions. +However, to protect the effort invested in building and maintaining it, commercial/competitive use is restricted. **Interested in commercial use? Reach out! We'll work out reasonable terms.** @@ -24,26 +25,89 @@ See [LICENSE.md](./LICENSE.md) for complete terms. - ✗ Building competing commercial products/services: _not allowed_. - ✗ Selling or hosting as a service: _not allowed_. -_Disclaimer: The authors and contributors accept no responsibility, direct or indirect, for any consequences from using this project._ +_Disclaimer: The authors and contributors accept no responsibility, direct or indirect, for any consequences from +using this project._ ## Developer guide -(This section is work in progress.) +(If some info was missing and you needed to figure it out, please create a pull request to add it here.) #### Install -```bash -npm install -``` +Clone the repo. Then: -#### Start the app in development mode (hot-code reloading, error reporting, etc.) +`npm install` or `npm ci` -```bash -quasar dev -``` +#### Build and start locally -#### Build the app for production +`npm run dev --qPublicBasePath=app/current/excel` +(this invokes `quasar dev` and passes a parameter to set the URL base the way Excel expects it) -```bash -quasar build -``` +Quasar will build the app and host it under `http://localhost:9000/app/current/excel/`. +Note: if port 9000 is taken, Quasar might silently choose another port. However, Excel will look for ExpLens on +port 9000. If you need to use another port, make sure to modify the manifest accordingly +(`ExpLens.Excel-AddIn.Manifest.xml`). + +##### Build for production + +`quasar build` or `npm run build --qPublicBasePath=url/base/path` + +#### Activate the Excel Add-In + +The _release_ version of ExpLens works on Excel Web and Excel Desktop (Windows & Mac). + +The instructions here are for the _dev_ version (Windows desktop). + +##### Option 1: "Admin Style" (easer to uninstall) + +1. Share the root folder of your cloned repo as a local network drive. + E.g., if you cloned into `c:\Code\ExpLens\` and your machine is called `DEV-PC`, then your share might be + called `\\DEV-PC\ExpLens`. + +2. In Excel, add the network share as a trusted Add-In Catalog: + - Go to: _File_ > _Options_ > _Trust Center_ > _Trust Center Settings_ > _Trusted Add-In Catalogs_. + - In _Catalog Url_, enter the address of your file share + (e.g., `\\DEV-PC\ExpLens`). + - Click _Add catalog_, select _Show in menu_, OK all dialogs, and restart Excel (make sure to close all windows). + +3. Activate the Add-In: + _Home_ > _Add-ins_ > _More Add-ins_. At the top you will have a _Shared Folder_ option. When you select it, you + will see the ExpLens add-in in the list. Install it. + +The Add-In will start and attempt to load from +`http://localhost:9000/app/current/excel/` + +(See section 'Build and start locally' above.) + +###### Uninstalling: + +Return to _Trusted Add-In Catalogs_, remove the shared repo directory, conform, and restart Excel (all windows). + +##### Option 2: "Dev Style" (easer to get started) + +1. Clone the repo and install packages. + (see above) + +2. Build and start the dev server. + (see above) + +3. Install the manifest using the Office AddIn tool: + `npm run office-start` + This will put some settings into the registry and open Excel with the Add-In loaded. + +The Add-In will start and attempt to load from +`http://localhost:9000/app/current/excel/` + +(See section 'Build and start locally' above.) + +###### Uninstalling: + +If you thought this was easier than the "Admin Style", then you have not yet tried to uninstall the +Add-In (which is a normal par of the dev process). +If you time it well, then this will do it: +`npm run office-stop` + +But some of the time the state required for the tool to correctly know how to uninstall is lost, and you have to +go to the registry. The add-ins are listed under: +`Computer\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\WEF\Developer`. +Find the one you want to remove, and delete all associated entries (there are several). diff --git a/package.json b/package.json index 9e7082b..d5611e1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "exp-lens-excel-addin", - "version": "0.0.1", + "version": "0.0.2", "description": "ExpLens Excel-AddIn", "productName": "ExpLens Excel-AddIn", "author": "macrogreg <macrogreg@users.noreply.github.com>", @@ -13,6 +13,7 @@ "format-check": "prettier --check \"**/*.{js,ts,vue,scss,html,md,json}\"", "test": "echo \"No test specified\" && exit 0", "dev": "quasar dev", + "dev-current": "npm run dev --qPublicBasePath=app/current/excel", "build": "quasar build", "postinstall": "quasar prepare", "licenses:generate": "license-checker-rseidelsohn --production --markdown --out license/THIRD-PARTY-LICENSES.md", @@ -22,9 +23,9 @@ "office-prettier": "office-addin-lint prettier", "office-signin": "office-addin-dev-settings m365-account login", "office-signout": "office-addin-dev-settings m365-account logout", - "office-start": "office-addin-debugging start manifest.xml", - "office-stop": "office-addin-debugging stop manifest.xml", - "office-validate": "office-addin-manifest validate manifest.xml" + "office-start": "office-addin-debugging start ExpLens.Excel-AddIn.Manifest.Local.xml", + "office-stop": "office-addin-debugging stop ExpLens.Excel-AddIn.Manifest.Local.xml", + "office-validate": "office-addin-manifest validate ExpLens.Excel-AddIn.Manifest.Local.xml" }, "dependencies": { "@quasar/extras": "^1.16.4", diff --git a/src/components/SyncTab.vue b/src/components/SyncTab.vue index 05c4876..f4f7a73 100644 --- a/src/components/SyncTab.vue +++ b/src/components/SyncTab.vue @@ -78,7 +78,7 @@ <div class="q-mb-sm"> <div class="text-primary text-weight-bold q-mb-xs" style="font-size: 0.7rem">Quick select:</div> <q-btn - color="primary" outline no-wrap no-caps dense label="Since Last Sync" class="q-mr-xs" + color="primary" outline no-wrap no-caps dense label="Since Last Sync" style="font-size: 0.8rem" class="q-mr-xs" :disable="isDataOperationInProgress || downloadDatesQuickSelectOptions.lastSync === null" @click="applyDownloadDatesQuickSelect(downloadDatesQuickSelectOptions.lastSync)"> <q-tooltip v-if="downloadDatesQuickSelectOptions.lastSync" @@ -91,7 +91,7 @@ </q-btn> <q-btn - color="primary" outline no-wrap no-caps dense label="Recent" class="q-mr-xs" + color="primary" outline no-wrap no-caps dense label="Recent" style="font-size: 0.8rem" class="q-mr-xs" :disable="isDataOperationInProgress || downloadDatesQuickSelectOptions.recent === null" @click="applyDownloadDatesQuickSelect(downloadDatesQuickSelectOptions.recent)"> <q-tooltip v-if="downloadDatesQuickSelectOptions.recent" @@ -103,7 +103,7 @@ </q-tooltip> </q-btn> <q-btn - color="primary" outline no-wrap no-caps dense label="Last 24 months" + color="primary" outline no-wrap no-caps dense label="Last 24 months" style="font-size: 0.8rem" :disable="isDataOperationInProgress || downloadDatesQuickSelectOptions.last24Months === null" @click="applyDownloadDatesQuickSelect(downloadDatesQuickSelectOptions.last24Months)"> <q-tooltip v-if="downloadDatesQuickSelectOptions.last24Months" @@ -116,8 +116,8 @@ </q-btn> </div> - <div class="date-inputs" style="display: flex; gap: 16px"> - <div style="max-width: 220px; width: 100%"> + <div class="date-inputs" style="display: flex; gap: 5px"> + <div style="max-width: 120px; width: 100%"> <q-input :disable="isDataOperationInProgress" filled @@ -127,12 +127,13 @@ :error="!!downloadStartDateError" :rules="[syncDateAgeRule]" @update:model-value="downloadStartDateError = ''" + style="font-size: 0.75rem" /> <div v-if="downloadStartDateError" class="text-negative q-mt-xs"> {{ downloadStartDateError }} </div> </div> - <div style="max-width: 220px; width: 100%"> + <div style="max-width: 120px; width: 100%"> <q-input :disable="isDataOperationInProgress" filled @@ -142,6 +143,7 @@ :error="!!downloadEndDateError" :rules="[syncDateAgeRule]" @update:model-value="downloadStartDateError = ''" + style="font-size: 0.75rem" /> <div v-if="downloadEndDateError" class="text-negative q-mt-xs">{{ downloadEndDateError }}</div> </div> @@ -159,8 +161,18 @@ no-caps dense :options="[ - { value: true, label: 'Overwrite Existing', icon: 'note_alt' }, - { value: false, label: 'Download New Only', icon: 'note_add' }, + { + value: true, + label: 'Overwrite Existing', + icon: 'note_alt', + attrs: { style: 'font-size: 0.7rem' }, + }, + { + value: false, + label: 'Download New Only', + icon: 'note_add', + attrs: { style: 'font-size: 0.7rem' }, + }, ]" > </q-btn-toggle> diff --git a/src/composables/app-version.ts b/src/composables/app-version.ts deleted file mode 100644 index ddab5be..0000000 --- a/src/composables/app-version.ts +++ /dev/null @@ -1 +0,0 @@ -export const AddInAppVersion = "0.1.0-alpha"; diff --git a/src/pages/IndexPage.vue b/src/pages/IndexPage.vue index 492b271..d44b7b4 100644 --- a/src/pages/IndexPage.vue +++ b/src/pages/IndexPage.vue @@ -3,8 +3,8 @@ <div class="main-content q-pa-md"> <div class="title-bar"> <h1 class="title-name">ExpLens</h1> - <div class="title-version">{{ AddInAppVersion }}</div> - <img src="/icons/favicon-32x32.png" alt="Logo" class="title-logo" /> + <div class="title-version">{{ packageVersion }}</div> + <img src="icons/favicon-32x32.png" alt="Logo" class="title-logo" /> </div> <q-tabs v-model="activeTab" inline-label align="center" class="q-mb-md" indicator-color="tab-bar-active"> @@ -117,15 +117,27 @@ </style> <script setup lang="ts"> -import { ref, onMounted } from "vue"; - console.debug("ExpLens Excel-AddIn: Loading IndexPage..."); -onMounted(async () => {}); +import { ref, onMounted } from "vue"; import SyncTab from "components/SyncTab.vue"; import AnalyzeTab from "components/AnalyzeTab.vue"; import SettingsTab from "components/SettingsTab.vue"; -import { AddInAppVersion } from "src/composables/app-version"; + +function getAppPackageVersion(): string { + let packageVersion = process.env.PACKAGE_VERSION ?? "_unspecified_"; + + const semVerZeroSuffix = ".0.0" as const; + if (packageVersion.endsWith(semVerZeroSuffix)) { + packageVersion = packageVersion.slice(0, packageVersion.length - semVerZeroSuffix.length); + } + + return packageVersion; +} + +const packageVersion = getAppPackageVersion(); const activeTab = ref("sync"); + +onMounted(async () => {}); </script>