Add Text2Image UI, UI tests, Readme, and Docker support (#927)

Signed-off-by: Yue, Wenjiao <wenjiao.yue@intel.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
WenjiaoYue
2024-10-14 13:36:33 +08:00
committed by GitHub
parent c0643b71e8
commit c6fc92d37c
32 changed files with 1054 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

View File

@@ -0,0 +1,26 @@
# Copyright (C) 2024 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
# Use node 20.11.1 as the base image
FROM node:20.11.1
# Update package manager and install Git
RUN apt-get update -y && apt-get install -y git
# Copy the front-end code repository
COPY svelte /home/user/svelte
# Set the working directory
WORKDIR /home/user/svelte
# Install front-end dependencies
RUN npm install
# Build the front-end application
RUN npm run build
# Expose the port of the front-end application
EXPOSE 5173
# Run the front-end application in preview mode
CMD ["npm", "run", "preview", "--", "--port", "5173", "--host", "0.0.0.0"]

View File

@@ -0,0 +1,10 @@
[*]
indent_style = tab
[package.json]
indent_style = space
indent_size = 2
[*.md]
indent_style = space
indent_size = 2

View File

@@ -0,0 +1,2 @@
BASE_URL = '/v1/text2image'

View File

@@ -0,0 +1,13 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock

View File

@@ -0,0 +1,34 @@
// Copyright (c) 2024 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
module.exports = {
root: true,
parser: "@typescript-eslint/parser",
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
plugins: ["svelte3", "@typescript-eslint", "neverthrow"],
ignorePatterns: ["*.cjs"],
overrides: [{ files: ["*.svelte"], processor: "svelte3/svelte3" }],
settings: {
"svelte3/typescript": () => require("typescript"),
},
parserOptions: {
sourceType: "module",
ecmaVersion: 2020,
},
env: {
browser: true,
es2017: true,
node: true,
},
};

View File

@@ -0,0 +1,13 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock

View File

@@ -0,0 +1 @@
{"pluginSearchDirs": ["."], "overrides": [{"files": "*.svelte", "options": {"parser": "svelte"}}]}

View File

@@ -0,0 +1,29 @@
# Text2Image Customized UI
## 📸 Project Screenshots
![project-screenshot](../../assets/img/text2img_init.png)
![project-screenshot](../../assets/img/text2img_response.png)
## 🧐 Features
Here're some of the project's features:
- Generate Images from Text: Enter the image description and the desired number of images, then wait for them to be generated.
## 🛠️ Get it Running
1. Clone the repo.
2. cd command to the current folder.
3. Modify the required .env variables.
```
BACKEND_BASE_URL = ''
```
4. Execute `npm install` to install the corresponding dependencies.
5. Execute `npm run dev` in both environments

View File

@@ -0,0 +1,61 @@
{
"name": "sveltekit-auth-example",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check . && eslint .",
"format": "prettier --write ."
},
"devDependencies": {
"@fortawesome/free-solid-svg-icons": "6.2.0",
"@playwright/test": "^1.48.0",
"@sveltejs/adapter-auto": "1.0.0-next.75",
"@sveltejs/adapter-static": "^3.0.0",
"@sveltejs/kit": "^2.0.0",
"@tailwindcss/typography": "0.5.7",
"@types/debug": "4.1.7",
"@types/node": "^20.12.13",
"@typescript-eslint/eslint-plugin": "^5.27.0",
"@typescript-eslint/parser": "^5.27.0",
"autoprefixer": "^10.4.7",
"daisyui": "3.5.1",
"date-picker-svelte": "^2.6.0",
"debug": "4.3.4",
"eslint": "^8.16.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-neverthrow": "1.1.4",
"postcss": "^8.4.31",
"postcss-load-config": "^4.0.1",
"postcss-preset-env": "^8.3.2",
"prettier": "^2.8.8",
"prettier-plugin-svelte": "^2.7.0",
"prettier-plugin-tailwindcss": "^0.3.0",
"svelte": "^4.0.0",
"svelte-check": "^3.0.0",
"svelte-fa": "3.0.3",
"svelte-preprocess": "^6.0.2",
"tailwindcss": "^3.1.5",
"tslib": "^2.3.1",
"typescript": "^5.0.0",
"vite": "^5.0.0"
},
"type": "module",
"dependencies": {
"date-fns": "^2.30.0",
"driver.js": "^1.3.0",
"flowbite-svelte": "^0.38.5",
"flowbite-svelte-icons": "^1.4.0",
"fuse.js": "^6.6.2",
"lodash": "^4.17.21",
"playwright": "^1.44.0",
"ramda": "^0.29.0",
"sse.js": "^0.6.1",
"svelte-notifications": "^0.9.98",
"svrollbar": "^0.12.0"
}
}

View File

@@ -0,0 +1,54 @@
// Copyright (C) 2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
import { defineConfig, devices } from "@playwright/test";
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: "./tests",
/* Maximum time one test can run for. */
timeout: 10 * 60 * 1000,
expect: {
/**
* Maximum time expect() should wait for the condition to be met.
* For example in `await expect(locator).toHaveText();`
*/
timeout: 5000,
},
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: [["html", { open: "never" }]],
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
actionTimeout: 0,
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: "http://localhost:5173",
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
},
/* Configure projects for major browsers */
projects: [
{
name: "webkit",
use: { ...devices["Desktop Safari"] },
},
],
});

View File

@@ -0,0 +1,27 @@
// Copyright (c) 2024 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
const tailwindcss = require("tailwindcss");
const autoprefixer = require("autoprefixer");
const config = {
plugins: [
//Some plugins, like tailwindcss/nesting, need to run before Tailwind,
tailwindcss(),
//But others, like autoprefixer, need to run after,
autoprefixer,
],
};
module.exports = config;

16
Text2Image/ui/svelte/src/app.d.ts vendored Normal file
View File

@@ -0,0 +1,16 @@
// Copyright (c) 2024 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// See: https://kit.svelte.dev/docs/types#app
// import { Result} from "neverthrow";

View File

@@ -0,0 +1,28 @@
<!--
Copyright (c) 2024 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width" />
%sveltekit.head%
</head>
<body>
<div class="h-full w-full">%sveltekit.body%</div>
</body>
</html>

View File

@@ -0,0 +1,86 @@
/* Write your global styles here, in PostCSS syntax */
@tailwind base;
@tailwind components;
@tailwind utilities;
html, body {
height: 100%;
}
.btn {
@apply flex-nowrap;
}
a.btn {
@apply no-underline;
}
.input {
@apply text-base;
}
.bg-dark-blue {
background-color: #004a86;
}
.bg-light-blue {
background-color: #0068b5;
}
.bg-turquoise {
background-color: #00a3f6;
}
.bg-header {
background-color: #ffffff;
}
.bg-button {
background-color: #0068b5;
}
.bg-title {
background-color: #f7f7f7;
}
.text-header {
color: #0068b5;
}
.text-button {
color: #252e47;
}
.text-title-color {
color: rgb(38,38,38);
}
.font-intel {
font-family: "intel-clear","tahoma",Helvetica,"helvetica",Arial,sans-serif;
}
.font-title-intel {
font-family: "intel-one","intel-clear",Helvetica,Arial,sans-serif;
}
.bg-footer {
background-color: #e7e7e7;
}
.bg-light-green {
background-color: #d7f3a1;
}
.bg-purple {
background-color: #653171;
}
.bg-dark-blue {
background-color: #224678;
}
.border-input-color {
border-color: #605e5c;
}
.w-12\/12 {
width: 100%
}

View File

@@ -0,0 +1,94 @@
.driverjs-theme {
background: transparent;
color: #fff;
box-shadow: none;
padding: 0;
}
.driver-popover-arrow {
border: 10px solid transparent;
animation: blink 1s 3 steps(1);
}
@keyframes blink {
0% {
opacity: 1;
}
50% {
opacity: 0.2;
}
100% {
opacity: 1;
}
}
.driver-popover.driverjs-theme .driver-popover-arrow-side-left.driver-popover-arrow {
border-left-color: #174ed1;
}
.driver-popover.driverjs-theme .driver-popover-arrow-side-right.driver-popover-arrow {
border-right-color: #174ed1;
}
.driver-popover.driverjs-theme .driver-popover-arrow-side-top.driver-popover-arrow {
border-top-color: #174ed1;
}
.driver-popover.driverjs-theme .driver-popover-arrow-side-bottom.driver-popover-arrow {
border-bottom-color: #174ed1;
}
.driver-popover-footer {
background: transparent;
color: #fff;
}
.driver-popover-title {
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
.driver-popover-title,
.driver-popover-description {
display: block;
padding: 15px 15px 7px 15px;
background: #174ed1;
border: none;
}
.driver-popover-close-btn {
color: #fff;
}
.driver-popover-footer button:hover,
.driver-popover-footer button:focus {
background: #174ed1;
color: #fff;
}
.driver-popover-description {
padding: 5px 15px;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
}
.driver-popover-title[style*="block"] + .driver-popover-description {
margin: 0;
}
.driver-popover-progress-text {
color: #fff;
}
.driver-popover-footer button {
background: #174ed1;
border: 2px #174ed1 dashed;
color: #fff;
border-radius: 50%;
text-shadow: none;
}
.driver-popover-close-btn:hover,
.driver-popover-close-btn:focus {
color: #fff;
}
.driver-popover-navigation-btns button + button {
margin-left: 10px;
}

View File

@@ -0,0 +1,24 @@
<!--
Copyright (C) 2024 Intel Corporation
SPDX-License-Identifier: Apache-2.0
-->
<script lang="ts">
import { imgList } from "$lib/shared/stores/common/Store";
</script>
<p class="my-2 text-2xl" data-testid="display-img">Result</p>
<div
class="3xl:grid-cols-7 3xl:h-[45rem] mt-4 grid h-[26rem] grid-cols-5 gap-12 overflow-auto"
>
{#each $imgList as img}
<div class="h-[15rem]">
<img
src={"data:image/png;base64," + img}
class="h-full max-h-[16rem] w-full rounded-3xl bg-gray-600"
alt=""
/>
</div>
{/each}
</div>

View File

@@ -0,0 +1,39 @@
// Copyright (c) 2024 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { env } from "$env/dynamic/public";
const BACKEND_BASE_URL = env.BASE_URL;
export async function fetchImgList(query: string, img_num: number) {
const url = `${BACKEND_BASE_URL}`;
const data = {
prompt: query,
num_images_per_prompt: img_num,
};
const init: RequestInit = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
};
try {
const response = await fetch(url, init);
if (!response.ok) throw response.status;
return await response.json();
} catch (error) {
console.error("network error: ", error);
return undefined;
}
}

View File

@@ -0,0 +1,33 @@
<!--
Copyright (c) 2024 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<script>
</script>
<header
class="sticky top-0 z-40 flex-none w-full mx-auto bg-[#0054ae] border-b border-gray-200 dark:border-gray-600 dark:bg-gray-800"
>
<nav
class="bg-[#0054ae] dark:bg-gray-800 text-gray-500 dark:text-gray-400 border-gray-200 dark:border-gray-700 divide-gray-200 dark:divide-gray-700 px-2 sm:px-4 w-full py-1.5"
>
<div class="mx-auto flex flex-wrap justify-end items-center w-full">
<span
class="self-center py-2 whitespace-nowrap text-[2rem] font-semibold text-white ml-4"
data-svelte-h="svelte-1hbktnk">Text2Image</span
>
</div>
</nav>
</header>

View File

@@ -0,0 +1,48 @@
<!--
Copyright (c) 2024 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<div
class="mb-6 flex items-center justify-center self-center bg-black text-sm text-gray-500"
/>
<div class="flex items-center justify-center gap-3">
<div class="relative inline-flex">
<div class="h-2 w-2 rounded-full bg-blue-600" />
<div
class="absolute left-0 top-0 h-2 w-2 animate-[ping_1s_infinite_100ms] rounded-full bg-blue-600"
/>
<div
class="duration-800 absolute left-0 top-0 h-2 w-2 animate-pulse rounded-full bg-blue-600"
/>
</div>
<div class="relative inline-flex">
<div class="h-2 w-2 rounded-full bg-blue-600" />
<div
class="absolute left-0 top-0 h-2 w-2 animate-[ping_1s_infinite_300ms] rounded-full bg-blue-600"
/>
<div
class="absolute left-0 top-0 h-2 w-2 animate-pulse rounded-full bg-blue-600"
/>
</div>
<div class="relative inline-flex">
<div class="h-2 w-2 rounded-full bg-blue-600" />
<div
class="absolute left-0 top-0 h-2 w-2 animate-[ping_1s_infinite_500ms] rounded-full bg-blue-600"
/>
<div
class="absolute left-0 top-0 h-2 w-2 animate-pulse rounded-full bg-blue-600"
/>
</div>
</div>

View File

@@ -0,0 +1,48 @@
<!--
Copyright (c) 2024 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<script lang="ts">
import { Svroller } from "svrollbar";
export let className: string = "";
export let classLayout: string = "";
export let alwaysVisible = true;
</script>
<div class={className}>
<Svroller height="100%" width="100%" {alwaysVisible}>
<div class={classLayout}>
<slot></slot>
</div>
</Svroller>
</div>
<style>
:global(.svlr-contents) {
height: 100%;
}
.row::-webkit-scrollbar {
display: none;
}
.row {
scrollbar-width: none;
}
.row {
-ms-overflow-style: none;
}
</style>

View File

@@ -0,0 +1,17 @@
// Copyright (c) 2024 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { writable } from "svelte/store";
export let imgList = writable([]);

View File

@@ -0,0 +1,29 @@
<!--
Copyright (c) 2024 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<script>
import "tailwindcss/tailwind.css";
import "../app.postcss";
import Notifications from "svelte-notifications";
</script>
<Notifications>
<div class="flex h-full flex-col">
<div class="h-0 grow bg-white lg:rounded-tl-3xl">
<slot />
</div>
</div>
</Notifications>

View File

@@ -0,0 +1,161 @@
<!--
Copyright (c) 2024 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<script lang="ts">
import "driver.js/dist/driver.css";
import "$lib/assets/layout/css/driver.css";
import { imgList } from "$lib/shared/stores/common/Store";
import Header from "$lib/shared/components/header/header.svelte";
import LoadingAnimation from "$lib/shared/components/loading/Loading.svelte";
import GenerateImg from "$lib/modules/imageList/GenerateImg.svelte";
import { fetchImgList } from "$lib/network/Network";
let query: string = "";
let loading: boolean = false;
let notNumber: boolean = false;
let inputHint: boolean = false;
let imgNum = 1;
let numButtons = [1, 2, 4];
let selectedButton = 1;
let genImgNum: number;
const selectButton = (button: number) => {
selectedButton = button;
imgNum = selectedButton;
notNumber = false; // Reset notNumber when selecting a button
};
const selectInput = () => {
selectedButton = 0;
notNumber = false;
verifyNum();
};
const updateInputHint = () => {
if (query) {
inputHint = false;
}
};
const verifyNum = () => {
if (/^\d+$/.test(genImgNum) && genImgNum > 0) {
imgNum = genImgNum;
notNumber = false;
} else {
notNumber = true;
}
};
const generateImages = async () => {
if (!query) {
inputHint = true;
return;
};
loading = true;
imgList.set([]);
await fetchImgList(query, imgNum).then((res) => {
imgList.set(res.images)
console.log('imgList', $imgList);
loading = false;
});
};
$: genImgNum && verifyNum();
$: query && updateInputHint();
</script>
<div class="h-full w-full bg-gray-200">
<Header />
<div class="mx-auto mt-[2%] h-[85%] w-[90%] rounded-3xl bg-white p-8">
<p class="text-3xl">AI Image Generator</p>
<div class="relative my-6 w-full">
<span class="absolute p-2 text-xs text-gray-500">Description prompt</span>
<input
class="block w-full rounded-xl border-gray-300 px-2 py-10 text-gray-900"
type="text"
data-testid="img-input"
placeholder="What do you want to see?"
disabled={loading}
maxlength="1200"
bind:value={query}
/>
{#if inputHint}
<p class="absolute -bottom-[1rem] mt-2 text-xs text-red-600">
Please input the details you want to describe!
</p>
{/if}
</div>
<div class="relative flex flex-row items-center justify-end gap-3">
<span class="text-[0.8rem] text-gray-700">Number of images:</span>
{#each numButtons as button}
<button
class="rounded-xl border px-6 py-1
{selectedButton === button
? 'border-2 border-[#1c64f2] outline-[#1c64f2] ring-2'
: 'border-gray-600'}"
on:click={() => selectButton(button)}
>
{button}
</button>
{/each}
<input
type="text"
class="
{selectedButton === 0
? 'border-2 border-[#1c64f2] outline-[#1c64f2] ring-2'
: 'border-gray-800'}
focus:ring-none h-[2.1rem] w-[3.6rem] rounded-xl pl-2 text-center focus:outline-none"
placeholder="?"
on:focus={selectInput}
bind:value={genImgNum}
/>
{#if notNumber}
<p
class="absolute -bottom-[1rem] right-[10rem] mt-2 text-xs text-red-600"
>
Enter a number greater than 0!
</p>
{/if}
<button
on:click={generateImages}
type="submit"
data-testid="img-gen"
class="ml-12 bg-blue-600 px-8 py-3 text-base font-medium text-white hover:bg-blue-700 focus:ring-blue-800"
>
Generate ({imgNum})
</button>
</div>
{#if loading}
<LoadingAnimation />
{:else if $imgList.length !== 0}
<GenerateImg />
{/if}
</div>
</div>
<style>
.row::-webkit-scrollbar {
display: none;
}
.row {
scrollbar-width: none;
-ms-overflow-style: none;
}
</style>

View File

@@ -0,0 +1,13 @@
// Copyright (c) 2024 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

View File

@@ -0,0 +1,38 @@
// Copyright (c) 2024 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import adapter from "@sveltejs/adapter-auto";
import preprocess from "svelte-preprocess";
import postcssPresetEnv from "postcss-preset-env";
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://github.com/sveltejs/svelte-preprocess
// for more information about preprocessors
preprocess: preprocess({
sourceMap: true,
postcss: {
plugins: [postcssPresetEnv({ features: { "nesting-rules": true } })],
},
}),
kit: {
adapter: adapter(),
env: {
publicPrefix: "",
},
},
};
export default config;

View File

@@ -0,0 +1,43 @@
// Copyright (c) 2024 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
const config = {
content: ["./src/**/*.{html,js,svelte,ts}", "./node_modules/flowbite-svelte/**/*.{html,js,svelte,ts}"],
plugins: [require("flowbite/plugin")],
darkMode: "class",
theme: {
extend: {
colors: {
// flowbite-svelte
primary: {
50: "#FFF5F2",
100: "#FFF1EE",
200: "#FFE4DE",
300: "#FFD5CC",
400: "#FFBCAD",
500: "#FE795D",
600: "#EF562F",
700: "#EB4F27",
800: "#CC4522",
900: "#A5371B",
},
},
},
},
};
module.exports = config;

View File

@@ -0,0 +1,28 @@
// Copyright (C) 2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
import { test, expect, type Page } from "@playwright/test";
// Initialization before each test
test.beforeEach(async ({ page }) => {
await page.goto("/");
});
// Constants definition
const CHAT_ITEMS = ["An astronaut riding a green horse"];
// Helper function: Enter message to chat
async function enterMessageToChat(page: Page, message: string) {
await page.getByTestId("img-input").click();
await page.getByTestId("img-input").fill(message);
await page.waitForTimeout(1000);
await page.getByTestId("img-gen").click();
}
// Test description: New Chat
test.describe("New Image", () => {
// Test: Enter message to generate new images
test("should enter message to generate new images", async ({ page }) => {
await enterMessageToChat(page, CHAT_ITEMS[0]);
});
});

View File

@@ -0,0 +1,13 @@
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true
}
}

View File

@@ -0,0 +1,26 @@
// Copyright (c) 2024 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { sveltekit } from "@sveltejs/kit/vite";
import type { UserConfig } from "vite";
const config: UserConfig = {
plugins: [sveltekit()],
server: {
host: "0.0.0.0",
port: 5173,
},
};
export default config;