Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/lib/appList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { PUBLIC_TITAN_BASE_URL } from "$env/static/public";

// 1. Define only the specific model constants you need
const tvViewership = "tv-viewership-2";
const revenueAgent = "revenue-agent";
const policyChatbot = "policy-chatbot";

// 2. Create a Union Type from these specific values
export type AppModel =
| typeof policyChatbot
| typeof tvViewership
| typeof revenueAgent;

export type AppItem = {
label: string;
href: string;
icon: string;
model?: AppModel;
access?: boolean;
tag?: string;
};

// 3. Flattened array containing only the three requested apps
export const apps: AppItem[] = [
{
label: "TV Viewership Agent",
href: `${PUBLIC_TITAN_BASE_URL}/?model=${tvViewership}`,
icon: "/static/suite/tv-viewership-2.svg",
model: tvViewership,
access: false,
},
{
label: "TV Revenue Agent",
href: `${PUBLIC_TITAN_BASE_URL}/?model=${revenueAgent}`,
icon: "/static/suite/revenue-agent.svg",
model: revenueAgent,
access: false,
},
{
label: "Policy Chatbot",
href: `${PUBLIC_TITAN_BASE_URL}/?model=${policyChatbot}`,
icon: "/static/suite/policy-chatbot.svg",
model: policyChatbot,
access: false,
}
];
138 changes: 138 additions & 0 deletions src/lib/components/NavbarApps.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<script lang="ts">
import { models } from '$lib/stores';
import { DropdownMenu, Dialog } from 'bits-ui';
import { apps as appList, type AppItem } from '$lib/appList';
import XMark from './icons/XMark.svelte';

let showNoAccessModal = false;

const updateAppAccess = (
apps: AppItem[],
userAccess: { id: string; [key: string]: any }[]
): AppItem[] => {
const accessibleModelIds = new Set(userAccess.map((item) => item.id));

return apps.map((app) => ({
...app,
access: !app.model || accessibleModelIds.has(app.model)
}));
};

const handleAppClick = (e: MouseEvent, app: AppItem) => {
if (!app.access) {
e.preventDefault();
showNoAccessModal = true;
}
};

$: displayApps = updateAppAccess(appList, $models);
</script>

<div class="flex lg:hidden items-center">
<DropdownMenu.Root>
<DropdownMenu.Trigger
class="inline-flex items-center gap-2 py-2 px-4 rounded-md text-sm font-medium bg-slate-100 dark:bg-gray-850 text-gray-900 dark:text-white hover:bg-slate-200 dark:hover:bg-gray-800 whitespace-nowrap transition-colors"
>
Apps
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</DropdownMenu.Trigger>

<DropdownMenu.Content
class="bg-white border border-gray-200 rounded-md shadow-lg mt-2 py-1 w-[260px] z-[999] dark:bg-gray-850 dark:border-gray-700"
>
{#each displayApps as app}
<DropdownMenu.Item>
<a
href={app.href}
target={!app.model ? "_blank" : "_self"}
on:click={(e) => handleAppClick(e, app)}
class="px-4 py-3 flex items-center gap-3 text-gray-900 dark:text-white hover:bg-slate-50 dark:hover:bg-gray-800 transition-colors {!app.access ? 'opacity-60 cursor-not-allowed' : ''}"
>
<img src={app.icon} alt={app.label} class="w-5 h-5 shrink-0" />
<span class="text-sm font-medium">
{app.label}
{#if app.tag}
<small class="opacity-60 ml-1">{app.tag}</small>
{/if}
</span>

{#if !app.access}
<svg class="w-3.5 h-3.5 ml-auto text-gray-500 dark:text-gray-400" fill="currentColor" viewBox="0 0 20 20">
<path
fill-rule="evenodd"
d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z"
clip-rule="evenodd"
/>
</svg>
{/if}
</a>
</DropdownMenu.Item>
{/each}
</DropdownMenu.Content>
</DropdownMenu.Root>
</div>

<div class="hidden lg:flex flex-wrap items-center gap-3">
{#each displayApps as app}
<a
href={app.href}
target={!app.model ? "_blank" : "_self"}
on:click={(e) => handleAppClick(e, app)}
class="inline-flex items-center justify-center font-primary py-2 px-4 rounded-md text-xs font-medium bg-slate-100 dark:bg-gray-850 text-gray-900 dark:text-white transition-colors {!app.access ? 'opacity-60 cursor-not-allowed' : 'hover:bg-slate-300 dark:hover:bg-gray-800'}"
>
<img src={app.icon} alt={app.label} class="w-5 h-5 shrink-0 mr-2" />
<span>
{app.label}
{#if app.tag}
<small class="opacity-60 ml-1">{app.tag}</small>
{/if}
</span>

{#if !app.access}
<svg class="w-3.5 h-3.5 ml-2 text-gray-500 dark:text-gray-400" fill="currentColor" viewBox="0 0 20 20">
<path
fill-rule="evenodd"
d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z"
clip-rule="evenodd"
/>
</svg>
{/if}
</a>
{/each}
</div>

<Dialog.Root bind:open={showNoAccessModal}>
<Dialog.Portal>
<Dialog.Overlay class="fixed inset-0 z-[1000] bg-black/50" />

<Dialog.Content
class="fixed z-[1001] top-1/2 left-1/2 w-[90vw] max-w-md
-translate-x-1/2 -translate-y-1/2
bg-white dark:bg-gray-800 rounded-lg shadow-xl p-6 text-center border border-white dark:border-gray-600"
>
<div class="flex justify-center mt-8 mb-3">
<div class="w-[70px]">
<img src="/static/error-icon.svg" alt="">
</div>
</div>
<Dialog.Title class="text-lg font-semibold text-black mb-1 dark:text-white">Restricted Access</Dialog.Title>

<Dialog.Description class="text-slate-600 dark:text-slate-300 mb-4 text-sm">
For access, kindly contact
<a href="mailto:titan.support@jiostar.com" class="font-medium text-secondary-700 dark:text-secondary-50 underline underline-offset-[3px]">titan.support@jiostar.com</a
>.
</Dialog.Description>
<Dialog.Close
class="focus-visible:ring-foreground focus-visible:ring-offset-background focus-visible:outline-hidden absolute right-5 top-5 rounded-md focus-visible:ring-2 focus-visible:ring-offset-2 active:scale-[0.98]"
>
<div>
<div class="border-gray-700 dark:border-gray-500 text-black p-1 border rounded-md">
<XMark className="w-5 h-5 text-black dark:text-white"></XMark>
</div>
</div>
</Dialog.Close>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
9 changes: 4 additions & 5 deletions src/lib/components/chat/Navbar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@
import ChatCheck from '../icons/ChatCheck.svelte';
import Knobs from '../icons/Knobs.svelte';
import { WEBUI_API_BASE_URL } from '$lib/constants';

import AppDropdown from '$lib/components/app-dropdown.svelte';
import NavbarApps from '$lib/components/NavbarApps.svelte'
import TitanSupport from '$lib/components/TitanSupport.svelte';

const i18n = getContext('i18n');
Expand Down Expand Up @@ -118,9 +117,9 @@
{/if}
</div>

<!-- <div class="flex-1 flex gap-3 justify-end xl:justify-center mr-3 xl:mr-0">
<AppDropdown />
</div> -->
<div class="flex-1 flex gap-3 justify-end lg:justify-center mr-3 xl:mr-0">
<NavbarApps />
</div>

<div class="flex flex-none items-center text-gray-600 dark:text-gray-400 ml-auto">

Expand Down
Loading