Highly ambitious ATProtocol AppView service and sdks
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

consolidate tabs ui

Chad Miller a9cf1a8e 7d2dab66

+72 -165
+45
frontend/src/components/SliceTabs.tsx
··· 1 + export interface SliceTab { 2 + id: string; 3 + name: string; 4 + href: string; 5 + } 6 + 7 + export function getSliceTabs(sliceId: string): SliceTab[] { 8 + return [ 9 + { id: "overview", name: "Overview", href: `/slices/${sliceId}` }, 10 + { id: "lexicon", name: "Lexicons", href: `/slices/${sliceId}/lexicon` }, 11 + { id: "records", name: "Records", href: `/slices/${sliceId}/records` }, 12 + { id: "sync", name: "Sync", href: `/slices/${sliceId}/sync` }, 13 + { id: "codegen", name: "Code Gen", href: `/slices/${sliceId}/codegen` }, 14 + { id: "settings", name: "Settings", href: `/slices/${sliceId}/settings` }, 15 + ]; 16 + } 17 + 18 + interface SliceTabsProps { 19 + sliceId: string; 20 + currentTab: string; 21 + } 22 + 23 + export function SliceTabs({ sliceId, currentTab }: SliceTabsProps) { 24 + const tabs = getSliceTabs(sliceId); 25 + 26 + return ( 27 + <nav className="border-b border-gray-200 mb-6"> 28 + <div className="flex space-x-8"> 29 + {tabs.map((tab) => ( 30 + <a 31 + key={tab.id} 32 + href={tab.href} 33 + className={`py-2 px-1 border-b-2 font-medium text-sm ${ 34 + currentTab === tab.id 35 + ? "border-blue-500 text-blue-600" 36 + : "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300" 37 + }`} 38 + > 39 + {tab.name} 40 + </a> 41 + ))} 42 + </div> 43 + </nav> 44 + ); 45 + }
+2 -25
frontend/src/pages/SliceCodegenPage.tsx
··· 1 1 import { Layout } from "../components/Layout.tsx"; 2 2 import { CodegenForm } from "../components/CodegenForm.tsx"; 3 + import { SliceTabs } from "../components/SliceTabs.tsx"; 3 4 4 5 interface SliceCodegenPageProps { 5 6 sliceName?: string; ··· 12 13 sliceId = "example", 13 14 currentUser, 14 15 }: SliceCodegenPageProps) { 15 - const tabs = [ 16 - { id: "overview", name: "Overview", href: `/slices/${sliceId}` }, 17 - { id: "records", name: "Records", href: `/slices/${sliceId}/records` }, 18 - { id: "sync", name: "Sync", href: `/slices/${sliceId}/sync` }, 19 - { id: "lexicon", name: "Lexicons", href: `/slices/${sliceId}/lexicon` }, 20 - { id: "codegen", name: "Code Gen", href: `/slices/${sliceId}/codegen` }, 21 - { id: "settings", name: "Settings", href: `/slices/${sliceId}/settings` }, 22 - ]; 23 16 24 17 return ( 25 18 <Layout title={`${sliceName} - Code Generation`} currentUser={currentUser}> ··· 39 32 </div> 40 33 41 34 {/* Tab Navigation */} 42 - <div className="border-b border-gray-200 mb-8"> 43 - <nav className="-mb-px flex space-x-8"> 44 - {tabs.map((tab) => ( 45 - <a 46 - key={tab.id} 47 - href={tab.href} 48 - className={`py-2 px-1 border-b-2 font-medium text-sm ${ 49 - tab.id === "codegen" 50 - ? "border-blue-500 text-blue-600" 51 - : "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300" 52 - }`} 53 - > 54 - {tab.name} 55 - </a> 56 - ))} 57 - </nav> 58 - </div> 35 + <SliceTabs sliceId={sliceId} currentTab="codegen" /> 59 36 60 37 <CodegenForm sliceId={sliceId} /> 61 38
+2 -25
frontend/src/pages/SliceLexiconPage.tsx
··· 1 1 import { Layout } from "../components/Layout.tsx"; 2 2 import { EmptyLexiconState } from "../components/EmptyLexiconState.tsx"; 3 + import { SliceTabs } from "../components/SliceTabs.tsx"; 3 4 4 5 interface SliceLexiconPageProps { 5 6 sliceName?: string; ··· 12 13 sliceId = "example", 13 14 currentUser, 14 15 }: SliceLexiconPageProps) { 15 - const tabs = [ 16 - { id: "overview", name: "Overview", href: `/slices/${sliceId}` }, 17 - { id: "records", name: "Records", href: `/slices/${sliceId}/records` }, 18 - { id: "sync", name: "Sync", href: `/slices/${sliceId}/sync` }, 19 - { id: "lexicon", name: "Lexicons", href: `/slices/${sliceId}/lexicon` }, 20 - { id: "codegen", name: "Code Gen", href: `/slices/${sliceId}/codegen` }, 21 - { id: "settings", name: "Settings", href: `/slices/${sliceId}/settings` }, 22 - ]; 23 16 24 17 return ( 25 18 <Layout title={`${sliceName} - Lexicons`} currentUser={currentUser}> ··· 34 27 </div> 35 28 36 29 {/* Tab Navigation */} 37 - <div className="border-b border-gray-200 mb-8"> 38 - <nav className="-mb-px flex space-x-8"> 39 - {tabs.map((tab) => ( 40 - <a 41 - key={tab.id} 42 - href={tab.href} 43 - className={`py-2 px-1 border-b-2 font-medium text-sm ${ 44 - tab.id === "lexicon" 45 - ? "border-blue-500 text-blue-600" 46 - : "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300" 47 - }`} 48 - > 49 - {tab.name} 50 - </a> 51 - ))} 52 - </nav> 53 - </div> 30 + <SliceTabs sliceId={sliceId} currentTab="lexicon" /> 54 31 55 32 <div className="bg-white rounded-lg shadow-md p-6 mb-6"> 56 33 <h2 className="text-xl font-semibold text-gray-800 mb-4">
+17 -40
frontend/src/pages/SlicePage.tsx
··· 1 1 import { Layout } from "../components/Layout.tsx"; 2 + import { SliceTabs } from "../components/SliceTabs.tsx"; 2 3 3 4 interface Collection { 4 5 name: string; ··· 27 28 currentTab = "overview", 28 29 currentUser, 29 30 }: SlicePageProps) { 30 - const tabs = [ 31 - { id: "overview", name: "Overview", href: `/slices/${sliceId}` }, 32 - { id: "records", name: "Records", href: `/slices/${sliceId}/records` }, 33 - { id: "sync", name: "Sync", href: `/slices/${sliceId}/sync` }, 34 - { id: "lexicon", name: "Lexicons", href: `/slices/${sliceId}/lexicon` }, 35 - { id: "codegen", name: "Code Gen", href: `/slices/${sliceId}/codegen` }, 36 - { id: "settings", name: "Settings", href: `/slices/${sliceId}/settings` }, 37 - ]; 38 31 39 32 return ( 40 33 <Layout title={sliceName} currentUser={currentUser}> ··· 54 47 </div> 55 48 56 49 {/* Tab Navigation */} 57 - <div className="border-b border-gray-200 mb-8"> 58 - <nav className="-mb-px flex space-x-8"> 59 - {tabs.map((tab) => ( 60 - <a 61 - key={tab.id} 62 - href={tab.href} 63 - className={`py-2 px-1 border-b-2 font-medium text-sm ${ 64 - currentTab === tab.id 65 - ? "border-blue-500 text-blue-600" 66 - : "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300" 67 - }`} 68 - > 69 - {tab.name} 70 - </a> 71 - ))} 72 - </nav> 73 - </div> 50 + <SliceTabs sliceId={sliceId} currentTab={currentTab} /> 74 51 75 52 {totalRecords > 0 && ( 76 53 <div className="bg-blue-50 border border-blue-200 rounded-lg p-6 mb-8"> ··· 97 74 <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> 98 75 <div className="bg-white rounded-lg shadow-md p-6"> 99 76 <h2 className="text-xl font-semibold text-gray-800 mb-4"> 77 + 📚 Lexicon Definitions 78 + </h2> 79 + <p className="text-gray-600 mb-4"> 80 + View lexicon definitions and schemas that define your slice. 81 + </p> 82 + <a 83 + href={`/slices/${sliceId}/lexicon`} 84 + className="bg-purple-500 hover:bg-purple-600 text-white px-4 py-2 rounded" 85 + > 86 + View Lexicons 87 + </a> 88 + </div> 89 + 90 + <div className="bg-white rounded-lg shadow-md p-6"> 91 + <h2 className="text-xl font-semibold text-gray-800 mb-4"> 100 92 📝 View Records 101 93 </h2> 102 94 <p className="text-gray-600 mb-4"> ··· 114 106 No records synced yet. Start by syncing some records! 115 107 </p> 116 108 )} 117 - </div> 118 - 119 - <div className="bg-white rounded-lg shadow-md p-6"> 120 - <h2 className="text-xl font-semibold text-gray-800 mb-4"> 121 - 📚 Lexicon Definitions 122 - </h2> 123 - <p className="text-gray-600 mb-4"> 124 - View lexicon definitions and schemas. 125 - </p> 126 - <a 127 - href={`/slices/${sliceId}/lexicon`} 128 - className="bg-purple-500 hover:bg-purple-600 text-white px-4 py-2 rounded" 129 - > 130 - View Lexicons 131 - </a> 132 109 </div> 133 110 134 111 <div className="bg-white rounded-lg shadow-md p-6">
+2 -25
frontend/src/pages/SliceRecordsPage.tsx
··· 1 1 import { Layout } from "../components/Layout.tsx"; 2 + import { SliceTabs } from "../components/SliceTabs.tsx"; 2 3 3 4 interface Record { 4 5 uri: string; ··· 34 35 sliceId = "example", 35 36 currentUser, 36 37 }: SliceRecordsPageProps) { 37 - const tabs = [ 38 - { id: "overview", name: "Overview", href: `/slices/${sliceId}` }, 39 - { id: "records", name: "Records", href: `/slices/${sliceId}/records` }, 40 - { id: "sync", name: "Sync", href: `/slices/${sliceId}/sync` }, 41 - { id: "lexicon", name: "Lexicons", href: `/slices/${sliceId}/lexicon` }, 42 - { id: "codegen", name: "Code Gen", href: `/slices/${sliceId}/codegen` }, 43 - { id: "settings", name: "Settings", href: `/slices/${sliceId}/settings` }, 44 - ]; 45 38 46 39 return ( 47 40 <Layout title={`${sliceName} - Records`} currentUser={currentUser}> ··· 61 54 </div> 62 55 63 56 {/* Tab Navigation */} 64 - <div className="border-b border-gray-200 mb-8"> 65 - <nav className="-mb-px flex space-x-8"> 66 - {tabs.map((tab) => ( 67 - <a 68 - key={tab.id} 69 - href={tab.href} 70 - className={`py-2 px-1 border-b-2 font-medium text-sm ${ 71 - tab.id === "records" 72 - ? "border-blue-500 text-blue-600" 73 - : "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300" 74 - }`} 75 - > 76 - {tab.name} 77 - </a> 78 - ))} 79 - </nav> 80 - </div> 57 + <SliceTabs sliceId={sliceId} currentTab="records" /> 81 58 82 59 <div className="bg-white rounded-lg shadow-md p-6 mb-6"> 83 60 <div className="flex justify-between items-center mb-4">
+2 -25
frontend/src/pages/SliceSettingsPage.tsx
··· 1 1 import { Layout } from "../components/Layout.tsx"; 2 + import { SliceTabs } from "../components/SliceTabs.tsx"; 2 3 3 4 interface SliceSettingsPageProps { 4 5 sliceName?: string; ··· 11 12 sliceId = "example", 12 13 currentUser, 13 14 }: SliceSettingsPageProps) { 14 - const tabs = [ 15 - { id: "overview", name: "Overview", href: `/slices/${sliceId}` }, 16 - { id: "records", name: "Records", href: `/slices/${sliceId}/records` }, 17 - { id: "sync", name: "Sync", href: `/slices/${sliceId}/sync` }, 18 - { id: "lexicon", name: "Lexicons", href: `/slices/${sliceId}/lexicon` }, 19 - { id: "codegen", name: "Code Gen", href: `/slices/${sliceId}/codegen` }, 20 - { id: "settings", name: "Settings", href: `/slices/${sliceId}/settings` }, 21 - ]; 22 15 23 16 return ( 24 17 <Layout title={`${sliceName} - Settings`} currentUser={currentUser}> ··· 38 31 </div> 39 32 40 33 {/* Tab Navigation */} 41 - <div className="border-b border-gray-200 mb-8"> 42 - <nav className="-mb-px flex space-x-8"> 43 - {tabs.map((tab) => ( 44 - <a 45 - key={tab.id} 46 - href={tab.href} 47 - className={`py-2 px-1 border-b-2 font-medium text-sm ${ 48 - tab.id === "settings" 49 - ? "border-blue-500 text-blue-600" 50 - : "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300" 51 - }`} 52 - > 53 - {tab.name} 54 - </a> 55 - ))} 56 - </nav> 57 - </div> 34 + <SliceTabs sliceId={sliceId} currentTab="settings" /> 58 35 59 36 {/* Settings Content */} 60 37 <div className="space-y-8">
+2 -25
frontend/src/pages/SliceSyncPage.tsx
··· 1 1 import { Layout } from "../components/Layout.tsx"; 2 + import { SliceTabs } from "../components/SliceTabs.tsx"; 2 3 3 4 interface SliceSyncPageProps { 4 5 sliceName?: string; ··· 13 14 currentUser, 14 15 collections = [], 15 16 }: SliceSyncPageProps) { 16 - const tabs = [ 17 - { id: "overview", name: "Overview", href: `/slices/${sliceId}` }, 18 - { id: "records", name: "Records", href: `/slices/${sliceId}/records` }, 19 - { id: "sync", name: "Sync", href: `/slices/${sliceId}/sync` }, 20 - { id: "lexicon", name: "Lexicons", href: `/slices/${sliceId}/lexicon` }, 21 - { id: "codegen", name: "Code Gen", href: `/slices/${sliceId}/codegen` }, 22 - { id: "settings", name: "Settings", href: `/slices/${sliceId}/settings` }, 23 - ]; 24 17 25 18 return ( 26 19 <Layout title={`${sliceName} - Sync`} currentUser={currentUser}> ··· 40 33 </div> 41 34 42 35 {/* Tab Navigation */} 43 - <div className="border-b border-gray-200 mb-8"> 44 - <nav className="-mb-px flex space-x-8"> 45 - {tabs.map((tab) => ( 46 - <a 47 - key={tab.id} 48 - href={tab.href} 49 - className={`py-2 px-1 border-b-2 font-medium text-sm ${ 50 - tab.id === "sync" 51 - ? "border-blue-500 text-blue-600" 52 - : "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300" 53 - }`} 54 - > 55 - {tab.name} 56 - </a> 57 - ))} 58 - </nav> 59 - </div> 36 + <SliceTabs sliceId={sliceId} currentTab="sync" /> 60 37 61 38 <div className="bg-white rounded-lg shadow-md p-6 mb-6"> 62 39 <h2 className="text-xl font-semibold text-gray-800 mb-4">