From bc27d7fbec366d2d359c92efd472b6bf1cdee1d6 Mon Sep 17 00:00:00 2001 From: Vinh Date: Tue, 3 Dec 2019 01:07:50 +0700 Subject: [PATCH] [CORL-729] Upgrade Final Form & improve tests (#2735) * CORL-729 Upgrade final form, fix and improve tests This is a squashed rebase from these commits: a300b31c23ab11e5e6f0668bc03ece7697360aaa feat: error on optimisic response warnings during test dd8a9776865ec41d346e23ae0743d0d4fb0caa21 fix: turn off @typescript-eslint/prefer-regexp-exec rule b995daacf1722cace60d755e672cb6a3a20d6bc2 feat: mute false warnings in test e44f9e28307cd63a82c1fb7ac013667dd7b7bc46 fix: wrap remaining tests with act afbd4329b97f3dbc9f873ea4ff234d98bb651ccf feat: fail when act(async () => ...) without await warnings 51dfb60b7d75411ba2e1a28db33f4aba5cf84de1 feat: fail tests with act warnings 97f93546ed8113e207882411eb4cdb7675b0796c fix: mock window.resizeTo globally in tests 850958b8c4d2fc0aca67ae580296433af223f8ab fix: more tests with act 24c05ab88e9a416e4962acc3f20f2c764ba07657 fix: wrap charCountEditComment test in acts ed590b82d147470bba74055dc682e6b70d2e76fb fix signInWithEmail 4a2b9402cb6ce9565d99ae1a950eaa422ff603c3 fix: PostCommentFormContainer 815ebe6ef364d954d4bd0a35495934c9d014170b fix: use final form initialize instead of reset and remove obsolete d3101f2112ed3ffe8d06609620e31e6655d2cf6d Merge branch 'feature/CORL-729-final-form' of https://github.com/coralproject/talk into feature/CORL-729-final-form a0658da610a5f39b6fae78ffb8dd291b22d54e50 fix: addEmailAddress 60f7fc99a44dfa49dfd401a0ef49c60973b3e8e3 fix: use proper act pattern in renderConfigure.spec.tsx d66bdfc2245c2b1ee03a1b3a3a56f1d5ba14ddc4 Stop propagation of Modal content click events (#2706) ec6689594136e22a5b9f05ea284162702dc4955d fix: use proper act pattern in createUsername.spec.tsx ef239496964a5f9a91ee1c4424ad81537c4f47fe fix: stream configuration c7e06a0c6aef6b299c41392af81f8a20855028bf fix: user proper act pattern in streamConfiguration 9712e659e394a898500ed649464ff14d4870e589 Merge branch 'feature/CORL-729-final-form' of https://github.com/coralproject/talk into feature/CORL-729-final-form 9e5cfbaf3593615b457055de23f187fa07edd4c4 fix: signIn test 99b44a4a1bbb7ff2cd44c6821ad33b80f90c4a99 fix: user proper act pattern in stories.spec.tsx ed7c1a92f93ab9aaa85ff92837b0ed21560cb358 fix: user proper act pattern in addEmailAddress a04b392cb2148b9a24791b062027796c409d053e fix: remove obsolete snapshots 59df67c0f9b9d26c74e2cca7d333f5868b0b202d fix: signUp test 7656f179df95b4cd96b37afbc88a1c3a2944fdf4 fix: use proper act pattern on createPassword 85246fbf1f9ab49ad3a09c11ab79bf537059b548 fix: use correct act() pattern in createUsername.spec.tsx d5239373a2d1bbed0bfe8c1ca62ef6a70ef5c7d9 fix: the correct way to use act on form submit :-) d84ecd168354f4acb422a5ddb725fb8faf9c3184 fix: moderation test d8df62ab1a6486144684ff917c47e6e375ffbe03 fix: reportComment test 2756e3184bb292168e8d34e201f340c3799941e6 fix: auth tests a28695dbdd313a7bc3dade9ac1f92d6ef0061526 Properly handle final-form actions in tests 2fafc8ea3458c5b15b66f3d65f0947672dd1a516 Update snapshots now that final form isn't overwriting props 1f9bbaec8678a7653124898ba4a2e84ddc1ef243 fix: prevent final form from overwriting field props f6c66c003d1917db2dcb3f757e8a303266c381fa fix: prevent final form fields overwrite out props 48d1fc7318ee4ba7bf72839127e9a0b1487c1729 chore: rename translation string 728373da5728a4e7c039bd0c3a3cf0037e9f5177 fix: purge relay metadata from request 7cdea925087a6b9b6e318bbb1b31b798be87dc2f fix: radiobuttons 9735bae79222219a81a28d458976a596201b650b chore: revert obsolete checks 0b556e1693584430a5814e81d87b0f233efd1a30 fix: refactor admin configure b245afc7b196035bcb454e031c966e63c77ce522 fix: implement withForm HOC 5787400051211f5d2e1773d7207f32b66b02a2a1 Update the Configure page form state to properly load form values 8c2af3e22a96a3d2e50e7f06fb45d1fb79cf0c8e Replace form.reset() with setTimeout(form.reset) 27d9c90e3f0166cc2db45db461619be15a3cb950 Update radio buttons and on/off fields to work with final-form updates b852dd14af85b14ff8e0d2823e1e83bf278b29b9 Replace any on OnSubmit with typed form submission interfaces f049a70aaf4872825ac3b2aa62dc5cb7f945290a (f) Preliminarily get Coral compiling with latest final-form libraries * feat: act is now actAndReturn * fix: print original filename and line number in custom console impl * feat: trace process warnings * fix: server warnings about potentially memory leak with too many listeners --- .eslintrc.js | 2 + config/jest/server.config.js | 1 + package-lock.json | 46 +- package.json | 12 +- .../UserDrawerNotesContainer.tsx | 2 +- .../components/UserStatus/SuspendForm.tsx | 15 +- .../Community/InviteUsers/EmailField.tsx | 2 +- .../Community/InviteUsers/RoleField.tsx | 6 +- .../routes/Community/UserTableFilter.tsx | 2 +- .../admin/routes/Configure/Configure.tsx | 4 +- .../admin/routes/Configure/ConfigureRoute.tsx | 2 +- .../admin/routes/Configure/OnOffField.tsx | 16 +- .../routes/Configure/PermissionField.tsx | 51 - .../sections/Advanced/AdvancedConfig.tsx | 54 - .../Advanced/AdvancedConfigContainer.tsx | 71 +- .../sections/Advanced/AdvancedConfigRoute.tsx | 3 - .../Advanced/CommentStreamLiveUpdates.tsx | 10 + .../CommentStreamLiveUpdatesContainer.tsx | 39 +- .../sections/Advanced/CustomCSSConfig.tsx | 10 +- .../Advanced/CustomCSSConfigContainer.tsx | 36 - .../Advanced/PermittedDomainsConfig.tsx | 10 +- .../PermittedDomainsConfigContainer.tsx | 36 - .../sections/Advanced/StoryCreationConfig.tsx | 16 +- .../Advanced/StoryCreationConfigContainer.tsx | 42 - .../sections/Auth/AccountFeaturesConfig.tsx | 12 + .../Auth/AccountFeaturesConfigContainer.tsx | 45 - .../Configure/sections/Auth/AuthConfig.tsx | 36 - .../sections/Auth/AuthConfigContainer.tsx | 92 +- .../sections/Auth/AuthConfigRoute.tsx | 4 - .../sections/Auth/AuthIntegrationsConfig.tsx | 46 +- .../Configure/sections/Auth/ClientIDField.tsx | 29 +- .../sections/Auth/ClientSecretField.tsx | 9 +- .../Auth/ConfigBoxWithToggleField.tsx | 2 +- .../sections/Auth/FacebookConfig.tsx | 26 +- .../sections/Auth/FacebookConfigContainer.tsx | 47 +- .../Configure/sections/Auth/GoogleConfig.tsx | 19 + .../sections/Auth/GoogleConfigContainer.tsx | 47 +- .../sections/Auth/LocalAuthConfig.tsx | 18 + .../Auth/LocalAuthConfigContainer.tsx | 46 - .../Configure/sections/Auth/OIDCConfig.tsx | 45 +- .../sections/Auth/OIDCConfigContainer.tsx | 69 +- .../sections/Auth/RegistrationField.tsx | 2 +- .../Configure/sections/Auth/SSOConfig.tsx | 18 + .../sections/Auth/SSOConfigContainer.tsx | 40 +- .../Configure/sections/Auth/SSOKeyField.tsx | 5 +- .../Configure/sections/Auth/SessionConfig.tsx | 10 +- .../sections/Auth/SessionConfigContainer.tsx | 36 - .../sections/Auth/TargetFilterField.tsx | 4 +- .../sections/Email/EmailConfigContainer.tsx | 118 +- .../sections/Email/EmailConfigRoute.tsx | 3 - .../routes/Configure/sections/Email/From.tsx | 14 +- .../sections/Email/FromContainer.tsx | 39 - .../routes/Configure/sections/Email/SMTP.tsx | 25 +- .../sections/Email/SMTPContainer.tsx | 45 - .../General/ClosedStreamMessageConfig.tsx | 12 +- .../ClosedStreamMessageConfigContainer.tsx | 38 - .../General/ClosingCommentStreamsConfig.tsx | 13 +- .../ClosingCommentStreamsConfigContainer.tsx | 39 - .../sections/General/CommentEditingConfig.tsx | 9 +- .../General/CommentEditingConfigContainer.tsx | 36 - .../sections/General/CommentLengthConfig.tsx | 18 +- .../General/CommentLengthConfigContainer.tsx | 40 - .../sections/General/GeneralConfig.tsx | 84 - .../General/GeneralConfigContainer.tsx | 87 +- .../sections/General/GeneralConfigRoute.tsx | 3 - .../sections/General/GuidelinesConfig.tsx | 13 +- .../General/GuidelinesConfigContainer.tsx | 39 - ...leConfigContainer.tsx => LocaleConfig.tsx} | 29 +- .../sections/General/ReactionConfig.tsx | 43 +- .../General/ReactionConfigContainer.tsx | 27 +- .../General/SitewideCommentingConfig.tsx | 13 +- .../SitewideCommentingConfigContainer.tsx | 39 - .../sections/General/StaffConfig.tsx | 17 +- .../sections/General/StaffConfigContainer.tsx | 38 - .../sections/Moderation/APIKeyField.tsx | 2 +- .../sections/Moderation/AkismetConfig.tsx | 16 +- .../Moderation/AkismetConfigContainer.tsx | 42 - .../Moderation/ModerationConfig.spec.tsx | 21 - .../sections/Moderation/ModerationConfig.tsx | 49 - .../Moderation/ModerationConfigContainer.tsx | 67 +- .../Moderation/ModerationConfigRoute.tsx | 3 - .../sections/Moderation/PerspectiveConfig.tsx | 36 +- .../Moderation/PerspectiveConfigContainer.tsx | 45 - .../Moderation/PreModerationConfig.tsx | 13 +- .../PreModerationConfigContainer.tsx | 37 - .../Moderation/RecentCommentHistoryConfig.tsx | 14 +- .../RecentCommentHistoryConfigContainer.tsx | 40 - .../ModerationConfig.spec.tsx.snap | 29 - .../Organization/OrganizationConfig.tsx | 42 - .../OrganizationConfigContainer.tsx | 69 +- .../Organization/OrganizationConfigRoute.tsx | 3 - .../OrganizationContactEmailConfig.tsx | 18 +- ...rganizationContactEmailConfigContainer.tsx | 38 - .../Organization/OrganizationNameConfig.tsx | 12 +- .../OrganizationNameConfigContainer.tsx | 38 - .../Organization/OrganizationURLConfig.tsx | 12 +- .../OrganizationURLConfigContainer.tsx | 38 - .../WordList/BannedWordListConfig.tsx | 10 + .../BannedWordListConfigContainer.tsx | 38 - .../WordList/SuspectWordListConfig.tsx | 10 + .../SuspectWordListConfigContainer.tsx | 38 - .../sections/WordList/WordListConfig.tsx | 35 - .../WordList/WordListConfigContainer.tsx | 59 +- .../sections/WordList/WordListConfigRoute.tsx | 3 - .../sections/WordList/WordListTextArea.tsx | 2 +- .../ForgotPassword/ForgotPasswordForm.tsx | 2 +- .../admin/routes/Invite/SetPasswordField.tsx | 2 +- .../admin/routes/Invite/SetUsernameField.tsx | 2 +- .../client/admin/routes/Login/EmailField.tsx | 2 +- .../views/AddEmailAddress/AddEmailAddress.tsx | 6 +- .../AddEmailAddressContainer.tsx | 2 +- .../AddEmailAddress/ConfirmEmailField.tsx | 2 +- .../views/AddEmailAddress/EmailField.tsx | 2 +- .../views/CreatePassword/CreatePassword.tsx | 6 +- .../CreatePasswordContainer.tsx | 2 +- .../views/CreatePassword/SetPasswordField.tsx | 2 +- .../views/CreateUsername/CreateUsername.tsx | 6 +- .../CreateUsernameContainer.tsx | 2 +- .../views/CreateUsername/UsernameField.tsx | 2 +- .../Login/views/SignIn/SignInWithEmail.tsx | 7 +- .../views/SignIn/SignInWithEmailContainer.tsx | 2 +- .../admin/routes/Stories/StoryTableFilter.tsx | 2 +- .../addEmailAddress.spec.tsx.snap | 4 +- .../createPassword.spec.tsx.snap | 2 +- .../createUsername.spec.tsx.snap | 2 +- .../admin/test/auth/addEmailAddress.spec.tsx | 136 +- .../admin/test/auth/createPassword.spec.tsx | 120 +- .../admin/test/auth/createUsername.spec.tsx | 88 +- .../admin/test/auth/signInWithEmail.spec.tsx | 122 +- .../admin/test/community/community.spec.tsx | 3 +- .../__snapshots__/advanced.spec.tsx.snap | 12 +- .../__snapshots__/auth.spec.tsx.snap | 4967 +++++------------ .../__snapshots__/general.spec.tsx.snap | 16 +- .../__snapshots__/moderation.spec.tsx.snap | 42 +- .../admin/test/configure/advanced.spec.tsx | 69 +- .../client/admin/test/configure/auth.spec.tsx | 269 +- .../admin/test/configure/general.spec.tsx | 199 +- .../admin/test/configure/moderation.spec.tsx | 133 +- .../test/configure/organization.spec.tsx | 53 +- .../admin/test/configure/wordList.spec.tsx | 21 +- .../admin/test/stories/stories.spec.tsx | 71 +- .../auth/components/ConfirmEmailField.tsx | 2 +- .../client/auth/components/EmailField.tsx | 2 +- .../auth/components/SetPasswordField.tsx | 9 +- .../client/auth/components/UsernameField.tsx | 2 +- src/core/client/auth/hooks/useResizePopup.ts | 10 +- .../addEmailAddress.spec.tsx.snap | 4 +- .../createPassword.spec.tsx.snap | 2 +- .../createUsername.spec.tsx.snap | 2 +- .../test/__snapshots__/signIn.spec.tsx.snap | 1012 ---- .../test/__snapshots__/signUp.spec.tsx.snap | 2046 ------- .../client/auth/test/addEmailAddress.spec.tsx | 139 +- .../client/auth/test/createPassword.spec.tsx | 40 +- .../client/auth/test/createUsername.spec.tsx | 104 +- .../client/auth/test/forgotPassword.spec.tsx | 39 +- src/core/client/auth/test/navigation.spec.tsx | 34 +- src/core/client/auth/test/signIn.spec.tsx | 139 +- src/core/client/auth/test/signUp.spec.tsx | 195 +- .../views/AddEmailAddress/AddEmailAddress.tsx | 8 +- .../views/CreatePassword/CreatePassword.tsx | 8 +- .../CreatePassword/SetPasswordMutation.ts | 2 +- .../views/CreateUsername/CreateUsername.tsx | 8 +- .../ForgotPassword/ForgotPasswordForm.tsx | 4 +- .../auth/views/SignIn/SignInWithEmail.tsx | 7 +- .../views/SignIn/SignInWithEmailContainer.tsx | 2 +- .../auth/views/SignUp/SignUpWithEmail.tsx | 6 +- .../views/SignUp/SignUpWithEmailContainer.tsx | 2 +- .../lib/form/components/FormInitializer.tsx | 40 - .../framework/lib/form/components/index.ts | 1 - .../client/framework/lib/form/helpers.tsx | 16 +- src/core/client/framework/lib/form/index.tsx | 1 + .../client/framework/lib/form/withForm.tsx | 24 + src/core/client/framework/lib/relay/index.ts | 1 + .../framework/lib/relay/purgeMetadata.spec.ts | 44 + .../framework/lib/relay/purgeMetadata.ts | 26 + src/core/client/framework/testHelpers/act.ts | 23 +- .../client/framework/testHelpers/byType.ts | 21 + .../framework/testHelpers/findParent.ts | 14 + .../client/framework/testHelpers/index.ts | 3 +- .../client/framework/testHelpers/within.ts | 11 +- .../install/App/steps/AddOrganizationStep.tsx | 12 +- .../App/steps/CreateYourAccountStep.tsx | 16 +- .../App/steps/PermittedDomainsStep.tsx | 12 +- .../EditCommentForm/EditCommentForm.tsx | 2 +- .../ModerationActionsContainer.tsx | 1 + .../RejectCommentMutation.ts | 7 +- .../ReplyCommentForm/ReplyCommentForm.tsx | 4 +- .../ReportPopover/ReportCommentForm.tsx | 12 +- .../UserBanPopoverContainer.tsx | 1 + .../PostCommentForm/PostCommentForm.tsx | 8 +- .../PostCommentFormContainer.spec.tsx | 148 +- .../PostCommentFormContainer.tsx | 2 +- .../ConfigureStream/ConfigureStream.tsx | 118 +- .../ConfigureStreamContainer.tsx | 9 +- .../LiveUpdatesConfig/LiveUpdatesConfig.tsx | 12 +- .../LiveUpdatesConfigContainer.tsx | 17 +- .../MessageBoxConfig.css | 0 .../MessageBoxConfig.tsx | 18 +- .../MessageBoxConfigContainer.tsx | 40 - .../ConfigureStream/MessageBoxConfig/index.ts | 4 - .../{PremodConfig => }/PremodConfig.tsx | 14 +- .../PremodConfig/PremodConfigContainer.tsx | 36 - .../ConfigureStream/PremodConfig/index.ts | 4 - .../PremodLinksConfig.tsx | 14 +- .../PremodLinksConfigContainer.tsx | 36 - .../PremodLinksConfig/index.ts | 4 - .../ChangeEmail/ChangeEmailContainer.tsx | 5 +- .../tabs/Profile/Settings/ChangePassword.tsx | 6 +- .../ChangeUsernameContainer.tsx | 3 +- .../DeleteAccount/Pages/ConfirmPage.tsx | 9 +- .../NotificationSettingsContainer.tsx | 11 +- .../permalinkViewLoadMoreParents.spec.tsx | 19 +- .../permalink/permalinkViewPostReply.spec.tsx | 15 +- .../stream/charCountEditComment.spec.tsx | 35 +- .../stream/charCountPostComment.spec.tsx | 82 +- .../stream/charCountReplyComment.spec.tsx | 48 +- .../test/comments/stream/editComment.spec.tsx | 141 +- .../test/comments/stream/postComment.spec.tsx | 396 +- .../comments/stream/postLocalReply.spec.tsx | 33 +- .../test/comments/stream/postReply.spec.tsx | 91 +- .../comments/stream/reportComment.spec.tsx | 136 +- .../test/configure/renderConfigure.spec.tsx | 19 +- .../configure/streamConfiguration.spec.tsx | 84 +- .../stream/test/profile/myComments.spec.tsx | 15 +- src/core/client/test/jsdom.ts | 18 +- src/core/client/test/setupConsole.ts | 93 + src/core/client/test/setupTestFramework.ts | 1 + .../PasswordField/PasswordField.tsx | 2 +- .../ui/components/TextField/TextField.tsx | 10 +- .../ui/components/v2/Delay/Delay.spec.tsx | 5 +- .../v2/PasswordField/PasswordField.tsx | 2 +- .../ui/components/v2/TextField/TextField.tsx | 10 +- src/core/common/utils/index.ts | 2 + src/core/common/utils/isPromise.ts | 5 + src/core/common/utils/isPromiseLike.ts | 7 + src/core/server/test/setupTestFramework.ts | 4 + src/locales/da/admin.ftl | 8 +- src/locales/en-US/admin.ftl | 4 +- src/locales/pt-BR/admin.ftl | 4 +- 239 files changed, 4996 insertions(+), 10266 deletions(-) delete mode 100644 src/core/client/admin/routes/Configure/PermissionField.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Advanced/AdvancedConfig.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Advanced/CustomCSSConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Advanced/PermittedDomainsConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Advanced/StoryCreationConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Auth/AccountFeaturesConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Auth/AuthConfig.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Auth/LocalAuthConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Auth/SessionConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Email/FromContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Email/SMTPContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/General/ClosedStreamMessageConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/General/ClosingCommentStreamsConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/General/CommentEditingConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/General/CommentLengthConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/General/GeneralConfig.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/General/GuidelinesConfigContainer.tsx rename src/core/client/admin/routes/Configure/sections/General/{LocaleConfigContainer.tsx => LocaleConfig.tsx} (66%) delete mode 100644 src/core/client/admin/routes/Configure/sections/General/SitewideCommentingConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/General/StaffConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Moderation/AkismetConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Moderation/ModerationConfig.spec.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Moderation/ModerationConfig.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Moderation/PerspectiveConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Moderation/PreModerationConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Moderation/RecentCommentHistoryConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Moderation/__snapshots__/ModerationConfig.spec.tsx.snap delete mode 100644 src/core/client/admin/routes/Configure/sections/Organization/OrganizationConfig.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Organization/OrganizationContactEmailConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Organization/OrganizationNameConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/Organization/OrganizationURLConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/WordList/BannedWordListConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/WordList/SuspectWordListConfigContainer.tsx delete mode 100644 src/core/client/admin/routes/Configure/sections/WordList/WordListConfig.tsx delete mode 100644 src/core/client/framework/lib/form/components/FormInitializer.tsx create mode 100644 src/core/client/framework/lib/form/withForm.tsx create mode 100644 src/core/client/framework/lib/relay/purgeMetadata.spec.ts create mode 100644 src/core/client/framework/lib/relay/purgeMetadata.ts create mode 100644 src/core/client/framework/testHelpers/findParent.ts rename src/core/client/stream/tabs/Configure/ConfigureStream/{MessageBoxConfig => }/MessageBoxConfig.css (100%) rename src/core/client/stream/tabs/Configure/ConfigureStream/{MessageBoxConfig => }/MessageBoxConfig.tsx (95%) delete mode 100644 src/core/client/stream/tabs/Configure/ConfigureStream/MessageBoxConfig/MessageBoxConfigContainer.tsx delete mode 100644 src/core/client/stream/tabs/Configure/ConfigureStream/MessageBoxConfig/index.ts rename src/core/client/stream/tabs/Configure/ConfigureStream/{PremodConfig => }/PremodConfig.tsx (78%) delete mode 100644 src/core/client/stream/tabs/Configure/ConfigureStream/PremodConfig/PremodConfigContainer.tsx delete mode 100644 src/core/client/stream/tabs/Configure/ConfigureStream/PremodConfig/index.ts rename src/core/client/stream/tabs/Configure/ConfigureStream/{PremodLinksConfig => }/PremodLinksConfig.tsx (77%) delete mode 100644 src/core/client/stream/tabs/Configure/ConfigureStream/PremodLinksConfig/PremodLinksConfigContainer.tsx delete mode 100644 src/core/client/stream/tabs/Configure/ConfigureStream/PremodLinksConfig/index.ts create mode 100644 src/core/client/test/setupConsole.ts create mode 100644 src/core/common/utils/isPromise.ts create mode 100644 src/core/common/utils/isPromiseLike.ts create mode 100644 src/core/server/test/setupTestFramework.ts diff --git a/.eslintrc.js b/.eslintrc.js index b81b112cd..a36133494 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -102,6 +102,8 @@ let typescriptTypeCheckingOverrides = { }, }, }], + // 28.11.19: (cvle) Disabled because behavior of regexp.exec seems different than str.match? + "@typescript-eslint/prefer-regexp-exec": "off", "@typescript-eslint/require-await": "off", "@typescript-eslint/no-misused-promises": "off", "@typescript-eslint/unbound-method": "off", // 10.10.19: (cvle) seems to give false positive. diff --git a/config/jest/server.config.js b/config/jest/server.config.js index 3c465e064..4409cca41 100644 --- a/config/jest/server.config.js +++ b/config/jest/server.config.js @@ -6,6 +6,7 @@ module.exports = { roots: ["/src"], collectCoverageFrom: ["**/*.{js,jsx,mjs,ts,tsx}"], coveragePathIgnorePatterns: ["/node_modules/"], + setupFilesAfterEnv: ["/src/core/server/test/setupTestFramework.ts"], testMatch: ["**/*.spec.{js,jsx,mjs,ts,tsx}"], testPathIgnorePatterns: ["/node_modules/", "/client/"], testEnvironment: "node", diff --git a/package-lock.json b/package-lock.json index c9823ebb0..93e985465 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4342,6 +4342,12 @@ "@types/node": "*" } }, + "@types/stack-trace": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/stack-trace/-/stack-trace-0.0.29.tgz", + "integrity": "sha512-TgfOX+mGY/NyNxJLIbDWrO9DjGoVSW9+aB8H2yy1fy32jsvxijhmyJI9fDFgvz3YP4lvJaq9DzdR/M1bOgVc9g==", + "dev": true + }, "@types/stack-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", @@ -14549,12 +14555,12 @@ } }, "final-form": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/final-form/-/final-form-4.11.0.tgz", - "integrity": "sha512-uO0VhAEbWvV8LHBpBHoIpbYqonYBXyd8gpTYFEAPCHEy5tcNqdVX4EnWQoxKl//+U9Vk0kTUsnPOWiBP2PiOUg==", + "version": "4.18.6", + "resolved": "https://registry.npmjs.org/final-form/-/final-form-4.18.6.tgz", + "integrity": "sha512-LssWTXTGkoNv5WxowFTTUyC86oLYlEHH2glARBxOq8RpjiQdOyUyVG7qfPaCeOwoOw7Y5wrhSWdePyOydqSrCw==", "dev": true, "requires": { - "@babel/runtime": "^7.1.5" + "@babel/runtime": "^7.3.1" } }, "finalhandler": { @@ -29389,12 +29395,30 @@ "dev": true }, "react-final-form": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/react-final-form/-/react-final-form-4.0.2.tgz", - "integrity": "sha512-EdFWrT8nMWu5sHViuZ/VmlaYT+mLu/q5TMDWZZj5gnssUAWfgcila0QpptFNDg6+qNtepGgFh5ZPASlivoEXUA==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/react-final-form/-/react-final-form-6.3.0.tgz", + "integrity": "sha512-jijhXR1fFGUBQwNOSqF4MK8XJO7Ynl1p8vcFsnQS0INSkGI52+4IagjUgtHj3w8EviIHPFK/Eflji6FELUl07w==", "dev": true, "requires": { - "@babel/runtime": "^7.1.2" + "@babel/runtime": "^7.4.5", + "ts-essentials": "^2.0.8" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.2.tgz", + "integrity": "sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "regenerator-runtime": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", + "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", + "dev": true + } } }, "react-helmet": { @@ -33398,6 +33422,12 @@ "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", "dev": true }, + "ts-essentials": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-2.0.12.tgz", + "integrity": "sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w==", + "dev": true + }, "ts-invariant": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.4.4.tgz", diff --git a/package.json b/package.json index 776c8bb13..5f78b1000 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "lint:scripts": "eslint 'scripts/**/*.{js,ts,tsx}'", "lint:graphql": "graphql-schema-linter src/core/server/graph/tenant/schema/schema.graphql", "lint-fix": "npm run lint:server -- --fix && npm run lint:client -- --fix && npm run lint:scripts -- --fix", - "test": "node scripts/test.js --env=jsdom", + "test": "node --trace-warnings scripts/test.js --env=jsdom", "tscheck": "npm-run-all --parallel tscheck:*", "tscheck:server": "tsc --project ./src/tsconfig.json --noEmit", "tscheck:client": "tsc --project ./src/core/client/tsconfig.json --noEmit", @@ -223,6 +223,7 @@ "@types/simplemde": "^1.11.7", "@types/sinon": "^7.0.11", "@types/source-map-support": "^0.5.0", + "@types/stack-trace": "0.0.29", "@types/stack-utils": "^1.0.1", "@types/throng": "^4.0.2", "@types/uuid": "^3.4.4", @@ -275,7 +276,7 @@ "eslint-plugin-react": "^7.15.1", "eventemitter2": "^5.0.1", "farce": "^0.2.6", - "final-form": "4.11.0", + "final-form": "4.18.6", "flat": "^4.1.0", "fluent-intl-polyfill": "^0.1.0", "fluent-langneg": "^0.1.1", @@ -326,7 +327,7 @@ "react-dev-utils": "^9.0.0", "react-dom": "^16.9.0-alpha.0", "react-error-overlay": "^5.1.6", - "react-final-form": "4.0.2", + "react-final-form": "6.3.0", "react-popper": "^1.3.2", "react-relay": "^4.0.0", "react-relay-network-modern": "^4.0.4", @@ -347,6 +348,7 @@ "simulant": "^0.2.2", "sinon": "^7.3.2", "sockjs-client": "^1.3.0", + "stack-trace": "0.0.10", "strip-ansi": "^5.2.0", "style-loader": "^0.23.1", "subscriptions-transport-ws": "^0.9.16", @@ -362,11 +364,11 @@ "tslint": "^5.20.0", "typed-css-modules": "^0.4.2", "typeface-manuale": "^0.0.71", + "typeface-nunito": "0.0.72", + "typeface-open-sans": "0.0.75", "typeface-source-sans-pro": "^0.0.54", "typescript": "3.3.4000", "typescript-snapshots-plugin": "^1.6.0", - "typeface-nunito": "0.0.72", - "typeface-open-sans": "0.0.75", "wait-for-expect": "^1.1.1", "webpack": "^4.30.0", "webpack-assets-manifest": "^3.1.1", diff --git a/src/core/client/admin/components/UserHistoryDrawer/UserDrawerNotesContainer.tsx b/src/core/client/admin/components/UserHistoryDrawer/UserDrawerNotesContainer.tsx index 8ff659f86..46537c9cf 100644 --- a/src/core/client/admin/components/UserHistoryDrawer/UserDrawerNotesContainer.tsx +++ b/src/core/client/admin/components/UserHistoryDrawer/UserDrawerNotesContainer.tsx @@ -52,7 +52,7 @@ const UserDrawerNotesContainer: FunctionComponent = ({ userID: user.id, body, }); - form.reset(); + form.initialize({}); }, [user] ); diff --git a/src/core/client/admin/components/UserStatus/SuspendForm.tsx b/src/core/client/admin/components/UserStatus/SuspendForm.tsx index a6bf533d5..38f8ae6a8 100644 --- a/src/core/client/admin/components/UserStatus/SuspendForm.tsx +++ b/src/core/client/admin/components/UserStatus/SuspendForm.tsx @@ -25,6 +25,11 @@ interface Props { lastFocusableRef: RefObject; } +interface FormStateValues { + duration: any; + emailMessage: any; +} + const DURATIONS: ScaledUnit[] = [ { original: 3600, value: "3600", unit: "hour", scaled: 1 }, // 1 hour { original: 10800, value: "10800", unit: "hour", scaled: 3 }, // 3 hours @@ -69,7 +74,8 @@ const SuspendForm: FunctionComponent = ({ const setMessageValue: Mutator = useCallback( ([name, newValue], state, { changeValue }) => { if (state.lastFormState) { - const { duration, emailMessage } = state.lastFormState.values; + const { duration, emailMessage } = state.lastFormState + .values as FormStateValues; const unit = DURATIONS.find(d => d.value === duration); const expectedEmailMessage = getMessageWithDuration(unit!); if (expectedEmailMessage === emailMessage) { @@ -86,7 +92,8 @@ const SuspendForm: FunctionComponent = ({ { changeValue } ) => { if (state.lastFormState && !checked) { - const { duration, emailMessage } = state.lastFormState.values; + const { duration, emailMessage } = state.lastFormState + .values as FormStateValues; const unit = DURATIONS.find(d => d.value === duration); const expectedEmailMessage = getMessageWithDuration(unit!); if (expectedEmailMessage !== emailMessage) { @@ -132,8 +139,8 @@ const SuspendForm: FunctionComponent = ({ $unit={unit} > { form.mutators.setMessageValue( "emailMessage", @@ -156,8 +163,8 @@ const SuspendForm: FunctionComponent = ({ {({ input }) => ( { form.mutators.resetMessageValue( "emailMessage", diff --git a/src/core/client/admin/routes/Community/InviteUsers/EmailField.tsx b/src/core/client/admin/routes/Community/InviteUsers/EmailField.tsx index 2e04108a2..f54f8d70e 100644 --- a/src/core/client/admin/routes/Community/InviteUsers/EmailField.tsx +++ b/src/core/client/admin/routes/Community/InviteUsers/EmailField.tsx @@ -20,11 +20,11 @@ const EmailField: FunctionComponent = ({ index, disabled }) => ( diff --git a/src/core/client/admin/routes/Community/InviteUsers/RoleField.tsx b/src/core/client/admin/routes/Community/InviteUsers/RoleField.tsx index dc206c94e..4c5aca164 100644 --- a/src/core/client/admin/routes/Community/InviteUsers/RoleField.tsx +++ b/src/core/client/admin/routes/Community/InviteUsers/RoleField.tsx @@ -21,9 +21,9 @@ const RoleField: FunctionComponent = ({ disabled }) => ( {({ input }) => ( Staff @@ -34,9 +34,9 @@ const RoleField: FunctionComponent = ({ disabled }) => ( {({ input }) => ( Moderator @@ -47,9 +47,9 @@ const RoleField: FunctionComponent = ({ disabled }) => ( {({ input }) => ( Admin diff --git a/src/core/client/admin/routes/Community/UserTableFilter.tsx b/src/core/client/admin/routes/Community/UserTableFilter.tsx index 2633c3afa..08afac545 100644 --- a/src/core/client/admin/routes/Community/UserTableFilter.tsx +++ b/src/core/client/admin/routes/Community/UserTableFilter.tsx @@ -60,12 +60,12 @@ const UserTableFilter: FunctionComponent = props => ( attrs={{ placeholder: true, "aria-label": true }} > void; - onChange: (formState: FormState) => void; + onChange: (formState: FormState) => void; children: React.ReactElement; } @@ -25,7 +25,7 @@ const Configure: FunctionComponent = ({ }) => (
- {({ handleSubmit, submitting, pristine, form, submitError }) => ( + {({ handleSubmit, submitting, form, pristine, submitError }) => ( diff --git a/src/core/client/admin/routes/Configure/ConfigureRoute.tsx b/src/core/client/admin/routes/Configure/ConfigureRoute.tsx index 6f0db23d6..fe98ec953 100644 --- a/src/core/client/admin/routes/Configure/ConfigureRoute.tsx +++ b/src/core/client/admin/routes/Configure/ConfigureRoute.tsx @@ -36,7 +36,7 @@ class ConfigureRoute extends React.Component { form.initialize(data); }; - private handleChange = ({ dirty }: FormState) => { + private handleChange = ({ dirty }: FormState) => { if (dirty !== this.state.dirty) { this.setState({ dirty }); } diff --git a/src/core/client/admin/routes/Configure/OnOffField.tsx b/src/core/client/admin/routes/Configure/OnOffField.tsx index 7bd7d1ef9..3c186104d 100644 --- a/src/core/client/admin/routes/Configure/OnOffField.tsx +++ b/src/core/client/admin/routes/Configure/OnOffField.tsx @@ -2,7 +2,7 @@ import { Localized } from "fluent-react/compat"; import React, { FunctionComponent } from "react"; import { Field } from "react-final-form"; -import { parseStringBool } from "coral-framework/lib/form"; +import { formatBool, parseStringBool } from "coral-framework/lib/form"; import { Validator } from "coral-framework/lib/validation"; import { RadioButton } from "coral-ui/components/v2"; @@ -13,8 +13,8 @@ interface Props { invert?: boolean; onLabel?: React.ReactNode; offLabel?: React.ReactNode; - format?: ((value: any, name: string) => any) | null; - parse?: ((value: any, name: string) => any) | null; + format?: (value: any, name: string) => any; + parse?: (value: any, name: string) => any; className?: string; } @@ -25,19 +25,19 @@ const OnOffField: FunctionComponent = ({ offLabel, invert = false, parse = parseStringBool, - format, + format = formatBool, className, }) => (
{({ input }) => ( - + {onLabel || ( On @@ -51,10 +51,10 @@ const OnOffField: FunctionComponent = ({ type="radio" parse={parse} format={format} - value={invert} + value={JSON.stringify(invert)} > {({ input }) => ( - + {offLabel || ( Off diff --git a/src/core/client/admin/routes/Configure/PermissionField.tsx b/src/core/client/admin/routes/Configure/PermissionField.tsx deleted file mode 100644 index 3de3c53cd..000000000 --- a/src/core/client/admin/routes/Configure/PermissionField.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { Localized } from "fluent-react/compat"; -import React, { FunctionComponent } from "react"; -import { Field } from "react-final-form"; - -import { parseStringBool } from "coral-framework/lib/form"; -import { Validator } from "coral-framework/lib/validation"; -import { RadioButton } from "coral-ui/components/v2"; - -interface Props { - validate?: Validator; - name: string; - disabled: boolean; - invert?: boolean; -} - -const PermissionField: FunctionComponent = ({ - name, - disabled, - invert = false, -}) => ( -
- - {({ input }) => ( - - - Allow - - - )} - - - {({ input }) => ( - - - Don't allow - - - )} - -
-); - -export default PermissionField; diff --git a/src/core/client/admin/routes/Configure/sections/Advanced/AdvancedConfig.tsx b/src/core/client/admin/routes/Configure/sections/Advanced/AdvancedConfig.tsx deleted file mode 100644 index 84f9da319..000000000 --- a/src/core/client/admin/routes/Configure/sections/Advanced/AdvancedConfig.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import React, { FunctionComponent } from "react"; - -import { PropTypesOf } from "coral-framework/types"; -import { HorizontalGutter } from "coral-ui/components/v2"; - -import CommentStreamLiveUpdatesContainer from "./CommentStreamLiveUpdatesContainer"; -import CustomCSSConfigContainer from "./CustomCSSConfigContainer"; -import EmbedCodeContainer from "./EmbedCodeContainer"; -import PermittedDomainsConfigContainer from "./PermittedDomainsConfigContainer"; -import StoryCreationConfigContainer from "./StoryCreationConfigContainer"; - -interface Props { - disabled: boolean; - settings: PropTypesOf["settings"] & - PropTypesOf["settings"] & - PropTypesOf["settings"] & - PropTypesOf["settingsReadOnly"] & - PropTypesOf["settings"] & - PropTypesOf["settings"]; - onInitValues: (values: any) => void; -} - -const AdvancedConfig: FunctionComponent = ({ - disabled, - settings, - onInitValues, -}) => ( - - - - - - - -); - -export default AdvancedConfig; diff --git a/src/core/client/admin/routes/Configure/sections/Advanced/AdvancedConfigContainer.tsx b/src/core/client/admin/routes/Configure/sections/Advanced/AdvancedConfigContainer.tsx index edc2a0e43..00fa67f46 100644 --- a/src/core/client/admin/routes/Configure/sections/Advanced/AdvancedConfigContainer.tsx +++ b/src/core/client/admin/routes/Configure/sections/Advanced/AdvancedConfigContainer.tsx @@ -1,57 +1,56 @@ -import { FormApi } from "final-form"; -import { RouteProps } from "found"; -import React from "react"; +import React, { useMemo } from "react"; +import { useForm } from "react-final-form"; import { graphql } from "react-relay"; -import { pureMerge } from "coral-common/utils"; -import { withFragmentContainer } from "coral-framework/lib/relay"; +import { + purgeMetadata, + withFragmentContainer, +} from "coral-framework/lib/relay"; +import { HorizontalGutter } from "coral-ui/components"; import { AdvancedConfigContainer_settings } from "coral-admin/__generated__/AdvancedConfigContainer_settings.graphql"; -import AdvancedConfig from "./AdvancedConfig"; +import CommentStreamLiveUpdatesContainer from "./CommentStreamLiveUpdatesContainer"; +import CustomCSSConfig from "./CustomCSSConfig"; +import EmbedCodeContainer from "./EmbedCodeContainer"; +import PermittedDomainsConfig from "./PermittedDomainsConfig"; +import StoryCreationConfig from "./StoryCreationConfig"; interface Props { - form: FormApi; submitting: boolean; settings: AdvancedConfigContainer_settings; } -class AdvancedConfigContainer extends React.Component { - public static routeConfig: RouteProps; - private initialValues = {}; - - constructor(props: Props) { - super(props); - } - - public componentDidMount() { - this.props.form.initialize(this.initialValues); - } - - private handleOnInitValues = (values: any) => { - this.initialValues = pureMerge(this.initialValues, values); - }; - - public render() { - return ( - = ({ + settings, + submitting, +}) => { + const form = useForm(); + useMemo(() => form.initialize(purgeMetadata(settings)), []); + return ( + + + + - ); - } -} + + + + ); +}; const enhanced = withFragmentContainer({ settings: graphql` fragment AdvancedConfigContainer_settings on Settings { + ...CustomCSSConfig_formValues @relay(mask: false) + ...PermittedDomainsConfig_formValues @relay(mask: false) + ...CommentStreamLiveUpdates_formValues @relay(mask: false) + ...StoryCreationConfig_formValues @relay(mask: false) + ...EmbedCodeContainer_settings - ...CustomCSSConfigContainer_settings - ...PermittedDomainsConfigContainer_settings ...CommentStreamLiveUpdatesContainer_settings - ...CommentStreamLiveUpdatesContainer_settingsReadOnly - ...StoryCreationConfigContainer_settings } `, })(AdvancedConfigContainer); diff --git a/src/core/client/admin/routes/Configure/sections/Advanced/AdvancedConfigRoute.tsx b/src/core/client/admin/routes/Configure/sections/Advanced/AdvancedConfigRoute.tsx index 39bd0d49d..34219fbce 100644 --- a/src/core/client/admin/routes/Configure/sections/Advanced/AdvancedConfigRoute.tsx +++ b/src/core/client/admin/routes/Configure/sections/Advanced/AdvancedConfigRoute.tsx @@ -1,4 +1,3 @@ -import { FormApi } from "final-form"; import React from "react"; import { graphql } from "react-relay"; @@ -11,7 +10,6 @@ import AdvancedConfigContainer from "./AdvancedConfigContainer"; interface Props { data: AdvancedConfigRouteQueryResponse | null; - form: FormApi; submitting: boolean; } @@ -27,7 +25,6 @@ class AdvancedConfigRoute extends React.Component { return ( ); diff --git a/src/core/client/admin/routes/Configure/sections/Advanced/CommentStreamLiveUpdates.tsx b/src/core/client/admin/routes/Configure/sections/Advanced/CommentStreamLiveUpdates.tsx index 87c331ec9..3457d2ae2 100644 --- a/src/core/client/admin/routes/Configure/sections/Advanced/CommentStreamLiveUpdates.tsx +++ b/src/core/client/admin/routes/Configure/sections/Advanced/CommentStreamLiveUpdates.tsx @@ -1,5 +1,6 @@ import { Localized } from "fluent-react/compat"; import React, { FunctionComponent } from "react"; +import { graphql } from "react-relay"; import { FormField, FormFieldDescription } from "coral-ui/components/v2"; @@ -7,6 +8,15 @@ import ConfigBox from "../../ConfigBox"; import Header from "../../Header"; import OnOffField from "../../OnOffField"; +// eslint-disable-next-line no-unused-expressions +graphql` + fragment CommentStreamLiveUpdates_formValues on Settings { + live { + enabled + } + } +`; + interface Props { disabled: boolean; } diff --git a/src/core/client/admin/routes/Configure/sections/Advanced/CommentStreamLiveUpdatesContainer.tsx b/src/core/client/admin/routes/Configure/sections/Advanced/CommentStreamLiveUpdatesContainer.tsx index 68a41a14f..efcc7303b 100644 --- a/src/core/client/admin/routes/Configure/sections/Advanced/CommentStreamLiveUpdatesContainer.tsx +++ b/src/core/client/admin/routes/Configure/sections/Advanced/CommentStreamLiveUpdatesContainer.tsx @@ -4,49 +4,30 @@ import { graphql } from "react-relay"; import { withFragmentContainer } from "coral-framework/lib/relay"; import { CommentStreamLiveUpdatesContainer_settings } from "coral-admin/__generated__/CommentStreamLiveUpdatesContainer_settings.graphql"; -import { CommentStreamLiveUpdatesContainer_settingsReadOnly } from "coral-admin/__generated__/CommentStreamLiveUpdatesContainer_settingsReadOnly.graphql"; import CommentStreamLiveUpdates from "./CommentStreamLiveUpdates"; interface Props { - settingsReadOnly: CommentStreamLiveUpdatesContainer_settingsReadOnly; settings: CommentStreamLiveUpdatesContainer_settings; - onInitValues: (values: CommentStreamLiveUpdatesContainer_settings) => void; disabled: boolean; } -class CommentStreamLiveUpdatesContainer extends React.Component { - constructor(props: Props) { - super(props); - props.onInitValues(props.settings); +const CommentStreamLiveUpdatesContainer: React.FunctionComponent = ({ + disabled, + settings: { + live: { configurable }, + }, +}) => { + if (!configurable) { + return null; } - public render() { - const { - disabled, - settingsReadOnly: { - live: { configurable }, - }, - } = this.props; - - if (!configurable) { - return null; - } - - return ; - } -} + return ; +}; const enhanced = withFragmentContainer({ settings: graphql` fragment CommentStreamLiveUpdatesContainer_settings on Settings { - live { - enabled - } - } - `, - settingsReadOnly: graphql` - fragment CommentStreamLiveUpdatesContainer_settingsReadOnly on Settings { live { configurable } diff --git a/src/core/client/admin/routes/Configure/sections/Advanced/CustomCSSConfig.tsx b/src/core/client/admin/routes/Configure/sections/Advanced/CustomCSSConfig.tsx index ce45949b7..2cdcc78cd 100644 --- a/src/core/client/admin/routes/Configure/sections/Advanced/CustomCSSConfig.tsx +++ b/src/core/client/admin/routes/Configure/sections/Advanced/CustomCSSConfig.tsx @@ -1,6 +1,7 @@ import { Localized } from "fluent-react/compat"; import React, { FunctionComponent } from "react"; import { Field } from "react-final-form"; +import { graphql } from "react-relay"; import { formatEmpty, parseEmptyAsNull } from "coral-framework/lib/form"; import { FormField, FormFieldDescription } from "coral-ui/components/v2"; @@ -9,6 +10,13 @@ import ConfigBox from "../../ConfigBox"; import Header from "../../Header"; import TextFieldWithValidation from "../../TextFieldWithValidation"; +// eslint-disable-next-line no-unused-expressions +graphql` + fragment CustomCSSConfig_formValues on Settings { + customCSSURL + } +`; + interface Props { disabled: boolean; } @@ -34,6 +42,7 @@ const CustomCSSConfig: FunctionComponent = ({ disabled }) => ( {({ input, meta }) => ( = ({ disabled }) => ( spellCheck={false} fullWidth meta={meta} - {...input} /> )} diff --git a/src/core/client/admin/routes/Configure/sections/Advanced/CustomCSSConfigContainer.tsx b/src/core/client/admin/routes/Configure/sections/Advanced/CustomCSSConfigContainer.tsx deleted file mode 100644 index 298e93ed3..000000000 --- a/src/core/client/admin/routes/Configure/sections/Advanced/CustomCSSConfigContainer.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import React from "react"; -import { graphql } from "react-relay"; - -import { withFragmentContainer } from "coral-framework/lib/relay"; - -import { CustomCSSConfigContainer_settings as SettingsData } from "coral-admin/__generated__/CustomCSSConfigContainer_settings.graphql"; - -import CustomCSSConfig from "./CustomCSSConfig"; - -interface Props { - settings: SettingsData; - onInitValues: (values: SettingsData) => void; - disabled: boolean; -} - -class CustomCSSConfigContainer extends React.Component { - constructor(props: Props) { - super(props); - props.onInitValues(props.settings); - } - - public render() { - const { disabled } = this.props; - return ; - } -} - -const enhanced = withFragmentContainer({ - settings: graphql` - fragment CustomCSSConfigContainer_settings on Settings { - customCSSURL - } - `, -})(CustomCSSConfigContainer); - -export default enhanced; diff --git a/src/core/client/admin/routes/Configure/sections/Advanced/PermittedDomainsConfig.tsx b/src/core/client/admin/routes/Configure/sections/Advanced/PermittedDomainsConfig.tsx index 985105ffb..c994104fa 100644 --- a/src/core/client/admin/routes/Configure/sections/Advanced/PermittedDomainsConfig.tsx +++ b/src/core/client/admin/routes/Configure/sections/Advanced/PermittedDomainsConfig.tsx @@ -1,6 +1,7 @@ import { Localized } from "fluent-react/compat"; import React, { FunctionComponent } from "react"; import { Field } from "react-final-form"; +import { graphql } from "react-relay"; import { formatStringList, parseStringList } from "coral-framework/lib/form"; import { validateStrictURLList } from "coral-framework/lib/validation"; @@ -10,6 +11,13 @@ import ConfigBox from "../../ConfigBox"; import Header from "../../Header"; import TextFieldWithValidation from "../../TextFieldWithValidation"; +// eslint-disable-next-line no-unused-expressions +graphql` + fragment PermittedDomainsConfig_formValues on Settings { + allowedDomains + } +`; + interface Props { disabled: boolean; } @@ -44,6 +52,7 @@ const PermittedDomainsConfig: FunctionComponent = ({ disabled }) => ( > {({ input, meta }) => ( = ({ disabled }) => ( autoCapitalize="off" spellCheck={false} meta={meta} - {...input} fullWidth /> )} diff --git a/src/core/client/admin/routes/Configure/sections/Advanced/PermittedDomainsConfigContainer.tsx b/src/core/client/admin/routes/Configure/sections/Advanced/PermittedDomainsConfigContainer.tsx deleted file mode 100644 index 5aa2c9c35..000000000 --- a/src/core/client/admin/routes/Configure/sections/Advanced/PermittedDomainsConfigContainer.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import React from "react"; -import { graphql } from "react-relay"; - -import { withFragmentContainer } from "coral-framework/lib/relay"; - -import { PermittedDomainsConfigContainer_settings as SettingsData } from "coral-admin/__generated__/PermittedDomainsConfigContainer_settings.graphql"; - -import PermittedDomainsConfig from "./PermittedDomainsConfig"; - -interface Props { - settings: SettingsData; - onInitValues: (values: SettingsData) => void; - disabled: boolean; -} - -class PermittedDomainsConfigContainer extends React.Component { - constructor(props: Props) { - super(props); - props.onInitValues(props.settings); - } - - public render() { - const { disabled } = this.props; - return ; - } -} - -const enhanced = withFragmentContainer({ - settings: graphql` - fragment PermittedDomainsConfigContainer_settings on Settings { - allowedDomains - } - `, -})(PermittedDomainsConfigContainer); - -export default enhanced; diff --git a/src/core/client/admin/routes/Configure/sections/Advanced/StoryCreationConfig.tsx b/src/core/client/admin/routes/Configure/sections/Advanced/StoryCreationConfig.tsx index c796b32dd..a050bd398 100644 --- a/src/core/client/admin/routes/Configure/sections/Advanced/StoryCreationConfig.tsx +++ b/src/core/client/admin/routes/Configure/sections/Advanced/StoryCreationConfig.tsx @@ -1,6 +1,7 @@ import { Localized } from "fluent-react/compat"; import React, { FunctionComponent } from "react"; import { Field } from "react-final-form"; +import { graphql } from "react-relay"; import { parseEmptyAsNull } from "coral-framework/lib/form"; import { ExternalLink } from "coral-framework/lib/i18n/components"; @@ -18,6 +19,19 @@ import HelperText from "../../HelperText"; import OnOffField from "../../OnOffField"; import TextFieldWithValidation from "../../TextFieldWithValidation"; +// eslint-disable-next-line no-unused-expressions +graphql` + fragment StoryCreationConfig_formValues on Settings { + stories { + scraping { + enabled + proxyURL + } + disableLazy + } + } +`; + interface Props { disabled: boolean; } @@ -90,6 +104,7 @@ const StoryCreationConfig: FunctionComponent = ({ disabled }) => ( > {({ input, meta }) => ( = ({ disabled }) => ( autoCapitalize="off" spellCheck={false} meta={meta} - {...input} /> )}
diff --git a/src/core/client/admin/routes/Configure/sections/Advanced/StoryCreationConfigContainer.tsx b/src/core/client/admin/routes/Configure/sections/Advanced/StoryCreationConfigContainer.tsx deleted file mode 100644 index 1d00b4e0e..000000000 --- a/src/core/client/admin/routes/Configure/sections/Advanced/StoryCreationConfigContainer.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from "react"; -import { graphql } from "react-relay"; - -import { withFragmentContainer } from "coral-framework/lib/relay"; - -import { StoryCreationConfigContainer_settings as SettingsData } from "coral-admin/__generated__/StoryCreationConfigContainer_settings.graphql"; - -import StoryCreationConfig from "./StoryCreationConfig"; - -interface Props { - settings: SettingsData; - onInitValues: (values: SettingsData) => void; - disabled: boolean; -} - -class StoryCreationConfigContainer extends React.Component { - constructor(props: Props) { - super(props); - props.onInitValues(props.settings); - } - - public render() { - const { disabled } = this.props; - return ; - } -} - -const enhanced = withFragmentContainer({ - settings: graphql` - fragment StoryCreationConfigContainer_settings on Settings { - stories { - scraping { - enabled - proxyURL - } - disableLazy - } - } - `, -})(StoryCreationConfigContainer); - -export default enhanced; diff --git a/src/core/client/admin/routes/Configure/sections/Auth/AccountFeaturesConfig.tsx b/src/core/client/admin/routes/Configure/sections/Auth/AccountFeaturesConfig.tsx index 0f0f39e67..2b70ea040 100644 --- a/src/core/client/admin/routes/Configure/sections/Auth/AccountFeaturesConfig.tsx +++ b/src/core/client/admin/routes/Configure/sections/Auth/AccountFeaturesConfig.tsx @@ -1,5 +1,6 @@ import { Localized } from "fluent-react/compat"; import React, { FunctionComponent } from "react"; +import { graphql } from "react-relay"; import { Flex, @@ -16,6 +17,17 @@ import OnOffField from "../../OnOffField"; import styles from "./AccountFeaturesConfig.css"; +// eslint-disable-next-line no-unused-expressions +graphql` + fragment AccountFeaturesConfig_formValues on Settings { + accountFeatures { + changeUsername + deleteAccount + downloadComments + } + } +`; + interface Props { disabled?: boolean; } diff --git a/src/core/client/admin/routes/Configure/sections/Auth/AccountFeaturesConfigContainer.tsx b/src/core/client/admin/routes/Configure/sections/Auth/AccountFeaturesConfigContainer.tsx deleted file mode 100644 index c6ee6f646..000000000 --- a/src/core/client/admin/routes/Configure/sections/Auth/AccountFeaturesConfigContainer.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import React from "react"; -import { graphql } from "react-relay"; - -import { DeepNullable, DeepPartial } from "coral-common/types"; -import { withFragmentContainer } from "coral-framework/lib/relay"; -import { GQLSettings } from "coral-framework/schema"; - -import { AccountFeaturesConfigContainer_settings as SettingsData } from "coral-admin/__generated__/AccountFeaturesConfigContainer_settings.graphql"; - -import AccountFeaturesConfig from "./AccountFeaturesConfig"; - -export type FormProps = DeepNullable>; -export type OnInitValuesFct = (values: DeepPartial) => void; - -interface Props { - settings: SettingsData; - onInitValues: (values: SettingsData) => void; - disabled?: boolean; -} - -class AccountFeaturesConfigContainer extends React.Component { - constructor(props: Props) { - super(props); - props.onInitValues(props.settings); - } - - public render() { - const { disabled } = this.props; - return ; - } -} - -const enhanced = withFragmentContainer({ - settings: graphql` - fragment AccountFeaturesConfigContainer_settings on Settings { - accountFeatures { - changeUsername - deleteAccount - downloadComments - } - } - `, -})(AccountFeaturesConfigContainer); - -export default enhanced; diff --git a/src/core/client/admin/routes/Configure/sections/Auth/AuthConfig.tsx b/src/core/client/admin/routes/Configure/sections/Auth/AuthConfig.tsx deleted file mode 100644 index d665f3075..000000000 --- a/src/core/client/admin/routes/Configure/sections/Auth/AuthConfig.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import React, { FunctionComponent } from "react"; - -import { PropTypesOf } from "coral-framework/types"; -import { HorizontalGutter } from "coral-ui/components/v2"; - -import { OnInitValuesFct } from "./AuthConfigContainer"; -import AuthIntegrationsConfig from "./AuthIntegrationsConfig"; -import SessionConfigContainer from "./SessionConfigContainer"; - -interface Props { - disabled?: boolean; - auth: PropTypesOf["auth"] & - PropTypesOf["auth"]; - onInitValues: OnInitValuesFct; -} - -const AuthConfig: FunctionComponent = ({ - disabled, - auth, - onInitValues, -}) => ( - - - - -); - -export default AuthConfig; diff --git a/src/core/client/admin/routes/Configure/sections/Auth/AuthConfigContainer.tsx b/src/core/client/admin/routes/Configure/sections/Auth/AuthConfigContainer.tsx index 2c617665e..1efea2cf4 100644 --- a/src/core/client/admin/routes/Configure/sections/Auth/AuthConfigContainer.tsx +++ b/src/core/client/admin/routes/Configure/sections/Auth/AuthConfigContainer.tsx @@ -5,24 +5,28 @@ import React from "react"; import { graphql } from "react-relay"; import { DeepNullable, DeepPartial } from "coral-common/types"; -import { pureMerge } from "coral-common/utils"; import { CoralContext, withContext } from "coral-framework/lib/bootstrap"; import { AddSubmitHook, RemoveSubmitHook, SubmitHook, + withForm, withSubmitHookContext, } from "coral-framework/lib/form"; import { getMessage } from "coral-framework/lib/i18n"; -import { withFragmentContainer } from "coral-framework/lib/relay"; +import { + purgeMetadata, + withFragmentContainer, +} from "coral-framework/lib/relay"; import { GQLSettings } from "coral-framework/schema"; import { HorizontalGutter } from "coral-ui/components/v2"; import { AuthConfigContainer_auth as AuthData } from "coral-admin/__generated__/AuthConfigContainer_auth.graphql"; import { AuthConfigContainer_settings as SettingsData } from "coral-admin/__generated__/AuthConfigContainer_settings.graphql"; -import AccountFeaturesConfigContainer from "./AccountFeaturesConfigContainer"; -import AuthConfig from "./AuthConfig"; +import AccountFeaturesConfig from "./AccountFeaturesConfig"; +import AuthIntegrationsConfig from "./AuthIntegrationsConfig"; +import SessionConfig from "./SessionConfig"; export type FormProps = DeepNullable< Pick @@ -40,16 +44,17 @@ interface Props { class AuthConfigContainer extends React.Component { public static routeConfig: RouteProps; - private initialValues: DeepPartial = {}; private removeSubmitHook: RemoveSubmitHook; constructor(props: Props) { super(props); this.removeSubmitHook = this.props.addSubmitHook(this.submitHook); - } - - public componentDidMount() { - this.props.form.initialize(this.initialValues); + this.props.form.initialize( + purgeMetadata({ + ...props.settings, + auth: props.auth, + }) + ); } public componentWillUnmount() { @@ -97,51 +102,48 @@ class AuthConfigContainer extends React.Component { return; }; - private handleOnInitValues: OnInitValuesFct = values => { - this.initialValues = pureMerge(this.initialValues, values); - }; - public render() { return ( - - - + + + ); } } -const enhanced = withFragmentContainer({ - settings: graphql` - fragment AuthConfigContainer_settings on Settings { - ...AccountFeaturesConfigContainer_settings - } - `, - auth: graphql` - fragment AuthConfigContainer_auth on Auth { - ...FacebookConfigContainer_auth - ...FacebookConfigContainer_authReadOnly - ...GoogleConfigContainer_auth - ...GoogleConfigContainer_authReadOnly - ...SSOConfigContainer_auth - ...SSOConfigContainer_authReadOnly - ...LocalAuthConfigContainer_auth - ...OIDCConfigContainer_auth - ...OIDCConfigContainer_authReadOnly - ...SessionConfigContainer_auth - } - `, -})( - withSubmitHookContext(addSubmitHook => ({ addSubmitHook }))( - withContext(({ localeBundles }) => ({ localeBundles }))(AuthConfigContainer) +const enhanced = withForm( + withFragmentContainer({ + settings: graphql` + fragment AuthConfigContainer_settings on Settings { + ...AccountFeaturesConfig_formValues @relay(mask: false) + } + `, + auth: graphql` + fragment AuthConfigContainer_auth on Auth { + ...FacebookConfig_formValues @relay(mask: false) + ...GoogleConfig_formValues @relay(mask: false) + ...SSOConfig_formValues @relay(mask: false) + ...LocalAuthConfig_formValues @relay(mask: false) + ...OIDCConfig_formValues @relay(mask: false) + ...SessionConfig_formValues @relay(mask: false) + + ...FacebookConfigContainer_auth + ...GoogleConfigContainer_auth + ...SSOConfigContainer_auth + ...OIDCConfigContainer_auth + } + `, + })( + withSubmitHookContext(addSubmitHook => ({ addSubmitHook }))( + withContext(({ localeBundles }) => ({ localeBundles }))( + AuthConfigContainer + ) + ) ) ); diff --git a/src/core/client/admin/routes/Configure/sections/Auth/AuthConfigRoute.tsx b/src/core/client/admin/routes/Configure/sections/Auth/AuthConfigRoute.tsx index 9f0fb5ad0..308cf9e6a 100644 --- a/src/core/client/admin/routes/Configure/sections/Auth/AuthConfigRoute.tsx +++ b/src/core/client/admin/routes/Configure/sections/Auth/AuthConfigRoute.tsx @@ -1,4 +1,3 @@ -import { FormApi } from "final-form"; import React from "react"; import { graphql } from "react-relay"; @@ -11,7 +10,6 @@ import AuthConfigContainer from "./AuthConfigContainer"; interface Props { data: AuthConfigRouteContainerQueryResponse | null; - form: FormApi; submitting?: boolean; } @@ -28,7 +26,6 @@ class AuthConfigRoute extends React.Component { ); @@ -42,7 +39,6 @@ const enhanced = withRouteConfig({ ...AuthConfigContainer_settings auth { ...AuthConfigContainer_auth - ...SessionConfigContainer_auth } } } diff --git a/src/core/client/admin/routes/Configure/sections/Auth/AuthIntegrationsConfig.tsx b/src/core/client/admin/routes/Configure/sections/Auth/AuthIntegrationsConfig.tsx index 5413ac28b..d7cdd56a6 100644 --- a/src/core/client/admin/routes/Configure/sections/Auth/AuthIntegrationsConfig.tsx +++ b/src/core/client/admin/routes/Configure/sections/Auth/AuthIntegrationsConfig.tsx @@ -3,62 +3,30 @@ import React, { FunctionComponent } from "react"; import { PropTypesOf } from "coral-framework/types"; import { HorizontalGutter } from "coral-ui/components/v2"; -import { OnInitValuesFct } from "./AuthConfigContainer"; import FacebookConfigContainer from "./FacebookConfigContainer"; import GoogleConfigContainer from "./GoogleConfigContainer"; -import LocalAuthConfigContainer from "./LocalAuthConfigContainer"; +import LocalAuthConfig from "./LocalAuthConfig"; import OIDCConfigContainer from "./OIDCConfigContainer"; import SSOConfigContainer from "./SSOConfigContainer"; interface Props { disabled?: boolean; auth: PropTypesOf["auth"] & - PropTypesOf["authReadOnly"] & PropTypesOf["auth"] & - PropTypesOf["authReadOnly"] & PropTypesOf["auth"] & - PropTypesOf["authReadOnly"] & - PropTypesOf["auth"] & - PropTypesOf["auth"] & - PropTypesOf["authReadOnly"]; - onInitValues: OnInitValuesFct; + PropTypesOf["auth"]; } const AuthIntegrationsConfig: FunctionComponent = ({ disabled, auth, - onInitValues, }) => ( - - - - - + + + + + ); diff --git a/src/core/client/admin/routes/Configure/sections/Auth/ClientIDField.tsx b/src/core/client/admin/routes/Configure/sections/Auth/ClientIDField.tsx index 2baba48e8..84441edea 100644 --- a/src/core/client/admin/routes/Configure/sections/Auth/ClientIDField.tsx +++ b/src/core/client/admin/routes/Configure/sections/Auth/ClientIDField.tsx @@ -20,21 +20,24 @@ const ClientSecretField: FunctionComponent = ({ validate, }) => ( - - - {({ input, meta }) => ( - + <> + + + + + )} diff --git a/src/core/client/admin/routes/Configure/sections/Auth/ClientSecretField.tsx b/src/core/client/admin/routes/Configure/sections/Auth/ClientSecretField.tsx index f968017ef..8c9322554 100644 --- a/src/core/client/admin/routes/Configure/sections/Auth/ClientSecretField.tsx +++ b/src/core/client/admin/routes/Configure/sections/Auth/ClientSecretField.tsx @@ -18,9 +18,6 @@ const ClientSecretField: FunctionComponent = ({ validate, }) => ( - - - = ({ > {({ input, meta }) => ( <> + + + diff --git a/src/core/client/admin/routes/Configure/sections/Auth/ConfigBoxWithToggleField.tsx b/src/core/client/admin/routes/Configure/sections/Auth/ConfigBoxWithToggleField.tsx index 8bf23b25e..959dfba0f 100644 --- a/src/core/client/admin/routes/Configure/sections/Auth/ConfigBoxWithToggleField.tsx +++ b/src/core/client/admin/routes/Configure/sections/Auth/ConfigBoxWithToggleField.tsx @@ -32,7 +32,7 @@ const ConfigBoxWithToggleField: FunctionComponent = ({ topRight={ - + Enabled diff --git a/src/core/client/admin/routes/Configure/sections/Auth/FacebookConfig.tsx b/src/core/client/admin/routes/Configure/sections/Auth/FacebookConfig.tsx index f74c6a3a1..21a90f535 100644 --- a/src/core/client/admin/routes/Configure/sections/Auth/FacebookConfig.tsx +++ b/src/core/client/admin/routes/Configure/sections/Auth/FacebookConfig.tsx @@ -1,5 +1,6 @@ import { Localized } from "fluent-react/compat"; import React, { FunctionComponent } from "react"; +import { graphql } from "react-relay"; import { Condition, @@ -17,6 +18,24 @@ import RedirectField from "./RedirectField"; import RegistrationField from "./RegistrationField"; import TargetFilterField from "./TargetFilterField"; +// eslint-disable-next-line no-unused-expressions +graphql` + fragment FacebookConfig_formValues on Auth { + integrations { + facebook { + enabled + allowRegistration + targetFilter { + admin + stream + } + clientID + clientSecret + } + } + } +`; + interface Props { disabled?: boolean; callbackURL: string; @@ -29,7 +48,12 @@ const FacebookLink = () => ( ); const isEnabled: Condition = (value, values) => - Boolean(values.auth.integrations.facebook.enabled); + Boolean( + values.auth && + values.auth.integrations && + values.auth.integrations.facebook && + values.auth.integrations.facebook.enabled + ); const FacebookConfig: FunctionComponent = ({ disabled, diff --git a/src/core/client/admin/routes/Configure/sections/Auth/FacebookConfigContainer.tsx b/src/core/client/admin/routes/Configure/sections/Auth/FacebookConfigContainer.tsx index 7814afd2f..9f559018b 100644 --- a/src/core/client/admin/routes/Configure/sections/Auth/FacebookConfigContainer.tsx +++ b/src/core/client/admin/routes/Configure/sections/Auth/FacebookConfigContainer.tsx @@ -4,54 +4,29 @@ import { graphql } from "react-relay"; import { withFragmentContainer } from "coral-framework/lib/relay"; import { FacebookConfigContainer_auth as AuthData } from "coral-admin/__generated__/FacebookConfigContainer_auth.graphql"; -import { FacebookConfigContainer_authReadOnly as AuthReadOnlyData } from "coral-admin/__generated__/FacebookConfigContainer_authReadOnly.graphql"; -import { OnInitValuesFct } from "./AuthConfigContainer"; import FacebookConfig from "./FacebookConfig"; interface Props { auth: AuthData; - authReadOnly: AuthReadOnlyData; - onInitValues: OnInitValuesFct; disabled?: boolean; } -class FacebookConfigContainer extends React.Component { - constructor(props: Props) { - super(props); - props.onInitValues({ auth: props.auth }); - } - - public render() { - const { disabled, authReadOnly } = this.props; - return ( - - ); - } -} +const FacebookConfigContainer: React.FunctionComponent = ({ + disabled, + auth, +}) => { + return ( + + ); +}; const enhanced = withFragmentContainer({ auth: graphql` fragment FacebookConfigContainer_auth on Auth { - integrations { - facebook { - enabled - allowRegistration - targetFilter { - admin - stream - } - clientID - clientSecret - } - } - } - `, - authReadOnly: graphql` - fragment FacebookConfigContainer_authReadOnly on Auth { integrations { facebook { callbackURL diff --git a/src/core/client/admin/routes/Configure/sections/Auth/GoogleConfig.tsx b/src/core/client/admin/routes/Configure/sections/Auth/GoogleConfig.tsx index 14cb1b359..8704c1bb7 100644 --- a/src/core/client/admin/routes/Configure/sections/Auth/GoogleConfig.tsx +++ b/src/core/client/admin/routes/Configure/sections/Auth/GoogleConfig.tsx @@ -1,5 +1,6 @@ import { Localized } from "fluent-react/compat"; import React, { FunctionComponent } from "react"; +import { graphql } from "react-relay"; import { Condition, @@ -17,6 +18,23 @@ import RedirectField from "./RedirectField"; import RegistrationField from "./RegistrationField"; import TargetFilterField from "./TargetFilterField"; +// eslint-disable-next-line no-unused-expressions +graphql` + fragment GoogleConfig_formValues on Auth { + integrations { + google { + enabled + allowRegistration + targetFilter { + admin + stream + } + clientID + clientSecret + } + } + } +`; interface Props { disabled?: boolean; callbackURL: string; @@ -42,6 +60,7 @@ const GoogleConfig: FunctionComponent = ({ disabled, callbackURL }) => ( } name="auth.integrations.google.enabled" disabled={disabled} + data-testid="configure-auth-google" > {disabledInside => ( <> diff --git a/src/core/client/admin/routes/Configure/sections/Auth/GoogleConfigContainer.tsx b/src/core/client/admin/routes/Configure/sections/Auth/GoogleConfigContainer.tsx index b6d7883f2..efa2185db 100644 --- a/src/core/client/admin/routes/Configure/sections/Auth/GoogleConfigContainer.tsx +++ b/src/core/client/admin/routes/Configure/sections/Auth/GoogleConfigContainer.tsx @@ -4,54 +4,29 @@ import { graphql } from "react-relay"; import { withFragmentContainer } from "coral-framework/lib/relay"; import { GoogleConfigContainer_auth as AuthData } from "coral-admin/__generated__/GoogleConfigContainer_auth.graphql"; -import { GoogleConfigContainer_authReadOnly as AuthReadOnlyData } from "coral-admin/__generated__/GoogleConfigContainer_authReadOnly.graphql"; -import { OnInitValuesFct } from "./AuthConfigContainer"; import GoogleConfig from "./GoogleConfig"; interface Props { auth: AuthData; - authReadOnly: AuthReadOnlyData; - onInitValues: OnInitValuesFct; disabled?: boolean; } -class GoogleConfigContainer extends React.Component { - constructor(props: Props) { - super(props); - props.onInitValues({ auth: props.auth }); - } - - public render() { - const { disabled, authReadOnly } = this.props; - return ( - - ); - } -} +const GoogleConfigContainer: React.FunctionComponent = ({ + disabled, + auth, +}) => { + return ( + + ); +}; const enhanced = withFragmentContainer({ auth: graphql` fragment GoogleConfigContainer_auth on Auth { - integrations { - google { - enabled - allowRegistration - targetFilter { - admin - stream - } - clientID - clientSecret - } - } - } - `, - authReadOnly: graphql` - fragment GoogleConfigContainer_authReadOnly on Auth { integrations { google { callbackURL diff --git a/src/core/client/admin/routes/Configure/sections/Auth/LocalAuthConfig.tsx b/src/core/client/admin/routes/Configure/sections/Auth/LocalAuthConfig.tsx index 8d996bdf4..1d12aafad 100644 --- a/src/core/client/admin/routes/Configure/sections/Auth/LocalAuthConfig.tsx +++ b/src/core/client/admin/routes/Configure/sections/Auth/LocalAuthConfig.tsx @@ -1,11 +1,28 @@ import { Localized } from "fluent-react/compat"; import React, { FunctionComponent } from "react"; +import { graphql } from "react-relay"; import Header from "../../Header"; import ConfigBoxWithToggleField from "./ConfigBoxWithToggleField"; import RegistrationField from "./RegistrationField"; import TargetFilterField from "./TargetFilterField"; +// eslint-disable-next-line no-unused-expressions +graphql` + fragment LocalAuthConfig_formValues on Auth { + integrations { + local { + enabled + allowRegistration + targetFilter { + admin + stream + } + } + } + } +`; + interface Props { disabled?: boolean; } @@ -19,6 +36,7 @@ const LocalAuthConfig: FunctionComponent = ({ disabled }) => ( } name="auth.integrations.local.enabled" disabled={disabled} + data-testid="configure-auth-local" > {disabledInside => ( <> diff --git a/src/core/client/admin/routes/Configure/sections/Auth/LocalAuthConfigContainer.tsx b/src/core/client/admin/routes/Configure/sections/Auth/LocalAuthConfigContainer.tsx deleted file mode 100644 index 889c481b5..000000000 --- a/src/core/client/admin/routes/Configure/sections/Auth/LocalAuthConfigContainer.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React from "react"; -import { graphql } from "react-relay"; - -import { withFragmentContainer } from "coral-framework/lib/relay"; - -import { LocalAuthConfigContainer_auth as AuthData } from "coral-admin/__generated__/LocalAuthConfigContainer_auth.graphql"; - -import { OnInitValuesFct } from "./AuthConfigContainer"; -import LocalAuthConfig from "./LocalAuthConfig"; - -interface Props { - auth: AuthData; - onInitValues: OnInitValuesFct; - disabled?: boolean; -} - -class LocalAuthConfigContainer extends React.Component { - constructor(props: Props) { - super(props); - props.onInitValues({ auth: props.auth }); - } - - public render() { - const { disabled } = this.props; - return ; - } -} - -const enhanced = withFragmentContainer({ - auth: graphql` - fragment LocalAuthConfigContainer_auth on Auth { - integrations { - local { - enabled - allowRegistration - targetFilter { - admin - stream - } - } - } - } - `, -})(LocalAuthConfigContainer); - -export default enhanced; diff --git a/src/core/client/admin/routes/Configure/sections/Auth/OIDCConfig.tsx b/src/core/client/admin/routes/Configure/sections/Auth/OIDCConfig.tsx index e0d78c820..e893a1f51 100644 --- a/src/core/client/admin/routes/Configure/sections/Auth/OIDCConfig.tsx +++ b/src/core/client/admin/routes/Configure/sections/Auth/OIDCConfig.tsx @@ -1,6 +1,7 @@ import { Localized } from "fluent-react/compat"; import React, { FunctionComponent } from "react"; import { Field } from "react-final-form"; +import { graphql } from "react-relay"; import { colorFromMeta, parseEmptyAsNull } from "coral-framework/lib/form"; import { @@ -33,6 +34,29 @@ import RedirectField from "./RedirectField"; import RegistrationField from "./RegistrationField"; import TargetFilterField from "./TargetFilterField"; +// eslint-disable-next-line no-unused-expressions +graphql` + fragment OIDCConfig_formValues on Auth { + integrations { + oidc { + enabled + allowRegistration + targetFilter { + admin + stream + } + name + clientID + clientSecret + authorizationURL + tokenURL + jwksURI + issuer + } + } + } +`; + interface Props { disabled?: boolean; callbackURL: string; @@ -76,7 +100,9 @@ const OIDCConfig: FunctionComponent = ({ - + @@ -94,6 +120,8 @@ const OIDCConfig: FunctionComponent = ({ > {({ input, meta }) => ( = ({ color={colorFromMeta(meta)} fullWidth meta={meta} - {...input} /> )} @@ -120,7 +147,7 @@ const OIDCConfig: FunctionComponent = ({ - + @@ -139,6 +166,8 @@ const OIDCConfig: FunctionComponent = ({ <> = ({ spellCheck={false} color={colorFromMeta(meta)} fullWidth - {...input} />