|
|
@@ -169,6 +169,88 @@ export class ShopDetailPage {
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
+ <!-- Shop Settings -->
|
|
|
+ <div class="card">
|
|
|
+ <div class="card-header">
|
|
|
+ <h3 class="text-lg font-medium text-gray-900 dark:text-white">Shop Settings</h3>
|
|
|
+ <p class="text-sm text-gray-500 dark:text-gray-400">Configure shop identifiers and metadata</p>
|
|
|
+ </div>
|
|
|
+ <div class="card-body">
|
|
|
+ <div class="space-y-6">
|
|
|
+ <!-- Internal ID -->
|
|
|
+ <div>
|
|
|
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
|
|
+ Internal ID
|
|
|
+ </label>
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <input
|
|
|
+ type="text"
|
|
|
+ value="${shop.id}"
|
|
|
+ readonly
|
|
|
+ class="flex-1 px-3 py-2 bg-gray-50 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-lg text-gray-500 dark:text-gray-400 cursor-not-allowed"
|
|
|
+ />
|
|
|
+ <button
|
|
|
+ type="button"
|
|
|
+ id="copy-internal-id"
|
|
|
+ class="btn btn-secondary"
|
|
|
+ title="Copy to clipboard"
|
|
|
+ >
|
|
|
+ <div class="w-4 h-4">${getIcon('copy')}</div>
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
|
|
+ Auto-generated UUID, cannot be changed
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- Custom ID -->
|
|
|
+ <div>
|
|
|
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
|
|
+ Custom ID
|
|
|
+ </label>
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
+ <input
|
|
|
+ type="text"
|
|
|
+ id="custom-id-input"
|
|
|
+ value="${shop.custom_id || ''}"
|
|
|
+ placeholder="e.g., 550e8400-e29b-41d4-a716-446655440000"
|
|
|
+ class="flex-1 px-3 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-lg text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
|
|
+ />
|
|
|
+ <button
|
|
|
+ type="button"
|
|
|
+ id="save-custom-id"
|
|
|
+ class="btn btn-primary"
|
|
|
+ >
|
|
|
+ <div class="w-4 h-4 mr-1">${getIcon('save')}</div>
|
|
|
+ Save
|
|
|
+ </button>
|
|
|
+ ${shop.custom_id ? `
|
|
|
+ <button
|
|
|
+ type="button"
|
|
|
+ id="clear-custom-id"
|
|
|
+ class="btn btn-secondary"
|
|
|
+ title="Clear custom ID"
|
|
|
+ >
|
|
|
+ <div class="w-4 h-4">${getIcon('delete')}</div>
|
|
|
+ </button>
|
|
|
+ ` : ''}
|
|
|
+ </div>
|
|
|
+ <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
|
|
+ Optional UUID for custom identification. Must be a valid UUID format.
|
|
|
+ </p>
|
|
|
+ ${shop.qdrant_enabled && shop.custom_id ? `
|
|
|
+ <div class="mt-2 flex items-start space-x-2 text-xs text-yellow-600 dark:text-yellow-400">
|
|
|
+ <div class="w-4 h-4 flex-shrink-0">${getIcon('warning')}</div>
|
|
|
+ <span>
|
|
|
+ Custom ID is linked to Qdrant collections and should not be changed while Qdrant is enabled.
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ ` : ''}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
<!-- Content Overview -->
|
|
|
<div class="card">
|
|
|
<div class="card-header">
|
|
|
@@ -492,5 +574,94 @@ export class ShopDetailPage {
|
|
|
this.toastService.error('Error', 'Failed to clear Qdrant errors');
|
|
|
}
|
|
|
});
|
|
|
+
|
|
|
+ // Copy internal ID to clipboard
|
|
|
+ this.element.querySelector('#copy-internal-id')?.addEventListener('click', async () => {
|
|
|
+ if (!this.shopDetail) return;
|
|
|
+
|
|
|
+ try {
|
|
|
+ await navigator.clipboard.writeText(this.shopDetail.shop.id);
|
|
|
+ this.toastService.success('Copied', 'Internal ID copied to clipboard');
|
|
|
+ } catch (error) {
|
|
|
+ this.toastService.error('Copy Failed', 'Failed to copy to clipboard');
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // Save custom ID
|
|
|
+ this.element.querySelector('#save-custom-id')?.addEventListener('click', async () => {
|
|
|
+ if (!this.shopDetail) return;
|
|
|
+
|
|
|
+ const input = this.element?.querySelector('#custom-id-input') as HTMLInputElement;
|
|
|
+ if (!input) return;
|
|
|
+
|
|
|
+ const newCustomId = input.value.trim();
|
|
|
+
|
|
|
+ // Validate UUID format if not empty
|
|
|
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
|
+ if (newCustomId && !uuidRegex.test(newCustomId)) {
|
|
|
+ this.toastService.error('Invalid Format', 'Custom ID must be a valid UUID format');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Warn if changing custom ID while Qdrant is enabled
|
|
|
+ if (this.shopDetail.shop.qdrant_enabled && this.shopDetail.shop.custom_id && newCustomId !== this.shopDetail.shop.custom_id) {
|
|
|
+ const confirmed = confirm(
|
|
|
+ 'Warning: Changing the custom ID while Qdrant is enabled may cause issues with existing collections. ' +
|
|
|
+ 'It is recommended to disable Qdrant first. Do you want to continue?'
|
|
|
+ );
|
|
|
+ if (!confirmed) return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ const response = await this.apiService.updateShopCustomId(
|
|
|
+ this.shopId,
|
|
|
+ newCustomId || null
|
|
|
+ );
|
|
|
+
|
|
|
+ if (response.success) {
|
|
|
+ this.toastService.success(
|
|
|
+ 'Custom ID Updated',
|
|
|
+ newCustomId ? `Custom ID set to ${newCustomId}` : 'Custom ID removed'
|
|
|
+ );
|
|
|
+ // Reload the page to show updated data
|
|
|
+ await this.loadShopDetail();
|
|
|
+ } else {
|
|
|
+ this.toastService.error('Update Failed', response.error || 'Failed to update custom ID');
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ this.toastService.error('Error', 'Failed to update custom ID');
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // Clear custom ID
|
|
|
+ this.element.querySelector('#clear-custom-id')?.addEventListener('click', async () => {
|
|
|
+ if (!this.shopDetail) return;
|
|
|
+
|
|
|
+ // Warn if clearing custom ID while Qdrant is enabled
|
|
|
+ if (this.shopDetail.shop.qdrant_enabled) {
|
|
|
+ const confirmed = confirm(
|
|
|
+ 'Warning: Removing the custom ID while Qdrant is enabled may cause issues with existing collections. ' +
|
|
|
+ 'It is recommended to disable Qdrant first. Do you want to continue?'
|
|
|
+ );
|
|
|
+ if (!confirmed) return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const confirmClear = confirm('Are you sure you want to clear the custom ID?');
|
|
|
+ if (!confirmClear) return;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const response = await this.apiService.updateShopCustomId(this.shopId, null);
|
|
|
+
|
|
|
+ if (response.success) {
|
|
|
+ this.toastService.success('Custom ID Cleared', 'Custom ID has been removed');
|
|
|
+ // Reload the page to show updated data
|
|
|
+ await this.loadShopDetail();
|
|
|
+ } else {
|
|
|
+ this.toastService.error('Clear Failed', response.error || 'Failed to clear custom ID');
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ this.toastService.error('Error', 'Failed to clear custom ID');
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
}
|