160 lines
9.0 KiB
JavaScript
160 lines
9.0 KiB
JavaScript
import "./DesktopFilesSidebar.js"
|
|
import "./DesktopFilesToolbar.js"
|
|
import "./DesktopFilesGrid.js"
|
|
|
|
css(`
|
|
files- {
|
|
font-family: 'Arial';
|
|
scrollbar-width: none;
|
|
-ms-overflow-style: none;
|
|
}
|
|
@keyframes pulse-ring {
|
|
0% { transform: scale(1); opacity: 0.5; }
|
|
100% { transform: scale(2.2); opacity: 0; }
|
|
}
|
|
`)
|
|
|
|
class Files extends Shadow {
|
|
constructor() {
|
|
super()
|
|
this.viewMode = "list"
|
|
this.searchText = ""
|
|
this.activeLocation = "all"
|
|
|
|
this.groups = [
|
|
{ id: 1, name: "All Members", color: "#3b82f6", fileCount: 24 },
|
|
{ id: 2, name: "Admins", color: "#ef4444", fileCount: 8 },
|
|
{ id: 3, name: "Editors", color: "#10b981", fileCount: 15 },
|
|
{ id: 4, name: "Viewers", color: "#f59e0b", fileCount: 19 },
|
|
{ id: 5, name: "External", color: "#8b5cf6", fileCount: 4 },
|
|
]
|
|
|
|
this.activeGroupIds = new Set(this.groups.map(g => g.id))
|
|
|
|
this.locations = [
|
|
{ id: "all", label: "All Files", icon: "🗂" },
|
|
{ id: "mine", label: "My Files", icon: "👤" },
|
|
{ id: "shared", label: "Shared with Me", icon: "👥" },
|
|
{ id: "recent", label: "Recent", icon: "🕐" },
|
|
{ id: "starred", label: "Starred", icon: "⭐" },
|
|
{ id: "trash", label: "Trash", icon: "🗑" },
|
|
]
|
|
|
|
const ago = (d) => new Date(Date.now() - d * 86400000);
|
|
|
|
this.files = [
|
|
// Folders
|
|
{ id: 1, type: "folder", name: "Design Assets", groupId: 3, modifiedAt: ago(0), size: "—", sharedWith: ["Sarah McIntyre", "Jordan Kim", "Marcus Webb"], activeEditors: [], ownerId: 1, starred: true },
|
|
{ id: 2, type: "folder", name: "Engineering Docs", groupId: 2, modifiedAt: ago(1), size: "—", sharedWith: ["Marcus Webb"], activeEditors: [], ownerId: 1, starred: false },
|
|
// PDFs
|
|
{ id: 3, type: "file", name: "Q2 Board Presentation.pdf", groupId: 2, modifiedAt: ago(0), size: "4.2 MB", sharedWith: ["Priya Anand", "Marcus Webb"], activeEditors: ["Sarah McIntyre"], ownerId: 1, starred: true },
|
|
{ id: 4, type: "file", name: "Brand Guidelines.pdf", groupId: 1, modifiedAt: ago(3), size: "12.8 MB", sharedWith: ["Sarah McIntyre", "Jordan Kim"], activeEditors: [], ownerId: 2, starred: false },
|
|
{ id: 5, type: "file", name: "Legal NDA Template.pdf", groupId: 2, modifiedAt: ago(14), size: "0.9 MB", sharedWith: ["Priya Anand"], activeEditors: [], ownerId: 1, starred: false },
|
|
// Docs
|
|
{ id: 6, type: "file", name: "Product Roadmap.docx", groupId: 3, modifiedAt: ago(0), size: "1.1 MB", sharedWith: ["Sarah McIntyre", "Priya Anand", "Jordan Kim"], activeEditors: ["Marcus Webb", "Priya Anand"], ownerId: 1, starred: true },
|
|
{ id: 7, type: "file", name: "Sprint 22 Notes.md", groupId: 3, modifiedAt: ago(1), size: "18 KB", sharedWith: ["Marcus Webb"], activeEditors: [], ownerId: 3, starred: false },
|
|
{ id: 8, type: "file", name: "Onboarding Checklist.docx", groupId: 1, modifiedAt: ago(5), size: "245 KB", sharedWith: ["Sarah McIntyre", "Priya Anand"], activeEditors: [], ownerId: 1, starred: false },
|
|
// Spreadsheets
|
|
{ id: 9, type: "file", name: "Budget 2026.xlsx", groupId: 2, modifiedAt: ago(2), size: "3.3 MB", sharedWith: ["Priya Anand"], activeEditors: ["Jordan Kim"], ownerId: 1, starred: true },
|
|
{ id: 10, type: "file", name: "Member Directory.csv", groupId: 4, modifiedAt: ago(7), size: "88 KB", sharedWith: ["Priya Anand", "Marcus Webb", "Sarah McIntyre"], activeEditors: [], ownerId: 2, starred: false },
|
|
{ id: 11, type: "file", name: "Event Attendance.xlsx", groupId: 3, modifiedAt: ago(10), size: "1.4 MB", sharedWith: [], activeEditors: [], ownerId: 3, starred: false },
|
|
// Images
|
|
{ id: 12, type: "file", name: "Logo Final.png", groupId: 1, modifiedAt: ago(21), size: "2.1 MB", sharedWith: ["Jordan Kim", "Sarah McIntyre"], activeEditors: [], ownerId: 2, starred: false },
|
|
{ id: 13, type: "file", name: "Homepage Hero.jpg", groupId: 3, modifiedAt: ago(4), size: "5.6 MB", sharedWith: ["Sarah McIntyre"], activeEditors: ["Sarah McIntyre"], ownerId: 1, starred: false },
|
|
{ id: 14, type: "file", name: "Team Photo 2026.jpg", groupId: 1, modifiedAt: ago(30), size: "8.9 MB", sharedWith: ["Priya Anand", "Marcus Webb", "Jordan Kim"], activeEditors: [], ownerId: 1, starred: true },
|
|
// Code / config
|
|
{ id: 15, type: "file", name: "api-config.json", groupId: 2, modifiedAt: ago(0), size: "4 KB", sharedWith: ["Marcus Webb"], activeEditors: ["Marcus Webb"], ownerId: 3, starred: false },
|
|
// Presentations
|
|
{ id: 16, type: "file", name: "Investor Deck May.pptx", groupId: 2, modifiedAt: ago(6), size: "18.4 MB", sharedWith: ["Priya Anand"], activeEditors: [], ownerId: 1, starred: true },
|
|
// External shared
|
|
{ id: 17, type: "file", name: "Vendor Contract.pdf", groupId: 5, modifiedAt: ago(45), size: "2.2 MB", sharedWith: ["Priya Anand"], activeEditors: [], ownerId: 1, starred: false },
|
|
{ id: 18, type: "file", name: "External Proposal.docx", groupId: 5, modifiedAt: ago(8), size: "0.7 MB", sharedWith: [], activeEditors: [], ownerId: 1, starred: false },
|
|
]
|
|
}
|
|
|
|
get locationLabel() {
|
|
return this.locations.find(l => l.id === this.activeLocation)?.label || "All Files"
|
|
}
|
|
|
|
get visibleFiles() {
|
|
let files = this.files;
|
|
|
|
// Filter by active groups
|
|
files = files.filter(f => this.activeGroupIds.has(f.groupId));
|
|
|
|
// Filter by location
|
|
if (this.activeLocation === "mine") files = files.filter(f => f.ownerId === 1);
|
|
if (this.activeLocation === "shared") files = files.filter(f => f.sharedWith?.length > 0);
|
|
if (this.activeLocation === "starred") files = files.filter(f => f.starred);
|
|
if (this.activeLocation === "recent") files = files.sort((a, b) => new Date(b.modifiedAt) - new Date(a.modifiedAt)).slice(0, 10);
|
|
|
|
// Search
|
|
if (this.searchText) {
|
|
const q = this.searchText.toLowerCase();
|
|
files = files.filter(f => f.name.toLowerCase().includes(q));
|
|
}
|
|
|
|
return files;
|
|
}
|
|
|
|
render() {
|
|
HStack(() => {
|
|
// Left sidebar
|
|
VStack(() => {
|
|
DesktopFilesSidebar(
|
|
this.groups,
|
|
this.activeGroupIds,
|
|
(groupId) => {
|
|
if (this.activeGroupIds.has(groupId)) {
|
|
if (this.activeGroupIds.size > 1) this.activeGroupIds.delete(groupId);
|
|
} else {
|
|
this.activeGroupIds.add(groupId);
|
|
}
|
|
this.rerender();
|
|
},
|
|
this.locations,
|
|
this.activeLocation,
|
|
(locId) => { this.activeLocation = locId; this.rerender(); }
|
|
)
|
|
})
|
|
.width(220, px)
|
|
.minWidth(200, px)
|
|
.height(100, pct)
|
|
.borderRight("1px solid var(--divider)")
|
|
.flexShrink(0)
|
|
.overflow("hidden")
|
|
|
|
// Main area
|
|
VStack(() => {
|
|
DesktopFilesToolbar(
|
|
this.locationLabel,
|
|
this.viewMode,
|
|
this.searchText,
|
|
(mode) => { this.viewMode = mode; this.rerender(); },
|
|
(text) => { this.searchText = text; this.rerender(); },
|
|
() => {}
|
|
)
|
|
|
|
DesktopFilesGrid(
|
|
this.visibleFiles,
|
|
this.groups,
|
|
this.viewMode,
|
|
() => {}
|
|
)
|
|
.flex(1)
|
|
.minHeight(0)
|
|
.width(100, pct)
|
|
.overflow("hidden")
|
|
})
|
|
.flex(1)
|
|
.height(100, pct)
|
|
.overflow("hidden")
|
|
})
|
|
.height(100, pct)
|
|
.width(100, pct)
|
|
.overflow("hidden")
|
|
}
|
|
}
|
|
|
|
register(Files)
|