fix: remove site picker, hardcode Commercial site for SHAPE import browser
This commit is contained in:
parent
e954a8f78e
commit
1d01c3fb3d
2 changed files with 23 additions and 70 deletions
|
|
@ -25,6 +25,14 @@ async function graphGet(token: string, url: string) {
|
|||
return res.json()
|
||||
}
|
||||
|
||||
// Fixed to the Seubert Commercial SharePoint site
|
||||
const COMMERCIAL_SITE_URL = 'seubert365.sharepoint.com:/sites/Commercial'
|
||||
|
||||
async function getCommercialSiteId(token: string): Promise<string> {
|
||||
const data = await graphGet(token, `https://graph.microsoft.com/v1.0/sites/${COMMERCIAL_SITE_URL}?$select=id`)
|
||||
return data.id
|
||||
}
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const session = await getServerSession(authOptions)
|
||||
if (!session?.user) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
|
|
@ -32,27 +40,15 @@ export async function GET(req: NextRequest) {
|
|||
if (!roles.includes('Admin')) return NextResponse.json({ error: 'Forbidden' }, { status: 403 })
|
||||
|
||||
const { searchParams } = req.nextUrl
|
||||
const level = searchParams.get('level') ?? 'sites' // sites | drives | folders
|
||||
const siteId = searchParams.get('siteId') ?? ''
|
||||
const level = searchParams.get('level') ?? 'drives' // drives | folders
|
||||
const driveId = searchParams.get('driveId') ?? ''
|
||||
const itemId = searchParams.get('itemId') ?? '' // folder item id, empty = root
|
||||
|
||||
try {
|
||||
const token = await getGraphToken()
|
||||
|
||||
if (level === 'sites') {
|
||||
// List all SharePoint sites the app has access to
|
||||
const data = await graphGet(token, 'https://graph.microsoft.com/v1.0/sites?search=*&$top=50&$select=id,displayName,webUrl')
|
||||
const sites = (data.value ?? []).map((s: any) => ({
|
||||
id: s.id,
|
||||
name: s.displayName,
|
||||
url: s.webUrl,
|
||||
}))
|
||||
return NextResponse.json({ sites })
|
||||
}
|
||||
|
||||
if (level === 'drives') {
|
||||
if (!siteId) return NextResponse.json({ error: 'siteId required' }, { status: 400 })
|
||||
const siteId = await getCommercialSiteId(token)
|
||||
const data = await graphGet(token, `https://graph.microsoft.com/v1.0/sites/${siteId}/drives?$select=id,name,driveType`)
|
||||
const drives = (data.value ?? []).map((d: any) => ({
|
||||
id: d.id,
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ import {
|
|||
const DEFAULT_DRIVE_ID = 'b!OYuzIexQkkOvfEPyMJPzzZHfzTrOCOdPhTWgTlzKs6M0ZWVrAc6LR4LjWl4QFEzm'
|
||||
const DEFAULT_FOLDER_PATH = 'Claims/SHAPE Accounts'
|
||||
|
||||
interface SpSite { id: string; name: string; url: string }
|
||||
interface SpDrive { id: string; name: string; type: string }
|
||||
interface SpFolder { id: string; name: string }
|
||||
|
||||
|
|
@ -75,14 +74,11 @@ export function ShapeImportPanel({ initialRuns }: { initialRuns: Run[] }) {
|
|||
const [runs, setRuns] = useState<Run[]>(initialRuns)
|
||||
|
||||
// SharePoint picker state
|
||||
const [sites, setSites] = useState<SpSite[]>([])
|
||||
const [drives, setDrives] = useState<SpDrive[]>([])
|
||||
const [folders, setFolders] = useState<SpFolder[]>([])
|
||||
const [selectedSiteId, setSelectedSiteId] = useState<string>('')
|
||||
const [selectedDriveId, setSelectedDriveId] = useState<string>(DEFAULT_DRIVE_ID)
|
||||
const [selectedFolderId, setSelectedFolderId] = useState<string>('')
|
||||
const [folderPath, setFolderPath] = useState<string>(DEFAULT_FOLDER_PATH)
|
||||
const [loadingSites, setLoadingSites] = useState(false)
|
||||
const [loadingDrives, setLoadingDrives] = useState(false)
|
||||
const [loadingFolders, setLoadingFolders] = useState(false)
|
||||
const [pickerError, setPickerError] = useState<string | null>(null)
|
||||
|
|
@ -170,34 +166,16 @@ export function ShapeImportPanel({ initialRuns }: { initialRuns: Run[] }) {
|
|||
|
||||
useEffect(() => () => stopPolling(), [stopPolling])
|
||||
|
||||
// Load sites on mount
|
||||
// Load document libraries on mount (site is fixed to Commercial)
|
||||
useEffect(() => {
|
||||
setLoadingSites(true)
|
||||
setPickerError(null)
|
||||
fetch('/api/admin/shape-import/browse?level=sites')
|
||||
.then((r) => r.json())
|
||||
.then((d) => { if (d.sites) setSites(d.sites); else setPickerError(d.error ?? 'Failed to load sites') })
|
||||
.catch((e) => setPickerError(e.message))
|
||||
.finally(() => setLoadingSites(false))
|
||||
}, [])
|
||||
|
||||
const handleSiteChange = async (siteId: string) => {
|
||||
setSelectedSiteId(siteId)
|
||||
setSelectedDriveId('')
|
||||
setSelectedFolderId('')
|
||||
setFolderPath(DEFAULT_FOLDER_PATH)
|
||||
setDrives([])
|
||||
setFolders([])
|
||||
setLoadingDrives(true)
|
||||
setPickerError(null)
|
||||
try {
|
||||
const res = await fetch(`/api/admin/shape-import/browse?level=drives&siteId=${encodeURIComponent(siteId)}`)
|
||||
const d = await res.json()
|
||||
if (d.drives) setDrives(d.drives)
|
||||
else setPickerError(d.error ?? 'Failed to load drives')
|
||||
} catch (e: any) { setPickerError(e.message) }
|
||||
finally { setLoadingDrives(false) }
|
||||
}
|
||||
fetch('/api/admin/shape-import/browse?level=drives')
|
||||
.then((r) => r.json())
|
||||
.then((d) => { if (d.drives) setDrives(d.drives); else setPickerError(d.error ?? 'Failed to load document libraries') })
|
||||
.catch((e) => setPickerError(e.message))
|
||||
.finally(() => setLoadingDrives(false))
|
||||
}, [])
|
||||
|
||||
const handleDriveChange = async (driveId: string) => {
|
||||
setSelectedDriveId(driveId)
|
||||
|
|
@ -301,29 +279,8 @@ export function ShapeImportPanel({ initialRuns }: { initialRuns: Run[] }) {
|
|||
)}
|
||||
</div>
|
||||
|
||||
{/* Site */}
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">Site</Label>
|
||||
<Select
|
||||
value={selectedSiteId}
|
||||
onValueChange={handleSiteChange}
|
||||
disabled={isRunning || loadingSites}
|
||||
>
|
||||
<SelectTrigger className="h-8 text-sm">
|
||||
{loadingSites ? (
|
||||
<span className="flex items-center gap-2 text-muted-foreground">
|
||||
<Loader2 className="h-3 w-3 animate-spin" /> Loading sites…
|
||||
</span>
|
||||
) : (
|
||||
<SelectValue placeholder="Select a site…" />
|
||||
)}
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{sites.map((s) => (
|
||||
<SelectItem key={s.id} value={s.id}>{s.name}</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Site: <span className="font-medium text-foreground">seubert365.sharepoint.com/sites/Commercial</span>
|
||||
</div>
|
||||
|
||||
{/* Document library (drive) */}
|
||||
|
|
@ -332,7 +289,7 @@ export function ShapeImportPanel({ initialRuns }: { initialRuns: Run[] }) {
|
|||
<Select
|
||||
value={selectedDriveId}
|
||||
onValueChange={handleDriveChange}
|
||||
disabled={isRunning || loadingDrives || (!selectedSiteId && drives.length === 0)}
|
||||
disabled={isRunning || loadingDrives}
|
||||
>
|
||||
<SelectTrigger className="h-8 text-sm">
|
||||
{loadingDrives ? (
|
||||
|
|
@ -340,7 +297,7 @@ export function ShapeImportPanel({ initialRuns }: { initialRuns: Run[] }) {
|
|||
<Loader2 className="h-3 w-3 animate-spin" /> Loading libraries…
|
||||
</span>
|
||||
) : (
|
||||
<SelectValue placeholder={selectedSiteId ? 'Select a document library…' : 'Select a site first'} />
|
||||
<SelectValue placeholder="Select a document library…" />
|
||||
)}
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
|
|
@ -388,9 +345,9 @@ export function ShapeImportPanel({ initialRuns }: { initialRuns: Run[] }) {
|
|||
size="sm"
|
||||
className="h-6 text-xs gap-1"
|
||||
onClick={() => {
|
||||
setSelectedSiteId(''); setSelectedDriveId(DEFAULT_DRIVE_ID)
|
||||
setSelectedDriveId(DEFAULT_DRIVE_ID)
|
||||
setSelectedFolderId(''); setFolderPath(DEFAULT_FOLDER_PATH)
|
||||
setDrives([]); setFolders([])
|
||||
setFolders([])
|
||||
}}
|
||||
disabled={isRunning}
|
||||
>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue