mirror of
https://github.com/khoj-ai/khoj.git
synced 2025-02-17 08:04:21 +00:00
Put logout, settings under dropdown menu with logged in user's profile picture
- Create dropdown menu. Put settings page, logout action under it - Make user's profile picture the dropdown menu heading - Create khoj.js to store shared js across web client It currently stores the dropdown menu open, close functionality - Put shared styling for khoj dropdown menu under khoj.css
This commit is contained in:
parent
58a7171911
commit
f585a71744
7 changed files with 163 additions and 18 deletions
|
@ -100,6 +100,65 @@ p#khoj-banner {
|
|||
display: inline;
|
||||
}
|
||||
|
||||
/* Dropdown in navigation menu*/
|
||||
.khoj-nav-dropdown-content {
|
||||
display: block;
|
||||
grid-auto-flow: row;
|
||||
position: absolute;
|
||||
background-color: var(--background-color);
|
||||
min-width: 160px;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||
right: 15vw;
|
||||
z-index: 1;
|
||||
opacity: 0;
|
||||
transition: opacity 0.1s ease-in-out;
|
||||
pointer-events: none;
|
||||
text-align: left;
|
||||
}
|
||||
.khoj-nav-dropdown-content.show {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.khoj-nav-dropdown-content a {
|
||||
color: black;
|
||||
padding: 12px 16px;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
}
|
||||
.khoj-nav-dropdown-content a:hover {
|
||||
background-color: var(--primary-hover);
|
||||
}
|
||||
.khoj-nav-username {
|
||||
padding: 12px 16px;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
}
|
||||
img.circle {
|
||||
border-radius: 50%;
|
||||
border: 2px solid var(--primary-hover);
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 700px) {
|
||||
.khoj-nav-dropdown-content {
|
||||
display: block;
|
||||
grid-auto-flow: row;
|
||||
position: absolute;
|
||||
background-color: var(--background-color);
|
||||
min-width: 160px;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||
right: 10px;
|
||||
z-index: 1;
|
||||
opacity: 0;
|
||||
transition: opacity 0.1s ease-in-out;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
div.khoj-header {
|
||||
display: grid;
|
||||
|
|
15
src/khoj/interface/web/assets/khoj.js
Normal file
15
src/khoj/interface/web/assets/khoj.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
// Toggle the navigation menu
|
||||
function toggleMenu() {
|
||||
var menu = document.getElementById("khoj-nav-menu");
|
||||
menu.classList.toggle("show");
|
||||
}
|
||||
|
||||
// Close the dropdown menu if the user clicks outside of it
|
||||
document.addEventListener('click', function(event) {
|
||||
let menu = document.getElementById("khoj-nav-menu");
|
||||
let menuContainer = document.getElementById("khoj-nav-menu-container");
|
||||
let isClickOnMenu = menuContainer.contains(event.target) || menuContainer === event.target;
|
||||
if (isClickOnMenu === false && menu.classList.contains("show")) {
|
||||
menu.classList.remove("show");
|
||||
}
|
||||
});
|
|
@ -8,6 +8,7 @@
|
|||
<link rel="stylesheet" href="/static/assets/pico.min.css">
|
||||
<link rel="stylesheet" href="/static/assets/khoj.css">
|
||||
</head>
|
||||
<script type="text/javascript" src="/static/assets/khoj.js"></script>
|
||||
<body class="khoj-configure">
|
||||
<div class="khoj-header-wrapper">
|
||||
<div class="filler"></div>
|
||||
|
@ -18,7 +19,15 @@
|
|||
<nav class="khoj-nav">
|
||||
<a class="khoj-nav" href="/chat">💬 Chat</a>
|
||||
<a class="khoj-nav" href="/">🔎 Search</a>
|
||||
<a class="khoj-nav khoj-nav-selected" href="/config">⚙️ Settings</a>
|
||||
<!-- Dropdown Menu -->
|
||||
<div id="khoj-nav-menu-container" class="khoj-nav dropdown">
|
||||
<img class="circle" src="{{ user_photo }}" alt="{{ username }}" onclick="toggleMenu()">
|
||||
<div id="khoj-nav-menu" class="khoj-nav-dropdown-content">
|
||||
<div class="khoj-nav-username"> {{ username }} </div>
|
||||
<a class="khoj-nav khoj-nav-selected" href="/config">⚙️ Settings</a>
|
||||
<a class="khoj-nav" href="/auth/logout">🔑 Logout</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="filler"></div>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
<link rel="manifest" href="/static/khoj_chat.webmanifest">
|
||||
<link rel="stylesheet" href="/static/assets/khoj.css">
|
||||
</head>
|
||||
<script type="text/javascript" src="/static/assets/khoj.js"></script>
|
||||
<script>
|
||||
let chatOptions = [];
|
||||
function copyProgrammaticOutput(event) {
|
||||
|
@ -284,7 +285,14 @@
|
|||
<a class="khoj-nav khoj-nav-selected" href="/chat">💬 Chat</a>
|
||||
<a class="khoj-nav" href="/">🔎 Search</a>
|
||||
{% if not demo %}
|
||||
<a class="khoj-nav" href="/config">⚙️ Settings</a>
|
||||
<!-- Dropdown Menu -->
|
||||
<div id="khoj-nav-menu-container" class="khoj-nav dropdown">
|
||||
<img class="circle" src="{{ user_photo }}" alt="{{ username }}" onclick="toggleMenu()">
|
||||
<div id="khoj-nav-menu" class="khoj-nav-dropdown-content">
|
||||
<div class="khoj-nav-username"> {{ username }} </div>
|
||||
<a class="khoj-nav khoj-nav-selected" href="/config">⚙️ Settings</a>
|
||||
<a class="khoj-nav" href="/auth/logout">🔑 Logout</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</nav>
|
||||
</div>
|
||||
|
|
|
@ -3,11 +3,6 @@
|
|||
|
||||
<div class="page">
|
||||
<div class="section">
|
||||
{% if anonymous_mode == False %}
|
||||
<div>
|
||||
Logged in as {{ username }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">Plugins</h2>
|
||||
<div class="section-cards">
|
||||
<div class="card">
|
||||
|
@ -328,11 +323,6 @@
|
|||
<div class="finalize-buttons">
|
||||
<button id="reinitialize" type="submit" title="Regenerate index from scratch">🔄 Reinitialize</button>
|
||||
</div>
|
||||
{% if anonymous_mode == False %}
|
||||
<div class="finalize-buttons">
|
||||
<button id="logout" class="logout" onclick="window.location.href='/auth/logout'">Logout</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
</head>
|
||||
<script type="text/javascript" src="/static/assets/org.min.js"></script>
|
||||
<script type="text/javascript" src="/static/assets/markdown-it.min.js"></script>
|
||||
<script type="text/javascript" src="/static/assets/khoj.js"></script>
|
||||
|
||||
<script>
|
||||
function render_image(item) {
|
||||
|
@ -296,7 +297,15 @@
|
|||
<a class="khoj-nav" href="/chat">💬 Chat</a>
|
||||
<a class="khoj-nav khoj-nav-selected" href="/">🔎 Search</a>
|
||||
{% if not demo %}
|
||||
<a class="khoj-nav" href="/config">⚙️ Settings</a>
|
||||
<!-- Dropdown Menu -->
|
||||
<div id="khoj-nav-menu-container" class="khoj-nav dropdown">
|
||||
<img class="circle" src="{{ user_photo }}" alt="{{ username }}" onclick="toggleMenu()">
|
||||
<div id="khoj-nav-menu" class="khoj-nav-dropdown-content">
|
||||
<div class="khoj-nav-username"> {{ username }} </div>
|
||||
<a class="khoj-nav" href="/config">⚙️ Settings</a>
|
||||
<a class="khoj-nav" href="/auth/logout">🔑 Logout</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</nav>
|
||||
</div>
|
||||
|
|
|
@ -34,19 +34,52 @@ VALID_TEXT_CONTENT_TYPES = ["org", "markdown", "pdf", "plaintext"]
|
|||
@web_client.get("/", response_class=FileResponse)
|
||||
@requires(["authenticated"], redirect="login_page")
|
||||
def index(request: Request):
|
||||
return templates.TemplateResponse("index.html", context={"request": request, "demo": state.demo})
|
||||
user = request.user.object
|
||||
user_picture = request.session.get("user", {}).get("picture")
|
||||
|
||||
return templates.TemplateResponse(
|
||||
"index.html",
|
||||
context={
|
||||
"request": request,
|
||||
"demo": state.demo,
|
||||
"username": user.username if user else None,
|
||||
"user_photo": user_picture,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@web_client.post("/", response_class=FileResponse)
|
||||
@requires(["authenticated"], redirect="login_page")
|
||||
def index_post(request: Request):
|
||||
return templates.TemplateResponse("index.html", context={"request": request, "demo": state.demo})
|
||||
user = request.user.object
|
||||
user_picture = request.session.get("user", {}).get("picture")
|
||||
|
||||
return templates.TemplateResponse(
|
||||
"index.html",
|
||||
context={
|
||||
"request": request,
|
||||
"demo": state.demo,
|
||||
"username": user.username if user else None,
|
||||
"user_photo": user_picture,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@web_client.get("/chat", response_class=FileResponse)
|
||||
@requires(["authenticated"], redirect="login_page")
|
||||
def chat_page(request: Request):
|
||||
return templates.TemplateResponse("chat.html", context={"request": request, "demo": state.demo})
|
||||
user = request.user.object
|
||||
user_picture = request.session.get("user", {}).get("picture")
|
||||
|
||||
return templates.TemplateResponse(
|
||||
"chat.html",
|
||||
context={
|
||||
"request": request,
|
||||
"demo": state.demo,
|
||||
"username": user.username if user else None,
|
||||
"user_photo": user_picture,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@web_client.get("/login", response_class=FileResponse)
|
||||
|
@ -84,6 +117,7 @@ if not state.demo:
|
|||
@requires(["authenticated"], redirect="login_page")
|
||||
def config_page(request: Request):
|
||||
user = request.user.object
|
||||
user_picture = request.session.get("user", {}).get("picture")
|
||||
enabled_content = set(EntryAdapters.get_unique_file_types(user).all())
|
||||
default_full_config = FullConfig(
|
||||
content_type=None,
|
||||
|
@ -129,6 +163,7 @@ if not state.demo:
|
|||
"current_model_state": successfully_configured,
|
||||
"anonymous_mode": state.anonymous_mode,
|
||||
"username": user.username if user else None,
|
||||
"user_photo": user_picture,
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -136,6 +171,7 @@ if not state.demo:
|
|||
@requires(["authenticated"], redirect="login_page")
|
||||
def github_config_page(request: Request):
|
||||
user = request.user.object
|
||||
user_picture = request.session.get("user", {}).get("picture")
|
||||
current_github_config = get_user_github_config(user)
|
||||
|
||||
if current_github_config:
|
||||
|
@ -158,13 +194,20 @@ if not state.demo:
|
|||
current_config = {} # type: ignore
|
||||
|
||||
return templates.TemplateResponse(
|
||||
"content_type_github_input.html", context={"request": request, "current_config": current_config}
|
||||
"content_type_github_input.html",
|
||||
context={
|
||||
"request": request,
|
||||
"current_config": current_config,
|
||||
"username": user.username if user else None,
|
||||
"user_photo": user_picture,
|
||||
},
|
||||
)
|
||||
|
||||
@web_client.get("/config/content_type/notion", response_class=HTMLResponse)
|
||||
@requires(["authenticated"], redirect="login_page")
|
||||
def notion_config_page(request: Request):
|
||||
user = request.user.object
|
||||
user_picture = request.session.get("user", {}).get("picture")
|
||||
current_notion_config = get_user_notion_config(user)
|
||||
|
||||
current_config = NotionContentConfig(
|
||||
|
@ -174,7 +217,13 @@ if not state.demo:
|
|||
current_config = json.loads(current_config.json())
|
||||
|
||||
return templates.TemplateResponse(
|
||||
"content_type_notion_input.html", context={"request": request, "current_config": current_config}
|
||||
"content_type_notion_input.html",
|
||||
context={
|
||||
"request": request,
|
||||
"current_config": current_config,
|
||||
"username": user.username if user else None,
|
||||
"user_photo": user_picture,
|
||||
},
|
||||
)
|
||||
|
||||
@web_client.get("/config/content_type/{content_type}", response_class=HTMLResponse)
|
||||
|
@ -185,6 +234,7 @@ if not state.demo:
|
|||
|
||||
object = map_config_to_object(content_type)
|
||||
user = request.user.object
|
||||
user_picture = request.session.get("user", {}).get("picture")
|
||||
config = object.objects.filter(user=user).first()
|
||||
if config == None:
|
||||
config = object.objects.create(user=user)
|
||||
|
@ -202,6 +252,8 @@ if not state.demo:
|
|||
"request": request,
|
||||
"current_config": current_config,
|
||||
"content_type": content_type,
|
||||
"username": user.username if user else None,
|
||||
"user_photo": user_picture,
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -209,6 +261,7 @@ if not state.demo:
|
|||
@requires(["authenticated"], redirect="login_page")
|
||||
def conversation_processor_config_page(request: Request):
|
||||
user = request.user.object
|
||||
user_picture = request.session.get("user", {}).get("picture")
|
||||
openai_config = ConversationAdapters.get_openai_conversation_config(user)
|
||||
|
||||
if openai_config:
|
||||
|
@ -229,5 +282,7 @@ if not state.demo:
|
|||
context={
|
||||
"request": request,
|
||||
"current_config": current_processor_openai_config,
|
||||
"username": user.username if user else None,
|
||||
"user_photo": user_picture,
|
||||
},
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue