fix: Login page language switcher (#30106)
Co-authored-by: Tasso Evangelista <2263066+tassoevan@users.noreply.github.com>pull/30212/head^2
parent
e7fbc00965
commit
b8f3d5014f
@ -0,0 +1,11 @@ |
||||
--- |
||||
"@rocket.chat/meteor": patch |
||||
"@rocket.chat/i18n": patch |
||||
"@rocket.chat/livechat": patch |
||||
"@rocket.chat/mock-providers": patch |
||||
"@rocket.chat/ui-client": patch |
||||
"@rocket.chat/ui-contexts": patch |
||||
"@rocket.chat/web-ui-registration": patch |
||||
--- |
||||
|
||||
Fixed the login page language switcher, now the component has a new look, is reactive and the language selection becomes concrete upon login in. Also changed the default language of the login page to be the browser language. |
||||
@ -0,0 +1,130 @@ |
||||
diff --git a/dist/generateDocgenCodeBlock.js b/dist/generateDocgenCodeBlock.js
|
||||
index 0993ac13e4b2aae6d24cf408d6a585b4ddeb7337..1405896291288eb1322d6c42144afd3b4fbd1abf 100644
|
||||
--- a/dist/generateDocgenCodeBlock.js
|
||||
+++ b/dist/generateDocgenCodeBlock.js
|
||||
@@ -34,7 +34,7 @@ function insertTsIgnoreBeforeStatement(statement) {
|
||||
* ```
|
||||
*/
|
||||
function setDisplayName(d) {
|
||||
- return insertTsIgnoreBeforeStatement(typescript_1.default.createExpressionStatement(typescript_1.default.createBinary(typescript_1.default.createPropertyAccess(typescript_1.default.createIdentifier(d.displayName), typescript_1.default.createIdentifier("displayName")), typescript_1.default.SyntaxKind.EqualsToken, typescript_1.default.createLiteral(d.displayName))));
|
||||
+ return insertTsIgnoreBeforeStatement(typescript_1.default.factory.createExpressionStatement(typescript_1.default.factory.createBinaryExpression(typescript_1.default.factory.createPropertyAccessExpression(typescript_1.default.factory.createIdentifier(d.displayName), typescript_1.default.factory.createIdentifier("displayName")), typescript_1.default.SyntaxKind.EqualsToken, typescript_1.default.factory.createStringLiteral(d.displayName))));
|
||||
}
|
||||
/**
|
||||
* Set a component prop description.
|
||||
@@ -65,7 +65,7 @@ function createPropDefinition(propName, prop, options) {
|
||||
*
|
||||
* @param defaultValue Default prop value or null if not set.
|
||||
*/
|
||||
- const setDefaultValue = (defaultValue) => typescript_1.default.createPropertyAssignment(typescript_1.default.createLiteral("defaultValue"),
|
||||
+ const setDefaultValue = (defaultValue) => typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createStringLiteral("defaultValue"),
|
||||
// Use a more extensive check on defaultValue. Sometimes the parser
|
||||
// returns an empty object.
|
||||
defaultValue !== null &&
|
||||
@@ -75,12 +75,19 @@ function createPropDefinition(propName, prop, options) {
|
||||
(typeof defaultValue.value === "string" ||
|
||||
typeof defaultValue.value === "number" ||
|
||||
typeof defaultValue.value === "boolean")
|
||||
- ? typescript_1.default.createObjectLiteral([
|
||||
- typescript_1.default.createPropertyAssignment(typescript_1.default.createIdentifier("value"), typescript_1.default.createLiteral(defaultValue.value)),
|
||||
+ ? typescript_1.default.factory.createObjectLiteralExpression([
|
||||
+ typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createIdentifier("value"), typeof defaultValue.value === "string"
|
||||
+ ? typescript_1.default.factory.createStringLiteral(defaultValue.value)
|
||||
+ : // eslint-disable-next-line no-nested-ternary
|
||||
+ typeof defaultValue.value === "number"
|
||||
+ ? typescript_1.default.factory.createNumericLiteral(defaultValue.value)
|
||||
+ : defaultValue.value
|
||||
+ ? typescript_1.default.factory.createTrue()
|
||||
+ : typescript_1.default.factory.createFalse()),
|
||||
])
|
||||
- : typescript_1.default.createNull());
|
||||
+ : typescript_1.default.factory.createNull());
|
||||
/** Set a property with a string value */
|
||||
- const setStringLiteralField = (fieldName, fieldValue) => typescript_1.default.createPropertyAssignment(typescript_1.default.createLiteral(fieldName), typescript_1.default.createLiteral(fieldValue));
|
||||
+ const setStringLiteralField = (fieldName, fieldValue) => typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createStringLiteral(fieldName), typescript_1.default.factory.createStringLiteral(fieldValue));
|
||||
/**
|
||||
* ```
|
||||
* SimpleComponent.__docgenInfo.props.someProp.description = "Prop description.";
|
||||
@@ -101,7 +108,7 @@ function createPropDefinition(propName, prop, options) {
|
||||
* ```
|
||||
* @param required Whether prop is required or not.
|
||||
*/
|
||||
- const setRequired = (required) => typescript_1.default.createPropertyAssignment(typescript_1.default.createLiteral("required"), required ? typescript_1.default.createTrue() : typescript_1.default.createFalse());
|
||||
+ const setRequired = (required) => typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createStringLiteral("required"), required ? typescript_1.default.factory.createTrue() : typescript_1.default.factory.createFalse());
|
||||
/**
|
||||
* ```
|
||||
* SimpleComponent.__docgenInfo.props.someProp.type = {
|
||||
@@ -113,7 +120,7 @@ function createPropDefinition(propName, prop, options) {
|
||||
*/
|
||||
const setValue = (typeValue) => Array.isArray(typeValue) &&
|
||||
typeValue.every((value) => typeof value.value === "string")
|
||||
- ? typescript_1.default.createPropertyAssignment(typescript_1.default.createLiteral("value"), typescript_1.default.createArrayLiteral(typeValue.map((value) => typescript_1.default.createObjectLiteral([
|
||||
+ ? typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createStringLiteral("value"), typescript_1.default.factory.createArrayLiteralExpression(typeValue.map((value) => typescript_1.default.factory.createObjectLiteralExpression([
|
||||
setStringLiteralField("value", value.value),
|
||||
]))))
|
||||
: undefined;
|
||||
@@ -130,9 +137,9 @@ function createPropDefinition(propName, prop, options) {
|
||||
if (valueField) {
|
||||
objectFields.push(valueField);
|
||||
}
|
||||
- return typescript_1.default.createPropertyAssignment(typescript_1.default.createLiteral(options.typePropName), typescript_1.default.createObjectLiteral(objectFields));
|
||||
+ return typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createStringLiteral(options.typePropName), typescript_1.default.factory.createObjectLiteralExpression(objectFields));
|
||||
};
|
||||
- return typescript_1.default.createPropertyAssignment(typescript_1.default.createLiteral(propName), typescript_1.default.createObjectLiteral([
|
||||
+ return typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createStringLiteral(propName), typescript_1.default.factory.createObjectLiteralExpression([
|
||||
setDefaultValue(prop.defaultValue),
|
||||
setDescription(prop.description),
|
||||
setName(prop.name),
|
||||
@@ -158,10 +165,10 @@ function createPropDefinition(propName, prop, options) {
|
||||
* @param relativeFilename Relative file path of the component source file.
|
||||
*/
|
||||
function insertDocgenIntoGlobalCollection(d, docgenCollectionName, relativeFilename) {
|
||||
- return insertTsIgnoreBeforeStatement(typescript_1.default.createIf(typescript_1.default.createBinary(typescript_1.default.createTypeOf(typescript_1.default.createIdentifier(docgenCollectionName)), typescript_1.default.SyntaxKind.ExclamationEqualsEqualsToken, typescript_1.default.createLiteral("undefined")), insertTsIgnoreBeforeStatement(typescript_1.default.createStatement(typescript_1.default.createBinary(typescript_1.default.createElementAccess(typescript_1.default.createIdentifier(docgenCollectionName), typescript_1.default.createLiteral(`${relativeFilename}#${d.displayName}`)), typescript_1.default.SyntaxKind.EqualsToken, typescript_1.default.createObjectLiteral([
|
||||
- typescript_1.default.createPropertyAssignment(typescript_1.default.createIdentifier("docgenInfo"), typescript_1.default.createPropertyAccess(typescript_1.default.createIdentifier(d.displayName), typescript_1.default.createIdentifier("__docgenInfo"))),
|
||||
- typescript_1.default.createPropertyAssignment(typescript_1.default.createIdentifier("name"), typescript_1.default.createLiteral(d.displayName)),
|
||||
- typescript_1.default.createPropertyAssignment(typescript_1.default.createIdentifier("path"), typescript_1.default.createLiteral(`${relativeFilename}#${d.displayName}`)),
|
||||
+ return insertTsIgnoreBeforeStatement(typescript_1.default.factory.createIfStatement(typescript_1.default.factory.createBinaryExpression(typescript_1.default.factory.createTypeOfExpression(typescript_1.default.factory.createIdentifier(docgenCollectionName)), typescript_1.default.SyntaxKind.ExclamationEqualsEqualsToken, typescript_1.default.factory.createStringLiteral("undefined")), insertTsIgnoreBeforeStatement(typescript_1.default.factory.createExpressionStatement(typescript_1.default.factory.createBinaryExpression(typescript_1.default.factory.createElementAccessExpression(typescript_1.default.factory.createIdentifier(docgenCollectionName), typescript_1.default.factory.createStringLiteral(`${relativeFilename}#${d.displayName}`)), typescript_1.default.SyntaxKind.EqualsToken, typescript_1.default.factory.createObjectLiteralExpression([
|
||||
+ typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createIdentifier("docgenInfo"), typescript_1.default.factory.createPropertyAccessExpression(typescript_1.default.factory.createIdentifier(d.displayName), typescript_1.default.factory.createIdentifier("__docgenInfo"))),
|
||||
+ typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createIdentifier("name"), typescript_1.default.factory.createStringLiteral(d.displayName)),
|
||||
+ typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createIdentifier("path"), typescript_1.default.factory.createStringLiteral(`${relativeFilename}#${d.displayName}`)),
|
||||
]))))));
|
||||
}
|
||||
/**
|
||||
@@ -180,15 +187,15 @@ function insertDocgenIntoGlobalCollection(d, docgenCollectionName, relativeFilen
|
||||
* @param options Generator options.
|
||||
*/
|
||||
function setComponentDocGen(d, options) {
|
||||
- return insertTsIgnoreBeforeStatement(typescript_1.default.createStatement(typescript_1.default.createBinary(
|
||||
+ return insertTsIgnoreBeforeStatement(typescript_1.default.factory.createExpressionStatement(typescript_1.default.factory.createBinaryExpression(
|
||||
// SimpleComponent.__docgenInfo
|
||||
- typescript_1.default.createPropertyAccess(typescript_1.default.createIdentifier(d.displayName), typescript_1.default.createIdentifier("__docgenInfo")), typescript_1.default.SyntaxKind.EqualsToken, typescript_1.default.createObjectLiteral([
|
||||
+ typescript_1.default.factory.createPropertyAccessExpression(typescript_1.default.factory.createIdentifier(d.displayName), typescript_1.default.factory.createIdentifier("__docgenInfo")), typescript_1.default.SyntaxKind.EqualsToken, typescript_1.default.factory.createObjectLiteralExpression([
|
||||
// SimpleComponent.__docgenInfo.description
|
||||
- typescript_1.default.createPropertyAssignment(typescript_1.default.createLiteral("description"), typescript_1.default.createLiteral(d.description)),
|
||||
+ typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createStringLiteral("description"), typescript_1.default.factory.createStringLiteral(d.description)),
|
||||
// SimpleComponent.__docgenInfo.displayName
|
||||
- typescript_1.default.createPropertyAssignment(typescript_1.default.createLiteral("displayName"), typescript_1.default.createLiteral(d.displayName)),
|
||||
+ typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createStringLiteral("displayName"), typescript_1.default.factory.createStringLiteral(d.displayName)),
|
||||
// SimpleComponent.__docgenInfo.props
|
||||
- typescript_1.default.createPropertyAssignment(typescript_1.default.createLiteral("props"), typescript_1.default.createObjectLiteral(Object.entries(d.props).map(([propName, prop]) => createPropDefinition(propName, prop, options)))),
|
||||
+ typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createStringLiteral("props"), typescript_1.default.factory.createObjectLiteralExpression(Object.entries(d.props).map(([propName, prop]) => createPropDefinition(propName, prop, options)))),
|
||||
]))));
|
||||
}
|
||||
function generateDocgenCodeBlock(options) {
|
||||
@@ -196,7 +203,7 @@ function generateDocgenCodeBlock(options) {
|
||||
const relativeFilename = path_1.default
|
||||
.relative("./", path_1.default.resolve("./", options.filename))
|
||||
.replace(/\\/g, "/");
|
||||
- const wrapInTryStatement = (statements) => typescript_1.default.createTry(typescript_1.default.createBlock(statements, true), typescript_1.default.createCatchClause(typescript_1.default.createVariableDeclaration(typescript_1.default.createIdentifier("__react_docgen_typescript_loader_error")), typescript_1.default.createBlock([])), undefined);
|
||||
+ const wrapInTryStatement = (statements) => typescript_1.default.factory.createTryStatement(typescript_1.default.factory.createBlock(statements, true), typescript_1.default.factory.createCatchClause(typescript_1.default.factory.createVariableDeclaration(typescript_1.default.factory.createIdentifier("__react_docgen_typescript_loader_error")), typescript_1.default.factory.createBlock([])), undefined);
|
||||
const codeBlocks = options.componentDocs.map((d) => wrapInTryStatement([
|
||||
options.setDisplayName ? setDisplayName(d) : null,
|
||||
setComponentDocGen(d, options),
|
||||
@@ -208,7 +215,7 @@ function generateDocgenCodeBlock(options) {
|
||||
const printer = typescript_1.default.createPrinter({ newLine: typescript_1.default.NewLineKind.LineFeed });
|
||||
const printNode = (sourceNode) => printer.printNode(typescript_1.default.EmitHint.Unspecified, sourceNode, sourceFile);
|
||||
// Concat original source code with code from generated code blocks.
|
||||
- const result = codeBlocks.reduce((acc, node) => `${acc}\n${printNode(node)}`,
|
||||
+ const result = codeBlocks.reduce((acc, node) => `${acc}\n${printNode(node)}`,
|
||||
// Use original source text rather than using printNode on the parsed form
|
||||
// to prevent issue where literals are stripped within components.
|
||||
// Ref: https://github.com/strothj/react-docgen-typescript-loader/issues/7
|
||||
@ -1,355 +0,0 @@ |
||||
import type { Serialized } from '@rocket.chat/core-typings'; |
||||
import type { Method, OperationParams, OperationResult, PathPattern, UrlParams } from '@rocket.chat/rest-typings'; |
||||
import type { ServerMethodName, ServerMethodParameters, ServerMethodReturn, TranslationKey } from '@rocket.chat/ui-contexts'; |
||||
import { |
||||
AuthorizationContext, |
||||
ConnectionStatusContext, |
||||
RouterContext, |
||||
ServerContext, |
||||
SettingsContext, |
||||
TranslationContext, |
||||
UserContext, |
||||
ActionManagerContext, |
||||
ModalContext, |
||||
} from '@rocket.chat/ui-contexts'; |
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; |
||||
import type { WrapperComponent } from '@testing-library/react-hooks'; |
||||
import type { ObjectId } from 'mongodb'; |
||||
import type { ContextType, ReactNode } from 'react'; |
||||
import React from 'react'; |
||||
|
||||
class MockedAppRootBuilder { |
||||
private wrappers: Array<(children: ReactNode) => ReactNode> = []; |
||||
|
||||
private connectionStatus: ContextType<typeof ConnectionStatusContext> = { |
||||
connected: true, |
||||
status: 'connected', |
||||
retryTime: undefined, |
||||
reconnect: () => undefined, |
||||
}; |
||||
|
||||
private server: ContextType<typeof ServerContext> = { |
||||
absoluteUrl: (path: string) => `http://localhost:3000/${path}`, |
||||
callEndpoint: <TMethod extends Method, TPathPattern extends PathPattern>(_args: { |
||||
method: TMethod; |
||||
pathPattern: TPathPattern; |
||||
keys: UrlParams<TPathPattern>; |
||||
params: OperationParams<TMethod, TPathPattern>; |
||||
}): Promise<Serialized<OperationResult<TMethod, TPathPattern>>> => { |
||||
throw new Error('not implemented'); |
||||
}, |
||||
getSingleStream: () => () => () => undefined, |
||||
getStream: () => () => () => undefined, |
||||
uploadToEndpoint: () => Promise.reject(new Error('not implemented')), |
||||
callMethod: () => Promise.reject(new Error('not implemented')), |
||||
info: undefined, |
||||
}; |
||||
|
||||
private router: ContextType<typeof RouterContext> = { |
||||
buildRoutePath: () => '/', |
||||
defineRoutes: () => () => undefined, |
||||
getLocationPathname: () => '/', |
||||
getLocationSearch: () => '', |
||||
getRouteName: () => undefined, |
||||
getRouteParameters: () => ({}), |
||||
getRoutes: () => [], |
||||
getSearchParameters: () => ({}), |
||||
navigate: () => undefined, |
||||
subscribeToRouteChange: () => () => undefined, |
||||
subscribeToRoutesChange: () => () => undefined, |
||||
}; |
||||
|
||||
private settings: ContextType<typeof SettingsContext> = { |
||||
hasPrivateAccess: true, |
||||
isLoading: false, |
||||
querySetting: (_id: string) => [() => () => undefined, () => undefined], |
||||
querySettings: () => [() => () => undefined, () => []], |
||||
dispatch: async () => undefined, |
||||
}; |
||||
|
||||
private translation: ContextType<typeof TranslationContext> = { |
||||
language: 'en', |
||||
languages: [ |
||||
{ |
||||
en: 'English', |
||||
key: 'en', |
||||
name: 'English', |
||||
}, |
||||
], |
||||
loadLanguage: () => Promise.resolve(), |
||||
translate: Object.assign((key: string) => key, { |
||||
has: (_key: string): _key is TranslationKey => true, |
||||
}), |
||||
}; |
||||
|
||||
private user: ContextType<typeof UserContext> = { |
||||
loginWithPassword: () => Promise.reject(new Error('not implemented')), |
||||
logout: () => Promise.reject(new Error('not implemented')), |
||||
loginWithService: () => () => Promise.reject(new Error('not implemented')), |
||||
loginWithToken: () => Promise.reject(new Error('not implemented')), |
||||
queryAllServices: () => [() => () => undefined, () => []], |
||||
queryPreference: () => [() => () => undefined, () => undefined], |
||||
queryRoom: () => [() => () => undefined, () => undefined], |
||||
querySubscription: () => [() => () => undefined, () => undefined], |
||||
querySubscriptions: () => [() => () => undefined, () => []], |
||||
user: null, |
||||
userId: null, |
||||
}; |
||||
|
||||
private modal: ContextType<typeof ModalContext> = { |
||||
currentModal: null, |
||||
modal: { |
||||
setModal: () => undefined, |
||||
}, |
||||
}; |
||||
|
||||
private authorization: ContextType<typeof AuthorizationContext> = { |
||||
queryPermission: () => [() => () => undefined, () => false], |
||||
queryAtLeastOnePermission: () => [() => () => undefined, () => false], |
||||
queryAllPermissions: () => [() => () => undefined, () => false], |
||||
queryRole: () => [() => () => undefined, () => false], |
||||
roleStore: { |
||||
roles: {}, |
||||
emit: () => undefined, |
||||
on: () => () => undefined, |
||||
off: () => undefined, |
||||
events: (): Array<'change'> => ['change'], |
||||
has: () => false, |
||||
once: () => () => undefined, |
||||
}, |
||||
}; |
||||
|
||||
wrap(wrapper: (children: ReactNode) => ReactNode): this { |
||||
this.wrappers.push(wrapper); |
||||
return this; |
||||
} |
||||
|
||||
withEndpoint<TMethod extends Method, TPathPattern extends PathPattern>( |
||||
method: TMethod, |
||||
pathPattern: TPathPattern, |
||||
response: ( |
||||
params: OperationParams<TMethod, TPathPattern>, |
||||
) => Serialized<OperationResult<TMethod, TPathPattern>> | Promise<Serialized<OperationResult<TMethod, TPathPattern>>>, |
||||
): this { |
||||
const innerFn = this.server.callEndpoint; |
||||
|
||||
const outerFn = <TMethod extends Method, TPathPattern extends PathPattern>(args: { |
||||
method: TMethod; |
||||
pathPattern: TPathPattern; |
||||
keys: UrlParams<TPathPattern>; |
||||
params: OperationParams<TMethod, TPathPattern>; |
||||
}): Promise<Serialized<OperationResult<TMethod, TPathPattern>>> => { |
||||
if (args.method === String(method) && args.pathPattern === String(pathPattern)) { |
||||
return Promise.resolve(response(args.params)) as Promise<Serialized<OperationResult<TMethod, TPathPattern>>>; |
||||
} |
||||
|
||||
return innerFn(args); |
||||
}; |
||||
|
||||
this.server.callEndpoint = outerFn; |
||||
|
||||
return this; |
||||
} |
||||
|
||||
withMethod<TMethodName extends ServerMethodName>(methodName: TMethodName, response: () => ServerMethodReturn<TMethodName>): this { |
||||
const innerFn = this.server.callMethod; |
||||
|
||||
const outerFn = <TMethodName extends ServerMethodName>( |
||||
innerMethodName: TMethodName, |
||||
...innerArgs: ServerMethodParameters<TMethodName> |
||||
): Promise<ServerMethodReturn<TMethodName>> => { |
||||
if (innerMethodName === String(methodName)) { |
||||
return Promise.resolve(response()) as Promise<ServerMethodReturn<TMethodName>>; |
||||
} |
||||
|
||||
if (!innerFn) { |
||||
throw new Error('not implemented'); |
||||
} |
||||
|
||||
return innerFn(innerMethodName, ...innerArgs); |
||||
}; |
||||
|
||||
this.server.callMethod = outerFn; |
||||
|
||||
return this; |
||||
} |
||||
|
||||
withPermission(permission: string): this { |
||||
const innerFn = this.authorization.queryPermission; |
||||
|
||||
const outerFn = ( |
||||
innerPermission: string | ObjectId, |
||||
innerScope?: string | ObjectId | undefined, |
||||
innerScopedRoles?: string[] | undefined, |
||||
): [subscribe: (onStoreChange: () => void) => () => void, getSnapshot: () => boolean] => { |
||||
if (innerPermission === permission) { |
||||
return [() => () => undefined, () => true]; |
||||
} |
||||
|
||||
return innerFn(innerPermission, innerScope, innerScopedRoles); |
||||
}; |
||||
|
||||
this.authorization.queryPermission = outerFn; |
||||
|
||||
const innerFn2 = this.authorization.queryAtLeastOnePermission; |
||||
|
||||
const outerFn2 = ( |
||||
innerPermissions: Array<string | ObjectId>, |
||||
innerScope?: string | ObjectId | undefined, |
||||
innerScopedRoles?: string[] | undefined, |
||||
): [subscribe: (onStoreChange: () => void) => () => void, getSnapshot: () => boolean] => { |
||||
if (innerPermissions.includes(permission)) { |
||||
return [() => () => undefined, () => true]; |
||||
} |
||||
|
||||
return innerFn2(innerPermissions, innerScope, innerScopedRoles); |
||||
}; |
||||
|
||||
this.authorization.queryAtLeastOnePermission = outerFn2; |
||||
|
||||
const innerFn3 = this.authorization.queryAllPermissions; |
||||
|
||||
const outerFn3 = ( |
||||
innerPermissions: Array<string | ObjectId>, |
||||
innerScope?: string | ObjectId | undefined, |
||||
innerScopedRoles?: string[] | undefined, |
||||
): [subscribe: (onStoreChange: () => void) => () => void, getSnapshot: () => boolean] => { |
||||
if (innerPermissions.includes(permission)) { |
||||
return [() => () => undefined, () => true]; |
||||
} |
||||
|
||||
return innerFn3(innerPermissions, innerScope, innerScopedRoles); |
||||
}; |
||||
|
||||
this.authorization.queryAllPermissions = outerFn3; |
||||
|
||||
return this; |
||||
} |
||||
|
||||
withJohnDoe(): this { |
||||
this.user.userId = 'john.doe'; |
||||
|
||||
this.user.user = { |
||||
_id: 'john.doe', |
||||
username: 'john.doe', |
||||
name: 'John Doe', |
||||
createdAt: new Date(), |
||||
active: true, |
||||
_updatedAt: new Date(), |
||||
roles: ['admin'], |
||||
type: 'user', |
||||
}; |
||||
|
||||
return this; |
||||
} |
||||
|
||||
withAnonymous(): this { |
||||
this.user.userId = null; |
||||
this.user.user = null; |
||||
|
||||
return this; |
||||
} |
||||
|
||||
withRole(role: string): this { |
||||
if (!this.user.user) { |
||||
throw new Error('user is not defined'); |
||||
} |
||||
|
||||
this.user.user.roles.push(role); |
||||
|
||||
const innerFn = this.authorization.queryRole; |
||||
|
||||
const outerFn = ( |
||||
innerRole: string | ObjectId, |
||||
innerScope?: string | undefined, |
||||
innerIgnoreSubscriptions?: boolean | undefined, |
||||
): [subscribe: (onStoreChange: () => void) => () => void, getSnapshot: () => boolean] => { |
||||
if (innerRole === role) { |
||||
return [() => () => undefined, () => true]; |
||||
} |
||||
|
||||
return innerFn(innerRole, innerScope, innerIgnoreSubscriptions); |
||||
}; |
||||
|
||||
this.authorization.queryRole = outerFn; |
||||
|
||||
return this; |
||||
} |
||||
|
||||
build(): WrapperComponent<{ children: ReactNode }> { |
||||
const queryClient = new QueryClient({ |
||||
defaultOptions: { |
||||
queries: { retry: false }, |
||||
mutations: { retry: false }, |
||||
}, |
||||
}); |
||||
|
||||
const { connectionStatus, server, router, settings, translation, user, modal, authorization, wrappers } = this; |
||||
|
||||
return function MockedAppRoot({ children }) { |
||||
return ( |
||||
<QueryClientProvider client={queryClient}> |
||||
<ConnectionStatusContext.Provider value={connectionStatus}> |
||||
<ServerContext.Provider value={server}> |
||||
<RouterContext.Provider value={router}> |
||||
<SettingsContext.Provider value={settings}> |
||||
<TranslationContext.Provider value={translation}> |
||||
{/* <SessionProvider> |
||||
<TooltipProvider> |
||||
<ToastMessagesProvider> |
||||
<LayoutProvider> |
||||
<AvatarUrlProvider> |
||||
<CustomSoundProvider> */} |
||||
<UserContext.Provider value={user}> |
||||
{/* <DeviceProvider>*/} |
||||
<ModalContext.Provider value={modal}> |
||||
<AuthorizationContext.Provider value={authorization}> |
||||
{/* <EmojiPickerProvider> |
||||
<OmnichannelRoomIconProvider> |
||||
<UserPresenceProvider>*/} |
||||
<ActionManagerContext.Provider |
||||
value={{ |
||||
triggerAction: () => Promise.reject(new Error('not implemented')), |
||||
generateTriggerId: () => '', |
||||
getUserInteractionPayloadByViewId: () => undefined, |
||||
handlePayloadUserInteraction: () => undefined, |
||||
off: () => undefined, |
||||
on: () => undefined, |
||||
triggerActionButtonAction: () => Promise.reject(new Error('not implemented')), |
||||
triggerBlockAction: () => Promise.reject(new Error('not implemented')), |
||||
triggerCancel: () => Promise.reject(new Error('not implemented')), |
||||
triggerSubmitView: () => Promise.reject(new Error('not implemented')), |
||||
}} |
||||
> |
||||
{/* <VideoConfProvider> |
||||
<CallProvider> |
||||
<OmnichannelProvider> */} |
||||
{wrappers.reduce((children, wrapper) => wrapper(children), children)} |
||||
{/* </OmnichannelProvider> |
||||
</CallProvider> |
||||
</VideoConfProvider>*/} |
||||
</ActionManagerContext.Provider> |
||||
{/* </UserPresenceProvider> |
||||
</OmnichannelRoomIconProvider> |
||||
</EmojiPickerProvider>*/} |
||||
</AuthorizationContext.Provider> |
||||
</ModalContext.Provider> |
||||
{/* </DeviceProvider>*/} |
||||
</UserContext.Provider> |
||||
{/* </CustomSoundProvider> |
||||
</AvatarUrlProvider> |
||||
</LayoutProvider> |
||||
</ToastMessagesProvider> |
||||
</TooltipProvider> |
||||
</SessionProvider> */} |
||||
</TranslationContext.Provider> |
||||
</SettingsContext.Provider> |
||||
</RouterContext.Provider> |
||||
</ServerContext.Provider> |
||||
</ConnectionStatusContext.Provider> |
||||
</QueryClientProvider> |
||||
); |
||||
}; |
||||
} |
||||
} |
||||
export const mockAppRoot = () => new MockedAppRootBuilder(); |
||||
@ -1,3 +1,3 @@ |
||||
module.exports = { |
||||
presets: ['@babel/preset-modules'], |
||||
presets: [['@babel/preset-env', { bugfixes: true }]], |
||||
}; |
||||
|
||||
@ -1,9 +0,0 @@ |
||||
{ |
||||
"extends": "../../tsconfig.base.client.json", |
||||
"compilerOptions": { |
||||
"rootDir": "./src", |
||||
"outDir": "./dist" |
||||
}, |
||||
"include": ["./src/**/*"], |
||||
"exclude": ["./dist/**/*"] |
||||
} |
||||
@ -0,0 +1,7 @@ |
||||
{ |
||||
"presets": [ |
||||
"@babel/preset-env", |
||||
"@babel/preset-react", |
||||
"@babel/preset-typescript" |
||||
] |
||||
} |
||||
|
After Width: | Height: | Size: 7.1 KiB |
@ -0,0 +1,3 @@ |
||||
declare const path: string; |
||||
|
||||
export = path; |
||||
@ -0,0 +1,12 @@ |
||||
import { type StorybookConfig } from '@storybook/core-common'; |
||||
|
||||
const config: StorybookConfig = { |
||||
stories: ['../src/**/*.stories.@(js|jsx|ts|tsx)'], |
||||
addons: ['@storybook/addon-essentials', 'storybook-dark-mode'], |
||||
features: { |
||||
postcss: false, |
||||
}, |
||||
framework: '@storybook/react', |
||||
}; |
||||
|
||||
module.exports = config; |
||||
@ -0,0 +1,36 @@ |
||||
import { themes } from '@storybook/theming'; |
||||
import { type Parameters } from '@storybook/addons'; |
||||
import manifest from '../package.json'; |
||||
import logo from './logo.svg'; |
||||
import '@rocket.chat/fuselage/dist/fuselage.css'; |
||||
import '@rocket.chat/icons/dist/rocketchat.css'; |
||||
|
||||
export const parameters: Parameters = { |
||||
actions: { argTypesRegex: "^on[A-Z].*" }, |
||||
backgrounds: { |
||||
grid: { |
||||
cellSize: 4, |
||||
cellAmount: 4, |
||||
opacity: 0.5, |
||||
}, |
||||
}, |
||||
options: { |
||||
storySort: ([, a], [, b]) => a.kind.localeCompare(b.kind), |
||||
}, |
||||
layout: 'fullscreen', |
||||
darkMode: { |
||||
dark: { |
||||
...themes.dark, |
||||
brandTitle: manifest.name, |
||||
brandImage: logo, |
||||
brandUrl: manifest.homepage, |
||||
}, |
||||
light: { |
||||
...themes.normal, |
||||
brandTitle: manifest.name, |
||||
brandImage: logo, |
||||
brandUrl: manifest.homepage, |
||||
}, |
||||
}, |
||||
}; |
||||
|
||||
@ -1,8 +1,12 @@ |
||||
import { mockAppRoot } from '@rocket.chat/mock-providers'; |
||||
import { type ComponentMeta } from '@storybook/react'; |
||||
|
||||
import ResetPasswordPage from './ResetPasswordPage'; |
||||
|
||||
export default { |
||||
title: 'Login/ResetPassword', |
||||
component: ResetPasswordPage, |
||||
}; |
||||
decorators: [mockAppRoot().buildStoryDecorator()], |
||||
} satisfies ComponentMeta<typeof ResetPasswordPage>; |
||||
|
||||
export const Basic = () => <ResetPasswordPage />; |
||||
|
||||
@ -0,0 +1,42 @@ |
||||
import { Box, Tile } from '@rocket.chat/fuselage'; |
||||
import { mockAppRoot } from '@rocket.chat/mock-providers'; |
||||
import { type ComponentStory, type ComponentMeta } from '@storybook/react'; |
||||
import { createElement } from 'react'; |
||||
import { useTranslation } from 'react-i18next'; |
||||
|
||||
import LoginSwitchLanguageFooter from './LoginSwitchLanguageFooter'; |
||||
|
||||
export default { |
||||
title: 'components/LoginSwitchLanguageFooter', |
||||
component: LoginSwitchLanguageFooter, |
||||
decorators: [ |
||||
(fn) => |
||||
createElement(function ExampleTranslationDecorator() { |
||||
const { t } = useTranslation(); |
||||
|
||||
return ( |
||||
<Box> |
||||
<Tile>{t('example.text')}</Tile> |
||||
{fn()} |
||||
</Box> |
||||
); |
||||
}), |
||||
mockAppRoot() |
||||
.withSetting('Language', 'fi') |
||||
.withTranslations('en', 'registration', { 'component.switchLanguage': 'Change to <1>{{ name }}</1>' }) |
||||
.withTranslations('en', 'example', { text: 'Hello!' }) |
||||
.withTranslations('fi', 'registration', { 'component.switchLanguage': 'Vaihda kieleksi <1>{{ name }}</1>' }) |
||||
.withTranslations('fi', 'example', { text: 'Hei!' }) |
||||
.withTranslations('pt-BR', 'registration', { 'component.switchLanguage': 'Mudar para <1>{{ name }}</1>' }) |
||||
.withTranslations('pt', 'example', { text: 'Olá!' }) |
||||
.buildStoryDecorator(), |
||||
], |
||||
args: { |
||||
browserLanguage: 'pt-BR', |
||||
}, |
||||
parameters: { |
||||
layout: 'centered', |
||||
}, |
||||
} satisfies ComponentMeta<typeof LoginSwitchLanguageFooter>; |
||||
|
||||
export const Default: ComponentStory<typeof LoginSwitchLanguageFooter> = (args) => <LoginSwitchLanguageFooter {...args} />; |
||||
@ -0,0 +1,8 @@ |
||||
{ |
||||
"extends": "./tsconfig.json", |
||||
"compilerOptions": { |
||||
"module": "ESNext" |
||||
}, |
||||
"include": ["./src/**/*"], |
||||
"exclude": ["./src/**/*.spec.ts", "./src/**/*.stories.tsx"] |
||||
} |
||||
@ -1,8 +1,9 @@ |
||||
{ |
||||
"extends": "../../tsconfig.base.client.json", |
||||
"compilerOptions": { |
||||
"rootDir": "./src", |
||||
"outDir": "./dist" |
||||
"rootDirs": ["./src","./.storybook"], |
||||
"outDir": "./dist", |
||||
"module": "CommonJS" |
||||
}, |
||||
"include": ["./src/**/*"] |
||||
"include": ["./src", "./.storybook"], |
||||
} |
||||
|
||||
Loading…
Reference in new issue