cleanup
This commit is contained in:
+1
-18
@@ -49,24 +49,7 @@ services:
|
|||||||
command: >
|
command: >
|
||||||
/bin/sh -c "
|
/bin/sh -c "
|
||||||
echo 'Running database migrations' &&
|
echo 'Running database migrations' &&
|
||||||
diesel migration run &&
|
diesel migration run
|
||||||
echo 'Ensuring tenant admin exists' &&
|
|
||||||
if papercrate-admin list-tenants | grep -q '^admin '; then
|
|
||||||
echo 'tenant admin already exists';
|
|
||||||
else
|
|
||||||
papercrate-admin create-tenant admin;
|
|
||||||
fi &&
|
|
||||||
ADMIN_TENANT_ID=$(papercrate-admin list-tenants | awk '/^admin / {print $2; exit}') &&
|
|
||||||
if [ -z "$ADMIN_TENANT_ID" ]; then
|
|
||||||
echo 'failed to resolve admin tenant id' >&2;
|
|
||||||
exit 1;
|
|
||||||
fi &&
|
|
||||||
echo 'Ensuring demo user credentials' &&
|
|
||||||
(papercrate-admin create-user admin adminadmin || papercrate-admin set-password admin adminadmin) &&
|
|
||||||
echo 'Ensuring demo membership' &&
|
|
||||||
papercrate-admin add-user-to-tenant admin "$ADMIN_TENANT_ID" &&
|
|
||||||
echo 'Ensuring Quickwit index for admin tenant' &&
|
|
||||||
papercrate-admin quickwit-create-index "$ADMIN_TENANT_ID"
|
|
||||||
"
|
"
|
||||||
user: root
|
user: root
|
||||||
restart: "no"
|
restart: "no"
|
||||||
|
|||||||
@@ -84,24 +84,7 @@ services:
|
|||||||
command: >
|
command: >
|
||||||
/bin/sh -c "
|
/bin/sh -c "
|
||||||
echo 'Running database migrations' &&
|
echo 'Running database migrations' &&
|
||||||
diesel migration run &&
|
diesel migration run
|
||||||
echo 'Ensuring tenant admin exists' &&
|
|
||||||
if papercrate-admin list-tenants | grep -q '^admin '; then
|
|
||||||
echo 'tenant admin already exists';
|
|
||||||
else
|
|
||||||
papercrate-admin create-tenant admin;
|
|
||||||
fi &&
|
|
||||||
ADMIN_TENANT_ID=$(papercrate-admin list-tenants | awk '/^admin / {print $2; exit}') &&
|
|
||||||
if [ -z "$ADMIN_TENANT_ID" ]; then
|
|
||||||
echo 'failed to resolve admin tenant id' >&2;
|
|
||||||
exit 1;
|
|
||||||
fi &&
|
|
||||||
echo 'Ensuring demo user credentials' &&
|
|
||||||
(papercrate-admin create-user admin adminadmin || papercrate-admin set-password admin adminadmin) &&
|
|
||||||
echo 'Ensuring demo membership' &&
|
|
||||||
papercrate-admin add-user-to-tenant admin "$ADMIN_TENANT_ID" &&
|
|
||||||
echo 'Ensuring Quickwit index for admin tenant' &&
|
|
||||||
papercrate-admin quickwit-create-index "$ADMIN_TENANT_ID"
|
|
||||||
"
|
"
|
||||||
user: root
|
user: root
|
||||||
restart: "no"
|
restart: "no"
|
||||||
+1
-1
@@ -39,7 +39,7 @@ npm run build
|
|||||||
- Drag-and-drop moves (documents between folders) and file uploads (window-wide or onto a folder)
|
- Drag-and-drop moves (documents between folders) and file uploads (window-wide or onto a folder)
|
||||||
- Search box plus tag chips filter documents across the selected folder and all descendants
|
- Search box plus tag chips filter documents across the selected folder and all descendants
|
||||||
- Tag management (create/assign/remove) from the detail panel
|
- Tag management (create/assign/remove) from the detail panel
|
||||||
- Login via the seeded admin account (`admin` / `adminadmin`) with stored JWT session
|
- Login with a WebAuthn passkey created through the signup flow (no baked-in demo account)
|
||||||
- Inline status banner for quick feedback on API interactions
|
- Inline status banner for quick feedback on API interactions
|
||||||
|
|
||||||
## Assets
|
## Assets
|
||||||
|
|||||||
@@ -23,9 +23,6 @@ const DEFAULT_CANVAS_WIDTH = 1024;
|
|||||||
const DEFAULT_CANVAS_HEIGHT = 680;
|
const DEFAULT_CANVAS_HEIGHT = 680;
|
||||||
const TAG_MIME_TYPES = ['application/x-papercrate-tag', 'text/papercrate-tag'];
|
const TAG_MIME_TYPES = ['application/x-papercrate-tag', 'text/papercrate-tag'];
|
||||||
|
|
||||||
const resolveSizeKey = (doc) =>
|
|
||||||
doc?.id || doc?.document_id || doc?.uuid || doc?.original_name || doc?.title || 'doc';
|
|
||||||
|
|
||||||
const CARD_MIN = 240;
|
const CARD_MIN = 240;
|
||||||
const CARD_MAX = 340;
|
const CARD_MAX = 340;
|
||||||
const TAG_REMOVE_DISTANCE = 160;
|
const TAG_REMOVE_DISTANCE = 160;
|
||||||
@@ -1170,7 +1167,7 @@ const syncLayoutSnapshot = useCallback(() => {
|
|||||||
id: doc.id,
|
id: doc.id,
|
||||||
width: docWidth,
|
width: docWidth,
|
||||||
height: docHeight,
|
height: docHeight,
|
||||||
seedKey: resolveSizeKey(doc),
|
seedKey: doc.id,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ const TagSection = ({
|
|||||||
{datalistId ? (
|
{datalistId ? (
|
||||||
<datalist id={datalistId}>
|
<datalist id={datalistId}>
|
||||||
{datalistOptions.map((option) => (
|
{datalistOptions.map((option) => (
|
||||||
<option key={option.id || option.label || option} value={option.label || option} />
|
<option key={option.id} />
|
||||||
))}
|
))}
|
||||||
</datalist>
|
</datalist>
|
||||||
) : null}
|
) : null}
|
||||||
@@ -456,7 +456,7 @@ const DetailPanel = ({
|
|||||||
id: doc.id,
|
id: doc.id,
|
||||||
url,
|
url,
|
||||||
orientation,
|
orientation,
|
||||||
alt: doc.title || doc.original_name || 'Document preview',
|
alt: doc.title,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[ensureAssetUrl, getDocumentAsset],
|
[ensureAssetUrl, getDocumentAsset],
|
||||||
@@ -500,7 +500,7 @@ const DetailPanel = ({
|
|||||||
id: singleDoc.id,
|
id: singleDoc.id,
|
||||||
url,
|
url,
|
||||||
orientation,
|
orientation,
|
||||||
alt: singleDoc.title || singleDoc.original_name || 'Document preview',
|
alt: singleDoc.title,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}, [singleDoc, singlePreviewNavigator.currentUrl, singlePreviewNavigator.currentMetadata]);
|
}, [singleDoc, singlePreviewNavigator.currentUrl, singlePreviewNavigator.currentMetadata]);
|
||||||
@@ -522,7 +522,7 @@ const DetailPanel = ({
|
|||||||
id: doc.id,
|
id: doc.id,
|
||||||
url,
|
url,
|
||||||
orientation,
|
orientation,
|
||||||
alt: doc.title || doc.original_name || 'Document preview',
|
alt: doc.title,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return makePreviewItem(doc, 1);
|
return makePreviewItem(doc, 1);
|
||||||
@@ -724,7 +724,7 @@ const DetailPanel = ({
|
|||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
url: singlePreviewNavigator.currentUrl,
|
url: singlePreviewNavigator.currentUrl,
|
||||||
alt: singleDoc.title || singleDoc.original_name || 'Document preview',
|
alt: singleDoc.title,
|
||||||
canGoPrev:
|
canGoPrev:
|
||||||
singleEffectiveCardinality > 1 && Boolean(singlePreviewNavigator.canGoPrev),
|
singleEffectiveCardinality > 1 && Boolean(singlePreviewNavigator.canGoPrev),
|
||||||
canGoNext:
|
canGoNext:
|
||||||
@@ -743,7 +743,7 @@ const DetailPanel = ({
|
|||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
url: stackPreviewNavigator.currentUrl,
|
url: stackPreviewNavigator.currentUrl,
|
||||||
alt: stackTopDocument.title || stackTopDocument.original_name || 'Document preview',
|
alt: stackTopDocument.title,
|
||||||
canGoPrev:
|
canGoPrev:
|
||||||
topEffectiveCardinality > 1 && Boolean(stackPreviewNavigator.canGoPrev),
|
topEffectiveCardinality > 1 && Boolean(stackPreviewNavigator.canGoPrev),
|
||||||
canGoNext:
|
canGoNext:
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ const resolveCorrespondents = (doc) => {
|
|||||||
doc.correspondents.forEach((entry, index) => {
|
doc.correspondents.forEach((entry, index) => {
|
||||||
if (!entry) return;
|
if (!entry) return;
|
||||||
|
|
||||||
const id = entry.id ?? entry.correspondent_id ?? null;
|
const id = entry.id;
|
||||||
const name = (entry.name || entry.label || entry.slug || '').trim();
|
const name = entry.name.trim();
|
||||||
if (!name) return;
|
if (!name) return;
|
||||||
|
|
||||||
if (id && seen.has(id)) {
|
if (id && seen.has(id)) {
|
||||||
@@ -951,7 +951,7 @@ const DocumentsTable = ({
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{(() => {
|
{(() => {
|
||||||
const issuedAt = doc.issued_at || doc.updated_at || null;
|
const issuedAt = doc.issued_at || null;
|
||||||
if (!issuedAt) {
|
if (!issuedAt) {
|
||||||
return '—';
|
return '—';
|
||||||
}
|
}
|
||||||
@@ -974,13 +974,13 @@ const DocumentsTable = ({
|
|||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
const nextName = window.prompt(
|
const nextName = window.prompt(
|
||||||
'Rename document',
|
'Rename document',
|
||||||
doc.title || doc.original_name || '',
|
doc.title
|
||||||
);
|
);
|
||||||
if (!nextName) {
|
if (!nextName) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const trimmed = nextName.trim();
|
const trimmed = nextName.trim();
|
||||||
if (!trimmed || trimmed === (doc.title || doc.original_name)) {
|
if (!trimmed || trimmed === doc.title) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
onDocumentRename(doc.id, trimmed);
|
onDocumentRename(doc.id, trimmed);
|
||||||
|
|||||||
@@ -4498,7 +4498,7 @@ const AppLayout = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const doc = documentLookup.get(documentId) || null;
|
const doc = documentLookup.get(documentId) || null;
|
||||||
const label = doc?.title || doc?.original_name || 'this document';
|
const label = doc?.title;
|
||||||
|
|
||||||
const confirmed = window.confirm(`Move "${label}" to trash? You can restore it from trash later.`);
|
const confirmed = window.confirm(`Move "${label}" to trash? You can restore it from trash later.`);
|
||||||
if (!confirmed) {
|
if (!confirmed) {
|
||||||
|
|||||||
@@ -11,14 +11,14 @@ const PreviewWorkspace = ({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const title = document.title || document.original_name || 'Document';
|
const title = document.title;
|
||||||
const mime = previewEntry?.contentType || document.content_type || 'application/pdf';
|
const mime = document.content_type;
|
||||||
const sizeBytes = Number(document.current_version?.size_bytes) || 0;
|
const sizeBytes = Number(document.current_version?.size_bytes) || 0;
|
||||||
const sizeLabel = sizeBytes > 0 ? formatFileSize(sizeBytes) : null;
|
const sizeLabel = sizeBytes > 0 ? formatFileSize(sizeBytes) : null;
|
||||||
const metadata =
|
const metadata =
|
||||||
document.metadata && Object.keys(document.metadata).length > 0 ? document.metadata : null;
|
document.metadata && Object.keys(document.metadata).length > 0 ? document.metadata : null;
|
||||||
const folderName = document.folder_path || document.folder_name || null;
|
const folderName = document.folder_path || document.folder_name || null;
|
||||||
const issuedAt = document.issued_at || document.current_version?.issued_at || null;
|
const issuedAt = document.issued_at || null;
|
||||||
const createdAt = document.created_at || null;
|
const createdAt = document.created_at || null;
|
||||||
const updatedAt = document.updated_at || null;
|
const updatedAt = document.updated_at || null;
|
||||||
const tags = Array.isArray(document.tags) ? document.tags : [];
|
const tags = Array.isArray(document.tags) ? document.tags : [];
|
||||||
@@ -33,13 +33,13 @@ const PreviewWorkspace = ({
|
|||||||
if (updatedAt) rows.push(['Updated', new Date(updatedAt).toLocaleString()]);
|
if (updatedAt) rows.push(['Updated', new Date(updatedAt).toLocaleString()]);
|
||||||
if (folderName) rows.push(['Folder', folderName]);
|
if (folderName) rows.push(['Folder', folderName]);
|
||||||
if (tags.length) {
|
if (tags.length) {
|
||||||
rows.push(['Tags', tags.map((tag) => tag.label || tag.name || tag.slug).filter(Boolean).join(', ')]);
|
rows.push(['Tags', tags.map((tag) => tag.label).filter(Boolean).join(', ')]);
|
||||||
}
|
}
|
||||||
if (correspondents.length) {
|
if (correspondents.length) {
|
||||||
rows.push([
|
rows.push([
|
||||||
'Correspondents',
|
'Correspondents',
|
||||||
correspondents
|
correspondents
|
||||||
.map((entry) => entry.name || entry.label || entry.slug)
|
.map((entry) => entry.name)
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join(', '),
|
.join(', '),
|
||||||
]);
|
]);
|
||||||
@@ -173,7 +173,7 @@ export const createPreviewSurface = ({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const title = document.title || document.original_name || 'Document preview';
|
const title = document.title;
|
||||||
const sidebarToggle = renderSidebarToggle ? renderSidebarToggle() : null;
|
const sidebarToggle = renderSidebarToggle ? renderSidebarToggle() : null;
|
||||||
const closeButton = onClose
|
const closeButton = onClose
|
||||||
? (
|
? (
|
||||||
|
|||||||
@@ -382,7 +382,7 @@ const Sidebar = ({
|
|||||||
{tenants.map((tenant) => {
|
{tenants.map((tenant) => {
|
||||||
const tenantId = tenant?.id || null;
|
const tenantId = tenant?.id || null;
|
||||||
const isActive = tenantId === activeTenantId;
|
const isActive = tenantId === activeTenantId;
|
||||||
const tenantLabel = tenant?.name || tenant?.slug || tenantId || 'Tenant';
|
const tenantLabel = tenant?.name;
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={tenantId || tenantLabel}
|
key={tenantId || tenantLabel}
|
||||||
|
|||||||
Reference in New Issue
Block a user