diff --git a/AiServer/wwwroot/Ui.mjs b/AiServer/wwwroot/Ui.mjs index 9de457e..383dd1a 100644 --- a/AiServer/wwwroot/Ui.mjs +++ b/AiServer/wwwroot/Ui.mjs @@ -12,7 +12,7 @@ import SpeechToText from "/mjs/components/SpeechToText.mjs" import TextToSpeech from "/mjs/components/TextToSpeech.mjs" import Transform from "/mjs/components/Transform.mjs" import UiHome from "/mjs/components/UiHome.mjs" -import { prefixes, icons } from "/mjs/utils.mjs" +import { prefixes, icons, uiLabel } from "/mjs/utils.mjs" const HomeSection = { id: '', @@ -148,12 +148,9 @@ export default { const refreshKey = ref(1) const showUserMenu = ref(false) - function toLabel(id) { - return humanify(id).replace('To','to') - } const sections = Object.keys(components).map(id => ({ id, - label: toLabel(id), + label: uiLabel(id), component: components[id], icon: icons[prefixes[id]], prefix: prefixes[id], diff --git a/AiServer/wwwroot/css/app.css b/AiServer/wwwroot/css/app.css index 3c302c9..f0a0ce5 100644 --- a/AiServer/wwwroot/css/app.css +++ b/AiServer/wwwroot/css/app.css @@ -1067,6 +1067,10 @@ select{ margin: auto; } +.-m-2 { + margin: -0.5rem; +} + .-mx-1\.5 { margin-left: -0.375rem; margin-right: -0.375rem; @@ -1318,6 +1322,10 @@ select{ margin-top: auto; } +.mt-32 { + margin-top: 8rem; +} + .block { display: block; } @@ -1346,6 +1354,10 @@ select{ display: table-cell; } +.flow-root { + display: flow-root; +} + .grid { display: grid; } @@ -1851,6 +1863,10 @@ select{ gap: 1.5rem; } +.gap-8 { + gap: 2rem; +} + .gap-x-1 { -moz-column-gap: 0.25rem; column-gap: 0.25rem; @@ -2020,6 +2036,10 @@ select{ white-space: pre; } +.text-balance { + text-wrap: balance; +} + .rounded { border-radius: 0.25rem; } @@ -2044,6 +2064,10 @@ select{ border-radius: 0.125rem; } +.rounded-xl { + border-radius: 0.75rem; +} + .rounded-l-md { border-top-left-radius: 0.375rem; border-bottom-left-radius: 0.375rem; @@ -2405,6 +2429,10 @@ select{ background-color: rgb(254 252 232 / var(--tw-bg-opacity)); } +.bg-gray-900\/5 { + background-color: rgb(17 24 39 / 0.05); +} + .bg-opacity-75 { --tw-bg-opacity: 0.75; } @@ -2607,6 +2635,21 @@ select{ padding-bottom: 2rem; } +.px-12 { + padding-left: 3rem; + padding-right: 3rem; +} + +.px-16 { + padding-left: 4rem; + padding-right: 4rem; +} + +.px-3\.5 { + padding-left: 0.875rem; + padding-right: 0.875rem; +} + .pb-0 { padding-bottom: 0px; } @@ -2830,6 +2873,11 @@ select{ line-height: 1rem; } +.text-4xl { + font-size: 2.25rem; + line-height: 2.5rem; +} + .font-bold { font-weight: 700; } @@ -3216,6 +3264,12 @@ select{ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } +.shadow-2xl { + --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25); + --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + .shadow-slate-200\/80 { --tw-shadow-color: rgb(226 232 240 / 0.8); --tw-shadow: var(--tw-shadow-colored); @@ -3301,6 +3355,10 @@ select{ --tw-ring-color: rgb(255 255 255 / var(--tw-ring-opacity)); } +.ring-gray-900\/10 { + --tw-ring-color: rgb(17 24 39 / 0.1); +} + .ring-opacity-5 { --tw-ring-opacity: 0.05; } @@ -3628,6 +3686,11 @@ select{ background-color: rgb(254 252 232 / var(--tw-bg-opacity)); } +.hover\:bg-indigo-500:hover { + --tw-bg-opacity: 1; + background-color: rgb(99 102 241 / var(--tw-bg-opacity)); +} + .hover\:text-blue-800:hover { --tw-text-opacity: 1; color: rgb(30 64 175 / var(--tw-text-opacity)); @@ -3869,10 +3932,26 @@ select{ outline-offset: 2px; } +.focus-visible\:outline:focus-visible { + outline-style: solid; +} + +.focus-visible\:outline-2:focus-visible { + outline-width: 2px; +} + +.focus-visible\:outline-offset-2:focus-visible { + outline-offset: 2px; +} + .focus-visible\:outline-black:focus-visible { outline-color: #000; } +.focus-visible\:outline-indigo-600:focus-visible { + outline-color: #4f46e5; +} + .focus-visible\:ring-0:focus-visible { --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color); @@ -4621,6 +4700,10 @@ select{ margin-top: 5rem; } + .sm\:mt-24 { + margin-top: 6rem; + } + .sm\:block { display: block; } @@ -4813,6 +4896,11 @@ select{ line-height: 1.25rem; } + .sm\:text-6xl { + font-size: 3.75rem; + line-height: 1; + } + .sm\:duration-700 { transition-duration: 700ms; } @@ -4980,6 +5068,10 @@ select{ z-index: 10; } + .lg\:-m-4 { + margin: -1rem; + } + .lg\:-mx-8 { margin-left: -2rem; margin-right: -2rem; @@ -5062,6 +5154,14 @@ select{ gap: 1.5rem; } + .lg\:rounded-2xl { + border-radius: 1rem; + } + + .lg\:p-4 { + padding: 1rem; + } + .lg\:px-1 { padding-left: 0.25rem; padding-right: 0.25rem; @@ -5093,6 +5193,10 @@ select{ padding-top: 1rem; } + .lg\:pb-40 { + padding-bottom: 10rem; + } + .lg\:text-center { text-align: center; } diff --git a/AiServer/wwwroot/mjs/components/UiHome.mjs b/AiServer/wwwroot/mjs/components/UiHome.mjs index 4ff1ff7..8b287d7 100644 --- a/AiServer/wwwroot/mjs/components/UiHome.mjs +++ b/AiServer/wwwroot/mjs/components/UiHome.mjs @@ -1,6 +1,6 @@ import { ref, inject, watch, onMounted } from "vue" import { langs, openAi } from "../langs.mjs" -import { icons } from "../utils.mjs" +import { prefixes, icons, uiLabel } from "../utils.mjs" export default { template: ` @@ -17,15 +17,15 @@ export default {

- + + +
- + Simple Unified API
@@ -37,9 +37,7 @@ export default {
- + Native Typed Integrations
@@ -51,9 +49,7 @@ export default {
- + Live Monitoring and Analytics
@@ -180,10 +176,46 @@ export default {
- + +
+
+ + +
+

Built-in UIs

+

+ Users also have access to custom UIs to access AI features protected by API Keys +

+
+ +
+ +
+ +
+
+ App screenshot +
+
+
+
-

+ + + +

Explore

@@ -245,7 +277,7 @@ export default {

-

+

Admin

@@ -321,7 +353,14 @@ export default { onMounted(() => { }) - return { routes, langs, openAi, icons } + const uis = Object.keys(prefixes).map(id => ({ + id, + label: uiLabel(id), + icon: icons[prefixes[id]], + prefix: prefixes[id], + })) + + return { routes, langs, openAi, icons, uis } } } diff --git a/AiServer/wwwroot/mjs/utils.mjs b/AiServer/wwwroot/mjs/utils.mjs index 1240a79..82a9078 100644 --- a/AiServer/wwwroot/mjs/utils.mjs +++ b/AiServer/wwwroot/mjs/utils.mjs @@ -1,6 +1,6 @@ import { ref, computed, inject, nextTick } from "vue" import { useFormatters } from "@servicestack/vue" -import { EventBus } from "@servicestack/client" +import { EventBus, humanify } from "@servicestack/client" const { truncate } = useFormatters() export const prefixes = { @@ -11,7 +11,10 @@ export const prefixes = { ImageUpscale: 'upscale', SpeechToText: 'spch2txt', TextToSpeech: 'txt2spch', - Transform: 'ffmpeg', + //Transform: 'ffmpeg', +} +export function uiLabel(id) { + return humanify(id).replace('To','to') } export function iconDataUri(svg) { @@ -35,6 +38,9 @@ export const icons = (() => { subtitle: "viewBox='0 0 24 24'%3E%3Cpath fill='currentColor' d='M6.577 15.423h7.846v-1H6.577zm9.846 0h1v-1h-1zm-9.846-3.577h1v-1h-1zm3 0h7.846v-1H9.577zM4.616 19q-.691 0-1.153-.462T3 17.384V6.616q0-.691.463-1.153T4.615 5h14.77q.69 0 1.152.463T21 6.616v10.769q0 .69-.463 1.153T19.385 19zm0-1h14.769q.23 0 .423-.192t.192-.424V6.616q0-.231-.192-.424T19.385 6H4.615q-.23 0-.423.192T4 6.616v10.769q0 .23.192.423t.423.192M4 18V6z'/%3E%3C/svg%3E", sync: "viewBox='0 0 24 24'%3E%3Cpath fill='currentColor' d='M7.78 5.97a.75.75 0 0 0-1.06 0l-5.25 5.25a.75.75 0 0 0 0 1.06l5.25 5.25a.75.75 0 0 0 1.06-1.06L3.81 12.5h16.38l-3.97 3.97a.75.75 0 1 0 1.06 1.06l5.25-5.25a.75.75 0 0 0 0-1.06l-5.25-5.25a.75.75 0 1 0-1.06 1.06L20.19 11H3.81l3.97-3.97a.75.75 0 0 0 0-1.06'/%3E%3C/svg%3E", reply: "viewBox='0 0 24 24'%3E%3Cpath fill='currentColor' d='m4.825 11l3.9 3.9q.3.3.288.7t-.313.7q-.3.275-.7.288t-.7-.288l-4.6-4.6q-.15-.15-.213-.325T2.426 11t.063-.375t.212-.325l4.6-4.6q.275-.275.688-.275T8.7 5.7q.3.3.3.713t-.3.712zm6 1l2.9 2.9q.3.3.288.7t-.313.7q-.3.275-.7.288t-.7-.288l-4.6-4.6q-.15-.15-.213-.325T7.426 11t.063-.375t.212-.325l4.6-4.6q.275-.275.688-.275t.712.275q.3.3.3.713t-.3.712L10.825 10H17q2.075 0 3.538 1.463T22 15v3q0 .425-.288.713T21 19t-.712-.288T20 18v-3q0-1.25-.875-2.125T17 12z'/%3E%3C/svg%3E", + typed: "viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='currentColor'%3E%3Cpath stroke-linecap='round' d='m13.5 7l3.5 3.5m-10 3l3.5 3.5m0-10L7 10.5m10 3L13.5 17'/%3E%3Ccircle cx='12' cy='5.5' r='2'/%3E%3Ccircle cx='12' cy='18.5' r='2'/%3E%3Ccircle cx='5.5' cy='12' r='2'/%3E%3Ccircle cx='18.5' cy='12' r='2'/%3E%3C/g%3E%3C/svg%3E", + one: "viewBox='0 0 24 24'%3E%3Cpath fill='currentColor' d='M8 20v1.933a.5.5 0 0 1-.82.384l-4.12-3.433A.5.5 0 0 1 3.382 18H18a2 2 0 0 0 2-2V8h2v8a4 4 0 0 1-4 4zm8-17.932a.5.5 0 0 1 .82-.385l4.12 3.433a.5.5 0 0 1-.321.884H6a2 2 0 0 0-2 2v8H2V8a4 4 0 0 1 4-4h10zM11 8h2v8h-2v-6H9V9z'/%3E%3C/svg%3E", + monitoring: "viewBox='0 0 32 32'%3E%3Cpath fill='currentColor' d='M28 16v6H4V6h7V4H4a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h8v4H8v2h16v-2h-4v-4h8a2 2 0 0 0 2-2v-6ZM18 28h-4v-4h4Z'/%3E%3Cpath fill='currentColor' d='M18 18h-.01a1 1 0 0 1-.951-.725L15.246 11H11V9h5a1 1 0 0 1 .962.725l1.074 3.76l3.009-9.78A1.01 1.01 0 0 1 22 3a.98.98 0 0 1 .949.684L24.72 9H30v2h-6a1 1 0 0 1-.949-.684l-1.013-3.04l-3.082 10.018A1 1 0 0 1 18 18'/%3E%3C/svg%3E", chat: "viewBox='0 0 26 26'%3E%3Cpath fill='currentColor' d='M10 0C4.547 0 0 3.75 0 8.5c0 2.43 1.33 4.548 3.219 6.094a4.778 4.778 0 0 1-.969 2.25a14.4 14.4 0 0 1-.656.781a2.507 2.507 0 0 0-.313.406c-.057.093-.146.197-.187.407c-.042.209.015.553.187.812l.125.219l.25.125c.875.437 1.82.36 2.688.125c.867-.236 1.701-.64 2.5-1.063c.798-.422 1.557-.864 2.156-1.187c.084-.045.138-.056.219-.094C10.796 19.543 13.684 21 16.906 21c.031.004.06 0 .094 0c1.3 0 5.5 4.294 8 2.594c.1-.399-2.198-1.4-2.313-4.375c1.957-1.383 3.22-3.44 3.22-5.719c0-3.372-2.676-6.158-6.25-7.156C18.526 2.664 14.594 0 10 0m0 2c4.547 0 8 3.05 8 6.5S14.547 15 10 15c-.812 0-1.278.332-1.938.688c-.66.355-1.417.796-2.156 1.187c-.64.338-1.25.598-1.812.781c.547-.79 1.118-1.829 1.218-3.281l.032-.563l-.469-.343C3.093 12.22 2 10.423 2 8.5C2 5.05 5.453 2 10 2'%3E%3C/path%3E%3C/svg%3E", txt2img: "viewBox='0 0 14 14'%3E%3Cg fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.77 8.286A3.5 3.5 0 0 1 5.577 6.88c.818 0 1.57.28 2.166.75'/%3E%3Cpath d='M5.076 10.629h-3.5a1 1 0 0 1-1-1v-8a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v3'/%3E%3Cpath d='M5.576 5.379a1.5 1.5 0 1 0 0-3a1.5 1.5 0 0 0 0 3m1.764 5.184c-.351-.061-.351-.565 0-.626a3.18 3.18 0 0 0 2.558-2.45l.021-.097c.076-.347.57-.349.649-.003l.026.113a3.19 3.19 0 0 0 2.565 2.435c.353.062.353.568 0 .63A3.19 3.19 0 0 0 10.594 13l-.026.113c-.079.346-.573.344-.649-.003l-.021-.097a3.18 3.18 0 0 0-2.558-2.45'/%3E%3C/g%3E%3C/svg%3E",