Skip to content

Commit

Permalink
fix: group color judgement error (#720)
Browse files Browse the repository at this point in the history
* fix: group color judgement error

* feat: notification i18n

* feat: signup default spacesname support i18n

* fix: space name cutting

* feat: `sort`、`group` FieldSelect alignment

* feat: signup api compatible api calling default space name

* chore: notification i18n name space to common from system

* feat: add import tips

* chore: reduce import tips complex judgement
  • Loading branch information
caoxing9 authored Jul 15, 2024
1 parent 5ce5a92 commit f4efd54
Show file tree
Hide file tree
Showing 22 changed files with 162 additions and 91 deletions.
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>
<AlertDialog>
{shouldAlert ? (
<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>
) : (
<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>
)}
<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>
</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

0 comments on commit f4efd54

Please sign in to comment.