Skip to content

Commit

Permalink
Added addition quick select dropdown for custom model selection.
Browse files Browse the repository at this point in the history
Moved main header text over to conversations sidebar header
  • Loading branch information
fingerthief committed Jul 6, 2024
1 parent 6b92e8c commit 8735bf1
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 27 deletions.
43 changes: 40 additions & 3 deletions src/components/dialogs/ConversationsDialog.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup>
import { onMounted, ref, nextTick } from 'vue';
import { Plus, Eraser, Download, Upload, MessageSquareX, Settings, Pencil, Database, Trash, MoreHorizontal } from 'lucide-vue-next';
import { onMounted, ref, nextTick, computed } from 'vue';
import { Plus, Eraser, Download, Upload, MessageSquareX, Settings, Pencil, Database, Trash, MoreHorizontal, Github } from 'lucide-vue-next';
import ToolTip from '../controls/ToolTip.vue';
import {
conversations,
Expand All @@ -12,6 +12,7 @@ import {
isSidebarOpen,
isSmallScreen,
showStoredFiles,
selectedModel,
} from '@/libs/state-management/state';
import { deleteCurrentConversation, editConversationTitle, saveMessagesHandler } from '@/libs/conversation-management/useConversations';
import { showToast } from '@/libs/utils/general-utils';
Expand Down Expand Up @@ -185,6 +186,18 @@ function toggleContextMenu() {
}
}
const modelTypes = [
{ name: 'claude', display: 'MinimalClaude' },
{ name: 'gpt', display: 'MinimalGPT' },
{ name: 'open-ai-format', display: 'MinimalCustom' },
{ name: 'web-llm', display: 'MinimalLocal' },
{ name: 'general', display: 'No Model Selected' },
];
const visibleModelLinks = computed(() => {
return modelTypes.filter((modelType) => selectedModel.value.includes(modelType.name));
});
</script>

<template>
Expand All @@ -195,6 +208,14 @@ function toggleContextMenu() {
<Database @click.stop="showStoredFiles = !showStoredFiles" v-if="!isSmallScreen" :id="'stored-Files'"
class="database-icon" />
<ToolTip :targetId="'stored-Files'" v-if="!isSmallScreen">View Stored Files</ToolTip>
<a v-for="modelType in visibleModelLinks" :key="modelType.name" id="navLink" v-show="!isSmallScreen"
href="https://github.com/fingerthief/minimal-chat" target="_blank" class="no-style-link">
{{ modelType.display }}
<Github :size="25" class="header-icon" />
</a>
<a href="https://github.com/fingerthief/minimal-chat" target="_blank" class="no-style-link">

</a>
<MoreHorizontal @blur="showContextMenu = false;" class="context-menu-icon" @click="toggleContextMenu"
id="contextMenu" :size="25" :stroke-width="1.0" />
<transition name="fade-slide">
Expand All @@ -207,7 +228,7 @@ function toggleContextMenu() {
<Upload @click="importConversations" id="importConversations" :size="25" :stroke-width="1.0" />
</div>
</transition>
<Settings v-if="!isSmallScreen" @click="toggleSidebar" class="settings-icon" :size="25" :stroke-width="1.0" />
<Settings v-if="!isSmallScreen" @click="toggleSidebar" class="settings-icon" :size="25" />
</h2>
</div>
<div class="sidebar-content-container">
Expand Down Expand Up @@ -262,6 +283,11 @@ function toggleContextMenu() {
<style lang="scss" scoped>
$shadow-color: #252629;
.header-icon {
position: absolute;
margin-left: 6px;
}
.new-conversation {
border-top: 1px solid black;
text-align: center;
Expand Down Expand Up @@ -293,6 +319,17 @@ $shadow-color: #252629;
text-align: left;
white-space: nowrap;
a {
left: 20px;
top: 22%;
position: relative;
@media (max-width: 600px) {
background-color: #0a1e24;
position: relative;
}
}
@media (max-width: 600px) {
text-align: center;
top: 16px;
Expand Down
68 changes: 46 additions & 22 deletions src/components/layout/ChatHeader.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
<!-- eslint-disable no-unused-vars -->

<script setup>
import { computed, ref } from 'vue';
import { computed, ref, watch } from 'vue';
import { Menu, Database, Github } from 'lucide-vue-next';
import { isSidebarOpen, showConversationOptions, selectedModel, showStoredFiles } from '@/libs/state-management/state';
import { isSidebarOpen, showConversationOptions, selectedModel, showStoredFiles, availableModels, localModelName } from '@/libs/state-management/state';
import ContextWindow from '@/components/controls/ContextWindow.vue';
import Dropdown from 'primevue/dropdown';
import { update } from '@/libs/utils/settings-utils';
// Define props
const props = defineProps({
Expand All @@ -16,16 +17,15 @@ const contextWindow = ref(null);
const emit = defineEmits(['toggle-sidebar', 'toggle-conversations', 'delete-conversation', 'new-conversation', 'change-model']);
const modelTypes = [
{ name: 'claude', display: 'MinimalClaude' },
{ name: 'gpt', display: 'MinimalGPT' },
{ name: 'open-ai-format', display: 'MinimalCustom' },
{ name: 'web-llm', display: 'MinimalLocal' },
{ name: 'general', display: 'No Model Selected' },
];
const showCustomModelDropdown = computed(() => selectedModel.value.includes('open-ai-format'));
const selectedCustomModel = ref('');
const visibleModelLinks = computed(() => {
return modelTypes.filter((modelType) => selectedModel.value.includes(modelType.name));
watch(selectedCustomModel, (newValue) => {
if (newValue) {
// You might want to update the selectedModel or emit an event here
console.log('Selected custom model:', newValue);
}
});
function toggleSidebar() {
Expand Down Expand Up @@ -54,23 +54,26 @@ const modelOptions = [
{ label: 'Custom API Endpoint', value: 'open-ai-format' },
{ label: 'Local Browser Model (Chrome and Edge Only)', value: 'web-llm' },
];
function handleUpdate(field, value) {
update(field, value);
}
</script>

<template>
<div class="header box">
<a v-for="modelType in visibleModelLinks" :key="modelType.name" id="navLink"
href="https://github.com/fingerthief/minimal-chat" target="_blank" class="no-style-link">
{{ modelType.display }}
</a>
<a href="https://github.com/fingerthief/minimal-chat" target="_blank" class="no-style-link">
<Github :size="20" :stroke-width="2.5" class="header-icon" />
</a>
<div class="models-dropdown">
<div class="control select-dropdown">
<label for="quick-select-model-selector"></label>
<Dropdown id="quick-select-model-selector" :options="modelOptions" v-model="selectedModel" optionValue="value"
optionLabel="label" @change="onModelChange" checkmark />
</div>
<div v-if="showCustomModelDropdown" class="control select-dropdown custom-model-dropdown">
<label for="custom-model-selector"></label>
<Dropdown id="custom-model-selector" :options="availableModels" v-model="localModelName"
@change="handleUpdate('localModelName', $event.value)" optionValue="id" optionLabel="name" filter
placeholder="Select a custom model" />
</div>
</div>
<div class="settings-btn">
<Menu @click="toggleSidebar" :stroke-width="1" :size="30" />&nbsp;&nbsp;
Expand All @@ -82,7 +85,7 @@ const modelOptions = [
</div>
</template>

<style lang="scss" scoped>
<style lang="scss">
/* Add your component-specific styles here */
$icon-color: rgb(187, 187, 187);
$shadow-color: #252629;
Expand All @@ -101,6 +104,11 @@ $shadow-spread-radius: 0px;
position: absolute;
}
.p-dropdown-filter-icon {
top: 28%;
}
.p-dropdown {
background-color: transparent;
border-bottom: 2px solid #157474;
Expand All @@ -114,6 +122,7 @@ $shadow-spread-radius: 0px;
font-size: 16px;
padding: 4px;
&:hover {
background-color: #262627;
}
Expand All @@ -133,10 +142,25 @@ $shadow-spread-radius: 0px;
cursor: pointer;
outline: none;
max-width: fit-content;
display: flex;
align-items: center;
transition:
background-color 0.15s ease,
transform 0.2s ease;
.custom-model-dropdown {
margin-left: -30px;
}
@media (max-width: 600px) {
flex-direction: column;
align-items: flex-start;
.custom-model-dropdown {
margin-left: 0;
margin-top: 10px;
}
}
transition: background-color 0.15s ease,
transform 0.2s ease;
.select-dropdown {
select {
Expand Down
20 changes: 18 additions & 2 deletions src/views/ChatLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<script setup>
import { onMounted, ref } from 'vue';
import { determineModelDisplayName, handleDoubleClick } from '@/libs/utils/general-utils';
import { determineModelDisplayName, handleDoubleClick, removeAPIEndpoints } from '@/libs/utils/general-utils';
import { handleExportConversations } from '@/libs/conversation-management/conversations-management';
import { uploadFileContentsToConversation, uploadFile, imageInputChanged } from '@/libs/file-processing/file-processing';
import messageItem from '@/components/controls/MessagesList.vue';
Expand All @@ -26,14 +26,16 @@ import {
conversations,
higherContrastMessages,
showStoredFiles,
isSmallScreen
isSmallScreen,
availableModels
} from '@/libs/state-management/state';
import { setupWatchers } from '@/libs/state-management/watchers';
import { saveMessagesHandler, selectConversationHandler } from '@/libs/conversation-management/useConversations';
import { addMessage } from '@/libs/conversation-management/message-processing';
import { runTutortialForNewUser } from '@/libs/utils/tutorial-utils';
import "driver.js/dist/driver.css";
import "../assets/tutorial.css";
import { getOpenAICompatibleAvailableModels } from '@/libs/api-access/open-ai-api-standard-access';
const sidebarContentContainer = ref(null);
Expand All @@ -55,6 +57,17 @@ async function imageInputChangedHandler(event) {
}
//#endregion
async function fetchAvailableModels() {
try {
if (localModelEndpoint.value.trim() !== '') {
const models = await getOpenAICompatibleAvailableModels(removeAPIEndpoints(localModelEndpoint.value));
availableModels.value = models;
}
} catch (error) {
console.error('Error fetching available models:', error);
}
}
//#region Lifecycle Hooks
onMounted(async () => {
setupWatchers();
Expand All @@ -65,6 +78,9 @@ onMounted(async () => {
modelDisplayName.value = determineModelDisplayName(selectedModel.value);
higherContrastMessages.value = localStorage.getItem('higherContrastMessages') || false;
if (selectedModel.value === 'open-ai-format') {
fetchAvailableModels();
}
selectConversationHandler(lastLoadedConversationId.value || conversations.value[0]?.id);
Expand Down

0 comments on commit 8735bf1

Please sign in to comment.