[NEW] Setup Wizard and Page not found, using React components (#15204)

pull/15102/head
Tasso Evangelista 6 years ago committed by Guilherme Gazzo
parent afa986bdd2
commit 2c49313a76
  1. 15
      .eslintrc
  2. 18
      app/setup-wizard/client/final.html
  3. 4
      app/setup-wizard/client/index.js
  4. 214
      app/setup-wizard/client/setupWizard.html
  5. 1
      app/setup-wizard/server/index.js
  6. 574
      app/theme/client/imports/components/setup-wizard.css
  7. 1
      app/theme/client/main.css
  8. 2
      app/ui/client/index.js
  9. 48
      app/ui/client/views/fxos.html
  10. 21
      app/ui/client/views/fxos.js
  11. 14
      client/RocketChat.font.css
  12. 23
      client/components/basic/Button.js
  13. 13
      client/components/basic/Icon.js
  14. 67
      client/components/basic/Input.js
  15. 19
      client/components/connectionStatus/ConnectionStatusAlert.css
  16. 69
      client/components/connectionStatus/ConnectionStatusAlert.js
  17. 44
      client/components/pageNotFound/PageNotFound.css
  18. 37
      client/components/pageNotFound/PageNotFound.js
  19. 81
      client/components/setupWizard/Epilogue.css
  20. 32
      client/components/setupWizard/Epilogue.js
  21. 17
      client/components/setupWizard/Pager.js
  22. 42
      client/components/setupWizard/ParametersProvider.js
  23. 18
      client/components/setupWizard/SetupWizard.css
  24. 26
      client/components/setupWizard/SetupWizard.js
  25. 164
      client/components/setupWizard/SideBar.css
  26. 39
      client/components/setupWizard/SideBar.js
  27. 47
      client/components/setupWizard/StateChecker.js
  28. 26
      client/components/setupWizard/Step.css
  29. 14
      client/components/setupWizard/Step.js
  30. 3
      client/components/setupWizard/StepContent.css
  31. 7
      client/components/setupWizard/StepContent.js
  32. 28
      client/components/setupWizard/StepHeader.css
  33. 13
      client/components/setupWizard/StepHeader.js
  34. 25
      client/components/setupWizard/Steps.css
  35. 49
      client/components/setupWizard/Steps.js
  36. 57
      client/components/setupWizard/StepsState.js
  37. 20
      client/components/setupWizard/functions.js
  38. 156
      client/components/setupWizard/steps/AdminUserInformationStep.js
  39. 81
      client/components/setupWizard/steps/RegisterServerStep.css
  40. 152
      client/components/setupWizard/steps/RegisterServerStep.js
  41. 141
      client/components/setupWizard/steps/SettingsBasedStep.js
  42. 15
      client/hooks/useFocus.js
  43. 19
      client/hooks/useReactiveValue.js
  44. 5
      client/hooks/useSession.js
  45. 4
      client/hooks/useSetting.js
  46. 21
      client/hooks/useTranslation.js
  47. 5
      client/hooks/useUserId.js
  48. 17
      client/hooks/useWipeInitialPageLoading.js
  49. 1
      client/importPackages.js
  50. 2
      client/importsCss.js
  51. 1
      client/main.js
  52. 9
      client/routes/pageNotFound.html
  53. 22
      client/routes/pageNotFound.js
  54. 67
      client/routes/router.js
  55. 48
      client/routes/stylesheets/pageNotFound.css
  56. 322
      package-lock.json
  57. 7
      package.json
  58. 1
      public/fonts/RocketChat.eot
  59. 1
      public/fonts/RocketChat.svg
  60. 1
      public/fonts/RocketChat.ttf
  61. 1
      public/fonts/RocketChat.woff
  62. 1
      public/fonts/RocketChat.woff2
  63. 1
      server/importPackages.js
  64. 1
      server/main.js
  65. 10
      server/methods/getSetupWizardParameters.js
  66. 4
      tests/pageobjects/setup-wizard.page.js

@ -7,5 +7,18 @@
"Assets" : false,
"chrome" : false,
"jscolor" : false
}
},
"plugins": ["react"],
"rules": {
"jsx-quotes": ["error", "prefer-single"],
"react/jsx-uses-react": "error",
"react/jsx-uses-vars": "error",
"react/jsx-no-undef": "error",
"react/jsx-fragments": ["error", "syntax"],
},
"settings": {
"react": {
"version": "detect",
},
},
}

@ -1,18 +0,0 @@
<template name="setupWizardFinal">
<div class="setup-wizard">
<div class="setup-wizard-final">
<header class="setup-wizard-info__header setup-wizard-final__header">
<img class="setup-wizard-info__header-logo" src="images/logo/logo.svg">
</header>
<main class="setup-wizard-final__box">
<span class="setup-wizard-forms__header-step">{{_ "Launched_successfully"}}</span>
<h1 class="setup-wizard-info__content-title setup-wizard-final__box-title">{{_ "Your_workspace_is_ready"}}</h1>
<span class="setup-wizard-final__link-text">{{_ "Your_server_link"}}</span>
<span class="setup-wizard-final__link">{{siteUrl}}</span>
<button class="rc-button rc-button--primary js-finish">
<span>{{_ "Go_to_your_workspace"}}</span>
</button>
</main>
</div>
</div>
</template>

@ -1,4 +0,0 @@
import './setupWizard.html';
import './setupWizard';
import './final.html';
import './final';

@ -1,214 +0,0 @@
<template name="setupWizard">
<div class="rc-old connection-status">
{{> status}}
</div>
<div class="setup-wizard">
{{> setupWizardInfo infoArgs}}
<section class="setup-wizard-forms">
<div class="setup-wizard-forms__wrapper">
<form class="setup-wizard-forms__box {{formLoadStateClass}}" novalidate>
<header class="setup-wizard-forms__header">
<span class="setup-wizard-forms__header-step">{{_ "Step"}} {{currentStep}}</span>
<h1 class="setup-wizard-forms__header-title">{{_ currentStepTitle}}</h1>
</header>
<main class="setup-wizard-forms__content">
{{> setupWizardAdminInfo adminInfoArgs}}
{{> setupWizardCustomStep (customStepArgs 2)}}
{{> setupWizardCustomStep (customStepArgs 3)}}
{{> setupWizardRegisterServer registerServerArgs}}
</main>
<footer class="setup-wizard-forms__footer">
{{#if showBackButton}}
<button type="button" class="rc-button rc-button--secondary setup-wizard-forms__footer-back">
<span>{{_ "Back"}}</span>
</button>
{{/if}}
<button type="submit" class="rc-button rc-button--primary setup-wizard-forms__footer-next" disabled={{isContinueDisabled}}>
<span>{{_ "Continue"}}</span>
</button>
</footer>
</form>
</div>
</section>
</div>
</template>
<template name="setupWizardInfo">
<section class="setup-wizard-info">
<header class="setup-wizard-info__header">
<img class="setup-wizard-info__header-logo" src="images/logo/logo.svg">
<span class="setup-wizard-info__header-tag">{{_ "Setup Wizard"}}</span>
</header>
<div class="setup-wizard-info__content">
<h1 class="setup-wizard-info__content-title">{{_ "Setup_Wizard"}}</h1>
<p class="setup-wizard-info__content-text">{{_ "Setup_Wizard_Info"}}</p>
<ol class="setup-wizard-info__steps">
<li class="setup-wizard-info__steps-item {{stepItemModifier 1}}">{{_ (stepTitle 1)}}</li>
<li class="setup-wizard-info__steps-item {{stepItemModifier 2}}">{{_ (stepTitle 2)}}<span class="setup-wizard-info__steps-item-bonding"></span></li>
<li class="setup-wizard-info__steps-item {{stepItemModifier 3}}">{{_ (stepTitle 3)}}<span class="setup-wizard-info__steps-item-bonding"></span></li>
<li class="setup-wizard-info__steps-item {{stepItemModifier 4}}">{{_ (stepTitle 4)}}<span class="setup-wizard-info__steps-item-bonding"></span></li>
</ol>
</div>
</section>
</template>
<template name="setupWizardAdminInfo">
<div class="setup-wizard-forms__content-step {{#if $eq currentStep 1}}setup-wizard-forms__content-step--active{{/if}}">
<div class="rc-input">
<label class="rc-input__label">
<div class="rc-input__title">{{_ "Name"}}</div>
<div class="rc-input__wrapper">
<div class="rc-input__icon">
{{> icon block="rc-input__icon-sv" icon="user"}}
</div>
<input type="text" class="rc-input__element js-setting-data" name="registration-name" placeholder="{{_ 'Type_your_name'}}" value="{{name}}">
</div>
</label>
</div>
<div class="rc-input {{#if invalidUsername}}rc-input--error{{/if}}">
<label class="rc-input__label">
<div class="rc-input__title">{{_ "Username"}}</div>
<div class="rc-input__wrapper">
<div class="rc-input__icon">
{{> icon block="rc-input__icon-sv" icon="at"}}
</div>
<input type="text" class="rc-input__element js-setting-data" name="registration-username" placeholder="{{_ 'Type_your_username'}}" value="{{username}}">
</div>
</label>
{{#if invalidUsername}}
<div class="rc-input__error">
<div class="rc-input__error-icon">
{{> icon block="rc-input__error-icon" icon="warning" classes="rc-input__error-icon-svg"}}
</div>
<div class="rc-input__error-message">{{_ "Invalid_username"}}</div>
</div>
{{/if}}
</div>
<div class="rc-input {{#if invalidEmail}}rc-input--error{{/if}}">
<label class="rc-input__label">
<div class="rc-input__title">{{_ "Organization_Email"}}</div>
<div class="rc-input__wrapper">
<div class="rc-input__icon">
{{> icon block="rc-input__icon-sv" icon="mail"}}
</div>
<input type="email" class="rc-input__element js-setting-data" name="registration-email" placeholder="{{_ 'Type_your_email'}}" value="{{email}}">
</div>
</label>
{{#if invalidEmail}}
<div class="rc-input__error">
<div class="rc-input__error-icon">
{{> icon block="rc-input__error-icon" icon="warning" classes="rc-input__error-icon-svg"}}
</div>
<div class="rc-input__error-message">{{_ "Invalid_email"}}</div>
</div>
{{/if}}
</div>
<div class="rc-input">
<label class="rc-input__label">
<div class="rc-input__title">{{_ "Password"}}</div>
<div class="rc-input__wrapper">
<div class="rc-input__icon">
{{> icon block="rc-input__icon-sv" icon="key"}}
</div>
<input type="password" class="rc-input__element js-setting-data" name="registration-pass" placeholder="{{_ 'Type_your_password'}}" value="{{password}}">
</div>
</label>
</div>
</div>
</template>
<template name="setupWizardRegisterServer">
<div class="setup-wizard-forms__content-step {{#if $eq currentStep 4}}setup-wizard-forms__content-step--active{{/if}}">
<p class="setup-wizard-forms__content-text">{{_ "Register_Server_Info"}}</p>
<form class="setup-wizard-forms__content-register">
<label class="setup-wizard-forms__content-register-option {{#if registerServer}}setup-wizard-forms__content-register-option--selected{{/if}}">
<div class="setup-wizard-forms__content-register-radio">
<input type="radio" name="registerServer" value="true" class="setup-wizard-forms__content-register-radio-element" checked="{{registerServer}}">
<span class="setup-wizard-forms__content-register-radio-fake"></span>
<span class="setup-wizard-forms__content-register-radio-text">{{_ "Register_Server_Registered"}}</span>
</div>
<ul class="setup-wizard-forms__content-register-items">
<li class="setup-wizard-forms__content-register-item">{{> icon block="setup-wizard-forms__content-register-radio-icon" icon="check"}}{{_ "Register_Server_Registered_Push_Notifications"}}</li>
<li class="setup-wizard-forms__content-register-item">{{> icon block="setup-wizard-forms__content-register-radio-icon" icon="check"}}{{_ "Register_Server_Registered_Livechat"}}</li>
<li class="setup-wizard-forms__content-register-item">{{> icon block="setup-wizard-forms__content-register-radio-icon" icon="check"}}{{_ "Register_Server_Registered_OAuth"}}</li>
<li class="setup-wizard-forms__content-register-item">{{> icon block="setup-wizard-forms__content-register-radio-icon" icon="check"}}{{_ "Register_Server_Registered_Marketplace"}}</li>
</ul>
<div>
<label class="setup-wizard-forms__content-register-checkbox">
<input type="checkbox" name="optIn" value="true" class="setup-wizard-forms__content-register-checkbox-element" checked="{{optIn}}" disabled={{$not registerServer}}>
<span class="setup-wizard-forms__content-register-checkbox-fake">
{{> icon block="setup-wizard-forms__content-register-checkbox-fake-icon" icon="check"}}
</span>
<span class="setup-wizard-forms__content-register-checkbox-text">{{_ "Register_Server_Opt_In"}}</span>
</label>
</div>
</label>
<label class="setup-wizard-forms__content-register-option {{#if $not registerServer}}setup-wizard-forms__content-register-option--selected{{/if}} {{#if $not allowStandaloneServer}}setup-wizard-forms__content-register-option--disabled{{/if}}">
<div class="setup-wizard-forms__content-register-radio">
<input type="radio" name="registerServer" value="false" class="setup-wizard-forms__content-register-radio-element" checked="{{$not registerServer}}" disabled={{$not allowStandaloneServer}}>
<span class="setup-wizard-forms__content-register-radio-fake"></span>
<span class="setup-wizard-forms__content-register-radio-text">{{_ "Register_Server_Standalone"}}</span>
</div>
<ul class="setup-wizard-forms__content-register-items">
<li class="setup-wizard-forms__content-register-item">{{> icon block="setup-wizard-forms__content-register-radio-icon" icon="circle"}}{{_ "Register_Server_Standalone_Service_Providers"}}</li>
<li class="setup-wizard-forms__content-register-item">{{> icon block="setup-wizard-forms__content-register-radio-icon" icon="circle"}}{{_ "Register_Server_Standalone_Update_Settings"}}</li>
<li class="setup-wizard-forms__content-register-item">{{> icon block="setup-wizard-forms__content-register-radio-icon" icon="circle"}}{{_ "Register_Server_Standalone_Own_Certificates"}}</li>
</ul>
</label>
</form>
</div>
</template>
<template name="setupWizardCustomStep">
<div class="setup-wizard-forms__content-step {{#if $eq currentStep step}}setup-wizard-forms__content-step--active{{/if}}">
{{#each settings}}
{{#if $eq type 'string'}}
<div class="rc-input">
<label class="rc-input__label">
<div class="rc-input__title">{{_ label}}</div>
<div class="rc-input__wrapper">
<input type="text" class="rc-input__element js-setting-data" name="{{id}}" value="{{value}}">
</div>
</label>
</div>
{{/if}}
{{#if $eq type 'select'}}
<div class="rc-input">
<label class="rc-input__label">
<div class="rc-input__title">{{_ label}}</div>
<div class="rc-select">
<select class="rc-select__element js-setting-data" name="{{id}}">
<option value="" disabled selected="{{this.isValueSelected undefined}}">{{_ "Select_an_option"}}</option>
{{#each options}}
<option class="rc-select__option" value="{{optionValue}}" selected="{{this.isValueSelected optionValue}}">{{_ optionLabel}}</option>
{{/each}}
</select>
{{> icon block="rc-select__arrow" icon="arrow-down" }}
</div>
</label>
</div>
{{/if}}
{{#if $eq type 'language'}}
<div class="rc-input">
<label class="rc-input__label">
<div class="rc-input__title">{{_ label}}</div>
<div class="rc-select">
<select class="rc-select__element js-setting-data" name="{{id}}">
<option value="" disabled selected="{{this.isValueSelected undefined}}">{{_ "Default"}}</option>
{{#each options}}
<option class="rc-select__option" value="{{optionValue}}" selected="{{this.isValueSelected optionValue}}" dir="auto">{{_ optionLabel}}</option>
{{/each}}
</select>
{{> icon block="rc-select__arrow" icon="arrow-down" }}
</div>
</label>
</div>
{{/if}}
{{/each}}
</div>
</template>

@ -1 +0,0 @@
import './getSetupWizardParameters';

@ -1,574 +0,0 @@
.setup-wizard {
--step-color: var(--rc-color-button-primary);
--highlight-color: var(--rc-color-button-primary);
display: flex;
width: 100%;
height: 100%;
background-color: #f7f8fa;
justify-content: center;
&-info {
overflow: hidden;
flex: 0 1 350px;
margin: 55px 65px 30px 80px;
&__header {
display: flex;
margin: 0 -0.375rem 3rem;
align-items: center;
&-logo {
height: 1.5rem;
margin: 0 0.375rem;
}
&-tag {
margin: 0 0.375rem;
padding: 4px 8px;
letter-spacing: 0.05rem;
text-transform: uppercase;
color: #ffffff;
border-radius: 50px;
background: #2f343d;
font-size: 10px;
line-height: 1rem;
}
}
&__content {
&-title {
margin-bottom: 1rem;
letter-spacing: 0.03rem;
color: #2f343d;
font-size: 2rem;
font-weight: 600;
line-height: 2.6rem;
}
&-text {
margin-bottom: 3rem;
color: #9ea2a8;
font-size: 1rem;
font-weight: 500;
line-height: 1.5rem;
}
}
&__steps {
counter-reset: steps;
&-item {
position: relative;
margin: 0 -0.5rem;
counter-increment: steps;
color: #d3d5d9;
font-size: 0.875rem;
font-weight: 500;
&:not(:last-child) {
margin-bottom: 2rem;
&::after {
position: absolute;
bottom: -1rem;
left: 1.2rem;
display: block;
width: 1px;
height: 1rem;
content: "";
background-color: #d3d5d9;
}
}
&::before {
display: inline-flex;
width: 1.5rem;
height: 1.5rem;
margin: 0 0.5rem;
content: counter(steps);
color: #d3d5d9;
border: 1px solid #d3d5d9;
border-radius: 50px;
font-size: 0.75rem;
align-items: center;
justify-content: center;
}
&--active {
color: var(--rc-color-button-primary);
&::before {
color: var(--rc-color-button-primary);
border-color: var(--rc-color-button-primary);
background-color: transparent;
}
}
&--past {
color: var(--rc-color-primary);
&::before {
color: var(--rc-color-content);
border-color: var(--rc-color-button-primary);
background-color: var(--rc-color-button-primary);
}
&::after {
background-color: var(--rc-color-button-primary) !important;
}
& .setup-wizard-info__steps-item-bonding {
background-color: var(--rc-color-button-primary);
}
}
&-bonding {
position: absolute;
top: -1rem;
left: 1.2rem;
display: block;
width: 1px;
height: 1rem;
background-color: currentColor;
}
}
}
}
&-forms {
flex: 1 1 auto;
&__wrapper {
display: flex;
overflow-y: auto;
width: calc(100% - 1rem);
height: calc(100% - 2rem);
margin: 1rem 1rem 1rem 0;
border-radius: 2px;
background: #ffffff;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.08);
justify-content: center;
}
&__box {
display: flex;
visibility: hidden;
flex-direction: column;
width: 350px;
min-height: min-content;
margin: 3rem;
transition: opacity 1s linear;
opacity: 0;
&--loaded {
visibility: visible;
opacity: 1;
}
}
&__header {
margin-bottom: 2rem;
&-step {
display: block;
margin-bottom: 3px;
letter-spacing: 0.05rem;
text-transform: uppercase;
color: #caced1;
font-size: 0.75rem;
line-height: 1.125rem;
}
&-title {
letter-spacing: 0.05rem;
color: #1f2329;
font-size: 1.25rem;
font-weight: 500;
line-height: 1.75rem;
}
}
&__content {
margin-bottom: 2rem;
&-step {
display: none;
&--active {
display: block;
}
}
&-text {
margin-bottom: 2rem;
color: #9ea2a8;
font-size: 1rem;
font-weight: 500;
line-height: 1.5rem;
}
&-register {
display: flex;
flex-direction: column;
&-option {
display: block;
padding: 1.5rem;
cursor: pointer;
color: #2f343d;
border: 2px solid #e7ebf2;
border-radius: 2px;
font-size: 0.875rem;
line-height: 1.25rem;
&--selected {
border-color: var(--highlight-color);
}
&--disabled {
opacity: 0.25;
}
&:first-child {
margin-bottom: 1rem;
}
}
&-radio {
position: relative;
display: flex;
margin: 0 -0.5rem 1rem;
&-element {
position: absolute;
z-index: -1;
top: 0;
left: 0;
width: 0;
height: 0;
&:checked + .setup-wizard-forms__content-register-radio-fake {
position: relative;
border-color: var(--highlight-color);
&::before {
position: absolute;
width: 100%;
height: 100%;
content: "";
border: 2px solid transparent;
border-radius: 50%;
background-color: var(--highlight-color);
background-clip: padding-box;
}
}
}
&-fake {
display: block;
width: 20px;
height: 20px;
margin: 0 0.5rem;
border: 2px solid #cfd8e6;
border-radius: 50px;
}
&-text {
font-weight: 500;
}
}
&-checkbox {
position: relative;
display: flex;
margin: 0 -0.5rem 1rem;
cursor: inherit;
&-element {
position: absolute;
z-index: -1;
top: 0;
left: 0;
width: 0;
height: 0;
&:checked + .setup-wizard-forms__content-register-checkbox-fake {
position: relative;
color: var(--rc-color-content);
border-color: var(--highlight-color);
background-color: var(--highlight-color);
.setup-wizard-forms__content-register-checkbox-fake-icon {
display: block;
}
}
}
&-fake {
display: block;
width: 16px;
height: 16px;
margin: 2px 0.5rem;
border: 2px solid #cfd8e6;
border-radius: 2px;
&-icon {
display: none;
width: 100%;
height: 100%;
}
}
&-text {
color: #666666;
}
}
&-items + * {
margin-top: 1rem;
}
&-item {
display: flex;
margin: 0 -0.5rem 0.5rem;
align-items: center;
&:last-child {
margin-bottom: 0;
}
& .setup-wizard-forms__content-register-radio-icon {
width: 20px;
min-width: 20px;
height: 20px;
margin: 0 0.5rem;
align-self: baseline;
&--check {
color: var(--highlight-color);
}
&--circle {
height: 6px;
margin: 7px 0.5rem;
}
}
}
}
}
&__footer {
display: flex;
flex-direction: row;
margin: 0 -0.5rem 2rem;
& .rc-button {
margin: 0 0.5rem;
}
}
}
&-final {
width: 930px;
padding-top: 5rem;
&__header {
margin-bottom: 5rem;
}
&__box {
padding: 5rem 6rem;
border-radius: 2px;
background: #ffffff;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.08);
&-title {
margin-bottom: 3.25rem;
}
}
&__link {
display: block;
margin-bottom: 1.5rem;
letter-spacing: 0;
color: var(--highlight-color);
font-size: 1rem;
line-height: 1.5rem;
&-text {
display: block;
letter-spacing: 0.03rem;
text-transform: uppercase;
color: #2f343d;
font-size: 0.625rem;
line-height: 1rem;
}
}
}
& .rc-input {
&:not(:last-child) {
margin-bottom: 1.5rem;
}
&__title {
letter-spacing: 0.03rem;
text-transform: uppercase;
color: #9ea2a8;
font-size: 0.625rem;
line-height: 1rem;
}
&__element {
color: #030c1a;
font-weight: 500;
}
}
& .rc-select {
&__element {
color: #030c1a;
font-size: 0.875rem;
font-weight: 500;
}
}
}
.rtl {
& .setup-wizard-info {
margin: 55px 80px 0 65px;
}
& .setup-wizard-forms__wrapper {
margin: 1rem 0 1rem 1rem;
}
& .setup-wizard-info__steps-item {
&:not(:last-child)::after,
&-bonding {
right: 1.2rem;
left: auto;
}
}
}
@media (width <= 760px) {
.setup-wizard {
flex-direction: column;
justify-content: initial;
& .setup-wizard-forms__wrapper {
width: 100%;
margin: 0;
}
}
}

@ -29,7 +29,6 @@
@import 'imports/components/sidebar/rooms-list.css';
/* Main */
@import 'imports/components/setup-wizard.css';
@import 'imports/components/flex-nav.css';
@import 'imports/components/header.css';
@import 'imports/components/memberlist.css';

@ -8,7 +8,6 @@ import './lib/parentTemplate';
import './lib/codeMirror/codeMirror';
import './lib/textarea-cursor';
import './views/cmsPage.html';
import './views/fxos.html';
import './views/modal.html';
import './views/404/roomNotFound.html';
import './views/404/invalidSecretURL.html';
@ -30,7 +29,6 @@ import './views/app/videoCall/videoButtons.html';
import './views/app/videoCall/videoCall.html';
import './views/app/photoswipe.html';
import './views/cmsPage';
import './views/fxos';
import './views/modal';
import './views/404/roomNotFound';
import './views/app/burger';

@ -1,48 +0,0 @@
<template name="fxOsInstallPrompt">
<section class="rc-old full-page color-tertiary-font-color">
<div class="wrapper">
<header>
<a class="logo" href="/">
<img src="images/logo/logo.svg?v=3" />
</a>
</header>
<div class="cms-page content-background-color">
<h1>{{_ "Install_FxOs"}}</h1>
<p>{{_ "Install_FxOs_follow_instructions"}}</p>
</div>
</div>
</section>
</template>
<template name="fxOsInstallDone">
<section class="rc-old full-page color-tertiary-font-color">
<div class="wrapper">
<header>
<a class="logo" href="/">
<img src="images/logo/logo.svg?v=3" />
</a>
</header>
<div class="cms-page content-background-color">
<h1>{{_ "Install_FxOs"}}</h1>
<p>{{_ "Install_FxOs_done"}}</p>
</div>
</div>
</section>
</template>
<template name="fxOsInstallError">
<section class="rc-old full-page color-tertiary-font-color">
<div class="wrapper">
<header>
<a class="logo" href="/">
<img src="images/logo/logo.svg?v=3" />
</a>
</header>
<div class="cms-page content-background-color">
<h1>{{_ "Install_FxOs"}}</h1>
<p>{{_ "Install_FxOs_error"}}</p>
<p>{{installError}}</p>
</div>
</div>
</section>
</template>

@ -1,21 +0,0 @@
import { BlazeLayout } from 'meteor/kadira:blaze-layout';
import { Template } from 'meteor/templating';
Template.fxOsInstallPrompt.onRendered(function() {
const showPrompt = function() {
const request = window.navigator.mozApps.install(`http://${ location.host }/manifest.webapp`);
request.onsuccess = function() {
BlazeLayout.render('fxOsInstallDone');
};
request.onerror = function() {
BlazeLayout.render('fxOsInstallError', {
installError: this.error.name,
});
};
};
setTimeout(showPrompt, 2000);
return $('#initial-page-loading').remove();
});
Template.fxOsInstallDone.onRendered(() => $('#initial-page-loading').remove());
Template.fxOsInstallError.onRendered(() => $('#initial-page-loading').remove());

@ -0,0 +1,14 @@
@font-face {
font-family: 'RocketChat';
font-weight: 400;
font-style: normal;
font-display: auto;
src: url('/fonts/RocketChat.eot');
src:
url('/fonts/RocketChat.eot?#iefix') format('embedded-opentype'),
url('/fonts/RocketChat.woff2') format('woff2'),
url('/fonts/RocketChat.woff') format('woff'),
url('/fonts/RocketChat.ttf') format('truetype'),
url('/fonts/RocketChat.svg#RocketChat') format('svg');
}

@ -0,0 +1,23 @@
import React from 'react';
export const Button = ({
children,
className,
invisible,
primary,
secondary,
submit,
...props
}) => <button
type={(submit && 'submit') || 'button'}
className={[
'rc-button',
primary && 'rc-button--primary',
secondary && 'rc-button--secondary',
invisible && 'rc-button--invisible',
className,
].filter(Boolean).join(' ')}
{...props}
>
{children}
</button>;

@ -0,0 +1,13 @@
import React from 'react';
export const Icon = ({ icon, block = '', baseUrl = '', className }) => <svg
className={[
'rc-icon',
block,
block && icon && `${ block }--${ icon }`,
className,
].filter(Boolean).join(' ')}
aria-hidden='true'
>
<use xlinkHref={`${ baseUrl }#icon-${ icon }`} />
</svg>;

@ -0,0 +1,67 @@
import React, { useEffect, useRef } from 'react';
import { Icon } from './Icon';
export const Input = ({
error,
title,
icon,
type = 'text',
className,
placeholder,
options,
focused,
...props
}) => {
const ref = useRef(null);
useEffect(() => {
if (focused && ref.current) {
ref.current.focus();
}
}, [focused]);
return <div
className={[
'rc-input',
error && 'rc-input--error',
].filter(Boolean).join(' ')}
>
<label className='rc-input__label'>
{title && <div className='rc-input__title'>{title}</div>}
{['text', 'email', 'password'].includes(type) && <div className='rc-input__wrapper'>
{icon && <div className='rc-input__icon'>
<Icon block='rc-input__icon-sv' icon={icon} />
</div>}<input
type={type}
className={['rc-input__element', className].filter(Boolean).join(' ')}
placeholder={placeholder}
ref={ref}
{...props}
/>
</div>}
{type === 'select' && <div className='rc-select'>
<select
className={['rc-select__element', className].filter(Boolean).join(' ')}
ref={ref}
{...props}
>
{placeholder && <option
disabled
value=''
>{placeholder}</option>}
{options.map(({ label, value }, i) =>
<option key={i} className='rc-select__option' value={value}>{label}</option>
)}
</select>
<Icon block='rc-select__arrow' icon='arrow-down' />
</div>}
{typeof error === 'string' && error && <div className='rc-input__error'>
<div className='rc-input__error-icon'>
<Icon block='rc-input__error-icon' icon='warning' className='rc-input__error-icon-svg'/>
</div>
<div className='rc-input__error-message'>{error}</div>
</div>}
</label>
</div>;
};

@ -0,0 +1,19 @@
.ConnectionStatusAlert {
position: fixed;
z-index: 1000000;
top: 0;
width: 100%;
padding: 2px;
text-align: center;
color: #916302;
border-bottom-width: 1px;
background-color: #fffdf9;
}
.ConnectionStatusAlert__link {
color: var(--color-blue);
}

@ -0,0 +1,69 @@
import { Meteor } from 'meteor/meteor';
import React, { useEffect, useRef, useState } from 'react';
import { useReactiveValue } from '../../hooks/useReactiveValue';
import { useTranslation } from '../../hooks/useTranslation';
import { Icon } from '../basic/Icon';
export function ConnectionStatusAlert() {
const {
connected,
retryTime,
status,
} = useReactiveValue(() => ({ ...Meteor.status() }));
const reconnectionTimerRef = useRef();
const [reconnectCountdown, setReconnectCountdown] = useState(0);
const t = useTranslation();
useEffect(() => {
if (status === 'waiting') {
if (reconnectionTimerRef.current) {
return;
}
reconnectionTimerRef.current = setInterval(() => {
const timeDiff = retryTime - Date.now();
setReconnectCountdown((timeDiff > 0 && Math.round(timeDiff / 1000)) || 0);
}, 500);
return;
}
clearInterval(reconnectionTimerRef.current);
reconnectionTimerRef.current = null;
}, [retryTime, status]);
useEffect(() => () => {
clearInterval(reconnectionTimerRef.current);
}, []);
if (connected) {
return null;
}
const handleRetryClick = (event) => {
event.preventDefault();
Meteor.reconnect();
};
return <div className='ConnectionStatusAlert' role='alert'>
<strong>
<Icon icon='warning' /> {t('meteor_status', { context: status })}
</strong>
{status === 'waiting' && <>
{' '}
{t('meteor_status_reconnect_in', { count: reconnectCountdown })}
</>}
{['waiting', 'offline'].includes(status) && <>
{' '}
<a
href='#'
className='ConnectionStatusAlert__link'
onClick={handleRetryClick}
>
{t('meteor_status_try_now', { context: status })}
</a>
</>}
</div>;
}

@ -0,0 +1,44 @@
.PageNotFound {
width: 100%;
min-height: 100vh;
padding: 10%;
text-align: center;
color: white;
background-color: var(--rc-color-primary);
background-image: url('/images/404.svg');
background-repeat: no-repeat;
background-position: center;
background-size: cover;
}
.PageNotFound__404 {
display: block;
padding: 10px;
font-size: 4em;
font-weight: bold;
}
.PageNotFound__message {
display: block;
padding: 10px;
font-size: 2em;
font-weight: bold;
}
.PageNotFound__description {
display: block;
padding: 10px;
font-size: 1em;
}
.PageNotFound__actions {
margin: 2rem;
}

@ -0,0 +1,37 @@
import { Button, ButtonGroup } from '@rocket.chat/fuselage';
import { FlowRouter } from 'meteor/kadira:flow-router';
import React from 'react';
import { useTranslation } from '../../hooks/useTranslation';
import { useWipeInitialPageLoading } from '../../hooks/useWipeInitialPageLoading';
import { ConnectionStatusAlert } from '../connectionStatus/ConnectionStatusAlert';
export function PageNotFound() {
useWipeInitialPageLoading();
const t = useTranslation();
const handleGoToPreviousPageClick = () => {
window.history.back();
};
const handleGoHomeClick = () => {
FlowRouter.go('home');
};
return <>
<ConnectionStatusAlert />
<section className='PageNotFound'>
<span className='PageNotFound__404'>404</span>
<span className='PageNotFound__message'>{t('Oops_page_not_found')}</span>
<span className='PageNotFound__description'>{t('Sorry_page_you_requested_does_not_exists_or_was_deleted')}</span>
<div className='PageNotFound__actions'>
<ButtonGroup>
<Button type='button' primary onClick={handleGoToPreviousPageClick}>{t('Return_to_previous_page')}</Button>
<Button type='button' primary onClick={handleGoHomeClick}>{t('Return_to_home')}</Button>
</ButtonGroup>
</div>
</section>
</>;
}

@ -0,0 +1,81 @@
.SetupWizard__Epilogue {
width: 930px;
padding-top: 5rem;
}
.SetupWizard__Epilogue-header {
display: flex;
margin: 0 -0.375rem 5rem;
align-items: center;
}
.SetupWizard__Epilogue-headerLogo {
height: 1.5rem;
margin: 0 0.375rem;
}
.SetupWizard__Epilogue-content {
padding: 5rem 6rem;
border-radius: 2px;
background: #ffffff;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.08);
}
.SetupWizard__Epilogue-runningHead {
display: block;
margin-bottom: 3px;
letter-spacing: 0.05rem;
text-transform: uppercase;
color: #caced1;
font-size: 0.75rem;
line-height: 1.125rem;
}
.SetupWizard__Epilogue-title {
margin-bottom: 3.25rem;
letter-spacing: 0.03rem;
color: #2f343d;
font-size: 2rem;
font-weight: 600;
line-height: 2.6rem;
}
.SetupWizard__Epilogue-link {
display: block;
margin-bottom: 1.5rem;
letter-spacing: 0;
color: var(--rc-color-button-primary);
font-size: 1rem;
line-height: 1.5rem;
}
.SetupWizard__Epilogue-linkLabel {
display: block;
letter-spacing: 0.03rem;
text-transform: uppercase;
color: var(--color-dark);
font-size: 0.625rem;
line-height: 1rem;
}

@ -0,0 +1,32 @@
import React from 'react';
import { Button } from '@rocket.chat/fuselage';
import { useTranslation } from '../../hooks/useTranslation';
import { useSetting } from '../../hooks/useSetting';
import { setSetting } from './functions';
import './Epilogue.css';
export function Epilogue() {
const t = useTranslation();
const siteUrl = useSetting('Site_Url');
const handleClick = () => {
setSetting('Show_Setup_Wizard', 'completed');
};
return <section className='SetupWizard__Epilogue'>
<header className='SetupWizard__Epilogue-header'>
<img className='SetupWizard__Epilogue-headerLogo' src='images/logo/logo.svg' />
</header>
<main className='SetupWizard__Epilogue-content'>
<span className='SetupWizard__Epilogue-runningHead'>{t('Launched_successfully')}</span>
<h1 className='SetupWizard__Epilogue-title'>{t('Your_workspace_is_ready')}</h1>
<span className='SetupWizard__Epilogue-linkLabel'>{t('Your_server_link')}</span>
<span className='SetupWizard__Epilogue-link'>{siteUrl}</span>
<Button type='button' primary onClick={handleClick} className='SetupWizard__Epilogue__goToWorkspace'>
{t('Go_to_your_workspace')}
</Button>
</main>
</section>;
}

@ -0,0 +1,17 @@
import { Button, ButtonGroup } from '@rocket.chat/fuselage';
import React from 'react';
import { useTranslation } from '../../hooks/useTranslation';
export function Pager({ disabled, onBackClick, isContinueEnabled = true }) {
const t = useTranslation();
return <ButtonGroup align='start'>
{onBackClick ? <Button type='button' disabled={disabled} onClick={onBackClick} className='SetupWizard__back'>
{t('Back')}
</Button> : null}
<Button type='submit' primary disabled={!isContinueEnabled || disabled} className='SetupWizard__continue'>
{t('Continue')}
</Button>
</ButtonGroup>;
}

@ -0,0 +1,42 @@
import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';
import { call } from '../../../app/ui-utils/client';
const ParametersContext = createContext({
loaded: true,
settings: [],
canDeclineServerRegistration: false,
});
export const useSetupWizardParameters = () => useContext(ParametersContext);
export function ParametersProvider({ children }) {
const [loaded, setLoaded] = useState(false);
const [settings, setSettings] = useState([]);
const [canDeclineServerRegistration, setCapableOfDeclineServerRegistration] = useState(false);
useEffect(() => {
const getParameters = async () => {
const {
settings,
allowStandaloneServer,
} = await call('getSetupWizardParameters') || {};
setLoaded(true);
setSettings(settings);
setCapableOfDeclineServerRegistration(allowStandaloneServer);
};
getParameters();
}, []);
const value = useMemo(() => ({
loaded,
settings,
canDeclineServerRegistration,
}), [loaded, settings, canDeclineServerRegistration]);
return <ParametersContext.Provider value={value}>
{children}
</ParametersContext.Provider>;
}

@ -0,0 +1,18 @@
.SetupWizard {
display: flex;
width: 100%;
height: 100vh;
background-color: var(--color-dark-05);
align-items: stretch;
justify-content: center;
}
@media (width <= 760px) {
.SetupWizard {
flex-direction: column;
justify-content: initial;
}
}

@ -0,0 +1,26 @@
import React from 'react';
import { useWipeInitialPageLoading } from '../../hooks/useWipeInitialPageLoading';
import { ConnectionStatusAlert } from '../connectionStatus/ConnectionStatusAlert';
import { ParametersProvider } from './ParametersProvider';
import { StateChecker } from './StateChecker';
import { Steps } from './Steps';
import { StepsState } from './StepsState';
import './SetupWizard.css';
export function SetupWizard() {
useWipeInitialPageLoading();
return <>
<ConnectionStatusAlert />
<StateChecker>
<ParametersProvider>
<StepsState>
<div className='SetupWizard'>
<Steps />
</div>
</StepsState>
</ParametersProvider>
</StateChecker>
</>;
}

@ -0,0 +1,164 @@
.SetupWizard__SideBar {
display: flex;
overflow: hidden;
flex: 0 1 350px;
flex-flow: column nowrap;
}
.SetupWizard__SideBar-header {
display: flex;
margin: 2rem 1.625rem;
align-items: center;
flex-flow: row wrap;
}
.SetupWizard__SideBar-headerLogo {
height: 1.5rem;
margin: 0.25rem 0.375rem;
}
.SetupWizard__SideBar-headerTag {
margin: 0.25rem 0.375rem;
padding: 4px 8px;
white-space: nowrap;
text-transform: uppercase;
color: var(--color-white);
border-radius: 50px;
background-color: var(--color-dark);
font-size: 10px;
line-height: 1rem;
}
.SetupWizard__SideBar-content {
overflow: auto;
flex: 1;
margin: 0 0 1rem;
padding: 0 2rem;
}
.SetupWizard__SideBar-title {
margin-bottom: 1rem;
letter-spacing: 0.03rem;
color: var(--color-dark);
font-size: 2rem;
font-weight: 600;
line-height: 2.6rem;
}
.SetupWizard__SideBar-text {
margin-bottom: 3rem;
color: var(--color-gray);
font-size: 1rem;
font-weight: 500;
line-height: 1.5rem;
}
.SetupWizard__SideBar-step {
position: relative;
margin: 0 -0.5rem 2rem;
color: var(--color-dark-10);
font-size: 0.875rem;
font-weight: 500;
&::before {
display: inline-flex;
width: 1.5rem;
height: 1.5rem;
margin: 0 0.5rem;
content: attr(data-number);
color: var(--color-dark-10);
border: 1px solid var(--color-dark-10);
border-radius: 9999px;
font-size: 0.75rem;
align-items: center;
justify-content: center;
}
&::after {
position: absolute;
bottom: -2rem;
left: 1.2rem;
display: block;
width: 0.0625rem;
height: 2rem;
content: '';
background-color: var(--color-dark-10);
}
&:last-child {
margin-bottom: 0;
&::after {
display: none;
}
}
&--active {
color: var(--rc-color-button-primary);
&::before {
color: var(--rc-color-button-primary);
border-color: var(--rc-color-button-primary);
background-color: transparent;
}
}
&--past {
color: var(--rc-color-primary);
&::before {
color: var(--rc-color-content);
border-color: var(--rc-color-button-primary);
background-color: var(--rc-color-button-primary);
}
&::after {
background-color: var(--rc-color-button-primary);
}
}
.rtl &::after {
right: 1.2rem;
left: auto;
}
}
@media (width <= 760px) {
.SetupWizard__SideBar {
flex-basis: auto;
}
.SetupWizard__SideBar-content {
display: none;
}
}

@ -0,0 +1,39 @@
import React from 'react';
import { useTranslation } from '../../hooks/useTranslation';
import { useSetupWizardStepsState } from './StepsState';
import './SideBar.css';
export function SideBar({ steps = [] }) {
const { currentStep } = useSetupWizardStepsState();
const t = useTranslation();
return <aside className='SetupWizard__SideBar'>
<header className='SetupWizard__SideBar-header'>
<img className='SetupWizard__SideBar-headerLogo' src='images/logo/logo.svg' />
<span className='SetupWizard__SideBar-headerTag'>{t('Setup_Wizard')}</span>
</header>
<div className='SetupWizard__SideBar-content'>
<h2 className='SetupWizard__SideBar-title'>{t('Setup_Wizard')}</h2>
<p className='SetupWizard__SideBar-text'>{t('Setup_Wizard_Info')}</p>
<ol className='SetupWizard__SideBar-steps'>
{steps.map(({ step, title }) =>
<li
key={step}
className={[
'SetupWizard__SideBar-step',
step === currentStep && 'SetupWizard__SideBar-step--active',
step < currentStep && 'SetupWizard__SideBar-step--past',
].filter(Boolean).join(' ')}
data-number={step}
>
{title}
</li>
)}
</ol>
</div>
</aside>;
}

@ -0,0 +1,47 @@
import { FlowRouter } from 'meteor/kadira:flow-router';
import React, { useEffect, useState } from 'react';
import { hasRole } from '../../../app/authorization';
import { Users } from '../../../app/models';
import { useSetting } from '../../hooks/useSetting';
import { useUserId } from '../../hooks/useUserId';
import { useReactiveValue } from '../../hooks/useReactiveValue';
export function StateChecker({ children }) {
const setupWizardState = useSetting('Show_Setup_Wizard');
const userId = useUserId();
const user = useReactiveValue(() => Users.findOne(userId, { fields: { status: true } }), [userId]);
const [renderAllowed, allowRender] = useState(false);
useEffect(() => {
if (!setupWizardState) {
return;
}
if (userId && (!user || !user.status)) {
return;
}
const isComplete = setupWizardState === 'completed';
const noUserLoggedInAndIsNotPending = !renderAllowed && !user && setupWizardState !== 'pending';
const userIsLoggedInButIsNotAdmin = !!user && !hasRole(user._id, 'admin');
const mustRedirect = isComplete || noUserLoggedInAndIsNotPending || userIsLoggedInButIsNotAdmin;
if (mustRedirect) {
FlowRouter.withReplaceState(() => {
FlowRouter.go('home');
});
return;
}
allowRender(true);
}, [setupWizardState, userId, user]);
if (!renderAllowed) {
return null;
}
return <>{children}</>;
}

@ -0,0 +1,26 @@
.SetupWizard__Step {
display: none;
flex-direction: column;
max-width: 350px;
margin: 2rem auto;
transition: opacity 1s;
opacity: 1;
&--active {
display: flex;
}
&--working {
opacity: 0.5;
}
}
@media (width <= 760px) {
.SetupWizard__Step {
margin: 0 auto;
}
}

@ -0,0 +1,14 @@
import React from 'react';
import './Step.css';
export const Step = ({ active, working = false, ...props }) =>
<form
className={[
'SetupWizard__Step',
active && 'SetupWizard__Step--active',
working && 'SetupWizard__Step--working',
].filter(Boolean).join(' ')}
disabled={working}
{...props}
/>;

@ -0,0 +1,3 @@
.SetupWizard__StepContent {
margin-bottom: 2rem;
}

@ -0,0 +1,7 @@
import React from 'react';
import './StepContent.css';
export function StepContent(props) {
return <section className='SetupWizard__StepContent' {...props} />;
}

@ -0,0 +1,28 @@
.SetupWizard__StepHeader {
margin-bottom: 2rem;
}
.SetupWizard__StepHeader-runningHead {
margin-bottom: 3px;
letter-spacing: 0.05rem;
text-transform: uppercase;
color: var(--color-dark-20);
font-size: 0.75rem;
line-height: 1.125rem;
}
.SetupWizard__StepHeader-title {
letter-spacing: 0.05rem;
color: var(--color-dark-90);
font-size: 1.25rem;
font-weight: 500;
line-height: 1.75rem;
}

@ -0,0 +1,13 @@
import React from 'react';
import { useTranslation } from '../../hooks/useTranslation';
import './StepHeader.css';
export function StepHeader({ number, title }) {
const t = useTranslation();
return <header className='SetupWizard__StepHeader'>
<p className='SetupWizard__StepHeader-runningHead'>{t('Step')} {number}</p>
<h2 className='SetupWizard__StepHeader-title'>{title}</h2>
</header>;
}

@ -0,0 +1,25 @@
.SetupWizard__Steps {
flex: 1 1 auto;
height: 100vh;
padding: 1rem;
}
.SetupWizard__Steps-wrapper {
overflow: auto;
width: 100%;
height: 100%;
padding: 1rem 3rem;
border-radius: 2px;
background-color: var(--color-white);
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.08);
justify-content: center;
}
@media (width <= 760px) {
.SetupWizard__Steps {
padding: 0;
}
}

@ -0,0 +1,49 @@
import React from 'react';
import { AdminUserInformationStep } from './steps/AdminUserInformationStep';
import { SettingsBasedStep } from './steps/SettingsBasedStep';
import { RegisterServerStep } from './steps/RegisterServerStep';
import { useTranslation } from '../../hooks/useTranslation';
import { Epilogue } from './Epilogue';
import { SideBar } from './SideBar';
import { useSetupWizardStepsState, finalStep } from './StepsState';
export function Steps() {
const { currentStep } = useSetupWizardStepsState();
const t = useTranslation();
if (currentStep === finalStep) {
return <Epilogue />;
}
return <>
<SideBar
steps={[
{
step: 1,
title: t('Admin_Info'),
},
{
step: 2,
title: t('Organization_Info'),
},
{
step: 3,
title: t('Server_Info'),
},
{
step: 4,
title: t('Register_Server'),
},
]}
/>
<section className='SetupWizard__Steps'>
<div className='SetupWizard__Steps-wrapper'>
<AdminUserInformationStep step={1} title={t('Admin_Info')} />
<SettingsBasedStep step={2} title={t('Organization_Info')} />
<SettingsBasedStep step={3} title={t('Server_Info')} />
<RegisterServerStep step={4} title={t('Register_Server')} />
</div>
</section>
</>;
}

@ -0,0 +1,57 @@
import { FlowRouter } from 'meteor/kadira:flow-router';
import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';
import { useUserId } from '../../hooks/useUserId';
const Context = createContext();
export const useSetupWizardStepsState = () => useContext(Context);
export const finalStep = 'final';
const useStepRouting = () => {
const userId = useUserId();
const [currentStep, setCurrentStep] = useState(() => {
const param = FlowRouter.getParam('step');
if (param === finalStep) {
return finalStep;
}
const step = parseInt(param, 10);
if (Number.isFinite(step) && step >= 1) {
return step;
}
return 1;
});
useEffect(() => {
if (!userId) {
setCurrentStep(1);
} else if (currentStep === 1) {
setCurrentStep(2);
}
FlowRouter.withReplaceState(() => {
FlowRouter.go('setup-wizard', { step: String(currentStep) });
});
}, [userId, currentStep]);
return [currentStep, setCurrentStep];
};
export function StepsState({ children }) {
const [currentStep, setCurrentStep] = useStepRouting();
const value = useMemo(() => ({
currentStep,
goToPreviousStep: () => setCurrentStep(currentStep - 1),
goToNextStep: () => setCurrentStep(currentStep + 1),
goToFinalStep: () => setCurrentStep(finalStep),
}), [currentStep]);
return <Context.Provider value={value}>
{children}
</Context.Provider>;
}

@ -0,0 +1,20 @@
import { Meteor } from 'meteor/meteor';
import { settings } from '../../../app/settings/lib/settings';
const withPromisifiedReturn = (f) => (...args) => new Promise((resolve, reject) => {
f(...args, (error, ...returnedValues) => {
if (error) {
reject(error);
return;
}
resolve(returnedValues);
});
});
export const loginWithPassword = withPromisifiedReturn(Meteor.loginWithPassword.bind(Meteor));
export const batchSetSettings = withPromisifiedReturn(settings.batchSet.bind(settings));
export const setSetting = withPromisifiedReturn(settings.set.bind(settings));

@ -0,0 +1,156 @@
import { Input, InputGroup } from '@rocket.chat/fuselage';
import { Session } from 'meteor/session';
import React, { useMemo, useState } from 'react';
import toastr from 'toastr';
import { call } from '../../../../app/ui-utils/client';
import { handleError } from '../../../../app/utils/client';
import { callbacks } from '../../../../app/callbacks/client';
import { useSetting } from '../../../hooks/useSetting';
import { useTranslation } from '../../../hooks/useTranslation';
import { useSetupWizardStepsState } from '../StepsState';
import { Step } from '../Step';
import { StepHeader } from '../StepHeader';
import { Pager } from '../Pager';
import { StepContent } from '../StepContent';
import { loginWithPassword } from '../functions';
import { useFocus } from '../../../hooks/useFocus';
const registerAdminUser = async ({ name, username, email, password, onRegistrationEmailSent }) => {
await call('registerUser', { name, username, email, pass: password });
callbacks.run('userRegistered');
try {
await loginWithPassword(email, password);
} catch (error) {
if (error.error === 'error-invalid-email') {
onRegistrationEmailSent && onRegistrationEmailSent();
return;
}
throw error;
}
Session.set('forceLogin', false);
await call('setUsername', username);
callbacks.run('usernameSet');
};
export function AdminUserInformationStep({ step, title }) {
const { currentStep, goToNextStep } = useSetupWizardStepsState();
const active = step === currentStep;
const regexpForUsernameValidation = useSetting('UTF8_Names_Validation');
const usernameRegExp = useMemo(() => new RegExp(`^${ regexpForUsernameValidation }$`), [regexpForUsernameValidation]);
const emailRegExp = useMemo(() => /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]+$/i, []);
const [name, setName] = useState('');
const [username, setUsername] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [isNameValid, validateName] = useState(true);
const [isUsernameValid, validateUsername] = useState(true);
const [isEmailValid, validateEmail] = useState(true);
const [isPasswordValid, validatePassword] = useState(true);
const isContinueEnabled = useMemo(() => name && username && email && password, [name, username, email, password]);
const [commiting, setCommiting] = useState(false);
const validate = () => {
const isNameValid = !!name;
const isUsernameValid = !!username && usernameRegExp.test(username);
const isEmailValid = !!email && emailRegExp.test(email);
const isPasswordValid = !!password;
validateName(isNameValid);
validateUsername(isUsernameValid);
validateEmail(isEmailValid);
validatePassword(isPasswordValid);
return isNameValid && isUsernameValid && isEmailValid && isPasswordValid;
};
const t = useTranslation();
const autoFocusRef = useFocus(active);
const handleSubmit = async (event) => {
event.preventDefault();
const canRegisterAdminUser = validate();
if (!canRegisterAdminUser) {
return;
}
setCommiting(true);
try {
await registerAdminUser({
name,
username,
email,
password,
onRegistrationEmailSent: () => toastr.success(t('We_have_sent_registration_email')),
});
goToNextStep();
} catch (error) {
console.error(error);
handleError(error);
} finally {
setCommiting(false);
}
};
return <Step active={active} working={commiting} onSubmit={handleSubmit}>
<StepHeader number={step} title={title} />
<StepContent>
<InputGroup>
<Input
ref={autoFocusRef}
type='text'
label={t('Name')}
icon='user'
placeholder={t('Type_your_name')}
value={name}
onChange={({ currentTarget: { value } }) => setName(value)}
error={!isNameValid}
/>
<Input
type='text'
label={t('Username')}
icon='at'
placeholder={t('Type_your_username')}
value={username}
onChange={({ currentTarget: { value } }) => setUsername(value)}
error={!isUsernameValid && t('Invalid_username')}
/>
<Input
type='email'
label={t('Organization_Email')}
icon='mail'
placeholder={t('Type_your_email')}
value={email}
onChange={({ currentTarget: { value } }) => setEmail(value)}
error={!isEmailValid && t('Invalid_email')}
/>
<Input
type='password'
label={t('Password')}
icon='key'
placeholder={t('Type_your_password')}
value={password}
onChange={({ currentTarget: { value } }) => setPassword(value)}
error={!isPasswordValid}
/>
</InputGroup>
</StepContent>
<Pager disabled={commiting} isContinueEnabled={isContinueEnabled} />
</Step>;
}

@ -0,0 +1,81 @@
.SetupWizard__RegisterServerStep-text {
margin-bottom: 3rem;
color: var(--color-gray);
font-size: 1rem;
font-weight: 500;
line-height: 1.5rem;
}
.SetupWizard__RegisterServerStep-content {
display: flex;
flex-direction: column;
}
.SetupWizard__RegisterServerStep-option {
display: block;
padding: 1.5rem;
cursor: pointer;
color: var(--color-dark);
border: 2px solid var(--color-dark-10);
border-radius: 2px;
font-size: 0.875rem;
line-height: 1.25rem;
&:first-child {
margin-bottom: 1rem;
}
&--selected {
border-color: var(--rc-color-button-primary);
}
&--disabled {
opacity: 0.25;
}
}
.SetupWizard__RegisterServerStep-items {
margin: 1rem 0;
& + * {
margin-top: 1rem;
}
}
.SetupWizard__RegisterServerStep-item {
display: flex;
margin: 0 -0.5rem 0.5rem;
align-items: center;
&:last-child {
margin-bottom: 0;
}
& > .SetupWizard__RegisterServerStep-item-icon {
width: 20px;
min-width: 20px;
height: 20px;
margin: 0 0.5rem;
align-self: baseline;
&--check {
color: var(--rc-color-button-primary);
}
&--circle {
height: 6px;
margin: 7px 0.5rem;
}
}
}

@ -0,0 +1,152 @@
import { CheckBox, RadioButton } from '@rocket.chat/fuselage';
import React, { useState } from 'react';
import { call } from '../../../../app/ui-utils/client';
import { handleError } from '../../../../app/utils/client';
import { useTranslation } from '../../../hooks/useTranslation';
import { Icon } from '../../basic/Icon';
import { Pager } from '../Pager';
import { useSetupWizardParameters } from '../ParametersProvider';
import { Step } from '../Step';
import { StepContent } from '../StepContent';
import { StepHeader } from '../StepHeader';
import { useSetupWizardStepsState } from '../StepsState';
import { batchSetSettings } from '../functions';
import { useFocus } from '../../../hooks/useFocus';
const Option = React.forwardRef(({ children, label, selected, disabled, ...props }, ref) =>
<label
className={[
'SetupWizard__RegisterServerStep-option',
selected && 'SetupWizard__RegisterServerStep-option--selected',
disabled && 'SetupWizard__RegisterServerStep-option--disabled',
].filter(Boolean).join(' ')}
>
<RadioButton ref={ref} label={label} checked={selected} disabled={disabled} {...props} />
{children}
</label>
);
const Items = (props) => <ul className='SetupWizard__RegisterServerStep-items' {...props} />;
const Item = ({ children, icon, ...props }) =>
<li className='SetupWizard__RegisterServerStep-item' {...props}>
<Icon block='SetupWizard__RegisterServerStep-item-icon' icon={icon} />
{children}
</li>;
export function RegisterServerStep({ step, title }) {
const { canDeclineServerRegistration } = useSetupWizardParameters();
const { currentStep, goToPreviousStep, goToFinalStep } = useSetupWizardStepsState();
const active = step === currentStep;
const [registerServer, setRegisterServer] = useState(true);
const [optInMarketingEmails, setOptInMarketingEmails] = useState(true);
const t = useTranslation();
const [commiting, setComitting] = useState(false);
const handleBackClick = () => {
goToPreviousStep();
};
const handleSubmit = async (event) => {
event.preventDefault();
setComitting(true);
try {
await batchSetSettings([
{
_id: 'Statistics_reporting',
value: registerServer,
},
{
_id: 'Apps_Framework_enabled',
value: registerServer,
},
{
_id: 'Register_Server',
value: registerServer,
},
{
_id: 'Allow_Marketing_Emails',
value: optInMarketingEmails,
},
]);
if (registerServer) {
await call('cloud:registerWorkspace');
}
setComitting(false);
goToFinalStep();
} catch (error) {
console.error(error);
handleError(error);
setComitting(false);
}
};
const autoFocusRef = useFocus(active);
return <Step active={active} working={commiting} onSubmit={handleSubmit}>
<StepHeader number={step} title={title} />
<StepContent>
<p className='SetupWizard__RegisterServerStep-text'>{t('Register_Server_Info')}</p>
<div className='SetupWizard__RegisterServerStep-content'>
<Option
ref={autoFocusRef}
label={t('Register_Server_Registered')}
name='registerServer'
value='true'
selected={registerServer}
onChange={({ currentTarget: { checked } }) => {
setRegisterServer(checked);
setOptInMarketingEmails(checked);
}}
>
<Items>
<Item icon='check'>{t('Register_Server_Registered_Push_Notifications')}</Item>
<Item icon='check'>{t('Register_Server_Registered_Livechat')}</Item>
<Item icon='check'>{t('Register_Server_Registered_OAuth')}</Item>
<Item icon='check'>{t('Register_Server_Registered_Marketplace')}</Item>
</Items>
<CheckBox
name='optInMarketingEmails'
value='true'
label={t('Register_Server_Opt_In')}
disabled={!registerServer}
checked={optInMarketingEmails}
onChange={({ currentTarget: { checked } }) => {
setOptInMarketingEmails(checked);
}}
/>
</Option>
<Option
label={t('Register_Server_Standalone')}
name='registerServer'
value='false'
disabled={!canDeclineServerRegistration}
selected={!registerServer}
onChange={({ currentTarget: { checked } }) => {
setRegisterServer(!checked);
setOptInMarketingEmails(!checked);
}}
>
<Items>
<Item icon='circle'>{t('Register_Server_Standalone_Service_Providers')}</Item>
<Item icon='circle'>{t('Register_Server_Standalone_Update_Settings')}</Item>
<Item icon='circle'>{t('Register_Server_Standalone_Own_Certificates')}</Item>
</Items>
</Option>
</div>
</StepContent>
<Pager disabled={commiting} onBackClick={handleBackClick} />
</Step>;
}

@ -0,0 +1,141 @@
import { Input, InputGroup } from '@rocket.chat/fuselage';
import { TAPi18n } from 'meteor/rocketchat:tap-i18n';
import React, { Fragment, useEffect, useReducer, useState } from 'react';
import { handleError } from '../../../../app/utils/client';
import { useTranslation } from '../../../hooks/useTranslation';
import { useReactiveValue } from '../../../hooks/useReactiveValue';
import { Pager } from '../Pager';
import { useSetupWizardParameters } from '../ParametersProvider';
import { useSetupWizardStepsState } from '../StepsState';
import { Step } from '../Step';
import { StepHeader } from '../StepHeader';
import { StepContent } from '../StepContent';
import { batchSetSettings } from '../functions';
import { useFocus } from '../../../hooks/useFocus';
const useFields = () => {
const reset = 'RESET';
const setValue = 'SET_VALUE';
const [fields, dispatch] = useReducer((fields, { type, payload }) => {
if (type === reset) {
return payload;
}
if (type === setValue) {
const { _id, value } = payload;
return fields.map((field) => (field._id === _id ? { ...field, value } : field));
}
return fields;
}, []);
const resetFields = (fields) => dispatch({ type: reset, payload: fields });
const setFieldValue = (_id, value) => dispatch({ type: setValue, payload: { _id, value } });
return { fields, resetFields, setFieldValue };
};
export function SettingsBasedStep({ step, title }) {
const { settings } = useSetupWizardParameters();
const { currentStep, goToPreviousStep, goToNextStep } = useSetupWizardStepsState();
const { fields, resetFields, setFieldValue } = useFields();
const [commiting, setCommiting] = useState(false);
const active = step === currentStep;
const languages = useReactiveValue(() => TAPi18n.getLanguages(), []);
useEffect(() => {
resetFields(
settings
.filter(({ wizard }) => wizard.step === step)
.filter(({ type }) => ['string', 'select', 'language'].includes(type))
.sort(({ wizard: { order: a } }, { wizard: { order: b } }) => a - b)
.map(({ value, ...field }) => ({ ...field, value: value || '' }))
);
}, [settings, currentStep]);
const t = useTranslation();
const handleBackClick = () => {
goToPreviousStep();
};
const handleSubmit = async (event) => {
event.preventDefault();
setCommiting(true);
try {
await batchSetSettings(fields.map(({ _id, value }) => ({ _id, value })));
goToNextStep();
} catch (error) {
console.error(error);
handleError(error);
} finally {
setCommiting(false);
}
};
const autoFocusRef = useFocus(active);
return <Step active={active} working={commiting} onSubmit={handleSubmit}>
<StepHeader number={step} title={title} />
<StepContent>
<InputGroup>
{fields.map(({ _id, type, i18nLabel, value, values }, i) =>
<Fragment key={i}>
{type === 'string'
&& <Input
type='text'
label={t(i18nLabel)}
name={_id}
ref={i === 0 ? autoFocusRef : undefined}
value={value}
onChange={({ currentTarget: { value } }) => setFieldValue(_id, value)}
/>}
{type === 'select'
&& <Input
type='select'
label={t(i18nLabel)}
name={_id}
placeholder={t('Select_an_option')}
ref={i === 0 ? autoFocusRef : undefined}
value={value}
onChange={({ currentTarget: { value } }) => setFieldValue(_id, value)}
>
{values
.map(({ i18nLabel, key }) => ({ label: t(i18nLabel), value: key }))
.map(({ label, value }) => <option key={value} value={value}>{label}</option>)}
</Input>}
{type === 'language'
&& <Input
type='select'
label={t(i18nLabel)}
name={_id}
placeholder={t('Default')}
ref={i === 0 ? autoFocusRef : undefined}
value={value}
onChange={({ currentTarget: { value } }) => setFieldValue(_id, value)}
>
{Object.entries(languages)
.map(([key, { name }]) => ({ label: name, value: key }))
.sort((a, b) => a.key - b.key)
.map(({ label, value }) => <option key={value} value={value}>{label}</option>)}
</Input>}
</Fragment>
)}
</InputGroup>
</StepContent>
<Pager
disabled={commiting}
onBackClick={currentStep > 2 && handleBackClick}
/>
</Step>;
}

@ -0,0 +1,15 @@
import { useEffect, useState } from 'react';
export const useFocus = (isFocused) => {
const [element, setElement] = useState(null);
useEffect(() => {
if (isFocused && element) {
element.focus();
}
}, [element, isFocused]);
return (ref) => {
setElement(ref);
};
};

@ -0,0 +1,19 @@
import { Tracker } from 'meteor/tracker';
import { useEffect, useState } from 'react';
export const useReactiveValue = (getValue, deps = []) => {
const [value, setValue] = useState(getValue);
useEffect(() => {
const computation = Tracker.autorun(() => {
const newValue = getValue();
setValue(() => newValue);
});
return () => {
computation.stop();
};
}, deps);
return value;
};

@ -0,0 +1,5 @@
import { Session } from 'meteor/session';
import { useReactiveValue } from './useReactiveValue';
export const useSession = (variableName) => useReactiveValue(() => Session.get(variableName));

@ -0,0 +1,4 @@
import { settings } from '../../app/settings/client';
import { useReactiveValue } from './useReactiveValue';
export const useSetting = (settingName) => useReactiveValue(() => settings.get(settingName));

@ -0,0 +1,21 @@
import { TAPi18n } from 'meteor/rocketchat:tap-i18n';
import { Tracker } from 'meteor/tracker';
import { useReactiveValue } from './useReactiveValue';
const translator = (key, ...replaces) => Tracker.nonreactive(() => {
if (typeof replaces[0] === 'object') {
return TAPi18n.__(key, ...replaces);
}
return TAPi18n.__(key, {
postProcess: 'sprintf',
sprintf: replaces,
});
});
export const useTranslation = () => {
useReactiveValue(() => TAPi18n.getLanguage());
return translator;
};

@ -0,0 +1,5 @@
import { Meteor } from 'meteor/meteor';
import { useReactiveValue } from './useReactiveValue';
export const useUserId = () => useReactiveValue(() => Meteor.userId());

@ -0,0 +1,17 @@
import { useLayoutEffect } from 'react';
export const useWipeInitialPageLoading = () => {
useLayoutEffect(() => {
const initialPageLoadingElement = document.getElementById('initial-page-loading');
if (!initialPageLoadingElement) {
return;
}
initialPageLoadingElement.style.display = 'none';
return () => {
initialPageLoadingElement.style.display = 'flex';
};
}, []);
};

@ -54,7 +54,6 @@ import '../app/oembed/client';
import '../app/otr/client';
import '../app/push-notifications/client';
import '../app/apps/client';
import '../app/setup-wizard/client';
import '../app/slackbridge/client';
import '../app/slashcommands-archiveroom/client';
import '../app/slashcommand-asciiarts/client';

@ -1,4 +1,4 @@
import './RocketChat.font.css';
import '../app/chatpal-search/client/style.css';
import '../app/theme/client/main.css';
import '../app/theme/client/vendor/photoswipe.css';

@ -21,7 +21,6 @@ import './notifications/updateAvatar';
import './notifications/updateUserState';
import './notifications/UsersNameChanged';
import './routes/adminRouter';
import './routes/pageNotFound';
import './routes/roomRoute';
import './routes/router';
import './startup/emailVerification';

@ -1,9 +0,0 @@
<template name="pageNotFound">
<section class = "page-not-found-container content-background-color">
<span class = "error-404">404</span>
<span class = "page-not-found-message">{{_ "Oops_page_not_found"}}</span>
<span class = "page-not-found-description">{{_ "Sorry_page_you_requested_does_not_exists_or_was_deleted"}}</span>
<button class = "page-not-found-button page-not-found-button-previous rc-button rc-button--primary">{{_ "Return_to_previous_page"}}</button>
<button class = "page-not-found-button page-not-found-button-home rc-button rc-button--primary">{{_ "Return_to_home"}}</button>
</section>
</template>

@ -1,22 +0,0 @@
import { Template } from 'meteor/templating';
import { FlowRouter } from 'meteor/kadira:flow-router';
import './pageNotFound.html';
Template.pageNotFound.onRendered(function() {
const parent = document.querySelector('.page-loading');
const child = document.querySelector('.loading-animation');
parent.removeChild(child);
});
Template.pageNotFound.events({
'click .page-not-found-button-home'(e) {
e.preventDefault();
FlowRouter.go('home');
},
'click .page-not-found-button-previous'(e) {
e.preventDefault();
window.history.back();
},
});

@ -3,8 +3,10 @@ import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/accounts-base';
import { Tracker } from 'meteor/tracker';
import { Blaze } from 'meteor/blaze';
import { HTML } from 'meteor/htmljs';
import { FlowRouter } from 'meteor/kadira:flow-router';
import { BlazeLayout } from 'meteor/kadira:blaze-layout';
import { Template } from 'meteor/templating';
import { Session } from 'meteor/session';
import { KonchatNotification } from '../../app/ui';
@ -15,6 +17,42 @@ Blaze.registerHelper('pathFor', function(path, kw) {
BlazeLayout.setRoot('body');
const createTemplateForComponent = async (
component,
props = {},
// eslint-disable-next-line new-cap
renderContainerView = () => HTML.DIV()
) => {
const React = await import('react');
const ReactDOM = await import('react-dom');
const name = component.displayName || component.name;
if (!name) {
throw new Error('the component must have a name');
}
Template[name] = new Blaze.Template(name, renderContainerView);
Template[name].onRendered(() => {
Template.instance().autorun((computation) => {
if (computation.firstRun) {
Template.instance().container = Template.instance().firstNode;
}
ReactDOM.render(React.createElement(component, props), Template.instance().firstNode);
});
});
Template[name].onDestroyed(() => {
if (Template.instance().container) {
ReactDOM.unmountComponentAtNode(Template.instance().container);
}
});
return name;
};
FlowRouter.subscriptions = function() {
Tracker.autorun(() => {
if (Meteor.userId()) {
@ -137,14 +175,6 @@ FlowRouter.route('/room-not-found/:type/:name', {
},
});
FlowRouter.route('/fxos', {
name: 'firefox-os-install',
action() {
BlazeLayout.render('fxOsInstallPrompt');
},
});
FlowRouter.route('/register/:hash', {
name: 'register-secret-url',
@ -164,24 +194,17 @@ FlowRouter.route('/register/:hash', {
},
});
FlowRouter.route('/setup-wizard', {
FlowRouter.route('/setup-wizard/:step?', {
name: 'setup-wizard',
action() {
BlazeLayout.render('setupWizard');
},
});
FlowRouter.route('/setup-wizard/final', {
name: 'setup-wizard-final',
action() {
BlazeLayout.render('setupWizardFinal');
action: async () => {
const { SetupWizard } = await import('../components/setupWizard/SetupWizard');
BlazeLayout.render(await createTemplateForComponent(SetupWizard));
},
});
FlowRouter.notFound = {
action() {
BlazeLayout.render('pageNotFound');
action: async () => {
const { PageNotFound } = await import('../components/pageNotFound/PageNotFound');
BlazeLayout.render(await createTemplateForComponent(PageNotFound));
},
};

@ -1,48 +0,0 @@
.page-not-found-container {
width: 100%;
height: 100%;
padding: 10%;
text-align: center;
color: white;
background-image: url("/images/404.svg");
background-repeat: no-repeat;
background-position: center;
background-size: cover;
.error-404 {
display: block;
padding: 10px;
font-size: 4em;
font-weight: bold;
}
.page-not-found-message {
display: block;
padding: 10px;
font-size: 2em;
font-weight: bold;
}
.page-not-found-description {
display: block;
padding: 10px;
font-size: 1em;
}
.page-not-found-button {
display: inline-block;
margin: 20px 10px 0;
padding: 8px 16px;
font-size: 1em;
}
}

322
package-lock.json generated

@ -702,6 +702,19 @@
"eslint-plugin-import": "^2.17.2"
}
},
"@rocket.chat/fuselage": {
"version": "0.2.0-alpha.2",
"resolved": "https://registry.npmjs.org/@rocket.chat/fuselage/-/fuselage-0.2.0-alpha.2.tgz",
"integrity": "sha512-fAGRMPGvluQAxwUCWmgn28anFT0NPsKEzM1yYOdo1xPbYbs48QKg6f9aUgNEAAqpviw58AKq8d/re8KPjzEYLw==",
"requires": {
"@rocket.chat/icons": "^0.2.0-alpha.0"
}
},
"@rocket.chat/icons": {
"version": "0.2.0-alpha.0",
"resolved": "https://registry.npmjs.org/@rocket.chat/icons/-/icons-0.2.0-alpha.0.tgz",
"integrity": "sha512-7bzc7frrOfSypD/QvJ+eBfiD5XZSpxzN8taaOB2g0AHDUYcS/yIDpZLRH0Eq0fVe4A4gXsg0MRgcU0cJzuXQ+g=="
},
"@rocket.chat/livechat": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/@rocket.chat/livechat/-/livechat-1.1.6.tgz",
@ -882,7 +895,7 @@
},
"@types/events": {
"version": "1.2.0",
"resolved": "http://registry.npmjs.org/@types/events/-/events-1.2.0.tgz",
"resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz",
"integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA=="
},
"@types/express": {
@ -1859,7 +1872,7 @@
},
"axios": {
"version": "0.18.0",
"resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
"integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=",
"requires": {
"follow-redirects": "^1.3.0",
@ -2197,7 +2210,7 @@
},
"babel-plugin-add-module-exports": {
"version": "0.2.1",
"resolved": "http://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz",
"resolved": "https://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz",
"integrity": "sha1-mumh9KjcZ/DN7E9K7aHkOl/2XiU=",
"dev": true
},
@ -2218,79 +2231,79 @@
},
"babel-plugin-syntax-async-functions": {
"version": "6.13.0",
"resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
"integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=",
"dev": true
},
"babel-plugin-syntax-async-generators": {
"version": "6.13.0",
"resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz",
"integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=",
"dev": true
},
"babel-plugin-syntax-class-constructor-call": {
"version": "6.18.0",
"resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz",
"integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=",
"dev": true
},
"babel-plugin-syntax-class-properties": {
"version": "6.13.0",
"resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
"integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=",
"dev": true
},
"babel-plugin-syntax-decorators": {
"version": "6.13.0",
"resolved": "http://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz",
"integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=",
"dev": true
},
"babel-plugin-syntax-do-expressions": {
"version": "6.13.0",
"resolved": "http://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz",
"integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=",
"dev": true
},
"babel-plugin-syntax-dynamic-import": {
"version": "6.18.0",
"resolved": "http://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
"integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=",
"dev": true
},
"babel-plugin-syntax-exponentiation-operator": {
"version": "6.13.0",
"resolved": "http://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
"integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=",
"dev": true
},
"babel-plugin-syntax-export-extensions": {
"version": "6.13.0",
"resolved": "http://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz",
"integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=",
"dev": true
},
"babel-plugin-syntax-flow": {
"version": "6.18.0",
"resolved": "http://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz",
"integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=",
"dev": true
},
"babel-plugin-syntax-function-bind": {
"version": "6.13.0",
"resolved": "http://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz",
"integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=",
"dev": true
},
"babel-plugin-syntax-jsx": {
"version": "6.18.0",
"resolved": "http://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
"integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=",
"dev": true
},
"babel-plugin-syntax-object-rest-spread": {
"version": "6.13.0",
"resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
"integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=",
"dev": true
},
@ -2687,7 +2700,7 @@
},
"babel-preset-es2015": {
"version": "6.3.13",
"resolved": "http://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.3.13.tgz",
"resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.3.13.tgz",
"integrity": "sha1-l9zn7ykuGMubK3VF2AxZPCjZUX8=",
"dev": true,
"requires": {
@ -2715,7 +2728,7 @@
},
"babel-preset-react": {
"version": "6.3.13",
"resolved": "http://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.3.13.tgz",
"resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.3.13.tgz",
"integrity": "sha1-E9VeBqZfqqoHw5v2Op2DbgMhFvo=",
"dev": true,
"requires": {
@ -2729,7 +2742,7 @@
},
"babel-preset-stage-0": {
"version": "6.3.13",
"resolved": "http://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.3.13.tgz",
"resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.3.13.tgz",
"integrity": "sha1-eKN8VvCzmI8qeZMtywzrj/N3sNE=",
"dev": true,
"requires": {
@ -3636,7 +3649,7 @@
},
"bl": {
"version": "1.2.2",
"resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
"integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
"requires": {
"readable-stream": "^2.3.5",
@ -4020,7 +4033,7 @@
},
"readable-stream": {
"version": "1.1.14",
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "~1.0.0",
@ -4386,7 +4399,7 @@
},
"chalk": {
"version": "1.1.3",
"resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
"requires": {
"ansi-styles": "^2.2.1",
@ -4489,7 +4502,7 @@
},
"chimp": {
"version": "0.51.1",
"resolved": "http://registry.npmjs.org/chimp/-/chimp-0.51.1.tgz",
"resolved": "https://registry.npmjs.org/chimp/-/chimp-0.51.1.tgz",
"integrity": "sha1-6hIbzfJsidV/jvNBlUDPPCeaPMU=",
"dev": true,
"requires": {
@ -4535,7 +4548,7 @@
"dependencies": {
"async": {
"version": "0.9.2",
"resolved": "http://registry.npmjs.org/async/-/async-0.9.2.tgz",
"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
"integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=",
"dev": true
},
@ -4607,7 +4620,7 @@
},
"minimist": {
"version": "1.2.0",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true
},
@ -4659,7 +4672,7 @@
},
"progress": {
"version": "1.1.8",
"resolved": "http://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
"resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
"integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=",
"dev": true
},
@ -4682,7 +4695,7 @@
},
"chokidar": {
"version": "1.6.1",
"resolved": "http://registry.npmjs.org/chokidar/-/chokidar-1.6.1.tgz",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.6.1.tgz",
"integrity": "sha1-L0RHq16W5Q+z14n9kNTHLg5McMI=",
"dev": true,
"requires": {
@ -5448,7 +5461,7 @@
"dependencies": {
"core-js": {
"version": "1.2.7",
"resolved": "http://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
"integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
}
}
@ -5848,7 +5861,7 @@
"dependencies": {
"pify": {
"version": "2.3.0",
"resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
"dev": true
}
@ -5878,7 +5891,7 @@
},
"deprecate": {
"version": "1.0.0",
"resolved": "http://registry.npmjs.org/deprecate/-/deprecate-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/deprecate/-/deprecate-1.0.0.tgz",
"integrity": "sha1-ZhSQ7SQokWpsiIPYg05WRvTkpKg="
},
"deprecated-decorator": {
@ -5936,7 +5949,7 @@
},
"readable-stream": {
"version": "1.1.14",
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "~1.0.0",
@ -6003,7 +6016,7 @@
"dependencies": {
"domelementtype": {
"version": "1.1.3",
"resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
"integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs="
}
}
@ -6381,7 +6394,7 @@
},
"es6-promisify": {
"version": "5.0.0",
"resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
"resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
"integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
"requires": {
"es6-promise": "^4.0.3"
@ -6717,6 +6730,67 @@
}
}
},
"eslint-plugin-react": {
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.14.3.tgz",
"integrity": "sha512-EzdyyBWC4Uz2hPYBiEJrKCUi2Fn+BJ9B/pJQcjw5X+x/H2Nm59S4MJIvL4O5NEE0+WbnQwEBxWY03oUk+Bc3FA==",
"dev": true,
"requires": {
"array-includes": "^3.0.3",
"doctrine": "^2.1.0",
"has": "^1.0.3",
"jsx-ast-utils": "^2.1.0",
"object.entries": "^1.1.0",
"object.fromentries": "^2.0.0",
"object.values": "^1.1.0",
"prop-types": "^15.7.2",
"resolve": "^1.10.1"
},
"dependencies": {
"doctrine": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
"integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
"dev": true,
"requires": {
"esutils": "^2.0.2"
}
},
"object.entries": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz",
"integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==",
"dev": true,
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.12.0",
"function-bind": "^1.1.1",
"has": "^1.0.3"
}
},
"object.values": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz",
"integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==",
"dev": true,
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.12.0",
"function-bind": "^1.1.1",
"has": "^1.0.3"
}
},
"resolve": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",
"integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==",
"dev": true,
"requires": {
"path-parse": "^1.0.6"
}
}
}
},
"eslint-scope": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz",
@ -6822,7 +6896,7 @@
},
"events": {
"version": "1.1.1",
"resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz",
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
"integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
},
"evp_bytestokey": {
@ -7240,7 +7314,7 @@
},
"external-editor": {
"version": "2.2.0",
"resolved": "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
"integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
"dev": true,
"requires": {
@ -7410,13 +7484,13 @@
"dependencies": {
"lodash": {
"version": "2.4.2",
"resolved": "http://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
"integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=",
"dev": true
},
"underscore.string": {
"version": "2.3.3",
"resolved": "http://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz",
"resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz",
"integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=",
"dev": true
}
@ -8597,7 +8671,7 @@
"dependencies": {
"minimist": {
"version": "1.1.3",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.1.3.tgz",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.3.tgz",
"integrity": "sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag=",
"dev": true
}
@ -9452,7 +9526,7 @@
},
"hapi": {
"version": "8.8.0",
"resolved": "http://registry.npmjs.org/hapi/-/hapi-8.8.0.tgz",
"resolved": "https://registry.npmjs.org/hapi/-/hapi-8.8.0.tgz",
"integrity": "sha1-h+N6Bum0meiXkOLcERqpZotuYX8=",
"dev": true,
"requires": {
@ -9522,7 +9596,7 @@
},
"catbox": {
"version": "4.3.0",
"resolved": "http://registry.npmjs.org/catbox/-/catbox-4.3.0.tgz",
"resolved": "https://registry.npmjs.org/catbox/-/catbox-4.3.0.tgz",
"integrity": "sha1-IiN3vWfxKRrA4l0AAC0GWp3385o=",
"dev": true,
"requires": {
@ -9619,7 +9693,7 @@
},
"joi": {
"version": "6.4.1",
"resolved": "http://registry.npmjs.org/joi/-/joi-6.4.1.tgz",
"resolved": "https://registry.npmjs.org/joi/-/joi-6.4.1.tgz",
"integrity": "sha1-9Q9CRTVgBo5jg9oVrC0w3Xzra24=",
"dev": true,
"requires": {
@ -9631,7 +9705,7 @@
"dependencies": {
"isemail": {
"version": "1.1.1",
"resolved": "http://registry.npmjs.org/isemail/-/isemail-1.1.1.tgz",
"resolved": "https://registry.npmjs.org/isemail/-/isemail-1.1.1.tgz",
"integrity": "sha1-4Mj23D9HCX53dzlcaJYnGqJWw7U=",
"dev": true
},
@ -9664,7 +9738,7 @@
"dependencies": {
"mime-db": {
"version": "1.14.0",
"resolved": "http://registry.npmjs.org/mime-db/-/mime-db-1.14.0.tgz",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.14.0.tgz",
"integrity": "sha1-1WHxC27mbbUflK5leilRp0IX7YM=",
"dev": true
}
@ -10405,7 +10479,7 @@
},
"readable-stream": {
"version": "1.1.14",
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "~1.0.0",
@ -10757,7 +10831,7 @@
},
"is-builtin-module": {
"version": "1.0.0",
"resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
"integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
"dev": true,
"requires": {
@ -10924,7 +10998,7 @@
},
"is-obj": {
"version": "1.0.1",
"resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
},
"is-object": {
@ -11097,7 +11171,7 @@
},
"isemail": {
"version": "1.2.0",
"resolved": "http://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz",
"resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz",
"integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo="
},
"isexe": {
@ -11133,7 +11207,7 @@
},
"jasmine-core": {
"version": "2.99.1",
"resolved": "http://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz",
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz",
"integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU=",
"dev": true
},
@ -11215,8 +11289,7 @@
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
},
"js-yaml": {
"version": "3.12.0",
@ -11339,7 +11412,7 @@
},
"jsonfile": {
"version": "2.4.0",
"resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
"integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
"dev": true,
"requires": {
@ -11402,6 +11475,16 @@
"resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-8.0.12.tgz",
"integrity": "sha1-Iqu5ZW00owuVMENnIINeicLlwxY="
},
"jsx-ast-utils": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.2.1.tgz",
"integrity": "sha512-v3FxCcAf20DayI+uxnCuw795+oOIkVu6EnJ1+kSzhqqTZHNkTZ7B66ZgLp4oLJ/gbA64cI0B7WRoHZMSRdyVRQ==",
"dev": true,
"requires": {
"array-includes": "^3.0.3",
"object.assign": "^4.1.0"
}
},
"juice": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/juice/-/juice-5.2.0.tgz",
@ -11632,7 +11715,7 @@
},
"promise": {
"version": "6.1.0",
"resolved": "http://registry.npmjs.org/promise/-/promise-6.1.0.tgz",
"resolved": "https://registry.npmjs.org/promise/-/promise-6.1.0.tgz",
"integrity": "sha1-LOcp9rlLRcJoka0GAsXJDgTG7vY=",
"optional": true,
"requires": {
@ -12095,7 +12178,6 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"dev": true,
"requires": {
"js-tokens": "^3.0.0 || ^4.0.0"
}
@ -12304,7 +12386,7 @@
},
"media-typer": {
"version": "0.3.0",
"resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"mem": {
@ -12813,14 +12895,14 @@
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
},
"minimist-options": {
@ -12908,7 +12990,7 @@
},
"mkdirp": {
"version": "0.5.1",
"resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"requires": {
"minimist": "0.0.8"
@ -13345,7 +13427,7 @@
},
"ncp": {
"version": "2.0.0",
"resolved": "http://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
"integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=",
"optional": true
},
@ -13715,7 +13797,7 @@
},
"npm-install-package": {
"version": "2.1.0",
"resolved": "http://registry.npmjs.org/npm-install-package/-/npm-install-package-2.1.0.tgz",
"resolved": "https://registry.npmjs.org/npm-install-package/-/npm-install-package-2.1.0.tgz",
"integrity": "sha1-1+/jz816sAYUuJbqUxGdyaslkSU=",
"dev": true
},
@ -13730,7 +13812,7 @@
"npmlog": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=",
"requires": {
"are-we-there-yet": "~1.1.2",
"console-control-strings": "~1.1.0",
@ -13840,6 +13922,18 @@
"has": "^1.0.1"
}
},
"object.fromentries": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.0.tgz",
"integrity": "sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA==",
"dev": true,
"requires": {
"define-properties": "^1.1.2",
"es-abstract": "^1.11.0",
"function-bind": "^1.1.1",
"has": "^1.0.1"
}
},
"object.getownpropertydescriptors": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
@ -13969,7 +14063,7 @@
},
"os-locale": {
"version": "1.4.0",
"resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
"integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
"requires": {
"lcid": "^1.0.0"
@ -14302,7 +14396,7 @@
},
"es6-promise": {
"version": "4.0.5",
"resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-4.0.5.tgz",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.0.5.tgz",
"integrity": "sha1-eILzCt3lskDM+n99eMVIMwlRrkI=",
"dev": true
},
@ -14358,7 +14452,7 @@
},
"progress": {
"version": "1.1.8",
"resolved": "http://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
"resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
"integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=",
"dev": true
},
@ -15352,6 +15446,16 @@
"integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
"dev": true
},
"prop-types": {
"version": "15.7.2",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
"requires": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
"react-is": "^16.8.1"
}
},
"protobufjs": {
"version": "6.8.8",
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.8.tgz",
@ -15596,11 +15700,38 @@
"dependencies": {
"minimist": {
"version": "1.2.0",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
}
}
},
"react": {
"version": "16.8.6",
"resolved": "https://registry.npmjs.org/react/-/react-16.8.6.tgz",
"integrity": "sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw==",
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"prop-types": "^15.6.2",
"scheduler": "^0.13.6"
}
},
"react-dom": {
"version": "16.8.6",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.6.tgz",
"integrity": "sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA==",
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"prop-types": "^15.6.2",
"scheduler": "^0.13.6"
}
},
"react-is": {
"version": "16.8.6",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz",
"integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA=="
},
"read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@ -15612,7 +15743,7 @@
"dependencies": {
"pify": {
"version": "2.3.0",
"resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
"dev": true
}
@ -15646,7 +15777,7 @@
},
"pify": {
"version": "2.3.0",
"resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
"dev": true
}
@ -15709,7 +15840,7 @@
},
"readable-stream": {
"version": "2.3.6",
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"requires": {
"core-util-is": "~1.0.0",
@ -15847,7 +15978,7 @@
},
"regjsgen": {
"version": "0.2.0",
"resolved": "http://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
"resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
"integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
"dev": true
},
@ -16039,7 +16170,7 @@
},
"requestretry": {
"version": "1.5.0",
"resolved": "http://registry.npmjs.org/requestretry/-/requestretry-1.5.0.tgz",
"resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.5.0.tgz",
"integrity": "sha1-7RV7ulNSbt6z7DKo5wSkmYvs5ic=",
"dev": true,
"requires": {
@ -16171,7 +16302,7 @@
},
"rimraf": {
"version": "2.4.5",
"resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz",
"integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=",
"requires": {
"glob": "^6.0.1"
@ -16266,7 +16397,7 @@
},
"safe-regex": {
"version": "1.1.0",
"resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
"requires": {
"ret": "~0.1.10"
@ -16297,7 +16428,7 @@
},
"sax": {
"version": "1.2.1",
"resolved": "http://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
"integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o="
},
"scandirectory": {
@ -16311,6 +16442,15 @@
"taskgroup": "^4.0.5"
}
},
"scheduler": {
"version": "0.13.6",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz",
"integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==",
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1"
}
},
"schema-inspector": {
"version": "1.6.8",
"resolved": "https://registry.npmjs.org/schema-inspector/-/schema-inspector-1.6.8.tgz",
@ -16321,7 +16461,7 @@
"dependencies": {
"async": {
"version": "1.5.2",
"resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz",
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo="
}
}
@ -16406,7 +16546,7 @@
},
"minimist": {
"version": "1.2.0",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true
},
@ -17148,7 +17288,7 @@
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"requires": {
"ansi-regex": "^2.0.0"
@ -17725,7 +17865,7 @@
},
"through": {
"version": "2.3.8",
"resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
"dev": true
},
@ -18521,7 +18661,7 @@
"dependencies": {
"semver": {
"version": "5.3.0",
"resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
"integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
}
}
@ -19190,7 +19330,7 @@
},
"wrap-ansi": {
"version": "2.1.0",
"resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
"requires": {
"string-width": "^1.0.1",
@ -19294,7 +19434,7 @@
},
"xolvio-ddp": {
"version": "0.12.3",
"resolved": "http://registry.npmjs.org/xolvio-ddp/-/xolvio-ddp-0.12.3.tgz",
"resolved": "https://registry.npmjs.org/xolvio-ddp/-/xolvio-ddp-0.12.3.tgz",
"integrity": "sha1-NqarlhKyQLWg0cCoNJCK8XwLjwI=",
"dev": true,
"requires": {
@ -19319,7 +19459,7 @@
},
"async": {
"version": "0.9.2",
"resolved": "http://registry.npmjs.org/async/-/async-0.9.2.tgz",
"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
"integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=",
"dev": true
},
@ -19331,7 +19471,7 @@
},
"bl": {
"version": "0.9.5",
"resolved": "http://registry.npmjs.org/bl/-/bl-0.9.5.tgz",
"resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz",
"integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=",
"dev": true,
"requires": {
@ -19340,7 +19480,7 @@
},
"bluebird": {
"version": "2.11.0",
"resolved": "http://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz",
"integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=",
"dev": true
},
@ -19352,7 +19492,7 @@
},
"combined-stream": {
"version": "0.0.7",
"resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz",
"integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=",
"dev": true,
"requires": {
@ -19373,7 +19513,7 @@
},
"form-data": {
"version": "0.2.0",
"resolved": "http://registry.npmjs.org/form-data/-/form-data-0.2.0.tgz",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-0.2.0.tgz",
"integrity": "sha1-Jvi8JtpkQOKZy9z7aQNcT3em5GY=",
"dev": true,
"requires": {
@ -19413,13 +19553,13 @@
},
"mime-db": {
"version": "1.12.0",
"resolved": "http://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz",
"integrity": "sha1-PQxjGA9FjrENMlqqN9fFiuMS6dc=",
"dev": true
},
"mime-types": {
"version": "2.0.14",
"resolved": "http://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz",
"integrity": "sha1-MQ4VnbI+B3+Lsit0jav6SVcUCqY=",
"dev": true,
"requires": {
@ -19446,7 +19586,7 @@
},
"readable-stream": {
"version": "1.0.34",
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
"integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
"dev": true,
"requires": {
@ -19458,7 +19598,7 @@
},
"request": {
"version": "2.53.0",
"resolved": "http://registry.npmjs.org/request/-/request-2.53.0.tgz",
"resolved": "https://registry.npmjs.org/request/-/request-2.53.0.tgz",
"integrity": "sha1-GAo66St7Y5gC5PlUXdj83rcddgw=",
"dev": true,
"requires": {
@ -19497,7 +19637,7 @@
},
"xolvio-fiber-utils": {
"version": "2.0.3",
"resolved": "http://registry.npmjs.org/xolvio-fiber-utils/-/xolvio-fiber-utils-2.0.3.tgz",
"resolved": "https://registry.npmjs.org/xolvio-fiber-utils/-/xolvio-fiber-utils-2.0.3.tgz",
"integrity": "sha1-vsjXDHQGGjFjFbun0w0lyz6C3FA=",
"dev": true,
"requires": {
@ -19515,7 +19655,7 @@
},
"xolvio-jasmine-expect": {
"version": "1.1.0",
"resolved": "http://registry.npmjs.org/xolvio-jasmine-expect/-/xolvio-jasmine-expect-1.1.0.tgz",
"resolved": "https://registry.npmjs.org/xolvio-jasmine-expect/-/xolvio-jasmine-expect-1.1.0.tgz",
"integrity": "sha1-vCud1ghCMR8EV59agtzqaisxnH0=",
"dev": true,
"requires": {
@ -19582,7 +19722,7 @@
},
"yargs": {
"version": "3.32.0",
"resolved": "http://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz",
"integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=",
"requires": {
"camelcase": "^2.0.1",

@ -104,12 +104,13 @@
"chimp": "^0.51.1",
"emojione-assets": "^4.5.0",
"eslint": "^5.9.0",
"eslint-plugin-react": "^7.14.3",
"fast-glob": "^2.2.6",
"husky": "^1.2.0",
"mocha": "^5.2.0",
"mock-require": "^3.0.2",
"node-sprite-generator": "^0.10.2",
"mongo-unit": "^1.4.4",
"node-sprite-generator": "^0.10.2",
"postcss": "^7.0.6",
"postcss-custom-properties": "^8.0.9",
"postcss-easy-import": "^3.0.0",
@ -135,6 +136,8 @@
"@google-cloud/storage": "^2.3.1",
"@google-cloud/vision": "^0.23.0",
"@rocket.chat/apps-engine": "^1.5.2",
"@rocket.chat/fuselage": "^0.2.0-alpha.2",
"@rocket.chat/icons": "^0.2.0-alpha.0",
"@slack/client": "^4.8.0",
"adm-zip": "^0.4.13",
"apollo-server-express": "^1.3.6",
@ -214,6 +217,8 @@
"prom-client": "^11.2.0",
"querystring": "^0.2.0",
"queue-fifo": "^0.2.5",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"redis": "^2.8.0",
"semver": "^5.6.0",
"sharp": "^0.22.1",

@ -0,0 +1 @@
../../node_modules/@rocket.chat/icons/dist/font/RocketChat.eot

@ -0,0 +1 @@
../../node_modules/@rocket.chat/icons/dist/font/RocketChat.svg

@ -0,0 +1 @@
../../node_modules/@rocket.chat/icons/dist/font/RocketChat.ttf

@ -0,0 +1 @@
../../node_modules/@rocket.chat/icons/dist/font/RocketChat.woff

@ -0,0 +1 @@
../../node_modules/@rocket.chat/icons/dist/font/RocketChat.woff2

@ -61,7 +61,6 @@ import '../app/otr/server';
import '../app/push-notifications/server';
import '../app/retention-policy';
import '../app/apps/server';
import '../app/setup-wizard/server';
import '../app/slackbridge/server';
import '../app/slashcommands-archiveroom/server';
import '../app/slashcommand-asciiarts/server';

@ -30,6 +30,7 @@ import './methods/getAvatarSuggestion';
import './methods/getRoomById';
import './methods/getRoomIdByNameOrId';
import './methods/getRoomNameById';
import './methods/getSetupWizardParameters';
import './methods/getTotalChannels';
import './methods/getUsersOfRoom';
import './methods/hideRoom';

@ -1,17 +1,9 @@
import { Meteor } from 'meteor/meteor';
import { hasRole } from '../../authorization';
import { Settings } from '../../models';
import { Settings } from '../../app/models';
Meteor.methods({
getSetupWizardParameters() {
const userId = Meteor.userId();
const userHasAdminRole = userId && hasRole(userId, 'admin');
if (!userHasAdminRole) {
throw new Meteor.Error('error-not-allowed');
}
const settings = Settings.findSetupWizardSettings().fetch();
const allowStandaloneServer = process.env.DEPLOY_PLATFORM !== 'rocket-cloud';

@ -3,9 +3,9 @@ import { adminEmail, adminPassword } from '../data/user';
class SetupWizard extends Page {
get nextButton() { return browser.element('.setup-wizard-forms__footer-next:enabled'); }
get nextButton() { return browser.element('.SetupWizard .SetupWizard__Step--active .SetupWizard__continue'); }
get goToWorkspace() { return browser.element('button.js-finish'); }
get goToWorkspace() { return browser.element('.SetupWizard .SetupWizard__Epilogue__goToWorkspace'); }
get organizationType() { return browser.element('select[name="Organization_Type"]'); }

Loading…
Cancel
Save