diff --git a/webapp/.babelrc b/webapp/.babelrc deleted file mode 100644 index 3c45d7307c9..00000000000 --- a/webapp/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "es2015", - "react", - "stage-0" - ] -} diff --git a/webapp/.eslintrc.json b/webapp/.eslintrc.json deleted file mode 100644 index b5368215372..00000000000 --- a/webapp/.eslintrc.json +++ /dev/null @@ -1,273 +0,0 @@ -{ - "extends": "eslint:recommended", - "parserOptions": { - "ecmaVersion": 8, - "sourceType": "module", - "ecmaFeatures": { - "jsx": true, - "impliedStrict": true, - "modules": true, - "experimentalObjectRestSpread": true - } - }, - "parser": "babel-eslint", - "plugins": [ - "react" - ], - "env": { - "browser": true, - "node": true, - "jquery": true, - "es6": true - }, - "globals": { - "jest": true, - "describe": true, - "it": true, - "expect": true, - "before": true, - "after": true - }, - "rules": { - "array-bracket-spacing": [2, "never"], - "array-callback-return": 2, - "arrow-body-style": 0, - "arrow-parens": [2, "always"], - "arrow-spacing": [2, { "before": true, "after": true }], - "block-scoped-var": 2, - "brace-style": [2, "1tbs", { "allowSingleLine": false }], - "camelcase": [2, {"properties": "never"}], - "capitalized-comments": 0, - "class-methods-use-this": 1, - "comma-dangle": [2, "never"], - "comma-spacing": [2, {"before": false, "after": true}], - "comma-style": [2, "last"], - "complexity": [1, 10], - "computed-property-spacing": [2, "never"], - "consistent-return": 2, - "consistent-this": [2, "self"], - "constructor-super": 2, - "curly": [2, "all"], - "dot-location": [2, "object"], - "dot-notation": 2, - "eqeqeq": [2, "smart"], - "func-call-spacing": [2, "never"], - "func-name-matching": 0, - "func-names": 2, - "func-style": [2, "declaration"], - "generator-star-spacing": [2, {"before": false, "after": true}], - "global-require": 2, - "guard-for-in": 2, - "id-blacklist": 0, - "indent": [2, 4, {"SwitchCase": 0}], - "jsx-quotes": [2, "prefer-single"], - "key-spacing": [2, {"beforeColon": false, "afterColon": true, "mode": "strict"}], - "keyword-spacing": [2, {"before": true, "after": true, "overrides": {}}], - "line-comment-position": 0, - "linebreak-style": 2, - "lines-around-comment": [2, { "beforeBlockComment": true, "beforeLineComment": true, "allowBlockStart": true, "allowBlockEnd": true }], - "max-lines": [1, {"max": 450, "skipBlankLines": true, "skipComments": false}], - "max-nested-callbacks": [1, {"max":1}], - "max-nested-callbacks": [2, {"max":2}], - "max-statements-per-line": [2, {"max": 1}], - "multiline-ternary": [1, "never"], - "new-cap": 2, - "new-parens": 2, - "newline-before-return": 0, - "newline-per-chained-call": 0, - "no-alert": 2, - "no-array-constructor": 2, - "no-await-in-loop": 2, - "no-caller": 2, - "no-case-declarations": 2, - "no-class-assign": 2, - "no-compare-neg-zero": 2, - "no-cond-assign": [2, "except-parens"], - "no-confusing-arrow": 2, - "no-console": 2, - "no-const-assign": 2, - "no-constant-condition": 2, - "no-debugger": 2, - "no-div-regex": 2, - "no-dupe-args": 2, - "no-dupe-class-members": 2, - "no-dupe-keys": 2, - "no-duplicate-case": 2, - "no-duplicate-imports": [2, {"includeExports": true}], - "no-else-return": 2, - "no-empty": 2, - "no-empty-function": 2, - "no-empty-pattern": 2, - "no-eval": 2, - "no-ex-assign": 2, - "no-extend-native": 2, - "no-extra-bind": 2, - "no-extra-label": 2, - "no-extra-parens": 0, - "no-extra-semi": 2, - "no-fallthrough": 2, - "no-floating-decimal": 2, - "no-func-assign": 2, - "no-global-assign": 2, - "no-implicit-coercion": 2, - "no-implicit-globals": 0, - "no-implied-eval": 2, - "no-inner-declarations": 0, - "no-invalid-regexp": 2, - "no-irregular-whitespace": 2, - "no-iterator": 2, - "no-labels": 2, - "no-lone-blocks": 2, - "no-lonely-if": 2, - "no-loop-func": 2, - "no-magic-numbers": [1, { "ignore": [-1, 0, 1, 2], "enforceConst": true, "detectObjects": true } ], - "no-mixed-operators": [2, {"allowSamePrecedence": false}], - "no-mixed-spaces-and-tabs": 2, - "no-multi-assign": 2, - "no-multi-spaces": [2, { "exceptions": { "Property": false } }], - "no-multi-str": 0, - "no-multiple-empty-lines": [2, {"max": 1}], - "no-native-reassign": 2, - "no-negated-condition": 2, - "no-nested-ternary": 2, - "no-new": 2, - "no-new-func": 2, - "no-new-object": 2, - "no-new-symbol": 2, - "no-new-wrappers": 2, - "no-octal-escape": 2, - "no-param-reassign": 2, - "no-process-env": 2, - "no-process-exit": 2, - "no-proto": 2, - "no-redeclare": 2, - "no-return-assign": [2, "always"], - "no-return-await": 2, - "no-script-url": 2, - "no-self-assign": [2, {"props": true}], - "no-self-compare": 2, - "no-sequences": 2, - "no-shadow": [2, {"hoist": "functions"}], - "no-shadow-restricted-names": 2, - "no-spaced-func": 2, - "no-tabs": 0, - "no-template-curly-in-string": 2, - "no-ternary": 0, - "no-this-before-super": 2, - "no-throw-literal": 2, - "no-trailing-spaces": [2, { "skipBlankLines": false }], - "no-undef-init": 2, - "no-undefined": 2, - "no-underscore-dangle": 2, - "no-unexpected-multiline": 2, - "no-unmodified-loop-condition": 2, - "no-unneeded-ternary": [2, {"defaultAssignment": false}], - "no-unreachable": 2, - "no-unsafe-finally": 2, - "no-unsafe-negation": 2, - "no-unused-expressions": 2, - "no-unused-vars": [2, {"vars": "all", "args": "after-used"}], - "no-use-before-define": [2, "nofunc"], - "no-useless-computed-key": 2, - "no-useless-concat": 2, - "no-useless-constructor": 2, - "no-useless-escape": 2, - "no-useless-rename": 2, - "no-useless-return": 2, - "no-var": 0, - "no-void": 2, - "no-warning-comments": 1, - "no-whitespace-before-property": 2, - "no-with": 2, - "object-curly-newline": 0, - "object-curly-spacing": [2, "never"], - "object-property-newline": [2, {"allowMultiplePropertiesPerLine": true}], - "object-shorthand": [2, "always"], - "one-var": [2, "never"], - "one-var-declaration-per-line": 0, - "operator-assignment": [2, "always"], - "operator-linebreak": [2, "after"], - "padded-blocks": [2, "never"], - "prefer-arrow-callback": 2, - "prefer-const": 2, - "prefer-destructuring": 0, - "prefer-numeric-literals": 2, - "prefer-promise-reject-errors": 2, - "prefer-rest-params": 2, - "prefer-spread": 2, - "prefer-template": 0, - "quote-props": [2, "as-needed"], - "quotes": [2, "single", "avoid-escape"], - "radix": 2, - "react/display-name": [2, { "ignoreTranspilerName": false }], - "react/forbid-component-props": 0, - "react/forbid-elements": [2, { "forbid": ["embed"] }], - "react/jsx-boolean-value": [2, "always"], - "react/jsx-closing-bracket-location": [2, { "location": "tag-aligned" }], - "react/jsx-curly-spacing": [2, "never"], - "react/jsx-equals-spacing": [2, "never"], - "react/jsx-filename-extension": 2, - "react/jsx-first-prop-new-line": [2, "multiline"], - "react/jsx-handler-names": 0, - "react/jsx-indent": [2, 4], - "react/jsx-indent-props": [2, 4], - "react/jsx-key": 2, - "react/jsx-max-props-per-line": [2, { "maximum": 1 }], - "react/jsx-no-bind": 0, - "react/jsx-no-comment-textnodes": 2, - "react/jsx-no-duplicate-props": [2, { "ignoreCase": false }], - "react/jsx-no-literals": 2, - "react/jsx-no-target-blank": 2, - "react/jsx-no-undef": 2, - "react/jsx-pascal-case": 2, - "react/jsx-space-before-closing": [2, "never"], - "react/jsx-tag-spacing": [2, { "closingSlash": "never", "beforeSelfClosing": "never", "afterOpening": "never" }], - "react/jsx-uses-react": 2, - "react/jsx-uses-vars": 2, - "react/jsx-wrap-multilines": 2, - "react/no-array-index-key": 1, - "react/no-children-prop": 2, - "react/no-danger": 0, - "react/no-danger-with-children": 2, - "react/no-deprecated": 2, - "react/no-did-mount-set-state": 2, - "react/no-did-update-set-state": 2, - "react/no-direct-mutation-state": 2, - "react/no-find-dom-node": 1, - "react/no-is-mounted": 2, - "react/no-multi-comp": [2, { "ignoreStateless": true }], - "react/no-render-return-value": 2, - "react/no-set-state": 0, - "react/no-string-refs": 0, - "react/no-unescaped-entities": 2, - "react/no-unknown-property": 2, - "react/no-unused-prop-types": [1, {"skipShapeProps": true}], - "react/prefer-es6-class": 2, - "react/prefer-stateless-function": 0, - "react/prop-types": 2, - "react/require-default-props": 0, - "react/require-optimization": 1, - "react/require-render-return": 2, - "react/self-closing-comp": 2, - "react/sort-comp": 0, - "react/style-prop-object": 2, - "require-yield": 2, - "rest-spread-spacing": [2, "never"], - "semi": [2, "always"], - "semi-spacing": [2, {"before": false, "after": true}], - "sort-imports": 0, - "sort-keys": 0, - "space-before-blocks": [2, "always"], - "space-before-function-paren": [2, {"anonymous": "never", "named": "never", "asyncArrow": "always"}], - "space-in-parens": [2, "never"], - "space-infix-ops": 2, - "space-unary-ops": [2, { "words": true, "nonwords": false }], - "symbol-description": 2, - "template-curly-spacing": [2, "never"], - "valid-typeof": [2, {"requireStringLiterals": false}], - "vars-on-top": 0, - "wrap-iife": [2, "outside"], - "wrap-regex": 2, - "yoda": [2, "never", {"exceptRange": false, "onlyEquality": false}] - } -} diff --git a/webapp/Makefile b/webapp/Makefile deleted file mode 100644 index 8bb7a83d14f..00000000000 --- a/webapp/Makefile +++ /dev/null @@ -1,59 +0,0 @@ -.PHONY: build test run clean stop check-style run-unit emojis - -BUILD_SERVER_DIR = .. - -check-style: .yarninstall - @echo Checking for style guide compliance - - yarn run check - -test: .yarninstall - cd $(BUILD_SERVER_DIR) && $(MAKE) internal-test-web-client - -.yarninstall: package.json - @echo Getting dependencies using yarn - - yarn install - - touch $@ - -build: .yarninstall - @echo Building mattermost Webapp - - rm -rf dist - - yarn run build - -run: .yarninstall - @echo Running mattermost Webapp for development - - yarn run run & - -run-fullmap: .yarninstall - @echo FULL SOURCE MAP Running mattermost Webapp for development FULL SOURCE MAP - - yarn run run-fullmap & - -stop: - @echo Stopping changes watching - -ifeq ($(OS),Windows_NT) - wmic process where "Caption='node.exe' and CommandLine like '%webpack%'" call terminate -else - @for PROCID in $$(ps -ef | grep "[n]ode.*[w]ebpack" | awk '{ print $$2 }'); do \ - echo stopping webpack watch $$PROCID; \ - kill $$PROCID; \ - done -endif - -clean: - @echo Cleaning Webapp - - yarn cache clean - - rm -rf dist - rm -rf node_modules - rm -f .yarninstall - -emojis: - ./make-emojis diff --git a/webapp/actions/admin_actions.jsx b/webapp/actions/admin_actions.jsx deleted file mode 100644 index 4dd0f848ffa..00000000000 --- a/webapp/actions/admin_actions.jsx +++ /dev/null @@ -1,397 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {clientLogout} from 'actions/global_actions.jsx'; - -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import * as AdminActions from 'mattermost-redux/actions/admin'; -import * as UserActions from 'mattermost-redux/actions/users'; -import {Client4} from 'mattermost-redux/client'; - -export function saveConfig(config, success, error) { - AdminActions.updateConfig(config)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.updateConfig.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function reloadConfig(success, error) { - AdminActions.reloadConfig()(dispatch, getState).then( - (data) => { - if (data && success) { - AdminActions.getConfig()(dispatch, getState); - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.reloadConfig.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function adminResetMfa(userId, success, error) { - UserActions.updateUserMfa(userId, false)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateUser.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function getClusterStatus(success, error) { - AdminActions.getClusterStatus()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.getClusterStatus.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function testEmail(config, success, error) { - AdminActions.testEmail(config)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.testEmail.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function ldapTest(success, error) { - AdminActions.testLdap()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.testLdap.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function invalidateAllCaches(success, error) { - AdminActions.invalidateCaches()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.invalidateCaches.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function recycleDatabaseConnection(success, error) { - AdminActions.recycleDatabase()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.recycleDatabase.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function adminResetPassword(userId, password, success, error) { - UserActions.updateUserPassword(userId, '', password)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateUser.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function samlCertificateStatus(success, error) { - AdminActions.getSamlCertificateStatus()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.getSamlCertificateStatus.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function ldapSyncNow(success, error) { - AdminActions.syncLdap()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.syncLdap.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function getOAuthAppInfo(clientId, success, error) { - Client4.getOAuthAppInfo(clientId).then( - (data) => { - if (success) { - success(data); - } - } - ).catch( - (err) => { - if (error) { - error(err); - } - } - ); -} - -export function allowOAuth2(params, success, error) { - const responseType = params.response_type; - const clientId = params.client_id; - const redirectUri = params.redirect_uri; - const state = params.state; - const scope = params.scope; - - Client4.authorizeOAuthApp(responseType, clientId, redirectUri, state, scope).then( - (data) => { - if (success) { - success(data); - } - } - ).catch( - (err) => { - if (error) { - error(err); - } - } - ); -} - -export function emailToLdap(loginId, password, token, ldapId, ldapPassword, success, error) { - UserActions.switchEmailToLdap(loginId, password, ldapId, ldapPassword, token)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.switchLogin.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function emailToOAuth(loginId, password, token, newType, success, error) { - UserActions.switchEmailToOAuth(newType, loginId, password, token)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.switchLogin.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function oauthToEmail(currentService, email, password, success, error) { - UserActions.switchOAuthToEmail(currentService, email, password)(dispatch, getState).then( - (data) => { - if (data) { - if (data.follow_link) { - clientLogout(data.follow_link); - } - if (success) { - success(data); - } - } else if (data == null && error) { - const serverError = getState().requests.users.switchLogin.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function uploadBrandImage(brandImage, success, error) { - AdminActions.uploadBrandImage(brandImage)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.uploadBrandImage.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function uploadLicenseFile(file, success, error) { - AdminActions.uploadLicense(file)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.uploadLicense.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function removeLicenseFile(success, error) { - AdminActions.removeLicense()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.removeLicense.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function uploadPublicSamlCertificate(file, success, error) { - AdminActions.uploadPublicSamlCertificate(file)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.uploadPublicSamlCertificate.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function uploadPrivateSamlCertificate(file, success, error) { - AdminActions.uploadPrivateSamlCertificate(file)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.uploadPrivateSamlCertificate.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function uploadIdpSamlCertificate(file, success, error) { - AdminActions.uploadIdpSamlCertificate(file)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.uploadIdpSamlCertificate.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function removePublicSamlCertificate(success, error) { - AdminActions.removePublicSamlCertificate()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.removePublicSamlCertificate.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function removePrivateSamlCertificate(success, error) { - AdminActions.removePrivateSamlCertificate()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.removePrivateSamlCertificate.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function removeIdpSamlCertificate(success, error) { - AdminActions.removeIdpSamlCertificate()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.removeIdpSamlCertificate.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function getStandardAnalytics(teamId) { - AdminActions.getStandardAnalytics(teamId)(dispatch, getState); -} - -export function getAdvancedAnalytics(teamId) { - AdminActions.getAdvancedAnalytics(teamId)(dispatch, getState); -} - -export function getPostsPerDayAnalytics(teamId) { - AdminActions.getPostsPerDayAnalytics(teamId)(dispatch, getState); -} - -export function getUsersPerDayAnalytics(teamId) { - AdminActions.getUsersPerDayAnalytics(teamId)(dispatch, getState); -} - -export function elasticsearchTest(config, success, error) { - AdminActions.testElasticsearch(config)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.testElasticsearch.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function elasticsearchPurgeIndexes(success, error) { - AdminActions.purgeElasticsearchIndexes()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.purgeElasticsearchIndexes.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} diff --git a/webapp/actions/channel_actions.jsx b/webapp/actions/channel_actions.jsx deleted file mode 100644 index 1df0d12f5cd..00000000000 --- a/webapp/actions/channel_actions.jsx +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import TeamStore from 'stores/team_store.jsx'; -import UserStore from 'stores/user_store.jsx'; -import ChannelStore from 'stores/channel_store.jsx'; -import * as ChannelUtils from 'utils/channel_utils.jsx'; -import PreferenceStore from 'stores/preference_store.jsx'; - -import * as GlobalActions from 'actions/global_actions.jsx'; -import * as PostActions from 'actions/post_actions.jsx'; - -import {loadProfilesForSidebar, loadNewDMIfNeeded, loadNewGMIfNeeded} from 'actions/user_actions.jsx'; -import {trackEvent} from 'actions/diagnostics_actions.jsx'; - -import * as UserAgent from 'utils/user_agent.jsx'; -import * as Utils from 'utils/utils.jsx'; -import {Constants, Preferences} from 'utils/constants.jsx'; - -import {browserHistory} from 'react-router/es6'; - -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import * as ChannelActions from 'mattermost-redux/actions/channels'; -import {savePreferences, deletePreferences} from 'mattermost-redux/actions/preferences'; -import {Client4} from 'mattermost-redux/client'; - -import {getMyChannelMemberships} from 'mattermost-redux/selectors/entities/channels'; - -export function goToChannel(channel) { - if (channel.fake) { - const user = UserStore.getProfileByUsername(channel.display_name); - if (!user) { - return; - } - openDirectChannelToUser( - user.id, - () => { - browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/channels/' + channel.name); - }, - null - ); - } else { - browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/channels/' + channel.name); - } -} - -export function executeCommand(message, args, success, error) { - let msg = message; - - let cmdLength = msg.indexOf(' '); - if (cmdLength < 0) { - cmdLength = msg.length; - } - const cmd = msg.substring(0, cmdLength).toLowerCase(); - msg = cmd + msg.substring(cmdLength, msg.length); - - switch (cmd) { - case '/search': - PostActions.searchForTerm(msg.substring(cmdLength + 1, msg.length)); - return; - case '/shortcuts': - if (UserAgent.isMobile()) { - const err = {message: Utils.localizeMessage('create_post.shortcutsNotSupported', 'Keyboard shortcuts are not supported on your device')}; - error(err); - return; - } - - GlobalActions.showShortcutsModal(); - return; - case '/leave': { - // /leave command not supported in reply threads. - if (args.channel_id && (args.root_id || args.parent_id)) { - GlobalActions.sendEphemeralPost('/leave is not supported in reply threads. Use it in the center channel instead.', args.channel_id, args.parent_id); - return; - } - const channel = ChannelStore.getCurrent(); - if (channel.type === Constants.PRIVATE_CHANNEL) { - GlobalActions.showLeavePrivateChannelModal(channel); - return; - } else if ( - channel.type === Constants.DM_CHANNEL || - channel.type === Constants.GM_CHANNEL - ) { - let name; - let category; - if (channel.type === Constants.DM_CHANNEL) { - name = Utils.getUserIdFromChannelName(channel); - category = Constants.Preferences.CATEGORY_DIRECT_CHANNEL_SHOW; - } else { - name = channel.id; - category = Constants.Preferences.CATEGORY_GROUP_CHANNEL_SHOW; - } - const currentUserId = UserStore.getCurrentId(); - savePreferences(currentUserId, [{category, name, user_id: currentUserId, value: 'false'}])(dispatch, getState); - if (ChannelUtils.isFavoriteChannel(channel)) { - unmarkFavorite(channel.id); - } - browserHistory.push(`${TeamStore.getCurrentTeamRelativeUrl()}/channels/town-square`); - return; - } - break; - } - case '/settings': - GlobalActions.showAccountSettingsModal(); - return; - } - - Client4.executeCommand(msg, args).then(success).catch( - (err) => { - if (error) { - error(err); - } - } - ); -} - -export function setChannelAsRead(channelIdParam) { - const channelId = channelIdParam || ChannelStore.getCurrentId(); - ChannelActions.viewChannel(channelId)(dispatch, getState); - ChannelStore.resetCounts([channelId]); - ChannelStore.emitChange(); - if (channelId === ChannelStore.getCurrentId()) { - ChannelStore.emitLastViewed(Number.MAX_VALUE, false); - } -} - -export function addUserToChannel(channelId, userId, success, error) { - ChannelActions.addChannelMember(channelId, userId)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.addChannelMember.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function removeUserFromChannel(channelId, userId, success, error) { - ChannelActions.removeChannelMember(channelId, userId)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.removeChannelMember.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function makeUserChannelAdmin(channelId, userId, success, error) { - ChannelActions.updateChannelMemberRoles(channelId, userId, 'channel_user channel_admin')(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.updateChannelMember.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function makeUserChannelMember(channelId, userId, success, error) { - ChannelActions.updateChannelMemberRoles(channelId, userId, 'channel_user')(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.updateChannelMember.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function openDirectChannelToUser(userId, success, error) { - const channelName = Utils.getDirectChannelName(UserStore.getCurrentId(), userId); - const channel = ChannelStore.getByName(channelName); - - if (channel) { - trackEvent('api', 'api_channels_join_direct'); - PreferenceStore.setPreference(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, userId, 'true'); - loadProfilesForSidebar(); - - const currentUserId = UserStore.getCurrentId(); - savePreferences(currentUserId, [{user_id: currentUserId, category: Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, name: userId, value: 'true'}])(dispatch, getState); - - if (success) { - success(channel, true); - } - - return; - } - - ChannelActions.createDirectChannel(UserStore.getCurrentId(), userId)(dispatch, getState).then( - (result) => { - loadProfilesForSidebar(); - if (result.data && success) { - success(result.data, false); - } else if (result.error && error) { - error({id: result.error.server_error_id, ...result.error}); - } - } - ); -} - -export function openGroupChannelToUsers(userIds, success, error) { - ChannelActions.createGroupChannel(userIds)(dispatch, getState).then( - (result) => { - loadProfilesForSidebar(); - if (result.data && success) { - success(result.data, false); - } else if (result.error && error) { - browserHistory.push(TeamStore.getCurrentTeamUrl()); - error({id: result.error.server_error_id, ...result.error}); - } - } - ); -} - -export function markFavorite(channelId) { - trackEvent('api', 'api_channels_favorited'); - const currentUserId = UserStore.getCurrentId(); - savePreferences(currentUserId, [{user_id: currentUserId, category: Preferences.CATEGORY_FAVORITE_CHANNEL, name: channelId, value: 'true'}])(dispatch, getState); -} - -export function unmarkFavorite(channelId) { - trackEvent('api', 'api_channels_unfavorited'); - const currentUserId = UserStore.getCurrentId(); - - const pref = { - user_id: currentUserId, - category: Preferences.CATEGORY_FAVORITE_CHANNEL, - name: channelId - }; - - deletePreferences(currentUserId, [pref])(dispatch, getState); -} - -export function loadChannelsForCurrentUser() { - ChannelActions.fetchMyChannelsAndMembers(TeamStore.getCurrentId())(dispatch, getState).then( - () => { - loadDMsAndGMsForUnreads(); - } - ); -} - -export function loadDMsAndGMsForUnreads() { - const unreads = ChannelStore.getUnreadCounts(); - for (const id in unreads) { - if (!unreads.hasOwnProperty(id)) { - continue; - } - - if (unreads[id].msgs > 0 || unreads[id].mentions > 0) { - const channel = ChannelStore.get(id); - if (channel && channel.type === Constants.DM_CHANNEL) { - loadNewDMIfNeeded(channel.id); - } else if (channel && channel.type === Constants.GM_CHANNEL) { - loadNewGMIfNeeded(channel.id); - } - } - } -} - -export async function joinChannel(channel, success, error) { - const {data, serverError} = await ChannelActions.joinChannel(UserStore.getCurrentId(), null, channel.id)(dispatch, getState); - - if (data && success) { - success(data); - } else if (data == null && error) { - error({id: serverError.server_error_id, ...serverError}); - } -} - -export function updateChannel(channel, success, error) { - ChannelActions.updateChannel(channel)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.updateChannel.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function searchMoreChannels(term, success, error) { - ChannelActions.searchChannels(TeamStore.getCurrentId(), term)(dispatch, getState).then( - (data) => { - if (data && success) { - const myMembers = getMyChannelMemberships(getState()); - const channels = data.filter((c) => !myMembers[c.id]); - success(channels); - } else if (data == null && error) { - const serverError = getState().requests.channels.getChannels.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function autocompleteChannels(term, success, error) { - ChannelActions.searchChannels(TeamStore.getCurrentId(), term)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.getChannels.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updateChannelNotifyProps(data, options, success, error) { - ChannelActions.updateChannelNotifyProps(data.user_id, data.channel_id, Object.assign({}, data, options))(dispatch, getState).then( - (result) => { - if (result && success) { - success(result); - } else if (result == null && error) { - const serverError = getState().requests.channels.updateChannelNotifyProps.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function createChannel(channel, success, error) { - ChannelActions.createChannel(channel)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.createChannel.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updateChannelPurpose(channelId, purpose, success, error) { - ChannelActions.patchChannel(channelId, {purpose})(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.updateChannel.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updateChannelHeader(channelId, header, success, error) { - ChannelActions.patchChannel(channelId, {header})(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.updateChannel.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function getChannelMembersForUserIds(channelId, userIds, success, error) { - ChannelActions.getChannelMembersByIds(channelId, userIds)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.members.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function leaveChannel(channelId, success) { - ChannelActions.leaveChannel(channelId)(dispatch, getState).then( - () => { - if (ChannelUtils.isFavoriteChannelId(channelId)) { - unmarkFavorite(channelId); - } - - const townsquare = ChannelStore.getByName('town-square'); - browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/channels/' + townsquare.name); - - if (success) { - success(); - } - } - ); -} - -export async function deleteChannel(channelId, success, error) { - const {data, serverError} = await ChannelActions.deleteChannel(channelId)(dispatch, getState); - - if (data && success) { - success(data); - } else if (serverError && error) { - error({id: serverError.server_error_id, ...serverError}); - } -} diff --git a/webapp/actions/diagnostics_actions.jsx b/webapp/actions/diagnostics_actions.jsx deleted file mode 100644 index 72cf387b4e0..00000000000 --- a/webapp/actions/diagnostics_actions.jsx +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import UserStore from 'stores/user_store.jsx'; - -export function trackEvent(category, event, props) { - if (global.window && global.window.analytics) { - const properties = Object.assign({category, type: event, user_actual_id: UserStore.getCurrentId()}, props); - const options = { - context: { - ip: '0.0.0.0' - }, - page: { - path: '', - referrer: '', - search: '', - title: '', - url: '' - }, - anonymousId: '00000000000000000000000000' - }; - global.window.analytics.track('event', properties, options); - } -} diff --git a/webapp/actions/emoji_actions.jsx b/webapp/actions/emoji_actions.jsx deleted file mode 100644 index 1c0d8b5ea41..00000000000 --- a/webapp/actions/emoji_actions.jsx +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import UserStore from 'stores/user_store.jsx'; - -import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; -import {ActionTypes} from 'utils/constants.jsx'; - -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; -import {getProfilesByIds} from 'mattermost-redux/actions/users'; -import * as EmojiActions from 'mattermost-redux/actions/emojis'; - -export async function loadEmoji(getProfiles = true) { - const data = await EmojiActions.getAllCustomEmojis()(dispatch, getState); - - if (data && getProfiles) { - loadProfilesForEmoji(data); - } -} - -function loadProfilesForEmoji(emojiList) { - const profilesToLoad = {}; - for (let i = 0; i < emojiList.length; i++) { - const emoji = emojiList[i]; - if (!UserStore.hasProfile(emoji.creator_id)) { - profilesToLoad[emoji.creator_id] = true; - } - } - - const list = Object.keys(profilesToLoad); - if (list.length === 0) { - return; - } - - getProfilesByIds(list)(dispatch, getState); -} - -export function addEmoji(emoji, image, success, error) { - EmojiActions.createCustomEmoji(emoji, image)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.emojis.createCustomEmoji.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function deleteEmoji(emojiId, success, error) { - EmojiActions.deleteCustomEmoji(emojiId)(dispatch, getState).then( - (data) => { - if (data) { - // Needed to remove recently used emoji - AppDispatcher.handleServerAction({ - type: ActionTypes.REMOVED_CUSTOM_EMOJI, - id: emojiId - }); - - if (success) { - success(data); - } - } else if (data == null && error) { - const serverError = getState().requests.emojis.deleteCustomEmoji.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} diff --git a/webapp/actions/file_actions.jsx b/webapp/actions/file_actions.jsx deleted file mode 100644 index 1d9617901f0..00000000000 --- a/webapp/actions/file_actions.jsx +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {batchActions} from 'redux-batched-actions'; -import request from 'superagent'; - -import store from 'stores/redux_store.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -import {FileTypes} from 'mattermost-redux/action_types'; -import {forceLogoutIfNecessary} from 'mattermost-redux/actions/helpers'; -import {getLogErrorAction} from 'mattermost-redux/actions/errors'; -import {Client4} from 'mattermost-redux/client'; - -export function uploadFile(file, name, channelId, clientId, successCallback, errorCallback) { - const {dispatch, getState} = store; - - function handleResponse(err, res) { - if (err) { - let e; - if (res && res.body && res.body.id) { - e = res.body; - } else if (err.status === 0 || !err.status) { - e = {message: Utils.localizeMessage('channel_loader.connection_error', 'There appears to be a problem with your internet connection.')}; - } else { - e = {message: Utils.localizeMessage('channel_loader.unknown_error', 'We received an unexpected status code from the server.') + ' (' + err.status + ')'}; - } - - forceLogoutIfNecessary(err, dispatch); - - const failure = { - type: FileTypes.UPLOAD_FILES_FAILURE, - clientIds: [clientId], - channelId, - rootId: null, - error: err - }; - - dispatch(batchActions([failure, getLogErrorAction(err)]), getState); - - if (errorCallback) { - errorCallback(e, err, res); - } - } else if (res) { - const data = res.body.file_infos.map((fileInfo, index) => { - return { - ...fileInfo, - clientId: res.body.client_ids[index] - }; - }); - - dispatch(batchActions([ - { - type: FileTypes.RECEIVED_UPLOAD_FILES, - data, - channelId, - rootId: null - }, - { - type: FileTypes.UPLOAD_FILES_SUCCESS - } - ]), getState); - - if (successCallback) { - successCallback(res.body, res); - } - } - } - - dispatch({type: FileTypes.UPLOAD_FILES_REQUEST}, getState); - - return request. - post(Client4.getFilesRoute()). - set(Client4.getOptions().headers). - attach('files', file, name). - field('channel_id', channelId). - field('client_ids', clientId). - accept('application/json'). - end(handleResponse); -} - -export async function getPublicLink(fileId, success) { - Client4.getFilePublicLink(fileId).then( - (data) => { - if (data && success) { - success(data.link); - } - } - ).catch( - () => {} //eslint-disable-line no-empty-function - ); -} diff --git a/webapp/actions/global_actions.jsx b/webapp/actions/global_actions.jsx deleted file mode 100644 index 73a57e0b0d9..00000000000 --- a/webapp/actions/global_actions.jsx +++ /dev/null @@ -1,626 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; - -import ChannelStore from 'stores/channel_store.jsx'; -import UserStore from 'stores/user_store.jsx'; -import BrowserStore from 'stores/browser_store.jsx'; -import ErrorStore from 'stores/error_store.jsx'; -import TeamStore from 'stores/team_store.jsx'; -import SearchStore from 'stores/search_store.jsx'; - -import {handleNewPost} from 'actions/post_actions.jsx'; -import {loadProfilesForSidebar, loadNewDMIfNeeded, loadNewGMIfNeeded} from 'actions/user_actions.jsx'; -import {loadChannelsForCurrentUser} from 'actions/channel_actions.jsx'; -import {stopPeriodicStatusUpdates} from 'actions/status_actions.jsx'; -import * as WebsocketActions from 'actions/websocket_actions.jsx'; -import {trackEvent} from 'actions/diagnostics_actions.jsx'; - -import {ActionTypes, Constants, ErrorPageTypes} from 'utils/constants.jsx'; -import EventTypes from 'utils/event_types.jsx'; - -import WebSocketClient from 'client/web_websocket_client.jsx'; -import {sortTeamsByDisplayName} from 'utils/team_utils.jsx'; -import * as Utils from 'utils/utils.jsx'; - -import en from 'i18n/en.json'; -import * as I18n from 'i18n/i18n.jsx'; -import {browserHistory} from 'react-router/es6'; - -// Redux actions -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import {Client4} from 'mattermost-redux/client'; - -import {removeUserFromTeam} from 'mattermost-redux/actions/teams'; -import {viewChannel, getChannelStats, getMyChannelMember, getChannelAndMyMember, createDirectChannel, joinChannel} from 'mattermost-redux/actions/channels'; -import {getPostThread} from 'mattermost-redux/actions/posts'; - -export function emitChannelClickEvent(channel) { - function userVisitedFakeChannel(chan, success, fail) { - const currentUserId = UserStore.getCurrentId(); - const otherUserId = Utils.getUserIdFromChannelName(chan); - createDirectChannel(currentUserId, otherUserId)(dispatch, getState).then( - (result) => { - const receivedChannel = result.data; - - if (receivedChannel) { - success(receivedChannel); - } else { - fail(); - } - } - ); - } - function switchToChannel(chan) { - const channelMember = ChannelStore.getMyMember(chan.id); - const getMyChannelMemberPromise = getMyChannelMember(chan.id)(dispatch, getState); - const oldChannelId = ChannelStore.getCurrentId(); - - getMyChannelMemberPromise.then(() => { - getChannelStats(chan.id)(dispatch, getState); - viewChannel(chan.id, oldChannelId)(dispatch, getState); - - // Mark previous and next channel as read - ChannelStore.resetCounts([chan.id, oldChannelId]); - reloadIfServerVersionChanged(); - }); - - // Subtract mentions for the team - const {msgs, mentions} = ChannelStore.getUnreadCounts()[chan.id] || {msgs: 0, mentions: 0}; - TeamStore.subtractUnread(chan.team_id, msgs, mentions); - - BrowserStore.setGlobalItem(chan.team_id, chan.id); - - loadProfilesForSidebar(); - - AppDispatcher.handleViewAction({ - type: ActionTypes.CLICK_CHANNEL, - name: chan.name, - id: chan.id, - team_id: chan.team_id, - total_msg_count: chan.total_msg_count, - channelMember, - prev: oldChannelId - }); - } - - if (channel.fake) { - userVisitedFakeChannel( - channel, - (data) => { - switchToChannel(data); - }, - () => { - browserHistory.push('/' + this.state.currentTeam.name); - } - ); - } else { - switchToChannel(channel); - } -} - -export async function doFocusPost(channelId, postId, data) { - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_FOCUSED_POST, - postId, - channelId, - post_list: data - }); - - dispatch({ - type: ActionTypes.RECEIVED_FOCUSED_POST, - data: postId, - channelId - }); - - const member = getState().entities.channels.myMembers[channelId]; - if (member == null) { - await joinChannel(UserStore.getCurrentId(), null, channelId)(dispatch, getState); - } - - loadChannelsForCurrentUser(); - getChannelStats(channelId)(dispatch, getState); -} - -export function emitPostFocusEvent(postId, onSuccess) { - loadChannelsForCurrentUser(); - getPostThread(postId)(dispatch, getState).then( - (data) => { - if (data) { - const channelId = data.posts[data.order[0]].channel_id; - const channel = ChannelStore.getChannelById(channelId); - if (channel && channel.type === Constants.DM_CHANNEL) { - loadNewDMIfNeeded(channel.id); - } else if (channel && channel.type === Constants.GM_CHANNEL) { - loadNewGMIfNeeded(channel.id); - } - - doFocusPost(channelId, postId, data).then(() => { - if (onSuccess) { - onSuccess(); - } - }); - } else { - browserHistory.push('/error?type=' + ErrorPageTypes.PERMALINK_NOT_FOUND); - } - } - ); -} - -export function emitCloseRightHandSide() { - SearchStore.storeSearchResults(null, false, false); - SearchStore.emitSearchChange(); - - dispatch({ - type: ActionTypes.SELECT_POST, - postId: '' - }); -} - -export function emitPostFocusRightHandSideFromSearch(post, isMentionSearch) { - getPostThread(post.id)(dispatch, getState).then( - () => { - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_POST_SELECTED, - postId: Utils.getRootId(post), - from_search: SearchStore.getSearchTerm(), - from_flagged_posts: SearchStore.getIsFlaggedPosts(), - from_pinned_posts: SearchStore.getIsPinnedPosts() - }); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH, - results: null, - is_mention_search: isMentionSearch - }); - } - ); -} - -export function emitLeaveTeam() { - removeUserFromTeam(TeamStore.getCurrentId(), UserStore.getCurrentId())(dispatch, getState); -} - -export function emitUserPostedEvent(post) { - AppDispatcher.handleServerAction({ - type: ActionTypes.CREATE_POST, - post - }); -} - -export function emitUserCommentedEvent(post) { - AppDispatcher.handleServerAction({ - type: ActionTypes.CREATE_COMMENT, - post - }); -} - -export function showAccountSettingsModal() { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_ACCOUNT_SETTINGS_MODAL, - value: true - }); -} - -export function showShortcutsModal() { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_SHORTCUTS_MODAL, - value: true - }); -} - -export function showDeletePostModal(post, commentCount = 0) { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_DELETE_POST_MODAL, - value: true, - post, - commentCount - }); -} - -export function showChannelHeaderUpdateModal(channel) { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_CHANNEL_HEADER_UPDATE_MODAL, - value: true, - channel - }); -} - -export function showChannelPurposeUpdateModal(channel) { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_CHANNEL_PURPOSE_UPDATE_MODAL, - value: true, - channel - }); -} - -export function showChannelNameUpdateModal(channel) { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_CHANNEL_NAME_UPDATE_MODAL, - value: true, - channel - }); -} - -export function showGetPostLinkModal(post) { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_GET_POST_LINK_MODAL, - value: true, - post - }); -} - -export function showGetPublicLinkModal(fileId) { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_GET_PUBLIC_LINK_MODAL, - value: true, - fileId - }); -} - -export function showGetTeamInviteLinkModal() { - AppDispatcher.handleViewAction({ - type: Constants.ActionTypes.TOGGLE_GET_TEAM_INVITE_LINK_MODAL, - value: true - }); -} - -export function showInviteMemberModal() { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_INVITE_MEMBER_MODAL, - value: true - }); -} - -export function showLeaveTeamModal() { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_LEAVE_TEAM_MODAL, - value: true - }); -} - -export function showLeavePrivateChannelModal(channel) { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_LEAVE_PRIVATE_CHANNEL_MODAL, - value: channel - }); -} - -export function emitSuggestionPretextChanged(suggestionId, pretext) { - AppDispatcher.handleViewAction({ - type: ActionTypes.SUGGESTION_PRETEXT_CHANGED, - id: suggestionId, - pretext - }); -} - -export function emitSelectNextSuggestion(suggestionId) { - AppDispatcher.handleViewAction({ - type: ActionTypes.SUGGESTION_SELECT_NEXT, - id: suggestionId - }); -} - -export function emitSelectPreviousSuggestion(suggestionId) { - AppDispatcher.handleViewAction({ - type: ActionTypes.SUGGESTION_SELECT_PREVIOUS, - id: suggestionId - }); -} - -export function emitCompleteWordSuggestion(suggestionId, term = '') { - AppDispatcher.handleViewAction({ - type: Constants.ActionTypes.SUGGESTION_COMPLETE_WORD, - id: suggestionId, - term - }); -} - -export function emitClearSuggestions(suggestionId) { - AppDispatcher.handleViewAction({ - type: Constants.ActionTypes.SUGGESTION_CLEAR_SUGGESTIONS, - id: suggestionId - }); -} - -export function emitPreferenceChangedEvent(preference) { - AppDispatcher.handleServerAction({ - type: Constants.ActionTypes.RECEIVED_PREFERENCE, - preference - }); - - if (addedNewDmUser(preference)) { - loadProfilesForSidebar(); - } -} - -export function emitPreferencesChangedEvent(preferences) { - AppDispatcher.handleServerAction({ - type: Constants.ActionTypes.RECEIVED_PREFERENCES, - preferences - }); - - if (preferences.findIndex(addedNewDmUser) !== -1) { - loadProfilesForSidebar(); - } -} - -function addedNewDmUser(preference) { - return preference.category === Constants.Preferences.CATEGORY_DIRECT_CHANNEL_SHOW && preference.value === 'true'; -} - -export function emitPreferencesDeletedEvent(preferences) { - AppDispatcher.handleServerAction({ - type: Constants.ActionTypes.DELETED_PREFERENCES, - preferences - }); -} - -export function sendEphemeralPost(message, channelId, parentId) { - const timestamp = Utils.getTimestamp(); - const post = { - id: Utils.generateId(), - user_id: '0', - channel_id: channelId || ChannelStore.getCurrentId(), - message, - type: Constants.PostTypes.EPHEMERAL, - create_at: timestamp, - update_at: timestamp, - root_id: parentId, - parent_id: parentId, - props: {} - }; - - handleNewPost(post); -} - -export function newLocalizationSelected(locale) { - const localeInfo = I18n.getLanguageInfo(locale); - - if (locale === 'en' || !localeInfo) { - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_LOCALE, - locale, - translations: en - }); - } else { - Client4.getTranslations(localeInfo.url).then( - (data, res) => { - let translations = data; - if (!data && res.text) { - translations = JSON.parse(res.text); - } - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_LOCALE, - locale, - translations - }); - } - ).catch( - () => {} //eslint-disable-line no-empty-function - ); - } -} - -export function loadCurrentLocale() { - const user = UserStore.getCurrentUser(); - - if (user && user.locale) { - newLocalizationSelected(user.locale); - } else { - loadDefaultLocale(); - } -} - -export function loadDefaultLocale() { - let locale = global.window.mm_config.DefaultClientLocale; - - if (!I18n.getLanguageInfo(locale)) { - locale = 'en'; - } - - return newLocalizationSelected(locale); -} - -let lastTimeTypingSent = 0; -export function emitLocalUserTypingEvent(channelId, parentId) { - const t = Date.now(); - const membersInChannel = ChannelStore.getStats(channelId).member_count; - - if (global.mm_license.IsLicensed === 'true' && global.mm_config.ExperimentalTownSquareIsReadOnly === 'true') { - const channel = ChannelStore.getChannelById(channelId); - if (channel && ChannelStore.isDefault(channel)) { - return; - } - } - - if (((t - lastTimeTypingSent) > global.window.mm_config.TimeBetweenUserTypingUpdatesMilliseconds) && membersInChannel < global.window.mm_config.MaxNotificationsPerChannel && global.window.mm_config.EnableUserTypingMessages === 'true') { - WebSocketClient.userTyping(channelId, parentId); - lastTimeTypingSent = t; - } -} - -export function emitRemoteUserTypingEvent(channelId, userId, postParentId) { - AppDispatcher.handleViewAction({ - type: Constants.ActionTypes.USER_TYPING, - channelId, - userId, - postParentId - }); -} - -export function emitUserLoggedOutEvent(redirectTo = '/', shouldSignalLogout = true) { - Client4.logout().then( - () => { - if (shouldSignalLogout) { - BrowserStore.signalLogout(); - } - - clientLogout(redirectTo); - } - ).catch( - () => { - browserHistory.push(redirectTo); - } - ); -} - -export function clientLogout(redirectTo = '/') { - BrowserStore.clear(); - ErrorStore.clearLastError(); - ChannelStore.clear(); - stopPeriodicStatusUpdates(); - WebsocketActions.close(); - document.cookie = 'MMUSERID=;expires=Thu, 01 Jan 1970 00:00:01 GMT;'; - window.location.href = redirectTo; -} - -export function emitSearchMentionsEvent(user) { - let terms = ''; - if (user.notify_props) { - const termKeys = UserStore.getMentionKeys(user.id); - - if (termKeys.indexOf('@channel') !== -1) { - termKeys[termKeys.indexOf('@channel')] = ''; - } - - if (termKeys.indexOf('@all') !== -1) { - termKeys[termKeys.indexOf('@all')] = ''; - } - - terms = termKeys.join(' '); - } - - trackEvent('api', 'api_posts_search_mention'); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH_TERM, - term: terms, - do_search: true, - is_mention_search: true - }); -} - -export function toggleSideBarAction(visible) { - if (!visible) { - //Array of actions resolving in the closing of the sidebar - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH, - results: null - }); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH_TERM, - term: null, - do_search: false, - is_mention_search: false - }); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_POST_SELECTED, - postId: null - }); - } -} - -export function toggleSideBarRightMenuAction() { - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH, - results: null - }); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_POST_SELECTED, - postId: null - }); - - document.querySelector('.app__body .inner-wrap').classList.remove('move--right', 'move--left', 'move--left-small'); - document.querySelector('.app__body .sidebar--left').classList.remove('move--right'); - document.querySelector('.app__body .sidebar--right').classList.remove('move--left'); - document.querySelector('.app__body .sidebar--menu').classList.remove('move--left'); -} - -export function emitBrowserFocus(focus) { - AppDispatcher.handleViewAction({ - type: ActionTypes.BROWSER_CHANGE_FOCUS, - focus - }); -} - -export function redirectUserToDefaultTeam() { - const teams = TeamStore.getAll(); - const teamMembers = TeamStore.getMyTeamMembers(); - let teamId = BrowserStore.getGlobalItem('team'); - - function redirect(teamName, channelName) { - browserHistory.push(`/${teamName}/channels/${channelName}`); - } - - if (!teams[teamId] && teamMembers.length > 0) { - let myTeams = []; - for (const index in teamMembers) { - if (teamMembers.hasOwnProperty(index)) { - const teamMember = teamMembers[index]; - myTeams.push(teams[teamMember.team_id]); - } - } - - if (myTeams.length > 0) { - myTeams = myTeams.sort(sortTeamsByDisplayName); - teamId = myTeams[0].id; - } - } - - if (teams[teamId]) { - const channelId = BrowserStore.getGlobalItem(teamId); - const channel = ChannelStore.getChannelById(channelId); - if (channel) { - redirect(teams[teamId].name, channel); - } else if (channelId) { - getChannelAndMyMember(channelId)(dispatch, getState).then( - (data) => { - if (data) { - redirect(teams[teamId].name, data.channel.name); - } else { - redirect(teams[teamId].name, 'town-square'); - } - } - ); - } else { - redirect(teams[teamId].name, 'town-square'); - } - } else { - browserHistory.push('/select_team'); - } -} - -export function postListScrollChange(forceScrollToBottom = false) { - AppDispatcher.handleViewAction({ - type: EventTypes.POST_LIST_SCROLL_CHANGE, - value: forceScrollToBottom - }); -} - -export function emitPopoverMentionKeyClick(isRHS, mentionKey) { - AppDispatcher.handleViewAction({ - type: ActionTypes.POPOVER_MENTION_KEY_CLICK, - isRHS, - mentionKey - }); -} - -let serverVersion = ''; - -export function reloadIfServerVersionChanged() { - const newServerVersion = Client4.getServerVersion(); - if (serverVersion && serverVersion !== newServerVersion) { - console.log('Detected version update refreshing the page'); //eslint-disable-line no-console - window.location.reload(true); - } - - serverVersion = newServerVersion; -} diff --git a/webapp/actions/integration_actions.jsx b/webapp/actions/integration_actions.jsx deleted file mode 100644 index cc20b3ab858..00000000000 --- a/webapp/actions/integration_actions.jsx +++ /dev/null @@ -1,301 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import UserStore from 'stores/user_store.jsx'; -import TeamStore from 'stores/team_store.jsx'; - -import * as UserAgent from 'utils/user_agent.jsx'; -import {ActionTypes} from 'utils/constants.jsx'; -import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; - -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import {Client4} from 'mattermost-redux/client'; - -import {getProfilesByIds} from 'mattermost-redux/actions/users'; -import * as IntegrationActions from 'mattermost-redux/actions/integrations'; - -import request from 'superagent'; - -export function loadIncomingHooks(complete) { - IntegrationActions.getIncomingHooks('', 0, 10000)(dispatch, getState).then( - (data) => { - if (data) { - loadProfilesForIncomingHooks(data); - } - - if (complete) { - complete(data); - } - } - ); -} - -export function loadIncomingHooksForTeam(teamId, complete) { - IntegrationActions.getIncomingHooks(teamId, 0, 10000)(dispatch, getState).then( - (data) => { - if (data) { - loadProfilesForIncomingHooks(data); - } - - if (complete) { - complete(data); - } - } - ); -} - -function loadProfilesForIncomingHooks(hooks) { - const profilesToLoad = {}; - for (let i = 0; i < hooks.length; i++) { - const hook = hooks[i]; - if (!UserStore.hasProfile(hook.user_id)) { - profilesToLoad[hook.user_id] = true; - } - } - - const list = Object.keys(profilesToLoad); - if (list.length === 0) { - return; - } - - getProfilesByIds(list)(dispatch, getState); -} - -export function loadOutgoingHooks(complete) { - IntegrationActions.getOutgoingHooks('', '', 0, 10000)(dispatch, getState).then( - (data) => { - if (data) { - loadProfilesForOutgoingHooks(data); - } - - if (complete) { - complete(data); - } - } - ); -} - -export function loadOutgoingHooksForTeam(teamId, complete) { - IntegrationActions.getOutgoingHooks('', teamId, 0, 10000)(dispatch, getState).then( - (data) => { - if (data) { - loadProfilesForOutgoingHooks(data); - } - - if (complete) { - complete(data); - } - } - ); -} - -function loadProfilesForOutgoingHooks(hooks) { - const profilesToLoad = {}; - for (let i = 0; i < hooks.length; i++) { - const hook = hooks[i]; - if (!UserStore.hasProfile(hook.creator_id)) { - profilesToLoad[hook.creator_id] = true; - } - } - - const list = Object.keys(profilesToLoad); - if (list.length === 0) { - return; - } - - getProfilesByIds(list)(dispatch, getState); -} - -export function loadTeamCommands(complete) { - IntegrationActions.getCustomTeamCommands(TeamStore.getCurrentId())(dispatch, getState).then( - (data) => { - if (data) { - loadProfilesForCommands(data); - } - - if (complete) { - complete(data); - } - } - ); -} - -function loadProfilesForCommands(commands) { - const profilesToLoad = {}; - for (let i = 0; i < commands.length; i++) { - const command = commands[i]; - if (!UserStore.hasProfile(command.creator_id)) { - profilesToLoad[command.creator_id] = true; - } - } - - const list = Object.keys(profilesToLoad); - if (list.length === 0) { - return; - } - - getProfilesByIds(list)(dispatch, getState); -} - -export function addIncomingHook(hook, success, error) { - IntegrationActions.createIncomingHook(hook)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.integrations.createIncomingHook.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updateIncomingHook(hook, success, error) { - IntegrationActions.updateIncomingHook(hook)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.integrations.updateIncomingHook.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function addOutgoingHook(hook, success, error) { - IntegrationActions.createOutgoingHook(hook)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.integrations.createOutgoingHook.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updateOutgoingHook(hook, success, error) { - IntegrationActions.updateOutgoingHook(hook)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.integrations.updateOutgoingHook.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function deleteIncomingHook(id) { - IntegrationActions.removeIncomingHook(id)(dispatch, getState); -} - -export function deleteOutgoingHook(id) { - IntegrationActions.removeOutgoingHook(id)(dispatch, getState); -} - -export function regenOutgoingHookToken(id) { - IntegrationActions.regenOutgoingHookToken(id)(dispatch, getState); -} - -export function addCommand(command, success, error) { - IntegrationActions.addCommand(command)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.integrations.addCommand.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function editCommand(command, success, error) { - IntegrationActions.editCommand(command)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.integrations.editCommand.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function deleteCommand(id) { - IntegrationActions.deleteCommand(id)(dispatch, getState); -} - -export function regenCommandToken(id) { - IntegrationActions.regenCommandToken(id)(dispatch, getState); -} - -export function getSuggestedCommands(command, suggestionId, component) { - Client4.getCommandsList(TeamStore.getCurrentId()).then( - (data) => { - let matches = []; - data.forEach((cmd) => { - if (!cmd.auto_complete) { - return; - } - - if (cmd.trigger !== 'shortcuts' || !UserAgent.isMobile()) { - if (('/' + cmd.trigger).indexOf(command) === 0) { - const s = '/' + cmd.trigger; - let hint = ''; - if (cmd.auto_complete_hint && cmd.auto_complete_hint.length !== 0) { - hint = cmd.auto_complete_hint; - } - matches.push({ - suggestion: s, - hint, - description: cmd.auto_complete_desc - }); - } - } - }); - - matches = matches.sort((a, b) => a.suggestion.localeCompare(b.suggestion)); - - // pull out the suggested commands from the returned data - const terms = matches.map((suggestion) => suggestion.suggestion); - - if (terms.length > 0) { - AppDispatcher.handleServerAction({ - type: ActionTypes.SUGGESTION_RECEIVED_SUGGESTIONS, - id: suggestionId, - matchedPretext: command, - terms, - items: matches, - component - }); - } - } - ).catch( - () => {} //eslint-disable-line no-empty-function - ); -} - -export function getYoutubeVideoInfo(googleKey, videoId, success, error) { - request.get('https://www.googleapis.com/youtube/v3/videos'). - query({part: 'snippet', id: videoId, key: googleKey}). - end((err, res) => { - if (err) { - return error(err); - } - - if (!res.body) { - console.error('Missing response body for getYoutubeVideoInfo'); // eslint-disable-line no-console - } - - return success(res.body); - }); -} diff --git a/webapp/actions/job_actions.jsx b/webapp/actions/job_actions.jsx deleted file mode 100644 index 75d70faecc9..00000000000 --- a/webapp/actions/job_actions.jsx +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import * as JobsActions from 'mattermost-redux/actions/jobs'; - -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -export function createJob(job, success, error) { - JobsActions.createJob(job)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.jobs.createJob.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function cancelJob(jobId, success, error) { - JobsActions.cancelJob(jobId)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.jobs.cancelJob.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} diff --git a/webapp/actions/notification_actions.jsx b/webapp/actions/notification_actions.jsx deleted file mode 100644 index 33709458a5b..00000000000 --- a/webapp/actions/notification_actions.jsx +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import Constants from 'utils/constants.jsx'; -import UserStore from 'stores/user_store.jsx'; -import ChannelStore from 'stores/channel_store.jsx'; -import NotificationStore from 'stores/notification_store.jsx'; - -import {isSystemMessage} from 'utils/post_utils.jsx'; -import {buildGroupChannelName} from 'utils/channel_utils.jsx'; -import {isWindowsApp, isMacApp, isMobileApp} from 'utils/user_agent.jsx'; -import * as Utils from 'utils/utils.jsx'; - -export function sendDesktopNotification(post, msgProps) { - if ((UserStore.getCurrentId() === post.user_id && post.props.from_webhook !== 'true')) { - return; - } - - if (isSystemMessage(post)) { - return; - } - - let mentions = []; - if (msgProps.mentions) { - mentions = JSON.parse(msgProps.mentions); - } - const teamId = msgProps.team_id; - - let channel = ChannelStore.get(post.channel_id); - const user = UserStore.getCurrentUser(); - const member = ChannelStore.getMyMember(post.channel_id); - - let notifyLevel = member && member.notify_props ? member.notify_props.desktop : 'default'; - if (notifyLevel === 'default') { - notifyLevel = user.notify_props.desktop; - } - - if (notifyLevel === 'none') { - return; - } else if (notifyLevel === 'mention' && mentions.indexOf(user.id) === -1 && msgProps.channel_type !== Constants.DM_CHANNEL) { - return; - } - - let username = Utils.localizeMessage('channel_loader.someone', 'Someone'); - if (post.props.override_username && global.window.mm_config.EnablePostUsernameOverride === 'true') { - username = post.props.override_username; - } else if (msgProps.sender_name) { - username = msgProps.sender_name; - } else if (UserStore.hasProfile(post.user_id)) { - username = UserStore.getProfile(post.user_id).username; - } - - let title = Utils.localizeMessage('channel_loader.posted', 'Posted'); - if (!channel) { - title = msgProps.channel_display_name; - channel = { - name: msgProps.channel_name, - type: msgProps.channel_type - }; - } else if (channel.type === Constants.DM_CHANNEL) { - title = Utils.localizeMessage('notification.dm', 'Direct Message'); - } else if (channel.type === Constants.GM_CHANNEL) { - title = buildGroupChannelName(channel.id); - } else { - title = channel.display_name; - } - - if (title === '') { - if (msgProps.channel_type === Constants.DM_CHANNEL) { - title = Utils.localizeMessage('notification.dm', 'Direct Message'); - } else { - title = msgProps.channel_display_name; - } - } - - let notifyText = post.message; - - const msgPropsPost = JSON.parse(msgProps.post); - const attachments = msgPropsPost && msgPropsPost.props && msgPropsPost.props.attachments ? msgPropsPost.props.attachments : []; - let image = false; - attachments.forEach((attachment) => { - if (notifyText.length === 0) { - notifyText = attachment.fallback || - attachment.pretext || - attachment.text; - } - image |= attachment.image_url.length > 0; - }); - - notifyText = notifyText.replace(/\n+/g, ' '); - if (notifyText.length > 50) { - notifyText = notifyText.substring(0, 49) + '...'; - } - - let body = ''; - if (notifyText.length === 0) { - if (msgProps.image) { - body = username + Utils.localizeMessage('channel_loader.uploadedImage', ' uploaded an image'); - } else if (msgProps.otherFile) { - body = username + Utils.localizeMessage('channel_loader.uploadedFile', ' uploaded a file'); - } else if (image) { - body = username + Utils.localizeMessage('channel_loader.postedImage', ' posted an image'); - } else { - body = username + Utils.localizeMessage('channel_loader.something', ' did something new'); - } - } else { - body = username + Utils.localizeMessage('channel_loader.wrote', ' wrote: ') + notifyText; - } - - let duration = Constants.DEFAULT_NOTIFICATION_DURATION; - if (user.notify_props && user.notify_props.desktop_duration) { - duration = parseInt(user.notify_props.desktop_duration, 10) * 1000; - } - - //Play a sound if explicitly set in settings - const sound = !user.notify_props || user.notify_props.desktop_sound === 'true'; - - // Notify if you're not looking in the right channel or when - // the window itself is not active - const activeChannel = ChannelStore.getCurrent(); - const channelId = channel ? channel.id : null; - const notify = (activeChannel && activeChannel.id !== channelId) || !NotificationStore.getFocus(); - - if (notify) { - Utils.notifyMe(title, body, channel, teamId, duration, !sound); - - //Don't add extra sounds on native desktop clients - if (sound && !isWindowsApp() && !isMacApp() && !isMobileApp()) { - Utils.ding(); - } - } -} diff --git a/webapp/actions/oauth_actions.jsx b/webapp/actions/oauth_actions.jsx deleted file mode 100644 index 54823a324f7..00000000000 --- a/webapp/actions/oauth_actions.jsx +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import * as IntegrationActions from 'mattermost-redux/actions/integrations'; - -export function deleteOAuthApp(id, success, error) { - IntegrationActions.deleteOAuthApp(id)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.integrations.deleteOAuthApp.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} diff --git a/webapp/actions/post_actions.jsx b/webapp/actions/post_actions.jsx deleted file mode 100644 index cb111ec3987..00000000000 --- a/webapp/actions/post_actions.jsx +++ /dev/null @@ -1,357 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; - -import ChannelStore from 'stores/channel_store.jsx'; -import UserStore from 'stores/user_store.jsx'; -import PostStore from 'stores/post_store.jsx'; -import TeamStore from 'stores/team_store.jsx'; - -import {loadNewDMIfNeeded, loadNewGMIfNeeded} from 'actions/user_actions.jsx'; -import {sendDesktopNotification} from 'actions/notification_actions.jsx'; - -import {ActionTypes, Constants} from 'utils/constants.jsx'; -import {EMOJI_PATTERN} from 'utils/emoticons.jsx'; - -import {browserHistory} from 'react-router/es6'; - -// Redux actions -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import * as PostActions from 'mattermost-redux/actions/posts'; -import {getMyChannelMember} from 'mattermost-redux/actions/channels'; - -import {Client4} from 'mattermost-redux/client'; - -import {PostTypes} from 'mattermost-redux/action_types'; -import * as Selectors from 'mattermost-redux/selectors/entities/posts'; -import {batchActions} from 'redux-batched-actions'; - -export function handleNewPost(post, msg) { - let websocketMessageProps = {}; - if (msg) { - websocketMessageProps = msg.data; - } - - if (ChannelStore.getMyMember(post.channel_id)) { - completePostReceive(post, websocketMessageProps); - } else { - getMyChannelMember(post.channel_id)(dispatch, getState).then(() => completePostReceive(post, websocketMessageProps)); - } - - if (msg && msg.data) { - if (msg.data.channel_type === Constants.DM_CHANNEL) { - loadNewDMIfNeeded(post.channel_id); - } else if (msg.data.channel_type === Constants.GM_CHANNEL) { - loadNewGMIfNeeded(post.channel_id); - } - } -} - -function completePostReceive(post, websocketMessageProps) { - if (post.root_id && Selectors.getPost(getState(), post.root_id) == null) { - PostActions.getPostThread(post.root_id)(dispatch, getState).then( - (data) => { - dispatchPostActions(post, websocketMessageProps); - PostActions.getProfilesAndStatusesForPosts(data.posts, dispatch, getState); - } - ); - - return; - } - - dispatchPostActions(post, websocketMessageProps); -} - -function dispatchPostActions(post, websocketMessageProps) { - const {currentChannelId} = getState().entities.channels; - - if (post.channel_id === currentChannelId) { - dispatch({ - type: ActionTypes.INCREASE_POST_VISIBILITY, - data: post.channel_id, - amount: 1 - }); - } - - // Need manual dispatch to remove pending post - dispatch({ - type: PostTypes.RECEIVED_POSTS, - data: { - order: [], - posts: { - [post.id]: post - } - }, - channelId: post.channel_id - }); - - // Still needed to update unreads - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_POST, - post, - websocketMessageProps - }); - - sendDesktopNotification(post, websocketMessageProps); -} - -export function flagPost(postId) { - PostActions.flagPost(postId)(dispatch, getState); -} - -export function unflagPost(postId) { - PostActions.unflagPost(postId)(dispatch, getState); -} - -export function getFlaggedPosts() { - Client4.getFlaggedPosts(UserStore.getCurrentId(), '', TeamStore.getCurrentId()).then( - (data) => { - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH_TERM, - term: null, - do_search: false, - is_mention_search: false - }); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH, - results: data, - is_flagged_posts: true, - is_pinned_posts: false - }); - - PostActions.getProfilesAndStatusesForPosts(data.posts, dispatch, getState); - } - ).catch( - () => {} //eslint-disable-line no-empty-function - ); -} - -export function getPinnedPosts(channelId = ChannelStore.getCurrentId()) { - Client4.getPinnedPosts(channelId).then( - (data) => { - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH_TERM, - term: null, - do_search: false, - is_mention_search: false - }); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH, - results: data, - is_flagged_posts: false, - is_pinned_posts: true - }); - - PostActions.getProfilesAndStatusesForPosts(data.posts, dispatch, getState); - } - ).catch( - () => {} //eslint-disable-line no-empty-function - ); -} - -export function addReaction(channelId, postId, emojiName) { - PostActions.addReaction(postId, emojiName)(dispatch, getState); -} - -export function removeReaction(channelId, postId, emojiName) { - PostActions.removeReaction(postId, emojiName)(dispatch, getState); -} - -export function createPost(post, files, success) { - // parse message and emit emoji event - const emojis = post.message.match(EMOJI_PATTERN); - if (emojis) { - for (const emoji of emojis) { - const trimmed = emoji.substring(1, emoji.length - 1); - emitEmojiPosted(trimmed); - } - } - - PostActions.createPost(post, files)(dispatch, getState).then(() => { - if (post.root_id) { - PostStore.storeCommentDraft(post.root_id, null); - } else { - PostStore.storeDraft(post.channel_id, null); - } - - if (success) { - success(); - } - }); -} - -export function updatePost(post, success) { - PostActions.editPost(post)(dispatch, getState).then( - (data) => { - if (data && success) { - success(); - } else { - const serverError = getState().requests.posts.editPost.error; - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_ERROR, - err: {id: serverError.server_error_id, ...serverError}, - method: 'editPost' - }); - } - } - ); -} - -export function emitEmojiPosted(emoji) { - AppDispatcher.handleServerAction({ - type: ActionTypes.EMOJI_POSTED, - alias: emoji - }); -} - -export function deletePost(channelId, post, success) { - const {currentUserId} = getState().entities.users; - - let hardDelete = false; - if (post.user_id === currentUserId) { - hardDelete = true; - } - - PostActions.deletePost(post, hardDelete)(dispatch, getState).then( - () => { - if (post.id === getState().views.rhs.selectedPostId) { - dispatch({ - type: ActionTypes.SELECT_POST, - postId: '' - }); - } - - dispatch({ - type: PostTypes.REMOVE_POST, - data: post - }); - - // Needed for search store - AppDispatcher.handleViewAction({ - type: Constants.ActionTypes.REMOVE_POST, - post - }); - - const {focusedPostId} = getState().views.channel; - const channel = getState().entities.channels.channels[post.channel_id]; - if (post.id === focusedPostId && channel) { - browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/channels/' + channel.name); - } - - if (success) { - success(); - } - } - ); -} - -export function performSearch(terms, isMentionSearch, success, error) { - Client4.searchPosts(TeamStore.getCurrentId(), terms, isMentionSearch).then( - (data) => { - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH, - results: data, - is_mention_search: isMentionSearch - }); - - PostActions.getProfilesAndStatusesForPosts(data.posts, dispatch, getState); - - if (success) { - success(data); - } - } - ).catch( - (err) => { - if (error) { - error(err); - } - } - ); -} - -const POST_INCREASE_AMOUNT = Constants.POST_CHUNK_SIZE / 2; - -// Returns true if there are more posts to load -export function increasePostVisibility(channelId, focusedPostId) { - return async (doDispatch, doGetState) => { - if (doGetState().views.channel.loadingPosts[channelId]) { - return true; - } - - const currentPostVisibility = doGetState().views.channel.postVisibility[channelId]; - - if (currentPostVisibility >= Constants.MAX_POST_VISIBILITY) { - return true; - } - - doDispatch(batchActions([ - { - type: ActionTypes.LOADING_POSTS, - data: true, - channelId - }, - { - type: ActionTypes.INCREASE_POST_VISIBILITY, - data: channelId, - amount: POST_INCREASE_AMOUNT - } - ])); - - const page = Math.floor(currentPostVisibility / POST_INCREASE_AMOUNT); - - let posts; - if (focusedPostId) { - posts = await PostActions.getPostsBefore(channelId, focusedPostId, page, POST_INCREASE_AMOUNT)(dispatch, getState); - } else { - posts = await PostActions.getPosts(channelId, page, POST_INCREASE_AMOUNT)(doDispatch, doGetState); - } - - doDispatch({ - type: ActionTypes.LOADING_POSTS, - data: false, - channelId - }); - - return posts.order.length >= POST_INCREASE_AMOUNT; - }; -} - -export function searchForTerm(term) { - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH_TERM, - term, - do_search: true - }); -} - -export function pinPost(postId) { - return async (doDispatch, doGetState) => { - await PostActions.pinPost(postId)(doDispatch, doGetState); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_POST_PINNED, - postId - }); - }; -} - -export function unpinPost(postId) { - return async (doDispatch, doGetState) => { - await PostActions.unpinPost(postId)(doDispatch, doGetState); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_POST_UNPINNED, - postId - }); - }; -} - -export function doPostAction(postId, actionId) { - PostActions.doPostAction(postId, actionId)(dispatch, getState); -} diff --git a/webapp/actions/status_actions.jsx b/webapp/actions/status_actions.jsx deleted file mode 100644 index e8559bd65a7..00000000000 --- a/webapp/actions/status_actions.jsx +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import ChannelStore from 'stores/channel_store.jsx'; -import PostStore from 'stores/post_store.jsx'; -import PreferenceStore from 'stores/preference_store.jsx'; -import UserStore from 'stores/user_store.jsx'; - -import {Preferences, Constants} from 'utils/constants.jsx'; - -// Redux actions -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import {getStatusesByIds} from 'mattermost-redux/actions/users'; - -export function loadStatusesForChannel(channelId = ChannelStore.getCurrentId()) { - const postList = PostStore.getVisiblePosts(channelId); - if (!postList || !postList.posts) { - return; - } - - const statuses = UserStore.getStatuses(); - const statusesToLoad = {}; - for (const pid in postList.posts) { - if (!postList.posts.hasOwnProperty(pid)) { - continue; - } - - const post = postList.posts[pid]; - if (statuses[post.user_id] == null) { - statusesToLoad[post.user_id] = true; - } - } - - loadStatusesByIds(Object.keys(statusesToLoad)); -} - -export function loadStatusesForDMSidebar() { - const dmPrefs = PreferenceStore.getCategory(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW); - const statusesToLoad = []; - - for (const [key, value] of dmPrefs) { - if (value === 'true') { - statusesToLoad.push(key); - } - } - - loadStatusesByIds(statusesToLoad); -} - -export function loadStatusesForChannelAndSidebar() { - const statusesToLoad = {}; - - const channelId = ChannelStore.getCurrentId(); - const posts = PostStore.getVisiblePosts(channelId) || []; - for (const post of posts) { - statusesToLoad[post.user_id] = true; - } - - const dmPrefs = PreferenceStore.getCategory(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW); - - for (const [key, value] of dmPrefs) { - if (value === 'true') { - statusesToLoad[key] = true; - } - } - - const {currentUserId} = getState().entities.users; - statusesToLoad[currentUserId] = true; - - loadStatusesByIds(Object.keys(statusesToLoad)); -} - -export function loadStatusesForProfilesList(users) { - if (users == null) { - return; - } - - const statusesToLoad = []; - for (let i = 0; i < users.length; i++) { - statusesToLoad.push(users[i].id); - } - - loadStatusesByIds(statusesToLoad); -} - -export function loadStatusesForProfilesMap(users) { - if (users == null) { - return; - } - - const statusesToLoad = []; - for (const userId in users) { - if (!users.hasOwnProperty(userId)) { - return; - } - statusesToLoad.push(userId); - } - - loadStatusesByIds(statusesToLoad); -} - -export function loadStatusesByIds(userIds) { - if (userIds.length === 0) { - return; - } - - getStatusesByIds(userIds)(dispatch, getState); -} - -let intervalId = ''; - -export function startPeriodicStatusUpdates() { - clearInterval(intervalId); - - intervalId = setInterval( - () => { - loadStatusesForChannelAndSidebar(); - }, - Constants.STATUS_INTERVAL - ); -} - -export function stopPeriodicStatusUpdates() { - clearInterval(intervalId); -} diff --git a/webapp/actions/team_actions.jsx b/webapp/actions/team_actions.jsx deleted file mode 100644 index af132b139b3..00000000000 --- a/webapp/actions/team_actions.jsx +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import TeamStore from 'stores/team_store.jsx'; -import ChannelStore from 'stores/channel_store.jsx'; - -import {browserHistory} from 'react-router/es6'; - -// Redux actions -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import {Client4} from 'mattermost-redux/client'; - -import {getUser} from 'mattermost-redux/actions/users'; -import {viewChannel} from 'mattermost-redux/actions/channels'; -import * as TeamActions from 'mattermost-redux/actions/teams'; - -import {TeamTypes} from 'mattermost-redux/action_types'; - -export function checkIfTeamExists(teamName, onSuccess, onError) { - TeamActions.checkIfTeamExists(teamName)(dispatch, getState).then( - (exists) => { - if (exists != null && onSuccess) { - onSuccess(exists); - } else if (exists == null && onError) { - const serverError = getState().requests.teams.getTeam.error; - onError({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function createTeam(team, onSuccess, onError) { - TeamActions.createTeam(team)(dispatch, getState).then( - (rteam) => { - if (rteam && onSuccess) { - browserHistory.push('/' + rteam.name + '/channels/town-square'); - onSuccess(rteam); - } else if (rteam == null && onError) { - const serverError = getState().requests.teams.createTeam.error; - onError({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updateTeam(team, onSuccess, onError) { - TeamActions.updateTeam(team)(dispatch, getState).then( - (rteam) => { - if (rteam && onSuccess) { - browserHistory.push('/' + rteam.name + '/channels/town-square'); - onSuccess(rteam); - } else if (rteam == null && onError) { - const serverError = getState().requests.teams.updateTeam.error; - onError({id: serverError.server_error_id, ...serverError}); - } - }, - ); -} - -export function removeUserFromTeam(teamId, userId, success, error) { - TeamActions.removeUserFromTeam(teamId, userId)(dispatch, getState).then( - (data) => { - getUser(userId)(dispatch, getState); - TeamActions.getTeamStats(teamId)(dispatch, getState); - - if (data && success) { - success(); - } else if (data == null && error) { - const serverError = getState().requests.teams.removeUserFromTeam.error; - error({id: serverError.server_error_id, ...serverError}); - } - }, - ); -} - -export function updateTeamMemberRoles(teamId, userId, newRoles, success, error) { - TeamActions.updateTeamMemberRoles(teamId, userId, newRoles)(dispatch, getState).then( - (data) => { - if (data && success) { - success(); - } else if (data == null && error) { - const serverError = getState().requests.teams.updateTeamMember.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function addUserToTeamFromInvite(data, hash, inviteId, success, error) { - Client4.addToTeamFromInvite(hash, data, inviteId).then( - (member) => { - TeamActions.getTeam(member.team_id)(dispatch, getState).then( - (team) => { - dispatch({ - type: TeamTypes.RECEIVED_MY_TEAM_MEMBER, - data: { - ...member, - delete_at: 0, - msg_count: 0, - mention_count: 0 - } - }); - - if (success) { - success(team); - } - } - ); - }, - ).catch( - (err) => { - if (error) { - error(err); - } - } - ); -} - -export function addUsersToTeam(teamId, userIds, success, error) { - TeamActions.addUsersToTeam(teamId, userIds)(dispatch, getState).then( - (teamMembers) => { - if (teamMembers && success) { - success(teamMembers); - } else if (teamMembers == null && error) { - const serverError = getState().requests.teams.addUserToTeam.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function getInviteInfo(inviteId, success, error) { - Client4.getTeamInviteInfo(inviteId).then( - (inviteData) => { - if (success) { - success(inviteData); - } - } - ).catch( - (err) => { - if (error) { - error(err); - } - } - ); -} - -export function inviteMembers(data, success, error) { - if (!data.invites) { - success(); - } - const emails = []; - data.invites.forEach((i) => { - emails.push(i.email); - }); - TeamActions.sendEmailInvitesToTeam(TeamStore.getCurrentId(), emails)(dispatch, getState).then( - (result) => { - if (result && success) { - success(); - } else if (result == null && error) { - const serverError = getState().requests.teams.emailInvite.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function switchTeams(url) { - viewChannel(ChannelStore.getCurrentId())(dispatch, getState); - browserHistory.push(url); -} - -export function getTeamsForUser(userId, success, error) { - TeamActions.getTeamsForUser(userId)(dispatch, getState).then( - (result) => { - if (result && success) { - success(result); - } else if (result == null && error) { - const serverError = getState().requests.teams.getTeams.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function getTeamMembersForUser(userId, success, error) { - TeamActions.getTeamMembersForUser(userId)(dispatch, getState).then( - (result) => { - if (result && success) { - success(result); - } else if (result == null && error) { - const serverError = getState().requests.teams.getTeamMembers.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} diff --git a/webapp/actions/user_actions.jsx b/webapp/actions/user_actions.jsx deleted file mode 100644 index 7c8f0afd541..00000000000 --- a/webapp/actions/user_actions.jsx +++ /dev/null @@ -1,839 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import PreferenceStore from 'stores/preference_store.jsx'; -import TeamStore from 'stores/team_store.jsx'; -import UserStore from 'stores/user_store.jsx'; -import ChannelStore from 'stores/channel_store.jsx'; - -import {getChannelMembersForUserIds} from 'actions/channel_actions.jsx'; -import {loadCurrentLocale, clientLogout} from 'actions/global_actions.jsx'; -import {loadStatusesForProfilesList, loadStatusesForProfilesMap} from 'actions/status_actions.jsx'; - -import {getDirectChannelName, getUserIdFromChannelName} from 'utils/utils.jsx'; - -import {Constants, ActionTypes, Preferences} from 'utils/constants.jsx'; -import {browserHistory} from 'react-router/es6'; - -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import * as Selectors from 'mattermost-redux/selectors/entities/users'; -import {getBool} from 'mattermost-redux/selectors/entities/preferences'; - -import * as UserActions from 'mattermost-redux/actions/users'; -import {Client4} from 'mattermost-redux/client'; - -import {getClientConfig, getLicenseConfig} from 'mattermost-redux/actions/general'; -import {getTeamMembersByIds, getMyTeamMembers, getMyTeamUnreads} from 'mattermost-redux/actions/teams'; -import {getChannelAndMyMember} from 'mattermost-redux/actions/channels'; -import {savePreferences as savePreferencesRedux, deletePreferences} from 'mattermost-redux/actions/preferences'; - -import {Preferences as PreferencesRedux} from 'mattermost-redux/constants'; - -export async function loadMe() { - await UserActions.loadMe()(dispatch, getState); - - if (window.mm_config) { - loadCurrentLocale(); - } -} - -export function loadMeAndConfig(callback) { - getClientConfig()(store.dispatch, store.getState).then((config) => { - global.window.mm_config = config; - - if (global.window && global.window.analytics) { - global.window.analytics.identify(global.window.mm_config.DiagnosticId, {}, { - context: { - ip: '0.0.0.0' - }, - page: { - path: '', - referrer: '', - search: '', - title: '', - url: '' - }, - anonymousId: '00000000000000000000000000' - }); - } - - Promise.all([ - loadMe(), - getLicenseConfig()(store.dispatch, store.getState).then( - (license) => { - global.window.mm_license = license; - } - ) - ]).then(callback); - }); -} - -export function switchFromLdapToEmail(email, password, token, ldapPassword, success, error) { - UserActions.switchLdapToEmail(ldapPassword, email, password, token)(dispatch, getState).then( - (data) => { - if (data) { - if (data.follow_link) { - clientLogout(data.follow_link); - } - if (success) { - success(data); - } - } else if (data == null && error) { - const serverError = getState().requests.users.switchLogin.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function loadProfilesAndTeamMembers(page, perPage, teamId = TeamStore.getCurrentId(), success) { - UserActions.getProfilesInTeam(teamId, page, perPage)(dispatch, getState).then( - (data) => { - loadTeamMembersForProfilesList(data, teamId, success); - loadStatusesForProfilesList(data); - } - ); -} - -export function loadProfilesAndTeamMembersAndChannelMembers(page, perPage, teamId = TeamStore.getCurrentId(), channelId = ChannelStore.getCurrentId(), success, error) { - UserActions.getProfilesInChannel(channelId, page, perPage)(dispatch, getState).then( - (data) => { - loadTeamMembersForProfilesList( - data, - teamId, - () => { - loadChannelMembersForProfilesList(data, channelId, success, error); - loadStatusesForProfilesList(data); - } - ); - } - ); -} - -export function loadTeamMembersForProfilesList(profiles, teamId = TeamStore.getCurrentId(), success, error) { - const membersToLoad = {}; - for (let i = 0; i < profiles.length; i++) { - const pid = profiles[i].id; - - if (!TeamStore.hasActiveMemberInTeam(teamId, pid)) { - membersToLoad[pid] = true; - } - } - - const list = Object.keys(membersToLoad); - if (list.length === 0) { - if (success) { - success({}); - } - return; - } - - loadTeamMembersForProfiles(list, teamId, success, error); -} - -export function loadProfilesWithoutTeam(page, perPage, success) { - UserActions.getProfilesWithoutTeam(page, perPage)(dispatch, getState).then( - (data) => { - loadStatusesForProfilesMap(data); - - if (success) { - success(data); - } - } - ); -} - -function loadTeamMembersForProfiles(userIds, teamId, success, error) { - getTeamMembersByIds(teamId, userIds)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.teams.getTeamMembers.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function loadChannelMembersForProfilesMap(profiles, channelId = ChannelStore.getCurrentId(), success, error) { - const membersToLoad = {}; - for (const pid in profiles) { - if (!profiles.hasOwnProperty(pid)) { - continue; - } - - if (!ChannelStore.hasActiveMemberInChannel(channelId, pid)) { - membersToLoad[pid] = true; - } - } - - const list = Object.keys(membersToLoad); - if (list.length === 0) { - if (success) { - success({}); - } - return; - } - - getChannelMembersForUserIds(channelId, list, success, error); -} - -export function loadTeamMembersAndChannelMembersForProfilesList(profiles, teamId = TeamStore.getCurrentId(), channelId = ChannelStore.getCurrentId(), success, error) { - loadTeamMembersForProfilesList(profiles, teamId, () => { - loadChannelMembersForProfilesList(profiles, channelId, success, error); - }, error); -} - -export function loadChannelMembersForProfilesList(profiles, channelId = ChannelStore.getCurrentId(), success, error) { - const membersToLoad = {}; - for (let i = 0; i < profiles.length; i++) { - const pid = profiles[i].id; - - if (!ChannelStore.hasActiveMemberInChannel(channelId, pid)) { - membersToLoad[pid] = true; - } - } - - const list = Object.keys(membersToLoad); - if (list.length === 0) { - if (success) { - success({}); - } - return; - } - - getChannelMembersForUserIds(channelId, list, success, error); -} - -function populateDMChannelsWithProfiles(userIds) { - const currentUserId = UserStore.getCurrentId(); - - for (let i = 0; i < userIds.length; i++) { - const channelName = getDirectChannelName(currentUserId, userIds[i]); - const channel = ChannelStore.getByName(channelName); - const profilesInChannel = Selectors.getUserIdsInChannels(getState())[channel.id] || new Set(); - if (channel && !profilesInChannel.has(userIds[i])) { - UserStore.saveUserIdInChannel(channel.id, userIds[i]); - } - } -} - -function populateChannelWithProfiles(channelId, users) { - for (let i = 0; i < users.length; i++) { - UserStore.saveUserIdInChannel(channelId, users[i].id); - } - UserStore.emitInChannelChange(); -} - -export function loadNewDMIfNeeded(channelId) { - function checkPreference(channel) { - const userId = getUserIdFromChannelName(channel); - - if (!userId) { - return; - } - - const pref = PreferenceStore.getBool(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, userId, false); - if (pref === false) { - PreferenceStore.setPreference(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, userId, 'true'); - const currentUserId = UserStore.getCurrentId(); - savePreferencesRedux(currentUserId, [{user_id: currentUserId, category: Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, name: userId, value: 'true'}])(dispatch, getState); - loadProfilesForDM(); - } - } - - const channel = ChannelStore.get(channelId); - if (channel) { - checkPreference(channel); - } else { - getChannelAndMyMember(channelId)(dispatch, getState).then( - (data) => { - if (data) { - checkPreference(data.channel); - } - } - ); - } -} - -export function loadNewGMIfNeeded(channelId) { - function checkPreference() { - const pref = PreferenceStore.getBool(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, channelId, false); - if (pref === false) { - PreferenceStore.setPreference(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, channelId, 'true'); - const currentUserId = UserStore.getCurrentId(); - savePreferencesRedux(currentUserId, [{user_id: currentUserId, category: Preferences.CATEGORY_GROUP_CHANNEL_SHOW, name: channelId, value: 'true'}])(dispatch, getState); - loadProfilesForGM(); - } - } - - const channel = ChannelStore.get(channelId); - if (channel) { - checkPreference(); - } else { - getChannelAndMyMember(channelId)(dispatch, getState).then( - () => { - checkPreference(); - } - ); - } -} - -export function loadProfilesForSidebar() { - loadProfilesForDM(); - loadProfilesForGM(); -} - -export function loadProfilesForGM() { - const channels = ChannelStore.getChannels(); - const newPreferences = []; - - for (let i = 0; i < channels.length; i++) { - const channel = channels[i]; - if (channel.type !== Constants.GM_CHANNEL) { - continue; - } - - if (UserStore.getProfileListInChannel(channel.id).length >= Constants.MIN_USERS_IN_GM) { - continue; - } - - const isVisible = PreferenceStore.getBool(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, channel.id); - - if (!isVisible) { - const member = ChannelStore.getMyMember(channel.id); - if (!member || (member.mention_count === 0 && member.msg_count >= channel.total_msg_count)) { - continue; - } - - newPreferences.push({ - user_id: UserStore.getCurrentId(), - category: Preferences.CATEGORY_GROUP_CHANNEL_SHOW, - name: channel.id, - value: 'true' - }); - } - - UserActions.getProfilesInChannel(channel.id, 0, Constants.MAX_USERS_IN_GM)(dispatch, getState).then( - (data) => { - populateChannelWithProfiles(channel.id, data); - } - ); - } - - if (newPreferences.length > 0) { - const currentUserId = UserStore.getCurrentId(); - savePreferencesRedux(currentUserId, newPreferences)(dispatch, getState); - } -} - -export function loadProfilesForDM() { - const channels = ChannelStore.getChannels(); - const newPreferences = []; - const profilesToLoad = []; - const profileIds = []; - - for (let i = 0; i < channels.length; i++) { - const channel = channels[i]; - if (channel.type !== Constants.DM_CHANNEL) { - continue; - } - - const teammateId = channel.name.replace(UserStore.getCurrentId(), '').replace('__', ''); - const isVisible = PreferenceStore.getBool(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, teammateId); - - if (!isVisible) { - const member = ChannelStore.getMyMember(channel.id); - if (!member || member.mention_count === 0) { - continue; - } - - newPreferences.push({ - user_id: UserStore.getCurrentId(), - category: Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, - name: teammateId, - value: 'true' - }); - } - - if (!UserStore.hasProfile(teammateId)) { - profilesToLoad.push(teammateId); - } - profileIds.push(teammateId); - } - - if (newPreferences.length > 0) { - const currentUserId = UserStore.getCurrentId(); - savePreferencesRedux(currentUserId, newPreferences)(dispatch, getState); - } - - if (profilesToLoad.length > 0) { - UserActions.getProfilesByIds(profilesToLoad)(dispatch, getState).then( - () => { - populateDMChannelsWithProfiles(profileIds); - }, - ); - } else { - populateDMChannelsWithProfiles(profileIds); - } -} - -export function saveTheme(teamId, theme, cb) { - const currentUserId = UserStore.getCurrentId(); - const preference = [{ - user_id: currentUserId, - category: Preferences.CATEGORY_THEME, - name: teamId, - value: JSON.stringify(theme) - }]; - - savePreferencesRedux(currentUserId, preference)(dispatch, getState).then( - () => { - onThemeSaved(teamId, theme, cb); - } - ); -} - -function onThemeSaved(teamId, theme, onSuccess) { - const themePreferences = PreferenceStore.getCategory(Preferences.CATEGORY_THEME); - - if (teamId !== '' && themePreferences.size > 1) { - // no extra handling to be done to delete team-specific themes - onSuccess(); - return; - } - - const toDelete = []; - - for (const [name] of themePreferences) { - if (name === '' || name === teamId) { - continue; - } - - toDelete.push({ - user_id: UserStore.getCurrentId(), - category: Preferences.CATEGORY_THEME, - name - }); - } - - if (toDelete.length > 0) { - // we're saving a new global theme so delete any team-specific ones - const currentUserId = UserStore.getCurrentId(); - deletePreferences(currentUserId, toDelete)(dispatch, getState); - } - - onSuccess(); -} - -export function searchUsers(term, teamId = TeamStore.getCurrentId(), options = {}, success) { - UserActions.searchProfiles(term, {team_id: teamId, ...options})(dispatch, getState).then( - (data) => { - loadStatusesForProfilesList(data); - - if (success) { - success(data); - } - } - ); -} - -export function searchUsersNotInTeam(term, teamId = TeamStore.getCurrentId(), options = {}, success) { - UserActions.searchProfiles(term, {not_in_team_id: teamId, ...options})(dispatch, getState).then( - (data) => { - loadStatusesForProfilesList(data); - - if (success) { - success(data); - } - } - ); -} - -export function autocompleteUsersInChannel(username, channelId, success) { - const channel = ChannelStore.get(channelId); - const teamId = channel ? channel.team_id : TeamStore.getCurrentId(); - UserActions.autocompleteUsers(username, teamId, channelId)(dispatch, getState).then( - (data) => { - if (success) { - success(data); - } - } - ); -} - -export function autocompleteUsersInTeam(username, success) { - UserActions.autocompleteUsers(username, TeamStore.getCurrentId())(dispatch, getState).then( - (data) => { - if (success) { - success(data); - } - } - ); -} - -export function autocompleteUsers(username, success) { - UserActions.autocompleteUsers(username)(dispatch, getState).then( - (data) => { - if (success) { - success(data); - } - } - ); -} - -export function updateUser(user, type, success, error) { - UserActions.updateMe(user)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateMe.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function generateMfaSecret(success, error) { - UserActions.generateMfaSecret(UserStore.getCurrentId())(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.generateMfaSecret.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updateUserNotifyProps(props, success, error) { - UserActions.updateMe({notify_props: props})(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateMe.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updateUserRoles(userId, newRoles, success, error) { - UserActions.updateUserRoles(userId, newRoles)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateUser.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function activateMfa(code, success, error) { - UserActions.updateUserMfa(UserStore.getCurrentId(), true, code)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateUser.error; - error({id: serverError.server_error_id, ...serverError}); - } - }, - ); -} - -export function deactivateMfa(success, error) { - UserActions.updateUserMfa(UserStore.getCurrentId(), false)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateUser.error; - error({id: serverError.server_error_id, ...serverError}); - } - }, - ); -} - -export function checkMfa(loginId, success, error) { - if (global.window.mm_config.EnableMultifactorAuthentication !== 'true') { - success(false); - return; - } - - UserActions.checkMfa(loginId)(dispatch, getState).then( - (data) => { - if (data != null && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.checkMfa.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updateActive(userId, active, success, error) { - UserActions.updateUserActive(userId, active)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateUser.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updatePassword(userId, currentPassword, newPassword, success, error) { - UserActions.updateUserPassword(userId, currentPassword, newPassword)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateUser.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function verifyEmail(token, success, error) { - UserActions.verifyUserEmail(token)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.verifyEmail.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function resetPassword(token, password, success, error) { - UserActions.resetUserPassword(token, password)(dispatch, getState).then( - (data) => { - if (data) { - browserHistory.push('/login?extra=' + ActionTypes.PASSWORD_CHANGE); - if (success) { - success(data); - } - } else if (data == null && error) { - const serverError = getState().requests.users.passwordReset.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function resendVerification(email, success, error) { - UserActions.sendVerificationEmail(email)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.verifyEmail.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function loginById(userId, password, mfaToken, success, error) { - UserActions.loginById(userId, password, mfaToken)(dispatch, getState).then( - (ok) => { - if (ok && success) { - success(); - } else if (!ok && error) { - const serverError = getState().requests.users.login.error; - if (serverError.server_error_id === 'api.context.mfa_required.app_error') { - if (success) { - success(); - } - return; - } - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function createUserWithInvite(user, data, emailHash, inviteId, success, error) { - UserActions.createUser(user, data, emailHash, inviteId)(dispatch, getState).then( - (resp) => { - if (resp && success) { - success(resp); - } else if (resp == null && error) { - const serverError = getState().requests.users.create.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function webLogin(loginId, password, token, success, error) { - UserActions.login(loginId, password, token)(dispatch, getState).then( - (ok) => { - if (ok && success) { - success(); - } else if (!ok && error) { - const serverError = getState().requests.users.login.error; - if (serverError.server_error_id === 'api.context.mfa_required.app_error') { - if (success) { - success(); - } - return; - } - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function webLoginByLdap(loginId, password, token, success, error) { - UserActions.login(loginId, password, token, true)(dispatch, getState).then( - (ok) => { - if (ok && success) { - success(); - } else if (!ok && error) { - const serverError = getState().requests.users.login.error; - if (serverError.server_error_id === 'api.context.mfa_required.app_error') { - if (success) { - success(); - } - return; - } - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function getAuthorizedApps(success, error) { - Client4.getAuthorizedOAuthApps(getState().entities.users.currentUserId).then( - (authorizedApps) => { - if (success) { - success(authorizedApps); - } - } - ).catch( - (err) => { - if (error) { - error(err); - } - } - ); -} - -export function deauthorizeOAuthApp(appId, success, error) { - Client4.deauthorizeOAuthApp(appId).then( - () => { - if (success) { - success(); - } - } - ).catch( - (err) => { - if (error) { - error(err); - } - } - ); -} - -export function uploadProfileImage(userPicture, success, error) { - UserActions.uploadProfileImage(Selectors.getCurrentUserId(getState()), userPicture)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateUser.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function loadProfiles(page, perPage, success) { - UserActions.getProfiles(page, perPage)(dispatch, getState).then( - (data) => { - if (success) { - success(data); - } - } - ); -} - -export function getMissingProfiles(ids) { - const missingIds = ids.filter((id) => !UserStore.hasProfile(id)); - - if (missingIds.length === 0) { - return; - } - - UserActions.getProfilesByIds(missingIds)(dispatch, getState); -} - -export function loadMyTeamMembers() { - getMyTeamMembers()(dispatch, getState).then( - () => { - getMyTeamUnreads()(dispatch, getState); - } - ); -} - -export function savePreferences(prefs, callback) { - const currentUserId = UserStore.getCurrentId(); - savePreferencesRedux(currentUserId, prefs)(dispatch, getState).then( - () => callback() - ); -} - -export async function savePreference(category, name, value) { - const currentUserId = UserStore.getCurrentId(); - return savePreferencesRedux(currentUserId, [{user_id: currentUserId, category, name, value}])(dispatch, getState); -} - -export function autoResetStatus() { - return async (doDispatch, doGetState) => { - const {currentUserId} = getState().entities.users; - const userStatus = await UserActions.getStatus(currentUserId)(doDispatch, doGetState); - - if (!userStatus.manual) { - return userStatus; - } - - const autoReset = getBool(getState(), PreferencesRedux.CATEGORY_AUTO_RESET_MANUAL_STATUS, currentUserId, false); - - if (autoReset) { - UserActions.setStatus({user_id: currentUserId, status: 'online'})(doDispatch, doGetState); - return userStatus; - } - - return userStatus; - }; -} - -export function sendPasswordResetEmail(email, success, error) { - UserActions.sendPasswordResetEmail(email)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.passwordReset.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} diff --git a/webapp/actions/webrtc_actions.jsx b/webapp/actions/webrtc_actions.jsx deleted file mode 100644 index 244de289b1d..00000000000 --- a/webapp/actions/webrtc_actions.jsx +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; -import {WebrtcActionTypes} from 'utils/constants.jsx'; - -import {Client4} from 'mattermost-redux/client'; - -export function initWebrtc(userId, isCalling) { - AppDispatcher.handleServerAction({ - type: WebrtcActionTypes.INITIALIZE, - user_id: userId, - is_calling: isCalling - }); -} - -export function handle(message) { - AppDispatcher.handleServerAction({ - type: message.action, - message - }); -} - -export function webrtcToken(success, error) { - Client4.webrtcToken().then( - (data) => { - if (success) { - success(data); - } - } - ).catch( - () => { - if (error) { - error(); - } - } - ); -} diff --git a/webapp/actions/websocket_actions.jsx b/webapp/actions/websocket_actions.jsx deleted file mode 100644 index 1e75b17583e..00000000000 --- a/webapp/actions/websocket_actions.jsx +++ /dev/null @@ -1,473 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import $ from 'jquery'; -import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; - -import UserStore from 'stores/user_store.jsx'; -import TeamStore from 'stores/team_store.jsx'; -import PreferenceStore from 'stores/preference_store.jsx'; -import ChannelStore from 'stores/channel_store.jsx'; -import BrowserStore from 'stores/browser_store.jsx'; -import ErrorStore from 'stores/error_store.jsx'; -import NotificationStore from 'stores/notification_store.jsx'; //eslint-disable-line no-unused-vars - -import WebSocketClient from 'client/web_websocket_client.jsx'; -import * as WebrtcActions from './webrtc_actions.jsx'; - -import * as GlobalActions from 'actions/global_actions.jsx'; -import {handleNewPost} from 'actions/post_actions.jsx'; -import {loadProfilesForSidebar} from 'actions/user_actions.jsx'; -import {loadChannelsForCurrentUser} from 'actions/channel_actions.jsx'; -import * as StatusActions from 'actions/status_actions.jsx'; - -import {Constants, Preferences, SocketEvents, UserStatuses, ErrorBarTypes} from 'utils/constants.jsx'; - -import {browserHistory} from 'react-router/es6'; - -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import {batchActions} from 'redux-batched-actions'; -import {Client4} from 'mattermost-redux/client'; -import {getSiteURL} from 'utils/url.jsx'; - -import * as TeamActions from 'mattermost-redux/actions/teams'; -import {viewChannel, getChannelAndMyMember, getChannelStats} from 'mattermost-redux/actions/channels'; -import {getPosts, getProfilesAndStatusesForPosts} from 'mattermost-redux/actions/posts'; -import {setServerVersion} from 'mattermost-redux/actions/general'; -import {ChannelTypes, TeamTypes, UserTypes, PostTypes, EmojiTypes} from 'mattermost-redux/action_types'; - -const MAX_WEBSOCKET_FAILS = 7; - -export function initialize() { - if (!window.WebSocket) { - console.log('Browser does not support websocket'); //eslint-disable-line no-console - return; - } - - let connUrl = getSiteURL(); - - // replace the protocol with a websocket one - if (connUrl.startsWith('https:')) { - connUrl = connUrl.replace(/^https:/, 'wss:'); - } else { - connUrl = connUrl.replace(/^http:/, 'ws:'); - } - - // append a port number if one isn't already specified - if (!(/:\d+$/).test(connUrl)) { - if (connUrl.startsWith('wss:')) { - connUrl += ':' + global.window.mm_config.WebsocketSecurePort; - } else { - connUrl += ':' + global.window.mm_config.WebsocketPort; - } - } - - connUrl += Client4.getUrlVersion() + '/websocket'; - - WebSocketClient.setEventCallback(handleEvent); - WebSocketClient.setFirstConnectCallback(handleFirstConnect); - WebSocketClient.setReconnectCallback(() => reconnect(false)); - WebSocketClient.setMissedEventCallback(() => reconnect(false)); - WebSocketClient.setCloseCallback(handleClose); - WebSocketClient.initialize(connUrl); -} - -export function close() { - WebSocketClient.close(); -} - -function reconnectWebSocket() { - close(); - initialize(); -} - -export function reconnect(includeWebSocket = true) { - if (includeWebSocket) { - reconnectWebSocket(); - } - - loadChannelsForCurrentUser(); - getPosts(ChannelStore.getCurrentId())(dispatch, getState); - StatusActions.loadStatusesForChannelAndSidebar(); - - ErrorStore.clearLastError(); - ErrorStore.emitChange(); -} - -let intervalId = ''; -const SYNC_INTERVAL_MILLISECONDS = 1000 * 60 * 15; // 15 minutes - -export function startPeriodicSync() { - clearInterval(intervalId); - - intervalId = setInterval( - () => { - if (UserStore.getCurrentUser() != null) { - reconnect(false); - } - }, - SYNC_INTERVAL_MILLISECONDS - ); -} - -export function stopPeriodicSync() { - clearInterval(intervalId); -} - -function handleFirstConnect() { - ErrorStore.clearLastError(); - ErrorStore.emitChange(); -} - -function handleClose(failCount) { - if (failCount > MAX_WEBSOCKET_FAILS) { - ErrorStore.storeLastError({message: ErrorBarTypes.WEBSOCKET_PORT_ERROR}); - } - - ErrorStore.setConnectionErrorCount(failCount); - ErrorStore.emitChange(); -} - -function handleEvent(msg) { - switch (msg.event) { - case SocketEvents.POSTED: - case SocketEvents.EPHEMERAL_MESSAGE: - handleNewPostEvent(msg); - break; - - case SocketEvents.POST_EDITED: - handlePostEditEvent(msg); - break; - - case SocketEvents.POST_DELETED: - handlePostDeleteEvent(msg); - break; - - case SocketEvents.LEAVE_TEAM: - handleLeaveTeamEvent(msg); - break; - - case SocketEvents.UPDATE_TEAM: - handleUpdateTeamEvent(msg); - break; - - case SocketEvents.ADDED_TO_TEAM: - handleTeamAddedEvent(msg); - break; - - case SocketEvents.USER_ADDED: - handleUserAddedEvent(msg); - break; - - case SocketEvents.USER_REMOVED: - handleUserRemovedEvent(msg); - break; - - case SocketEvents.USER_UPDATED: - handleUserUpdatedEvent(msg); - break; - - case SocketEvents.MEMBERROLE_UPDATED: - handleUpdateMemberRoleEvent(msg); - break; - - case SocketEvents.CHANNEL_CREATED: - handleChannelCreatedEvent(msg); - break; - - case SocketEvents.CHANNEL_DELETED: - handleChannelDeletedEvent(msg); - break; - - case SocketEvents.CHANNEL_UPDATED: - handleChannelUpdatedEvent(msg); - break; - - case SocketEvents.DIRECT_ADDED: - handleDirectAddedEvent(msg); - break; - - case SocketEvents.PREFERENCE_CHANGED: - handlePreferenceChangedEvent(msg); - break; - - case SocketEvents.PREFERENCES_CHANGED: - handlePreferencesChangedEvent(msg); - break; - - case SocketEvents.PREFERENCES_DELETED: - handlePreferencesDeletedEvent(msg); - break; - - case SocketEvents.TYPING: - handleUserTypingEvent(msg); - break; - - case SocketEvents.STATUS_CHANGED: - handleStatusChangedEvent(msg); - break; - - case SocketEvents.HELLO: - handleHelloEvent(msg); - break; - - case SocketEvents.WEBRTC: - handleWebrtc(msg); - break; - - case SocketEvents.REACTION_ADDED: - handleReactionAddedEvent(msg); - break; - - case SocketEvents.REACTION_REMOVED: - handleReactionRemovedEvent(msg); - break; - - case SocketEvents.EMOJI_ADDED: - handleAddEmoji(msg); - break; - - case SocketEvents.CHANNEL_VIEWED: - handleChannelViewedEvent(msg); - break; - - default: - } -} - -function handleChannelUpdatedEvent(msg) { - const channel = JSON.parse(msg.data.channel); - dispatch({type: ChannelTypes.RECEIVED_CHANNEL, data: channel}); -} - -function handleNewPostEvent(msg) { - const post = JSON.parse(msg.data.post); - handleNewPost(post, msg); - - getProfilesAndStatusesForPosts([post], dispatch, getState); - - if (post.user_id !== UserStore.getCurrentId()) { - UserStore.setStatus(post.user_id, UserStatuses.ONLINE); - } -} - -function handlePostEditEvent(msg) { - // Store post - const post = JSON.parse(msg.data.post); - dispatch({type: PostTypes.RECEIVED_POST, data: post}); - - // Update channel state - if (ChannelStore.getCurrentId() === msg.broadcast.channel_id) { - if (window.isActive) { - viewChannel(ChannelStore.getCurrentId())(dispatch, getState); - } - } - - // Needed for search store - AppDispatcher.handleViewAction({ - type: Constants.ActionTypes.POST_UPDATED, - post - }); -} - -function handlePostDeleteEvent(msg) { - const post = JSON.parse(msg.data.post); - dispatch({type: PostTypes.POST_DELETED, data: post}); - - // Needed for search store - AppDispatcher.handleViewAction({ - type: Constants.ActionTypes.POST_DELETED, - post - }); -} - -async function handleTeamAddedEvent(msg) { - await TeamActions.getTeam(msg.data.team_id)(dispatch, getState); - await TeamActions.getMyTeamMembers()(dispatch, getState); - await TeamActions.getMyTeamUnreads()(dispatch, getState); -} - -function handleLeaveTeamEvent(msg) { - if (UserStore.getCurrentId() === msg.data.user_id) { - TeamStore.removeMyTeamMember(msg.data.team_id); - - // if they are on the team being removed redirect them to default team - if (TeamStore.getCurrentId() === msg.data.team_id) { - BrowserStore.removeGlobalItem('team'); - BrowserStore.removeGlobalItem(msg.data.team_id); - - if (!global.location.pathname.startsWith('/admin_console')) { - GlobalActions.redirectUserToDefaultTeam(); - } - } - - dispatch(batchActions([ - { - type: UserTypes.RECEIVED_PROFILE_NOT_IN_TEAM, - data: {user_id: msg.data.user_id}, - id: msg.data.team_id - }, - { - type: TeamTypes.REMOVE_MEMBER_FROM_TEAM, - data: {team_id: msg.data.team_id, user_id: msg.data.user_id} - } - ])); - } else { - UserStore.removeProfileFromTeam(msg.data.team_id, msg.data.user_id); - TeamStore.removeMemberInTeam(msg.data.team_id, msg.data.user_id); - } -} - -function handleUpdateTeamEvent(msg) { - TeamStore.updateTeam(msg.data.team); -} - -function handleUpdateMemberRoleEvent(msg) { - const member = JSON.parse(msg.data.member); - TeamStore.updateMyRoles(member); -} - -function handleDirectAddedEvent(msg) { - getChannelAndMyMember(msg.broadcast.channel_id)(dispatch, getState); - PreferenceStore.setPreference(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, msg.data.teammate_id, 'true'); - loadProfilesForSidebar(); -} - -function handleUserAddedEvent(msg) { - if (ChannelStore.getCurrentId() === msg.broadcast.channel_id) { - getChannelStats(ChannelStore.getCurrentId())(dispatch, getState); - } - - if (TeamStore.getCurrentId() === msg.data.team_id && UserStore.getCurrentId() === msg.data.user_id) { - getChannelAndMyMember(msg.broadcast.channel_id)(dispatch, getState); - } -} - -function handleUserRemovedEvent(msg) { - if (UserStore.getCurrentId() === msg.broadcast.user_id) { - loadChannelsForCurrentUser(); - - if (msg.data.remover_id !== msg.broadcast.user_id && - msg.data.channel_id === ChannelStore.getCurrentId() && - $('#removed_from_channel').length > 0) { - var sentState = {}; - sentState.channelName = ChannelStore.getCurrent().display_name; - sentState.remover = UserStore.getProfile(msg.data.remover_id).username; - - BrowserStore.setItem('channel-removed-state', sentState); - $('#removed_from_channel').modal('show'); - } - - GlobalActions.toggleSideBarAction(false); - - const townsquare = ChannelStore.getByName('town-square'); - browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/channels/' + townsquare.name); - - dispatch({ - type: ChannelTypes.LEAVE_CHANNEL, - data: {id: msg.data.channel_id, user_id: msg.broadcast.user_id} - }); - } else if (ChannelStore.getCurrentId() === msg.broadcast.channel_id) { - getChannelStats(ChannelStore.getCurrentId())(dispatch, getState); - } -} - -function handleUserUpdatedEvent(msg) { - const user = msg.data.user; - if (UserStore.getCurrentId() !== user.id) { - UserStore.saveProfile(user); - } -} - -function handleChannelCreatedEvent(msg) { - const channelId = msg.data.channel_id; - const teamId = msg.data.team_id; - - if (TeamStore.getCurrentId() === teamId && !ChannelStore.getChannelById(channelId)) { - getChannelAndMyMember(channelId)(dispatch, getState); - } -} - -function handleChannelDeletedEvent(msg) { - if (ChannelStore.getCurrentId() === msg.data.channel_id) { - const teamUrl = TeamStore.getCurrentTeamRelativeUrl(); - browserHistory.push(teamUrl + '/channels/' + Constants.DEFAULT_CHANNEL); - } - dispatch({type: ChannelTypes.RECEIVED_CHANNEL_DELETED, data: {id: msg.data.channel_id, team_id: msg.broadcast.team_id}}, getState); - loadChannelsForCurrentUser(); -} - -function handlePreferenceChangedEvent(msg) { - const preference = JSON.parse(msg.data.preference); - GlobalActions.emitPreferenceChangedEvent(preference); -} - -function handlePreferencesChangedEvent(msg) { - const preferences = JSON.parse(msg.data.preferences); - GlobalActions.emitPreferencesChangedEvent(preferences); -} - -function handlePreferencesDeletedEvent(msg) { - const preferences = JSON.parse(msg.data.preferences); - GlobalActions.emitPreferencesDeletedEvent(preferences); -} - -function handleUserTypingEvent(msg) { - GlobalActions.emitRemoteUserTypingEvent(msg.broadcast.channel_id, msg.data.user_id, msg.data.parent_id); - - if (msg.data.user_id !== UserStore.getCurrentId()) { - UserStore.setStatus(msg.data.user_id, UserStatuses.ONLINE); - } -} - -function handleStatusChangedEvent(msg) { - UserStore.setStatus(msg.data.user_id, msg.data.status); -} - -function handleHelloEvent(msg) { - setServerVersion(msg.data.server_version)(dispatch, getState); -} - -function handleWebrtc(msg) { - const data = msg.data; - return WebrtcActions.handle(data); -} - -function handleReactionAddedEvent(msg) { - const reaction = JSON.parse(msg.data.reaction); - - dispatch({ - type: PostTypes.RECEIVED_REACTION, - data: reaction - }); -} - -function handleAddEmoji(msg) { - const data = JSON.parse(msg.data.emoji); - - dispatch({ - type: EmojiTypes.RECEIVED_CUSTOM_EMOJI, - data - }); -} - -function handleReactionRemovedEvent(msg) { - const reaction = JSON.parse(msg.data.reaction); - - dispatch({ - type: PostTypes.REACTION_DELETED, - data: reaction - }); -} - -function handleChannelViewedEvent(msg) { -// Useful for when multiple devices have the app open to different channels - if (ChannelStore.getCurrentId() !== msg.data.channel_id && - UserStore.getCurrentId() === msg.broadcast.user_id) { - // Mark previous and next channel as read - ChannelStore.resetCounts([msg.data.channel_id]); - } -} diff --git a/webapp/client/web_websocket_client.jsx b/webapp/client/web_websocket_client.jsx deleted file mode 100644 index 775c0ff5932..00000000000 --- a/webapp/client/web_websocket_client.jsx +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import WebSocketClient from './websocket_client.jsx'; - -var WebClient = new WebSocketClient(); -export default WebClient; diff --git a/webapp/client/websocket_client.jsx b/webapp/client/websocket_client.jsx deleted file mode 100644 index eaa059197b3..00000000000 --- a/webapp/client/websocket_client.jsx +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -const MAX_WEBSOCKET_FAILS = 7; -const MIN_WEBSOCKET_RETRY_TIME = 3000; // 3 sec -const MAX_WEBSOCKET_RETRY_TIME = 300000; // 5 mins - -export default class WebSocketClient { - constructor() { - this.conn = null; - this.connectionUrl = null; - this.sequence = 1; - this.eventSequence = 0; - this.connectFailCount = 0; - this.eventCallback = null; - this.responseCallbacks = {}; - this.firstConnectCallback = null; - this.reconnectCallback = null; - this.missedEventCallback = null; - this.errorCallback = null; - this.closeCallback = null; - } - - initialize(connectionUrl = this.connectionUrl, token) { - if (this.conn) { - return; - } - - if (connectionUrl == null) { - console.log('websocket must have connection url'); //eslint-disable-line no-console - return; - } - - if (this.connectFailCount === 0) { - console.log('websocket connecting to ' + connectionUrl); //eslint-disable-line no-console - } - - this.conn = new WebSocket(connectionUrl); - this.connectionUrl = connectionUrl; - - this.conn.onopen = () => { - this.eventSequence = 0; - - if (token) { - this.sendMessage('authentication_challenge', {token}); - } - - if (this.connectFailCount > 0) { - console.log('websocket re-established connection'); //eslint-disable-line no-console - if (this.reconnectCallback) { - this.reconnectCallback(); - } - } else if (this.firstConnectCallback) { - this.firstConnectCallback(); - } - - this.connectFailCount = 0; - }; - - this.conn.onclose = () => { - this.conn = null; - this.sequence = 1; - - if (this.connectFailCount === 0) { - console.log('websocket closed'); //eslint-disable-line no-console - } - - this.connectFailCount++; - - if (this.closeCallback) { - this.closeCallback(this.connectFailCount); - } - - let retryTime = MIN_WEBSOCKET_RETRY_TIME; - - // If we've failed a bunch of connections then start backing off - if (this.connectFailCount > MAX_WEBSOCKET_FAILS) { - retryTime = MIN_WEBSOCKET_RETRY_TIME * this.connectFailCount * this.connectFailCount; - if (retryTime > MAX_WEBSOCKET_RETRY_TIME) { - retryTime = MAX_WEBSOCKET_RETRY_TIME; - } - } - - setTimeout( - () => { - this.initialize(connectionUrl, token); - }, - retryTime - ); - }; - - this.conn.onerror = (evt) => { - if (this.connectFailCount <= 1) { - console.log('websocket error'); //eslint-disable-line no-console - console.log(evt); //eslint-disable-line no-console - } - - if (this.errorCallback) { - this.errorCallback(evt); - } - }; - - this.conn.onmessage = (evt) => { - const msg = JSON.parse(evt.data); - if (msg.seq_reply) { - if (msg.error) { - console.log(msg); //eslint-disable-line no-console - } - - if (this.responseCallbacks[msg.seq_reply]) { - this.responseCallbacks[msg.seq_reply](msg); - Reflect.deleteProperty(this.responseCallbacks, msg.seq_reply); - } - } else if (this.eventCallback) { - if (msg.seq !== this.eventSequence && this.missedEventCallback) { - console.log('missed websocket event, act_seq=' + msg.seq + ' exp_seq=' + this.eventSequence); //eslint-disable-line no-console - this.missedEventCallback(); - } - this.eventSequence = msg.seq + 1; - this.eventCallback(msg); - } - }; - } - - setEventCallback(callback) { - this.eventCallback = callback; - } - - setFirstConnectCallback(callback) { - this.firstConnectCallback = callback; - } - - setReconnectCallback(callback) { - this.reconnectCallback = callback; - } - - setMissedEventCallback(callback) { - this.missedEventCallback = callback; - } - - setErrorCallback(callback) { - this.errorCallback = callback; - } - - setCloseCallback(callback) { - this.closeCallback = callback; - } - - close() { - this.connectFailCount = 0; - this.sequence = 1; - if (this.conn && this.conn.readyState === WebSocket.OPEN) { - this.conn.onclose = () => {}; //eslint-disable-line no-empty-function - this.conn.close(); - this.conn = null; - console.log('websocket closed'); //eslint-disable-line no-console - } - } - - sendMessage(action, data, responseCallback) { - const msg = { - action, - seq: this.sequence++, - data - }; - - if (responseCallback) { - this.responseCallbacks[msg.seq] = responseCallback; - } - - if (this.conn && this.conn.readyState === WebSocket.OPEN) { - this.conn.send(JSON.stringify(msg)); - } else if (!this.conn || this.conn.readyState === WebSocket.CLOSED) { - this.conn = null; - this.initialize(); - } - } - - userTyping(channelId, parentId, callback) { - const data = {}; - data.channel_id = channelId; - data.parent_id = parentId; - - this.sendMessage('user_typing', data, callback); - } - - getStatuses(callback) { - this.sendMessage('get_statuses', null, callback); - } - - getStatusesByIds(userIds, callback) { - const data = {}; - data.user_ids = userIds; - this.sendMessage('get_statuses_by_ids', data, callback); - } -} diff --git a/webapp/components/about_build_modal.jsx b/webapp/components/about_build_modal.jsx deleted file mode 100644 index 4621cfc89f0..00000000000 --- a/webapp/components/about_build_modal.jsx +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {Modal} from 'react-bootstrap'; - -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; - -import PropTypes from 'prop-types'; - -import React from 'react'; -import Constants from 'utils/constants.jsx'; - -export default class AboutBuildModal extends React.Component { - constructor(props) { - super(props); - this.doHide = this.doHide.bind(this); - } - - doHide() { - this.props.onModalDismissed(); - } - - render() { - const config = global.window.mm_config; - const license = global.window.mm_license; - const mattermostLogo = Constants.MATTERMOST_ICON_SVG; - - let title = ( - - ); - - let subTitle = ( - - ); - - let learnMore = ( -
- - - {'mattermost.org'} - -
- ); - - let licensee; - if (config.BuildEnterpriseReady === 'true') { - title = ( - - ); - - subTitle = ( - - ); - - learnMore = ( -
- - - {'about.mattermost.com'} - -
- ); - - if (license.IsLicensed === 'true') { - title = ( - - ); - licensee = ( -
- -  {license.Company} -
- ); - } - } - - let version = '\u00a0' + config.Version; - if (config.BuildNumber !== config.Version) { - version += '\u00a0 (' + config.BuildNumber + ')'; - } - - return ( - - - - - - - -
-
- -
-
-

{'Mattermost'} {title}

-

{subTitle}

-
-
- - {version} -
-
- - {'\u00a0' + config.SQLDriverName} -
-
- {licensee} -
-
-
- {learnMore} -
- -
-
-
-

- -

-
-
-

- -  {config.BuildHash} -
- -  {config.BuildHashEnterprise} -

-

- -  {config.BuildDate} -

-
-
-
- ); - } -} - -AboutBuildModal.defaultProps = { - show: false -}; - -AboutBuildModal.propTypes = { - show: PropTypes.bool.isRequired, - onModalDismissed: PropTypes.func.isRequired -}; diff --git a/webapp/components/access_history_modal/access_history_modal.jsx b/webapp/components/access_history_modal/access_history_modal.jsx deleted file mode 100644 index fdd18669bff..00000000000 --- a/webapp/components/access_history_modal/access_history_modal.jsx +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import LoadingScreen from 'components/loading_screen.jsx'; -import AuditTable from 'components/audit_table.jsx'; - -import UserStore from 'stores/user_store.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -import $ from 'jquery'; -import PropTypes from 'prop-types'; -import React from 'react'; - -import {Modal} from 'react-bootstrap'; -import {FormattedMessage} from 'react-intl'; - -export default class AccessHistoryModal extends React.Component { - static propTypes = { - onHide: PropTypes.func.isRequired, - actions: PropTypes.shape({ - getUserAudits: PropTypes.func.isRequired - }).isRequired - } - - constructor(props) { - super(props); - - this.onAuditChange = this.onAuditChange.bind(this); - this.onShow = this.onShow.bind(this); - this.onHide = this.onHide.bind(this); - - const state = this.getStateFromStoresForAudits(); - state.moreInfo = []; - state.show = true; - - this.state = state; - } - - getStateFromStoresForAudits() { - return { - audits: UserStore.getAudits() - }; - } - - onShow() { - this.props.actions.getUserAudits(UserStore.getCurrentId(), 0, 200); - if (!Utils.isMobile()) { - $('.modal-body').perfectScrollbar(); - } - } - - onHide() { - this.setState({show: false}); - } - - componentDidMount() { - UserStore.addAuditsChangeListener(this.onAuditChange); - this.onShow(); - } - - componentWillUnmount() { - UserStore.removeAuditsChangeListener(this.onAuditChange); - } - - onAuditChange() { - const newState = this.getStateFromStoresForAudits(); - if (!Utils.areObjectsEqual(newState.audits, this.state.audits)) { - this.setState(newState); - } - } - - render() { - let content; - if (this.state.audits.length === 0) { - content = (); - } else { - content = ( - - ); - } - - return ( - - - - - - - - {content} - - - ); - } -} diff --git a/webapp/components/access_history_modal/index.js b/webapp/components/access_history_modal/index.js deleted file mode 100644 index 4842ca730e3..00000000000 --- a/webapp/components/access_history_modal/index.js +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {getUserAudits} from 'mattermost-redux/actions/users'; - -import AccessHistoryModal from './access_history_modal.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getUserAudits - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(AccessHistoryModal); diff --git a/webapp/components/activity_log_modal/activity_log_modal.jsx b/webapp/components/activity_log_modal/activity_log_modal.jsx deleted file mode 100644 index 854a2f0cf35..00000000000 --- a/webapp/components/activity_log_modal/activity_log_modal.jsx +++ /dev/null @@ -1,338 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import LoadingScreen from 'components/loading_screen.jsx'; - -import UserStore from 'stores/user_store.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -import $ from 'jquery'; -import PropTypes from 'prop-types'; -import React from 'react'; -import {Modal} from 'react-bootstrap'; -import {FormattedMessage, FormattedTime, FormattedDate} from 'react-intl'; -import {General} from 'mattermost-redux/constants'; - -export default class ActivityLogModal extends React.Component { - static propTypes = { - onHide: PropTypes.func.isRequired, - actions: PropTypes.shape({ - getSessions: PropTypes.func.isRequired, - revokeSession: PropTypes.func.isRequired - }).isRequired - } - - constructor(props) { - super(props); - - this.submitRevoke = this.submitRevoke.bind(this); - this.onListenerChange = this.onListenerChange.bind(this); - this.handleMoreInfo = this.handleMoreInfo.bind(this); - this.onHide = this.onHide.bind(this); - this.onShow = this.onShow.bind(this); - - const state = this.getStateFromStores(); - state.moreInfo = []; - state.show = true; - - this.state = state; - } - - getStateFromStores() { - return { - sessions: UserStore.getSessions(), - clientError: null - }; - } - - submitRevoke(altId, e) { - e.preventDefault(); - var modalContent = $(e.target).closest('.modal-content'); - modalContent.addClass('animation--highlight'); - setTimeout(() => { - modalContent.removeClass('animation--highlight'); - }, 1500); - this.props.actions.revokeSession(UserStore.getCurrentId(), altId).then(() => { - this.props.actions.getSessions(UserStore.getCurrentId()); - }); - } - - onShow() { - this.props.actions.getSessions(UserStore.getCurrentId()); - if (!Utils.isMobile()) { - $('.modal-body').perfectScrollbar(); - } - } - - onHide() { - this.setState({show: false}); - } - - componentDidMount() { - UserStore.addSessionsChangeListener(this.onListenerChange); - this.onShow(); - } - - componentWillUnmount() { - UserStore.removeSessionsChangeListener(this.onListenerChange); - } - - onListenerChange() { - const newState = this.getStateFromStores(); - if (!Utils.areObjectsEqual(newState.sessions, this.state.sessions)) { - this.setState(newState); - } - } - - handleMoreInfo(index) { - const newMoreInfo = this.state.moreInfo; - newMoreInfo[index] = true; - this.setState({moreInfo: newMoreInfo}); - } - - isMobileSession = (session) => { - return session.device_id && (session.device_id.includes('apple') || session.device_id.includes('android')); - }; - - mobileSessionInfo = (session) => { - let deviceTypeId; - let deviceTypeMessage; - let devicePicture; - - if (session.device_id.includes('apple')) { - devicePicture = 'fa fa-apple'; - deviceTypeId = 'activity_log_modal.iphoneNativeClassicApp'; - deviceTypeMessage = 'iPhone Native Classic App'; - - if (session.device_id.includes(General.PUSH_NOTIFY_APPLE_REACT_NATIVE)) { - deviceTypeId = 'activity_log_modal.iphoneNativeApp'; - deviceTypeMessage = 'iPhone Native App'; - } - } else if (session.device_id.includes('android')) { - devicePicture = 'fa fa-android'; - deviceTypeId = 'activity_log_modal.androidNativeClassicApp'; - deviceTypeMessage = 'Android Native Classic App'; - - if (session.device_id.includes(General.PUSH_NOTIFY_ANDROID_REACT_NATIVE)) { - deviceTypeId = 'activity_log_modal.androidNativeApp'; - deviceTypeMessage = 'Android Native App'; - } - } - - return { - devicePicture, - devicePlatform: ( - - ) - }; - }; - - render() { - const activityList = []; - - for (let i = 0; i < this.state.sessions.length; i++) { - const currentSession = this.state.sessions[i]; - const lastAccessTime = new Date(currentSession.last_activity_at); - const firstAccessTime = new Date(currentSession.create_at); - let devicePlatform = currentSession.props.platform; - let devicePicture = ''; - - if (currentSession.props.type === 'UserAccessToken') { - continue; - } - - if (currentSession.props.platform === 'Windows') { - devicePicture = 'fa fa-windows'; - } else if (this.isMobileSession(currentSession)) { - const sessionInfo = this.mobileSessionInfo(currentSession); - - devicePicture = sessionInfo.devicePicture; - devicePlatform = sessionInfo.devicePlatform; - } else if (currentSession.props.platform === 'Macintosh' || - currentSession.props.platform === 'iPhone') { - devicePicture = 'fa fa-apple'; - } else if (currentSession.props.platform === 'Linux') { - if (currentSession.props.os.indexOf('Android') >= 0) { - devicePlatform = ( - - ); - devicePicture = 'fa fa-android'; - } else { - devicePicture = 'fa fa-linux'; - } - } else if (currentSession.props.os.indexOf('Linux') !== -1) { - devicePicture = 'fa fa-linux'; - } - - if (currentSession.props.browser.indexOf('Desktop App') !== -1) { - devicePlatform = ( - - ); - } - - let moreInfo; - if (this.state.moreInfo[i]) { - moreInfo = ( -
-
- - ), - time: ( - - ) - }} - /> -
-
- -
-
- -
-
- -
-
- ); - } else { - moreInfo = ( - - - - ); - } - - activityList[i] = ( -
-
-
{devicePlatform}
-
-
- - ), - time: ( - - ) - }} - /> -
- {moreInfo} -
-
-
- -
-
- ); - } - - let content; - if (this.state.sessions.loading) { - content = ; - } else { - content =
{activityList}
; - } - - return ( - - - - - - - -

- -

- {content} -
-
- ); - } -} diff --git a/webapp/components/activity_log_modal/index.js b/webapp/components/activity_log_modal/index.js deleted file mode 100644 index 1c4890c655f..00000000000 --- a/webapp/components/activity_log_modal/index.js +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {revokeSession, getSessions} from 'mattermost-redux/actions/users'; - -import ActivityLogModal from './activity_log_modal.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getSessions, - revokeSession - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(ActivityLogModal); diff --git a/webapp/components/add_users_to_team/add_users_to_team.jsx b/webapp/components/add_users_to_team/add_users_to_team.jsx deleted file mode 100644 index b86176c34b6..00000000000 --- a/webapp/components/add_users_to_team/add_users_to_team.jsx +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import MultiSelect from 'components/multiselect/multiselect.jsx'; -import ProfilePicture from 'components/profile_picture.jsx'; - -import {addUsersToTeam} from 'actions/team_actions.jsx'; -import {searchUsersNotInTeam} from 'actions/user_actions.jsx'; - -import UserStore from 'stores/user_store.jsx'; -import TeamStore from 'stores/team_store.jsx'; - -import Constants from 'utils/constants.jsx'; -import {displayEntireNameForUser} from 'utils/utils.jsx'; -import {Client4} from 'mattermost-redux/client'; - -import PropTypes from 'prop-types'; - -import React from 'react'; -import {Modal} from 'react-bootstrap'; -import {FormattedMessage} from 'react-intl'; -import {browserHistory} from 'react-router/es6'; - -import store from 'stores/redux_store.jsx'; -import {searchProfilesNotInCurrentTeam} from 'mattermost-redux/selectors/entities/users'; - -const USERS_PER_PAGE = 50; -const MAX_SELECTABLE_VALUES = 20; - -export default class AddUsersToTeam extends React.Component { - static propTypes = { - onModalDismissed: PropTypes.func, - actions: PropTypes.shape({ - getProfilesNotInTeam: PropTypes.func.isRequired - }).isRequired - } - - constructor(props) { - super(props); - - this.handleHide = this.handleHide.bind(this); - this.handleExit = this.handleExit.bind(this); - this.handleSubmit = this.handleSubmit.bind(this); - this.handleDelete = this.handleDelete.bind(this); - this.onChange = this.onChange.bind(this); - this.search = this.search.bind(this); - this.addValue = this.addValue.bind(this); - this.handlePageChange = this.handlePageChange.bind(this); - - this.searchTimeoutId = 0; - - this.state = { - users: Object.assign([], UserStore.getProfileListNotInTeam(TeamStore.getCurrentId(), true)), - values: [], - show: true, - search: false - }; - } - - componentDidMount() { - UserStore.addChangeListener(this.onChange); - UserStore.addNotInTeamChangeListener(this.onChange); - UserStore.addStatusesChangeListener(this.onChange); - - this.props.actions.getProfilesNotInTeam(TeamStore.getCurrentId(), 0, USERS_PER_PAGE * 2); - } - - componentWillUnmount() { - UserStore.removeChangeListener(this.onChange); - UserStore.removeNotInTeamChangeListener(this.onChange); - UserStore.removeStatusesChangeListener(this.onChange); - } - - handleHide() { - this.setState({show: false}); - } - - handleExit() { - if (this.exitToChannel) { - browserHistory.push(this.exitToChannel); - } - - if (this.props.onModalDismissed) { - this.props.onModalDismissed(); - } - } - - handleSubmit(e) { - if (e) { - e.preventDefault(); - } - - const userIds = this.state.values.map((v) => v.id); - if (userIds.length === 0) { - return; - } - - addUsersToTeam(TeamStore.getCurrentId(), userIds); - - this.handleHide(); - } - - addValue(value) { - const values = Object.assign([], this.state.values); - if (values.indexOf(value) === -1) { - values.push(value); - } - - this.setState({values}); - } - - onChange() { - let users; - if (this.term) { - users = Object.assign([], searchProfilesNotInCurrentTeam(store.getState(), this.term, true)); - } else { - users = Object.assign([], UserStore.getProfileListNotInTeam(TeamStore.getCurrentId(), true)); - } - - for (let i = 0; i < users.length; i++) { - const user = Object.assign({}, users[i]); - user.value = user.id; - user.label = '@' + user.username; - users[i] = user; - } - - this.setState({ - users - }); - } - - handlePageChange(page, prevPage) { - if (page > prevPage) { - this.props.actions.getProfilesNotInTeam(TeamStore.getCurrentId(), page + 1, USERS_PER_PAGE); - } - } - - search(term) { - clearTimeout(this.searchTimeoutId); - this.term = term; - - if (term === '') { - this.onChange(); - return; - } - - this.searchTimeoutId = setTimeout( - () => { - searchUsersNotInTeam(term, TeamStore.getCurrentId(), {}); - }, - Constants.SEARCH_TIMEOUT_MILLISECONDS - ); - } - - handleDelete(values) { - this.setState({values}); - } - - renderOption(option, isSelected, onAdd) { - var rowSelected = ''; - if (isSelected) { - rowSelected = 'more-modal__row--selected'; - } - - return ( -
onAdd(option)} - > - -
-
- {displayEntireNameForUser(option)} -
-
- {option.email} -
-
-
-
- -
-
-
- ); - } - - renderValue(user) { - return user.username; - } - - render() { - const numRemainingText = ( - - ); - - const buttonSubmitText = ( - - ); - - let users = []; - if (this.state.users) { - users = this.state.users.filter((user) => user.delete_at === 0); - } - - return ( - - - - {TeamStore.getCurrent().display_name} - ) - }} - /> - - - - - - - ); - } -} diff --git a/webapp/components/add_users_to_team/index.js b/webapp/components/add_users_to_team/index.js deleted file mode 100644 index d38aeb4e55b..00000000000 --- a/webapp/components/add_users_to_team/index.js +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {getProfilesNotInTeam} from 'mattermost-redux/actions/users'; - -import AddUsersToTeam from './add_users_to_team.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getProfilesNotInTeam - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(AddUsersToTeam); diff --git a/webapp/components/admin_console/admin_console.jsx b/webapp/components/admin_console/admin_console.jsx deleted file mode 100644 index 17670d6ab35..00000000000 --- a/webapp/components/admin_console/admin_console.jsx +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import PropTypes from 'prop-types'; -import 'bootstrap'; - -import AnnouncementBar from 'components/announcement_bar'; -import AdminSidebar from './admin_sidebar.jsx'; - -import {reloadIfServerVersionChanged} from 'actions/global_actions.jsx'; - -export default class AdminConsole extends React.Component { - static propTypes = { - - /* - * Children components to render - */ - children: PropTypes.node.isRequired, - - /* - * Object representing the config file - */ - config: PropTypes.object.isRequired, - - actions: PropTypes.shape({ - - /* - * Function to get the config file - */ - getConfig: PropTypes.func.isRequired - }).isRequired - } - - componentWillMount() { - this.props.actions.getConfig(); - reloadIfServerVersionChanged(); - } - - render() { - const config = this.props.config; - if (Object.keys(config).length === 0) { - return
; - } - if (config && Object.keys(config).length === 0 && config.constructor === 'Object') { - return ( -
- -
-
- ); - } - - // not every page in the system console will need the config, but the vast majority will - const children = React.cloneElement(this.props.children, { - config - }); - return ( -
- -
- - {children} -
-
- ); - } -} diff --git a/webapp/components/admin_console/admin_navbar_dropdown.jsx b/webapp/components/admin_console/admin_navbar_dropdown.jsx deleted file mode 100644 index 6ef4906f56f..00000000000 --- a/webapp/components/admin_console/admin_navbar_dropdown.jsx +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import $ from 'jquery'; -import ReactDOM from 'react-dom'; - -import TeamStore from 'stores/team_store.jsx'; -import Constants from 'utils/constants.jsx'; -import AboutBuildModal from 'components/about_build_modal.jsx'; -import {sortTeamsByDisplayName} from 'utils/team_utils.jsx'; -import * as GlobalActions from 'actions/global_actions.jsx'; - -import {FormattedMessage} from 'react-intl'; - -import {Link} from 'react-router/es6'; - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -export default class AdminNavbarDropdown extends React.Component { - constructor(props) { - super(props); - this.blockToggle = false; - this.onTeamChange = this.onTeamChange.bind(this); - this.handleAboutModal = this.handleAboutModal.bind(this); - this.aboutModalDismissed = this.aboutModalDismissed.bind(this); - - this.state = { - teams: TeamStore.getAll(), - teamMembers: TeamStore.getMyTeamMembers(), - showAboutModal: false - }; - } - - componentDidMount() { - $(ReactDOM.findDOMNode(this.refs.dropdown)).on('hide.bs.dropdown', () => { - this.blockToggle = true; - setTimeout(() => { - this.blockToggle = false; - }, 100); - }); - - TeamStore.addChangeListener(this.onTeamChange); - } - - componentWillUnmount() { - $(ReactDOM.findDOMNode(this.refs.dropdown)).off('hide.bs.dropdown'); - TeamStore.removeChangeListener(this.onTeamChange); - } - - handleAboutModal(e) { - e.preventDefault(); - - this.setState({showAboutModal: true}); - } - - aboutModalDismissed() { - this.setState({showAboutModal: false}); - } - - onTeamChange() { - this.setState({ - teams: TeamStore.getAll(), - teamMembers: TeamStore.getMyTeamMembers() - }); - } - - render() { - var teamsArray = []; // Array of team objects - var teams = []; // Array of team components - let switchTeams; - - if (this.state.teamMembers && this.state.teamMembers.length > 0) { - for (const index in this.state.teamMembers) { - if (this.state.teamMembers.hasOwnProperty(index)) { - const teamMember = this.state.teamMembers[index]; - const team = this.state.teams[teamMember.team_id]; - teamsArray.push(team); - } - } - - // Sort teams alphabetically with display_name - teamsArray = teamsArray.sort(sortTeamsByDisplayName); - - for (const team of teamsArray) { - teams.push( -
  • - - - {team.display_name} - -
  • - ); - } - - teams.push( -
  • - ); - } else { - switchTeams = ( -
  • - - - - -
  • - ); - } - - return ( - - ); - } -} diff --git a/webapp/components/admin_console/admin_settings.jsx b/webapp/components/admin_console/admin_settings.jsx deleted file mode 100644 index 2411fbdb880..00000000000 --- a/webapp/components/admin_console/admin_settings.jsx +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import PropTypes from 'prop-types'; - -import FormError from 'components/form_error.jsx'; -import SaveButton from 'components/admin_console/save_button.jsx'; - -import {saveConfig} from 'actions/admin_actions.jsx'; - -export default class AdminSettings extends React.Component { - static propTypes = { - - /* - * Object representing the config file - */ - config: PropTypes.object - } - - constructor(props) { - super(props); - - this.handleChange = this.handleChange.bind(this); - this.handleSubmit = this.handleSubmit.bind(this); - this.doSubmit = this.doSubmit.bind(this); - - this.state = Object.assign(this.getStateFromConfig(props.config), { - saveNeeded: false, - saving: false, - serverError: null - }); - } - - handleChange(id, value) { - this.setState({ - saveNeeded: true, - [id]: value - }); - } - - handleSubmit(e) { - e.preventDefault(); - - this.doSubmit(); - } - - doSubmit(callback) { - this.setState({ - saving: true, - serverError: null - }); - - // clone config so that we aren't modifying data in the stores - let config = JSON.parse(JSON.stringify(this.props.config)); - config = this.getConfigFromState(config); - - saveConfig( - config, - (savedConfig) => { - this.setState(this.getStateFromConfig(savedConfig)); - - this.setState({ - saveNeeded: false, - saving: false - }); - - if (callback) { - callback(); - } - - if (this.handleSaved) { - this.handleSaved(config); - } - }, - (err) => { - this.setState({ - saving: false, - serverError: err.message - }); - - if (callback) { - callback(); - } - - if (this.handleSaved) { - this.handleSaved(config); - } - } - ); - } - - parseInt(str, defaultValue) { - const n = parseInt(str, 10); - - if (isNaN(n)) { - if (defaultValue) { - return defaultValue; - } - return 0; - } - - return n; - } - - parseIntNonZero(str, defaultValue) { - const n = parseInt(str, 10); - - if (isNaN(n) || n < 1) { - if (defaultValue) { - return defaultValue; - } - return 1; - } - - return n; - } - - render() { - return ( -
    -

    - {this.renderTitle()} -

    -
    - {this.renderSettings()} -
    - -
    -
    -
    - -
    -
    -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/admin_sidebar.jsx b/webapp/components/admin_console/admin_sidebar.jsx deleted file mode 100644 index 4918cdac056..00000000000 --- a/webapp/components/admin_console/admin_sidebar.jsx +++ /dev/null @@ -1,702 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import $ from 'jquery'; -import PropTypes from 'prop-types'; -import React from 'react'; -import {FormattedMessage} from 'react-intl'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSidebarCategory from './admin_sidebar_category.jsx'; -import AdminSidebarHeader from './admin_sidebar_header.jsx'; -import AdminSidebarSection from './admin_sidebar_section.jsx'; - -export default class AdminSidebar extends React.Component { - static get contextTypes() { - return { - router: PropTypes.object.isRequired - }; - } - - constructor(props) { - super(props); - - this.updateTitle = this.updateTitle.bind(this); - } - - componentDidMount() { - this.updateTitle(); - - if (!Utils.isMobile()) { - $('.admin-sidebar .nav-pills__container').perfectScrollbar({ - suppressScrollX: true - }); - } - } - - componentDidUpdate() { - if (!Utils.isMobile()) { - $('.admin-sidebar .nav-pills__container').perfectScrollbar({ - suppressScrollX: true - }); - } - } - - updateTitle() { - let currentSiteName = ''; - if (global.window.mm_config.SiteName != null) { - currentSiteName = global.window.mm_config.SiteName; - } - - document.title = Utils.localizeMessage('sidebar_right_menu.console', 'System Console') + ' - ' + currentSiteName; - } - - render() { - let oauthSettings = null; - let ldapSettings = null; - let samlSettings = null; - let clusterSettings = null; - let metricsSettings = null; - let complianceSettings = null; - let mfaSettings = null; - let pluginSettings = null; - - let license = null; - let audits = null; - let policy = null; - - if (window.mm_config.BuildEnterpriseReady === 'true') { - license = ( - - } - /> - ); - } - - if (window.mm_license.IsLicensed === 'true') { - if (global.window.mm_license.LDAP === 'true') { - ldapSettings = ( - - } - /> - ); - } - - if (global.window.mm_license.Cluster === 'true') { - clusterSettings = ( - - } - /> - ); - } - - if (global.window.mm_license.Metrics === 'true') { - metricsSettings = ( - - } - /> - ); - } - - if (global.window.mm_license.SAML === 'true') { - samlSettings = ( - - } - /> - ); - } - - if (global.window.mm_license.Compliance === 'true') { - complianceSettings = ( - - } - /> - ); - } - - if (global.window.mm_license.MFA === 'true') { - mfaSettings = ( - - } - /> - ); - } - - oauthSettings = ( - - } - /> - ); - - policy = ( - - } - /> - ); - } else { - oauthSettings = ( - - } - /> - ); - } - - if (window.mm_license.IsLicensed === 'true') { - audits = ( - - } - /> - ); - } - - let customBranding = null; - - if (window.mm_license.IsLicensed === 'true') { - customBranding = ( - - } - /> - ); - } - - let otherCategory = null; - if (license || audits) { - otherCategory = ( - - } - > - {license} - {audits} - - ); - } - - const webrtcSettings = ( - - } - /> - ); - - let elasticSearchSettings = null; - if (window.mm_license.IsLicensed === 'true') { - elasticSearchSettings = ( - - } - /> - ); - } - - if (window.mm_config.PluginsEnabled === 'true' && window.mm_license.IsLicensed === 'true') { - pluginSettings = ( - - } - /> - ); - } - - const SHOW_CLIENT_VERSIONS = false; - let clientVersions = null; - if (SHOW_CLIENT_VERSIONS) { - clientVersions = ( - - } - /> - ); - } - - return ( -
    - -
    -
      - - } - > - - } - /> - - } - /> - - } - /> - - } - /> - - - } - > - - } - > - - } - /> - - } - /> - - } - /> - {policy} - - } - /> - {complianceSettings} - - } - /> - - - } - > - - } - /> - {oauthSettings} - {ldapSettings} - {samlSettings} - {mfaSettings} - - - } - > - - } - /> - - } - /> - - } - /> - - } - /> - - } - /> - {clientVersions} - - - } - > - - } - /> - - } - /> - - - } - > - - } - /> - - } - /> - {webrtcSettings} - - } - /> - {pluginSettings} - - - } - > - - } - /> - - - } - > - {customBranding} - - - } - /> - - - } - /> - - } - /> - - - } - /> - - - } - > - - } - /> - - } - /> - {elasticSearchSettings} - - } - /> - {clusterSettings} - {metricsSettings} - - - {otherCategory} -
    -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/admin_sidebar_category.jsx b/webapp/components/admin_console/admin_sidebar_category.jsx deleted file mode 100644 index 5db68e87669..00000000000 --- a/webapp/components/admin_console/admin_sidebar_category.jsx +++ /dev/null @@ -1,86 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import {Link} from 'react-router/es6'; - -export default class AdminSidebarCategory extends React.Component { - static get propTypes() { - return { - name: PropTypes.string, - title: PropTypes.node.isRequired, - icon: PropTypes.string.isRequired, - sectionClass: PropTypes.string, - parentLink: PropTypes.string, - children: PropTypes.node, - action: PropTypes.node - }; - } - - static get defaultProps() { - return { - parentLink: '' - }; - } - - static get contextTypes() { - return { - router: PropTypes.object.isRequired - }; - } - - render() { - let link = this.props.parentLink; - let title = ( -
    - - - {this.props.title} - - {this.props.action} -
    - ); - - if (this.props.name) { - link += '/' + name; - title = ( - - {title} - - ); - } - - let clonedChildren = null; - if (this.props.children && this.context.router.isActive(link)) { - clonedChildren = ( -
      - { - React.Children.map(this.props.children, (child) => { - if (child === null) { - return null; - } - - return React.cloneElement(child, { - parentLink: link - }); - }) - } -
    - ); - } - - return ( -
  • - {title} - {clonedChildren} -
  • - ); - } -} diff --git a/webapp/components/admin_console/admin_sidebar_header.jsx b/webapp/components/admin_console/admin_sidebar_header.jsx deleted file mode 100644 index 1c64eb6d18c..00000000000 --- a/webapp/components/admin_console/admin_sidebar_header.jsx +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import $ from 'jquery'; -import AdminNavbarDropdown from './admin_navbar_dropdown.jsx'; -import UserStore from 'stores/user_store.jsx'; -import {Client4} from 'mattermost-redux/client'; - -import {FormattedMessage} from 'react-intl'; - -import React from 'react'; - -export default class SidebarHeader extends React.Component { - constructor(props) { - super(props); - - this.state = {}; - } - - toggleDropdown = (e) => { - e.preventDefault(); - - if (this.refs.dropdown.blockToggle) { - this.refs.dropdown.blockToggle = false; - return; - } - - $('.team__header').find('.dropdown-toggle').dropdown('toggle'); - } - - render() { - var me = UserStore.getCurrentUser(); - var profilePicture = null; - - if (!me) { - return null; - } - - if (me.last_picture_update) { - profilePicture = ( - - ); - } - - return ( - - ); - } -} diff --git a/webapp/components/admin_console/admin_sidebar_section.jsx b/webapp/components/admin_console/admin_sidebar_section.jsx deleted file mode 100644 index 2a8ecab719e..00000000000 --- a/webapp/components/admin_console/admin_sidebar_section.jsx +++ /dev/null @@ -1,102 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import {Link} from 'react-router/es6'; -import * as Utils from 'utils/utils.jsx'; - -export default class AdminSidebarSection extends React.Component { - static get propTypes() { - return { - name: PropTypes.string.isRequired, - title: PropTypes.node.isRequired, - type: PropTypes.string, - parentLink: PropTypes.string, - subsection: PropTypes.bool, - children: PropTypes.node, - action: PropTypes.node, - onlyActiveOnIndex: PropTypes.bool - }; - } - - static get defaultProps() { - return { - parentLink: '', - subsection: false, - children: [], - onlyActiveOnIndex: true - }; - } - - getLink() { - return this.props.parentLink + '/' + this.props.name; - } - - render() { - const link = this.getLink(); - - let clonedChildren = null; - if (this.props.children) { - clonedChildren = ( -
      - { - React.Children.map(this.props.children, (child) => { - if (child === null) { - return null; - } - - return React.cloneElement(child, { - parentLink: link, - subsection: true - }); - }) - } -
    - ); - } - - let className = 'sidebar-section'; - if (this.props.subsection) { - className += ' sidebar-subsection'; - } - - let sidebarItem = ( - - - {this.props.title} - - {this.props.action} - - ); - - if (this.props.type === 'text') { - sidebarItem = ( -
    - - {this.props.title} - - {this.props.action} -
    - ); - } - - return ( -
  • - {sidebarItem} - {clonedChildren} -
  • - ); - } -} diff --git a/webapp/components/admin_console/audits/audits.jsx b/webapp/components/admin_console/audits/audits.jsx deleted file mode 100644 index 0811c216f0c..00000000000 --- a/webapp/components/admin_console/audits/audits.jsx +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import LoadingScreen from 'components/loading_screen.jsx'; -import AuditTable from 'components/audit_table.jsx'; -import ComplianceReports from 'components/admin_console/compliance_reports'; - -import React from 'react'; -import PropTypes from 'prop-types'; -import {FormattedMessage} from 'react-intl'; - -export default class Audits extends React.PureComponent { - static propTypes = { - - /* - * Array of audits to render - */ - audits: PropTypes.arrayOf(PropTypes.object).isRequired, - - actions: PropTypes.shape({ - - /* - * Function to fetch audits - */ - getAudits: PropTypes.func.isRequired - }).isRequired - } - - constructor(props) { - super(props); - - this.state = { - loadingAudits: true - }; - } - - componentDidMount() { - this.props.actions.getAudits().then( - () => this.setState({loadingAudits: false}) - ); - } - - reload = () => { - this.setState({loadingAudits: true}); - this.props.actions.getAudits().then( - () => this.setState({loadingAudits: false}) - ); - } - - render() { - let content = null; - - if (global.window.mm_license.IsLicensed !== 'true') { - return
    ; - } - - if (this.state.loadingAudits) { - content = ; - } else { - content = ( -
    - -
    - ); - } - - return ( -
    - - -
    -

    - - -

    -
    - {content} -
    -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/audits/index.js b/webapp/components/admin_console/audits/index.js deleted file mode 100644 index a48e335382a..00000000000 --- a/webapp/components/admin_console/audits/index.js +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {getAudits} from 'mattermost-redux/actions/admin'; - -import * as Selectors from 'mattermost-redux/selectors/entities/admin'; - -import Audits from './audits.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps, - audits: Object.values(Selectors.getAudits(state)) - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getAudits - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(Audits); diff --git a/webapp/components/admin_console/banner.jsx b/webapp/components/admin_console/banner.jsx deleted file mode 100644 index 6395ef4a1c1..00000000000 --- a/webapp/components/admin_console/banner.jsx +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import PropTypes from 'prop-types'; -import {FormattedMessage} from 'react-intl'; - -export default function Banner(props) { - let title = ( - - ); - - if (props.title) { - title = props.title; - } - - return ( -
    -
    -

    - {title} -

    -

    - {props.description} -

    -
    -
    - ); -} - -Banner.defaultProps = { -}; -Banner.propTypes = { - title: PropTypes.node, - description: PropTypes.node.isRequired -}; diff --git a/webapp/components/admin_console/boolean_setting.jsx b/webapp/components/admin_console/boolean_setting.jsx deleted file mode 100644 index 45c23c86902..00000000000 --- a/webapp/components/admin_console/boolean_setting.jsx +++ /dev/null @@ -1,99 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import Setting from './setting.jsx'; - -import {FormattedMessage} from 'react-intl'; - -import * as Utils from 'utils/utils.jsx'; - -export default class BooleanSetting extends React.Component { - constructor(props) { - super(props); - - this.handleChange = this.handleChange.bind(this); - } - - handleChange(e) { - this.props.onChange(this.props.id, e.target.value === 'true'); - } - - render() { - let helpText; - if (this.props.disabled && this.props.disabledText) { - helpText = ( -
    - - {this.props.disabledText} - - {this.props.helpText} -
    - ); - } else { - helpText = this.props.helpText; - } - - return ( - - - - - ); - } -} -BooleanSetting.defaultProps = { - trueText: ( - - ), - falseText: ( - - ), - disabled: false -}; - -BooleanSetting.propTypes = { - id: PropTypes.string.isRequired, - label: PropTypes.node.isRequired, - value: PropTypes.bool.isRequired, - onChange: PropTypes.func.isRequired, - trueText: PropTypes.node, - falseText: PropTypes.node, - disabled: PropTypes.bool.isRequired, - disabledText: PropTypes.node, - helpText: PropTypes.node.isRequired -}; diff --git a/webapp/components/admin_console/brand_image_setting.jsx b/webapp/components/admin_console/brand_image_setting.jsx deleted file mode 100644 index d2eae3f6e4b..00000000000 --- a/webapp/components/admin_console/brand_image_setting.jsx +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import $ from 'jquery'; -import PropTypes from 'prop-types'; -import React from 'react'; - -import {Client4} from 'mattermost-redux/client'; -import * as Utils from 'utils/utils.jsx'; -import {uploadBrandImage} from 'actions/admin_actions.jsx'; - -import FormError from 'components/form_error.jsx'; -import {FormattedHTMLMessage, FormattedMessage} from 'react-intl'; - -const HTTP_STATUS_OK = 200; - -export default class BrandImageSetting extends React.PureComponent { - static propTypes = { - - /* - * Set to disable the setting - */ - disabled: PropTypes.bool.isRequired - } - - constructor(props) { - super(props); - - this.handleImageChange = this.handleImageChange.bind(this); - this.handleImageSubmit = this.handleImageSubmit.bind(this); - - this.state = { - brandImage: null, - brandImageExists: false, - brandImageTimestamp: Date.now(), - uploading: false, - uploadCompleted: false, - error: '' - }; - } - - componentWillMount() { - fetch(Client4.getBrandImageUrl(this.state.brandImageTimestamp)).then( - (resp) => { - if (resp.status === HTTP_STATUS_OK) { - this.setState({brandImageExists: true}); - } else { - this.setState({brandImageExists: false}); - } - } - ); - } - - componentDidUpdate() { - if (this.refs.image) { - const reader = new FileReader(); - - const img = this.refs.image; - reader.onload = (e) => { - $(img).attr('src', e.target.result); - }; - - reader.readAsDataURL(this.state.brandImage); - } - } - - handleImageChange() { - const element = $(this.refs.fileInput); - - if (element.prop('files').length > 0) { - this.setState({ - brandImage: element.prop('files')[0] - }); - } - } - - handleImageSubmit(e) { - e.preventDefault(); - - if (!this.state.brandImage) { - return; - } - - if (this.state.uploading) { - return; - } - - $(this.refs.upload).button('loading'); - - this.setState({ - uploading: true, - error: '' - }); - - uploadBrandImage( - this.state.brandImage, - () => { - $(this.refs.upload).button('complete'); - - this.setState({ - brandImageExists: true, - brandImage: null, - brandImageTimestamp: Date.now(), - uploading: false - }); - }, - (err) => { - $(this.refs.upload).button('reset'); - - this.setState({ - uploading: false, - error: err.message - }); - } - ); - } - - render() { - let btnPrimaryClass = 'btn'; - if (this.state.brandImage) { - btnPrimaryClass += ' btn-primary'; - } - - let letbtnDefaultClass = 'btn'; - if (!this.props.disabled) { - letbtnDefaultClass += ' btn-default'; - } - - let img = null; - if (this.state.brandImage) { - img = ( - - ); - } else if (this.state.brandImageExists) { - img = ( - - ); - } else { - img = ( -

    - -

    - ); - } - - return ( -
    - -
    - {img} -
    -
    -
    -
    - - -
    - -
    - -

    - -

    -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/client_versions_settings.jsx b/webapp/components/admin_console/client_versions_settings.jsx deleted file mode 100644 index 0c9a5f58aec..00000000000 --- a/webapp/components/admin_console/client_versions_settings.jsx +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class ClientVersionsSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ClientRequirements.AndroidLatestVersion = this.state.androidLatestVersion; - config.ClientRequirements.AndroidMinVersion = this.state.androidMinVersion; - config.ClientRequirements.DesktopLatestVersion = this.state.desktopLatestVersion; - config.ClientRequirements.DesktopMinVersion = this.state.desktopMinVersion; - config.ClientRequirements.IosLatestVersion = this.state.iosLatestVersion; - config.ClientRequirements.IosMinVersion = this.state.iosMinVersion; - - return config; - } - - getStateFromConfig(config) { - return { - androidLatestVersion: config.ClientRequirements.AndroidLatestVersion, - androidMinVersion: config.ClientRequirements.AndroidMinVersion, - desktopLatestVersion: config.ClientRequirements.DesktopLatestVersion, - desktopMinVersion: config.ClientRequirements.DesktopMinVersion, - iosLatestVersion: config.ClientRequirements.IosLatestVersion, - iosMinVersion: config.ClientRequirements.IosMinVersion - }; - } - - renderTitle() { - return ( -

    - -

    - ); - } - - renderSettings() { - return ( - - - } - placeholder={Utils.localizeMessage('admin.client_versions.androidLatestVersion', 'X.X.X')} - helpText={ - - } - value={this.state.androidLatestVersion} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.client_versions.androidMinVersion', 'X.X.X')} - helpText={ - - } - value={this.state.androidMinVersion} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.client_versions.desktopLatestVersion', 'X.X.X')} - helpText={ - - } - value={this.state.desktopLatestVersion} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.client_versions.desktopMinVersion', 'X.X.X')} - helpText={ - - } - value={this.state.desktopMinVersion} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.client_versions.iosLatestVersion', 'X.X.X')} - helpText={ - - } - value={this.state.iosLatestVersion} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.client_versions.iosMinVersion', 'X.X.X')} - helpText={ - - } - value={this.state.iosMinVersion} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/cluster_settings.jsx b/webapp/components/admin_console/cluster_settings.jsx deleted file mode 100644 index 36f86f0ef51..00000000000 --- a/webapp/components/admin_console/cluster_settings.jsx +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import TextSetting from './text_setting.jsx'; - -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import ClusterTableContainer from './cluster_table_container.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -import {Client4} from 'mattermost-redux/client'; - -export default class ClusterSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - this.renderSettings = this.renderSettings.bind(this); - this.overrideHandleChange = this.overrideHandleChange.bind(this); - } - - getConfigFromState(config) { - config.ClusterSettings.Enable = this.state.Enable; - config.ClusterSettings.ClusterName = this.state.ClusterName; - config.ClusterSettings.OverrideHostname = this.state.OverrideHostname; - config.ClusterSettings.UseIpAddress = this.state.UseIpAddress; - config.ClusterSettings.UseExperimentalGossip = this.state.UseExperimentalGossip; - config.ClusterSettings.ReadOnlyConfig = this.state.ReadOnlyConfig; - config.ClusterSettings.GossipPort = this.parseIntNonZero(this.state.GossipPort, 8074); - config.ClusterSettings.StreamingPort = this.parseIntNonZero(this.state.StreamingPort, 8075); - return config; - } - - getStateFromConfig(config) { - const settings = config.ClusterSettings; - - return { - Enable: settings.Enable, - ClusterName: settings.ClusterName, - OverrideHostname: settings.OverrideHostname, - UseIpAddress: settings.UseIpAddress, - UseExperimentalGossip: settings.UseExperimentalGossip, - ReadOnlyConfig: settings.ReadOnlyConfig, - GossipPort: settings.GossipPort, - StreamingPort: settings.StreamingPort, - showWarning: false - }; - } - - renderTitle() { - return ( - - ); - } - - overrideHandleChange(id, value) { - this.setState({ - showWarning: true - }); - - this.handleChange(id, value); - } - - renderSettings() { - const licenseEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.Cluster === 'true'; - if (!licenseEnabled) { - return null; - } - - var configLoadedFromCluster = null; - - if (Client4.clusterId) { - configLoadedFromCluster = ( -
    - - -
    - ); - } - - var warning = null; - if (this.state.showWarning) { - warning = ( -
    - - -
    - ); - } - - var clusterTableContainer = null; - if (this.state.Enable) { - clusterTableContainer = (); - } - - return ( - - {configLoadedFromCluster} - {clusterTableContainer} -
    - -
    - {warning} - - } - helpText={ - - } - value={this.state.Enable} - onChange={this.overrideHandleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.cluster.ClusterNameEx', 'Ex "Production" or "Staging"')} - helpText={ - - } - value={this.state.ClusterName} - onChange={this.overrideHandleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.cluster.OverrideHostnameEx', 'Ex "app-server-01"')} - helpText={ - - } - value={this.state.OverrideHostname} - onChange={this.overrideHandleChange} - /> - - } - helpText={ - - } - value={this.state.UseIpAddress} - onChange={this.overrideHandleChange} - /> - - } - helpText={ - - } - value={this.state.UseExperimentalGossip} - onChange={this.overrideHandleChange} - /> - - } - helpText={ - - } - value={this.state.ReadOnlyConfig} - onChange={this.overrideHandleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.cluster.GossipPortEx', 'Ex "8074"')} - helpText={ - - } - value={this.state.GossipPort} - onChange={this.overrideHandleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.cluster.StreamingPortEx', 'Ex "8075"')} - helpText={ - - } - value={this.state.StreamingPort} - onChange={this.overrideHandleChange} - /> -
    - ); - } -} diff --git a/webapp/components/admin_console/cluster_table.jsx b/webapp/components/admin_console/cluster_table.jsx deleted file mode 100644 index e7157635d00..00000000000 --- a/webapp/components/admin_console/cluster_table.jsx +++ /dev/null @@ -1,172 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import {FormattedMessage} from 'react-intl'; -import * as Utils from 'utils/utils.jsx'; - -import statusGreen from 'images/status_green.png'; -import statusYellow from 'images/status_yellow.png'; - -export default class ClusterTable extends React.Component { - static propTypes = { - clusterInfos: PropTypes.array.isRequired, - reload: PropTypes.func.isRequired - } - - render() { - var versionMismatch = ( - - ); - - var configMismatch = ( - - ); - - var version = ''; - var configHash = ''; - var singleItem = false; - - if (this.props.clusterInfos.length) { - version = this.props.clusterInfos[0].version; - configHash = this.props.clusterInfos[0].config_hash; - singleItem = this.props.clusterInfos.length === 1; - } - - this.props.clusterInfos.map((clusterInfo) => { - if (clusterInfo.version !== version) { - versionMismatch = ( - - ); - } - - if (clusterInfo.config_hash !== configHash) { - configMismatch = ( - - ); - } - - return null; - }); - - var items = this.props.clusterInfos.map((clusterInfo) => { - var status = null; - - if (clusterInfo.hostname === '') { - clusterInfo.hostname = Utils.localizeMessage('admin.cluster.unknown', 'unknown'); - } - - if (clusterInfo.version === '') { - clusterInfo.version = Utils.localizeMessage('admin.cluster.unknown', 'unknown'); - } - - if (clusterInfo.config_hash === '') { - clusterInfo.config_hash = Utils.localizeMessage('admin.cluster.unknown', 'unknown'); - } - - if (singleItem) { - status = ( - - ); - } else { - status = ( - - ); - } - - return ( - - {status} - {clusterInfo.hostname} - {versionMismatch} {clusterInfo.version} -
    {configMismatch} {clusterInfo.config_hash}
    - {clusterInfo.ipaddress} - - ); - }); - - return ( -
    -
    - -
    - - - - - - - - - - - - {items} - -
    - - - - - - - - - -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/cluster_table_container.jsx b/webapp/components/admin_console/cluster_table_container.jsx deleted file mode 100644 index 7a67bb84251..00000000000 --- a/webapp/components/admin_console/cluster_table_container.jsx +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import ClusterTable from './cluster_table.jsx'; -import LoadingScreen from '../loading_screen.jsx'; - -import {getClusterStatus} from 'actions/admin_actions.jsx'; - -export default class ClusterTableContainer extends React.Component { - constructor(props) { - super(props); - - this.load = this.load.bind(this); - this.reload = this.reload.bind(this); - - this.interval = null; - - this.state = { - clusterInfos: null - }; - } - - load() { - getClusterStatus( - (data) => { - this.setState({ - clusterInfos: data - }); - }, - null - ); - } - - componentWillMount() { - this.load(); - - // reload the cluster status every 15 seconds - this.interval = setInterval(this.load, 15000); - } - - componentWillUnmount() { - if (this.interval) { - clearInterval(this.interval); - } - } - - reload(e) { - if (e) { - e.preventDefault(); - } - - this.setState({ - clusterInfos: null - }); - - this.load(); - } - - render() { - if (this.state.clusterInfos == null) { - return (); - } - - return ( - - ); - } -} diff --git a/webapp/components/admin_console/color_setting.jsx b/webapp/components/admin_console/color_setting.jsx deleted file mode 100644 index 483b585eefe..00000000000 --- a/webapp/components/admin_console/color_setting.jsx +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import Setting from './setting.jsx'; - -import React from 'react'; -import PropTypes from 'prop-types'; -import {ChromePicker} from 'react-color'; - -export default class ColorSetting extends React.PureComponent { - static propTypes = { - - /* - * The unique identifer for the admin console setting - */ - id: PropTypes.string.isRequired, - - /* - * The text/jsx display name for the setting - */ - label: PropTypes.node.isRequired, - - /* - * The text/jsx help text to display underneath the setting - */ - helpText: PropTypes.node, - - /* - * The hex color value - */ - value: PropTypes.string.isRequired, - - /* - * Function called when the input changes - */ - onChange: PropTypes.func, - - /* - * Set to disable the setting - */ - disabled: PropTypes.bool - } - - constructor(props) { - super(props); - - this.state = { - showPicker: false - }; - } - - componentDidMount() { - document.addEventListener('click', this.closePicker); - } - - componentWillUnmount() { - document.removeEventListener('click', this.closePicker); - } - - handleChange = (color) => { - this.props.onChange(this.props.id, color.hex); - } - - togglePicker = () => { - if (this.props.disabled) { - this.setState({showPicker: false}); - } - this.setState({showPicker: !this.state.showPicker}); - } - - closePicker = (e) => { - if (!e.target.closest('.picker-' + this.props.id)) { - this.setState({showPicker: false}); - } - } - - onTextInput = (e) => { - this.props.onChange(this.props.id, e.target.value); - } - - render() { - let picker; - if (this.state.showPicker) { - picker = ( -
    - -
    - ); - } - - return ( - -
    - - - - - {picker} -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/compliance_reports/compliance_reports.jsx b/webapp/components/admin_console/compliance_reports/compliance_reports.jsx deleted file mode 100644 index af361bace16..00000000000 --- a/webapp/components/admin_console/compliance_reports/compliance_reports.jsx +++ /dev/null @@ -1,394 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import LoadingScreen from 'components/loading_screen.jsx'; - -import * as Utils from 'utils/utils.jsx'; -import UserStore from 'stores/user_store.jsx'; -import {Client4} from 'mattermost-redux/client'; - -import React from 'react'; -import PropTypes from 'prop-types'; -import {FormattedMessage, FormattedDate, FormattedTime} from 'react-intl'; - -export default class ComplianceReports extends React.PureComponent { - static propTypes = { - - /* - * Set if compliance reports are enabled in the config - */ - enabled: PropTypes.bool.isRequired, - - /* - * Array of reports to render - */ - reports: PropTypes.arrayOf(PropTypes.object).isRequired, - - /* - * Error message to display - */ - serverError: PropTypes.string, - - actions: PropTypes.shape({ - - /* - * Function to get compliance reports - */ - getComplianceReports: PropTypes.func.isRequired, - - /* - * Function to save compliance reports - */ - createComplianceReport: PropTypes.func.isRequired - }).isRequired - } - - constructor(props) { - super(props); - - this.state = { - loadingReports: true - }; - } - - componentDidMount() { - if (global.window.mm_license.IsLicensed !== 'true' || !this.props.enabled) { - return; - } - - this.props.actions.getComplianceReports().then( - () => this.setState({loadingReports: false}) - ); - } - - reload = () => { - this.setState({loadingReports: true}); - - this.props.actions.getComplianceReports().then( - () => this.setState({loadingReports: false}) - ); - } - - runReport = (e) => { - e.preventDefault(); - - this.setState({runningReport: true}); - - const job = {}; - job.desc = this.refs.desc.value; - job.emails = this.refs.emails.value; - job.keywords = this.refs.keywords.value; - job.start_at = Date.parse(this.refs.from.value); - job.end_at = Date.parse(this.refs.to.value); - - this.props.actions.createComplianceReport(job).then( - (data) => { - if (data) { - this.refs.emails.value = ''; - this.refs.keywords.value = ''; - this.refs.desc.value = ''; - this.refs.from.value = ''; - this.refs.to.value = ''; - } - this.setState({runningReport: false}); - } - ); - } - - getDateTime(millis) { - const date = new Date(millis); - return ( - - - {' - '} - - - ); - } - - render() { - if (global.window.mm_license.IsLicensed !== 'true' || !this.props.enabled) { - return
    ; - } - - let content = null; - if (this.state.loadingReports) { - content = ; - } else { - var list = []; - - for (var i = 0; i < this.props.reports.length; i++) { - const report = this.props.reports[i]; - - let params = ''; - if (report.type === 'adhoc') { - params = ( - - {' '}{this.getDateTime(report.start_at)} -
    - {' '}{this.getDateTime(report.end_at)} -
    - {' '}{report.emails} -
    - {' '}{report.keywords} -
    ); - } - - let download = ''; - if (report.status === 'finished') { - download = ( - - - - ); - } - - let status = report.status; - if (report.status === 'finished') { - status = ( - {report.status} - ); - } - - if (report.status === 'failed') { - status = ( - {report.status} - ); - } - - let user = report.user_id; - const profile = UserStore.getProfile(report.user_id); - if (profile) { - user = profile.email; - } - - list[i] = ( - - {download} - {this.getDateTime(report.create_at)} - {status} - {report.count} - {report.type} - {report.desc} - {user} - {params} - - ); - } - - content = ( -
    - - - - - - - - - - - - - - {list} - -
    - - - - - - - - - - - - - - -
    -
    - ); - } - - let serverError = ''; - if (this.props.serverError) { - serverError = ( -
    - -
    - ); - } - - return ( -
    -

    - -

    -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    -
    -
    - - -
    -
    - - -
    -
    -
    - -
    - {serverError} -
    - -
    -
    - {content} -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/compliance_reports/index.js b/webapp/components/admin_console/compliance_reports/index.js deleted file mode 100644 index 1cbf669e5c3..00000000000 --- a/webapp/components/admin_console/compliance_reports/index.js +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {getComplianceReports, createComplianceReport} from 'mattermost-redux/actions/admin'; - -import {getComplianceReports as selectComplianceReports, getConfig} from 'mattermost-redux/selectors/entities/admin'; - -import ComplianceReports from './compliance_reports.jsx'; - -function mapStateToProps(state, ownProps) { - let enabled = false; - const config = getConfig(state); - if (config && config.ComplianceSettings) { - enabled = config.ComplianceSettings.Enable; - } - - let serverError; - const error = state.requests.admin.createCompliance.error; - if (error) { - serverError = error.message; - } - - const reports = Object.values(selectComplianceReports(state)).sort((a, b) => { - return b.create_at - a.create_at; - }); - - return { - ...ownProps, - enabled, - reports, - serverError - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getComplianceReports, - createComplianceReport - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(ComplianceReports); diff --git a/webapp/components/admin_console/compliance_settings.jsx b/webapp/components/admin_console/compliance_settings.jsx deleted file mode 100644 index 5521c6e39f6..00000000000 --- a/webapp/components/admin_console/compliance_settings.jsx +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedHTMLMessage, FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class ComplianceSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ComplianceSettings.Enable = this.state.enable; - config.ComplianceSettings.Directory = this.state.directory; - config.ComplianceSettings.EnableDaily = this.state.enableDaily; - - return config; - } - - getStateFromConfig(config) { - return { - enable: config.ComplianceSettings.Enable, - directory: config.ComplianceSettings.Directory, - enableDaily: config.ComplianceSettings.EnableDaily - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - const licenseEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.Compliance === 'true'; - - let bannerContent; - if (!licenseEnabled) { - bannerContent = ( -
    -
    - -
    -
    - ); - } - - return ( - - {bannerContent} - - } - helpText={ - - } - value={this.state.enable} - onChange={this.handleChange} - disabled={!licenseEnabled} - /> - - } - placeholder={Utils.localizeMessage('admin.sql.maxOpenExample', 'Ex "10"')} - helpText={ - - } - value={this.state.directory} - onChange={this.handleChange} - disabled={!licenseEnabled || !this.state.enable} - /> - - } - helpText={ - - } - value={this.state.enableDaily} - onChange={this.handleChange} - disabled={!licenseEnabled || !this.state.enable} - /> - - ); - } -} diff --git a/webapp/components/admin_console/configuration_settings.jsx b/webapp/components/admin_console/configuration_settings.jsx deleted file mode 100644 index 6ac68a3bb7f..00000000000 --- a/webapp/components/admin_console/configuration_settings.jsx +++ /dev/null @@ -1,356 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; - -import ErrorStore from 'stores/error_store.jsx'; - -import {ErrorBarTypes} from 'utils/constants.jsx'; -import * as Utils from 'utils/utils.jsx'; - -import {invalidateAllCaches, reloadConfig} from 'actions/admin_actions.jsx'; -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {ConnectionSecurityDropdownSettingWebserver} from './connection_security_dropdown_setting.jsx'; -import SettingsGroup from './settings_group.jsx'; -import RequestButton from './request_button/request_button'; -import TextSetting from './text_setting.jsx'; -import WebserverModeDropdownSetting from './webserver_mode_dropdown_setting.jsx'; - -export default class ConfigurationSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.handleSaved = this.handleSaved.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - componentWillReceiveProps(nextProps) { - // special case for this page since we don't update AdminSettings components when the - // stored config changes, but we want this page to update when you reload the config - this.setState(this.getStateFromConfig(nextProps.config)); - } - - getConfigFromState(config) { - config.ServiceSettings.SiteURL = this.state.siteURL; - config.ServiceSettings.ListenAddress = this.state.listenAddress; - config.ServiceSettings.WebserverMode = this.state.webserverMode; - config.ServiceSettings.ConnectionSecurity = this.state.connectionSecurity; - config.ServiceSettings.TLSCertFile = this.state.TLSCertFile; - config.ServiceSettings.TLSKeyFile = this.state.TLSKeyFile; - config.ServiceSettings.UseLetsEncrypt = this.state.useLetsEncrypt; - config.ServiceSettings.LetsEncryptCertificateCacheFile = this.state.letsEncryptCertificateCacheFile; - config.ServiceSettings.Forward80To443 = this.state.forward80To443; - config.ServiceSettings.ReadTimeout = this.parseIntNonZero(this.state.readTimeout); - config.ServiceSettings.WriteTimeout = this.parseIntNonZero(this.state.writeTimeout); - config.ServiceSettings.EnableAPIv3 = this.state.enableAPIv3; - - return config; - } - - getStateFromConfig(config) { - return { - siteURL: config.ServiceSettings.SiteURL, - listenAddress: config.ServiceSettings.ListenAddress, - webserverMode: config.ServiceSettings.WebserverMode, - connectionSecurity: config.ServiceSettings.ConnectionSecurity, - TLSCertFile: config.ServiceSettings.TLSCertFile, - TLSKeyFile: config.ServiceSettings.TLSKeyFile, - useLetsEncrypt: config.ServiceSettings.UseLetsEncrypt, - letsEncryptCertificateCacheFile: config.ServiceSettings.LetsEncryptCertificateCacheFile, - forward80To443: config.ServiceSettings.Forward80To443, - readTimeout: config.ServiceSettings.ReadTimeout, - writeTimeout: config.ServiceSettings.WriteTimeout, - enableAPIv3: config.ServiceSettings.EnableAPIv3 - }; - } - - handleSaved(newConfig) { - if (newConfig.ServiceSettings.SiteURL) { - ErrorStore.clearError(ErrorBarTypes.SITE_URL); - } - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - const reloadConfigurationHelpText = ( - - - - ), - recycleDatabaseConnections: ( - - - - - - ) - }} - /> - ); - - let reloadConfigButton =
    ; - if (global.window.mm_license.IsLicensed === 'true') { - reloadConfigButton = ( - - } - showSuccessMessage={false} - errorMessage={{ - id: 'admin.reload.reloadFail', - defaultMessage: 'Reload unsuccessful: {error}' - }} - /> - ); - } - - return ( - -
    -
    - -
    -
    - - } - placeholder={Utils.localizeMessage('admin.service.siteURLExample', 'Ex "https://mattermost.example.com:1234"')} - helpText={ - - } - value={this.state.siteURL} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.service.listenExample', 'Ex ":8065"')} - helpText={ - - } - value={this.state.listenAddress} - onChange={this.handleChange} - /> - - - } - helpText={ - - } - disabled={this.state.useLetsEncrypt} - value={this.state.TLSCertFile} - onChange={this.handleChange} - /> - - } - helpText={ - - } - disabled={this.state.useLetsEncrypt} - value={this.state.TLSKeyFile} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.useLetsEncrypt} - onChange={this.handleChange} - /> - - } - helpText={ - - } - disabled={!this.state.useLetsEncrypt} - value={this.state.letsEncryptCertificateCacheFile} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.forward80To443} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.readTimeout} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.writeTimeout} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableAPIv3} - onChange={this.handleChange} - /> - - {reloadConfigButton} - - } - buttonText={ - - } - showSuccessMessage={false} - includeDetailedError={true} - errorMessage={{ - id: 'admin.purge.purgeFail', - defaultMessage: 'Purging unsuccessful: {error}' - }} - /> -
    - ); - } -} diff --git a/webapp/components/admin_console/connection_security_dropdown_setting.jsx b/webapp/components/admin_console/connection_security_dropdown_setting.jsx deleted file mode 100644 index b7b283be193..00000000000 --- a/webapp/components/admin_console/connection_security_dropdown_setting.jsx +++ /dev/null @@ -1,191 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import * as Utils from 'utils/utils.jsx'; - -import DropdownSetting from './dropdown_setting.jsx'; -import {FormattedMessage} from 'react-intl'; - -const SECTION_NONE = ( - - - - - - - - -); - -const SECTION_TLS = ( - - - - - - - - -); - -const SECTION_STARTTLS = ( - - - - - - - - -); - -const CONNECTION_SECURITY_HELP_TEXT_EMAIL = ( - - - {SECTION_NONE} - {SECTION_TLS} - {SECTION_STARTTLS} - -
    -); - -const CONNECTION_SECURITY_HELP_TEXT_LDAP = ( - - - {SECTION_NONE} - {SECTION_TLS} - {SECTION_STARTTLS} - -
    -); - -const CONNECTION_SECURITY_HELP_TEXT_WEBSERVER = ( - - - {SECTION_NONE} - {SECTION_TLS} - -
    -); - -export function ConnectionSecurityDropdownSettingEmail(props) { - return ( - - } - value={props.value} - onChange={props.onChange} - disabled={props.disabled} - helpText={CONNECTION_SECURITY_HELP_TEXT_EMAIL} - /> - ); -} -ConnectionSecurityDropdownSettingEmail.defaultProps = { -}; - -ConnectionSecurityDropdownSettingEmail.propTypes = { - value: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - disabled: PropTypes.bool.isRequired -}; - -export function ConnectionSecurityDropdownSettingLdap(props) { - return ( - - } - value={props.value} - onChange={props.onChange} - disabled={props.disabled} - helpText={CONNECTION_SECURITY_HELP_TEXT_LDAP} - /> - ); -} -ConnectionSecurityDropdownSettingLdap.defaultProps = { -}; - -ConnectionSecurityDropdownSettingLdap.propTypes = { - value: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - disabled: PropTypes.bool.isRequired -}; - -export function ConnectionSecurityDropdownSettingWebserver(props) { - return ( - - } - value={props.value} - onChange={props.onChange} - disabled={props.disabled} - helpText={CONNECTION_SECURITY_HELP_TEXT_WEBSERVER} - /> - ); -} -ConnectionSecurityDropdownSettingWebserver.defaultProps = { -}; - -ConnectionSecurityDropdownSettingWebserver.propTypes = { - value: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - disabled: PropTypes.bool.isRequired -}; diff --git a/webapp/components/admin_console/connection_settings.jsx b/webapp/components/admin_console/connection_settings.jsx deleted file mode 100644 index 78a0b89edc5..00000000000 --- a/webapp/components/admin_console/connection_settings.jsx +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class ConnectionSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ServiceSettings.AllowCorsFrom = this.state.allowCorsFrom; - config.ServiceSettings.EnableInsecureOutgoingConnections = this.state.enableInsecureOutgoingConnections; - - return config; - } - - getStateFromConfig(config) { - return { - allowCorsFrom: config.ServiceSettings.AllowCorsFrom, - enableInsecureOutgoingConnections: config.ServiceSettings.EnableInsecureOutgoingConnections - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - placeholder={Utils.localizeMessage('admin.service.corsEx', 'http://example.com')} - helpText={ - - } - value={this.state.allowCorsFrom} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableInsecureOutgoingConnections} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/custom_brand_settings.jsx b/webapp/components/admin_console/custom_brand_settings.jsx deleted file mode 100644 index 4ca3dee0c65..00000000000 --- a/webapp/components/admin_console/custom_brand_settings.jsx +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import BrandImageSetting from './brand_image_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; -import Constants from 'utils/constants.jsx'; - -export default class CustomBrandSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.TeamSettings.SiteName = this.state.siteName; - if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.CustomBrand === 'true') { - config.TeamSettings.customDescriptionText = this.state.customDescriptionText; - config.TeamSettings.EnableCustomBrand = this.state.enableCustomBrand; - config.TeamSettings.CustomBrandText = this.state.customBrandText; - } - - return config; - } - - getStateFromConfig(config) { - return { - siteName: config.TeamSettings.SiteName, - enableCustomBrand: config.TeamSettings.EnableCustomBrand, - customBrandText: config.TeamSettings.CustomBrandText, - customDescriptionText: config.TeamSettings.CustomDescriptionText - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - const enterpriseSettings = []; - if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.CustomBrand === 'true') { - enterpriseSettings.push( - - } - helpText={ - - } - value={this.state.customDescriptionText} - placeholder={Utils.localizeMessage('web.root.signup_info', 'All team communication in one place, searchable and accessible anywhere')} - onChange={this.handleChange} - /> - ); - - enterpriseSettings.push( - - } - helpText={ - - } - value={this.state.enableCustomBrand} - onChange={this.handleChange} - /> - ); - - enterpriseSettings.push( - - ); - - enterpriseSettings.push( - - } - helpText={ - - } - value={this.state.customBrandText} - onChange={this.handleChange} - disabled={!this.state.enableCustomBrand} - /> - ); - } - - return ( - - - } - maxLength={Constants.MAX_SITENAME_LENGTH} - placeholder={Utils.localizeMessage('admin.team.siteNameExample', 'Ex "Mattermost"')} - helpText={ - - } - value={this.state.siteName} - onChange={this.handleChange} - /> - {enterpriseSettings} - - ); - } -} diff --git a/webapp/components/admin_console/custom_emoji_settings.jsx b/webapp/components/admin_console/custom_emoji_settings.jsx deleted file mode 100644 index 329900888e6..00000000000 --- a/webapp/components/admin_console/custom_emoji_settings.jsx +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import DropdownSetting from './dropdown_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; - -export default class CustomEmojiSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ServiceSettings.EnableCustomEmoji = this.state.enableCustomEmoji; - config.ServiceSettings.EnableEmojiPicker = this.state.enableEmojiPicker; - - if (global.window.mm_license.IsLicensed === 'true') { - config.ServiceSettings.RestrictCustomEmojiCreation = this.state.restrictCustomEmojiCreation; - } - - return config; - } - - getStateFromConfig(config) { - return { - enableCustomEmoji: config.ServiceSettings.EnableCustomEmoji, - enableEmojiPicker: config.ServiceSettings.EnableEmojiPicker, - restrictCustomEmojiCreation: config.ServiceSettings.RestrictCustomEmojiCreation - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - let restrictSetting = null; - if (global.window.mm_license.IsLicensed === 'true') { - restrictSetting = ( - - } - helpText={ - - } - value={this.state.restrictCustomEmojiCreation} - onChange={this.handleChange} - disabled={!this.state.enableCustomEmoji} - /> - ); - } - - return ( - - - } - helpText={ - - } - value={this.state.enableEmojiPicker} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableCustomEmoji} - onChange={this.handleChange} - /> - {restrictSetting} - - ); - } -} diff --git a/webapp/components/admin_console/custom_integrations_settings.jsx b/webapp/components/admin_console/custom_integrations_settings.jsx deleted file mode 100644 index e6bcb4b3221..00000000000 --- a/webapp/components/admin_console/custom_integrations_settings.jsx +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedHTMLMessage, FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; - -export default class WebhookSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ServiceSettings.EnableIncomingWebhooks = this.state.enableIncomingWebhooks; - config.ServiceSettings.EnableOutgoingWebhooks = this.state.enableOutgoingWebhooks; - config.ServiceSettings.EnableCommands = this.state.enableCommands; - config.ServiceSettings.EnableOnlyAdminIntegrations = this.state.enableOnlyAdminIntegrations; - config.ServiceSettings.EnablePostUsernameOverride = this.state.enablePostUsernameOverride; - config.ServiceSettings.EnablePostIconOverride = this.state.enablePostIconOverride; - config.ServiceSettings.EnableOAuthServiceProvider = this.state.enableOAuthServiceProvider; - config.ServiceSettings.EnableUserAccessTokens = this.state.enableUserAccessTokens; - - return config; - } - - getStateFromConfig(config) { - return { - enableIncomingWebhooks: config.ServiceSettings.EnableIncomingWebhooks, - enableOutgoingWebhooks: config.ServiceSettings.EnableOutgoingWebhooks, - enableCommands: config.ServiceSettings.EnableCommands, - enableOnlyAdminIntegrations: config.ServiceSettings.EnableOnlyAdminIntegrations, - enablePostUsernameOverride: config.ServiceSettings.EnablePostUsernameOverride, - enablePostIconOverride: config.ServiceSettings.EnablePostIconOverride, - enableOAuthServiceProvider: config.ServiceSettings.EnableOAuthServiceProvider, - enableUserAccessTokens: config.ServiceSettings.EnableUserAccessTokens - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ - - } - value={this.state.enableIncomingWebhooks} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableOutgoingWebhooks} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableCommands} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableOAuthServiceProvider} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableOnlyAdminIntegrations} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enablePostUsernameOverride} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enablePostIconOverride} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableUserAccessTokens} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/database_settings.jsx b/webapp/components/admin_console/database_settings.jsx deleted file mode 100644 index 9f008483cf9..00000000000 --- a/webapp/components/admin_console/database_settings.jsx +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import {recycleDatabaseConnection} from 'actions/admin_actions.jsx'; -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import GeneratedSetting from './generated_setting.jsx'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; -import RequestButton from './request_button/request_button.jsx'; - -export default class DatabaseSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - // driverName and dataSource are read-only from the UI - - config.SqlSettings.MaxIdleConns = this.parseIntNonZero(this.state.maxIdleConns); - config.SqlSettings.MaxOpenConns = this.parseIntNonZero(this.state.maxOpenConns); - config.SqlSettings.AtRestEncryptKey = this.state.atRestEncryptKey; - config.SqlSettings.Trace = this.state.trace; - config.SqlSettings.QueryTimeout = this.parseIntNonZero(this.state.queryTimeout); - - return config; - } - - getStateFromConfig(config) { - return { - driverName: config.SqlSettings.DriverName, - dataSource: config.SqlSettings.DataSource, - maxIdleConns: config.SqlSettings.MaxIdleConns, - maxOpenConns: config.SqlSettings.MaxOpenConns, - atRestEncryptKey: config.SqlSettings.AtRestEncryptKey, - trace: config.SqlSettings.Trace, - queryTimeout: config.SqlSettings.QueryTimeout - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - const dataSource = '**********' + this.state.dataSource.substring(this.state.dataSource.indexOf('@')); - - let recycleDbButton =
    ; - if (global.window.mm_license.IsLicensed === 'true') { - recycleDbButton = ( - - - - ), - reloadConfiguration: ( - - - - - - ) - }} - /> - } - buttonText={ - - } - showSuccessMessage={false} - errorMessage={{ - id: 'admin.recycle.reloadFail', - defaultMessage: 'Recycling unsuccessful: {error}' - }} - includeDetailedError={true} - /> - ); - } - - return ( - -
    - -
    -
    - -
    -

    {this.state.driverName}

    -
    -
    -
    - -
    -

    {dataSource}

    -
    -
    - - } - placeholder={Utils.localizeMessage('admin.sql.maxConnectionsExample', 'Ex "10"')} - helpText={ - - } - value={this.state.maxIdleConns} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.sql.maxOpenExample', 'Ex "10"')} - helpText={ - - } - value={this.state.maxOpenConns} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.sql.queryTimeoutExample', 'Ex "30"')} - helpText={ - - } - value={this.state.queryTimeout} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.sql.keyExample', 'Ex "gxHVDcKUyP2y1eiyW8S8na1UYQAfq6J6"')} - helpText={ - - } - value={this.state.atRestEncryptKey} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.trace} - onChange={this.handleChange} - /> - {recycleDbButton} -
    - ); - } -} diff --git a/webapp/components/admin_console/developer_settings.jsx b/webapp/components/admin_console/developer_settings.jsx deleted file mode 100644 index 6a8f49dbd5d..00000000000 --- a/webapp/components/admin_console/developer_settings.jsx +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class DeveloperSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ServiceSettings.EnableTesting = this.state.enableTesting; - config.ServiceSettings.EnableDeveloper = this.state.enableDeveloper; - config.ServiceSettings.AllowedUntrustedInternalConnections = this.state.allowedUntrustedInternalConnections; - - return config; - } - - getStateFromConfig(config) { - return { - enableTesting: config.ServiceSettings.EnableTesting, - enableDeveloper: config.ServiceSettings.EnableDeveloper, - allowedUntrustedInternalConnections: config.ServiceSettings.AllowedUntrustedInternalConnections - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ - - } - value={this.state.enableTesting} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableDeveloper} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.service.internalConnectionsEx', 'webhooks.internal.example.com 127.0.0.1 10.0.16.0/28')} - helpText={ - - } - value={this.state.allowedUntrustedInternalConnections} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/dropdown_setting.jsx b/webapp/components/admin_console/dropdown_setting.jsx deleted file mode 100644 index 05179a4b9b5..00000000000 --- a/webapp/components/admin_console/dropdown_setting.jsx +++ /dev/null @@ -1,66 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import Setting from './setting.jsx'; - -export default class DropdownSetting extends React.Component { - constructor(props) { - super(props); - - this.handleChange = this.handleChange.bind(this); - } - - handleChange(e) { - this.props.onChange(this.props.id, e.target.value); - } - - render() { - const options = []; - for (const {value, text} of this.props.values) { - options.push( - - ); - } - - return ( - - - - ); - } -} - -DropdownSetting.defaultProps = { - isDisabled: false -}; - -DropdownSetting.propTypes = { - id: PropTypes.string.isRequired, - values: PropTypes.array.isRequired, - label: PropTypes.node.isRequired, - value: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - disabled: PropTypes.bool, - helpText: PropTypes.node -}; diff --git a/webapp/components/admin_console/elasticsearch_settings.jsx b/webapp/components/admin_console/elasticsearch_settings.jsx deleted file mode 100644 index b739241efab..00000000000 --- a/webapp/components/admin_console/elasticsearch_settings.jsx +++ /dev/null @@ -1,333 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import {elasticsearchTest, elasticsearchPurgeIndexes} from 'actions/admin_actions.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; -import RequestButton from './request_button/request_button.jsx'; -import ElasticsearchStatus from './elasticsearch_status'; - -export default class ElasticsearchSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.doTestConfig = this.doTestConfig.bind(this); - this.handleChange = this.handleChange.bind(this); - this.handleSaved = this.handleSaved.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ElasticsearchSettings.ConnectionUrl = this.state.connectionUrl; - config.ElasticsearchSettings.Username = this.state.username; - config.ElasticsearchSettings.Password = this.state.password; - config.ElasticsearchSettings.Sniff = this.state.sniff; - config.ElasticsearchSettings.EnableIndexing = this.state.enableIndexing; - config.ElasticsearchSettings.EnableSearching = this.state.enableSearching; - - return config; - } - - getStateFromConfig(config) { - return { - connectionUrl: config.ElasticsearchSettings.ConnectionUrl, - username: config.ElasticsearchSettings.Username, - password: config.ElasticsearchSettings.Password, - sniff: config.ElasticsearchSettings.Sniff, - enableIndexing: config.ElasticsearchSettings.EnableIndexing, - enableSearching: config.ElasticsearchSettings.EnableSearching, - configTested: true, - canSave: true, - canPurgeAndIndex: config.ElasticsearchSettings.EnableIndexing - }; - } - - handleChange(id, value) { - if (id === 'enableIndexing') { - if (value === false) { - this.setState({ - enableSearching: false - }); - } else { - this.setState({ - canSave: false, - configTested: false - }); - } - } - - if (id === 'connectionUrl' || id === 'username' || id === 'password' || id === 'sniff') { - this.setState({ - configTested: false, - canSave: false - }); - } - - if (id !== 'enableSearching') { - this.setState({ - canPurgeAndIndex: false - }); - } - - super.handleChange(id, value); - } - - handleSaved() { - this.setState({ - canPurgeAndIndex: this.state.enableIndexing - }); - } - - canSave() { - return this.state.canSave; - } - - doTestConfig(success, error) { - const config = JSON.parse(JSON.stringify(this.props.config)); - this.getConfigFromState(config); - - elasticsearchTest( - config, - () => { - this.setState({ - configTested: true, - canSave: true - }); - success(); - this.doSubmit(); - }, - (err) => { - this.setState({ - configTested: false, - canSave: false - }); - error(err); - } - ); - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - -
    -
    - -
    -
    - - } - helpText={ - - - - ) - }} - /> - } - value={this.state.enableIndexing} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.elasticsearch.connectionUrlExample', 'E.g.: "https://elasticsearch.example.org:9200"')} - helpText={ - - - - ) - }} - /> - } - value={this.state.connectionUrl} - disabled={!this.state.enableIndexing} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.elasticsearch.usernameExample', 'E.g.: "elastic"')} - helpText={ - - } - value={this.state.username} - disabled={!this.state.enableIndexing} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.elasticsearch.password', 'E.g.: "yourpassword"')} - helpText={ - - } - value={this.state.password} - disabled={!this.state.enableIndexing} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.sniff} - disabled={!this.state.enableIndexing} - onChange={this.handleChange} - /> - - } - buttonText={ - - } - successMessage={{ - id: 'admin.elasticsearch.testConfigSuccess', - defaultMessage: 'Test successful. Configuration saved.' - }} - disabled={!this.state.enableIndexing} - /> - - - } - buttonText={ - - } - successMessage={{ - id: 'admin.elasticsearch.purgeIndexesButton.success', - defaultMessage: 'Indexes purged successfully.' - }} - errorMessage={{ - id: 'admin.elasticsearch.purgeIndexesButton.error', - defaultMessage: 'Failed to purge indexes: {error}' - }} - disabled={!this.state.canPurgeAndIndex} - label={( - - )} - /> - - } - helpText={ - - } - value={this.state.enableSearching} - disabled={!this.state.enableIndexing || !this.state.configTested} - onChange={this.handleChange} - /> -
    - ); - } -} diff --git a/webapp/components/admin_console/elasticsearch_status/index.js b/webapp/components/admin_console/elasticsearch_status/index.js deleted file mode 100644 index 6446195d241..00000000000 --- a/webapp/components/admin_console/elasticsearch_status/index.js +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {getJobsByType} from 'mattermost-redux/actions/jobs'; -import {JobTypes} from 'utils/constants.jsx'; - -import * as Selectors from 'mattermost-redux/selectors/entities/jobs'; - -import Status from './status.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps, - jobs: Selectors.makeGetJobsByType(JobTypes.ELASTICSEARCH_POST_INDEXING)(state) - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getJobsByType - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(Status); diff --git a/webapp/components/admin_console/elasticsearch_status/status.jsx b/webapp/components/admin_console/elasticsearch_status/status.jsx deleted file mode 100644 index 0a32d39c833..00000000000 --- a/webapp/components/admin_console/elasticsearch_status/status.jsx +++ /dev/null @@ -1,361 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import PropTypes from 'prop-types'; -import {FormattedMessage} from 'react-intl'; - -import {createJob, cancelJob} from 'actions/job_actions.jsx'; -import {JobTypes, JobStatuses} from 'utils/constants.jsx'; -import RequestButton from '../request_button/request_button.jsx'; - -export default class Status extends React.PureComponent { - static propTypes = { - - /** - * Array of jobs - */ - jobs: PropTypes.arrayOf(PropTypes.object).isRequired, - - /** - * Whether Elasticsearch is properly configured. - */ - isConfigured: PropTypes.bool.isRequired, - - actions: PropTypes.shape({ - - /** - * Function to fetch jobs - */ - getJobsByType: PropTypes.func.isRequired - }).isRequired - }; - - constructor(props) { - super(props); - - this.interval = null; - - this.state = { - loading: true, - cancelInProgress: false - }; - } - - componentWillMount() { - // reload the cluster status every 15 seconds - this.interval = setInterval(this.reload, 15000); - } - - componentDidMount() { - this.props.actions.getJobsByType(JobTypes.ELASTICSEARCH_POST_INDEXING).then( - () => this.setState({loading: false}) - ); - } - - componentWillUnmount() { - if (this.interval) { - clearInterval(this.interval); - } - } - - reload = () => { - this.props.actions.getJobsByType(JobTypes.ELASTICSEARCH_POST_INDEXING).then( - () => { - this.setState({ - loading: false, - cancelInProgress: false - }); - } - ); - }; - - createIndexJob = (success, error) => { - const job = { - type: JobTypes.ELASTICSEARCH_POST_INDEXING - }; - - createJob( - job, - () => { - this.reload(); - success(); - }, - error - ); - }; - - cancelIndexJob = (e) => { - e.preventDefault(); - - const chosenJob = this.getChosenJob(); - if (!chosenJob) { - return; - } - - this.setState({ - cancelInProgress: true - }); - - cancelJob( - chosenJob.id, - () => { - this.reload(); - }, - () => { - this.reload(); - } - ); - }; - - getChosenJob = () => { - let chosenJob = null; - - if (this.props.jobs.length > 0) { - for (let i = 0; i < this.props.jobs.length; i++) { - const job = this.props.jobs[i]; - if (job.status === JobStatuses.CANCEL_REQUESTED || job.status === JobStatuses.IN_PROGRESS) { - chosenJob = job; - } else { - break; - } - } - - if (!chosenJob) { - for (let i = 0; i < this.props.jobs.length; i++) { - const job = this.props.jobs[i]; - if (job.status !== JobStatuses.PENDING && chosenJob) { - continue; - } else { - chosenJob = job; - break; - } - } - } - } - - return chosenJob; - }; - - render() { - const chosenJob = this.getChosenJob(); - - let indexButtonDisabled = !this.props.isConfigured; - let buttonText = ( - - ); - let cancelButton = null; - let indexButtonHelp = ( - - ); - - if (this.state.loading) { - indexButtonDisabled = true; - } else if (chosenJob) { - if (chosenJob.status === JobStatuses.PENDING || chosenJob.status === JobStatuses.IN_PROGRESS || chosenJob.status === JobStatuses.CANCEL_REQUESTED) { - indexButtonDisabled = true; - buttonText = ( - - - - - ); - } - - if (chosenJob.status === JobStatuses.PENDING || chosenJob.status === JobStatuses.IN_PROGRESS || chosenJob.status === JobStatuses.CANCEL_REQUESTED) { - indexButtonHelp = ( - - ); - } - - if (!this.state.cancelInProgress && (chosenJob.status === JobStatuses.PENDING || chosenJob.status === JobStatuses.IN_PROGRESS)) { - cancelButton = ( - - - - ); - } - } - - const indexButton = ( - - )} - /> - ); - - let status = null; - let statusHelp = null; - let statusClass = null; - if (!this.props.isConfigured) { - status = ( - - ); - } else if (this.state.loading) { - status = ( - - ); - statusClass = 'status-icon-unknown'; - } else if (chosenJob) { - if (chosenJob.status === JobStatuses.PENDING) { - status = ( - - ); - statusHelp = ( - - ); - statusClass = 'status-icon-warning'; - } else if (chosenJob.status === JobStatuses.IN_PROGRESS) { - status = ( - - ); - statusHelp = ( - - ); - statusClass = 'status-icon-warning'; - } else if (chosenJob.status === JobStatuses.SUCCESS) { - status = ( - - ); - statusHelp = ( - - ); - statusClass = 'status-icon-success'; - } else if (chosenJob.status === JobStatuses.ERROR) { - status = ( - - ); - statusHelp = ( - - ); - statusClass = 'status-icon-error'; - } else if (chosenJob.status === JobStatuses.CANCEL_REQUESTED) { - status = ( - - ); - statusClass = 'status-icon-warning'; - } else if (chosenJob.status === JobStatuses.CANCELED) { - status = ( - - ); - statusClass = 'status-icon-error'; - } - } else { - status = ( - - ); - statusClass = 'status-icon-unknown'; - } - - if (statusHelp !== null) { - statusHelp = ( -
    -
    - {statusHelp} -
    -
    - ); - } - - statusClass = 'fa fa-circle margin--right ' + statusClass; - - return ( -
    - {indexButton} -
    -
    -
    - - - {status} -
    -
    - {statusHelp} -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/email_authentication_settings.jsx b/webapp/components/admin_console/email_authentication_settings.jsx deleted file mode 100644 index 9cc3ab3d788..00000000000 --- a/webapp/components/admin_console/email_authentication_settings.jsx +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; - -export default class EmailAuthenticationSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.EmailSettings.EnableSignUpWithEmail = this.state.enableSignUpWithEmail; - config.EmailSettings.EnableSignInWithEmail = this.state.enableSignInWithEmail; - config.EmailSettings.EnableSignInWithUsername = this.state.enableSignInWithUsername; - - return config; - } - - getStateFromConfig(config) { - return { - enableSignUpWithEmail: config.EmailSettings.EnableSignUpWithEmail, - enableSignInWithEmail: config.EmailSettings.EnableSignInWithEmail, - enableSignInWithUsername: config.EmailSettings.EnableSignInWithUsername - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ - - } - value={this.state.enableSignUpWithEmail} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableSignInWithEmail} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableSignInWithUsername} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/email_connection_test.jsx b/webapp/components/admin_console/email_connection_test.jsx deleted file mode 100644 index 17edbf23ef9..00000000000 --- a/webapp/components/admin_console/email_connection_test.jsx +++ /dev/null @@ -1,130 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import {FormattedMessage} from 'react-intl'; - -import {testEmail} from 'actions/admin_actions.jsx'; - -export default class EmailConnectionTestButton extends React.Component { - static get propTypes() { - return { - config: PropTypes.object.isRequired, - getConfigFromState: PropTypes.func.isRequired, - disabled: PropTypes.bool.isRequired - }; - } - - constructor(props) { - super(props); - - this.handleTestConnection = this.handleTestConnection.bind(this); - - this.state = { - testing: false, - success: false, - fail: null - }; - } - - handleTestConnection(e) { - e.preventDefault(); - - this.setState({ - testing: true, - success: false, - fail: null - }); - - const config = JSON.parse(JSON.stringify(this.props.config)); - this.props.getConfigFromState(config); - - testEmail( - config, - () => { - this.setState({ - testing: false, - success: true - }); - }, - (err) => { - let fail = err.message; - if (err.detailed_error) { - fail += ' - ' + err.detailed_error; - } - - this.setState({ - testing: false, - fail - }); - } - ); - } - - render() { - let testMessage = null; - if (this.state.success) { - testMessage = ( -
    - - -
    - ); - } else if (this.state.fail) { - testMessage = ( -
    - - -
    - ); - } - - let contents = null; - if (this.state.testing) { - contents = ( - - - {Utils.localizeMessage('admin.email.testing', 'Testing...')} - - ); - } else { - contents = ( - - ); - } - - return ( -
    -
    -
    - - {testMessage} -
    -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/email_settings.jsx b/webapp/components/admin_console/email_settings.jsx deleted file mode 100644 index e630402bc57..00000000000 --- a/webapp/components/admin_console/email_settings.jsx +++ /dev/null @@ -1,395 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import ErrorStore from 'stores/error_store.jsx'; - -import {ErrorBarTypes} from 'utils/constants.jsx'; -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {ConnectionSecurityDropdownSettingEmail} from './connection_security_dropdown_setting.jsx'; -import DropdownSetting from './dropdown_setting.jsx'; -import EmailConnectionTest from './email_connection_test.jsx'; -import {FormattedHTMLMessage, FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -const EMAIL_NOTIFICATION_CONTENTS_FULL = 'full'; -const EMAIL_NOTIFICATION_CONTENTS_GENERIC = 'generic'; - -export default class EmailSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - this.handleSaved = this.handleSaved.bind(this); - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.EmailSettings.SendEmailNotifications = this.state.sendEmailNotifications; - config.EmailSettings.FeedbackName = this.state.feedbackName; - config.EmailSettings.FeedbackEmail = this.state.feedbackEmail; - config.EmailSettings.FeedbackOrganization = this.state.feedbackOrganization; - config.EmailSettings.EnableSMTPAuth = this.state.enableSMTPAuth; - config.EmailSettings.SMTPUsername = this.state.smtpUsername; - config.EmailSettings.SMTPPassword = this.state.smtpPassword; - config.EmailSettings.SMTPServer = this.state.smtpServer; - config.EmailSettings.SMTPPort = this.state.smtpPort; - config.EmailSettings.ConnectionSecurity = this.state.connectionSecurity; - config.EmailSettings.EnableEmailBatching = this.state.enableEmailBatching; - config.ServiceSettings.EnableSecurityFixAlert = this.state.enableSecurityFixAlert; - config.EmailSettings.SkipServerCertificateVerification = this.state.skipServerCertificateVerification; - config.EmailSettings.EmailNotificationContentsType = this.state.emailNotificationContentsType; - - return config; - } - - handleSaved(newConfig) { - if (newConfig.EmailSettings.SendEmailNotifications) { - ErrorStore.clearError(ErrorBarTypes.PREVIEW_MODE); - } - } - - getStateFromConfig(config) { - return { - sendEmailNotifications: config.EmailSettings.SendEmailNotifications, - feedbackName: config.EmailSettings.FeedbackName, - feedbackEmail: config.EmailSettings.FeedbackEmail, - feedbackOrganization: config.EmailSettings.FeedbackOrganization, - enableSMTPAuth: config.EmailSettings.EnableSMTPAuth, - smtpUsername: config.EmailSettings.SMTPUsername, - smtpPassword: config.EmailSettings.SMTPPassword, - smtpServer: config.EmailSettings.SMTPServer, - smtpPort: config.EmailSettings.SMTPPort, - connectionSecurity: config.EmailSettings.ConnectionSecurity, - enableEmailBatching: config.EmailSettings.EnableEmailBatching, - skipServerCertificateVerification: config.EmailSettings.SkipServerCertificateVerification, - enableSecurityFixAlert: config.ServiceSettings.EnableSecurityFixAlert, - emailNotificationContentsType: config.EmailSettings.EmailNotificationContentsType - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - let enableEmailBatchingDisabledText = null; - - if (this.props.config.ClusterSettings.Enable) { - enableEmailBatchingDisabledText = ( - - - - ); - } else if (!this.props.config.ServiceSettings.SiteURL) { - enableEmailBatchingDisabledText = ( - - - - ); - } - - let emailNotificationContentsTypeDropdown = null; - let emailNotificationContentsHelpText = null; - if (window.mm_license.EmailNotificationContents === 'true') { - const emailNotificationContentsTypes = []; - emailNotificationContentsTypes.push({value: EMAIL_NOTIFICATION_CONTENTS_FULL, text: Utils.localizeMessage('admin.email.notification.contents.full', 'Send full message contents')}); - emailNotificationContentsTypes.push({value: EMAIL_NOTIFICATION_CONTENTS_GENERIC, text: Utils.localizeMessage('admin.email.notification.contents.generic', 'Send generic description with only sender name')}); - - if (this.state.emailNotificationContentsType === EMAIL_NOTIFICATION_CONTENTS_FULL) { - emailNotificationContentsHelpText = ( - - ); - } else if (this.state.emailNotificationContentsType === EMAIL_NOTIFICATION_CONTENTS_GENERIC) { - emailNotificationContentsHelpText = ( - - ); - } - - emailNotificationContentsTypeDropdown = ( - - } - value={this.state.emailNotificationContentsType} - onChange={this.handleChange} - helpText={emailNotificationContentsHelpText} - /> - ); - } - - return ( - - - } - helpText={ - - } - value={this.state.sendEmailNotifications} - onChange={this.handleChange} - /> - - } - helpText={[ - , - enableEmailBatchingDisabledText - ]} - value={this.state.enableEmailBatching && !this.props.config.ClusterSettings.Enable && Boolean(this.props.config.ServiceSettings.SiteURL)} - onChange={this.handleChange} - disabled={!this.state.sendEmailNotifications || this.props.config.ClusterSettings.Enable || !this.props.config.ServiceSettings.SiteURL} - /> - {emailNotificationContentsTypeDropdown} - - } - placeholder={Utils.localizeMessage('admin.email.notificationDisplayExample', 'Ex: "Mattermost Notification", "System", "No-Reply"')} - helpText={ - - } - value={this.state.feedbackName} - onChange={this.handleChange} - disabled={!this.state.sendEmailNotifications} - /> - - } - placeholder={Utils.localizeMessage('admin.email.notificationEmailExample', 'Ex: "mattermost@yourcompany.com", "admin@yourcompany.com"')} - helpText={ - - } - value={this.state.feedbackEmail} - onChange={this.handleChange} - disabled={!this.state.sendEmailNotifications} - /> - - } - placeholder={Utils.localizeMessage('admin.email.notificationOrganizationExample', 'Ex: "© ABC Corporation, 565 Knight Way, Palo Alto, California, 94305, USA"')} - helpText={ - - } - value={this.state.feedbackOrganization} - onChange={this.handleChange} - disabled={!this.state.sendEmailNotifications} - /> - - } - placeholder={Utils.localizeMessage('admin.email.smtpServerExample', 'Ex: "smtp.yourcompany.com", "email-smtp.us-east-1.amazonaws.com"')} - helpText={ - - } - value={this.state.smtpServer} - onChange={this.handleChange} - disabled={!this.state.sendEmailNotifications} - /> - - } - placeholder={Utils.localizeMessage('admin.email.smtpPortExample', 'Ex: "25", "465", "587"')} - helpText={ - - } - value={this.state.smtpPort} - onChange={this.handleChange} - disabled={!this.state.sendEmailNotifications} - /> - - } - helpText={[ - - ]} - value={this.state.enableSMTPAuth} - onChange={this.handleChange} - disabled={!this.state.sendEmailNotifications} - /> - - } - placeholder={Utils.localizeMessage('admin.email.smtpUsernameExample', 'Ex: "admin@yourcompany.com", "AKIADTOVBGERKLCBV"')} - helpText={ - - } - value={this.state.smtpUsername} - onChange={this.handleChange} - disabled={!this.state.sendEmailNotifications || !this.state.enableSMTPAuth} - /> - - } - placeholder={Utils.localizeMessage('admin.email.smtpPasswordExample', 'Ex: "yourpassword", "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"')} - helpText={ - - } - value={this.state.smtpPassword} - onChange={this.handleChange} - disabled={!this.state.sendEmailNotifications || !this.state.enableSMTPAuth} - /> - - - - } - helpText={ - - } - value={this.state.skipServerCertificateVerification} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableSecurityFixAlert} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/external_service_settings.jsx b/webapp/components/admin_console/external_service_settings.jsx deleted file mode 100644 index 6359470a88e..00000000000 --- a/webapp/components/admin_console/external_service_settings.jsx +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import {FormattedHTMLMessage, FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class ExternalServiceSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ServiceSettings.GoogleDeveloperKey = this.state.googleDeveloperKey; - return config; - } - - getStateFromConfig(config) { - return { - googleDeveloperKey: config.ServiceSettings.GoogleDeveloperKey - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - placeholder={Utils.localizeMessage('admin.service.googleExample', 'Ex "7rAh6iwQCkV4cA1Gsg3fgGOXJAQ43QV"')} - helpText={ - - } - value={this.state.googleDeveloperKey} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/file_upload_setting.jsx b/webapp/components/admin_console/file_upload_setting.jsx deleted file mode 100644 index c2bc9869ecf..00000000000 --- a/webapp/components/admin_console/file_upload_setting.jsx +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import $ from 'jquery'; -import PropTypes from 'prop-types'; -import React from 'react'; -import {FormattedMessage} from 'react-intl'; - -import Setting from './setting.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -export default class FileUploadSetting extends Setting { - static get propTypes() { - return { - id: PropTypes.string.isRequired, - label: PropTypes.node.isRequired, - helpText: PropTypes.node, - uploadingText: PropTypes.node, - onSubmit: PropTypes.func.isRequired, - disabled: PropTypes.bool, - fileType: PropTypes.string.isRequired, - error: PropTypes.string - }; - } - - constructor(props) { - super(props); - - this.handleChange = this.handleChange.bind(this); - this.handleSubmit = this.handleSubmit.bind(this); - - this.state = { - fileName: null, - serverError: props.error - }; - } - - handleChange() { - const files = this.refs.fileInput.files; - if (files && files.length > 0) { - this.setState({fileSelected: true, fileName: files[0].name}); - } - } - - handleSubmit(e) { - e.preventDefault(); - - $(this.refs.upload_button).button('loading'); - this.props.onSubmit(this.props.id, this.refs.fileInput.files[0], (error) => { - $(this.refs.upload_button).button('reset'); - if (error) { - Utils.clearFileInput(this.refs.fileInput); - } - }); - } - - render() { - let serverError; - if (this.state.serverError) { - serverError =
    ; - } - - let btnClass = 'btn'; - if (this.state.fileSelected) { - btnClass = 'btn btn-primary'; - } - - let fileName; - if (this.state.fileName) { - fileName = this.state.fileName; - } else { - fileName = ( - - ); - } - - return ( - -
    -
    - - -
    - -
    - {fileName} -
    - {serverError} -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/generated_setting.jsx b/webapp/components/admin_console/generated_setting.jsx deleted file mode 100644 index 2fed2f42fe6..00000000000 --- a/webapp/components/admin_console/generated_setting.jsx +++ /dev/null @@ -1,106 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import crypto from 'crypto'; - -import {FormattedMessage} from 'react-intl'; - -export default class GeneratedSetting extends React.Component { - static get propTypes() { - return { - id: PropTypes.string.isRequired, - label: PropTypes.node.isRequired, - placeholder: PropTypes.string, - value: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - disabled: PropTypes.bool.isRequired, - disabledText: PropTypes.node, - helpText: PropTypes.node.isRequired, - regenerateText: PropTypes.node, - regenerateHelpText: PropTypes.node - }; - } - - static get defaultProps() { - return { - disabled: false, - regenerateText: ( - - ) - }; - } - - constructor(props) { - super(props); - - this.regenerate = this.regenerate.bind(this); - } - - regenerate(e) { - e.preventDefault(); - - this.props.onChange(this.props.id, crypto.randomBytes(256).toString('base64').substring(0, 32)); - } - - render() { - let disabledText = null; - if (this.props.disabled && this.props.disabledText) { - disabledText = ( -
    - {this.props.disabledText} -
    - ); - } - - let regenerateHelpText = null; - if (this.props.regenerateHelpText) { - regenerateHelpText = ( -
    - {this.props.regenerateHelpText} -
    - ); - } - - return ( -
    - -
    - - {disabledText} -
    - {this.props.helpText} -
    -
    - -
    - {regenerateHelpText} -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/gitlab_settings.jsx b/webapp/components/admin_console/gitlab_settings.jsx deleted file mode 100644 index d08597b7dba..00000000000 --- a/webapp/components/admin_console/gitlab_settings.jsx +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedHTMLMessage, FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class GitLabSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.GitLabSettings.Enable = this.state.enable; - config.GitLabSettings.Id = this.state.id; - config.GitLabSettings.Secret = this.state.secret; - config.GitLabSettings.UserApiEndpoint = this.state.userApiEndpoint; - config.GitLabSettings.AuthEndpoint = this.state.authEndpoint; - config.GitLabSettings.TokenEndpoint = this.state.tokenEndpoint; - - return config; - } - - getStateFromConfig(config) { - return { - enable: config.GitLabSettings.Enable, - id: config.GitLabSettings.Id, - secret: config.GitLabSettings.Secret, - userApiEndpoint: config.GitLabSettings.UserApiEndpoint, - authEndpoint: config.GitLabSettings.AuthEndpoint, - tokenEndpoint: config.GitLabSettings.TokenEndpoint - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ -
    - -
    - -
    - } - value={this.state.enable} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.gitlab.clientIdExample', 'Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"')} - helpText={ - - } - value={this.state.id} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.gitlab.clientSecretExample', 'Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"')} - helpText={ - - } - value={this.state.secret} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.gitlab.userExample', 'Ex "https:///api/v3/user"')} - helpText={ - - } - value={this.state.userApiEndpoint} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.gitlab.authExample', 'Ex "https:///oauth/authorize"')} - helpText={ - - } - value={this.state.authEndpoint} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.gitlab.tokenExample', 'Ex "https:///oauth/token"')} - helpText={ - - } - value={this.state.tokenEndpoint} - onChange={this.handleChange} - disabled={!this.state.enable} - /> -
    - ); - } -} diff --git a/webapp/components/admin_console/index.js b/webapp/components/admin_console/index.js deleted file mode 100644 index 4b333e65cbc..00000000000 --- a/webapp/components/admin_console/index.js +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {getConfig} from 'mattermost-redux/actions/admin'; - -import * as Selectors from 'mattermost-redux/selectors/entities/admin'; - -import AdminConsole from './admin_console.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps, - config: Selectors.getConfig(state) - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getConfig - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(AdminConsole); diff --git a/webapp/components/admin_console/ldap_settings.jsx b/webapp/components/admin_console/ldap_settings.jsx deleted file mode 100644 index 9ffbe3b0ee5..00000000000 --- a/webapp/components/admin_console/ldap_settings.jsx +++ /dev/null @@ -1,504 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {ConnectionSecurityDropdownSettingLdap} from './connection_security_dropdown_setting.jsx'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -import {ldapSyncNow, ldapTest} from 'actions/admin_actions.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -import React from 'react'; -import {FormattedMessage} from 'react-intl'; -import RequestButton from './request_button/request_button.jsx'; - -export default class LdapSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.LdapSettings.Enable = this.state.enable; - config.LdapSettings.LdapServer = this.state.ldapServer; - config.LdapSettings.LdapPort = this.parseIntNonZero(this.state.ldapPort); - config.LdapSettings.ConnectionSecurity = this.state.connectionSecurity; - config.LdapSettings.BaseDN = this.state.baseDN; - config.LdapSettings.BindUsername = this.state.bindUsername; - config.LdapSettings.BindPassword = this.state.bindPassword; - config.LdapSettings.UserFilter = this.state.userFilter; - config.LdapSettings.FirstNameAttribute = this.state.firstNameAttribute; - config.LdapSettings.LastNameAttribute = this.state.lastNameAttribute; - config.LdapSettings.NicknameAttribute = this.state.nicknameAttribute; - config.LdapSettings.EmailAttribute = this.state.emailAttribute; - config.LdapSettings.UsernameAttribute = this.state.usernameAttribute; - config.LdapSettings.PositionAttribute = this.state.positionAttribute; - config.LdapSettings.IdAttribute = this.state.idAttribute; - config.LdapSettings.SyncIntervalMinutes = this.parseIntNonZero(this.state.syncIntervalMinutes); - config.LdapSettings.SkipCertificateVerification = this.state.skipCertificateVerification; - config.LdapSettings.QueryTimeout = this.parseIntNonZero(this.state.queryTimeout); - config.LdapSettings.MaxPageSize = this.parseInt(this.state.maxPageSize); - config.LdapSettings.LoginFieldName = this.state.loginFieldName; - - return config; - } - - getStateFromConfig(config) { - return { - enable: config.LdapSettings.Enable, - ldapServer: config.LdapSettings.LdapServer, - ldapPort: config.LdapSettings.LdapPort, - connectionSecurity: config.LdapSettings.ConnectionSecurity, - baseDN: config.LdapSettings.BaseDN, - bindUsername: config.LdapSettings.BindUsername, - bindPassword: config.LdapSettings.BindPassword, - userFilter: config.LdapSettings.UserFilter, - firstNameAttribute: config.LdapSettings.FirstNameAttribute, - lastNameAttribute: config.LdapSettings.LastNameAttribute, - nicknameAttribute: config.LdapSettings.NicknameAttribute, - emailAttribute: config.LdapSettings.EmailAttribute, - usernameAttribute: config.LdapSettings.UsernameAttribute, - positionAttribute: config.LdapSettings.PositionAttribute, - idAttribute: config.LdapSettings.IdAttribute, - syncIntervalMinutes: config.LdapSettings.SyncIntervalMinutes, - skipCertificateVerification: config.LdapSettings.SkipCertificateVerification, - queryTimeout: config.LdapSettings.QueryTimeout, - maxPageSize: config.LdapSettings.MaxPageSize, - loginFieldName: config.LdapSettings.LoginFieldName - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - const licenseEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.LDAP === 'true'; - if (!licenseEnabled) { - return null; - } - - return ( - - - } - helpText={ - - } - value={this.state.enable} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.serverEx', 'Ex "10.0.0.23"')} - helpText={ - - } - value={this.state.ldapServer} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.portEx', 'Ex "389"')} - helpText={ - - } - value={this.state.ldapPort} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - - } - helpText={ - - } - value={this.state.skipCertificateVerification} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.baseEx', 'Ex "ou=Unit Name,dc=corp,dc=example,dc=com"')} - helpText={ - - } - value={this.state.baseDN} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - helpText={ - - } - value={this.state.bindUsername} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - helpText={ - - } - value={this.state.bindPassword} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.userFilterEx', 'Ex. "(objectClass=user)"')} - helpText={ - - } - value={this.state.userFilter} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.firstnameAttrEx', 'Ex "givenName"')} - helpText={ - - } - value={this.state.firstNameAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.lastnameAttrEx', 'Ex "sn"')} - helpText={ - - } - value={this.state.lastNameAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.nicknameAttrEx', 'Ex "nickname"')} - helpText={ - - } - value={this.state.nicknameAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.positionAttrEx', 'E.g.: "title"')} - helpText={ - - } - value={this.state.positionAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.emailAttrEx', 'Ex "mail" or "userPrincipalName"')} - helpText={ - - } - value={this.state.emailAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.usernameAttrEx', 'Ex "sAMAccountName"')} - helpText={ - - } - value={this.state.usernameAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.idAttrEx', 'Ex "sAMAccountName"')} - helpText={ - - } - value={this.state.idAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.loginNameEx', 'Ex "AD/LDAP Username"')} - helpText={ - - } - value={this.state.loginFieldName} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - helpText={ - - } - value={this.state.syncIntervalMinutes} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.maxPageSizeEx', 'Ex "2000"')} - helpText={ - - } - value={this.state.maxPageSize} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.queryEx', 'Ex "60"')} - helpText={ - - } - value={this.state.queryTimeout} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - buttonText={ - - } - disabled={!this.state.enable} - showSuccessMessage={false} - errorMessage={{ - id: 'admin.ldap.syncFailure', - defaultMessage: 'Sync Failure: {error}' - }} - includeDetailedError={true} - /> - - } - buttonText={ - - } - disabled={!this.state.enable} - saveNeeded={this.state.saveNeeded} - saveConfigAction={this.doSubmit} - errorMessage={{ - id: 'admin.ldap.testFailure', - defaultMessage: 'AD/LDAP Test Failure: {error}' - }} - successMessage={{ - id: 'admin.ldap.testSuccess', - defaultMessage: 'AD/LDAP Test Successful' - }} - /> - - ); - } -} diff --git a/webapp/components/admin_console/legal_and_support_settings.jsx b/webapp/components/admin_console/legal_and_support_settings.jsx deleted file mode 100644 index 6b64e0c07f6..00000000000 --- a/webapp/components/admin_console/legal_and_support_settings.jsx +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class LegalAndSupportSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.SupportSettings.TermsOfServiceLink = this.state.termsOfServiceLink; - config.SupportSettings.PrivacyPolicyLink = this.state.privacyPolicyLink; - config.SupportSettings.AboutLink = this.state.aboutLink; - config.SupportSettings.HelpLink = this.state.helpLink; - config.SupportSettings.ReportAProblemLink = this.state.reportAProblemLink; - config.SupportSettings.SupportEmail = this.state.supportEmail; - - return config; - } - - getStateFromConfig(config) { - return { - termsOfServiceLink: config.SupportSettings.TermsOfServiceLink, - privacyPolicyLink: config.SupportSettings.PrivacyPolicyLink, - aboutLink: config.SupportSettings.AboutLink, - helpLink: config.SupportSettings.HelpLink, - reportAProblemLink: config.SupportSettings.ReportAProblemLink, - supportEmail: config.SupportSettings.SupportEmail - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ - - } - value={this.state.termsOfServiceLink} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.privacyPolicyLink} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.aboutLink} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.helpLink} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.reportAProblemLink} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.supportEmail} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/license_settings.jsx b/webapp/components/admin_console/license_settings.jsx deleted file mode 100644 index f04a0c3518f..00000000000 --- a/webapp/components/admin_console/license_settings.jsx +++ /dev/null @@ -1,286 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import $ from 'jquery'; -import ReactDOM from 'react-dom'; -import * as Utils from 'utils/utils.jsx'; - -import ErrorStore from 'stores/error_store.jsx'; -import {uploadLicenseFile, removeLicenseFile} from 'actions/admin_actions.jsx'; - -import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'react-intl'; - -const holders = defineMessages({ - removing: { - id: 'admin.license.removing', - defaultMessage: 'Removing License...' - }, - uploading: { - id: 'admin.license.uploading', - defaultMessage: 'Uploading License...' - } -}); - -import PropTypes from 'prop-types'; - -import React from 'react'; - -class LicenseSettings extends React.Component { - constructor(props) { - super(props); - - this.handleChange = this.handleChange.bind(this); - this.handleSubmit = this.handleSubmit.bind(this); - this.handleRemove = this.handleRemove.bind(this); - - this.state = { - fileSelected: false, - fileName: null, - serverError: null - }; - } - - handleChange() { - const element = $(ReactDOM.findDOMNode(this.refs.fileInput)); - if (element.prop('files').length > 0) { - this.setState({fileSelected: true, fileName: element.prop('files')[0].name}); - } - } - - handleSubmit(e) { - e.preventDefault(); - - const element = $(ReactDOM.findDOMNode(this.refs.fileInput)); - if (element.prop('files').length === 0) { - return; - } - const file = element.prop('files')[0]; - - $('#upload-button').button('loading'); - - uploadLicenseFile( - file, - () => { - Utils.clearFileInput(element[0]); - $('#upload-button').button('reset'); - this.setState({fileSelected: false, fileName: null, serverError: null}); - window.location.reload(true); - }, - (error) => { - Utils.clearFileInput(element[0]); - $('#upload-button').button('reset'); - this.setState({fileSelected: false, fileName: null, serverError: error.message}); - } - ); - } - - handleRemove(e) { - e.preventDefault(); - - $('#remove-button').button('loading'); - - removeLicenseFile( - () => { - $('#remove-button').button('reset'); - this.setState({fileSelected: false, fileName: null, serverError: null}); - ErrorStore.clearLastError(true); - window.location.reload(true); - }, - (error) => { - $('#remove-button').button('reset'); - this.setState({fileSelected: false, fileName: null, serverError: error.message}); - } - ); - } - - render() { - var serverError = ''; - if (this.state.serverError) { - serverError =
    ; - } - - var btnClass = 'btn'; - if (this.state.fileSelected) { - btnClass = 'btn btn-primary'; - } - - let edition; - let licenseType; - let licenseKey; - - const issued = Utils.displayDate(parseInt(global.window.mm_license.IssuedAt, 10)) + ' ' + Utils.displayTime(parseInt(global.window.mm_license.IssuedAt, 10), true); - const startsAt = Utils.displayDate(parseInt(global.window.mm_license.StartsAt, 10)); - const expiresAt = Utils.displayDate(parseInt(global.window.mm_license.ExpiresAt, 10)); - - if (global.window.mm_license.IsLicensed === 'true') { - // Note: DO NOT LOCALISE THESE STRINGS. Legally we can not since the license is in English. - edition = 'Mattermost Enterprise Edition. Enterprise features on this server have been unlocked with a license key and a valid subscription.'; - licenseType = ( -
    -

    - {'This software is offered under a commercial license.\n\nSee ENTERPRISE-EDITION-LICENSE.txt in your root install directory for details. See NOTICE.txt for information about open source software used in this system.\n\nYour subscription details are as follows:'} -

    - {`Name: ${global.window.mm_license.Name}`}
    - {`Company or organization name: ${global.window.mm_license.Company}`}
    - {`Number of users: ${global.window.mm_license.Users}`}
    - {`License issued: ${issued}`}
    - {`Start date of license: ${startsAt}`}
    - {`Expiry date of license: ${expiresAt}`}
    -
    - {'See also '}{'Enterprise Edition Terms of Service'}{' and '}{'Privacy Policy.'} -
    - ); - - licenseKey = ( -
    - -
    -
    -

    - {'If you migrate servers you may need to remove your license key to install it elsewhere. You can remove the key here, which will revert functionality to that of Team Edition.'} -

    -
    - ); - } else { - // Note: DO NOT LOCALISE THESE STRINGS. Legally we can not since the license is in English. - edition = ( -

    - {'Mattermost Enterprise Edition. Unlock enterprise features in this software through the purchase of a subscription from '} - - {'https://mattermost.com/'} - -

    - ); - - licenseType = 'This software is offered under a commercial license.\n\nSee ENTERPRISE-EDITION-LICENSE.txt in your root install directory for details. See NOTICE.txt for information about open source software used in this system.'; - - let fileName; - if (this.state.fileName) { - fileName = this.state.fileName; - } else { - fileName = ( - - ); - } - - licenseKey = ( -
    -
    - - -
    - -
    - {fileName} -
    -
    - {serverError} -

    - -

    -
    - ); - } - - return ( -
    -

    - -

    -
    -
    - -
    - {edition} -
    -
    -
    - -
    - {licenseType} -
    -
    -
    - - {licenseKey} -
    -
    -
    - ); - } -} - -LicenseSettings.propTypes = { - intl: intlShape.isRequired, - config: PropTypes.object -}; - -export default injectIntl(LicenseSettings); diff --git a/webapp/components/admin_console/link_previews_settings.jsx b/webapp/components/admin_console/link_previews_settings.jsx deleted file mode 100644 index b120d75d2f9..00000000000 --- a/webapp/components/admin_console/link_previews_settings.jsx +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; - -export default class LinkPreviewsSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ServiceSettings.EnableLinkPreviews = this.state.enableLinkPreviews; - - return config; - } - - getStateFromConfig(config) { - return { - enableLinkPreviews: config.ServiceSettings.EnableLinkPreviews - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ - - } - value={this.state.enableLinkPreviews} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/localization_settings.jsx b/webapp/components/admin_console/localization_settings.jsx deleted file mode 100644 index 78b63b16332..00000000000 --- a/webapp/components/admin_console/localization_settings.jsx +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as I18n from 'i18n/i18n.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import DropdownSetting from './dropdown_setting.jsx'; -import MultiSelectSetting from './multiselect_settings.jsx'; - -export default class LocalizationSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - this.canSave = this.canSave.bind(this); - - const locales = I18n.getAllLanguages(); - - this.state = Object.assign(this.state, { - hasErrors: false, - languages: Object.keys(locales).map((l) => { - return {value: locales[l].value, text: locales[l].name, order: locales[l].order}; - }).sort((a, b) => a.order - b.order) - }); - } - - canSave() { - return this.state.availableLocales.join(',').indexOf(this.state.defaultClientLocale) !== -1 || this.state.availableLocales.length === 0; - } - - getConfigFromState(config) { - config.LocalizationSettings.DefaultServerLocale = this.state.defaultServerLocale; - config.LocalizationSettings.DefaultClientLocale = this.state.defaultClientLocale; - config.LocalizationSettings.AvailableLocales = this.state.availableLocales.join(','); - - return config; - } - - getStateFromConfig(config) { - return { - defaultServerLocale: config.LocalizationSettings.DefaultServerLocale, - defaultClientLocale: config.LocalizationSettings.DefaultClientLocale, - availableLocales: config.LocalizationSettings.AvailableLocales ? config.LocalizationSettings.AvailableLocales.split(',') : [] - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - value={this.state.defaultServerLocale} - onChange={this.handleChange} - helpText={ - - } - /> - - } - value={this.state.defaultClientLocale} - onChange={this.handleChange} - helpText={ - - } - /> - - } - selected={this.state.availableLocales} - onChange={this.handleChange} - helpText={ - - } - noResultText={ - - } - notPresent={ - - } - /> - - ); - } -} diff --git a/webapp/components/admin_console/log_settings.jsx b/webapp/components/admin_console/log_settings.jsx deleted file mode 100644 index 8e1e4891e06..00000000000 --- a/webapp/components/admin_console/log_settings.jsx +++ /dev/null @@ -1,282 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import DropdownSetting from './dropdown_setting.jsx'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class LogSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.LogSettings.EnableConsole = this.state.enableConsole; - config.LogSettings.ConsoleLevel = this.state.consoleLevel; - config.LogSettings.EnableFile = this.state.enableFile; - config.LogSettings.FileLevel = this.state.fileLevel; - config.LogSettings.FileLocation = this.state.fileLocation; - config.LogSettings.FileFormat = this.state.fileFormat; - config.LogSettings.EnableWebhookDebugging = this.state.enableWebhookDebugging; - config.LogSettings.EnableDiagnostics = this.state.enableDiagnostics; - - return config; - } - - getStateFromConfig(config) { - return { - enableConsole: config.LogSettings.EnableConsole, - consoleLevel: config.LogSettings.ConsoleLevel, - enableFile: config.LogSettings.EnableFile, - fileLevel: config.LogSettings.FileLevel, - fileLocation: config.LogSettings.FileLocation, - fileFormat: config.LogSettings.FileFormat, - enableWebhookDebugging: config.LogSettings.EnableWebhookDebugging, - enableDiagnostics: config.LogSettings.EnableDiagnostics - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - const logLevels = [ - {value: 'DEBUG', text: 'DEBUG'}, - {value: 'INFO', text: 'INFO'}, - {value: 'ERROR', text: 'ERROR'} - ]; - - return ( - - - } - helpText={ - - } - value={this.state.enableConsole} - onChange={this.handleChange} - /> - - } - value={this.state.consoleLevel} - onChange={this.handleChange} - disabled={!this.state.enableConsole} - helpText={ - - } - /> - - } - helpText={ - - } - value={this.state.enableFile} - onChange={this.handleChange} - /> - - } - value={this.state.fileLevel} - onChange={this.handleChange} - disabled={!this.state.enableFile} - helpText={ - - } - /> - - } - placeholder={Utils.localizeMessage('admin.log.locationPlaceholder', 'Enter your file location')} - helpText={ - - } - value={this.state.fileLocation} - onChange={this.handleChange} - disabled={!this.state.enableFile} - /> - - } - placeholder={Utils.localizeMessage('admin.log.formatPlaceholder', 'Enter your file format')} - helpText={this.renderFileFormatHelpText()} - value={this.state.fileFormat} - onChange={this.handleChange} - disabled={!this.state.enableFile} - /> - - } - helpText={ - - } - value={this.state.enableWebhookDebugging} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableDiagnostics} - onChange={this.handleChange} - /> - - ); - } - - renderFileFormatHelpText() { - return ( -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {'%T'} - -
    {'%D'} - -
    {'%d'} - -
    {'%L'} - -
    {'%S'} - -
    {'%M'} - -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/manage_roles_modal/index.js b/webapp/components/admin_console/manage_roles_modal/index.js deleted file mode 100644 index 1ca243621f8..00000000000 --- a/webapp/components/admin_console/manage_roles_modal/index.js +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {updateUserRoles} from 'mattermost-redux/actions/users'; - -import ManageRolesModal from './manage_roles_modal.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps, - userAccessTokensEnabled: state.entities.admin.config.ServiceSettings.EnableUserAccessTokens - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - updateUserRoles - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(ManageRolesModal); diff --git a/webapp/components/admin_console/manage_roles_modal/manage_roles_modal.jsx b/webapp/components/admin_console/manage_roles_modal/manage_roles_modal.jsx deleted file mode 100644 index 2358f0241ff..00000000000 --- a/webapp/components/admin_console/manage_roles_modal/manage_roles_modal.jsx +++ /dev/null @@ -1,349 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import * as UserUtils from 'mattermost-redux/utils/user_utils'; -import {Client4} from 'mattermost-redux/client'; -import {General} from 'mattermost-redux/constants'; - -import {trackEvent} from 'actions/diagnostics_actions.jsx'; - -import React from 'react'; -import {Modal} from 'react-bootstrap'; -import PropTypes from 'prop-types'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; - -function getStateFromProps(props) { - const roles = props.user && props.user.roles ? props.user.roles : ''; - - return { - error: null, - hasPostAllRole: UserUtils.hasPostAllRole(roles), - hasPostAllPublicRole: UserUtils.hasPostAllPublicRole(roles), - hasUserAccessTokenRole: UserUtils.hasUserAccessTokenRole(roles), - isSystemAdmin: UserUtils.isSystemAdmin(roles) - }; -} - -export default class ManageRolesModal extends React.PureComponent { - static propTypes = { - - /** - * Set to render the modal - */ - show: PropTypes.bool.isRequired, - - /** - * The user the roles are being managed for - */ - user: PropTypes.object, - - /** - * Set if user access tokens are enabled - */ - userAccessTokensEnabled: PropTypes.bool.isRequired, - - /** - * Function called when modal is dismissed - */ - onModalDismissed: PropTypes.func.isRequired, - - actions: PropTypes.shape({ - - /** - * Function to update a user's roles - */ - updateUserRoles: PropTypes.func.isRequired - }).isRequired - }; - - constructor(props) { - super(props); - this.state = getStateFromProps(props); - } - - componentWillReceiveProps(nextProps) { - const user = this.props.user || {}; - const nextUser = nextProps.user || {}; - if (user.id !== nextUser.id) { - this.setState(getStateFromProps(nextProps)); - } - } - - handleError = (error) => { - this.setState({ - error - }); - } - - handleSystemAdminChange = (e) => { - if (e.target.name === 'systemadmin') { - this.setState({isSystemAdmin: true}); - } else if (e.target.name === 'systemmember') { - this.setState({isSystemAdmin: false}); - } - }; - - handleUserAccessTokenChange = (e) => { - this.setState({ - hasUserAccessTokenRole: e.target.checked - }); - }; - - handlePostAllChange = (e) => { - this.setState({ - hasPostAllRole: e.target.checked - }); - }; - - handlePostAllPublicChange = (e) => { - this.setState({ - hasPostAllPublicRole: e.target.checked - }); - }; - - trackRoleChanges = (roles, oldRoles) => { - if (UserUtils.hasUserAccessTokenRole(roles) && !UserUtils.hasUserAccessTokenRole(oldRoles)) { - trackEvent('actions', 'add_roles', {role: General.SYSTEM_USER_ACCESS_TOKEN_ROLE}); - } else if (!UserUtils.hasUserAccessTokenRole(roles) && UserUtils.hasUserAccessTokenRole(oldRoles)) { - trackEvent('actions', 'remove_roles', {role: General.SYSTEM_USER_ACCESS_TOKEN_ROLE}); - } - - if (UserUtils.hasPostAllRole(roles) && !UserUtils.hasPostAllRole(oldRoles)) { - trackEvent('actions', 'add_roles', {role: General.SYSTEM_POST_ALL_ROLE}); - } else if (!UserUtils.hasPostAllRole(roles) && UserUtils.hasPostAllRole(oldRoles)) { - trackEvent('actions', 'remove_roles', {role: General.SYSTEM_POST_ALL_ROLE}); - } - - if (UserUtils.hasPostAllPublicRole(roles) && !UserUtils.hasPostAllPublicRole(oldRoles)) { - trackEvent('actions', 'add_roles', {role: General.SYSTEM_POST_ALL_PUBLIC_ROLE}); - } else if (!UserUtils.hasPostAllPublicRole(roles) && UserUtils.hasPostAllPublicRole(oldRoles)) { - trackEvent('actions', 'remove_roles', {role: General.SYSTEM_POST_ALL_PUBLIC_ROLE}); - } - } - - handleSave = async () => { - this.setState({error: null}); - - let roles = General.SYSTEM_USER_ROLE; - - if (this.state.isSystemAdmin) { - roles += ' ' + General.SYSTEM_ADMIN_ROLE; - } else if (this.state.hasUserAccessTokenRole) { - roles += ' ' + General.SYSTEM_USER_ACCESS_TOKEN_ROLE; - if (this.state.hasPostAllRole) { - roles += ' ' + General.SYSTEM_POST_ALL_ROLE; - } else if (this.state.hasPostAllPublicRole) { - roles += ' ' + General.SYSTEM_POST_ALL_PUBLIC_ROLE; - } - } - - const data = await this.props.actions.updateUserRoles(this.props.user.id, roles); - - this.trackRoleChanges(roles, this.props.user.roles); - - if (data) { - this.props.onModalDismissed(); - } else { - this.handleError( - - ); - } - } - - renderContents = () => { - const {user} = this.props; - - if (user == null) { - return
    ; - } - - let name = UserUtils.getFullName(user); - if (name) { - name += ` (@${user.username})`; - } else { - name = `@${user.username}`; - } - - let additionalRoles; - if (this.state.hasUserAccessTokenRole || this.state.isSystemAdmin) { - additionalRoles = ( -
    -

    - -

    -
    - -
    -
    - -
    -
    - ); - } - - let userAccessTokenContent; - if (this.props.userAccessTokensEnabled) { - userAccessTokenContent = ( -
    -
    - -
    -
    - {additionalRoles} -
    -
    - ); - } - - return ( -
    -
    - -
    -
    - {name} -
    -
    - {user.email} -
    -
    -
    -
    -
    -
    - -
    -
    - -
    -
    - {userAccessTokenContent} -
    -
    - ); - } - - render() { - return ( - - - - - - - - {this.renderContents()} - {this.state.error} - - - - - - - ); - } -} diff --git a/webapp/components/admin_console/manage_teams_modal/manage_teams_dropdown.jsx b/webapp/components/admin_console/manage_teams_modal/manage_teams_dropdown.jsx deleted file mode 100644 index 4ee3c11cd9f..00000000000 --- a/webapp/components/admin_console/manage_teams_modal/manage_teams_dropdown.jsx +++ /dev/null @@ -1,148 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import {Dropdown, MenuItem} from 'react-bootstrap'; -import {FormattedMessage} from 'react-intl'; - -import {updateTeamMemberRoles, removeUserFromTeam} from 'actions/team_actions.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -export default class ManageTeamsDropdown extends React.Component { - static propTypes = { - user: PropTypes.object.isRequired, - teamMember: PropTypes.object.isRequired, - onError: PropTypes.func.isRequired, - onMemberChange: PropTypes.func.isRequired, - onMemberRemove: PropTypes.func.isRequired - }; - - constructor(props) { - super(props); - - this.toggleDropdown = this.toggleDropdown.bind(this); - - this.makeTeamAdmin = this.makeTeamAdmin.bind(this); - this.makeMember = this.makeMember.bind(this); - this.removeFromTeam = this.removeFromTeam.bind(this); - - this.handleMemberChange = this.handleMemberChange.bind(this); - this.handleMemberRemove = this.handleMemberRemove.bind(this); - - this.state = { - show: false - }; - } - - toggleDropdown() { - this.setState((prevState) => { - return {show: !prevState.show}; - }); - } - - makeTeamAdmin() { - updateTeamMemberRoles( - this.props.teamMember.team_id, - this.props.user.id, - 'team_user team_admin', - this.handleMemberChange, - this.props.onError - ); - } - - makeMember() { - updateTeamMemberRoles( - this.props.teamMember.team_id, - this.props.user.id, - 'team_user', - this.handleMemberChange, - this.props.onError - ); - } - - removeFromTeam() { - removeUserFromTeam( - this.props.teamMember.team_id, - this.props.user.id, - this.handleMemberRemove, - this.props.onError - ); - } - - handleMemberChange() { - this.props.onMemberChange(this.props.teamMember.team_id); - } - - handleMemberRemove() { - this.props.onMemberRemove(this.props.teamMember.team_id); - } - - render() { - const isTeamAdmin = Utils.isAdmin(this.props.teamMember.roles); - - let title; - if (isTeamAdmin) { - title = Utils.localizeMessage('admin.user_item.teamAdmin', 'Team Admin'); - } else { - title = Utils.localizeMessage('admin.user_item.teamMember', 'Team Member'); - } - - let makeTeamAdmin = null; - if (!isTeamAdmin) { - makeTeamAdmin = ( - - - - ); - } - - let makeMember = null; - if (isTeamAdmin) { - makeMember = ( - - - - ); - } - - return ( - - - {title} - - - {makeTeamAdmin} - {makeMember} - - - - - - ); - } -} diff --git a/webapp/components/admin_console/manage_teams_modal/manage_teams_modal.jsx b/webapp/components/admin_console/manage_teams_modal/manage_teams_modal.jsx deleted file mode 100644 index 21f9d762d32..00000000000 --- a/webapp/components/admin_console/manage_teams_modal/manage_teams_modal.jsx +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import {Modal} from 'react-bootstrap'; -import {FormattedMessage} from 'react-intl'; -import PropTypes from 'prop-types'; - -import * as TeamActions from 'actions/team_actions.jsx'; - -import {Client4} from 'mattermost-redux/client'; - -import LoadingScreen from 'components/loading_screen.jsx'; - -import {sortTeamsByDisplayName} from 'utils/team_utils.jsx'; -import * as Utils from 'utils/utils.jsx'; - -import ManageTeamsDropdown from './manage_teams_dropdown.jsx'; -import RemoveFromTeamButton from './remove_from_team_button.jsx'; - -export default class ManageTeamsModal extends React.Component { - static propTypes = { - onModalDismissed: PropTypes.func.isRequired, - show: PropTypes.bool.isRequired, - user: PropTypes.object - }; - - constructor(props) { - super(props); - - this.state = { - error: null, - teams: null, - teamMembers: null - }; - } - - componentDidMount() { - if (this.props.user) { - this.loadTeamsAndTeamMembers(); - } - } - - componentWillReceiveProps(nextProps) { - const userId = this.props.user ? this.props.user.id : ''; - const nextUserId = nextProps.user ? nextProps.user.id : ''; - - if (userId !== nextUserId) { - this.setState({ - teams: null, - teamMembers: null - }); - - if (nextProps.user) { - this.loadTeamsAndTeamMembers(nextProps.user); - } - } - } - - loadTeamsAndTeamMembers = (user = this.props.user) => { - TeamActions.getTeamsForUser(user.id, (teams) => { - this.setState({ - teams: teams.sort(sortTeamsByDisplayName) - }); - }); - - TeamActions.getTeamMembersForUser(user.id, (teamMembers) => { - this.setState({ - teamMembers - }); - }); - } - - handleError = (error) => { - this.setState({ - error - }); - } - - handleMemberChange = () => { - TeamActions.getTeamMembersForUser(this.props.user.id, (teamMembers) => { - this.setState({ - teamMembers - }); - }); - } - - handleMemberRemove = (teamId) => { - this.setState({ - teams: this.state.teams.filter((team) => team.id !== teamId), - teamMembers: this.state.teamMembers.filter((teamMember) => teamMember.team_id !== teamId) - }); - } - - renderContents = () => { - const {user} = this.props; - const {teams, teamMembers} = this.state; - - if (!user) { - return ; - } - - const isSystemAdmin = Utils.isAdmin(user.roles); - - let name = Utils.getFullName(user); - if (name) { - name += ` (@${user.username})`; - } else { - name = `@${user.username}`; - } - - let teamList; - if (teams && teamMembers) { - teamList = teams.map((team) => { - const teamMember = teamMembers.find((member) => member.team_id === team.id); - if (!teamMember) { - return null; - } - - let action; - if (isSystemAdmin) { - action = ( - - ); - } else { - action = ( - - ); - } - - return ( -
    -
    - {team.display_name} -
    -
    - {action} -
    -
    - ); - }); - } else { - teamList = ; - } - - let systemAdminIndicator = null; - if (isSystemAdmin) { - systemAdminIndicator = ( -
    - -
    - ); - } - - return ( -
    -
    - -
    -
    - {name} -
    -
    - {user.email} -
    -
    - {systemAdminIndicator} -
    -
    - {teamList} -
    -
    - ); - } - - render() { - return ( - - - - - - - - {this.renderContents()} - - - ); - } -} diff --git a/webapp/components/admin_console/manage_teams_modal/remove_from_team_button.jsx b/webapp/components/admin_console/manage_teams_modal/remove_from_team_button.jsx deleted file mode 100644 index 69579d46fd4..00000000000 --- a/webapp/components/admin_console/manage_teams_modal/remove_from_team_button.jsx +++ /dev/null @@ -1,54 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import {FormattedMessage} from 'react-intl'; - -import {removeUserFromTeam} from 'actions/team_actions.jsx'; - -export default class RemoveFromTeamButton extends React.PureComponent { - static propTypes = { - onError: PropTypes.func.isRequired, - onMemberRemove: PropTypes.func.isRequired, - team: PropTypes.object.isRequired, - user: PropTypes.object.isRequired - }; - - constructor(props) { - super(props); - - this.handleClick = this.handleClick.bind(this); - this.handleMemberRemove = this.handleMemberRemove.bind(this); - } - - handleClick(e) { - e.preventDefault(); - - removeUserFromTeam( - this.props.team.id, - this.props.user.id, - this.handleMemberRemove, - this.props.onError - ); - } - - handleMemberRemove() { - this.props.onMemberRemove(this.props.team.id); - } - - render() { - return ( - - ); - } -} diff --git a/webapp/components/admin_console/manage_tokens_modal/index.js b/webapp/components/admin_console/manage_tokens_modal/index.js deleted file mode 100644 index 9f7a3114115..00000000000 --- a/webapp/components/admin_console/manage_tokens_modal/index.js +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {getUserAccessTokensForUser} from 'mattermost-redux/actions/users'; - -import ManageTokensModal from './manage_tokens_modal.jsx'; - -function mapStateToProps(state, ownProps) { - const userId = ownProps.user ? ownProps.user.id : ''; - - return { - ...ownProps, - userAccessTokens: state.entities.admin.userAccessTokens[userId] - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getUserAccessTokensForUser - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(ManageTokensModal); diff --git a/webapp/components/admin_console/manage_tokens_modal/manage_tokens_modal.jsx b/webapp/components/admin_console/manage_tokens_modal/manage_tokens_modal.jsx deleted file mode 100644 index fdef870e57f..00000000000 --- a/webapp/components/admin_console/manage_tokens_modal/manage_tokens_modal.jsx +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import LoadingScreen from 'components/loading_screen.jsx'; -import RevokeTokenButton from 'components/admin_console/revoke_token_button'; - -import {Client4} from 'mattermost-redux/client'; -import * as UserUtils from 'mattermost-redux/utils/user_utils'; - -import React from 'react'; -import {Modal} from 'react-bootstrap'; -import PropTypes from 'prop-types'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; - -export default class ManageTokensModal extends React.PureComponent { - static propTypes = { - - /** - * Set to render the modal - */ - show: PropTypes.bool.isRequired, - - /** - * The user the roles are being managed for - */ - user: PropTypes.object, - - /** - * The personal access tokens for a user, object with token ids as keys - */ - userAccessTokens: PropTypes.object, - - /** - * Function called when modal is dismissed - */ - onModalDismissed: PropTypes.func.isRequired, - - actions: PropTypes.shape({ - - /** - * Function to get a user's access tokens - */ - getUserAccessTokensForUser: PropTypes.func.isRequired - }).isRequired - }; - - constructor(props) { - super(props); - this.state = {error: null}; - } - - componentWillReceiveProps(nextProps) { - const userId = this.props.user ? this.props.user.id : null; - const nextUserId = nextProps.user ? nextProps.user.id : null; - if (nextUserId && nextUserId !== userId) { - this.props.actions.getUserAccessTokensForUser(nextUserId, 0, 200); - } - } - - handleError = (error) => { - this.setState({ - error - }); - } - - renderContents = () => { - const {user, userAccessTokens} = this.props; - - if (!user) { - return ; - } - - let name = UserUtils.getFullName(user); - if (name) { - name += ` (@${user.username})`; - } else { - name = `@${user.username}`; - } - - let tokenList; - if (userAccessTokens) { - const userAccessTokensList = Object.values(userAccessTokens); - - if (userAccessTokensList.length === 0) { - tokenList = ( -
    - -
    - ); - } else { - tokenList = userAccessTokensList.map((token) => { - return ( -
    -
    -
    - - {token.description} -
    -
    - - {token.id} -
    -
    -
    - -
    -
    - ); - }); - } - } else { - tokenList = ; - } - - return ( -
    -
    - -
    -
    - {name} -
    -
    - {user.email} -
    -
    -
    -
    - -
    -
    - {tokenList} -
    -
    - ); - } - - render() { - return ( - - - - - - - - {this.renderContents()} - {this.state.error} - - - ); - } -} diff --git a/webapp/components/admin_console/metrics_settings.jsx b/webapp/components/admin_console/metrics_settings.jsx deleted file mode 100644 index 9eab4073bc1..00000000000 --- a/webapp/components/admin_console/metrics_settings.jsx +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import TextSetting from './text_setting.jsx'; - -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -export default class MetricsSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.MetricsSettings.Enable = this.state.enable; - config.MetricsSettings.ListenAddress = this.state.listenAddress; - - return config; - } - - getStateFromConfig(config) { - const settings = config.MetricsSettings; - - return { - enable: settings.Enable, - listenAddress: settings.ListenAddress - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - const licenseEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.Metrics === 'true'; - if (!licenseEnabled) { - return null; - } - - return ( - - - } - helpText={ - - } - value={this.state.enable} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.metrics.listenAddressEx', 'Ex ":8067"')} - helpText={ - - } - value={this.state.listenAddress} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/mfa_settings.jsx b/webapp/components/admin_console/mfa_settings.jsx deleted file mode 100644 index 9d7a64d05b0..00000000000 --- a/webapp/components/admin_console/mfa_settings.jsx +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import AdminSettings from './admin_settings.jsx'; -import SettingsGroup from './settings_group.jsx'; -import BooleanSetting from './boolean_setting.jsx'; - -import React from 'react'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; - -export default class MfaSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - - this.state = Object.assign(this.state, { - enableMultifactorAuthentication: props.config.ServiceSettings.EnableMultifactorAuthentication, - enforceMultifactorAuthentication: props.config.ServiceSettings.EnforceMultifactorAuthentication - }); - } - - getConfigFromState(config) { - config.ServiceSettings.EnableMultifactorAuthentication = this.state.enableMultifactorAuthentication; - config.ServiceSettings.EnforceMultifactorAuthentication = this.state.enableMultifactorAuthentication && this.state.enforceMultifactorAuthentication; - - return config; - } - - getStateFromConfig(config) { - return { - enableMultifactorAuthentication: config.ServiceSettings.EnableMultifactorAuthentication, - enforceMultifactorAuthentication: config.ServiceSettings.EnableMultifactorAuthentication && config.ServiceSettings.EnforceMultifactorAuthentication - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - -
    -
    - -
    -
    - - } - helpText={ - - } - value={this.state.enableMultifactorAuthentication} - onChange={this.handleChange} - /> - - } - helpText={ - - } - disabled={!this.state.enableMultifactorAuthentication} - value={this.state.enforceMultifactorAuthentication} - onChange={this.handleChange} - /> -
    - ); - } -} diff --git a/webapp/components/admin_console/multiselect_settings.jsx b/webapp/components/admin_console/multiselect_settings.jsx deleted file mode 100644 index 8ae8e1349bd..00000000000 --- a/webapp/components/admin_console/multiselect_settings.jsx +++ /dev/null @@ -1,81 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. -import React from 'react'; -import ReactSelect from 'react-select'; - -import Setting from './setting.jsx'; -import FormError from 'components/form_error.jsx'; - -export default class MultiSelectSetting extends React.Component { - constructor(props) { - super(props); - - this.handleChange = this.handleChange.bind(this); - this.state = {error: false}; - } - - handleChange(newValue) { - const values = newValue.map((n) => { - return n.value; - }); - - if (this.props.selected.length > 0 && this.props.mustBePresent && values.join(',').indexOf(this.props.mustBePresent) === -1) { - this.setState({error: this.props.notPresent}); - } else { - this.props.onChange(this.props.id, values); - this.setState({error: false}); - } - } - - componentWillReceiveProps(newProps) { - if (newProps.selected.length > 0 && newProps.mustBePresent && newProps.selected.join(',').indexOf(newProps.mustBePresent) === -1) { - this.setState({error: this.props.notPresent}); - } else { - this.setState({error: false}); - } - } - - render() { - return ( - - - - - ); - } -} - -MultiSelectSetting.defaultProps = { - disabled: false -}; - -MultiSelectSetting.propTypes = { - id: PropTypes.string.isRequired, - values: PropTypes.array.isRequired, - label: PropTypes.node.isRequired, - selected: PropTypes.array.isRequired, - mustBePresent: PropTypes.string, - onChange: PropTypes.func.isRequired, - disabled: PropTypes.bool, - helpText: PropTypes.node, - noResultText: PropTypes.node, - errorText: PropTypes.node, - notPresent: PropTypes.node -}; diff --git a/webapp/components/admin_console/native_app_link_settings.jsx b/webapp/components/admin_console/native_app_link_settings.jsx deleted file mode 100644 index 88c07847631..00000000000 --- a/webapp/components/admin_console/native_app_link_settings.jsx +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class NativeAppLinkSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.NativeAppSettings.AppDownloadLink = this.state.appDownloadLink; - config.NativeAppSettings.AndroidAppDownloadLink = this.state.androidAppDownloadLink; - config.NativeAppSettings.IosAppDownloadLink = this.state.iosAppDownloadLink; - - return config; - } - - getStateFromConfig(config) { - return { - appDownloadLink: config.NativeAppSettings.AppDownloadLink, - androidAppDownloadLink: config.NativeAppSettings.AndroidAppDownloadLink, - iosAppDownloadLink: config.NativeAppSettings.IosAppDownloadLink - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ - - } - value={this.state.appDownloadLink} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.androidAppDownloadLink} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.iosAppDownloadLink} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/oauth_settings.jsx b/webapp/components/admin_console/oauth_settings.jsx deleted file mode 100644 index abb4dc76261..00000000000 --- a/webapp/components/admin_console/oauth_settings.jsx +++ /dev/null @@ -1,430 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import * as Utils from 'utils/utils.jsx'; -import Constants from 'utils/constants.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import DropdownSetting from './dropdown_setting.jsx'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -import React from 'react'; -import {FormattedHTMLMessage, FormattedMessage} from 'react-intl'; - -export default class OAuthSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - this.getStateFromConfig = this.getStateFromConfig.bind(this); - this.renderSettings = this.renderSettings.bind(this); - this.renderOffice365 = this.renderOffice365.bind(this); - this.renderGoogle = this.renderGoogle.bind(this); - this.renderGitLab = this.renderGitLab.bind(this); - this.changeType = this.changeType.bind(this); - } - - getConfigFromState(config) { - config.GitLabSettings.Enable = false; - config.GoogleSettings.Enable = false; - config.Office365Settings.Enable = false; - - if (this.state.oauthType === Constants.GITLAB_SERVICE) { - config.GitLabSettings.Enable = true; - config.GitLabSettings.Id = this.state.id; - config.GitLabSettings.Secret = this.state.secret; - config.GitLabSettings.UserApiEndpoint = this.state.userApiEndpoint; - config.GitLabSettings.AuthEndpoint = this.state.authEndpoint; - config.GitLabSettings.TokenEndpoint = this.state.tokenEndpoint; - } - - if (this.state.oauthType === Constants.GOOGLE_SERVICE) { - config.GoogleSettings.Enable = true; - config.GoogleSettings.Id = this.state.id; - config.GoogleSettings.Secret = this.state.secret; - config.GoogleSettings.UserApiEndpoint = 'https://www.googleapis.com/plus/v1/people/me'; - config.GoogleSettings.AuthEndpoint = 'https://accounts.google.com/o/oauth2/v2/auth'; - config.GoogleSettings.TokenEndpoint = 'https://www.googleapis.com/oauth2/v4/token'; - config.GoogleSettings.Scope = 'profile email'; - } - - if (this.state.oauthType === Constants.OFFICE365_SERVICE) { - config.Office365Settings.Enable = true; - config.Office365Settings.Id = this.state.id; - config.Office365Settings.Secret = this.state.secret; - config.Office365Settings.UserApiEndpoint = 'https://graph.microsoft.com/v1.0/me'; - config.Office365Settings.AuthEndpoint = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize'; - config.Office365Settings.TokenEndpoint = 'https://login.microsoftonline.com/common/oauth2/v2.0/token'; - config.Office365Settings.Scope = 'User.Read'; - } - - return config; - } - - getStateFromConfig(config) { - this.config = config; - - let oauthType = 'off'; - let settings = {}; - if (config.GitLabSettings.Enable) { - oauthType = Constants.GITLAB_SERVICE; - settings = config.GitLabSettings; - } else if (config.GoogleSettings.Enable) { - oauthType = Constants.GOOGLE_SERVICE; - settings = config.GoogleSettings; - } else if (config.Office365Settings.Enable) { - oauthType = Constants.OFFICE365_SERVICE; - settings = config.Office365Settings; - } - - return { - oauthType, - id: settings.Id, - secret: settings.Secret, - userApiEndpoint: settings.UserApiEndpoint, - authEndpoint: settings.AuthEndpoint, - tokenEndpoint: settings.TokenEndpoint - }; - } - - changeType(id, value) { - let settings = {}; - if (value === Constants.GITLAB_SERVICE) { - settings = this.config.GitLabSettings; - } else if (value === Constants.GOOGLE_SERVICE) { - settings = this.config.GoogleSettings; - } else if (value === Constants.OFFICE365_SERVICE) { - settings = this.config.Office365Settings; - } - - this.setState({ - id: settings.Id, - secret: settings.Secret, - userApiEndpoint: settings.UserApiEndpoint, - authEndpoint: settings.AuthEndpoint, - tokenEndpoint: settings.TokenEndpoint - }); - - this.handleChange(id, value); - } - - renderTitle() { - return ( - - ); - } - - renderGoogle() { - return ( -
    - - } - placeholder={Utils.localizeMessage('admin.google.clientIdExample', 'Ex "7602141235235-url0fhs1mayfasbmop5qlfns8dh4.apps.googleusercontent.com"')} - helpText={ - - } - value={this.state.id} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.google.clientSecretExample', 'Ex "H8sz0Az-dDs2p15-7QzD231"')} - helpText={ - - } - value={this.state.secret} - onChange={this.handleChange} - /> - - } - value='https://www.googleapis.com/plus/v1/people/me' - disabled={true} - /> - - } - value='https://accounts.google.com/o/oauth2/v2/auth' - disabled={true} - /> - - } - value='https://www.googleapis.com/oauth2/v4/token' - disabled={true} - /> -
    - ); - } - - renderOffice365() { - return ( -
    - - } - placeholder={Utils.localizeMessage('admin.office365.clientIdExample', 'Ex "adf3sfa2-ag3f-sn4n-ids0-sh1hdax192qq"')} - helpText={ - - } - value={this.state.id} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.office365.clientSecretExample', 'Ex "shAieM47sNBfgl20f8ci294"')} - helpText={ - - } - value={this.state.secret} - onChange={this.handleChange} - /> - - } - value='https://graph.microsoft.com/v1.0/me' - disabled={true} - /> - - } - value='https://login.microsoftonline.com/common/oauth2/v2.0/authorize' - disabled={true} - /> - - } - value='https://login.microsoftonline.com/common/oauth2/v2.0/token' - disabled={true} - /> -
    - ); - } - - renderGitLab() { - return ( -
    - - } - placeholder={Utils.localizeMessage('admin.gitlab.clientIdExample', 'Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"')} - helpText={ - - } - value={this.state.id} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.gitlab.clientSecretExample', 'Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"')} - helpText={ - - } - value={this.state.secret} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.gitlab.userExample', 'Ex "https:///api/v3/user"')} - helpText={ - - } - value={this.state.userApiEndpoint} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.gitlab.authExample', 'Ex "https:///oauth/authorize"')} - helpText={ - - } - value={this.state.authEndpoint} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.gitlab.tokenExample', 'Ex "https:///oauth/token"')} - helpText={ - - } - value={this.state.tokenEndpoint} - onChange={this.handleChange} - /> -
    - ); - } - - renderSettings() { - let contents; - let helpText; - if (this.state.oauthType === Constants.GITLAB_SERVICE) { - contents = this.renderGitLab(); - helpText = ( - - ); - } else if (this.state.oauthType === Constants.GOOGLE_SERVICE) { - contents = this.renderGoogle(); - helpText = ( - - ); - } else if (this.state.oauthType === Constants.OFFICE365_SERVICE) { - contents = this.renderOffice365(); - helpText = ( - - ); - } - - const oauthTypes = []; - oauthTypes.push({value: 'off', text: Utils.localizeMessage('admin.oauth.off', 'Do not allow sign-in via an OAuth 2.0 provider.')}); - oauthTypes.push({value: Constants.GITLAB_SERVICE, text: Utils.localizeMessage('admin.oauth.gitlab', 'GitLab')}); - if (global.window.mm_license.IsLicensed === 'true') { - if (global.window.mm_license.GoogleOAuth === 'true') { - oauthTypes.push({value: Constants.GOOGLE_SERVICE, text: Utils.localizeMessage('admin.oauth.google', 'Google Apps')}); - } - if (global.window.mm_license.Office365OAuth === 'true') { - oauthTypes.push({value: Constants.OFFICE365_SERVICE, text: Utils.localizeMessage('admin.oauth.office365', 'Office 365 (Beta)')}); - } - } - - return ( - - - } - helpText={helpText} - value={this.state.oauthType} - onChange={this.changeType} - /> - {contents} - - ); - } -} diff --git a/webapp/components/admin_console/password_settings.jsx b/webapp/components/admin_console/password_settings.jsx deleted file mode 100644 index 6f39269c070..00000000000 --- a/webapp/components/admin_console/password_settings.jsx +++ /dev/null @@ -1,281 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import AdminSettings from './admin_settings.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; -import Setting from './setting.jsx'; -import * as Utils from 'utils/utils.jsx'; -import Constants from 'utils/constants.jsx'; - -export default class PasswordSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - - this.getSampleErrorMsg = this.getSampleErrorMsg.bind(this); - - this.handlePasswordLengthChange = this.handlePasswordLengthChange.bind(this); - this.handleCheckboxChange = this.handleCheckboxChange.bind(this); - - this.state = Object.assign(this.state, { - passwordMinimumLength: props.config.PasswordSettings.MinimumLength, - passwordLowercase: props.config.PasswordSettings.Lowercase, - passwordNumber: props.config.PasswordSettings.Number, - passwordUppercase: props.config.PasswordSettings.Uppercase, - passwordSymbol: props.config.PasswordSettings.Symbol, - maximumLoginAttempts: props.config.ServiceSettings.MaximumLoginAttempts - }); - - // Update sample message from config settings - this.sampleErrorMsg = null; - if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.PasswordRequirements === 'true') { - let sampleErrorMsgId = 'user.settings.security.passwordError'; - if (props.config.PasswordSettings.Lowercase) { - sampleErrorMsgId += 'Lowercase'; - } - if (props.config.PasswordSettings.Uppercase) { - sampleErrorMsgId += 'Uppercase'; - } - if (props.config.PasswordSettings.Number) { - sampleErrorMsgId += 'Number'; - } - if (props.config.PasswordSettings.Symbol) { - sampleErrorMsgId += 'Symbol'; - } - this.sampleErrorMsg = ( - - ); - } - } - - getConfigFromState(config) { - if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.PasswordRequirements === 'true') { - config.PasswordSettings.MinimumLength = this.parseIntNonZero(this.state.passwordMinimumLength, Constants.MIN_PASSWORD_LENGTH); - config.PasswordSettings.Lowercase = this.refs.lowercase.checked; - config.PasswordSettings.Uppercase = this.refs.uppercase.checked; - config.PasswordSettings.Number = this.refs.number.checked; - config.PasswordSettings.Symbol = this.refs.symbol.checked; - } - - config.ServiceSettings.MaximumLoginAttempts = this.parseIntNonZero(this.state.maximumLoginAttempts); - - return config; - } - - getStateFromConfig(config) { - return { - passwordMinimumLength: config.PasswordSettings.MinimumLength, - passwordLowercase: config.PasswordSettings.Lowercase, - passwordNumber: config.PasswordSettings.Number, - passwordUppercase: config.PasswordSettings.Uppercase, - passwordSymbol: config.PasswordSettings.Symbol, - maximumLoginAttempts: config.ServiceSettings.MaximumLoginAttempts - }; - } - - getSampleErrorMsg(minLength) { - if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.PasswordRequirements === 'true') { - if (this.props.config.PasswordSettings.MinimumLength > Constants.MAX_PASSWORD_LENGTH || this.props.config.PasswordSettings.MinimumLength < Constants.MIN_PASSWORD_LENGTH) { - return ( - - ); - } - let sampleErrorMsgId = 'user.settings.security.passwordError'; - if (this.refs.lowercase.checked) { - sampleErrorMsgId += 'Lowercase'; - } - if (this.refs.uppercase.checked) { - sampleErrorMsgId += 'Uppercase'; - } - if (this.refs.number.checked) { - sampleErrorMsgId += 'Number'; - } - if (this.refs.symbol.checked) { - sampleErrorMsgId += 'Symbol'; - } - return ( - - ); - } - - return null; - } - - handlePasswordLengthChange(id, value) { - this.sampleErrorMsg = this.getSampleErrorMsg(value); - this.handleChange(id, value); - } - - handleCheckboxChange(id, value) { - this.sampleErrorMsg = this.getSampleErrorMsg(this.state.passwordMinimumLength); - this.handleChange(id, value); - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - let passwordSettings = null; - if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.PasswordRequirements === 'true') { - passwordSettings = ( -
    - - } - placeholder={Utils.localizeMessage('admin.password.minimumLengthExample', 'Ex "5"')} - helpText={ - - } - value={this.state.passwordMinimumLength} - onChange={this.handlePasswordLengthChange} - /> - - } - > -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    - -
    - {this.sampleErrorMsg} -
    -
    -
    - ); - } - - return ( - - {passwordSettings} - - } - placeholder={Utils.localizeMessage('admin.service.attemptExample', 'Ex "10"')} - helpText={ - - } - value={this.state.maximumLoginAttempts} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/plugin_settings/index.js b/webapp/components/admin_console/plugin_settings/index.js deleted file mode 100644 index 469d4ee2e13..00000000000 --- a/webapp/components/admin_console/plugin_settings/index.js +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {uploadPlugin, removePlugin, getPlugins} from 'mattermost-redux/actions/admin'; - -import PluginSettings from './plugin_settings.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps, - plugins: state.entities.admin.plugins - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - uploadPlugin, - removePlugin, - getPlugins - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(PluginSettings); diff --git a/webapp/components/admin_console/plugin_settings/plugin_settings.jsx b/webapp/components/admin_console/plugin_settings/plugin_settings.jsx deleted file mode 100644 index 286e05c06cf..00000000000 --- a/webapp/components/admin_console/plugin_settings/plugin_settings.jsx +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import LoadingScreen from 'components/loading_screen.jsx'; -import Banner from 'components/admin_console/banner.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -import React from 'react'; -import PropTypes from 'prop-types'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; - -export default class PluginSettings extends React.Component { - static propTypes = { - - /* - * The config - */ - config: PropTypes.object.isRequired, - - /* - * Plugins object with ids as keys and manifests as values - */ - plugins: PropTypes.object.isRequired, - - actions: PropTypes.shape({ - - /* - * Function to upload a plugin - */ - uploadPlugin: PropTypes.func.isRequired, - - /* - * Function to remove a plugin - */ - removePlugin: PropTypes.func.isRequired, - - /* - * Function to get installed plugins - */ - getPlugins: PropTypes.func.isRequired - }).isRequired - } - - constructor(props) { - super(props); - - this.state = { - loading: true, - fileSelected: false, - fileName: null, - serverError: null - }; - } - - componentDidMount() { - this.props.actions.getPlugins().then( - () => this.setState({loading: false}) - ); - } - - handleChange = () => { - const element = this.refs.fileInput; - if (element.files.length > 0) { - this.setState({fileSelected: true, fileName: element.files[0].name}); - } - } - - handleSubmit = async (e) => { - e.preventDefault(); - - const element = this.refs.fileInput; - if (element.files.length === 0) { - return; - } - const file = element.files[0]; - - this.setState({uploading: true}); - - const {error} = await this.props.actions.uploadPlugin(file); - this.setState({fileSelected: false, fileName: null, uploading: false}); - Utils.clearFileInput(element); - - if (error) { - if (error.server_error_id === 'app.plugin.activate.app_error') { - this.setState({serverError: Utils.localizeMessage('admin.plugin.error.activate', 'Unable to upload the plugin. It may conflict with another plugin on your server.')}); - } else if (error.server_error_id === 'app.plugin.extract.app_error') { - this.setState({serverError: Utils.localizeMessage('admin.plugin.error.extract', 'Encountered an error when extracting the plugin. Review your plugin file content and try again.')}); - } else { - this.setState({serverError: error.message}); - } - } - } - - handleRemove = async (pluginId) => { - this.setState({removing: pluginId}); - - const {error} = await this.props.actions.removePlugin(pluginId); - this.setState({removing: null}); - - if (error) { - this.setState({serverError: error.message}); - } - } - - render() { - let serverError = ''; - if (this.state.serverError) { - serverError =
    ; - } - - let btnClass = 'btn'; - if (this.state.fileSelected) { - btnClass = 'btn btn-primary'; - } - - let fileName; - if (this.state.fileName) { - fileName = this.state.fileName; - } - - let uploadButtonText; - if (this.state.uploading) { - uploadButtonText = ( - - ); - } else { - uploadButtonText = ( - - ); - } - - let activePluginsList; - let activePluginsContainer; - const plugins = Object.values(this.props.plugins); - if (this.state.loading) { - activePluginsList = ; - } else if (plugins.length === 0) { - activePluginsContainer = ( - - ); - } else { - activePluginsList = plugins.map( - (p) => { - let removeButtonText; - if (this.state.removing === p.id) { - removeButtonText = ( - - ); - } else { - removeButtonText = ( - - ); - } - - return ( -
    -
    - - - - {' ' + p.id} -
    -
    - - - - {' ' + p.description} -
    - -
    -
    - ); - } - ); - - activePluginsContainer = ( -
    - {activePluginsList} -
    - ); - } - - return ( -
    -

    - -

    - } - description={ - - } - /> -
    -
    - -
    -
    - - -
    - -
    - {fileName} -
    - {serverError} -

    - -

    -
    -
    -
    - -
    - {activePluginsContainer} -
    -
    -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/policy_settings.jsx b/webapp/components/admin_console/policy_settings.jsx deleted file mode 100644 index f689efd82b1..00000000000 --- a/webapp/components/admin_console/policy_settings.jsx +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import SettingsGroup from './settings_group.jsx'; -import DropdownSetting from './dropdown_setting.jsx'; -import RadioSetting from './radio_setting.jsx'; -import PostEditSetting from './post_edit_setting.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import TextSetting from './text_setting.jsx'; -import ColorSetting from './color_setting.jsx'; - -import Constants from 'utils/constants.jsx'; -import * as Utils from 'utils/utils.jsx'; - -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; - -export default class PolicySettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ServiceSettings.RestrictPostDelete = this.state.restrictPostDelete; - config.ServiceSettings.AllowEditPost = this.state.allowEditPost; - config.ServiceSettings.PostEditTimeLimit = this.parseIntNonZero(this.state.postEditTimeLimit, Constants.DEFAULT_POST_EDIT_TIME_LIMIT); - config.TeamSettings.RestrictTeamInvite = this.state.restrictTeamInvite; - config.TeamSettings.RestrictPublicChannelCreation = this.state.restrictPublicChannelCreation; - config.TeamSettings.RestrictPrivateChannelCreation = this.state.restrictPrivateChannelCreation; - config.TeamSettings.RestrictPublicChannelManagement = this.state.restrictPublicChannelManagement; - config.TeamSettings.RestrictPrivateChannelManagement = this.state.restrictPrivateChannelManagement; - config.TeamSettings.RestrictPublicChannelDeletion = this.state.restrictPublicChannelDeletion; - config.TeamSettings.RestrictPrivateChannelDeletion = this.state.restrictPrivateChannelDeletion; - config.TeamSettings.RestrictPrivateChannelManageMembers = this.state.restrictPrivateChannelManageMembers; - config.AnnouncementSettings.EnableBanner = this.state.enableBanner; - config.AnnouncementSettings.BannerText = this.state.bannerText; - config.AnnouncementSettings.BannerColor = this.state.bannerColor; - config.AnnouncementSettings.BannerTextColor = this.state.bannerTextColor; - config.AnnouncementSettings.AllowBannerDismissal = this.state.allowBannerDismissal; - - return config; - } - - getStateFromConfig(config) { - return { - restrictPostDelete: config.ServiceSettings.RestrictPostDelete, - allowEditPost: config.ServiceSettings.AllowEditPost, - postEditTimeLimit: config.ServiceSettings.PostEditTimeLimit, - restrictTeamInvite: config.TeamSettings.RestrictTeamInvite, - restrictPublicChannelCreation: config.TeamSettings.RestrictPublicChannelCreation, - restrictPrivateChannelCreation: config.TeamSettings.RestrictPrivateChannelCreation, - restrictPublicChannelManagement: config.TeamSettings.RestrictPublicChannelManagement, - restrictPrivateChannelManagement: config.TeamSettings.RestrictPrivateChannelManagement, - restrictPublicChannelDeletion: config.TeamSettings.RestrictPublicChannelDeletion, - restrictPrivateChannelDeletion: config.TeamSettings.RestrictPrivateChannelDeletion, - restrictPrivateChannelManageMembers: config.TeamSettings.RestrictPrivateChannelManageMembers, - enableBanner: config.AnnouncementSettings.EnableBanner, - bannerText: config.AnnouncementSettings.BannerText, - bannerColor: config.AnnouncementSettings.BannerColor, - bannerTextColor: config.AnnouncementSettings.BannerTextColor, - allowBannerDismissal: config.AnnouncementSettings.AllowBannerDismissal - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - value={this.state.restrictTeamInvite} - onChange={this.handleChange} - helpText={ - - } - /> - - } - value={this.state.restrictPublicChannelCreation} - onChange={this.handleChange} - helpText={ - - } - /> - - } - value={this.state.restrictPublicChannelManagement} - onChange={this.handleChange} - helpText={ - - } - /> - - } - value={this.state.restrictPublicChannelDeletion} - onChange={this.handleChange} - helpText={ - - - - ) - }} - /> - } - /> - - } - value={this.state.restrictPrivateChannelCreation} - onChange={this.handleChange} - helpText={ - - } - /> - - } - value={this.state.restrictPrivateChannelManagement} - onChange={this.handleChange} - helpText={ - - } - /> - - } - value={this.state.restrictPrivateChannelManageMembers} - onChange={this.handleChange} - helpText={ - - } - /> - - } - value={this.state.restrictPrivateChannelDeletion} - onChange={this.handleChange} - helpText={ - - - - ) - }} - /> - } - /> - - } - value={this.state.restrictPostDelete} - onChange={this.handleChange} - helpText={ - - } - /> - - } - value={this.state.allowEditPost} - timeLimitValue={this.state.postEditTimeLimit} - onChange={this.handleChange} - helpText={ - - } - /> - - } - helpText={ - - } - value={this.state.enableBanner} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.bannerText} - onChange={this.handleChange} - disabled={!this.state.enableBanner} - /> - - } - value={this.state.bannerColor} - onChange={this.handleChange} - disabled={!this.state.enableBanner} - /> - - } - value={this.state.bannerTextColor} - onChange={this.handleChange} - disabled={!this.state.enableBanner} - /> - - } - helpText={ - - } - value={this.state.allowBannerDismissal} - onChange={this.handleChange} - disabled={!this.state.enableBanner} - /> - - ); - } -} diff --git a/webapp/components/admin_console/post_edit_setting.jsx b/webapp/components/admin_console/post_edit_setting.jsx deleted file mode 100644 index 08fafc14be6..00000000000 --- a/webapp/components/admin_console/post_edit_setting.jsx +++ /dev/null @@ -1,101 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import Setting from './setting.jsx'; - -import Constants from 'utils/constants.jsx'; -import * as Utils from 'utils/utils.jsx'; - -export default class PostEditSetting extends React.Component { - constructor(props) { - super(props); - - this.handleChange = this.handleChange.bind(this); - this.handleTimeLimitChange = this.handleTimeLimitChange.bind(this); - } - - handleChange(e) { - this.props.onChange(this.props.id, e.target.value); - } - - handleTimeLimitChange(e) { - this.props.onChange(this.props.timeLimitId, e.target.value); - } - - render() { - return ( - -
    - -
    -
    - -
    -
    - -
    -
    - ); - } -} - -PostEditSetting.defaultProps = { - isDisabled: false -}; - -PostEditSetting.propTypes = { - id: PropTypes.string.isRequired, - timeLimitId: PropTypes.string.isRequired, - label: PropTypes.node.isRequired, - value: PropTypes.string.isRequired, - timeLimitValue: PropTypes.number.isRequired, - onChange: PropTypes.func.isRequired, - disabled: PropTypes.bool, - helpText: PropTypes.node -}; diff --git a/webapp/components/admin_console/privacy_settings.jsx b/webapp/components/admin_console/privacy_settings.jsx deleted file mode 100644 index 92fcb3e887b..00000000000 --- a/webapp/components/admin_console/privacy_settings.jsx +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; - -export default class PrivacySettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.PrivacySettings.ShowEmailAddress = this.state.showEmailAddress; - config.PrivacySettings.ShowFullName = this.state.showFullName; - - return config; - } - - getStateFromConfig(config) { - return { - showEmailAddress: config.PrivacySettings.ShowEmailAddress, - showFullName: config.PrivacySettings.ShowFullName - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ - - } - value={this.state.showEmailAddress} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.showFullName} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/public_link_settings.jsx b/webapp/components/admin_console/public_link_settings.jsx deleted file mode 100644 index a105743534f..00000000000 --- a/webapp/components/admin_console/public_link_settings.jsx +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import GeneratedSetting from './generated_setting.jsx'; -import SettingsGroup from './settings_group.jsx'; - -export default class PublicLinkSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.FileSettings.EnablePublicLink = this.state.enablePublicLink; - config.FileSettings.PublicLinkSalt = this.state.publicLinkSalt; - - return config; - } - - getStateFromConfig(config) { - return { - enablePublicLink: config.FileSettings.EnablePublicLink, - publicLinkSalt: config.FileSettings.PublicLinkSalt - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ - - } - value={this.state.enablePublicLink} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.publicLinkSalt} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/push_settings.jsx b/webapp/components/admin_console/push_settings.jsx deleted file mode 100644 index b5f788c8672..00000000000 --- a/webapp/components/admin_console/push_settings.jsx +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import Constants from 'utils/constants.jsx'; -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import DropdownSetting from './dropdown_setting.jsx'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -const PUSH_NOTIFICATIONS_OFF = 'off'; -const PUSH_NOTIFICATIONS_MHPNS = 'mhpns'; -const PUSH_NOTIFICATIONS_MTPNS = 'mtpns'; -const PUSH_NOTIFICATIONS_CUSTOM = 'custom'; - -export default class PushSettings extends AdminSettings { - constructor(props) { - super(props); - - this.canSave = this.canSave.bind(this); - - this.handleAgreeChange = this.handleAgreeChange.bind(this); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - canSave() { - return this.state.pushNotificationServerType !== PUSH_NOTIFICATIONS_MHPNS || this.state.agree; - } - - handleAgreeChange(e) { - this.setState({ - agree: e.target.checked - }); - } - - handleChange(id, value) { - if (id === 'pushNotificationServerType') { - this.setState({ - agree: false - }); - - if (value === PUSH_NOTIFICATIONS_MHPNS) { - this.setState({ - pushNotificationServer: Constants.MHPNS - }); - } else if (value === PUSH_NOTIFICATIONS_MTPNS) { - this.setState({ - pushNotificationServer: Constants.MTPNS - }); - } - } - - super.handleChange(id, value); - } - - getConfigFromState(config) { - config.EmailSettings.SendPushNotifications = this.state.pushNotificationServerType !== PUSH_NOTIFICATIONS_OFF; - config.EmailSettings.PushNotificationServer = this.state.pushNotificationServer.trim(); - config.EmailSettings.PushNotificationContents = this.state.pushNotificationContents; - - return config; - } - - getStateFromConfig(config) { - let pushNotificationServerType = PUSH_NOTIFICATIONS_CUSTOM; - let agree = false; - if (!config.EmailSettings.SendPushNotifications) { - pushNotificationServerType = PUSH_NOTIFICATIONS_OFF; - } else if (config.EmailSettings.PushNotificationServer === Constants.MHPNS && - global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.MHPNS === 'true') { - pushNotificationServerType = PUSH_NOTIFICATIONS_MHPNS; - agree = true; - } else if (config.EmailSettings.PushNotificationServer === Constants.MTPNS) { - pushNotificationServerType = PUSH_NOTIFICATIONS_MTPNS; - } - - let pushNotificationServer = config.EmailSettings.PushNotificationServer; - if (pushNotificationServerType === PUSH_NOTIFICATIONS_MTPNS) { - pushNotificationServer = Constants.MTPNS; - } else if (pushNotificationServerType === PUSH_NOTIFICATIONS_MHPNS) { - pushNotificationServer = Constants.MHPNS; - } - - return { - pushNotificationServerType, - pushNotificationServer, - pushNotificationContents: config.EmailSettings.PushNotificationContents, - agree - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - const pushNotificationServerTypes = []; - pushNotificationServerTypes.push({value: PUSH_NOTIFICATIONS_OFF, text: Utils.localizeMessage('admin.email.pushOff', 'Do not send push notifications')}); - if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.MHPNS === 'true') { - pushNotificationServerTypes.push({value: PUSH_NOTIFICATIONS_MHPNS, text: Utils.localizeMessage('admin.email.mhpns', 'Use encrypted, production-quality HPNS connection to iOS and Android apps')}); - } - pushNotificationServerTypes.push({value: PUSH_NOTIFICATIONS_MTPNS, text: Utils.localizeMessage('admin.email.mtpns', 'Use iOS and Android apps on iTunes and Google Play with TPNS')}); - pushNotificationServerTypes.push({value: PUSH_NOTIFICATIONS_CUSTOM, text: Utils.localizeMessage('admin.email.selfPush', 'Manually enter Push Notification Service location')}); - - let sendHelpText = null; - let pushServerHelpText = null; - if (this.state.pushNotificationServerType === PUSH_NOTIFICATIONS_OFF) { - sendHelpText = ( - - ); - } else if (this.state.pushNotificationServerType === PUSH_NOTIFICATIONS_MHPNS) { - pushServerHelpText = ( - - ); - } else if (this.state.pushNotificationServerType === PUSH_NOTIFICATIONS_MTPNS) { - pushServerHelpText = ( - - ); - } else { - pushServerHelpText = ( - - ); - } - - let tosCheckbox; - if (this.state.pushNotificationServerType === PUSH_NOTIFICATIONS_MHPNS) { - tosCheckbox = ( -
    -
    -
    - - -
    -
    - ); - } - - return ( - - } - > - - } - value={this.state.pushNotificationServerType} - onChange={this.handleChange} - helpText={sendHelpText} - /> - {tosCheckbox} - - } - placeholder={Utils.localizeMessage('admin.email.pushServerEx', 'E.g.: "http://push-test.mattermost.com"')} - helpText={pushServerHelpText} - value={this.state.pushNotificationServer} - onChange={this.handleChange} - disabled={this.state.pushNotificationServerType !== PUSH_NOTIFICATIONS_CUSTOM} - /> - - } - value={this.state.pushNotificationContents} - onChange={this.handleChange} - disabled={this.state.pushNotificationServerType === PUSH_NOTIFICATIONS_OFF} - helpText={ - - } - /> - - ); - } -} diff --git a/webapp/components/admin_console/radio_setting.jsx b/webapp/components/admin_console/radio_setting.jsx deleted file mode 100644 index 7a6c2e459b3..00000000000 --- a/webapp/components/admin_console/radio_setting.jsx +++ /dev/null @@ -1,65 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import Setting from './setting.jsx'; - -export default class RadioSetting extends React.Component { - constructor(props) { - super(props); - - this.handleChange = this.handleChange.bind(this); - } - - handleChange(e) { - this.props.onChange(this.props.id, e.target.value); - } - - render() { - const options = []; - for (const {value, text} of this.props.values) { - options.push( -
    - -
    - ); - } - - return ( - - {options} - - ); - } -} - -RadioSetting.defaultProps = { - isDisabled: false -}; - -RadioSetting.propTypes = { - id: PropTypes.string.isRequired, - values: PropTypes.array.isRequired, - label: PropTypes.node.isRequired, - value: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - disabled: PropTypes.bool, - helpText: PropTypes.node -}; diff --git a/webapp/components/admin_console/rate_settings.jsx b/webapp/components/admin_console/rate_settings.jsx deleted file mode 100644 index a0cf14f7597..00000000000 --- a/webapp/components/admin_console/rate_settings.jsx +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class RateSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.RateLimitSettings.Enable = this.state.enable; - config.RateLimitSettings.PerSec = this.parseIntNonZero(this.state.perSec); - config.RateLimitSettings.MaxBurst = this.parseIntNonZero(this.state.maxBurst); - config.RateLimitSettings.MemoryStoreSize = this.parseIntNonZero(this.state.memoryStoreSize); - config.RateLimitSettings.VaryByRemoteAddr = this.state.varyByRemoteAddr; - config.RateLimitSettings.VaryByHeader = this.state.varyByHeader; - - return config; - } - - getStateFromConfig(config) { - return { - enable: config.RateLimitSettings.Enable, - perSec: config.RateLimitSettings.PerSec, - maxBurst: config.RateLimitSettings.MaxBurst, - memoryStoreSize: config.RateLimitSettings.MemoryStoreSize, - varyByRemoteAddr: config.RateLimitSettings.VaryByRemoteAddr, - varyByHeader: config.RateLimitSettings.VaryByHeader - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - -
    -
    - -
    -
    - - } - helpText={ - - } - value={this.state.enable} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.rate.queriesExample', 'Ex "10"')} - helpText={ - - } - value={this.state.perSec} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.rate.maxBurstExample', 'Ex "100"')} - helpText={ - - } - value={this.state.maxBurst} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.rate.memoryExample', 'Ex "10000"')} - helpText={ - - } - value={this.state.memoryStoreSize} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - helpText={ - - } - value={this.state.varyByRemoteAddr} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.rate.httpHeaderExample', 'Ex "X-Real-IP", "X-Forwarded-For"')} - helpText={ - - } - value={this.state.varyByHeader} - onChange={this.handleChange} - disabled={!this.state.enable || this.state.varyByRemoteAddr} - /> -
    - ); - } -} diff --git a/webapp/components/admin_console/remove_file_setting.jsx b/webapp/components/admin_console/remove_file_setting.jsx deleted file mode 100644 index ff453d9fcce..00000000000 --- a/webapp/components/admin_console/remove_file_setting.jsx +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import $ from 'jquery'; -import PropTypes from 'prop-types'; -import React from 'react'; - -import Setting from './setting.jsx'; - -export default class RemoveFileSetting extends Setting { - static get propTypes() { - return { - id: PropTypes.string.isRequired, - label: PropTypes.node.isRequired, - helpText: PropTypes.node, - removeButtonText: PropTypes.node.isRequired, - removingText: PropTypes.node, - fileName: PropTypes.string.isRequired, - onSubmit: PropTypes.func.isRequired, - disabled: PropTypes.bool - }; - } - - constructor(props) { - super(props); - this.handleRemove = this.handleRemove.bind(this); - } - - handleRemove(e) { - e.preventDefault(); - - $(this.refs.remove_button).button('loading'); - this.props.onSubmit(this.props.id, () => { - $(this.refs.remove_button).button('reset'); - }); - } - - render() { - return ( - -
    -
    - {this.props.fileName} -
    - -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/request_button/request_button.jsx b/webapp/components/admin_console/request_button/request_button.jsx deleted file mode 100644 index e78d0443ddb..00000000000 --- a/webapp/components/admin_console/request_button/request_button.jsx +++ /dev/null @@ -1,262 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import {FormattedMessage} from 'react-intl'; -import PropTypes from 'prop-types'; - -import * as Utils from 'utils/utils.jsx'; - -/** - * A button which, when clicked, performs an action and displays - * its outcome as either success, or failure accompanied by the - * `message` property of the `err` object. - */ -export default class RequestButton extends React.Component { - static propTypes = { - - /** - * The action to be called to carry out the request. - */ - requestAction: PropTypes.func.isRequired, - - /** - * A component that displays help text for the request button. - * - * Typically, this will be a . - */ - helpText: PropTypes.element.isRequired, - - /** - * A component to be displayed on the button. - * - * Typically, this will be a - */ - buttonText: PropTypes.element.isRequired, - - /** - * The element to display as the field label. - * - * Typically, this will be a - */ - label: PropTypes.element, - - /** - * True if the button form control should be disabled, otherwise false. - */ - disabled: PropTypes.bool, - - /** - * True if the config needs to be saved before running the request, otherwise false. - * - * If set to true, the action provided in the `saveConfigAction` property will be - * called before the action provided in the `requestAction` property, with the later - * only being called if the former is successful. - */ - saveNeeded: PropTypes.bool, - - /** - * Action to be called to save the config, if saveNeeded is set to true. - */ - saveConfigAction: PropTypes.func, - - /** - * True if the success message should be show when the request completes successfully, - * otherwise false. - */ - showSuccessMessage: PropTypes.bool, - - /** - * The message to show when the request completes successfully. - */ - successMessage: PropTypes.shape({ - - /** - * The i18n string ID for the success message. - */ - id: PropTypes.string.isRequired, - - /** - * The i18n default value for the success message. - */ - defaultMessage: PropTypes.string.isRequired - }), - - /** - * The message to show when the request returns an error. - */ - errorMessage: PropTypes.shape({ - - /** - * The i18n string ID for the error message. - */ - id: PropTypes.string.isRequired, - - /** - * The i18n default value for the error message. - * - * The placeholder {error} may be used to include the error message returned - * by the server in response to the failed request. - */ - defaultMessage: PropTypes.string.isRequired - }), - - /** - * True if the {error} placeholder for the `errorMessage` property should include both - * the `message` and `detailed_error` properties of the error returned from the server, - * otherwise false to include only the `message` property. - */ - includeDetailedError: PropTypes.bool, - - /** - * An element to display adjacent to the request button. - */ - alternativeActionElement: PropTypes.element - } - - static defaultProps = { - disabled: false, - saveNeeded: false, - showSuccessMessage: true, - includeDetailedError: false, - successMessage: { - id: 'admin.requestButton.requestSuccess', - defaultMessage: 'Test Successful' - }, - errorMessage: { - id: 'admin.requestButton.requestFailure', - defaultMessage: 'Test Failure: {error}' - } - } - - constructor(props) { - super(props); - - this.handleRequest = this.handleRequest.bind(this); - - this.state = { - busy: false, - fail: null, - success: false - }; - } - - handleRequest(e) { - e.preventDefault(); - - this.setState({ - busy: true, - fail: null, - success: false - }); - - const doRequest = () => { //eslint-disable-line func-style - this.props.requestAction( - () => { - this.setState({ - busy: false, - success: true - }); - }, - (err) => { - let errMsg = err.message; - if (this.props.includeDetailedError) { - errMsg += ' - ' + err.detailed_error; - } - - this.setState({ - busy: false, - fail: errMsg - }); - } - ); - }; - - if (this.props.saveNeeded) { - this.props.saveConfigAction(doRequest); - } else { - doRequest(); - } - } - - render() { - let message = null; - if (this.state.fail) { - message = ( -
    -
    - - -
    -
    - ); - } else if (this.state.success && this.props.showSuccessMessage) { - message = ( -
    -
    - - -
    -
    - ); - } - - let contents = null; - if (this.state.busy) { - contents = ( - - - {Utils.localizeMessage('admin.requestButton.loading', ' Loading...')} - - ); - } else { - contents = this.props.buttonText; - } - - let widgetClassNames = 'col-sm-8'; - let label = null; - if (this.props.label) { - label = ( - - ); - } else { - widgetClassNames = 'col-sm-offset-4 ' + widgetClassNames; - } - - return ( -
    - {label} -
    -
    - - {this.props.alternativeActionElement} - {message} -
    -
    - {this.props.helpText} -
    -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/reset_password_modal.jsx b/webapp/components/admin_console/reset_password_modal.jsx deleted file mode 100644 index 0a38adda18e..00000000000 --- a/webapp/components/admin_console/reset_password_modal.jsx +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import * as Utils from 'utils/utils.jsx'; -import {Modal} from 'react-bootstrap'; - -import {FormattedMessage} from 'react-intl'; - -import {adminResetPassword} from 'actions/admin_actions.jsx'; - -import PropTypes from 'prop-types'; - -import React from 'react'; - -export default class ResetPasswordModal extends React.Component { - static propTypes = { - user: PropTypes.object, - show: PropTypes.bool.isRequired, - onModalSubmit: PropTypes.func, - onModalDismissed: PropTypes.func - }; - - static defaultProps = { - show: false - }; - - constructor(props) { - super(props); - - this.doSubmit = this.doSubmit.bind(this); - this.doCancel = this.doCancel.bind(this); - - this.state = { - serverError: null - }; - } - - doSubmit(e) { - e.preventDefault(); - const password = this.refs.password.value; - - const passwordErr = Utils.isValidPassword(password); - if (passwordErr) { - this.setState({serverError: passwordErr}); - return; - } - this.setState({serverError: null}); - - adminResetPassword( - this.props.user.id, - password, - () => { - this.props.onModalSubmit(this.props.user); - }, - (err) => { - this.setState({serverError: err.message}); - } - ); - } - - doCancel() { - this.setState({serverError: null}); - this.props.onModalDismissed(); - } - - render() { - const user = this.props.user; - if (user == null) { - return
    ; - } - - let urlClass = 'input-group input-group--limit'; - let serverError = null; - - if (this.state.serverError) { - urlClass += ' has-error'; - serverError =

    {this.state.serverError}

    ; - } - - let title; - if (user.auth_service) { - title = ( - - ); - } else { - title = ( - - ); - } - - return ( - - - - {title} - - -
    - -
    -
    -
    - - - - -
    - {serverError} -
    -
    -
    - - - - -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/revoke_token_button/index.js b/webapp/components/admin_console/revoke_token_button/index.js deleted file mode 100644 index 6fada1bcc65..00000000000 --- a/webapp/components/admin_console/revoke_token_button/index.js +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {revokeUserAccessToken} from 'mattermost-redux/actions/users'; - -import RevokeTokenButton from './revoke_token_button.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - revokeUserAccessToken - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(RevokeTokenButton); diff --git a/webapp/components/admin_console/revoke_token_button/revoke_token_button.jsx b/webapp/components/admin_console/revoke_token_button/revoke_token_button.jsx deleted file mode 100644 index 4829a0cde99..00000000000 --- a/webapp/components/admin_console/revoke_token_button/revoke_token_button.jsx +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import PropTypes from 'prop-types'; -import {FormattedMessage} from 'react-intl'; - -import {trackEvent} from 'actions/diagnostics_actions.jsx'; - -export default class RevokeTokenButton extends React.PureComponent { - static propTypes = { - - /* - * Token id to revoke - */ - tokenId: PropTypes.string.isRequired, - - /* - * Function to call on error - */ - onError: PropTypes.func.isRequired, - - actions: PropTypes.shape({ - - /** - * Function to revoke a user access token - */ - revokeUserAccessToken: PropTypes.func.isRequired - }).isRequired - }; - - handleClick = async (e) => { - e.preventDefault(); - - const {error} = await this.props.actions.revokeUserAccessToken(this.props.tokenId); - trackEvent('system_console', 'revoke_user_access_token'); - - if (error) { - this.props.onError(error.message); - } - } - - render() { - return ( - - ); - } -} diff --git a/webapp/components/admin_console/saml_settings.jsx b/webapp/components/admin_console/saml_settings.jsx deleted file mode 100644 index 98c02e5712c..00000000000 --- a/webapp/components/admin_console/saml_settings.jsx +++ /dev/null @@ -1,584 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import TextSetting from './text_setting.jsx'; -import FileUploadSetting from './file_upload_setting.jsx'; -import RemoveFileSetting from './remove_file_setting.jsx'; - -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -import * as AdminActions from 'actions/admin_actions.jsx'; - -export default class SamlSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - this.uploadCertificate = this.uploadCertificate.bind(this); - this.removeCertificate = this.removeCertificate.bind(this); - } - - getConfigFromState(config) { - config.SamlSettings.Enable = this.state.enable; - config.SamlSettings.Verify = this.state.verify; - config.SamlSettings.Encrypt = this.state.encrypt; - config.SamlSettings.IdpUrl = this.state.idpUrl; - config.SamlSettings.IdpDescriptorUrl = this.state.idpDescriptorUrl; - config.SamlSettings.AssertionConsumerServiceURL = this.state.assertionConsumerServiceURL; - config.SamlSettings.IdpCertificateFile = this.state.idpCertificateFile; - config.SamlSettings.PublicCertificateFile = this.state.publicCertificateFile; - config.SamlSettings.PrivateKeyFile = this.state.privateKeyFile; - config.SamlSettings.FirstNameAttribute = this.state.firstNameAttribute; - config.SamlSettings.LastNameAttribute = this.state.lastNameAttribute; - config.SamlSettings.EmailAttribute = this.state.emailAttribute; - config.SamlSettings.UsernameAttribute = this.state.usernameAttribute; - config.SamlSettings.NicknameAttribute = this.state.nicknameAttribute; - config.SamlSettings.PositionAttribute = this.state.positionAttribute; - config.SamlSettings.LocaleAttribute = this.state.localeAttribute; - config.SamlSettings.LoginButtonText = this.state.loginButtonText; - - return config; - } - - getStateFromConfig(config) { - const settings = config.SamlSettings; - - return { - enable: settings.Enable, - verify: settings.Verify, - encrypt: settings.Encrypt, - idpUrl: settings.IdpUrl, - idpDescriptorUrl: settings.IdpDescriptorUrl, - assertionConsumerServiceURL: settings.AssertionConsumerServiceURL, - idpCertificateFile: settings.IdpCertificateFile, - publicCertificateFile: settings.PublicCertificateFile, - privateKeyFile: settings.PrivateKeyFile, - firstNameAttribute: settings.FirstNameAttribute, - lastNameAttribute: settings.LastNameAttribute, - emailAttribute: settings.EmailAttribute, - usernameAttribute: settings.UsernameAttribute, - nicknameAttribute: settings.NicknameAttribute, - positionAttribute: settings.PositionAttribute, - localeAttribute: settings.LocaleAttribute, - loginButtonText: settings.LoginButtonText - }; - } - - componentWillMount() { - AdminActions.samlCertificateStatus( - (data) => { - const files = {}; - if (!data.idp_certificate_file) { - files.idpCertificateFile = ''; - } - - if (!data.public_certificate_file) { - files.publicCertificateFile = ''; - } - - if (!data.private_key_file) { - files.privateKeyFile = ''; - } - this.setState(files); - } - ); - } - - uploadCertificate(id, file, callback) { - const complete = () => { - const fileName = file.name; - this.handleChange(id, fileName); - this.setState({[id]: fileName, [`${id}Error`]: null}); - if (callback && typeof callback === 'function') { - callback(); - } - }; - - function fail(error) { - if (callback && typeof callback === 'function') { - callback(error.message); - } - } - - if (id === 'idpCertificateFile') { - AdminActions.uploadIdpSamlCertificate(file, complete, fail); - } else if (id === 'publicCertificateFile') { - AdminActions.uploadPublicSamlCertificate(file, complete, fail); - } else if (id === 'privateKeyFile') { - AdminActions.uploadPrivateSamlCertificate(file, complete, fail); - } - } - - removeCertificate(id, callback) { - const complete = () => { - this.handleChange(id, ''); - this.setState({[id]: null, [`${id}Error`]: null}); - }; - - const fail = (error) => { - if (callback && typeof callback === 'function') { - callback(); - } - this.setState({[id]: null, [`${id}Error`]: error.message}); - }; - - if (id === 'idpCertificateFile') { - AdminActions.removeIdpSamlCertificate(complete, fail); - } else if (id === 'publicCertificateFile') { - AdminActions.removePublicSamlCertificate(complete, fail); - } else if (id === 'privateKeyFile') { - AdminActions.removePrivateSamlCertificate(complete, fail); - } - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - const licenseEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.SAML === 'true'; - if (!licenseEnabled) { - return null; - } - - let idpCert; - let privKey; - let pubCert; - - if (this.state.idpCertificateFile) { - idpCert = ( - - } - helpText={ - - } - removeButtonText={Utils.localizeMessage('admin.saml.remove.idp_certificate', 'Remove Identity Provider Certificate')} - removingText={Utils.localizeMessage('admin.saml.removing.certificate', 'Removing Certificate...')} - fileName={this.state.idpCertificateFile} - onSubmit={this.removeCertificate} - disabled={!this.state.enable} - /> - ); - } else { - idpCert = ( - - } - helpText={ - - } - uploadingText={Utils.localizeMessage('admin.saml.uploading.certificate', 'Uploading Certificate...')} - disabled={!this.state.enable} - fileType='.crt,.cer' - onSubmit={this.uploadCertificate} - error={this.state.idpCertificateFileError} - /> - ); - } - - if (this.state.privateKeyFile) { - privKey = ( - - } - helpText={ - - } - removeButtonText={Utils.localizeMessage('admin.saml.remove.privKey', 'Remove Service Provider Private Key')} - removingText={Utils.localizeMessage('admin.saml.removing.privKey', 'Removing Private Key...')} - fileName={this.state.privateKeyFile} - onSubmit={this.removeCertificate} - disabled={!this.state.enable || !this.state.encrypt} - /> - ); - } else { - privKey = ( - - } - helpText={ - - } - uploadingText={Utils.localizeMessage('admin.saml.uploading.privateKey', 'Uploading Private Key...')} - disabled={!this.state.enable || !this.state.encrypt} - fileType='.key' - onSubmit={this.uploadCertificate} - error={this.state.privateKeyFileError} - /> - ); - } - - if (this.state.publicCertificateFile) { - pubCert = ( - - } - helpText={ - - } - removeButtonText={Utils.localizeMessage('admin.saml.remove.sp_certificate', 'Remove Service Provider Certificate')} - removingText={Utils.localizeMessage('admin.saml.removing.certificate', 'Removing Certificate...')} - fileName={this.state.publicCertificateFile} - onSubmit={this.removeCertificate} - disabled={!this.state.enable || !this.state.encrypt} - /> - ); - } else { - pubCert = ( - - } - helpText={ - - } - uploadingText={Utils.localizeMessage('admin.saml.uploading.certificate', 'Uploading Certificate...')} - disabled={!this.state.enable || !this.state.encrypt} - fileType='.crt,.cer' - onSubmit={this.uploadCertificate} - error={this.state.publicCertificateFileError} - /> - ); - } - - return ( - -
    -
    - -
    -
    - - } - helpText={ - - } - value={this.state.enable} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.idpUrlEx', 'Ex "https://idp.example.org/SAML2/SSO/Login"')} - helpText={ - - } - value={this.state.idpUrl} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.idpDescriptorUrlEx', 'Ex "https://idp.example.org/SAML2/issuer"')} - helpText={ - - } - value={this.state.idpDescriptorUrl} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - {idpCert} - - } - helpText={ - - } - value={this.state.verify} - disabled={!this.state.enable} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.assertionConsumerServiceURLEx', 'Ex "https:///login/sso/saml"')} - helpText={ - - } - value={this.state.assertionConsumerServiceURL} - onChange={this.handleChange} - disabled={!this.state.enable || !this.state.verify} - /> - - } - helpText={ - - } - value={this.state.encrypt} - disabled={!this.state.enable} - onChange={this.handleChange} - /> - {privKey} - {pubCert} - - } - placeholder={Utils.localizeMessage('admin.saml.emailAttrEx', 'Ex "Email" or "PrimaryEmail"')} - helpText={ - - } - value={this.state.emailAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.usernameAttrEx', 'Ex "Username"')} - helpText={ - - } - value={this.state.usernameAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.firstnameAttrEx', 'Ex "FirstName"')} - helpText={ - - } - value={this.state.firstNameAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.lastnameAttrEx', 'Ex "LastName"')} - helpText={ - - } - value={this.state.lastNameAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.nicknameAttrEx', 'Ex "Nickname"')} - helpText={ - - } - value={this.state.nicknameAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.positionAttrEx', 'E.g.: "Role"')} - helpText={ - - } - value={this.state.positionAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.localeAttrEx', 'Ex "Locale" or "PrimaryLanguage"')} - helpText={ - - } - value={this.state.localeAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.loginButtonTextEx', 'Ex "With OKTA"')} - helpText={ - - } - value={this.state.loginButtonText} - onChange={this.handleChange} - disabled={!this.state.enable} - /> -
    - ); - } -} diff --git a/webapp/components/admin_console/save_button.jsx b/webapp/components/admin_console/save_button.jsx deleted file mode 100644 index 4d2b562da03..00000000000 --- a/webapp/components/admin_console/save_button.jsx +++ /dev/null @@ -1,64 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import {FormattedMessage} from 'react-intl'; - -export default class SaveButton extends React.Component { - static get propTypes() { - return { - saving: PropTypes.bool.isRequired, - disabled: PropTypes.bool - }; - } - - static get defaultProps() { - return { - disabled: false - }; - } - - render() { - const {saving, disabled, ...props} = this.props; // eslint-disable-line no-use-before-define - - let contents; - if (saving) { - contents = ( - - - - - ); - } else { - contents = ( - - ); - } - - let className = 'save-button btn'; - if (!disabled) { - className += ' btn-primary'; - } - - return ( - - ); - } -} diff --git a/webapp/components/admin_console/server_logs/index.js b/webapp/components/admin_console/server_logs/index.js deleted file mode 100644 index 3adacaf1aab..00000000000 --- a/webapp/components/admin_console/server_logs/index.js +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {getLogs} from 'mattermost-redux/actions/admin'; - -import * as Selectors from 'mattermost-redux/selectors/entities/admin'; - -import Logs from './logs.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps, - logs: Selectors.getLogs(state) - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getLogs - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(Logs); diff --git a/webapp/components/admin_console/server_logs/logs.jsx b/webapp/components/admin_console/server_logs/logs.jsx deleted file mode 100644 index b0d8b38ac49..00000000000 --- a/webapp/components/admin_console/server_logs/logs.jsx +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import LoadingScreen from 'components/loading_screen.jsx'; - -import React from 'react'; -import PropTypes from 'prop-types'; -import {FormattedMessage} from 'react-intl'; - -export default class Logs extends React.PureComponent { - static propTypes = { - - /* - * Array of logs to render - */ - logs: PropTypes.arrayOf(PropTypes.string).isRequired, - - actions: PropTypes.shape({ - - /* - * Function to fetch logs - */ - getLogs: PropTypes.func.isRequired - }).isRequired - } - - constructor(props) { - super(props); - - this.state = { - loadingLogs: true - }; - } - - componentDidMount() { - this.refs.logPanel.focus(); - - this.props.actions.getLogs().then( - () => this.setState({loadingLogs: false}) - ); - } - - componentDidUpdate() { - // Scroll Down to get the latest logs - var node = this.refs.logPanel; - node.scrollTop = node.scrollHeight; - node.focus(); - } - - reload = () => { - this.setState({loadingLogs: true}); - this.props.actions.getLogs().then( - () => this.setState({loadingLogs: false}) - ); - } - - render() { - let content = null; - - if (this.state.loadingLogs) { - content = ; - } else { - content = []; - - for (let i = 0; i < this.props.logs.length; i++) { - const style = { - whiteSpace: 'nowrap', - fontFamily: 'monospace' - }; - - if (this.props.logs[i].indexOf('[EROR]') > 0) { - style.color = 'red'; - } - - content.push(
    ); - content.push( - - {this.props.logs[i]} - - ); - } - } - - return ( -
    -

    - -

    -
    -
    - -
    -
    - -
    - {content} -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/session_settings.jsx b/webapp/components/admin_console/session_settings.jsx deleted file mode 100644 index a36126789f4..00000000000 --- a/webapp/components/admin_console/session_settings.jsx +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class SessionSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ServiceSettings.SessionLengthWebInDays = this.parseIntNonZero(this.state.sessionLengthWebInDays); - config.ServiceSettings.SessionLengthMobileInDays = this.parseIntNonZero(this.state.sessionLengthMobileInDays); - config.ServiceSettings.SessionLengthSSOInDays = this.parseIntNonZero(this.state.sessionLengthSSOInDays); - config.ServiceSettings.SessionCacheInMinutes = this.parseIntNonZero(this.state.sessionCacheInMinutes); - - return config; - } - - getStateFromConfig(config) { - return { - sessionLengthWebInDays: config.ServiceSettings.SessionLengthWebInDays, - sessionLengthMobileInDays: config.ServiceSettings.SessionLengthMobileInDays, - sessionLengthSSOInDays: config.ServiceSettings.SessionLengthSSOInDays, - sessionCacheInMinutes: config.ServiceSettings.SessionCacheInMinutes - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - placeholder={Utils.localizeMessage('admin.service.sessionDaysEx', 'Ex "30"')} - helpText={ - - } - value={this.state.sessionLengthWebInDays} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.service.sessionDaysEx', 'Ex "30"')} - helpText={ - - } - value={this.state.sessionLengthMobileInDays} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.service.sessionDaysEx', 'Ex "30"')} - helpText={ - - } - value={this.state.sessionLengthSSOInDays} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.service.sessionDaysEx', 'Ex "30"')} - helpText={ - - } - value={this.state.sessionCacheInMinutes} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/setting.jsx b/webapp/components/admin_console/setting.jsx deleted file mode 100644 index 9ef6554ac56..00000000000 --- a/webapp/components/admin_console/setting.jsx +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React, {PureComponent} from 'react'; -import PropTypes from 'prop-types'; - -export default class Settings extends PureComponent { - static propTypes = { - inputId: PropTypes.string, - label: PropTypes.node.isRequired, - children: PropTypes.node.isRequired, - helpText: PropTypes.node - }; - - render() { - const {children, helpText, inputId, label} = this.props; - - return ( -
    - -
    - {children} -
    - {helpText} -
    -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/settings_group.jsx b/webapp/components/admin_console/settings_group.jsx deleted file mode 100644 index 79f8dac970b..00000000000 --- a/webapp/components/admin_console/settings_group.jsx +++ /dev/null @@ -1,44 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -export default class SettingsGroup extends React.Component { - static get propTypes() { - return { - show: PropTypes.bool.isRequired, - header: PropTypes.node, - children: PropTypes.node - }; - } - - static get defaultProps() { - return { - show: true - }; - } - - render() { - if (!this.props.show) { - return null; - } - - let header = null; - if (this.props.header) { - header = ( -

    - {this.props.header} -

    - ); - } - - return ( -
    - {header} - {this.props.children} -
    - ); - } -} diff --git a/webapp/components/admin_console/signup_settings.jsx b/webapp/components/admin_console/signup_settings.jsx deleted file mode 100644 index b3ae6fe60d4..00000000000 --- a/webapp/components/admin_console/signup_settings.jsx +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import GeneratedSetting from './generated_setting.jsx'; -import SettingsGroup from './settings_group.jsx'; - -export default class SignupSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.EmailSettings.RequireEmailVerification = this.state.requireEmailVerification; - config.EmailSettings.InviteSalt = this.state.inviteSalt; - config.TeamSettings.EnableOpenServer = this.state.enableOpenServer; - - return config; - } - - getStateFromConfig(config) { - return { - requireEmailVerification: config.EmailSettings.RequireEmailVerification, - inviteSalt: config.EmailSettings.InviteSalt, - enableOpenServer: config.TeamSettings.EnableOpenServer - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ - - } - value={this.state.requireEmailVerification} - onChange={this.handleChange} - disabled={this.state.sendEmailNotifications} - disabledText={ - - } - /> - - } - helpText={ - - } - value={this.state.inviteSalt} - onChange={this.handleChange} - disabled={this.state.sendEmailNotifications} - disabledText={ - - } - /> - - } - helpText={ - - } - value={this.state.enableOpenServer} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/storage_settings.jsx b/webapp/components/admin_console/storage_settings.jsx deleted file mode 100644 index 4b20a8b9349..00000000000 --- a/webapp/components/admin_console/storage_settings.jsx +++ /dev/null @@ -1,340 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import DropdownSetting from './dropdown_setting.jsx'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; -import BooleanSetting from './boolean_setting.jsx'; - -const DRIVER_LOCAL = 'local'; -const DRIVER_S3 = 'amazons3'; - -export default class StorageSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.FileSettings.EnableFileAttachments = this.state.enableFileAttachments; - config.FileSettings.EnableMobileUpload = this.state.enableMobileUpload; - config.FileSettings.EnableMobileDownload = this.state.enableMobileDownload; - config.FileSettings.MaxFileSize = this.parseInt(this.state.maxFileSize) * 1024 * 1024; - config.FileSettings.DriverName = this.state.driverName; - config.FileSettings.Directory = this.state.directory; - config.FileSettings.AmazonS3AccessKeyId = this.state.amazonS3AccessKeyId; - config.FileSettings.AmazonS3SecretAccessKey = this.state.amazonS3SecretAccessKey; - config.FileSettings.AmazonS3Bucket = this.state.amazonS3Bucket; - config.FileSettings.AmazonS3Endpoint = this.state.amazonS3Endpoint; - config.FileSettings.AmazonS3SSL = this.state.amazonS3SSL; - config.FileSettings.AmazonS3SSE = this.state.amazonS3SSE; - config.FileSettings.AmazonS3Trace = this.state.amazonS3Trace; - - return config; - } - - getStateFromConfig(config) { - return { - enableFileAttachments: config.FileSettings.EnableFileAttachments, - enableMobileUpload: config.FileSettings.EnableMobileUpload, - enableMobileDownload: config.FileSettings.EnableMobileDownload, - maxFileSize: config.FileSettings.MaxFileSize / 1024 / 1024, - driverName: config.FileSettings.DriverName, - directory: config.FileSettings.Directory, - amazonS3AccessKeyId: config.FileSettings.AmazonS3AccessKeyId, - amazonS3SecretAccessKey: config.FileSettings.AmazonS3SecretAccessKey, - amazonS3Bucket: config.FileSettings.AmazonS3Bucket, - amazonS3Endpoint: config.FileSettings.AmazonS3Endpoint, - amazonS3SSL: config.FileSettings.AmazonS3SSL, - amazonS3SSE: config.FileSettings.AmazonS3SSE, - amazonS3Trace: config.FileSettings.AmazonS3Trace - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - let amazonSSEComp; - const mobileUploadDownloadSettings = []; - if (window.mm_license.IsLicensed === 'true' && window.mm_license.Compliance === 'true') { - mobileUploadDownloadSettings.push( - - } - helpText={ - - } - value={this.state.enableMobileUpload} - onChange={this.handleChange} - disabled={!this.state.enableFileAttachments} - /> - ); - - mobileUploadDownloadSettings.push( - - } - helpText={ - - } - value={this.state.enableMobileDownload} - onChange={this.handleChange} - disabled={!this.state.enableFileAttachments} - /> - ); - - amazonSSEComp = - ( - - } - helpText={ - - } - value={this.state.amazonS3SSE} - onChange={this.handleChange} - disabled={this.state.driverName !== DRIVER_S3} - /> - ); - } - - return ( - - - } - helpText={ - - } - value={this.state.driverName} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.image.localExample', 'Ex "./data/"')} - helpText={ - - } - value={this.state.directory} - onChange={this.handleChange} - disabled={this.state.driverName !== DRIVER_LOCAL} - /> - - } - placeholder={Utils.localizeMessage('admin.image.amazonS3IdExample', 'Ex "AKIADTOVBGERKLCBV"')} - helpText={ - - } - value={this.state.amazonS3AccessKeyId} - onChange={this.handleChange} - disabled={this.state.driverName !== DRIVER_S3} - /> - - } - placeholder={Utils.localizeMessage('admin.image.amazonS3SecretExample', 'Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"')} - helpText={ - - } - value={this.state.amazonS3SecretAccessKey} - onChange={this.handleChange} - disabled={this.state.driverName !== DRIVER_S3} - /> - - } - placeholder={Utils.localizeMessage('admin.image.amazonS3BucketExample', 'Ex "mattermost-media"')} - helpText={ - - } - value={this.state.amazonS3Bucket} - onChange={this.handleChange} - disabled={this.state.driverName !== DRIVER_S3} - /> - - } - placeholder={Utils.localizeMessage('admin.image.amazonS3EndpointExample', 'Ex "s3.amazonaws.com"')} - helpText={ - - } - value={this.state.amazonS3Endpoint} - onChange={this.handleChange} - disabled={this.state.driverName !== DRIVER_S3} - /> - - } - helpText={ - - } - value={this.state.amazonS3SSL} - onChange={this.handleChange} - disabled={this.state.driverName !== DRIVER_S3} - /> - {amazonSSEComp} - - } - helpText={ - - } - value={this.state.amazonS3Trace} - onChange={this.handleChange} - disabled={this.state.driverName !== DRIVER_S3} - /> - - } - helpText={ - - } - value={this.state.enableFileAttachments} - onChange={this.handleChange} - /> - {mobileUploadDownloadSettings} - - } - placeholder={Utils.localizeMessage('admin.image.maxFileSizeExample', '50')} - helpText={ - - } - value={this.state.maxFileSize} - onChange={this.handleChange} - disabled={!this.state.enableFileAttachments} - /> - - ); - } -} diff --git a/webapp/components/admin_console/system_users/index.js b/webapp/components/admin_console/system_users/index.js deleted file mode 100644 index 261a11d7efa..00000000000 --- a/webapp/components/admin_console/system_users/index.js +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {getTeams, getTeamStats} from 'mattermost-redux/actions/teams'; -import {getUser, getUserAccessToken} from 'mattermost-redux/actions/users'; - -import {getTeamsList} from 'mattermost-redux/selectors/entities/teams'; - -import SystemUsers from './system_users.jsx'; - -function mapStateToProps(state, ownProps) { - return { - teams: getTeamsList(state), - ...ownProps - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getTeams, - getTeamStats, - getUser, - getUserAccessToken - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(SystemUsers); diff --git a/webapp/components/admin_console/system_users/system_users.jsx b/webapp/components/admin_console/system_users/system_users.jsx deleted file mode 100644 index db8400217a9..00000000000 --- a/webapp/components/admin_console/system_users/system_users.jsx +++ /dev/null @@ -1,372 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import PropTypes from 'prop-types'; -import {FormattedMessage} from 'react-intl'; - -import { - loadProfiles, - loadProfilesAndTeamMembers, - loadProfilesWithoutTeam, - searchUsers -} from 'actions/user_actions.jsx'; - -import AnalyticsStore from 'stores/analytics_store.jsx'; -import TeamStore from 'stores/team_store.jsx'; -import UserStore from 'stores/user_store.jsx'; - -import {reloadIfServerVersionChanged} from 'actions/global_actions.jsx'; -import {getStandardAnalytics} from 'actions/admin_actions.jsx'; -import {Constants, StatTypes, UserSearchOptions} from 'utils/constants.jsx'; -import * as Utils from 'utils/utils.jsx'; - -import SystemUsersList from './system_users_list.jsx'; - -import store from 'stores/redux_store.jsx'; -import {searchProfiles, searchProfilesInTeam} from 'mattermost-redux/selectors/entities/users'; - -const ALL_USERS = ''; -const NO_TEAM = 'no_team'; - -const USER_ID_LENGTH = 26; -const USERS_PER_PAGE = 50; - -export default class SystemUsers extends React.Component { - static propTypes = { - - /* - * Array of team objects - */ - teams: PropTypes.arrayOf(PropTypes.object).isRequired, - - actions: PropTypes.shape({ - - /* - * Function to get teams - */ - getTeams: PropTypes.func.isRequired, - - /* - * Function to get statistics for a team - */ - getTeamStats: PropTypes.func.isRequired, - - /* - * Function to get a user - */ - getUser: PropTypes.func.isRequired, - - /* - * Function to get a user access token - */ - getUserAccessToken: PropTypes.func.isRequired - }).isRequired - } - - constructor(props) { - super(props); - - this.updateTotalUsersFromStore = this.updateTotalUsersFromStore.bind(this); - this.updateUsersFromStore = this.updateUsersFromStore.bind(this); - - this.loadDataForTeam = this.loadDataForTeam.bind(this); - this.loadComplete = this.loadComplete.bind(this); - - this.handleTeamChange = this.handleTeamChange.bind(this); - this.handleTermChange = this.handleTermChange.bind(this); - this.nextPage = this.nextPage.bind(this); - - this.doSearch = this.doSearch.bind(this); - this.search = this.search.bind(this); - this.getUserById = this.getUserById.bind(this); - - this.renderFilterRow = this.renderFilterRow.bind(this); - - this.state = { - totalUsers: AnalyticsStore.getAllSystem()[StatTypes.TOTAL_USERS], - users: UserStore.getProfileList(), - - teamId: ALL_USERS, - term: '', - loading: true, - searching: false - }; - } - - componentDidMount() { - AnalyticsStore.addChangeListener(this.updateTotalUsersFromStore); - TeamStore.addStatsChangeListener(this.updateTotalUsersFromStore); - - UserStore.addChangeListener(this.updateUsersFromStore); - UserStore.addInTeamChangeListener(this.updateUsersFromStore); - UserStore.addWithoutTeamChangeListener(this.updateUsersFromStore); - - this.loadDataForTeam(this.state.teamId); - this.props.actions.getTeams(0, 1000).then(reloadIfServerVersionChanged); - } - - componentWillUpdate(nextProps, nextState) { - const nextTeamId = nextState.teamId; - - if (this.state.teamId !== nextTeamId) { - this.updateTotalUsersFromStore(nextTeamId); - this.updateUsersFromStore(nextTeamId, nextState.term); - - this.loadDataForTeam(nextTeamId); - } - } - - componentWillUnmount() { - AnalyticsStore.removeChangeListener(this.updateTotalUsersFromStore); - TeamStore.removeStatsChangeListener(this.updateTotalUsersFromStore); - - UserStore.removeChangeListener(this.updateUsersFromStore); - UserStore.removeInTeamChangeListener(this.updateUsersFromStore); - UserStore.removeWithoutTeamChangeListener(this.updateUsersFromStore); - } - - updateTotalUsersFromStore(teamId = this.state.teamId) { - if (teamId === ALL_USERS) { - this.setState({ - totalUsers: AnalyticsStore.getAllSystem()[StatTypes.TOTAL_USERS] - }); - } else if (teamId === NO_TEAM) { - this.setState({ - totalUsers: 0 - }); - } else { - this.setState({ - totalUsers: TeamStore.getStats(teamId).total_member_count - }); - } - } - - updateUsersFromStore(teamId = this.state.teamId, term = this.state.term) { - if (term) { - let users; - if (teamId) { - users = searchProfilesInTeam(store.getState(), teamId, term); - } else { - users = searchProfiles(store.getState(), term); - } - - if (users.length === 0 && UserStore.hasProfile(term)) { - users = [UserStore.getProfile(term)]; - } - - this.setState({users}); - return; - } - - if (teamId === ALL_USERS) { - this.setState({users: UserStore.getProfileList(false, true)}); - } else if (teamId === NO_TEAM) { - this.setState({users: UserStore.getProfileListWithoutTeam()}); - } else { - this.setState({users: UserStore.getProfileListInTeam(this.state.teamId)}); - } - } - - loadDataForTeam(teamId) { - if (this.state.term) { - this.search(this.state.term, teamId); - return; - } - - if (teamId === ALL_USERS) { - loadProfiles(0, Constants.PROFILE_CHUNK_SIZE, this.loadComplete); - getStandardAnalytics(); - } else if (teamId === NO_TEAM) { - loadProfilesWithoutTeam(0, Constants.PROFILE_CHUNK_SIZE, this.loadComplete); - } else { - loadProfilesAndTeamMembers(0, Constants.PROFILE_CHUNK_SIZE, teamId, this.loadComplete); - this.props.actions.getTeamStats(teamId); - } - } - - loadComplete() { - this.setState({loading: false}); - } - - handleTeamChange(e) { - this.setState({teamId: e.target.value}); - } - - handleTermChange(term) { - this.setState({term}); - } - - nextPage(page) { - // Paging isn't supported while searching - - if (this.state.teamId === ALL_USERS) { - loadProfiles(page, USERS_PER_PAGE, this.loadComplete); - } else if (this.state.teamId === NO_TEAM) { - loadProfilesWithoutTeam(page + 1, USERS_PER_PAGE, this.loadComplete); - } else { - loadProfilesAndTeamMembers(page + 1, USERS_PER_PAGE, this.state.teamId, this.loadComplete); - } - } - - search(term, teamId = this.state.teamId) { - if (term === '') { - this.updateUsersFromStore(teamId, term); - - this.setState({ - loading: false - }); - - this.searchTimeoutId = ''; - return; - } - - this.doSearch(teamId, term); - } - - doSearch(teamId, term, now = false) { - clearTimeout(this.searchTimeoutId); - this.term = term; - - this.setState({loading: true}); - - const options = { - [UserSearchOptions.ALLOW_INACTIVE]: true - }; - if (teamId === NO_TEAM) { - options[UserSearchOptions.WITHOUT_TEAM] = true; - } - - this.searchTimeoutId = setTimeout( - () => { - searchUsers( - term, - teamId, - options, - (users) => { - if (users.length === 0 && term.length === USER_ID_LENGTH) { - // This term didn't match any users name, but it does look like it might be a user's ID - this.getUserByTokenOrId(term); - } else { - this.setState({loading: false}); - } - }, - () => { - this.setState({loading: false}); - } - ); - }, - now ? 0 : Constants.SEARCH_TIMEOUT_MILLISECONDS - ); - } - - getUserById(id) { - if (UserStore.hasProfile(id)) { - this.setState({loading: false}); - return; - } - - this.props.actions.getUser(id).then( - () => { - this.setState({ - loading: false - }); - } - ); - } - - getUserByTokenOrId = async (id) => { - if (global.window.mm_config.EnableUserAccessTokens === 'true') { - const {data} = await this.props.actions.getUserAccessToken(id); - - if (data) { - this.term = data.user_id; - this.setState({term: data.user_id}); - this.updateUsersFromStore(this.state.teamId, data.user_id); - this.getUserById(data.user_id); - return; - } - } - - this.getUserById(id); - } - - renderFilterRow(doSearch) { - const teams = this.props.teams.map((team) => { - return ( - - ); - }); - - return ( -
    -
    - -
    - -
    - ); - } - - render() { - let users = null; - if (!this.state.loading) { - users = this.state.users; - } - - return ( -
    -

    - -

    -
    - -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/system_users/system_users_dropdown.jsx b/webapp/components/admin_console/system_users/system_users_dropdown.jsx deleted file mode 100644 index 79ccc8b3184..00000000000 --- a/webapp/components/admin_console/system_users/system_users_dropdown.jsx +++ /dev/null @@ -1,529 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import ConfirmModal from 'components/confirm_modal.jsx'; - -import TeamStore from 'stores/team_store.jsx'; -import UserStore from 'stores/user_store.jsx'; - -import Constants from 'utils/constants.jsx'; -import * as Utils from 'utils/utils.jsx'; -import {updateActive} from 'actions/user_actions.jsx'; -import {adminResetMfa} from 'actions/admin_actions.jsx'; -import * as UserUtils from 'mattermost-redux/utils/user_utils'; - -import {FormattedMessage} from 'react-intl'; - -import PropTypes from 'prop-types'; - -import React from 'react'; - -export default class SystemUsersDropdown extends React.Component { - static propTypes = { - - /* - * User to manage with dropdown - */ - user: PropTypes.object.isRequired, - - /* - * Function to open password reset, takes user as an argument - */ - doPasswordReset: PropTypes.func.isRequired, - - /* - * Function to open manage teams, takes user as an argument - */ - doManageTeams: PropTypes.func.isRequired, - - /* - * Function to open manage roles, takes user as an argument - */ - doManageRoles: PropTypes.func.isRequired, - - /* - * Function to open manage tokens, takes user as an argument - */ - doManageTokens: PropTypes.func.isRequired - }; - - constructor(props) { - super(props); - - this.state = { - serverError: null, - showDemoteModal: false, - showDeactivateMemberModal: false, - user: null, - role: null - }; - } - - handleMakeActive = (e) => { - e.preventDefault(); - updateActive(this.props.user.id, true, null, - (err) => { - this.setState({serverError: err.message}); - } - ); - } - - handleManageTeams = (e) => { - e.preventDefault(); - - this.props.doManageTeams(this.props.user); - } - - handleManageRoles = (e) => { - e.preventDefault(); - - this.props.doManageRoles(this.props.user); - } - - handleManageTokens = (e) => { - e.preventDefault(); - - this.props.doManageTokens(this.props.user); - } - - handleResetPassword = (e) => { - e.preventDefault(); - this.props.doPasswordReset(this.props.user); - } - - handleResetMfa = (e) => { - e.preventDefault(); - - adminResetMfa(this.props.user.id, - null, - (err) => { - this.setState({serverError: err.message}); - } - ); - } - - handleDemoteSystemAdmin = (user, role) => { - this.setState({ - serverError: this.state.serverError, - showDemoteModal: true, - user, - role - }); - } - - handleDemoteCancel = () => { - this.setState({ - serverError: null, - showDemoteModal: false, - user: null, - role: null - }); - } - - handleDemoteSubmit = () => { - if (this.state.role === 'member') { - this.doMakeMember(); - } - - const teamUrl = TeamStore.getCurrentTeamUrl(); - if (teamUrl) { - // the channel is added to the URL cause endless loading not being fully fixed - window.location.href = teamUrl + '/channels/town-square'; - } else { - window.location.href = '/'; - } - } - - handleShowDeactivateMemberModal = (e) => { - e.preventDefault(); - - this.setState({showDeactivateMemberModal: true}); - } - - handleDeactivateMember = () => { - updateActive(this.props.user.id, false, null, - (err) => { - this.setState({serverError: err.message}); - } - ); - - this.setState({showDeactivateMemberModal: false}); - } - - handleDeactivateCancel = () => { - this.setState({showDeactivateMemberModal: false}); - } - - renderDeactivateMemberModal = () => { - const title = ( - - ); - - const message = ( - - ); - - const confirmButtonClass = 'btn btn-danger'; - const deactivateMemberButton = ( - - ); - - return ( - - ); - } - - renderAccessToken = () => { - const userAccessTokensEnabled = global.window.mm_config.EnableUserAccessTokens === 'true'; - if (!userAccessTokensEnabled) { - return null; - } - - const user = this.props.user; - const hasPostAllRole = UserUtils.hasPostAllRole(user.roles); - const hasPostAllPublicRole = UserUtils.hasPostAllPublicRole(user.roles); - const hasUserAccessTokenRole = UserUtils.hasUserAccessTokenRole(user.roles); - const isSystemAdmin = UserUtils.isSystemAdmin(user.roles); - - let messageId = ''; - if (hasUserAccessTokenRole || isSystemAdmin) { - if (hasPostAllRole) { - messageId = 'admin.user_item.userAccessTokenPostAll'; - } else if (hasPostAllPublicRole) { - messageId = 'admin.user_item.userAccessTokenPostAllPublic'; - } else { - messageId = 'admin.user_item.userAccessTokenYes'; - } - } - - if (!messageId) { - return null; - } - - return ( -
    - -
    - ); - } - - render() { - let serverError = null; - if (this.state.serverError) { - serverError = ( -
    - -
    - ); - } - - const user = this.props.user; - if (!user) { - return
    ; - } - let currentRoles = ( - - ); - - if (user.roles.length > 0 && Utils.isSystemAdmin(user.roles)) { - currentRoles = ( - - ); - } - - const me = UserStore.getCurrentUser(); - let showMakeActive = false; - let showMakeNotActive = !Utils.isSystemAdmin(user.roles); - let showManageTeams = true; - const mfaEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.MFA === 'true' && global.window.mm_config.EnableMultifactorAuthentication === 'true'; - const showMfaReset = mfaEnabled && user.mfa_active; - - if (user.delete_at > 0) { - currentRoles = ( - - ); - showMakeActive = true; - showMakeNotActive = false; - showManageTeams = false; - } - - let disableActivationToggle = false; - if (user.auth_service === Constants.LDAP_SERVICE) { - disableActivationToggle = true; - } - - let menuClass = ''; - if (disableActivationToggle) { - menuClass = 'disabled'; - } - - let makeActive = null; - if (showMakeActive) { - makeActive = ( -
  • - - - -
  • - ); - } - - let makeNotActive = null; - if (showMakeNotActive) { - makeNotActive = ( -
  • - - - -
  • - ); - } - - let manageTeams = null; - if (showManageTeams) { - manageTeams = ( -
  • - - - -
  • - ); - } - - let mfaReset = null; - if (showMfaReset) { - mfaReset = ( -
  • - - - -
  • - ); - } - - let passwordReset; - if (user.auth_service) { - passwordReset = ( -
  • - - - -
  • - ); - } else { - passwordReset = ( -
  • - - - -
  • - ); - } - - let manageTokens; - if (global.window.mm_config.EnableUserAccessTokens === 'true') { - manageTokens = ( -
  • - - - -
  • - ); - } - - let makeDemoteModal = null; - if (this.props.user.id === me.id) { - const title = ( - - ); - - const message = ( -
    - -
    -
    - - {serverError} -
    - ); - - const confirmButton = ( - - ); - - makeDemoteModal = ( - - ); - } - - const deactivateMemberModal = this.renderDeactivateMemberModal(); - - let displayedName = Utils.getDisplayName(user); - if (displayedName !== user.username) { - displayedName += ' (@' + user.username + ')'; - } - - return ( -
    - - {currentRoles} - - - {this.renderAccessToken()} -
      - {makeActive} - {makeNotActive} -
    • - - - -
    • - {manageTeams} - {manageTokens} - {mfaReset} - {passwordReset} -
    - {makeDemoteModal} - {deactivateMemberModal} - {serverError} -
    - ); - } -} diff --git a/webapp/components/admin_console/system_users/system_users_list.jsx b/webapp/components/admin_console/system_users/system_users_list.jsx deleted file mode 100644 index 8a7f30e1b7e..00000000000 --- a/webapp/components/admin_console/system_users/system_users_list.jsx +++ /dev/null @@ -1,295 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import PropTypes from 'prop-types'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; - -import ManageTeamsModal from 'components/admin_console/manage_teams_modal/manage_teams_modal.jsx'; -import ManageRolesModal from 'components/admin_console/manage_roles_modal'; -import ManageTokensModal from 'components/admin_console/manage_tokens_modal'; -import ResetPasswordModal from 'components/admin_console/reset_password_modal.jsx'; -import SearchableUserList from 'components/searchable_user_list/searchable_user_list.jsx'; - -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import {getUser} from 'mattermost-redux/actions/users'; -import {Constants} from 'utils/constants.jsx'; -import * as Utils from 'utils/utils.jsx'; - -import SystemUsersDropdown from './system_users_dropdown.jsx'; - -export default class SystemUsersList extends React.Component { - static propTypes = { - users: PropTypes.arrayOf(PropTypes.object), - usersPerPage: PropTypes.number, - total: PropTypes.number, - nextPage: PropTypes.func, - search: PropTypes.func.isRequired, - focusOnMount: PropTypes.bool, - renderFilterRow: PropTypes.func, - - teamId: PropTypes.string.isRequired, - term: PropTypes.string.isRequired, - onTermChange: PropTypes.func.isRequired - }; - - constructor(props) { - super(props); - - this.state = { - page: 0, - - showManageTeamsModal: false, - showManageRolesModal: false, - showManageTokensModal: false, - showPasswordModal: false, - user: null - }; - } - - componentWillReceiveProps(nextProps) { - if (nextProps.teamId !== this.props.teamId) { - this.setState({page: 0}); - } - } - - nextPage = () => { - this.setState({page: this.state.page + 1}); - - this.props.nextPage(this.state.page + 1); - } - - previousPage = () => { - this.setState({page: this.state.page - 1}); - } - - search = (term) => { - this.props.search(term); - - if (term !== '') { - this.setState({page: 0}); - } - } - - doManageTeams = (user) => { - this.setState({ - showManageTeamsModal: true, - user - }); - } - - doManageRoles = (user) => { - this.setState({ - showManageRolesModal: true, - user - }); - } - - doManageTokens = (user) => { - this.setState({ - showManageTokensModal: true, - user - }); - } - - doManageTeamsDismiss = () => { - this.setState({ - showManageTeamsModal: false, - user: null - }); - } - - doManageRolesDismiss = () => { - this.setState({ - showManageRolesModal: false, - user: null - }); - } - - doManageTokensDismiss = () => { - this.setState({ - showManageTokensModal: false, - user: null - }); - } - - doPasswordReset = (user) => { - this.setState({ - showPasswordModal: true, - user - }); - } - - doPasswordResetDismiss = () => { - this.setState({ - showPasswordModal: false, - user: null - }); - } - - doPasswordResetSubmit = (user) => { - getUser(user.id)(dispatch, getState); - - this.setState({ - showPasswordModal: false, - user: null - }); - } - - getInfoForUser(user) { - const info = []; - - if (user.auth_service) { - let service; - if (user.auth_service === Constants.LDAP_SERVICE || user.auth_service === Constants.SAML_SERVICE) { - service = user.auth_service.toUpperCase(); - } else { - service = Utils.toTitleCase(user.auth_service); - } - - info.push( - - ); - } else { - info.push( - - ); - } - - const mfaEnabled = global.window.mm_license.IsLicensed === 'true' && - global.window.mm_license.MFA === 'true' && - global.window.mm_config.EnableMultifactorAuthentication === 'true'; - if (mfaEnabled) { - info.push(', '); - - if (user.mfa_active) { - info.push( - - ); - } else { - info.push( - - ); - } - } - - return info; - } - - renderCount(count, total, startCount, endCount, isSearch) { - if (total) { - if (isSearch) { - return ( - - ); - } else if (startCount !== 0 || endCount !== total) { - return ( - - ); - } - - return ( - - ); - } - - return null; - } - - render() { - const extraInfo = {}; - if (this.props.users) { - for (const user of this.props.users) { - extraInfo[user.id] = this.getInfoForUser(user); - } - } - - return ( -
    - - - - - -
    - ); - } -} diff --git a/webapp/components/admin_console/text_setting.jsx b/webapp/components/admin_console/text_setting.jsx deleted file mode 100644 index 5830828d2c7..00000000000 --- a/webapp/components/admin_console/text_setting.jsx +++ /dev/null @@ -1,88 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import Setting from './setting.jsx'; - -export default class TextSetting extends React.Component { - static get propTypes() { - return { - id: PropTypes.string.isRequired, - label: PropTypes.node.isRequired, - placeholder: PropTypes.string, - helpText: PropTypes.node, - value: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number - ]).isRequired, - maxLength: PropTypes.number, - onChange: PropTypes.func, - disabled: PropTypes.bool, - type: PropTypes.oneOf([ - 'input', - 'textarea' - ]) - }; - } - - static get defaultProps() { - return { - type: 'input', - maxLength: null - }; - } - - constructor(props) { - super(props); - - this.handleChange = this.handleChange.bind(this); - } - - handleChange(e) { - this.props.onChange(this.props.id, e.target.value); - } - - render() { - let input = null; - if (this.props.type === 'input') { - input = ( - - ); - } else if (this.props.type === 'textarea') { - input = ( -