Skip to content

Commit bf2191c

Browse files
committed
Updates from Rainer review
1 parent 0dfb780 commit bf2191c

File tree

12 files changed

+99
-97
lines changed

12 files changed

+99
-97
lines changed

.env.example

-3
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ PUBLIC_SUPABASE_API_KEY="your-anonymous-key"
1010
PUBLIC_USERSNAP_GLOBAL_API_KEY="usersnap-global-api-key"
1111
PUBLIC_USERSNAP_PROJECT_API_KEY="usersnap-project-api-key"
1212

13-
# SSO domain
14-
PUBLIC_SSO_DOMAIN="example.com"
15-
1613
###
1714
# Non-public vars stay on the server
1815
###

.prettierrc

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"trailingComma": "es5",
3+
"tabWidth": 2,
4+
"semi": true,
5+
"singleQuote": true,
6+
"jsxSingleQuote": true,
7+
"overrides": [
8+
{
9+
"files": [
10+
"**/*.mjs"
11+
],
12+
"options": {
13+
"singleQuote": true
14+
}
15+
}
16+
]
17+
}

astro.config.mjs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import { defineConfig } from "astro/config";
2-
import react from "@astrojs/react";
3-
import netlify from "@astrojs/netlify/functions";
1+
import { defineConfig } from 'astro/config';
2+
import react from '@astrojs/react';
3+
import netlify from '@astrojs/netlify/functions';
44

55
export default defineConfig({
66
integrations: [react()],
7-
output: "server",
7+
output: 'server',
88
adapter: netlify(),
99
vite: {
1010
ssr: {
11-
noExternal: ["@radix-ui/*", "@phosphor-icons/*"],
11+
noExternal: ['@radix-ui/*', '@phosphor-icons/*'],
1212
},
1313
},
1414
});

src/Types.ts

+17-17
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,11 @@ export interface DocumentInTaggedContext extends DocumentInContext {
138138
context: TaggedContext;
139139
}
140140

141-
export const ContentTypes = ["text/plain", "text/xml"] as const;
141+
export const ContentTypes = ['text/plain', 'text/xml'] as const;
142142

143143
export type ContentType = (typeof ContentTypes)[number];
144144

145-
export const Protocols = ["IIIF_IMAGE"] as const;
145+
export const Protocols = ['IIIF_IMAGE'] as const;
146146

147147
export type Protocol = (typeof Protocols)[number];
148148

@@ -214,14 +214,14 @@ export interface TagDefinition {
214214
name: string;
215215

216216
target_type?:
217-
| "context"
218-
| "document"
219-
| "group"
220-
| "layer"
221-
| "profile"
222-
| "project";
217+
| 'context'
218+
| 'document'
219+
| 'group'
220+
| 'layer'
221+
| 'profile'
222+
| 'project';
223223

224-
scope: "organization" | "project" | "system";
224+
scope: 'organization' | 'project' | 'system';
225225

226226
scope_id?: string;
227227
}
@@ -263,21 +263,21 @@ export interface Invitation {
263263
}
264264

265265
export type TableName =
266-
| "bodies"
267-
| "documents"
268-
| "contexts"
269-
| "layers"
270-
| "projects"
271-
| "targets";
266+
| 'bodies'
267+
| 'documents'
268+
| 'contexts'
269+
| 'layers'
270+
| 'projects'
271+
| 'targets';
272272

273-
export type OperationType = "SELECT" | "INSERT" | "UPDATE" | "DELETE";
273+
export type OperationType = 'SELECT' | 'INSERT' | 'UPDATE' | 'DELETE';
274274

275275
export type Policies = {
276276
get(t: TableName): { has: (operation: OperationType) => boolean };
277277
};
278278

279279
export type LoginMethod = {
280280
name: string;
281-
type: "username_password" | "saml" | "oauth" | "magic_link";
281+
type: 'username_password' | 'saml' | 'oauth' | 'magic_link';
282282
domain: string;
283283
};

src/apps/auth-login/Login.css

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
.login-separator::before,
4343
.login-separator::after {
4444
border-top: 1px solid var(--border-light-color);
45-
content: "";
45+
content: '';
4646
flex-grow: 1;
4747
}
4848

src/apps/auth-login/Login.tsx

+14-16
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
1-
import { useEffect, useState } from "react";
2-
import type { Session } from "@supabase/supabase-js";
3-
import { supabase } from "@backend/supabaseBrowserClient";
4-
import { isLoggedIn } from "@backend/auth";
5-
import type { LoginMethod, Translations } from "src/Types";
6-
import { StateChecking, StateLoginForm, StateMagicLink } from "./states";
7-
import { LoginMethodSelector } from "@apps/auth-login/LoginMethodSelector";
1+
import { useEffect, useState } from 'react';
2+
import type { Session } from '@supabase/supabase-js';
3+
import { supabase } from '@backend/supabaseBrowserClient';
4+
import { isLoggedIn } from '@backend/auth';
5+
import type { LoginMethod, Translations } from 'src/Types';
6+
import { StateChecking, StateLoginForm, StateMagicLink } from './states';
7+
import { LoginMethodSelector } from '@apps/auth-login/LoginMethodSelector';
88

9-
import "./Login.css";
10-
11-
const SSO_DOMAIN = import.meta.env.PUBLIC_SSO_DOMAIN;
9+
import './Login.css';
1210

1311
const setCookies = (session: Session | null) => {
14-
if (!session) throw "SIGNED_IN event without session - should never happen";
12+
if (!session) throw 'SIGNED_IN event without session - should never happen';
1513

1614
const maxAge = 100 * 365 * 24 * 60 * 60; // 100 years, never expires
1715
document.cookie = `sb-access-token=${session?.access_token}; path=/; max-age=${maxAge}; SameSite=Lax; secure`;
@@ -38,9 +36,9 @@ export const Login = (props: {
3836

3937
useEffect(() => {
4038
supabase.auth.onAuthStateChange((event, session) => {
41-
if (event === "SIGNED_OUT") {
39+
if (event === 'SIGNED_OUT') {
4240
clearCookies();
43-
} else if (event === "SIGNED_IN" || event === "TOKEN_REFRESHED") {
41+
} else if (event === 'SIGNED_IN' || event === 'TOKEN_REFRESHED') {
4442
setCookies(session);
4543
window.location.href = `/${props.i18n.lang}/projects`;
4644
}
@@ -74,13 +72,13 @@ export const Login = (props: {
7472

7573
const onMethodChanged = (method: LoginMethod) => {
7674
setCurrentMethod(method);
77-
if (method.type === "username_password") {
75+
if (method.type === 'username_password') {
7876
setShowLogin(true);
7977
setSendLink(false);
80-
} else if (method.type === "magic_link") {
78+
} else if (method.type === 'magic_link') {
8179
setSendLink(true);
8280
setShowLogin(false);
83-
} else if (method.type === "saml") {
81+
} else if (method.type === 'saml') {
8482
setSendLink(false);
8583
setShowLogin(false);
8684
signInWithSSO(method.domain);

src/apps/auth-login/LoginMethodSelector/LoginMethodSelector.tsx

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
import { ReactNode, forwardRef, useState } from "react";
2-
import * as Select from "@radix-ui/react-select";
3-
import { CaretDown, Check } from "@phosphor-icons/react";
4-
import { updateUserProjectGroup } from "@backend/crud";
5-
import { supabase } from "@backend/supabaseBrowserClient";
6-
import type { LoginMethod, Translations } from "src/Types";
1+
import { ReactNode, forwardRef } from 'react';
2+
import * as Select from '@radix-ui/react-select';
3+
import { CaretDown, Check } from '@phosphor-icons/react';
4+
import type { LoginMethod, Translations } from 'src/Types';
75

86
interface LoginMethodSelectorProps {
97
i18n: Translations;
@@ -51,7 +49,7 @@ export const LoginMethodSelector = (props: LoginMethodSelectorProps) => {
5149
onValueChange={onValueChange}
5250
>
5351
<Select.Trigger className='select-trigger' aria-label='Login method'>
54-
<Select.Value placeholder={t["Sign In"]} />
52+
<Select.Value placeholder={t['Sign In']} />
5553
<Select.Icon className='select-icon'>
5654
<CaretDown />
5755
</Select.Icon>

src/apps/auth-login/states/StateLoginForm.tsx

+22-22
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { useEffect, useState } from "react";
2-
import { Lock, MagicWand, WarningOctagon } from "@phosphor-icons/react";
3-
import { Button } from "@components/Button";
4-
import { TextInput } from "@components/TextInput";
5-
import { supabase } from "@backend/supabaseBrowserClient";
6-
import type { Translations } from "src/Types";
7-
import { isValidEmail } from "../validation";
1+
import { useEffect, useState } from 'react';
2+
import { Lock, MagicWand, WarningOctagon } from '@phosphor-icons/react';
3+
import { Button } from '@components/Button';
4+
import { TextInput } from '@components/TextInput';
5+
import { supabase } from '@backend/supabaseBrowserClient';
6+
import type { Translations } from 'src/Types';
7+
import { isValidEmail } from '../validation';
88

99
export interface StateSignInFormProps {
1010
i18n: Translations;
@@ -17,44 +17,44 @@ export interface StateSignInFormProps {
1717
export const StateLoginForm = (props: StateSignInFormProps) => {
1818
const { t } = props.i18n;
1919

20-
const [email, setEmail] = useState("");
20+
const [email, setEmail] = useState('');
2121

2222
const [loading, setLoading] = useState(false);
2323

24-
const [password, setPassword] = useState("");
24+
const [password, setPassword] = useState('');
2525

26-
const [error, setError] = useState("");
26+
const [error, setError] = useState('');
2727

2828
const onSignIn = (evt: React.MouseEvent) => {
2929
evt.preventDefault();
3030

3131
setLoading(true);
3232

3333
if (!isValidEmail(email)) {
34-
setError(t["Please enter a valid email address"]);
34+
setError(t['Please enter a valid email address']);
3535
} else {
36-
setError("");
36+
setError('');
3737

3838
supabase.auth
3939
.signInWithPassword({
4040
email,
4141
password,
4242
})
4343
.then(({ error }) => {
44-
if (error) setError(t["Invalid email or password"]);
44+
if (error) setError(t['Invalid email or password']);
4545
});
4646
}
4747
};
4848

4949
useEffect(() => {
50-
document.getElementById("email")?.focus();
50+
document.getElementById('email')?.focus();
5151
}, []);
5252

5353
return (
5454
<div className='login'>
5555
<main>
56-
<h1>{t["Welcome Back"]}</h1>
57-
<p>{t["Log into your account"]}</p>
56+
<h1>{t['Welcome Back']}</h1>
57+
<p>{t['Log into your account']}</p>
5858

5959
<div className='login-email'>
6060
<form>
@@ -63,7 +63,7 @@ export const StateLoginForm = (props: StateSignInFormProps) => {
6363
error={Boolean(error)}
6464
id='email'
6565
name='email'
66-
label={t["Email"]}
66+
label={t['Email']}
6767
className='lg w-full'
6868
onChange={setEmail}
6969
/>
@@ -72,7 +72,7 @@ export const StateLoginForm = (props: StateSignInFormProps) => {
7272
autoComplete={false}
7373
id='password'
7474
name='password'
75-
label={t["Password"]}
75+
label={t['Password']}
7676
type='password'
7777
className='lg w-full'
7878
onChange={setPassword}
@@ -84,7 +84,7 @@ export const StateLoginForm = (props: StateSignInFormProps) => {
8484
className='icon text-bottom'
8585
size={18}
8686
weight='fill'
87-
/>{" "}
87+
/>{' '}
8888
{error}
8989
</p>
9090
)}
@@ -94,21 +94,21 @@ export const StateLoginForm = (props: StateSignInFormProps) => {
9494
busy={loading}
9595
onClick={onSignIn}
9696
>
97-
<span>{t["Sign In"]}</span>
97+
<span>{t['Sign In']}</span>
9898
</Button>
9999
</form>
100100

101101
<div className='forgot-password'>
102102
<a href={`/${props.i18n.lang}/forgot-password`}>
103-
{t["Forgot password?"]}
103+
{t['Forgot password?']}
104104
</a>
105105
</div>
106106
</div>
107107
</main>
108108

109109
<footer>
110110
<p>
111-
{t["Don't have an account?"]} <a href='#'>{t["Sign up now."]}</a>
111+
{t["Don't have an account?"]} <a href='#'>{t['Sign up now.']}</a>
112112
</p>
113113
</footer>
114114
</div>

src/config.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"_comment": "This is a default configuration file that can be replaced a build time",
2+
"_comment": "This is a default configuration file that can be replaced at build time",
33
"branding": {
44
"platform_name": "Recogito",
55
"site_name": "Default",

src/layouts/BaseLayout.astro

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
2-
import { getLangFromUrl } from "@i18n";
2+
import { getLangFromUrl } from '@i18n';
33
4-
import "@themes/default/index.css";
4+
import '@themes/default/index.css';
55
66
export interface Props {
77
title: string;
@@ -21,18 +21,18 @@ const { title } = Astro.props;
2121
<body>
2222
<slot />
2323
<script>
24-
window.onUsersnapLoad = function (api) {
24+
window.onUsersnapLoad = function (api: any) {
2525
api.init();
2626
api.show(import.meta.env.PUBLIC_USERSNAP_PROJECT_API_KEY);
2727
};
2828

29-
var script = document.createElement("script");
29+
var script = document.createElement('script');
3030
script.defer = 1;
3131
script.src = `https://widget.usersnap.com/global/load/${
3232
import.meta.env.PUBLIC_USERSNAP_GLOBAL_API_KEY
3333
}?onload=onUsersnapLoad`;
3434

35-
document.getElementsByTagName("head")[0].appendChild(script);
35+
document.getElementsByTagName('head')[0].appendChild(script);
3636
</script>
3737
</body>
3838
</html>

src/layouts/login/LoginLayout.astro

+5-13
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,14 @@
11
---
2-
import BaseLayout from "../BaseLayout.astro";
3-
import type {
4-
ExtendedAssignmentData,
5-
ExtendedProjectData,
6-
MyProfile,
7-
LoginMethod,
8-
} from "../../Types";
9-
import config from "../../config.json";
10-
import { LoginMethodSelector } from "@apps/auth-login/LoginMethodSelector";
2+
import BaseLayout from '../BaseLayout.astro';
3+
import config from '../../config.json';
4+
import type { Translations } from 'src/Types';
115
126
export interface Props {
137
title: string;
14-
i18n: Node;
8+
i18n: Translations;
159
}
1610
17-
const { title, i18n } = Astro.props;
18-
19-
const cookie = Astro.cookies.get("x-project-sidebar-collapsed");
11+
const { title } = Astro.props;
2012
2113
const siteColor = config.branding.site_color;
2214
const siteBanner = config.branding.home_banner;

0 commit comments

Comments
 (0)