Skip to content

Commit

Permalink
Merge pull request #4 from Eyevinn/feat/delete-source-from-inventory
Browse files Browse the repository at this point in the history
Delete "dead" source from inventory
  • Loading branch information
malmen237 committed Sep 5, 2024
2 parents 50d8e97 + 9554fe0 commit 2d9ac25
Show file tree
Hide file tree
Showing 13 changed files with 220 additions and 33 deletions.
22 changes: 22 additions & 0 deletions src/api/agileLive/ingest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,25 @@ export async function getSourceThumbnail(
}
throw await response.json();
}

export async function deleteSrtSource(ingestUuid: string, sourceId: number) {
const response = await fetch(
new URL(
AGILE_BASE_API_PATH + `/ingests/${ingestUuid}/sources/${sourceId}`,
process.env.AGILE_URL
),
{
method: 'DELETE',
headers: {
authorization: getAuthorizationHeader()
},
next: {
revalidate: 0
}
}
);
if (response.ok) {
return response.status;
}
throw await response.text();
}
21 changes: 20 additions & 1 deletion src/api/manager/inventory.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ObjectId } from 'mongodb';
import { ObjectId, UpdateResult } from 'mongodb';
import { getDatabase } from '../mongoClient/dbClient';
import { Numbers } from '../../interfaces/Source';
import { Log } from '../logger';

interface IResponse {
audio_stream?: {
Expand All @@ -20,3 +21,21 @@ export async function getAudioMapping(id: ObjectId): Promise<IResponse> {
throw `Could not find audio mapping for source: ${id.toString()}`;
})) as IResponse;
}

export async function purgeInventorySourceItem(
id: string
): Promise<UpdateResult<Document>> {
const db = await getDatabase();
const objectId = new ObjectId(id);

// Not possible to delete from API so this adds a purge-flag
// to the source
const result = await db
.collection('inventory')
.updateOne({ _id: objectId, status: 'gone' }, { $set: { status: 'purge' } })
.catch((error) => {
throw `Was not able to set source-id for ${id} to purge: ${error}`;
});

return result as UpdateResult<Document>;
}
33 changes: 28 additions & 5 deletions src/api/manager/job/syncInventory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,29 @@ async function getSourcesFromAPI() {
*/
export async function runSyncInventory() {
const db = await getDatabase();
const dbInventory = await db.collection<Source>('inventory').find().toArray();
const apiSources = await getSourcesFromAPI();
const dbInventory = await db.collection<Source>('inventory').find().toArray();

const statusUpdateCheck = (
inventorySource: WithId<Source>,
apiSource: SourceWithoutLastConnected,
lastConnected: Date
) => {
const databaseStatus = inventorySource.status;
const apiStatus = apiSource.status;
const currentTime = new Date().getTime();
const lastConnectedTime = new Date(lastConnected).getTime();
const monthInMilliseconds = 30 * 24 * 60 * 60 * 1000;
const expiryTime = lastConnectedTime + monthInMilliseconds;

if (databaseStatus === 'purge' && apiStatus === 'gone') {
return databaseStatus;
} else if (apiStatus === 'gone' && currentTime > expiryTime) {
return 'purge';
} else {
return apiStatus;
}
};

// Update status of all sources in the inventory to the status found in API.
// If a source is not found in the API, it is marked as gone.
Expand All @@ -73,12 +94,14 @@ export async function runSyncInventory() {
// If source was not found in response from API, always mark it as gone
return { ...inventorySource, status: 'gone' } satisfies WithId<Source>;
}
// Keep all old fields from the inventory source (name, tags, id, audio_stream etc), but update the status and set the lastConnected to the current date
const lastConnected =
apiSource.status !== 'gone' ? new Date() : inventorySource.lastConnected;

// Keep all old fields from the inventory source (name, tags, id, audio_stream etc), but update the status
return {
...inventorySource,
status: apiSource.status,
lastConnected:
apiSource.status !== 'gone' ? new Date() : inventorySource.lastConnected
status: statusUpdateCheck(inventorySource, apiSource, lastConnected),
lastConnected: lastConnected
} satisfies WithId<Source>;
});

Expand Down
39 changes: 39 additions & 0 deletions src/app/api/manager/inventory/[_id]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { NextRequest, NextResponse } from 'next/server';
import { isAuthenticated } from '../../../../../api/manager/auth';
import { Params } from 'next/dist/shared/lib/router/utils/route-matcher';
import { purgeInventorySourceItem } from '../../../../../api/manager/inventory';

export async function PUT(
request: NextRequest,
{ params }: { params: Params }
): Promise<NextResponse> {
if (!(await isAuthenticated())) {
return new NextResponse(`Not Authorized!`, {
status: 403
});
}

try {
const response = await purgeInventorySourceItem(params._id);
if (response.acknowledged && response.modifiedCount === 0) {
return new NextResponse(`Did not match requirements`, {
status: 204
});
} else if (response.acknowledged) {
return new NextResponse(null, {
status: 200
});
} else {
return new NextResponse(`Could not update database-status`, {
status: 500
});
}
} catch (error) {
return new NextResponse(
`Error occurred while posting to DB! Error: ${error}`,
{
status: 500
}
);
}
}
6 changes: 3 additions & 3 deletions src/app/production/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -649,13 +649,13 @@ export default function ProductionConfiguration({ params }: PageProps) {
/>
</div>
</HeaderNavigation>
<div className="flex max-h-full min-h-[100%] flex-row">
<div className="flex h-[95%] flex-row">
<div
className={`overflow-hidden transition-[min-width] w-0 min-w-0 ${
inventoryVisible ? 'min-w-[35%] ml-2 mt-2 max-h-[89vh]' : ''
}`}
>
<div className={`p-3 w-full bg-container rounded break-all h-full`}>
<div className={`p-3 w-full bg-container rounded break-all h-[98%]`}>
<div className="flex justify-end mb-2">
<button className="flex justify-end mb-2">
<IconX
Expand All @@ -674,7 +674,7 @@ export default function ProductionConfiguration({ params }: PageProps) {
</FilterProvider>
</div>
<ul
className={`flex flex-col border-t border-gray-600 overflow-scroll h-full ${
className={`flex flex-col border-t border-gray-600 overflow-scroll h-[91%] ${
!inventoryVisible && 'hidden'
} ${styles.no_scrollbar}`}
>
Expand Down
2 changes: 1 addition & 1 deletion src/components/button/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { PropsWithChildren } from 'react';
import { twMerge } from 'tailwind-merge';
type ButtonProps = {
type?: 'submit';
type?: 'submit' | 'button';
className?: string;
onClick?: () => void;
disabled?: boolean;
Expand Down
44 changes: 29 additions & 15 deletions src/components/inventory/Inventory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { useEffect, useState } from 'react';
import { useSources } from '../../hooks/sources/useSources';
import { useSetSourceToPurge } from '../../hooks/sources/useSetSourceToPurge';
import FilterOptions from '../../components/filter/FilterOptions';
import SourceListItem from '../../components/sourceListItem/SourceListItem';
import { SourceWithId } from '../../interfaces/Source';
Expand All @@ -10,13 +11,15 @@ import FilterContext from './FilterContext';
import styles from './Inventory.module.scss';

export default function Inventory() {
const [removeInventorySource, reloadList] = useSetSourceToPurge();
const [updatedSource, setUpdatedSource] = useState<
SourceWithId | undefined
>();
const [sources] = useSources(updatedSource);
const [sources] = useSources(reloadList, updatedSource);
const [currentSource, setCurrentSource] = useState<SourceWithId | null>();
const [filteredSources, setFilteredSources] =
useState<Map<string, SourceWithId>>(sources);

const inventoryVisible = true;

useEffect(() => {
Expand All @@ -25,6 +28,12 @@ export default function Inventory() {
}
}, [updatedSource]);

useEffect(() => {
if (reloadList) {
setCurrentSource(null);
}
}, [reloadList]);

const editSource = (source: SourceWithId) => {
setCurrentSource(() => source);
};
Expand All @@ -35,23 +44,25 @@ export default function Inventory() {
return Array.from(
filteredSources.size > 0 ? filteredSources.values() : sources.values()
).map((source, index) => {
return (
<SourceListItem
edit
key={`${source.ingest_source_name}-${index}`}
source={source}
disabled={false}
action={(source) => {
editSource(source);
}}
/>
);
if (source.status !== 'purge') {
return (
<SourceListItem
edit
key={`${source.ingest_source_name}-${index}`}
source={source}
disabled={false}
action={(source) => {
editSource(source);
}}
/>
);
}
});
}

return (
<FilterContext sources={sources}>
<div className="flex max-h-full min-h-[100%] flex-row">
<div className="flex h-[93%] flex-row">
<div
className={
inventoryVisible
Expand All @@ -71,19 +82,22 @@ export default function Inventory() {
/>
</div>
<ul
className={`flex flex-col border-t border-gray-600 overflow-scroll h-full ${styles.no_scrollbar}`}
className={`flex flex-col border-t border-gray-600 overflow-scroll h-[95%] ${styles.no_scrollbar}`}
>
{getSourcesToDisplay(filteredSources)}
</ul>
</div>
</div>

{currentSource ? (
<div className={`p-3 ml-2 mt-2 bg-container rounded h-1/2 min-w-max`}>
<div
className={`p-3 ml-2 mt-2 bg-container rounded h-[60%] min-w-max`}
>
<EditView
source={currentSource}
updateSource={(source) => setUpdatedSource(source)}
close={() => setCurrentSource(null)}
removeInventorySource={(source) => removeInventorySource(source)}
/>
</div>
) : null}
Expand Down
12 changes: 9 additions & 3 deletions src/components/inventory/editView/EditView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ import { IconExclamationCircle } from '@tabler/icons-react';
export default function EditView({
source,
updateSource,
close
close,
removeInventorySource
}: {
source: SourceWithId;
updateSource: (source: SourceWithId) => void;
close: () => void;
removeInventorySource: (source: SourceWithId) => void;
}) {
const [loaded, setLoaded] = useState(false);
const src = useMemo(() => getSourceThumbnail(source), [source]);

return (
<EditViewContext source={source} updateSource={updateSource}>
<div className="flex flex-row">
Expand Down Expand Up @@ -49,8 +52,11 @@ export default function EditView({
<div className="flex-auto">
<AudioChannels source={source} />
</div>

<UpdateButtons close={close} />
<UpdateButtons
close={close}
removeInventorySource={removeInventorySource}
source={source}
/>
</EditViewContext>
);
}
21 changes: 20 additions & 1 deletion src/components/inventory/editView/UpdateButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,18 @@ import { EditViewContext } from '../EditViewContext';
import { useTranslate } from '../../../i18n/useTranslate';
import styles from './animation.module.scss';
import { Loader } from '../../loader/Loader';
import { SourceWithId } from '../../../interfaces/Source';
import { IconTrash } from '@tabler/icons-react';

export default function UpdateButtons({ close }: { close: () => void }) {
export default function UpdateButtons({
close,
removeInventorySource,
source
}: {
close: () => void;
removeInventorySource: (source: SourceWithId) => void;
source: SourceWithId;
}) {
const t = useTranslate();
const {
saved: [saved],
Expand All @@ -22,6 +32,15 @@ export default function UpdateButtons({ close }: { close: () => void }) {
</div>

<div className="flex">
<Button
type="button"
state="warning"
disabled={source.status !== 'gone'}
className="mr-5 relative flex"
onClick={() => removeInventorySource(source)}
>
<IconTrash className="text-p" />
</Button>
<Button state="warning" onClick={close}>
{t('close')}
</Button>
Expand Down
2 changes: 1 addition & 1 deletion src/components/layout/DefaultLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default function DefaultLayout({
}) {
return (
<div className="flex h-screen justify-between w-full flex-col">
<div className="flex flex-row rounded p-2 w-full mb-8">
<div className="flex flex-row rounded p-2 w-full mb-8 h-full">
<div className="p-3 m-2 grow rounded">{children}</div>
</div>

Expand Down
Loading

0 comments on commit 2d9ac25

Please sign in to comment.