Skip to content

Commit

Permalink
[studio] implement login #1298 (#1318)
Browse files Browse the repository at this point in the history
* studio - login

* studio - login spinner

* studio - auth error

* studio - login

* studio - login

* studio - fixed path
  • Loading branch information
janavlachova authored Oct 20, 2024
1 parent 74bab00 commit ddcb70e
Show file tree
Hide file tree
Showing 18 changed files with 305 additions and 146 deletions.
10 changes: 9 additions & 1 deletion .github/workflows/agdb_studio.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ jobs:
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run test:unit
working-directory: agdb_api/typescript
- run: npm run build
working-directory: agdb_api/typescript
- run: npm ci
- run: npm run test
- uses: actions/upload-artifact@v4
if: always()
with:
Expand All @@ -57,6 +61,10 @@ jobs:
working-directory: agdb_studio
steps:
- uses: actions/checkout@v4
- run: npm ci
working-directory: agdb_api/typescript
- run: npm run build
working-directory: agdb_api/typescript
- run: npm ci
- run: npx playwright install --with-deps
- run: npm run build
Expand Down
21 changes: 21 additions & 0 deletions .vscode/terminals.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,27 @@
"open": true,
"focus": false,
"commands": ["cd agdb_web"]
},
{
"name": "studio SERVER",
"description": "For running web studio server",
"open": true,
"focus": false,
"commands": ["cd agdb_studio", "npm run dev"]
},
{
"name": "studio SCRIPTS",
"description": "For running studio scripts",
"open": true,
"focus": false,
"commands": ["cd agdb_studio"]
},
{
"name": "api SCRIPTS",
"description": "For running api/typescript scripts",
"open": true,
"focus": false,
"commands": ["cd agdb_api/typescript"]
}
]
}
26 changes: 16 additions & 10 deletions agdb_api/typescript/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { OpenAPIClientAxios } from "openapi-client-axios";
import { AxiosRequestConfig, OpenAPIClientAxios } from "openapi-client-axios";
import type { Client } from "./openapi";

type AgdbApi = {
token: string;
token: string | undefined;
login: (username: string, password: string) => Promise<string>; // eslint-disable-line no-unused-vars
logout: () => Promise<void>;
get_token: () => string;
get_token: () => string | undefined;
set_token: (token: string) => void; // eslint-disable-line no-unused-vars
reset_token: () => void;
};

async function login(username: string, password: string): Promise<string> {
Expand All @@ -19,26 +20,30 @@ async function login(username: string, password: string): Promise<string> {
return token.data;
}

function get_token(): string {
function get_token(): string | undefined {
return this.token;
}

async function logout(): Promise<void> {
await this.user_logout();
this.token = "";
this.interceptors.request.use((config) => {
return config;
});
this.reset_token();
}

function set_token(token: string) {
function set_token(token: string): void {
this.token = token;
this.interceptors.request.use((config) => {
this.interceptors.request.use((config: AxiosRequestConfig) => {
config.headers.Authorization = `Bearer ${token}`;
return config;
});
}

function reset_token(): void {
this.token = undefined;
this.interceptors.request.use((config: AxiosRequestConfig) => {
return config;
});
}

export type AgdbApiClient = Client & AgdbApi;

export async function client(address: String): Promise<AgdbApiClient> {
Expand All @@ -51,5 +56,6 @@ export async function client(address: String): Promise<AgdbApiClient> {
client.logout = logout;
client.set_token = set_token;
client.get_token = get_token;
client.reset_token = reset_token;
return client;
}
2 changes: 1 addition & 1 deletion agdb_api/typescript/tests/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe("openapi test", () => {
let client = await AgdbApi.client("http://localhost:3000");
await client.login("admin", "admin");
await client.logout();
expect(client.get_token()).toEqual("");
expect(client.get_token()).toEqual(undefined);

await expect(client.db_list()).rejects.toThrowError(
"Request failed with status code 401",
Expand Down
2 changes: 1 addition & 1 deletion agdb_studio/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ npm run build
### Run Unit Tests with [Vitest](https://vitest.dev/)

```sh
npm run test:unit
npm run test
```

### Run End-to-End Tests with [Playwright](https://playwright.dev)
Expand Down
4 changes: 2 additions & 2 deletions agdb_studio/e2e/vue.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import { test, expect } from "@playwright/test";
// See here how to get started:
// https://playwright.dev/docs/intro
test("visits the app root url", async ({ page }) => {
await page.goto("/");
await expect(page.locator("div.main-wrapper")).toBeVisible();
await page.goto("/login");
await expect(page.locator("div.login-form")).toBeVisible();
});
49 changes: 49 additions & 0 deletions agdb_studio/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions agdb_studio/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@
"dev": "vite",
"build": "run-p type-check \"build-only {@}\" --",
"preview": "vite preview",
"test:unit": "vitest run --coverage",
"test": "vitest run --coverage",
"test:e2e": "playwright test",
"build-only": "vite build",
"type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false",
"lint": "eslint --max-warnings=0 . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
"format": "prettier --write src/ e2e/ tests/",
"format:check": "prettier --check src/ e2e/ tests/",
"before-commit": "npm run format && npm run lint && npm run test:unit && npm run test:e2e"
"before-commit": "npm run format && npm run lint && npm run test && npm run test:e2e"
},
"dependencies": {
"@kalimahapps/vue-icons": "^1.7.1",
"agdb_api": "file:../agdb_api/typescript",
"openapi-client-axios": "^7.5.1",
"pinia": "^2.1.7",
"vue": "^3.3.4",
Expand Down
50 changes: 25 additions & 25 deletions agdb_studio/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,32 +53,32 @@ const config: PlaywrightTestConfig = {
...devices["Desktop Chrome"],
},
},
{
name: "firefox",
use: {
...devices["Desktop Firefox"],
},
},
{
name: "webkit",
use: {
...devices["Desktop Safari"],
},
},
// {
// name: "firefox",
// use: {
// ...devices["Desktop Firefox"],
// },
// },
// {
// name: "webkit",
// use: {
// ...devices["Desktop Safari"],
// },
// },

/* Test against mobile viewports. */
{
name: "Mobile Chrome",
use: {
...devices["Pixel 5"],
},
},
{
name: "Mobile Safari",
use: {
...devices["iPhone 12"],
},
},
// /* Test against mobile viewports. */
// {
// name: "Mobile Chrome",
// use: {
// ...devices["Pixel 5"],
// },
// },
// {
// name: "Mobile Safari",
// use: {
// ...devices["iPhone 12"],
// },
// },

/* Test against branded browsers. */
// {
Expand Down
4 changes: 2 additions & 2 deletions agdb_studio/src/assets/button.less
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
}

.button-warning {
background-color: #ffc107;
color: #212529;
background-color: #ff9f2c;
color: #181818;
}

.button-danger {
Expand Down
34 changes: 30 additions & 4 deletions agdb_studio/src/components/auth/LoginForm.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,37 @@
<script lang="ts" setup>
import { ref } from "vue";
import { login } from "@/services/auth.service";
import { CgSpinnerTwo } from "@kalimahapps/vue-icons";
import router from "@/router";
const username = ref("");
const password = ref("");
const login = async () => {
// todo - handle login
const loading = ref(false);
const error = ref("");
const clearError = () => {
error.value = "";
};
const onLogin = async () => {
loading.value = true;
clearError();
login(username.value, password.value)
.then(() => {
loading.value = false;
router.push({ name: "home" });
})
.catch((e) => {
loading.value = false;
error.value = e.message;
});
};
</script>

<template>
<div class="base-form login-form">
<form @submit.prevent="login">
<form @submit.prevent="onLogin">
<div>
<label for="username">Username:</label>
<input type="text" id="username" v-model="username" required />
Expand All @@ -25,7 +45,10 @@ const login = async () => {
required
/>
</div>
<button type="submit" class="button button-success">Login</button>
<button type="submit" class="button button-success">
<CgSpinnerTwo v-if="loading" />
Login
</button>
</form>
</div>
</template>
Expand All @@ -38,5 +61,8 @@ const login = async () => {
font-size: 1.2rem;
margin-top: 0.6rem;
}
input {
border-radius: 0.2rem;
}
}
</style>
Loading

0 comments on commit ddcb70e

Please sign in to comment.