Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: group color judgement error #720

Merged
merged 9 commits into from
Jul 15, 2024
Merged
4 changes: 3 additions & 1 deletion apps/nestjs-backend/src/features/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ export class AuthController {
@Res({ passthrough: true }) res: Response,
@Req() req: Express.Request
) {
const user = pickUserMe(await this.authService.signup(body.email, body.password));
const user = pickUserMe(
await this.authService.signup(body.email, body.password, body.defaultSpaceName)
);
// set cookie, passport login
await new Promise<void>((resolve, reject) => {
req.login(user, (err) => (err ? reject(err) : resolve()));
Expand Down
22 changes: 13 additions & 9 deletions apps/nestjs-backend/src/features/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export class AuthService {
return (await this.comparePassword(pass, password, salt)) ? { ...result, password } : null;
}

async signup(email: string, password: string) {
async signup(email: string, password: string, defaultSpaceName?: string) {
const user = await this.userService.getUserByEmail(email);
if (user && (user.password !== null || user.accounts.length > 0)) {
throw new HttpException(`User ${email} is already registered`, HttpStatus.BAD_REQUEST);
Expand All @@ -83,14 +83,18 @@ export class AuthService {
},
});
}
return await this.userService.createUserWithSettingCheck({
id: generateUserId(),
name: email.split('@')[0],
email,
salt,
password: hashPassword,
lastSignTime: new Date().toISOString(),
});
return await this.userService.createUserWithSettingCheck(
{
id: generateUserId(),
name: email.split('@')[0],
email,
salt,
password: hashPassword,
lastSignTime: new Date().toISOString(),
},
undefined,
defaultSpaceName
);
});
}

Expand Down
10 changes: 6 additions & 4 deletions apps/nestjs-backend/src/features/user/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ export class UserService {

async createUserWithSettingCheck(
user: Omit<Prisma.UserCreateInput, 'name'> & { name?: string },
account?: Omit<Prisma.AccountUncheckedCreateInput, 'userId'>
account?: Omit<Prisma.AccountUncheckedCreateInput, 'userId'>,
defaultSpaceName?: string
) {
const setting = await this.prismaService.setting.findFirst({
select: {
Expand All @@ -95,12 +96,13 @@ export class UserService {
throw new BadRequestException('The current instance disallow sign up by the administrator');
}

return await this.createUser(user, account);
return await this.createUser(user, account, defaultSpaceName);
}

async createUser(
user: Omit<Prisma.UserCreateInput, 'name'> & { name?: string },
account?: Omit<Prisma.AccountUncheckedCreateInput, 'userId'>
account?: Omit<Prisma.AccountUncheckedCreateInput, 'userId'>,
defaultSpaceName?: string
) {
// defaults
const defaultNotifyMeta: IUserNotifyMeta = {
Expand Down Expand Up @@ -141,7 +143,7 @@ export class UserService {
}
await this.cls.runWith(this.cls.get(), async () => {
this.cls.set('user.id', id);
await this.createSpaceBySignup({ name: `${name}'s space` });
await this.createSpaceBySignup({ name: defaultSpaceName || `${name}'s space` });
});
this.eventEmitterService.emitAsync(Events.USER_SIGNUP, new UserSignUpEvent(id));
return newUser;
Expand Down
120 changes: 70 additions & 50 deletions apps/nextjs-app/src/features/app/blocks/import-table/TableImport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
importTableFromFile,
inplaceImportTableFromFile,
} from '@teable/openapi';
import { useBase } from '@teable/sdk';
import { useBase, LocalStorageKeys } from '@teable/sdk';
import {
Dialog,
DialogContent,
Expand All @@ -35,11 +35,14 @@ import {
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
Checkbox,
} from '@teable/ui-lib';
import { toast } from '@teable/ui-lib/shadcn/ui/sonner';
import { useRouter } from 'next/router';
import { useTranslation } from 'next-i18next';
import { useState, useRef, useCallback } from 'react';
import { useLocalStorage } from 'react-use';
import { FieldConfigPanel, InplaceFieldConfigPanel } from './field-config-panel';
import { UploadPanel } from './upload-panel';
import { UrlPanel } from './UrlPanel';
Expand Down Expand Up @@ -68,7 +71,6 @@ export const TableImport = (props: ITableImportProps) => {
const [step, setStep] = useState(Step.UPLOAD);
const { children, open, onOpenChange, fileType, tableId } = props;
const [errorMessage, setErrorMessage] = useState('');
const [alterDialogVisible, setAlterDialogVisible] = useState(false);
const [file, setFile] = useState<File | null>(null);
const [fileInfo, setFileInfo] = useState<IAnalyzeRo>({} as IAnalyzeRo);
const primitiveWorkSheets = useRef<IAnalyzeVo['worksheets']>({});
Expand All @@ -78,10 +80,8 @@ export const TableImport = (props: ITableImportProps) => {
sourceWorkSheetKey: '',
sourceColumnMap: {},
});

const closeDialog = () => {
dialogOpenProxy(false);
};
const [shouldAlert, setShouldAlert] = useLocalStorage(LocalStorageKeys.ImportAlert, true);
const [shouldTips, setShouldTips] = useState(false);

const { mutateAsync: importNewTableFn, isLoading } = useMutation({
mutationFn: async ({ baseId, importRo }: { baseId: string; importRo: IImportOptionRo }) => {
Expand Down Expand Up @@ -241,17 +241,6 @@ export const TableImport = (props: ITableImportProps) => {
[fileType, t]
);

const dialogOpenProxy = useCallback(
(open: boolean) => {
if (!open && Step.CONFIG && isLoading) {
setAlterDialogVisible(true);
return;
}
onOpenChange?.(open);
},
[isLoading, onOpenChange]
);

const fieldChangeHandler = (value: IImportOptionRo['worksheets']) => {
setWorkSheets(value);
};
Expand All @@ -262,7 +251,7 @@ export const TableImport = (props: ITableImportProps) => {

return (
<>
<Dialog open={open} onOpenChange={dialogOpenProxy}>
<Dialog open={open} onOpenChange={(open) => onOpenChange?.(open)}>
{children && <DialogTrigger>{children}</DialogTrigger>}
{open && (
<DialogContent
Expand Down Expand Up @@ -341,46 +330,77 @@ export const TableImport = (props: ITableImportProps) => {
{step === Step.CONFIG && (
<DialogFooter>
<footer className="mt-1 flex items-center justify-end">
<Button size="sm" variant="secondary" onClick={() => closeDialog()}>
<Button size="sm" variant="secondary" onClick={() => onOpenChange?.(false)}>
{t('table:import.menu.cancel')}
</Button>
<Button
size="sm"
className="ml-1"
onClick={() => importTable()}
disabled={tableId ? inplaceLoading : isLoading}
>
{(tableId ? inplaceLoading : isLoading) && <Spin className="mr-1 size-4" />}
{t('table:import.title.import')}
</Button>
{shouldAlert ? (
<AlertDialog>
<AlertDialogTrigger asChild>
<Button
size="sm"
className="ml-1"
disabled={tableId ? inplaceLoading : isLoading}
>
{(tableId ? inplaceLoading : isLoading) && (
<Spin className="mr-1 size-4" />
)}
{t('table:import.title.import')}
</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{t('table:import.title.tipsTitle')}</AlertDialogTitle>
<AlertDialogDescription>
{t('table:import.tips.importAlert')}
</AlertDialogDescription>
</AlertDialogHeader>
<div className="flex items-center">
<Checkbox
id="noTips"
checked={shouldTips}
onCheckedChange={(res: boolean) => {
setShouldTips(res);
}}
/>
<label
htmlFor="noTips"
className="pl-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
{t('table:import.tips.noTips')}
</label>
</div>
<AlertDialogFooter>
<AlertDialogCancel>{t('table:import.menu.cancel')}</AlertDialogCancel>
<AlertDialogAction
onClick={() => {
importTable();
if (shouldTips) {
setShouldAlert(false);
}
}}
>
{t('table:import.title.confirm')}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
) : (
<Button
size="sm"
className="ml-1"
onClick={() => importTable()}
disabled={tableId ? inplaceLoading : isLoading}
>
{(tableId ? inplaceLoading : isLoading) && <Spin className="mr-1 size-4" />}
{t('table:import.title.import')}
</Button>
)}
</footer>
</DialogFooter>
)}
</DialogContent>
)}
</Dialog>

<AlertDialog
open={alterDialogVisible}
onOpenChange={(open: boolean) => setAlterDialogVisible(open)}
>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{t('table:import.title.leaveTitle')}</AlertDialogTitle>
<AlertDialogDescription>{t('table:import.tips.leaveTip')}</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>{t('table:import.menu.cancel')}</AlertDialogCancel>
<AlertDialogAction
onClick={() => {
onOpenChange?.(false);
}}
>
{t('table:import.menu.leave')}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ interface IFieldSelector {
export function FieldSelector(props: IFieldSelector) {
const { options, onSelect, value, disabled = false } = props;
const [open, setOpen] = useState(false);
const { t } = useTranslation(['table']);
const { t } = useTranslation(['table', 'common']);

const comOptions = useMemo(() => {
const result = [...options];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,12 @@ const FieldConfigPanel = (props: IFieldConfigPanel) => {
key={sheetKey}
size="xs"
onClick={() => setSelectedSheetKey(sheetKey)}
className={cn('w-20 shrink-0 cursor-pointer truncate rounded-sm', {
className={cn('max-w-32 shrink-0 cursor-pointer truncate rounded-sm px-2', {
'bg-secondary': sheetKey === selectedSheetKey,
})}
title={workSheets[sheetKey].name}
>
{workSheets[sheetKey].name}
<span className="truncate">{workSheets[sheetKey].name}</span>
</Button>
))}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export const SpaceCard: FC<ISpaceCard> = (props) => {
onChange={(e) => setSpaceName(e.target.value)}
onBlur={(e) => toggleUpdateSpace(e)}
>
<CardTitle className="truncate" title={space.name}>
<CardTitle className="truncate leading-5" title={space.name}>
{space.name}
</CardTitle>
</SpaceRenaming>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { SpaceItem } from './SpaceItem';
export const SpaceList: FC = () => {
const router = useRouter();
const { disallowSpaceCreation } = useSetting();
const { t } = useTranslation('space');
const { t } = useTranslation('common');

const queryClient = useQueryClient();
const { data: spaceList } = useQuery({
Expand Down Expand Up @@ -46,7 +46,7 @@ export const SpaceList: FC = () => {
className="w-full"
onClick={() => {
const name = getUniqName(
t('defaultSpaceName'),
t('noun.space'),
spaceList?.data?.length ? spaceList?.data.map((space) => space?.name) : []
);
addSpace({ name });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
TooltipProvider,
TooltipTrigger,
} from '@teable/ui-lib';
import { useTranslation } from 'next-i18next';
import React from 'react';

interface ActionBarProps {
Expand All @@ -20,6 +21,7 @@ interface ActionBarProps {

export const NotificationActionBar: React.FC<ActionBarProps> = (props) => {
const { notifyStatus, children, onStatusCheck } = props;
const { t } = useTranslation('common');

return (
<HoverCard openDelay={100} closeDelay={0}>
Expand All @@ -45,8 +47,12 @@ export const NotificationActionBar: React.FC<ActionBarProps> = (props) => {
</Button>
</TooltipTrigger>
<TooltipContent side="top" align="center" sideOffset={10}>
Mark this notification as
{notifyStatus === NotificationStatesEnum.Unread ? ' read' : ' unread'}
{t('notification.markAs', {
status:
notifyStatus === NotificationStatesEnum.Unread
? t('notification.read')
: t('notification.unread'),
})}
</TooltipContent>
</Tooltip>
</TooltipProvider>
Expand All @@ -60,7 +66,7 @@ export const NotificationActionBar: React.FC<ActionBarProps> = (props) => {
</Button>
</TooltipTrigger>
<TooltipContent side="top" align="center" sideOffset={10}>
Change page notification settings
{t('notification.changeSetting')}
</TooltipContent>
</Tooltip>
</TooltipProvider>
Expand Down
Loading