Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
949487629d | ||
|
|
79593f12b4 | ||
|
|
1ac60dc5ba | ||
|
|
31396dd555 | ||
|
|
c91ac135b3 | ||
|
|
1dc534b61f | ||
|
|
7df52312ba | ||
|
|
d30597a921 | ||
|
|
c969c536bf | ||
|
|
5cf1759653 |
+6
-2
@@ -1,10 +1,14 @@
|
|||||||
|
|
||||||
# Only the variables that start with VITE_ are seen in the application import.meta.env in Vue.
|
# Only the variables that start with VITE_ are seen in the application import.meta.env in Vue.
|
||||||
|
|
||||||
|
# Logging Configuration - Development environment gets maximum visibility
|
||||||
|
VITE_LOG_LEVEL=debug
|
||||||
|
|
||||||
# iOS doesn't like spaces in the app title.
|
# iOS doesn't like spaces in the app title.
|
||||||
TIME_SAFARI_APP_TITLE="TimeSafari_Dev"
|
TIME_SAFARI_APP_TITLE="TimeSafari_Dev"
|
||||||
VITE_APP_SERVER=http://localhost:8080
|
VITE_APP_SERVER=http://localhost:8080
|
||||||
# This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not production).
|
# This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not
|
||||||
|
|
||||||
|
|
||||||
VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F
|
VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F
|
||||||
VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000
|
VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000
|
||||||
# Using shared server by default to ease setup, which works for shared test users.
|
# Using shared server by default to ease setup, which works for shared test users.
|
||||||
|
|||||||
+2
-1
@@ -1,6 +1,7 @@
|
|||||||
# Only the variables that start with VITE_ are seen in the application import.meta.env in Vue.
|
# Only the variables that start with VITE_ are seen in the application import.meta.env in Vue.
|
||||||
|
|
||||||
|
# Logging Configuration - Production environment gets minimal logging for performance
|
||||||
|
VITE_LOG_LEVEL=warn
|
||||||
|
|
||||||
VITE_APP_SERVER=https://timesafari.app
|
VITE_APP_SERVER=https://timesafari.app
|
||||||
# This is the claim ID for actions in the BVC project.
|
# This is the claim ID for actions in the BVC project.
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
# Only the variables that start with VITE_ are seen in the application import.meta.env in Vue.
|
# Only the variables that start with VITE_ are seen in the application import.meta.env in Vue.
|
||||||
|
|
||||||
|
# Logging Configuration - Test environment gets balanced logging for debugging
|
||||||
|
VITE_LOG_LEVEL=info
|
||||||
|
|
||||||
# iOS doesn't like spaces in the app title.
|
# iOS doesn't like spaces in the app title.
|
||||||
TIME_SAFARI_APP_TITLE="TimeSafari_Test"
|
TIME_SAFARI_APP_TITLE="TimeSafari_Test"
|
||||||
VITE_APP_SERVER=https://test.timesafari.app
|
VITE_APP_SERVER=https://test.timesafari.app
|
||||||
# This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not production).
|
# This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not
|
||||||
|
production).
|
||||||
|
|
||||||
VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F
|
VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F
|
||||||
VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch
|
VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,35 @@ See [BUILDING.md](BUILDING.md) for comprehensive build instructions for all plat
|
|||||||
|
|
||||||
TimeSafari provides a simple script-based approach to clear the local database (not the claim server) for development purposes.
|
TimeSafari provides a simple script-based approach to clear the local database (not the claim server) for development purposes.
|
||||||
|
|
||||||
|
## Logging Configuration
|
||||||
|
|
||||||
|
TimeSafari supports configurable logging levels via the `VITE_LOG_LEVEL` environment variable. This allows developers to control console output verbosity without modifying code.
|
||||||
|
|
||||||
|
### Quick Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Show only errors
|
||||||
|
VITE_LOG_LEVEL=error npm run dev
|
||||||
|
|
||||||
|
# Show warnings and errors
|
||||||
|
VITE_LOG_LEVEL=warn npm run dev
|
||||||
|
|
||||||
|
# Show info, warnings, and errors (default)
|
||||||
|
VITE_LOG_LEVEL=info npm run dev
|
||||||
|
|
||||||
|
# Show all log levels including debug
|
||||||
|
VITE_LOG_LEVEL=debug npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Available Levels
|
||||||
|
|
||||||
|
- **`error`**: Critical errors only
|
||||||
|
- **`warn`**: Warnings and errors (default for production web)
|
||||||
|
- **`info`**: Info, warnings, and errors (default for development/capacitor)
|
||||||
|
- **`debug`**: All log levels including verbose debugging
|
||||||
|
|
||||||
|
See [Logging Configuration Guide](doc/logging-configuration.md) for complete details.
|
||||||
|
|
||||||
### Quick Usage
|
### Quick Usage
|
||||||
```bash
|
```bash
|
||||||
# Run the database clearing script
|
# Run the database clearing script
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
# Logging Configuration Guide
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
TimeSafari now supports configurable logging levels via the `VITE_LOG_LEVEL` environment variable. This allows developers to control the verbosity of console output without modifying code.
|
||||||
|
|
||||||
|
## Available Log Levels
|
||||||
|
|
||||||
|
| Level | Value | Description | Console Output |
|
||||||
|
|-------|-------|-------------|----------------|
|
||||||
|
| `error` | 0 | Errors only | Critical errors only |
|
||||||
|
| `warn` | 1 | Warnings and errors | Warnings and errors |
|
||||||
|
| `info` | 2 | Info, warnings, and errors | General information, warnings, and errors |
|
||||||
|
| `debug` | 3 | All log levels | Verbose debugging information |
|
||||||
|
|
||||||
|
## Environment Variable
|
||||||
|
|
||||||
|
Set the `VITE_LOG_LEVEL` environment variable to control logging:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Show only errors
|
||||||
|
VITE_LOG_LEVEL=error
|
||||||
|
|
||||||
|
# Show warnings and errors (default for production web)
|
||||||
|
VITE_LOG_LEVEL=warn
|
||||||
|
|
||||||
|
# Show info, warnings, and errors (default for development/capacitor)
|
||||||
|
VITE_LOG_LEVEL=info
|
||||||
|
|
||||||
|
# Show all log levels including debug
|
||||||
|
VITE_LOG_LEVEL=debug
|
||||||
|
```
|
||||||
|
|
||||||
|
## Default Behavior by Platform
|
||||||
|
|
||||||
|
The logger automatically selects appropriate default log levels based on your platform and environment:
|
||||||
|
|
||||||
|
- **Production Web**: `warn` (warnings and errors only)
|
||||||
|
- **Electron**: `error` (errors only - very quiet)
|
||||||
|
- **Development/Capacitor**: `info` (info and above)
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
### Setting Log Level in Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# In your terminal before running the app
|
||||||
|
export VITE_LOG_LEVEL=debug
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# Or inline
|
||||||
|
VITE_LOG_LEVEL=debug npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Setting Log Level in Production
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# For verbose production logging
|
||||||
|
VITE_LOG_LEVEL=info npm run build:web
|
||||||
|
|
||||||
|
# For minimal production logging
|
||||||
|
VITE_LOG_LEVEL=warn npm run build:web
|
||||||
|
```
|
||||||
|
|
||||||
|
### Programmatic Access
|
||||||
|
|
||||||
|
The logger provides methods to check current configuration:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { logger } from '@/utils/logger';
|
||||||
|
|
||||||
|
// Get current log level
|
||||||
|
const currentLevel = logger.getCurrentLevel(); // 'info'
|
||||||
|
|
||||||
|
// Check if a level is enabled
|
||||||
|
const debugEnabled = logger.isLevelEnabled('debug'); // false if level < debug
|
||||||
|
|
||||||
|
// Get available levels
|
||||||
|
const levels = logger.getAvailableLevels(); // ['error', 'warn', 'info', 'debug']
|
||||||
|
```
|
||||||
|
|
||||||
|
## Database Logging
|
||||||
|
|
||||||
|
Database logging continues to work regardless of console log level settings. All log messages are still stored in the database for debugging and audit purposes.
|
||||||
|
|
||||||
|
## Migration Notes
|
||||||
|
|
||||||
|
- **Existing code**: No changes required - logging behavior remains the same
|
||||||
|
- **New feature**: Use `VITE_LOG_LEVEL` to override default behavior
|
||||||
|
- **Backward compatible**: All existing logging calls work as before
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Development**: Use `VITE_LOG_LEVEL=debug` for maximum visibility
|
||||||
|
2. **Testing**: Use `VITE_LOG_LEVEL=info` for balanced output
|
||||||
|
3. **Production**: Use `VITE_LOG_LEVEL=warn` for minimal noise
|
||||||
|
4. **Debugging**: Temporarily set `VITE_LOG_LEVEL=debug` to troubleshoot issues
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### No Logs Appearing
|
||||||
|
|
||||||
|
Check your `VITE_LOG_LEVEL` setting:
|
||||||
|
```bash
|
||||||
|
echo $VITE_LOG_LEVEL
|
||||||
|
```
|
||||||
|
|
||||||
|
### Too Many Logs
|
||||||
|
|
||||||
|
Reduce verbosity by setting a lower log level:
|
||||||
|
```bash
|
||||||
|
VITE_LOG_LEVEL=warn
|
||||||
|
```
|
||||||
|
|
||||||
|
### Platform-Specific Issues
|
||||||
|
|
||||||
|
Remember that Electron is very quiet by default. Use `VITE_LOG_LEVEL=info` to see more output in Electron builds.
|
||||||
Generated
+1
-1
@@ -96,7 +96,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@capacitor/assets": "^3.0.5",
|
"@capacitor/assets": "^3.0.5",
|
||||||
"@playwright/test": "^1.45.2",
|
"@playwright/test": "^1.54.2",
|
||||||
"@types/dom-webcodecs": "^0.1.7",
|
"@types/dom-webcodecs": "^0.1.7",
|
||||||
"@types/jest": "^30.0.0",
|
"@types/jest": "^30.0.0",
|
||||||
"@types/js-yaml": "^4.0.9",
|
"@types/js-yaml": "^4.0.9",
|
||||||
|
|||||||
+1
-1
@@ -204,7 +204,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@capacitor/assets": "^3.0.5",
|
"@capacitor/assets": "^3.0.5",
|
||||||
"@playwright/test": "^1.45.2",
|
"@playwright/test": "^1.54.2",
|
||||||
"@types/dom-webcodecs": "^0.1.7",
|
"@types/dom-webcodecs": "^0.1.7",
|
||||||
"@types/jest": "^30.0.0",
|
"@types/jest": "^30.0.0",
|
||||||
"@types/js-yaml": "^4.0.9",
|
"@types/js-yaml": "^4.0.9",
|
||||||
|
|||||||
@@ -300,18 +300,20 @@ serve_build() {
|
|||||||
exit 5
|
exit 5
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Use a simple HTTP server to serve the build
|
# Use a server that supports SPA routing (serves index.html for all routes)
|
||||||
if command -v python3 &> /dev/null; then
|
if command -v npx &> /dev/null; then
|
||||||
|
log_info "Starting npx serve with SPA support on port 8080..."
|
||||||
|
npx serve -s dist -l 8080
|
||||||
|
elif command -v python3 &> /dev/null; then
|
||||||
|
log_warn "Python HTTP server doesn't support SPA routing. Routes like /discover, /account will return 404."
|
||||||
log_info "Starting Python HTTP server on port 8080..."
|
log_info "Starting Python HTTP server on port 8080..."
|
||||||
cd dist && python3 -m http.server 8080
|
cd dist && python3 -m http.server 8080
|
||||||
elif command -v python &> /dev/null; then
|
elif command -v python &> /dev/null; then
|
||||||
|
log_warn "Python HTTP server doesn't support SPA routing. Routes like /discover, /account will return 404."
|
||||||
log_info "Starting Python HTTP server on port 8080..."
|
log_info "Starting Python HTTP server on port 8080..."
|
||||||
cd dist && python -m SimpleHTTPServer 8080
|
cd dist && python -m SimpleHTTPServer 8080
|
||||||
elif command -v npx &> /dev/null; then
|
|
||||||
log_info "Starting npx serve on port 8080..."
|
|
||||||
npx serve -s dist -l 8080
|
|
||||||
else
|
else
|
||||||
log_error "No suitable HTTP server found. Install Python or npx serve."
|
log_error "No suitable HTTP server found. Install npx serve or Python."
|
||||||
exit 5
|
exit 5
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
+43
-22
@@ -27,9 +27,13 @@
|
|||||||
v-if="notification.type === 'toast'"
|
v-if="notification.type === 'toast'"
|
||||||
class="w-full max-w-sm mx-auto mb-3 overflow-hidden bg-slate-900/90 text-white rounded-lg shadow-md"
|
class="w-full max-w-sm mx-auto mb-3 overflow-hidden bg-slate-900/90 text-white rounded-lg shadow-md"
|
||||||
>
|
>
|
||||||
<div class="w-full px-4 py-3">
|
<div class="w-full px-4 py-3 overflow-hidden">
|
||||||
<span class="font-semibold">{{ notification.title }}</span>
|
<h4 class="font-semibold text-ellipsis overflow-hidden">
|
||||||
<p class="text-sm">{{ notification.text }}</p>
|
{{ notification.title }}
|
||||||
|
</h4>
|
||||||
|
<p class="text-sm text-ellipsis overflow-hidden">
|
||||||
|
{{ notification.text }}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -46,9 +50,15 @@
|
|||||||
></font-awesome>
|
></font-awesome>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="relative w-full pl-4 pr-8 py-2 text-slate-900">
|
<div
|
||||||
<span class="font-semibold">{{ notification.title }}</span>
|
class="relative w-full pl-4 pr-8 py-2 text-slate-900 overflow-hidden"
|
||||||
<p class="text-sm">{{ truncateLongWords(notification.text) }}</p>
|
>
|
||||||
|
<h4 class="font-semibold text-ellipsis overflow-hidden">
|
||||||
|
{{ notification.title }}
|
||||||
|
</h4>
|
||||||
|
<p class="text-sm text-ellipsis overflow-hidden">
|
||||||
|
{{ notification.text }}
|
||||||
|
</p>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="absolute top-2 right-2 px-0.5 py-0 rounded-full bg-slate-200 text-slate-600"
|
class="absolute top-2 right-2 px-0.5 py-0 rounded-full bg-slate-200 text-slate-600"
|
||||||
@@ -72,9 +82,15 @@
|
|||||||
></font-awesome>
|
></font-awesome>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="relative w-full pl-4 pr-8 py-2 text-emerald-900">
|
<div
|
||||||
<span class="font-semibold">{{ notification.title }}</span>
|
class="relative w-full pl-4 pr-8 py-2 text-emerald-900 overflow-hidden"
|
||||||
<p class="text-sm">{{ truncateLongWords(notification.text) }}</p>
|
>
|
||||||
|
<h4 class="font-semibold text-ellipsis overflow-hidden">
|
||||||
|
{{ notification.title }}
|
||||||
|
</h4>
|
||||||
|
<p class="text-sm text-ellipsis overflow-hidden">
|
||||||
|
{{ notification.text }}
|
||||||
|
</p>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="absolute top-2 right-2 px-0.5 py-0 rounded-full bg-emerald-200 text-emerald-600"
|
class="absolute top-2 right-2 px-0.5 py-0 rounded-full bg-emerald-200 text-emerald-600"
|
||||||
@@ -98,9 +114,15 @@
|
|||||||
></font-awesome>
|
></font-awesome>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="relative w-full pl-4 pr-8 py-2 text-amber-900">
|
<div
|
||||||
<span class="font-semibold">{{ notification.title }}</span>
|
class="relative w-full pl-4 pr-8 py-2 text-amber-900 overflow-hidden"
|
||||||
<p class="text-sm">{{ truncateLongWords(notification.text) }}</p>
|
>
|
||||||
|
<h4 class="font-semibold text-ellipsis overflow-hidden">
|
||||||
|
{{ notification.title }}
|
||||||
|
</h4>
|
||||||
|
<p class="text-sm text-ellipsis overflow-hidden">
|
||||||
|
{{ notification.text }}
|
||||||
|
</p>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="absolute top-2 right-2 px-0.5 py-0 rounded-full bg-amber-200 text-amber-600"
|
class="absolute top-2 right-2 px-0.5 py-0 rounded-full bg-amber-200 text-amber-600"
|
||||||
@@ -124,9 +146,15 @@
|
|||||||
></font-awesome>
|
></font-awesome>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="relative w-full pl-4 pr-8 py-2 text-rose-900">
|
<div
|
||||||
<span class="font-semibold">{{ notification.title }}</span>
|
class="relative w-full pl-4 pr-8 py-2 text-rose-900 overflow-hidden"
|
||||||
<p class="text-sm">{{ truncateLongWords(notification.text) }}</p>
|
>
|
||||||
|
<h4 class="font-semibold text-ellipsis overflow-hidden">
|
||||||
|
{{ notification.title }}
|
||||||
|
</h4>
|
||||||
|
<p class="text-sm text-ellipsis overflow-hidden">
|
||||||
|
{{ notification.text }}
|
||||||
|
</p>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="absolute top-2 right-2 px-0.5 py-0 rounded-full bg-rose-200 text-rose-600"
|
class="absolute top-2 right-2 px-0.5 py-0 rounded-full bg-rose-200 text-rose-600"
|
||||||
@@ -349,13 +377,6 @@ export default class App extends Vue {
|
|||||||
|
|
||||||
stopAsking = false;
|
stopAsking = false;
|
||||||
|
|
||||||
truncateLongWords(sentence: string) {
|
|
||||||
return sentence
|
|
||||||
.split(" ")
|
|
||||||
.map((word) => (word.length > 30 ? word.slice(0, 30) + "..." : word))
|
|
||||||
.join(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
async turnOffNotifications(
|
async turnOffNotifications(
|
||||||
notification: NotificationIface,
|
notification: NotificationIface,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ import { GiveRecordWithContactInfo } from "@/interfaces/give";
|
|||||||
import EntityIcon from "./EntityIcon.vue";
|
import EntityIcon from "./EntityIcon.vue";
|
||||||
import { isHiddenDid } from "../libs/endorserServer";
|
import { isHiddenDid } from "../libs/endorserServer";
|
||||||
import ProjectIcon from "./ProjectIcon.vue";
|
import ProjectIcon from "./ProjectIcon.vue";
|
||||||
import { createNotifyHelpers } from "@/utils/notify";
|
import { createNotifyHelpers, NotifyFunction } from "@/utils/notify";
|
||||||
import {
|
import {
|
||||||
NOTIFY_PERSON_HIDDEN,
|
NOTIFY_PERSON_HIDDEN,
|
||||||
NOTIFY_UNKNOWN_PERSON,
|
NOTIFY_UNKNOWN_PERSON,
|
||||||
@@ -273,7 +273,7 @@ export default class ActivityListItem extends Vue {
|
|||||||
|
|
||||||
isHiddenDid = isHiddenDid;
|
isHiddenDid = isHiddenDid;
|
||||||
notify!: ReturnType<typeof createNotifyHelpers>;
|
notify!: ReturnType<typeof createNotifyHelpers>;
|
||||||
$notify!: (notification: any, timeout?: number) => void;
|
$notify!: NotifyFunction;
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
this.notify = createNotifyHelpers(this.$notify);
|
this.notify = createNotifyHelpers(this.$notify);
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ import EntitySelectionStep from "../components/EntitySelectionStep.vue";
|
|||||||
import GiftDetailsStep from "../components/GiftDetailsStep.vue";
|
import GiftDetailsStep from "../components/GiftDetailsStep.vue";
|
||||||
import { PlanData } from "../interfaces/records";
|
import { PlanData } from "../interfaces/records";
|
||||||
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
||||||
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
|
import { createNotifyHelpers, TIMEOUTS, NotifyFunction } from "@/utils/notify";
|
||||||
import {
|
import {
|
||||||
NOTIFY_GIFT_ERROR_NEGATIVE_AMOUNT,
|
NOTIFY_GIFT_ERROR_NEGATIVE_AMOUNT,
|
||||||
NOTIFY_GIFT_ERROR_NO_DESCRIPTION,
|
NOTIFY_GIFT_ERROR_NO_DESCRIPTION,
|
||||||
@@ -98,7 +98,7 @@ import {
|
|||||||
mixins: [PlatformServiceMixin],
|
mixins: [PlatformServiceMixin],
|
||||||
})
|
})
|
||||||
export default class GiftedDialog extends Vue {
|
export default class GiftedDialog extends Vue {
|
||||||
$notify!: (notification: any, timeout?: number) => void;
|
$notify!: NotifyFunction;
|
||||||
notify!: ReturnType<typeof createNotifyHelpers>;
|
notify!: ReturnType<typeof createNotifyHelpers>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ import {
|
|||||||
NOTIFY_IMAGE_DIALOG_UNSUPPORTED_FORMAT,
|
NOTIFY_IMAGE_DIALOG_UNSUPPORTED_FORMAT,
|
||||||
createImageDialogCameraErrorMessage,
|
createImageDialogCameraErrorMessage,
|
||||||
} from "../constants/notifications";
|
} from "../constants/notifications";
|
||||||
import { createNotifyHelpers, TIMEOUTS } from "../utils/notify";
|
import { createNotifyHelpers, TIMEOUTS, NotifyFunction } from "../utils/notify";
|
||||||
|
|
||||||
const inputImageFileNameRef = ref<Blob>();
|
const inputImageFileNameRef = ref<Blob>();
|
||||||
|
|
||||||
@@ -291,7 +291,7 @@ const inputImageFileNameRef = ref<Blob>();
|
|||||||
mixins: [PlatformServiceMixin],
|
mixins: [PlatformServiceMixin],
|
||||||
})
|
})
|
||||||
export default class ImageMethodDialog extends Vue {
|
export default class ImageMethodDialog extends Vue {
|
||||||
$notify!: (notification: any, timeout?: number) => void;
|
$notify!: NotifyFunction;
|
||||||
$router!: Router;
|
$router!: Router;
|
||||||
notify = createNotifyHelpers(this.$notify);
|
notify = createNotifyHelpers(this.$notify);
|
||||||
|
|
||||||
|
|||||||
+9
-3
@@ -15,10 +15,15 @@ const TEST_USER_0_MNEMONIC =
|
|||||||
"rigid shrug mobile smart veteran half all pond toilet brave review universe ship congress found yard skate elite apology jar uniform subway slender luggage";
|
"rigid shrug mobile smart veteran half all pond toilet brave review universe ship congress found yard skate elite apology jar uniform subway slender luggage";
|
||||||
|
|
||||||
export async function testBecomeUser0() {
|
export async function testBecomeUser0() {
|
||||||
const [addr, privateHex, publicHex, deriPath] = deriveAddress(TEST_USER_0_MNEMONIC);
|
const [addr, privateHex, publicHex, deriPath] =
|
||||||
|
deriveAddress(TEST_USER_0_MNEMONIC);
|
||||||
|
|
||||||
const identity0 = newIdentifier(addr, publicHex, privateHex, deriPath);
|
const identity0 = newIdentifier(addr, publicHex, privateHex, deriPath);
|
||||||
await saveNewIdentity(identity0, TEST_USER_0_MNEMONIC, DEFAULT_ROOT_DERIVATION_PATH);
|
await saveNewIdentity(
|
||||||
|
identity0,
|
||||||
|
TEST_USER_0_MNEMONIC,
|
||||||
|
DEFAULT_ROOT_DERIVATION_PATH,
|
||||||
|
);
|
||||||
const platformService = await PlatformServiceFactory.getInstance();
|
const platformService = await PlatformServiceFactory.getInstance();
|
||||||
await platformService.updateDidSpecificSettings(identity0.did, {
|
await platformService.updateDidSpecificSettings(identity0.did, {
|
||||||
isRegistered: true,
|
isRegistered: true,
|
||||||
@@ -35,7 +40,8 @@ export async function testBecomeUser0() {
|
|||||||
* @throws Error if registration fails or database access fails
|
* @throws Error if registration fails or database access fails
|
||||||
*/
|
*/
|
||||||
export async function testServerRegisterUser() {
|
export async function testServerRegisterUser() {
|
||||||
const [addr, privateHex, publicHex, deriPath] = deriveAddress(TEST_USER_0_MNEMONIC);
|
const [addr, privateHex, publicHex, deriPath] =
|
||||||
|
deriveAddress(TEST_USER_0_MNEMONIC);
|
||||||
|
|
||||||
const identity0 = newIdentifier(addr, publicHex, privateHex, deriPath);
|
const identity0 = newIdentifier(addr, publicHex, privateHex, deriPath);
|
||||||
|
|
||||||
|
|||||||
+56
-20
@@ -2,9 +2,10 @@
|
|||||||
* Enhanced logger with self-contained database logging
|
* Enhanced logger with self-contained database logging
|
||||||
*
|
*
|
||||||
* Provides comprehensive logging with console and database output.
|
* Provides comprehensive logging with console and database output.
|
||||||
|
* Supports configurable log levels via VITE_LOG_LEVEL environment variable.
|
||||||
*
|
*
|
||||||
* @author Matthew Raymer
|
* @author Matthew Raymer
|
||||||
* @version 2.0.0
|
* @version 2.1.0
|
||||||
* @since 2025-01-25
|
* @since 2025-01-25
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -46,6 +47,42 @@ export function safeStringify(obj: unknown) {
|
|||||||
const isElectron = process.env.VITE_PLATFORM === "electron";
|
const isElectron = process.env.VITE_PLATFORM === "electron";
|
||||||
const isProduction = process.env.NODE_ENV === "production";
|
const isProduction = process.env.NODE_ENV === "production";
|
||||||
|
|
||||||
|
// Log level configuration via environment variable
|
||||||
|
const LOG_LEVELS = {
|
||||||
|
error: 0,
|
||||||
|
warn: 1,
|
||||||
|
info: 2,
|
||||||
|
debug: 3,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
type LogLevel = keyof typeof LOG_LEVELS;
|
||||||
|
|
||||||
|
// Parse VITE_LOG_LEVEL environment variable
|
||||||
|
const getLogLevel = (): LogLevel => {
|
||||||
|
const envLogLevel = process.env.VITE_LOG_LEVEL?.toLowerCase();
|
||||||
|
|
||||||
|
if (envLogLevel && envLogLevel in LOG_LEVELS) {
|
||||||
|
return envLogLevel as LogLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default log levels based on environment
|
||||||
|
if (isProduction && !isElectron) {
|
||||||
|
return "warn"; // Production web: warnings and errors only
|
||||||
|
} else if (isElectron) {
|
||||||
|
return "error"; // Electron: errors only
|
||||||
|
} else {
|
||||||
|
return "info"; // Development/Capacitor: info and above
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const currentLogLevel = getLogLevel();
|
||||||
|
const currentLevelValue = LOG_LEVELS[currentLogLevel];
|
||||||
|
|
||||||
|
// Helper function to check if a log level should be displayed
|
||||||
|
const shouldLog = (level: LogLevel): boolean => {
|
||||||
|
return LOG_LEVELS[level] <= currentLevelValue;
|
||||||
|
};
|
||||||
|
|
||||||
// Track initialization state to prevent circular dependencies
|
// Track initialization state to prevent circular dependencies
|
||||||
let isInitializing = true;
|
let isInitializing = true;
|
||||||
|
|
||||||
@@ -105,11 +142,11 @@ async function logToDatabase(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enhanced logger with self-contained database methods
|
// Enhanced logger with self-contained database methods and log level control
|
||||||
export const logger = {
|
export const logger = {
|
||||||
debug: (message: string, ...args: unknown[]) => {
|
debug: (message: string, ...args: unknown[]) => {
|
||||||
// Debug logs are very verbose - only show in development mode for web
|
// Debug logs only show if VITE_LOG_LEVEL allows it
|
||||||
if (!isProduction && !isElectron) {
|
if (shouldLog("debug")) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.debug(message, ...args);
|
console.debug(message, ...args);
|
||||||
}
|
}
|
||||||
@@ -117,11 +154,8 @@ export const logger = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
log: (message: string, ...args: unknown[]) => {
|
log: (message: string, ...args: unknown[]) => {
|
||||||
// Regular logs - show in development or for capacitor, but quiet for Electron
|
// Regular logs - show if VITE_LOG_LEVEL allows info level
|
||||||
if (
|
if (shouldLog("info")) {
|
||||||
(!isProduction && !isElectron) ||
|
|
||||||
process.env.VITE_PLATFORM === "capacitor"
|
|
||||||
) {
|
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(message, ...args);
|
console.log(message, ...args);
|
||||||
}
|
}
|
||||||
@@ -132,11 +166,7 @@ export const logger = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
info: (message: string, ...args: unknown[]) => {
|
info: (message: string, ...args: unknown[]) => {
|
||||||
if (
|
if (shouldLog("info")) {
|
||||||
process.env.NODE_ENV !== "production" ||
|
|
||||||
process.env.VITE_PLATFORM === "capacitor" ||
|
|
||||||
process.env.VITE_PLATFORM === "electron"
|
|
||||||
) {
|
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.info(message, ...args);
|
console.info(message, ...args);
|
||||||
}
|
}
|
||||||
@@ -147,8 +177,7 @@ export const logger = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
warn: (message: string, ...args: unknown[]) => {
|
warn: (message: string, ...args: unknown[]) => {
|
||||||
// Always show warnings, but for Electron, suppress routine database warnings
|
if (shouldLog("warn")) {
|
||||||
if (!isElectron || !message.includes("[CapacitorPlatformService]")) {
|
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.warn(message, ...args);
|
console.warn(message, ...args);
|
||||||
}
|
}
|
||||||
@@ -159,9 +188,10 @@ export const logger = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
error: (message: string, ...args: unknown[]) => {
|
error: (message: string, ...args: unknown[]) => {
|
||||||
// Errors will always be logged to console
|
if (shouldLog("error")) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.error(message, ...args);
|
console.error(message, ...args);
|
||||||
|
}
|
||||||
|
|
||||||
// Database logging
|
// Database logging
|
||||||
const messageString = safeStringify(message);
|
const messageString = safeStringify(message);
|
||||||
@@ -175,11 +205,11 @@ export const logger = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
toConsoleAndDb: async (message: string, isError = false): Promise<void> => {
|
toConsoleAndDb: async (message: string, isError = false): Promise<void> => {
|
||||||
// Console output
|
// Console output based on log level
|
||||||
if (isError) {
|
if (isError && shouldLog("error")) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.error(message);
|
console.error(message);
|
||||||
} else {
|
} else if (!isError && shouldLog("info")) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(message);
|
console.log(message);
|
||||||
}
|
}
|
||||||
@@ -194,6 +224,12 @@ export const logger = {
|
|||||||
error: (message: string) =>
|
error: (message: string) =>
|
||||||
logToDatabase(`[${componentName}] ${message}`, "error"),
|
logToDatabase(`[${componentName}] ${message}`, "error"),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
// Log level information methods
|
||||||
|
getCurrentLevel: (): LogLevel => currentLogLevel,
|
||||||
|
getCurrentLevelValue: (): number => currentLevelValue,
|
||||||
|
isLevelEnabled: (level: LogLevel): boolean => shouldLog(level),
|
||||||
|
getAvailableLevels: (): LogLevel[] => Object.keys(LOG_LEVELS) as LogLevel[],
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function to manually mark initialization as complete
|
// Function to manually mark initialization as complete
|
||||||
|
|||||||
@@ -724,6 +724,8 @@ export default class ClaimView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async created() {
|
async created() {
|
||||||
|
this.notify = createNotifyHelpers(this.$notify);
|
||||||
|
|
||||||
const settings = await this.$accountSettings();
|
const settings = await this.$accountSettings();
|
||||||
|
|
||||||
this.activeDid = settings.activeDid || "";
|
this.activeDid = settings.activeDid || "";
|
||||||
@@ -754,8 +756,6 @@ export default class ClaimView extends Vue {
|
|||||||
this.windowDeepLink = `${APP_SERVER}/deep-link/claim/${claimId}`;
|
this.windowDeepLink = `${APP_SERVER}/deep-link/claim/${claimId}`;
|
||||||
|
|
||||||
this.canShare = !!navigator.share;
|
this.canShare = !!navigator.share;
|
||||||
|
|
||||||
this.notify = createNotifyHelpers(this.$notify);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert a space before any capital letters except the initial letter
|
// insert a space before any capital letters except the initial letter
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ import {
|
|||||||
QR_TIMEOUT_STANDARD,
|
QR_TIMEOUT_STANDARD,
|
||||||
QR_TIMEOUT_LONG,
|
QR_TIMEOUT_LONG,
|
||||||
} from "@/constants/notifications";
|
} from "@/constants/notifications";
|
||||||
import { createNotifyHelpers } from "../utils/notify";
|
import { createNotifyHelpers, NotifyFunction } from "../utils/notify";
|
||||||
|
|
||||||
interface QRScanResult {
|
interface QRScanResult {
|
||||||
rawValue?: string;
|
rawValue?: string;
|
||||||
@@ -191,7 +191,7 @@ interface IUserNameDialog {
|
|||||||
* @since 2024
|
* @since 2024
|
||||||
*/
|
*/
|
||||||
export default class ContactQRScanFull extends Vue {
|
export default class ContactQRScanFull extends Vue {
|
||||||
$notify!: (notification: any, timeout?: number) => void;
|
$notify!: NotifyFunction;
|
||||||
$router!: Router;
|
$router!: Router;
|
||||||
|
|
||||||
// Notification helper system
|
// Notification helper system
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ import {
|
|||||||
import { logger } from "../utils/logger";
|
import { logger } from "../utils/logger";
|
||||||
import { Account, AccountEncrypted } from "../db/tables/accounts";
|
import { Account, AccountEncrypted } from "../db/tables/accounts";
|
||||||
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
||||||
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
|
import { createNotifyHelpers, TIMEOUTS, NotifyFunction } from "@/utils/notify";
|
||||||
import {
|
import {
|
||||||
NOTIFY_ACCOUNT_DERIVATION_SUCCESS,
|
NOTIFY_ACCOUNT_DERIVATION_SUCCESS,
|
||||||
NOTIFY_ACCOUNT_DERIVATION_ERROR,
|
NOTIFY_ACCOUNT_DERIVATION_ERROR,
|
||||||
@@ -100,7 +100,7 @@ import {
|
|||||||
export default class ImportAccountView extends Vue {
|
export default class ImportAccountView extends Vue {
|
||||||
$route!: RouteLocationNormalizedLoaded;
|
$route!: RouteLocationNormalizedLoaded;
|
||||||
$router!: Router;
|
$router!: Router;
|
||||||
$notify!: (notification: any, timeout?: number) => void;
|
$notify!: NotifyFunction;
|
||||||
|
|
||||||
notify!: ReturnType<typeof createNotifyHelpers>;
|
notify!: ReturnType<typeof createNotifyHelpers>;
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ test('Record an offer', async ({ page }) => {
|
|||||||
await page.locator('button', { hasText: 'Edit' }).isVisible(); // since the 'edit' takes longer to show, wait for that (lest the click miss)
|
await page.locator('button', { hasText: 'Edit' }).isVisible(); // since the 'edit' takes longer to show, wait for that (lest the click miss)
|
||||||
await page.getByTestId('offerButton').click();
|
await page.getByTestId('offerButton').click();
|
||||||
await page.getByTestId('inputDescription').fill(description);
|
await page.getByTestId('inputDescription').fill(description);
|
||||||
await page.getByTestId('inputOfferAmount').fill(randomNonZeroNumber.toString());
|
await page.getByTestId('inputOfferAmount').locator('input').fill(randomNonZeroNumber.toString());
|
||||||
expect(page.getByRole('button', { name: 'Sign & Send' }));
|
expect(page.getByRole('button', { name: 'Sign & Send' }));
|
||||||
await page.getByRole('button', { name: 'Sign & Send' }).click();
|
await page.getByRole('button', { name: 'Sign & Send' }).click();
|
||||||
await expect(page.getByText('That offer was recorded.')).toBeVisible();
|
await expect(page.getByText('That offer was recorded.')).toBeVisible();
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ test('New offers for another user', async ({ page }) => {
|
|||||||
const randomString1 = Math.random().toString(36).substring(2, 5);
|
const randomString1 = Math.random().toString(36).substring(2, 5);
|
||||||
await page.getByTestId('offerButton').click();
|
await page.getByTestId('offerButton').click();
|
||||||
await page.getByTestId('inputDescription').fill(`help of ${randomString1} from #000`);
|
await page.getByTestId('inputDescription').fill(`help of ${randomString1} from #000`);
|
||||||
await page.getByTestId('inputOfferAmount').fill('1');
|
await page.getByTestId('inputOfferAmount').locator('input').fill('1');
|
||||||
await page.getByRole('button', { name: 'Sign & Send' }).click();
|
await page.getByRole('button', { name: 'Sign & Send' }).click();
|
||||||
await expect(page.getByText('That offer was recorded.')).toBeVisible();
|
await expect(page.getByText('That offer was recorded.')).toBeVisible();
|
||||||
await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss info alert
|
await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss info alert
|
||||||
@@ -46,7 +46,7 @@ test('New offers for another user', async ({ page }) => {
|
|||||||
const randomString2 = Math.random().toString(36).substring(2, 5);
|
const randomString2 = Math.random().toString(36).substring(2, 5);
|
||||||
await page.getByTestId('offerButton').click();
|
await page.getByTestId('offerButton').click();
|
||||||
await page.getByTestId('inputDescription').fill(`help of ${randomString2} from #000`);
|
await page.getByTestId('inputDescription').fill(`help of ${randomString2} from #000`);
|
||||||
await page.getByTestId('inputOfferAmount').fill('3');
|
await page.getByTestId('inputOfferAmount').locator('input').fill('3');
|
||||||
await page.getByRole('button', { name: 'Sign & Send' }).click();
|
await page.getByRole('button', { name: 'Sign & Send' }).click();
|
||||||
await expect(page.getByText('That offer was recorded.')).toBeVisible();
|
await expect(page.getByText('That offer was recorded.')).toBeVisible();
|
||||||
await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss info alert
|
await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss info alert
|
||||||
|
|||||||
Reference in New Issue
Block a user