diff options
37 files changed, 1205 insertions, 278 deletions
diff --git a/packages/ui/src/badge/ProBadge.tsx b/packages/ui/src/badge/ProBadge.tsx index 612e23210..2dad7ef49 100644 --- a/packages/ui/src/badge/ProBadge.tsx +++ b/packages/ui/src/badge/ProBadge.tsx | |||
@@ -3,13 +3,14 @@ import classnames from 'classnames'; | |||
3 | import React, { Component } from 'react'; | 3 | import React, { Component } from 'react'; |
4 | import injectStyle from 'react-jss'; | 4 | import injectStyle from 'react-jss'; |
5 | 5 | ||
6 | import { Icon, Badge } from '../'; | 6 | import { Badge, Icon } from '../'; |
7 | import { IWithStyle } from '../typings/generic'; | 7 | import { IWithStyle } from '../typings/generic'; |
8 | 8 | ||
9 | interface IProps extends IWithStyle { | 9 | interface IProps extends IWithStyle { |
10 | badgeClasses?: string; | 10 | badgeClasses?: string; |
11 | iconClasses?: string; | 11 | iconClasses?: string; |
12 | inverted?: boolean; | 12 | inverted?: boolean; |
13 | className?: string; | ||
13 | } | 14 | } |
14 | 15 | ||
15 | const styles = (theme: Theme) => ({ | 16 | const styles = (theme: Theme) => ({ |
@@ -37,6 +38,7 @@ class ProBadgeComponent extends Component<IProps> { | |||
37 | badgeClasses, | 38 | badgeClasses, |
38 | iconClasses, | 39 | iconClasses, |
39 | inverted, | 40 | inverted, |
41 | className, | ||
40 | } = this.props; | 42 | } = this.props; |
41 | 43 | ||
42 | return ( | 44 | return ( |
@@ -46,6 +48,7 @@ class ProBadgeComponent extends Component<IProps> { | |||
46 | classes.badge, | 48 | classes.badge, |
47 | inverted && classes.invertedBadge, | 49 | inverted && classes.invertedBadge, |
48 | badgeClasses, | 50 | badgeClasses, |
51 | className, | ||
49 | ])} | 52 | ])} |
50 | > | 53 | > |
51 | <Icon | 54 | <Icon |
diff --git a/packages/ui/src/infobox/index.tsx b/packages/ui/src/infobox/index.tsx index 9066a623e..09fc4596a 100644 --- a/packages/ui/src/infobox/index.tsx +++ b/packages/ui/src/infobox/index.tsx | |||
@@ -48,13 +48,13 @@ const styles = (theme: Theme) => ({ | |||
48 | position: 'relative', | 48 | position: 'relative', |
49 | overflow: 'hidden', | 49 | overflow: 'hidden', |
50 | height: 'auto', | 50 | height: 'auto', |
51 | marginBottom: 30, | ||
51 | }, | 52 | }, |
52 | infobox: { | 53 | infobox: { |
53 | alignItems: 'center', | 54 | alignItems: 'center', |
54 | borderRadius: theme.borderRadiusSmall, | 55 | borderRadius: theme.borderRadiusSmall, |
55 | display: 'flex', | 56 | display: 'flex', |
56 | height: 'auto', | 57 | height: 'auto', |
57 | marginBottom: 30, | ||
58 | padding: '15px 20px', | 58 | padding: '15px 20px', |
59 | top: 0, | 59 | top: 0, |
60 | transition: 'all 0.5s', | 60 | transition: 'all 0.5s', |
diff --git a/src/components/services/content/ServiceRestricted.js b/src/components/services/content/ServiceRestricted.js new file mode 100644 index 000000000..4b8d926aa --- /dev/null +++ b/src/components/services/content/ServiceRestricted.js | |||
@@ -0,0 +1,78 @@ | |||
1 | import React, { Component } from 'react'; | ||
2 | import PropTypes from 'prop-types'; | ||
3 | import { observer } from 'mobx-react'; | ||
4 | import { defineMessages, intlShape } from 'react-intl'; | ||
5 | |||
6 | import { serviceLimitStore } from '../../../features/serviceLimit'; | ||
7 | import Button from '../../ui/Button'; | ||
8 | import { RESTRICTION_TYPES } from '../../../models/Service'; | ||
9 | |||
10 | const messages = defineMessages({ | ||
11 | headlineServiceLimit: { | ||
12 | id: 'service.restrictedHandler.serviceLimit.headline', | ||
13 | defaultMessage: '!!!You have reached your service limit.', | ||
14 | }, | ||
15 | textServiceLimit: { | ||
16 | id: 'service.restrictedHandler.serviceLimit.text', | ||
17 | defaultMessage: '!!!Please upgrade your account to use more than {count} services.', | ||
18 | }, | ||
19 | headlineCustomUrl: { | ||
20 | id: 'service.restrictedHandler.customUrl.headline', | ||
21 | defaultMessage: '!!!Franz Professional Plan required', | ||
22 | }, | ||
23 | textCustomUrl: { | ||
24 | id: 'service.restrictedHandler.customUrl.text', | ||
25 | defaultMessage: '!!!Please upgrade to the Franz Professional plan to use custom urls & self hosted services.', | ||
26 | }, | ||
27 | action: { | ||
28 | id: 'service.restrictedHandler.action', | ||
29 | defaultMessage: '!!!Upgrade Account', | ||
30 | }, | ||
31 | }); | ||
32 | |||
33 | export default @observer class ServiceRestricted extends Component { | ||
34 | static propTypes = { | ||
35 | name: PropTypes.string.isRequired, | ||
36 | upgrade: PropTypes.func.isRequired, | ||
37 | type: PropTypes.number.isRequired, | ||
38 | }; | ||
39 | |||
40 | static contextTypes = { | ||
41 | intl: intlShape, | ||
42 | }; | ||
43 | |||
44 | countdownInterval = null; | ||
45 | |||
46 | countdownIntervalTimeout = 1000; | ||
47 | |||
48 | render() { | ||
49 | const { | ||
50 | name, | ||
51 | upgrade, | ||
52 | type, | ||
53 | } = this.props; | ||
54 | const { intl } = this.context; | ||
55 | |||
56 | return ( | ||
57 | <div className="services__info-layer"> | ||
58 | {type === RESTRICTION_TYPES.SERVICE_LIMIT && ( | ||
59 | <> | ||
60 | <h1>{intl.formatMessage(messages.headlineServiceLimit)}</h1> | ||
61 | <p>{intl.formatMessage(messages.textServiceLimit, { count: serviceLimitStore.serviceLimit })}</p> | ||
62 | </> | ||
63 | )} | ||
64 | {type === RESTRICTION_TYPES.CUSTOM_URL && ( | ||
65 | <> | ||
66 | <h1>{intl.formatMessage(messages.headlineCustomUrl)}</h1> | ||
67 | <p>{intl.formatMessage(messages.textCustomUrl)}</p> | ||
68 | </> | ||
69 | )} | ||
70 | <Button | ||
71 | label={intl.formatMessage(messages.action, { name })} | ||
72 | buttonType="inverted" | ||
73 | onClick={() => upgrade()} | ||
74 | /> | ||
75 | </div> | ||
76 | ); | ||
77 | } | ||
78 | } | ||
diff --git a/src/components/services/content/ServiceView.js b/src/components/services/content/ServiceView.js index 13148b9b3..f65f51346 100644 --- a/src/components/services/content/ServiceView.js +++ b/src/components/services/content/ServiceView.js | |||
@@ -10,6 +10,7 @@ import WebviewLoader from '../../ui/WebviewLoader'; | |||
10 | import WebviewCrashHandler from './WebviewCrashHandler'; | 10 | import WebviewCrashHandler from './WebviewCrashHandler'; |
11 | import WebviewErrorHandler from './ErrorHandlers/WebviewErrorHandler'; | 11 | import WebviewErrorHandler from './ErrorHandlers/WebviewErrorHandler'; |
12 | import ServiceDisabled from './ServiceDisabled'; | 12 | import ServiceDisabled from './ServiceDisabled'; |
13 | import ServiceRestricted from './ServiceRestricted'; | ||
13 | import ServiceWebview from './ServiceWebview'; | 14 | import ServiceWebview from './ServiceWebview'; |
14 | 15 | ||
15 | export default @observer class ServiceView extends Component { | 16 | export default @observer class ServiceView extends Component { |
@@ -21,6 +22,7 @@ export default @observer class ServiceView extends Component { | |||
21 | edit: PropTypes.func.isRequired, | 22 | edit: PropTypes.func.isRequired, |
22 | enable: PropTypes.func.isRequired, | 23 | enable: PropTypes.func.isRequired, |
23 | isActive: PropTypes.bool, | 24 | isActive: PropTypes.bool, |
25 | upgrade: PropTypes.func.isRequired, | ||
24 | }; | 26 | }; |
25 | 27 | ||
26 | static defaultProps = { | 28 | static defaultProps = { |
@@ -72,6 +74,7 @@ export default @observer class ServiceView extends Component { | |||
72 | reload, | 74 | reload, |
73 | edit, | 75 | edit, |
74 | enable, | 76 | enable, |
77 | upgrade, | ||
75 | } = this.props; | 78 | } = this.props; |
76 | 79 | ||
77 | const webviewClasses = classnames({ | 80 | const webviewClasses = classnames({ |
@@ -99,7 +102,7 @@ export default @observer class ServiceView extends Component { | |||
99 | reload={reload} | 102 | reload={reload} |
100 | /> | 103 | /> |
101 | )} | 104 | )} |
102 | {service.isEnabled && service.isLoading && service.isFirstLoad && ( | 105 | {service.isEnabled && service.isLoading && service.isFirstLoad && !service.isServiceAccessRestricted && ( |
103 | <WebviewLoader | 106 | <WebviewLoader |
104 | loaded={false} | 107 | loaded={false} |
105 | name={service.name} | 108 | name={service.name} |
@@ -126,11 +129,21 @@ export default @observer class ServiceView extends Component { | |||
126 | )} | 129 | )} |
127 | </Fragment> | 130 | </Fragment> |
128 | ) : ( | 131 | ) : ( |
129 | <ServiceWebview | 132 | <> |
130 | service={service} | 133 | {service.isServiceAccessRestricted ? ( |
131 | setWebviewReference={setWebviewReference} | 134 | <ServiceRestricted |
132 | detachService={detachService} | 135 | name={service.recipe.name} |
133 | /> | 136 | upgrade={upgrade} |
137 | type={service.restrictionType} | ||
138 | /> | ||
139 | ) : ( | ||
140 | <ServiceWebview | ||
141 | service={service} | ||
142 | setWebviewReference={setWebviewReference} | ||
143 | detachService={detachService} | ||
144 | /> | ||
145 | )} | ||
146 | </> | ||
134 | )} | 147 | )} |
135 | {statusBar} | 148 | {statusBar} |
136 | </div> | 149 | </div> |
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js index 8f8c38a11..48de0ebaa 100644 --- a/src/components/services/content/Services.js +++ b/src/components/services/content/Services.js | |||
@@ -89,6 +89,7 @@ export default @observer class Services extends Component { | |||
89 | }, | 89 | }, |
90 | redirect: false, | 90 | redirect: false, |
91 | })} | 91 | })} |
92 | upgrade={() => openSettings({ path: 'user' })} | ||
92 | /> | 93 | /> |
93 | ))} | 94 | ))} |
94 | </div> | 95 | </div> |
diff --git a/src/components/settings/navigation/SettingsNavigation.js b/src/components/settings/navigation/SettingsNavigation.js index df4b3b3b2..4696b82eb 100644 --- a/src/components/settings/navigation/SettingsNavigation.js +++ b/src/components/settings/navigation/SettingsNavigation.js | |||
@@ -8,6 +8,7 @@ import Link from '../../ui/Link'; | |||
8 | import { workspaceStore } from '../../../features/workspaces'; | 8 | import { workspaceStore } from '../../../features/workspaces'; |
9 | import UIStore from '../../../stores/UIStore'; | 9 | import UIStore from '../../../stores/UIStore'; |
10 | import UserStore from '../../../stores/UserStore'; | 10 | import UserStore from '../../../stores/UserStore'; |
11 | import { serviceLimitStore } from '../../../features/serviceLimit'; | ||
11 | 12 | ||
12 | const messages = defineMessages({ | 13 | const messages = defineMessages({ |
13 | availableServices: { | 14 | availableServices: { |
@@ -80,7 +81,12 @@ export default @inject('stores') @observer class SettingsNavigation extends Comp | |||
80 | > | 81 | > |
81 | {intl.formatMessage(messages.yourServices)} | 82 | {intl.formatMessage(messages.yourServices)} |
82 | {' '} | 83 | {' '} |
83 | <span className="badge">{serviceCount}</span> | 84 | <span className="badge"> |
85 | {serviceCount} | ||
86 | {serviceLimitStore.serviceLimit !== 0 && ( | ||
87 | `/${serviceLimitStore.serviceLimit}` | ||
88 | )} | ||
89 | </span> | ||
84 | </Link> | 90 | </Link> |
85 | {workspaceStore.isFeatureEnabled ? ( | 91 | {workspaceStore.isFeatureEnabled ? ( |
86 | <Link | 92 | <Link |
diff --git a/src/components/settings/recipes/RecipeItem.js b/src/components/settings/recipes/RecipeItem.js index 3bb0852b2..12e3775f6 100644 --- a/src/components/settings/recipes/RecipeItem.js +++ b/src/components/settings/recipes/RecipeItem.js | |||
@@ -19,7 +19,7 @@ export default @observer class RecipeItem extends Component { | |||
19 | className="recipe-teaser" | 19 | className="recipe-teaser" |
20 | onClick={onClick} | 20 | onClick={onClick} |
21 | > | 21 | > |
22 | {recipe.local && ( | 22 | {recipe.isDevRecipe && ( |
23 | <span className="recipe-teaser__dev-badge">dev</span> | 23 | <span className="recipe-teaser__dev-badge">dev</span> |
24 | )} | 24 | )} |
25 | <img | 25 | <img |
diff --git a/src/components/settings/recipes/RecipesDashboard.js b/src/components/settings/recipes/RecipesDashboard.js index 00cd725cf..75e60b7ec 100644 --- a/src/components/settings/recipes/RecipesDashboard.js +++ b/src/components/settings/recipes/RecipesDashboard.js | |||
@@ -4,12 +4,17 @@ import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; | |||
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, intlShape } from 'react-intl'; |
5 | import { Link } from 'react-router'; | 5 | import { Link } from 'react-router'; |
6 | 6 | ||
7 | import { Button, Input } from '@meetfranz/forms'; | ||
8 | import injectSheet from 'react-jss'; | ||
9 | import { H3, H2, ProBadge } from '@meetfranz/ui'; | ||
7 | import SearchInput from '../../ui/SearchInput'; | 10 | import SearchInput from '../../ui/SearchInput'; |
8 | import Infobox from '../../ui/Infobox'; | 11 | import Infobox from '../../ui/Infobox'; |
9 | import RecipeItem from './RecipeItem'; | 12 | import RecipeItem from './RecipeItem'; |
10 | import Loader from '../../ui/Loader'; | 13 | import Loader from '../../ui/Loader'; |
11 | import Appear from '../../ui/effects/Appear'; | 14 | import Appear from '../../ui/effects/Appear'; |
12 | import { FRANZ_SERVICE_REQUEST } from '../../../config'; | 15 | import { FRANZ_SERVICE_REQUEST } from '../../../config'; |
16 | import LimitReachedInfobox from '../../../features/serviceLimit/components/LimitReachedInfobox'; | ||
17 | import PremiumFeatureContainer from '../../ui/PremiumFeatureContainer'; | ||
13 | 18 | ||
14 | const messages = defineMessages({ | 19 | const messages = defineMessages({ |
15 | headline: { | 20 | headline: { |
@@ -28,9 +33,9 @@ const messages = defineMessages({ | |||
28 | id: 'settings.recipes.all', | 33 | id: 'settings.recipes.all', |
29 | defaultMessage: '!!!All services', | 34 | defaultMessage: '!!!All services', |
30 | }, | 35 | }, |
31 | devRecipes: { | 36 | customRecipes: { |
32 | id: 'settings.recipes.dev', | 37 | id: 'settings.recipes.custom', |
33 | defaultMessage: '!!!Development', | 38 | defaultMessage: '!!!Custom Services', |
34 | }, | 39 | }, |
35 | nothingFound: { | 40 | nothingFound: { |
36 | id: 'settings.recipes.nothingFound', | 41 | id: 'settings.recipes.nothingFound', |
@@ -44,9 +49,61 @@ const messages = defineMessages({ | |||
44 | id: 'settings.recipes.missingService', | 49 | id: 'settings.recipes.missingService', |
45 | defaultMessage: '!!!Missing a service?', | 50 | defaultMessage: '!!!Missing a service?', |
46 | }, | 51 | }, |
52 | customRecipeIntro: { | ||
53 | id: 'settings.recipes.customService.intro', | ||
54 | defaultMessage: '!!!To add a custom service, copy the recipe folder into:', | ||
55 | }, | ||
56 | openFolder: { | ||
57 | id: 'settings.recipes.customService.openFolder', | ||
58 | defaultMessage: '!!!Open directory', | ||
59 | }, | ||
60 | openDevDocs: { | ||
61 | id: 'settings.recipes.customService.openDevDocs', | ||
62 | defaultMessage: '!!!Developer Documentation', | ||
63 | }, | ||
64 | headlineCustomRecipes: { | ||
65 | id: 'settings.recipes.customService.headline.customRecipes', | ||
66 | defaultMessage: '!!!Custom Service Recipes', | ||
67 | }, | ||
68 | headlineCommunityRecipes: { | ||
69 | id: 'settings.recipes.customService.headline.communityRecipes', | ||
70 | defaultMessage: '!!!Community Services', | ||
71 | }, | ||
72 | headlineDevRecipes: { | ||
73 | id: 'settings.recipes.customService.headline.devRecipes', | ||
74 | defaultMessage: '!!!Your Development Service Recipes', | ||
75 | }, | ||
47 | }); | 76 | }); |
48 | 77 | ||
49 | export default @observer class RecipesDashboard extends Component { | 78 | const styles = { |
79 | devRecipeIntroContainer: { | ||
80 | textAlign: 'center', | ||
81 | width: '100%', | ||
82 | height: 'auto', | ||
83 | margin: [40, 0], | ||
84 | }, | ||
85 | path: { | ||
86 | marginTop: 20, | ||
87 | |||
88 | '& > div': { | ||
89 | fontFamily: 'SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace', | ||
90 | }, | ||
91 | }, | ||
92 | actionContainer: { | ||
93 | '& button': { | ||
94 | margin: [0, 10], | ||
95 | }, | ||
96 | }, | ||
97 | devRecipeList: { | ||
98 | marginTop: 20, | ||
99 | height: 'auto', | ||
100 | }, | ||
101 | proBadge: { | ||
102 | marginLeft: '10px !important', | ||
103 | }, | ||
104 | }; | ||
105 | |||
106 | export default @injectSheet(styles) @observer class RecipesDashboard extends Component { | ||
50 | static propTypes = { | 107 | static propTypes = { |
51 | recipes: MobxPropTypes.arrayOrObservableArray.isRequired, | 108 | recipes: MobxPropTypes.arrayOrObservableArray.isRequired, |
52 | isLoading: PropTypes.bool.isRequired, | 109 | isLoading: PropTypes.bool.isRequired, |
@@ -55,12 +112,18 @@ export default @observer class RecipesDashboard extends Component { | |||
55 | searchRecipes: PropTypes.func.isRequired, | 112 | searchRecipes: PropTypes.func.isRequired, |
56 | resetSearch: PropTypes.func.isRequired, | 113 | resetSearch: PropTypes.func.isRequired, |
57 | serviceStatus: MobxPropTypes.arrayOrObservableArray.isRequired, | 114 | serviceStatus: MobxPropTypes.arrayOrObservableArray.isRequired, |
58 | devRecipesCount: PropTypes.number.isRequired, | ||
59 | searchNeedle: PropTypes.string, | 115 | searchNeedle: PropTypes.string, |
116 | recipeFilter: PropTypes.string, | ||
117 | recipeDirectory: PropTypes.string.isRequired, | ||
118 | openRecipeDirectory: PropTypes.func.isRequired, | ||
119 | openDevDocs: PropTypes.func.isRequired, | ||
120 | classes: PropTypes.object.isRequired, | ||
121 | isCommunityRecipesIncludedInCurrentPlan: PropTypes.bool.isRequired, | ||
60 | }; | 122 | }; |
61 | 123 | ||
62 | static defaultProps = { | 124 | static defaultProps = { |
63 | searchNeedle: '', | 125 | searchNeedle: '', |
126 | recipeFilter: 'all', | ||
64 | } | 127 | } |
65 | 128 | ||
66 | static contextTypes = { | 129 | static contextTypes = { |
@@ -76,16 +139,26 @@ export default @observer class RecipesDashboard extends Component { | |||
76 | searchRecipes, | 139 | searchRecipes, |
77 | resetSearch, | 140 | resetSearch, |
78 | serviceStatus, | 141 | serviceStatus, |
79 | devRecipesCount, | ||
80 | searchNeedle, | 142 | searchNeedle, |
143 | recipeFilter, | ||
144 | recipeDirectory, | ||
145 | openRecipeDirectory, | ||
146 | openDevDocs, | ||
147 | classes, | ||
148 | isCommunityRecipesIncludedInCurrentPlan, | ||
81 | } = this.props; | 149 | } = this.props; |
82 | const { intl } = this.context; | 150 | const { intl } = this.context; |
83 | 151 | ||
152 | |||
153 | const communityRecipes = recipes.filter(r => !r.isDevRecipe); | ||
154 | const devRecipes = recipes.filter(r => r.isDevRecipe); | ||
155 | |||
84 | return ( | 156 | return ( |
85 | <div className="settings__main"> | 157 | <div className="settings__main"> |
86 | <div className="settings__header"> | 158 | <div className="settings__header"> |
87 | <h1>{intl.formatMessage(messages.headline)}</h1> | 159 | <h1>{intl.formatMessage(messages.headline)}</h1> |
88 | </div> | 160 | </div> |
161 | <LimitReachedInfobox /> | ||
89 | <div className="settings__body recipes"> | 162 | <div className="settings__body recipes"> |
90 | {serviceStatus.length > 0 && serviceStatus.includes('created') && ( | 163 | {serviceStatus.length > 0 && serviceStatus.includes('created') && ( |
91 | <Appear> | 164 | <Appear> |
@@ -122,20 +195,14 @@ export default @observer class RecipesDashboard extends Component { | |||
122 | > | 195 | > |
123 | {intl.formatMessage(messages.allRecipes)} | 196 | {intl.formatMessage(messages.allRecipes)} |
124 | </Link> | 197 | </Link> |
125 | {devRecipesCount > 0 && ( | 198 | <Link |
126 | <Link | 199 | to="/settings/recipes/dev" |
127 | to="/settings/recipes/dev" | 200 | className="badge" |
128 | className="badge" | 201 | activeClassName={`${!searchNeedle ? 'badge--primary' : ''}`} |
129 | activeClassName={`${!searchNeedle ? 'badge--primary' : ''}`} | 202 | onClick={() => resetSearch()} |
130 | onClick={() => resetSearch()} | 203 | > |
131 | > | 204 | {intl.formatMessage(messages.customRecipes)} |
132 | {intl.formatMessage(messages.devRecipes)} | 205 | </Link> |
133 | {' '} | ||
134 | ( | ||
135 | {devRecipesCount} | ||
136 | ) | ||
137 | </Link> | ||
138 | )} | ||
139 | <a href={FRANZ_SERVICE_REQUEST} target="_blank" className="link recipes__service-request"> | 206 | <a href={FRANZ_SERVICE_REQUEST} target="_blank" className="link recipes__service-request"> |
140 | {intl.formatMessage(messages.missingService)} | 207 | {intl.formatMessage(messages.missingService)} |
141 | {' '} | 208 | {' '} |
@@ -146,23 +213,78 @@ export default @observer class RecipesDashboard extends Component { | |||
146 | {isLoading ? ( | 213 | {isLoading ? ( |
147 | <Loader /> | 214 | <Loader /> |
148 | ) : ( | 215 | ) : ( |
149 | <div className="recipes__list"> | 216 | <> |
150 | {hasLoadedRecipes && recipes.length === 0 && ( | 217 | {recipeFilter === 'dev' && ( |
151 | <p className="align-middle settings__empty-state"> | 218 | <> |
152 | <span className="emoji"> | 219 | <H2> |
153 | <img src="./assets/images/emoji/dontknow.png" alt="" /> | 220 | {intl.formatMessage(messages.headlineCustomRecipes)} |
154 | </span> | 221 | {isCommunityRecipesIncludedInCurrentPlan && ( |
155 | {intl.formatMessage(messages.nothingFound)} | 222 | <ProBadge className={classes.proBadge} /> |
156 | </p> | 223 | )} |
224 | </H2> | ||
225 | <div className={classes.devRecipeIntroContainer}> | ||
226 | <p> | ||
227 | {intl.formatMessage(messages.customRecipeIntro)} | ||
228 | </p> | ||
229 | <Input | ||
230 | value={recipeDirectory} | ||
231 | className={classes.path} | ||
232 | showLabel={false} | ||
233 | /> | ||
234 | <div className={classes.actionContainer}> | ||
235 | <Button | ||
236 | onClick={openRecipeDirectory} | ||
237 | buttonType="secondary" | ||
238 | label={intl.formatMessage(messages.openFolder)} | ||
239 | /> | ||
240 | <Button | ||
241 | onClick={openDevDocs} | ||
242 | buttonType="secondary" | ||
243 | label={intl.formatMessage(messages.openDevDocs)} | ||
244 | /> | ||
245 | </div> | ||
246 | </div> | ||
247 | </> | ||
248 | )} | ||
249 | <PremiumFeatureContainer | ||
250 | condition={(recipeFilter === 'dev' && communityRecipes.length > 0) && isCommunityRecipesIncludedInCurrentPlan} | ||
251 | > | ||
252 | {recipeFilter === 'dev' && communityRecipes.length > 0 && ( | ||
253 | <H3>{intl.formatMessage(messages.headlineCommunityRecipes)}</H3> | ||
254 | )} | ||
255 | <div className="recipes__list"> | ||
256 | {hasLoadedRecipes && recipes.length === 0 && recipeFilter !== 'dev' && ( | ||
257 | <p className="align-middle settings__empty-state"> | ||
258 | <span className="emoji"> | ||
259 | <img src="./assets/images/emoji/dontknow.png" alt="" /> | ||
260 | </span> | ||
261 | {intl.formatMessage(messages.nothingFound)} | ||
262 | </p> | ||
263 | )} | ||
264 | {communityRecipes.map(recipe => ( | ||
265 | <RecipeItem | ||
266 | key={recipe.id} | ||
267 | recipe={recipe} | ||
268 | onClick={() => showAddServiceInterface({ recipeId: recipe.id })} | ||
269 | /> | ||
270 | ))} | ||
271 | </div> | ||
272 | </PremiumFeatureContainer> | ||
273 | {recipeFilter === 'dev' && devRecipes.length > 0 && ( | ||
274 | <div className={classes.devRecipeList}> | ||
275 | <H3>{intl.formatMessage(messages.headlineDevRecipes)}</H3> | ||
276 | <div className="recipes__list"> | ||
277 | {devRecipes.map(recipe => ( | ||
278 | <RecipeItem | ||
279 | key={recipe.id} | ||
280 | recipe={recipe} | ||
281 | onClick={() => showAddServiceInterface({ recipeId: recipe.id })} | ||
282 | /> | ||
283 | ))} | ||
284 | </div> | ||
285 | </div> | ||
157 | )} | 286 | )} |
158 | {recipes.map(recipe => ( | 287 | </> |
159 | <RecipeItem | ||
160 | key={recipe.id} | ||
161 | recipe={recipe} | ||
162 | onClick={() => showAddServiceInterface({ recipeId: recipe.id })} | ||
163 | /> | ||
164 | ))} | ||
165 | </div> | ||
166 | )} | 288 | )} |
167 | </div> | 289 | </div> |
168 | </div> | 290 | </div> |
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js index 4ba2eb844..5cde0db8e 100644 --- a/src/components/settings/services/EditServiceForm.js +++ b/src/components/settings/services/EditServiceForm.js | |||
@@ -17,6 +17,8 @@ import ImageUpload from '../../ui/ImageUpload'; | |||
17 | import Select from '../../ui/Select'; | 17 | import Select from '../../ui/Select'; |
18 | 18 | ||
19 | import PremiumFeatureContainer from '../../ui/PremiumFeatureContainer'; | 19 | import PremiumFeatureContainer from '../../ui/PremiumFeatureContainer'; |
20 | import LimitReachedInfobox from '../../../features/serviceLimit/components/LimitReachedInfobox'; | ||
21 | import { serviceLimitStore } from '../../../features/serviceLimit'; | ||
20 | 22 | ||
21 | const messages = defineMessages({ | 23 | const messages = defineMessages({ |
22 | saveService: { | 24 | saveService: { |
@@ -128,8 +130,8 @@ export default @observer class EditServiceForm extends Component { | |||
128 | isSaving: PropTypes.bool.isRequired, | 130 | isSaving: PropTypes.bool.isRequired, |
129 | isDeleting: PropTypes.bool.isRequired, | 131 | isDeleting: PropTypes.bool.isRequired, |
130 | isProxyFeatureEnabled: PropTypes.bool.isRequired, | 132 | isProxyFeatureEnabled: PropTypes.bool.isRequired, |
131 | isProxyPremiumFeature: PropTypes.bool.isRequired, | 133 | isServiceProxyIncludedInCurrentPlan: PropTypes.bool.isRequired, |
132 | isSpellcheckerPremiumFeature: PropTypes.bool.isRequired, | 134 | isSpellcheckerIncludedInCurrentPlan: PropTypes.bool.isRequired, |
133 | }; | 135 | }; |
134 | 136 | ||
135 | static defaultProps = { | 137 | static defaultProps = { |
@@ -192,8 +194,8 @@ export default @observer class EditServiceForm extends Component { | |||
192 | isDeleting, | 194 | isDeleting, |
193 | onDelete, | 195 | onDelete, |
194 | isProxyFeatureEnabled, | 196 | isProxyFeatureEnabled, |
195 | isProxyPremiumFeature, | 197 | isServiceProxyIncludedInCurrentPlan, |
196 | isSpellcheckerPremiumFeature, | 198 | isSpellcheckerIncludedInCurrentPlan, |
197 | } = this.props; | 199 | } = this.props; |
198 | const { intl } = this.context; | 200 | const { intl } = this.context; |
199 | 201 | ||
@@ -252,6 +254,7 @@ export default @observer class EditServiceForm extends Component { | |||
252 | )} | 254 | )} |
253 | </span> | 255 | </span> |
254 | </div> | 256 | </div> |
257 | <LimitReachedInfobox /> | ||
255 | <div className="settings__body"> | 258 | <div className="settings__body"> |
256 | <form onSubmit={e => this.submit(e)} id="form"> | 259 | <form onSubmit={e => this.submit(e)} id="form"> |
257 | <div className="service-name"> | 260 | <div className="service-name"> |
@@ -342,7 +345,7 @@ export default @observer class EditServiceForm extends Component { | |||
342 | </div> | 345 | </div> |
343 | 346 | ||
344 | <PremiumFeatureContainer | 347 | <PremiumFeatureContainer |
345 | condition={isSpellcheckerPremiumFeature} | 348 | condition={!isSpellcheckerIncludedInCurrentPlan} |
346 | gaEventInfo={{ category: 'User', event: 'upgrade', label: 'spellchecker' }} | 349 | gaEventInfo={{ category: 'User', event: 'upgrade', label: 'spellchecker' }} |
347 | > | 350 | > |
348 | <div className="settings__settings-group"> | 351 | <div className="settings__settings-group"> |
@@ -352,7 +355,7 @@ export default @observer class EditServiceForm extends Component { | |||
352 | 355 | ||
353 | {isProxyFeatureEnabled && ( | 356 | {isProxyFeatureEnabled && ( |
354 | <PremiumFeatureContainer | 357 | <PremiumFeatureContainer |
355 | condition={isProxyPremiumFeature} | 358 | condition={!isServiceProxyIncludedInCurrentPlan} |
356 | gaEventInfo={{ category: 'User', event: 'upgrade', label: 'proxy' }} | 359 | gaEventInfo={{ category: 'User', event: 'upgrade', label: 'proxy' }} |
357 | > | 360 | > |
358 | <div className="settings__settings-group"> | 361 | <div className="settings__settings-group"> |
@@ -418,7 +421,7 @@ export default @observer class EditServiceForm extends Component { | |||
418 | type="submit" | 421 | type="submit" |
419 | label={intl.formatMessage(messages.saveService)} | 422 | label={intl.formatMessage(messages.saveService)} |
420 | htmlForm="form" | 423 | htmlForm="form" |
421 | disabled={action !== 'edit' && form.isPristine && requiresUserInput} | 424 | disabled={action !== 'edit' && ((form.isPristine && requiresUserInput) || serviceLimitStore.userHasReachedServiceLimit)} |
422 | /> | 425 | /> |
423 | )} | 426 | )} |
424 | </div> | 427 | </div> |
diff --git a/src/components/settings/services/ServicesDashboard.js b/src/components/settings/services/ServicesDashboard.js index 53bae12df..78038e86a 100644 --- a/src/components/settings/services/ServicesDashboard.js +++ b/src/components/settings/services/ServicesDashboard.js | |||
@@ -9,6 +9,7 @@ import Infobox from '../../ui/Infobox'; | |||
9 | import Loader from '../../ui/Loader'; | 9 | import Loader from '../../ui/Loader'; |
10 | import ServiceItem from './ServiceItem'; | 10 | import ServiceItem from './ServiceItem'; |
11 | import Appear from '../../ui/effects/Appear'; | 11 | import Appear from '../../ui/effects/Appear'; |
12 | import LimitReachedInfobox from '../../../features/serviceLimit/components/LimitReachedInfobox'; | ||
12 | 13 | ||
13 | const messages = defineMessages({ | 14 | const messages = defineMessages({ |
14 | headline: { | 15 | headline: { |
@@ -91,6 +92,7 @@ export default @observer class ServicesDashboard extends Component { | |||
91 | <div className="settings__header"> | 92 | <div className="settings__header"> |
92 | <h1>{intl.formatMessage(messages.headline)}</h1> | 93 | <h1>{intl.formatMessage(messages.headline)}</h1> |
93 | </div> | 94 | </div> |
95 | <LimitReachedInfobox /> | ||
94 | <div className="settings__body"> | 96 | <div className="settings__body"> |
95 | {!isLoading && ( | 97 | {!isLoading && ( |
96 | <SearchInput | 98 | <SearchInput |
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js index efd453356..6d0811b1b 100644 --- a/src/components/settings/settings/EditSettingsForm.js +++ b/src/components/settings/settings/EditSettingsForm.js | |||
@@ -100,7 +100,7 @@ export default @observer class EditSettingsForm extends Component { | |||
100 | isClearingAllCache: PropTypes.bool.isRequired, | 100 | isClearingAllCache: PropTypes.bool.isRequired, |
101 | onClearAllCache: PropTypes.func.isRequired, | 101 | onClearAllCache: PropTypes.func.isRequired, |
102 | cacheSize: PropTypes.string.isRequired, | 102 | cacheSize: PropTypes.string.isRequired, |
103 | isSpellcheckerPremiumFeature: PropTypes.bool.isRequired, | 103 | isSpellcheckerIncludedInCurrentPlan: PropTypes.bool.isRequired, |
104 | }; | 104 | }; |
105 | 105 | ||
106 | static contextTypes = { | 106 | static contextTypes = { |
@@ -130,7 +130,7 @@ export default @observer class EditSettingsForm extends Component { | |||
130 | isClearingAllCache, | 130 | isClearingAllCache, |
131 | onClearAllCache, | 131 | onClearAllCache, |
132 | cacheSize, | 132 | cacheSize, |
133 | isSpellcheckerPremiumFeature, | 133 | isSpellcheckerIncludedInCurrentPlan, |
134 | } = this.props; | 134 | } = this.props; |
135 | const { intl } = this.context; | 135 | const { intl } = this.context; |
136 | 136 | ||
@@ -143,6 +143,8 @@ export default @observer class EditSettingsForm extends Component { | |||
143 | updateButtonLabelMessage = messages.buttonSearchForUpdate; | 143 | updateButtonLabelMessage = messages.buttonSearchForUpdate; |
144 | } | 144 | } |
145 | 145 | ||
146 | console.log('isSpellcheckerIncludedInCurrentPlan', isSpellcheckerIncludedInCurrentPlan); | ||
147 | |||
146 | return ( | 148 | return ( |
147 | <div className="settings__main"> | 149 | <div className="settings__main"> |
148 | <div className="settings__header"> | 150 | <div className="settings__header"> |
@@ -173,7 +175,7 @@ export default @observer class EditSettingsForm extends Component { | |||
173 | <h2 id="language">{intl.formatMessage(messages.headlineLanguage)}</h2> | 175 | <h2 id="language">{intl.formatMessage(messages.headlineLanguage)}</h2> |
174 | <Select field={form.$('locale')} showLabel={false} /> | 176 | <Select field={form.$('locale')} showLabel={false} /> |
175 | <PremiumFeatureContainer | 177 | <PremiumFeatureContainer |
176 | condition={isSpellcheckerPremiumFeature} | 178 | condition={!isSpellcheckerIncludedInCurrentPlan} |
177 | gaEventInfo={{ category: 'User', event: 'upgrade', label: 'spellchecker' }} | 179 | gaEventInfo={{ category: 'User', event: 'upgrade', label: 'spellchecker' }} |
178 | > | 180 | > |
179 | <Fragment> | 181 | <Fragment> |
diff --git a/src/config.js b/src/config.js index 5bc318545..3c8b0f0d0 100644 --- a/src/config.js +++ b/src/config.js | |||
@@ -45,16 +45,16 @@ export const DEFAULT_APP_SETTINGS = { | |||
45 | }; | 45 | }; |
46 | 46 | ||
47 | export const DEFAULT_FEATURES_CONFIG = { | 47 | export const DEFAULT_FEATURES_CONFIG = { |
48 | isSpellcheckerPremiumFeature: false, | 48 | isSpellcheckerIncludedInCurrentPlan: true, |
49 | needToWaitToProceed: false, | 49 | needToWaitToProceed: false, |
50 | needToWaitToProceedConfig: { | 50 | needToWaitToProceedConfig: { |
51 | delayOffset: ms('1h'), | 51 | delayOffset: ms('1h'), |
52 | wait: ms('10s'), | 52 | wait: ms('10s'), |
53 | }, | 53 | }, |
54 | isServiceProxyEnabled: false, | 54 | isServiceProxyEnabled: false, |
55 | isServiceProxyPremiumFeature: true, | 55 | isServiceProxyIncludedInCurrentPlan: false, |
56 | isAnnouncementsEnabled: true, | 56 | isAnnouncementsEnabled: true, |
57 | isWorkspacePremiumFeature: true, | 57 | isWorkspaceIncludedInCurrentPlan: true, |
58 | isWorkspaceEnabled: false, | 58 | isWorkspaceEnabled: false, |
59 | }; | 59 | }; |
60 | 60 | ||
@@ -67,6 +67,7 @@ export const DEFAULT_WINDOW_OPTIONS = { | |||
67 | 67 | ||
68 | export const FRANZ_SERVICE_REQUEST = 'https://bit.ly/franz-plugin-docs'; | 68 | export const FRANZ_SERVICE_REQUEST = 'https://bit.ly/franz-plugin-docs'; |
69 | export const FRANZ_TRANSLATION = 'https://bit.ly/franz-translate'; | 69 | export const FRANZ_TRANSLATION = 'https://bit.ly/franz-translate'; |
70 | export const FRANZ_DEV_DOCS = 'http://bit.ly/franz-dev-hub'; | ||
70 | 71 | ||
71 | export const FILE_SYSTEM_SETTINGS_TYPES = [ | 72 | export const FILE_SYSTEM_SETTINGS_TYPES = [ |
72 | 'app', | 73 | 'app', |
diff --git a/src/containers/settings/EditServiceScreen.js b/src/containers/settings/EditServiceScreen.js index 870ca4ecd..e4ff03bb3 100644 --- a/src/containers/settings/EditServiceScreen.js +++ b/src/containers/settings/EditServiceScreen.js | |||
@@ -330,8 +330,8 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex | |||
330 | onSubmit={d => this.onSubmit(d)} | 330 | onSubmit={d => this.onSubmit(d)} |
331 | onDelete={() => this.deleteService()} | 331 | onDelete={() => this.deleteService()} |
332 | isProxyFeatureEnabled={proxyFeature.isEnabled} | 332 | isProxyFeatureEnabled={proxyFeature.isEnabled} |
333 | isProxyPremiumFeature={proxyFeature.isPremium} | 333 | isServiceProxyIncludedInCurrentPlan={proxyFeature.isIncludedInCurrentPlan} |
334 | isSpellcheckerPremiumFeature={spellcheckerFeature.isPremium} | 334 | isSpellcheckerIncludedInCurrentPlan={spellcheckerFeature.isIncludedInCurrentPlan} |
335 | /> | 335 | /> |
336 | </ErrorBoundary> | 336 | </ErrorBoundary> |
337 | ); | 337 | ); |
diff --git a/src/containers/settings/EditSettingsScreen.js b/src/containers/settings/EditSettingsScreen.js index 97c1fa3b1..67d52f102 100644 --- a/src/containers/settings/EditSettingsScreen.js +++ b/src/containers/settings/EditSettingsScreen.js | |||
@@ -159,8 +159,8 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e | |||
159 | }, | 159 | }, |
160 | enableSpellchecking: { | 160 | enableSpellchecking: { |
161 | label: intl.formatMessage(messages.enableSpellchecking), | 161 | label: intl.formatMessage(messages.enableSpellchecking), |
162 | value: !this.props.stores.user.data.isPremium && spellcheckerConfig.isPremium ? false : settings.all.app.enableSpellchecking, | 162 | value: !this.props.stores.user.data.isPremium && !spellcheckerConfig.isIncludedInCurrentPlan ? false : settings.all.app.enableSpellchecking, |
163 | default: !this.props.stores.user.data.isPremium && spellcheckerConfig.isPremium ? false : DEFAULT_APP_SETTINGS.enableSpellchecking, | 163 | default: !this.props.stores.user.data.isPremium && !spellcheckerConfig.isIncludedInCurrentPlan ? false : DEFAULT_APP_SETTINGS.enableSpellchecking, |
164 | }, | 164 | }, |
165 | spellcheckerLanguage: { | 165 | spellcheckerLanguage: { |
166 | label: intl.formatMessage(globalMessages.spellcheckerLanguage), | 166 | label: intl.formatMessage(globalMessages.spellcheckerLanguage), |
@@ -223,7 +223,7 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e | |||
223 | cacheSize={cacheSize} | 223 | cacheSize={cacheSize} |
224 | isClearingAllCache={isClearingAllCache} | 224 | isClearingAllCache={isClearingAllCache} |
225 | onClearAllCache={clearAllCache} | 225 | onClearAllCache={clearAllCache} |
226 | isSpellcheckerPremiumFeature={spellcheckerConfig.isPremium} | 226 | isSpellcheckerIncludedInCurrentPlan={spellcheckerConfig.isIncludedInCurrentPlan} |
227 | /> | 227 | /> |
228 | </ErrorBoundary> | 228 | </ErrorBoundary> |
229 | ); | 229 | ); |
diff --git a/src/containers/settings/RecipesScreen.js b/src/containers/settings/RecipesScreen.js index eda5ae54c..132820b6f 100644 --- a/src/containers/settings/RecipesScreen.js +++ b/src/containers/settings/RecipesScreen.js | |||
@@ -1,7 +1,9 @@ | |||
1 | import { remote, shell } from 'electron'; | ||
1 | import React, { Component } from 'react'; | 2 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 3 | import PropTypes from 'prop-types'; |
3 | import { autorun } from 'mobx'; | 4 | import { autorun } from 'mobx'; |
4 | import { inject, observer } from 'mobx-react'; | 5 | import { inject, observer } from 'mobx-react'; |
6 | import path from 'path'; | ||
5 | 7 | ||
6 | import RecipePreviewsStore from '../../stores/RecipePreviewsStore'; | 8 | import RecipePreviewsStore from '../../stores/RecipePreviewsStore'; |
7 | import RecipeStore from '../../stores/RecipesStore'; | 9 | import RecipeStore from '../../stores/RecipesStore'; |
@@ -10,6 +12,11 @@ import UserStore from '../../stores/UserStore'; | |||
10 | 12 | ||
11 | import RecipesDashboard from '../../components/settings/recipes/RecipesDashboard'; | 13 | import RecipesDashboard from '../../components/settings/recipes/RecipesDashboard'; |
12 | import ErrorBoundary from '../../components/util/ErrorBoundary'; | 14 | import ErrorBoundary from '../../components/util/ErrorBoundary'; |
15 | import { FRANZ_DEV_DOCS } from '../../config'; | ||
16 | import { gaEvent } from '../../lib/analytics'; | ||
17 | import { communityRecipesStore } from '../../features/communityRecipes'; | ||
18 | |||
19 | const { app } = remote; | ||
13 | 20 | ||
14 | export default @inject('stores', 'actions') @observer class RecipesScreen extends Component { | 21 | export default @inject('stores', 'actions') @observer class RecipesScreen extends Component { |
15 | static propTypes = { | 22 | static propTypes = { |
@@ -67,9 +74,16 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend | |||
67 | 74 | ||
68 | render() { | 75 | render() { |
69 | const { | 76 | const { |
70 | recipePreviews, recipes, services, user, | 77 | recipePreviews, |
78 | recipes, | ||
79 | services, | ||
80 | user, | ||
71 | } = this.props.stores; | 81 | } = this.props.stores; |
72 | const { showAddServiceInterface } = this.props.actions.service; | 82 | |
83 | const { | ||
84 | app: appActions, | ||
85 | service: serviceActions, | ||
86 | } = this.props.actions; | ||
73 | 87 | ||
74 | const { filter } = this.props.params; | 88 | const { filter } = this.props.params; |
75 | let recipeFilter; | 89 | let recipeFilter; |
@@ -77,7 +91,7 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend | |||
77 | if (filter === 'all') { | 91 | if (filter === 'all') { |
78 | recipeFilter = recipePreviews.all; | 92 | recipeFilter = recipePreviews.all; |
79 | } else if (filter === 'dev') { | 93 | } else if (filter === 'dev') { |
80 | recipeFilter = recipePreviews.dev; | 94 | recipeFilter = communityRecipesStore.communityRecipes; |
81 | } else { | 95 | } else { |
82 | recipeFilter = recipePreviews.featured; | 96 | recipeFilter = recipePreviews.featured; |
83 | } | 97 | } |
@@ -89,6 +103,8 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend | |||
89 | || recipes.installRecipeRequest.isExecuting | 103 | || recipes.installRecipeRequest.isExecuting |
90 | || recipePreviews.searchRecipePreviewsRequest.isExecuting; | 104 | || recipePreviews.searchRecipePreviewsRequest.isExecuting; |
91 | 105 | ||
106 | const recipeDirectory = path.join(app.getPath('userData'), 'recipes', 'dev'); | ||
107 | |||
92 | return ( | 108 | return ( |
93 | <ErrorBoundary> | 109 | <ErrorBoundary> |
94 | <RecipesDashboard | 110 | <RecipesDashboard |
@@ -97,12 +113,23 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend | |||
97 | addedServiceCount={services.all.length} | 113 | addedServiceCount={services.all.length} |
98 | isPremium={user.data.isPremium} | 114 | isPremium={user.data.isPremium} |
99 | hasLoadedRecipes={recipePreviews.featuredRecipePreviewsRequest.wasExecuted} | 115 | hasLoadedRecipes={recipePreviews.featuredRecipePreviewsRequest.wasExecuted} |
100 | showAddServiceInterface={showAddServiceInterface} | 116 | showAddServiceInterface={serviceActions.showAddServiceInterface} |
101 | searchRecipes={e => this.searchRecipes(e)} | 117 | searchRecipes={e => this.searchRecipes(e)} |
102 | resetSearch={() => this.resetSearch()} | 118 | resetSearch={() => this.resetSearch()} |
103 | searchNeedle={this.state.needle} | 119 | searchNeedle={this.state.needle} |
104 | serviceStatus={services.actionStatus} | 120 | serviceStatus={services.actionStatus} |
105 | devRecipesCount={recipePreviews.dev.length} | 121 | recipeFilter={filter} |
122 | recipeDirectory={recipeDirectory} | ||
123 | openRecipeDirectory={() => { | ||
124 | shell.openItem(recipeDirectory); | ||
125 | gaEvent('Recipe', 'open-recipe-folder', 'Open Folder'); | ||
126 | }} | ||
127 | openDevDocs={() => { | ||
128 | appActions.openExternalUrl({ url: FRANZ_DEV_DOCS }); | ||
129 | gaEvent('Recipe', 'open-dev-docs', 'Developer Documentation'); | ||
130 | }} | ||
131 | isCommunityRecipesIncludedInCurrentPlan={communityRecipesStore.isCommunityRecipesIncludedInCurrentPlan} | ||
132 | isUserPremiumUser={user.isPremium} | ||
106 | /> | 133 | /> |
107 | </ErrorBoundary> | 134 | </ErrorBoundary> |
108 | ); | 135 | ); |
@@ -117,6 +144,9 @@ RecipesScreen.wrappedComponent.propTypes = { | |||
117 | user: PropTypes.instanceOf(UserStore).isRequired, | 144 | user: PropTypes.instanceOf(UserStore).isRequired, |
118 | }).isRequired, | 145 | }).isRequired, |
119 | actions: PropTypes.shape({ | 146 | actions: PropTypes.shape({ |
147 | app: PropTypes.shape({ | ||
148 | openExternalUrl: PropTypes.func.isRequired, | ||
149 | }).isRequired, | ||
120 | service: PropTypes.shape({ | 150 | service: PropTypes.shape({ |
121 | showAddServiceInterface: PropTypes.func.isRequired, | 151 | showAddServiceInterface: PropTypes.func.isRequired, |
122 | }).isRequired, | 152 | }).isRequired, |
diff --git a/src/features/communityRecipes/index.js b/src/features/communityRecipes/index.js new file mode 100644 index 000000000..4d050f90e --- /dev/null +++ b/src/features/communityRecipes/index.js | |||
@@ -0,0 +1,28 @@ | |||
1 | import { reaction } from 'mobx'; | ||
2 | import { CommunityRecipesStore } from './store'; | ||
3 | |||
4 | const debug = require('debug')('Franz:feature:communityRecipes'); | ||
5 | |||
6 | export const DEFAULT_SERVICE_LIMIT = 3; | ||
7 | |||
8 | export const communityRecipesStore = new CommunityRecipesStore(); | ||
9 | |||
10 | export default function initCommunityRecipes(stores, actions) { | ||
11 | const { features } = stores; | ||
12 | |||
13 | communityRecipesStore.start(stores, actions); | ||
14 | |||
15 | // Toggle communityRecipe premium status | ||
16 | reaction( | ||
17 | () => ( | ||
18 | features.features.isCommunityRecipesIncludedInCurrentPlan | ||
19 | ), | ||
20 | (isPremiumFeature) => { | ||
21 | debug('Community recipes is premium feature: ', isPremiumFeature); | ||
22 | communityRecipesStore.isCommunityRecipesIncludedInCurrentPlan = isPremiumFeature; | ||
23 | }, | ||
24 | { | ||
25 | fireImmediately: true, | ||
26 | }, | ||
27 | ); | ||
28 | } | ||
diff --git a/src/features/communityRecipes/store.js b/src/features/communityRecipes/store.js new file mode 100644 index 000000000..4d45c3b33 --- /dev/null +++ b/src/features/communityRecipes/store.js | |||
@@ -0,0 +1,31 @@ | |||
1 | import { computed, observable } from 'mobx'; | ||
2 | import { FeatureStore } from '../utils/FeatureStore'; | ||
3 | |||
4 | const debug = require('debug')('Franz:feature:communityRecipes:store'); | ||
5 | |||
6 | export class CommunityRecipesStore extends FeatureStore { | ||
7 | @observable isCommunityRecipesIncludedInCurrentPlan = false; | ||
8 | |||
9 | start(stores, actions) { | ||
10 | debug('start'); | ||
11 | this.stores = stores; | ||
12 | this.actions = actions; | ||
13 | } | ||
14 | |||
15 | stop() { | ||
16 | debug('stop'); | ||
17 | super.stop(); | ||
18 | } | ||
19 | |||
20 | @computed get communityRecipes() { | ||
21 | if (!this.stores) return []; | ||
22 | |||
23 | return this.stores.recipePreviews.dev.map((r) => { | ||
24 | r.isDevRecipe = !!r.author.find(a => a.email === this.stores.user.data.email); | ||
25 | |||
26 | return r; | ||
27 | }); | ||
28 | } | ||
29 | } | ||
30 | |||
31 | export default CommunityRecipesStore; | ||
diff --git a/src/features/serviceLimit/components/LimitReachedInfobox.js b/src/features/serviceLimit/components/LimitReachedInfobox.js new file mode 100644 index 000000000..fc54dcf85 --- /dev/null +++ b/src/features/serviceLimit/components/LimitReachedInfobox.js | |||
@@ -0,0 +1,78 @@ | |||
1 | import React, { Component } from 'react'; | ||
2 | import PropTypes from 'prop-types'; | ||
3 | import { inject, observer } from 'mobx-react'; | ||
4 | import { defineMessages, intlShape } from 'react-intl'; | ||
5 | import injectSheet from 'react-jss'; | ||
6 | import { Infobox } from '@meetfranz/ui'; | ||
7 | |||
8 | import { gaEvent } from '../../../lib/analytics'; | ||
9 | |||
10 | const messages = defineMessages({ | ||
11 | limitReached: { | ||
12 | id: 'feature.serviceLimit.limitReached', | ||
13 | defaultMessage: '!!!You have added {amount} of {limit} services. Please upgrade your account to add more services.', | ||
14 | }, | ||
15 | action: { | ||
16 | id: 'premiumFeature.button.upgradeAccount', | ||
17 | defaultMessage: '!!!Upgrade account', | ||
18 | }, | ||
19 | }); | ||
20 | |||
21 | const styles = theme => ({ | ||
22 | container: { | ||
23 | height: 'auto', | ||
24 | background: theme.styleTypes.primary.accent, | ||
25 | color: theme.styleTypes.primary.contrast, | ||
26 | borderRadius: 0, | ||
27 | marginBottom: 0, | ||
28 | |||
29 | '& > div': { | ||
30 | marginBottom: 0, | ||
31 | }, | ||
32 | |||
33 | '& button': { | ||
34 | color: theme.styleTypes.primary.contrast, | ||
35 | }, | ||
36 | }, | ||
37 | }); | ||
38 | |||
39 | |||
40 | @inject('stores', 'actions') @injectSheet(styles) @observer | ||
41 | class LimitReachedInfobox extends Component { | ||
42 | static propTypes = { | ||
43 | classes: PropTypes.object.isRequired, | ||
44 | stores: PropTypes.object.isRequired, | ||
45 | actions: PropTypes.object.isRequired, | ||
46 | }; | ||
47 | |||
48 | static contextTypes = { | ||
49 | intl: intlShape, | ||
50 | }; | ||
51 | |||
52 | render() { | ||
53 | const { classes, stores, actions } = this.props; | ||
54 | const { intl } = this.context; | ||
55 | |||
56 | const { | ||
57 | serviceLimit, | ||
58 | } = stores; | ||
59 | |||
60 | if (!serviceLimit.userHasReachedServiceLimit) return null; | ||
61 | |||
62 | return ( | ||
63 | <Infobox | ||
64 | icon="mdiInformation" | ||
65 | className={classes.container} | ||
66 | ctaLabel={intl.formatMessage(messages.action)} | ||
67 | ctaOnClick={() => { | ||
68 | actions.ui.openSettings({ path: 'user' }); | ||
69 | gaEvent('Service Limit', 'upgrade', 'Upgrade account'); | ||
70 | }} | ||
71 | > | ||
72 | {intl.formatMessage(messages.limitReached, { amount: serviceLimit.serviceCount, limit: serviceLimit.serviceLimit })} | ||
73 | </Infobox> | ||
74 | ); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | export default LimitReachedInfobox; | ||
diff --git a/src/features/serviceLimit/index.js b/src/features/serviceLimit/index.js new file mode 100644 index 000000000..92ad8bb98 --- /dev/null +++ b/src/features/serviceLimit/index.js | |||
@@ -0,0 +1,33 @@ | |||
1 | import { reaction } from 'mobx'; | ||
2 | import { ServiceLimitStore } from './store'; | ||
3 | |||
4 | const debug = require('debug')('Franz:feature:serviceLimit'); | ||
5 | |||
6 | export const DEFAULT_SERVICE_LIMIT = 3; | ||
7 | |||
8 | let store = null; | ||
9 | |||
10 | export const serviceLimitStore = new ServiceLimitStore(); | ||
11 | |||
12 | export default function initServiceLimit(stores, actions) { | ||
13 | const { features } = stores; | ||
14 | |||
15 | // Toggle serviceLimit feature | ||
16 | reaction( | ||
17 | () => ( | ||
18 | features.features.isServiceLimitEnabled | ||
19 | ), | ||
20 | (isEnabled) => { | ||
21 | if (isEnabled) { | ||
22 | debug('Initializing `serviceLimit` feature'); | ||
23 | store = serviceLimitStore.start(stores, actions); | ||
24 | } else if (store) { | ||
25 | debug('Disabling `serviceLimit` feature'); | ||
26 | serviceLimitStore.stop(); | ||
27 | } | ||
28 | }, | ||
29 | { | ||
30 | fireImmediately: true, | ||
31 | }, | ||
32 | ); | ||
33 | } | ||
diff --git a/src/features/serviceLimit/store.js b/src/features/serviceLimit/store.js new file mode 100644 index 000000000..9836c5f51 --- /dev/null +++ b/src/features/serviceLimit/store.js | |||
@@ -0,0 +1,41 @@ | |||
1 | import { computed, observable } from 'mobx'; | ||
2 | import { FeatureStore } from '../utils/FeatureStore'; | ||
3 | import { DEFAULT_SERVICE_LIMIT } from '.'; | ||
4 | |||
5 | const debug = require('debug')('Franz:feature:serviceLimit:store'); | ||
6 | |||
7 | export class ServiceLimitStore extends FeatureStore { | ||
8 | @observable isServiceLimitEnabled = false; | ||
9 | |||
10 | start(stores, actions) { | ||
11 | debug('start'); | ||
12 | this.stores = stores; | ||
13 | this.actions = actions; | ||
14 | |||
15 | this.isServiceLimitEnabled = true; | ||
16 | } | ||
17 | |||
18 | stop() { | ||
19 | super.stop(); | ||
20 | |||
21 | this.isServiceLimitEnabled = false; | ||
22 | } | ||
23 | |||
24 | @computed get userHasReachedServiceLimit() { | ||
25 | if (!this.isServiceLimitEnabled) return false; | ||
26 | |||
27 | return this.serviceLimit !== 0 && this.serviceCount >= this.serviceLimit; | ||
28 | } | ||
29 | |||
30 | @computed get serviceLimit() { | ||
31 | if (!this.isServiceLimitEnabled || this.stores.features.features.serviceLimitCount === 0) return 0; | ||
32 | |||
33 | return this.stores.features.features.serviceLimitCount || DEFAULT_SERVICE_LIMIT; | ||
34 | } | ||
35 | |||
36 | @computed get serviceCount() { | ||
37 | return this.stores.services.all.length; | ||
38 | } | ||
39 | } | ||
40 | |||
41 | export default ServiceLimitStore; | ||
diff --git a/src/features/serviceProxy/index.js b/src/features/serviceProxy/index.js index 4bea327ad..55c600de4 100644 --- a/src/features/serviceProxy/index.js +++ b/src/features/serviceProxy/index.js | |||
@@ -9,17 +9,17 @@ const debug = require('debug')('Franz:feature:serviceProxy'); | |||
9 | 9 | ||
10 | export const config = observable({ | 10 | export const config = observable({ |
11 | isEnabled: DEFAULT_FEATURES_CONFIG.isServiceProxyEnabled, | 11 | isEnabled: DEFAULT_FEATURES_CONFIG.isServiceProxyEnabled, |
12 | isPremium: DEFAULT_FEATURES_CONFIG.isServiceProxyPremiumFeature, | 12 | isPremium: DEFAULT_FEATURES_CONFIG.isServiceProxyIncludedInCurrentPlan, |
13 | }); | 13 | }); |
14 | 14 | ||
15 | export default function init(stores) { | 15 | export default function init(stores) { |
16 | debug('Initializing `serviceProxy` feature'); | 16 | debug('Initializing `serviceProxy` feature'); |
17 | 17 | ||
18 | autorun(() => { | 18 | autorun(() => { |
19 | const { isServiceProxyEnabled, isServiceProxyPremiumFeature } = stores.features.features; | 19 | const { isServiceProxyEnabled, isServiceProxyIncludedInCurrentPlan } = stores.features.features; |
20 | 20 | ||
21 | config.isEnabled = isServiceProxyEnabled !== undefined ? isServiceProxyEnabled : DEFAULT_FEATURES_CONFIG.isServiceProxyEnabled; | 21 | config.isEnabled = isServiceProxyEnabled !== undefined ? isServiceProxyEnabled : DEFAULT_FEATURES_CONFIG.isServiceProxyEnabled; |
22 | config.isPremium = isServiceProxyPremiumFeature !== undefined ? isServiceProxyPremiumFeature : DEFAULT_FEATURES_CONFIG.isServiceProxyPremiumFeature; | 22 | config.isIncludedInCurrentPlan = isServiceProxyIncludedInCurrentPlan !== undefined ? isServiceProxyIncludedInCurrentPlan : DEFAULT_FEATURES_CONFIG.isServiceProxyIncludedInCurrentPlan; |
23 | 23 | ||
24 | const services = stores.services.enabled; | 24 | const services = stores.services.enabled; |
25 | const isPremiumUser = stores.user.data.isPremium; | 25 | const isPremiumUser = stores.user.data.isPremium; |
@@ -30,7 +30,7 @@ export default function init(stores) { | |||
30 | services.forEach((service) => { | 30 | services.forEach((service) => { |
31 | const s = session.fromPartition(`persist:service-${service.id}`); | 31 | const s = session.fromPartition(`persist:service-${service.id}`); |
32 | 32 | ||
33 | if (config.isEnabled && (isPremiumUser || !config.isPremium)) { | 33 | if (config.isEnabled && (isPremiumUser || !config.isIncludedInCurrentPlan)) { |
34 | const serviceProxyConfig = proxySettings[service.id]; | 34 | const serviceProxyConfig = proxySettings[service.id]; |
35 | 35 | ||
36 | if (serviceProxyConfig && serviceProxyConfig.isEnabled && serviceProxyConfig.host) { | 36 | if (serviceProxyConfig && serviceProxyConfig.isEnabled && serviceProxyConfig.host) { |
diff --git a/src/features/spellchecker/index.js b/src/features/spellchecker/index.js index 79a2172b4..a07f9f63a 100644 --- a/src/features/spellchecker/index.js +++ b/src/features/spellchecker/index.js | |||
@@ -5,18 +5,18 @@ import { DEFAULT_FEATURES_CONFIG } from '../../config'; | |||
5 | const debug = require('debug')('Franz:feature:spellchecker'); | 5 | const debug = require('debug')('Franz:feature:spellchecker'); |
6 | 6 | ||
7 | export const config = observable({ | 7 | export const config = observable({ |
8 | isPremium: DEFAULT_FEATURES_CONFIG.isSpellcheckerPremiumFeature, | 8 | isIncludedInCurrentPlan: DEFAULT_FEATURES_CONFIG.isSpellcheckerIncludedInCurrentPlan, |
9 | }); | 9 | }); |
10 | 10 | ||
11 | export default function init(stores) { | 11 | export default function init(stores) { |
12 | debug('Initializing `spellchecker` feature'); | 12 | debug('Initializing `spellchecker` feature'); |
13 | 13 | ||
14 | autorun(() => { | 14 | autorun(() => { |
15 | const { isSpellcheckerPremiumFeature } = stores.features.features; | 15 | const { isSpellcheckerIncludedInCurrentPlan } = stores.features.features; |
16 | 16 | ||
17 | config.isPremium = isSpellcheckerPremiumFeature !== undefined ? isSpellcheckerPremiumFeature : DEFAULT_FEATURES_CONFIG.isSpellcheckerPremiumFeature; | 17 | config.isIncludedInCurrentPlan = isSpellcheckerIncludedInCurrentPlan !== undefined ? isSpellcheckerIncludedInCurrentPlan : DEFAULT_FEATURES_CONFIG.isSpellcheckerIncludedInCurrentPlan; |
18 | 18 | ||
19 | if (!stores.user.data.isPremium && config.isPremium && stores.settings.app.enableSpellchecking) { | 19 | if (!stores.user.data.isPremium && config.isIncludedInCurrentPlan && stores.settings.app.enableSpellchecking) { |
20 | debug('Override settings.spellcheckerEnabled flag to false'); | 20 | debug('Override settings.spellcheckerEnabled flag to false'); |
21 | 21 | ||
22 | Object.assign(stores.settings.app, { | 22 | Object.assign(stores.settings.app, { |
diff --git a/src/features/workspaces/store.js b/src/features/workspaces/store.js index 07b16ff23..e1adc9cab 100644 --- a/src/features/workspaces/store.js +++ b/src/features/workspaces/store.js | |||
@@ -251,9 +251,9 @@ export default class WorkspacesStore extends FeatureStore { | |||
251 | _setIsPremiumFeatureReaction = () => { | 251 | _setIsPremiumFeatureReaction = () => { |
252 | const { features, user } = this.stores; | 252 | const { features, user } = this.stores; |
253 | const { isPremium } = user.data; | 253 | const { isPremium } = user.data; |
254 | const { isWorkspacePremiumFeature } = features.features; | 254 | const { isWorkspaceIncludedInCurrentPlan } = features.features; |
255 | this.isPremiumFeature = isWorkspacePremiumFeature; | 255 | this.isPremiumFeature = isWorkspaceIncludedInCurrentPlan; |
256 | this.isPremiumUpgradeRequired = isWorkspacePremiumFeature && !isPremium; | 256 | this.isPremiumUpgradeRequired = isWorkspaceIncludedInCurrentPlan && !isPremium; |
257 | }; | 257 | }; |
258 | 258 | ||
259 | _setWorkspaceBeingEditedReaction = () => { | 259 | _setWorkspaceBeingEditedReaction = () => { |
diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json index d517b456b..3d11a372d 100644 --- a/src/i18n/locales/defaultMessages.json +++ b/src/i18n/locales/defaultMessages.json | |||
@@ -894,6 +894,76 @@ | |||
894 | { | 894 | { |
895 | "descriptors": [ | 895 | "descriptors": [ |
896 | { | 896 | { |
897 | "defaultMessage": "!!!You have reached your service limit.", | ||
898 | "end": { | ||
899 | "column": 3, | ||
900 | "line": 14 | ||
901 | }, | ||
902 | "file": "src/components/services/content/ServiceRestricted.js", | ||
903 | "id": "service.restrictedHandler.serviceLimit.headline", | ||
904 | "start": { | ||
905 | "column": 24, | ||
906 | "line": 11 | ||
907 | } | ||
908 | }, | ||
909 | { | ||
910 | "defaultMessage": "!!!Please upgrade your account to use more than {count} services.", | ||
911 | "end": { | ||
912 | "column": 3, | ||
913 | "line": 18 | ||
914 | }, | ||
915 | "file": "src/components/services/content/ServiceRestricted.js", | ||
916 | "id": "service.restrictedHandler.serviceLimit.text", | ||
917 | "start": { | ||
918 | "column": 20, | ||
919 | "line": 15 | ||
920 | } | ||
921 | }, | ||
922 | { | ||
923 | "defaultMessage": "!!!Franz Professional Plan required", | ||
924 | "end": { | ||
925 | "column": 3, | ||
926 | "line": 22 | ||
927 | }, | ||
928 | "file": "src/components/services/content/ServiceRestricted.js", | ||
929 | "id": "service.restrictedHandler.customUrl.headline", | ||
930 | "start": { | ||
931 | "column": 21, | ||
932 | "line": 19 | ||
933 | } | ||
934 | }, | ||
935 | { | ||
936 | "defaultMessage": "!!!Please upgrade to the Franz Professional plan to use custom urls & self hosted services.", | ||
937 | "end": { | ||
938 | "column": 3, | ||
939 | "line": 26 | ||
940 | }, | ||
941 | "file": "src/components/services/content/ServiceRestricted.js", | ||
942 | "id": "service.restrictedHandler.customUrl.text", | ||
943 | "start": { | ||
944 | "column": 17, | ||
945 | "line": 23 | ||
946 | } | ||
947 | }, | ||
948 | { | ||
949 | "defaultMessage": "!!!Upgrade Account", | ||
950 | "end": { | ||
951 | "column": 3, | ||
952 | "line": 30 | ||
953 | }, | ||
954 | "file": "src/components/services/content/ServiceRestricted.js", | ||
955 | "id": "service.restrictedHandler.action", | ||
956 | "start": { | ||
957 | "column": 10, | ||
958 | "line": 27 | ||
959 | } | ||
960 | } | ||
961 | ], | ||
962 | "path": "src/components/services/content/ServiceRestricted.json" | ||
963 | }, | ||
964 | { | ||
965 | "descriptors": [ | ||
966 | { | ||
897 | "defaultMessage": "!!!Welcome to Franz", | 967 | "defaultMessage": "!!!Welcome to Franz", |
898 | "end": { | 968 | "end": { |
899 | "column": 3, | 969 | "column": 3, |
@@ -1307,104 +1377,104 @@ | |||
1307 | "defaultMessage": "!!!Available services", | 1377 | "defaultMessage": "!!!Available services", |
1308 | "end": { | 1378 | "end": { |
1309 | "column": 3, | 1379 | "column": 3, |
1310 | "line": 16 | 1380 | "line": 17 |
1311 | }, | 1381 | }, |
1312 | "file": "src/components/settings/navigation/SettingsNavigation.js", | 1382 | "file": "src/components/settings/navigation/SettingsNavigation.js", |
1313 | "id": "settings.navigation.availableServices", | 1383 | "id": "settings.navigation.availableServices", |
1314 | "start": { | 1384 | "start": { |
1315 | "column": 21, | 1385 | "column": 21, |
1316 | "line": 13 | 1386 | "line": 14 |
1317 | } | 1387 | } |
1318 | }, | 1388 | }, |
1319 | { | 1389 | { |
1320 | "defaultMessage": "!!!Your services", | 1390 | "defaultMessage": "!!!Your services", |
1321 | "end": { | 1391 | "end": { |
1322 | "column": 3, | 1392 | "column": 3, |
1323 | "line": 20 | 1393 | "line": 21 |
1324 | }, | 1394 | }, |
1325 | "file": "src/components/settings/navigation/SettingsNavigation.js", | 1395 | "file": "src/components/settings/navigation/SettingsNavigation.js", |
1326 | "id": "settings.navigation.yourServices", | 1396 | "id": "settings.navigation.yourServices", |
1327 | "start": { | 1397 | "start": { |
1328 | "column": 16, | 1398 | "column": 16, |
1329 | "line": 17 | 1399 | "line": 18 |
1330 | } | 1400 | } |
1331 | }, | 1401 | }, |
1332 | { | 1402 | { |
1333 | "defaultMessage": "!!!Your workspaces", | 1403 | "defaultMessage": "!!!Your workspaces", |
1334 | "end": { | 1404 | "end": { |
1335 | "column": 3, | 1405 | "column": 3, |
1336 | "line": 24 | 1406 | "line": 25 |
1337 | }, | 1407 | }, |
1338 | "file": "src/components/settings/navigation/SettingsNavigation.js", | 1408 | "file": "src/components/settings/navigation/SettingsNavigation.js", |
1339 | "id": "settings.navigation.yourWorkspaces", | 1409 | "id": "settings.navigation.yourWorkspaces", |
1340 | "start": { | 1410 | "start": { |
1341 | "column": 18, | 1411 | "column": 18, |
1342 | "line": 21 | 1412 | "line": 22 |
1343 | } | 1413 | } |
1344 | }, | 1414 | }, |
1345 | { | 1415 | { |
1346 | "defaultMessage": "!!!Account", | 1416 | "defaultMessage": "!!!Account", |
1347 | "end": { | 1417 | "end": { |
1348 | "column": 3, | 1418 | "column": 3, |
1349 | "line": 28 | 1419 | "line": 29 |
1350 | }, | 1420 | }, |
1351 | "file": "src/components/settings/navigation/SettingsNavigation.js", | 1421 | "file": "src/components/settings/navigation/SettingsNavigation.js", |
1352 | "id": "settings.navigation.account", | 1422 | "id": "settings.navigation.account", |
1353 | "start": { | 1423 | "start": { |
1354 | "column": 11, | 1424 | "column": 11, |
1355 | "line": 25 | 1425 | "line": 26 |
1356 | } | 1426 | } |
1357 | }, | 1427 | }, |
1358 | { | 1428 | { |
1359 | "defaultMessage": "!!!Manage Team", | 1429 | "defaultMessage": "!!!Manage Team", |
1360 | "end": { | 1430 | "end": { |
1361 | "column": 3, | 1431 | "column": 3, |
1362 | "line": 32 | 1432 | "line": 33 |
1363 | }, | 1433 | }, |
1364 | "file": "src/components/settings/navigation/SettingsNavigation.js", | 1434 | "file": "src/components/settings/navigation/SettingsNavigation.js", |
1365 | "id": "settings.navigation.team", | 1435 | "id": "settings.navigation.team", |
1366 | "start": { | 1436 | "start": { |
1367 | "column": 8, | 1437 | "column": 8, |
1368 | "line": 29 | 1438 | "line": 30 |
1369 | } | 1439 | } |
1370 | }, | 1440 | }, |
1371 | { | 1441 | { |
1372 | "defaultMessage": "!!!Settings", | 1442 | "defaultMessage": "!!!Settings", |
1373 | "end": { | 1443 | "end": { |
1374 | "column": 3, | 1444 | "column": 3, |
1375 | "line": 36 | 1445 | "line": 37 |
1376 | }, | 1446 | }, |
1377 | "file": "src/components/settings/navigation/SettingsNavigation.js", | 1447 | "file": "src/components/settings/navigation/SettingsNavigation.js", |
1378 | "id": "settings.navigation.settings", | 1448 | "id": "settings.navigation.settings", |
1379 | "start": { | 1449 | "start": { |
1380 | "column": 12, | 1450 | "column": 12, |
1381 | "line": 33 | 1451 | "line": 34 |
1382 | } | 1452 | } |
1383 | }, | 1453 | }, |
1384 | { | 1454 | { |
1385 | "defaultMessage": "!!!Invite Friends", | 1455 | "defaultMessage": "!!!Invite Friends", |
1386 | "end": { | 1456 | "end": { |
1387 | "column": 3, | 1457 | "column": 3, |
1388 | "line": 40 | 1458 | "line": 41 |
1389 | }, | 1459 | }, |
1390 | "file": "src/components/settings/navigation/SettingsNavigation.js", | 1460 | "file": "src/components/settings/navigation/SettingsNavigation.js", |
1391 | "id": "settings.navigation.inviteFriends", | 1461 | "id": "settings.navigation.inviteFriends", |
1392 | "start": { | 1462 | "start": { |
1393 | "column": 17, | 1463 | "column": 17, |
1394 | "line": 37 | 1464 | "line": 38 |
1395 | } | 1465 | } |
1396 | }, | 1466 | }, |
1397 | { | 1467 | { |
1398 | "defaultMessage": "!!!Logout", | 1468 | "defaultMessage": "!!!Logout", |
1399 | "end": { | 1469 | "end": { |
1400 | "column": 3, | 1470 | "column": 3, |
1401 | "line": 44 | 1471 | "line": 45 |
1402 | }, | 1472 | }, |
1403 | "file": "src/components/settings/navigation/SettingsNavigation.js", | 1473 | "file": "src/components/settings/navigation/SettingsNavigation.js", |
1404 | "id": "settings.navigation.logout", | 1474 | "id": "settings.navigation.logout", |
1405 | "start": { | 1475 | "start": { |
1406 | "column": 10, | 1476 | "column": 10, |
1407 | "line": 41 | 1477 | "line": 42 |
1408 | } | 1478 | } |
1409 | } | 1479 | } |
1410 | ], | 1480 | ], |
@@ -1416,104 +1486,182 @@ | |||
1416 | "defaultMessage": "!!!Available Services", | 1486 | "defaultMessage": "!!!Available Services", |
1417 | "end": { | 1487 | "end": { |
1418 | "column": 3, | 1488 | "column": 3, |
1419 | "line": 18 | 1489 | "line": 23 |
1420 | }, | 1490 | }, |
1421 | "file": "src/components/settings/recipes/RecipesDashboard.js", | 1491 | "file": "src/components/settings/recipes/RecipesDashboard.js", |
1422 | "id": "settings.recipes.headline", | 1492 | "id": "settings.recipes.headline", |
1423 | "start": { | 1493 | "start": { |
1424 | "column": 12, | 1494 | "column": 12, |
1425 | "line": 15 | 1495 | "line": 20 |
1426 | } | 1496 | } |
1427 | }, | 1497 | }, |
1428 | { | 1498 | { |
1429 | "defaultMessage": "!!!Search service", | 1499 | "defaultMessage": "!!!Search service", |
1430 | "end": { | 1500 | "end": { |
1431 | "column": 3, | 1501 | "column": 3, |
1432 | "line": 22 | 1502 | "line": 27 |
1433 | }, | 1503 | }, |
1434 | "file": "src/components/settings/recipes/RecipesDashboard.js", | 1504 | "file": "src/components/settings/recipes/RecipesDashboard.js", |
1435 | "id": "settings.searchService", | 1505 | "id": "settings.searchService", |
1436 | "start": { | 1506 | "start": { |
1437 | "column": 17, | 1507 | "column": 17, |
1438 | "line": 19 | 1508 | "line": 24 |
1439 | } | 1509 | } |
1440 | }, | 1510 | }, |
1441 | { | 1511 | { |
1442 | "defaultMessage": "!!!Most popular", | 1512 | "defaultMessage": "!!!Most popular", |
1443 | "end": { | 1513 | "end": { |
1444 | "column": 3, | 1514 | "column": 3, |
1445 | "line": 26 | 1515 | "line": 31 |
1446 | }, | 1516 | }, |
1447 | "file": "src/components/settings/recipes/RecipesDashboard.js", | 1517 | "file": "src/components/settings/recipes/RecipesDashboard.js", |
1448 | "id": "settings.recipes.mostPopular", | 1518 | "id": "settings.recipes.mostPopular", |
1449 | "start": { | 1519 | "start": { |
1450 | "column": 22, | 1520 | "column": 22, |
1451 | "line": 23 | 1521 | "line": 28 |
1452 | } | 1522 | } |
1453 | }, | 1523 | }, |
1454 | { | 1524 | { |
1455 | "defaultMessage": "!!!All services", | 1525 | "defaultMessage": "!!!All services", |
1456 | "end": { | 1526 | "end": { |
1457 | "column": 3, | 1527 | "column": 3, |
1458 | "line": 30 | 1528 | "line": 35 |
1459 | }, | 1529 | }, |
1460 | "file": "src/components/settings/recipes/RecipesDashboard.js", | 1530 | "file": "src/components/settings/recipes/RecipesDashboard.js", |
1461 | "id": "settings.recipes.all", | 1531 | "id": "settings.recipes.all", |
1462 | "start": { | 1532 | "start": { |
1463 | "column": 14, | 1533 | "column": 14, |
1464 | "line": 27 | 1534 | "line": 32 |
1465 | } | 1535 | } |
1466 | }, | 1536 | }, |
1467 | { | 1537 | { |
1468 | "defaultMessage": "!!!Development", | 1538 | "defaultMessage": "!!!Custom Services", |
1469 | "end": { | 1539 | "end": { |
1470 | "column": 3, | 1540 | "column": 3, |
1471 | "line": 34 | 1541 | "line": 39 |
1472 | }, | 1542 | }, |
1473 | "file": "src/components/settings/recipes/RecipesDashboard.js", | 1543 | "file": "src/components/settings/recipes/RecipesDashboard.js", |
1474 | "id": "settings.recipes.dev", | 1544 | "id": "settings.recipes.custom", |
1475 | "start": { | 1545 | "start": { |
1476 | "column": 14, | 1546 | "column": 17, |
1477 | "line": 31 | 1547 | "line": 36 |
1478 | } | 1548 | } |
1479 | }, | 1549 | }, |
1480 | { | 1550 | { |
1481 | "defaultMessage": "!!!Sorry, but no service matched your search term.", | 1551 | "defaultMessage": "!!!Sorry, but no service matched your search term.", |
1482 | "end": { | 1552 | "end": { |
1483 | "column": 3, | 1553 | "column": 3, |
1484 | "line": 38 | 1554 | "line": 43 |
1485 | }, | 1555 | }, |
1486 | "file": "src/components/settings/recipes/RecipesDashboard.js", | 1556 | "file": "src/components/settings/recipes/RecipesDashboard.js", |
1487 | "id": "settings.recipes.nothingFound", | 1557 | "id": "settings.recipes.nothingFound", |
1488 | "start": { | 1558 | "start": { |
1489 | "column": 16, | 1559 | "column": 16, |
1490 | "line": 35 | 1560 | "line": 40 |
1491 | } | 1561 | } |
1492 | }, | 1562 | }, |
1493 | { | 1563 | { |
1494 | "defaultMessage": "!!!Service successfully added", | 1564 | "defaultMessage": "!!!Service successfully added", |
1495 | "end": { | 1565 | "end": { |
1496 | "column": 3, | 1566 | "column": 3, |
1497 | "line": 42 | 1567 | "line": 47 |
1498 | }, | 1568 | }, |
1499 | "file": "src/components/settings/recipes/RecipesDashboard.js", | 1569 | "file": "src/components/settings/recipes/RecipesDashboard.js", |
1500 | "id": "settings.recipes.servicesSuccessfulAddedInfo", | 1570 | "id": "settings.recipes.servicesSuccessfulAddedInfo", |
1501 | "start": { | 1571 | "start": { |
1502 | "column": 31, | 1572 | "column": 31, |
1503 | "line": 39 | 1573 | "line": 44 |
1504 | } | 1574 | } |
1505 | }, | 1575 | }, |
1506 | { | 1576 | { |
1507 | "defaultMessage": "!!!Missing a service?", | 1577 | "defaultMessage": "!!!Missing a service?", |
1508 | "end": { | 1578 | "end": { |
1509 | "column": 3, | 1579 | "column": 3, |
1510 | "line": 46 | 1580 | "line": 51 |
1511 | }, | 1581 | }, |
1512 | "file": "src/components/settings/recipes/RecipesDashboard.js", | 1582 | "file": "src/components/settings/recipes/RecipesDashboard.js", |
1513 | "id": "settings.recipes.missingService", | 1583 | "id": "settings.recipes.missingService", |
1514 | "start": { | 1584 | "start": { |
1515 | "column": 18, | 1585 | "column": 18, |
1516 | "line": 43 | 1586 | "line": 48 |
1587 | } | ||
1588 | }, | ||
1589 | { | ||
1590 | "defaultMessage": "!!!To add a custom service, copy the recipe folder into:", | ||
1591 | "end": { | ||
1592 | "column": 3, | ||
1593 | "line": 55 | ||
1594 | }, | ||
1595 | "file": "src/components/settings/recipes/RecipesDashboard.js", | ||
1596 | "id": "settings.recipes.customService.intro", | ||
1597 | "start": { | ||
1598 | "column": 21, | ||
1599 | "line": 52 | ||
1600 | } | ||
1601 | }, | ||
1602 | { | ||
1603 | "defaultMessage": "!!!Open directory", | ||
1604 | "end": { | ||
1605 | "column": 3, | ||
1606 | "line": 59 | ||
1607 | }, | ||
1608 | "file": "src/components/settings/recipes/RecipesDashboard.js", | ||
1609 | "id": "settings.recipes.customService.openFolder", | ||
1610 | "start": { | ||
1611 | "column": 14, | ||
1612 | "line": 56 | ||
1613 | } | ||
1614 | }, | ||
1615 | { | ||
1616 | "defaultMessage": "!!!Developer Documentation", | ||
1617 | "end": { | ||
1618 | "column": 3, | ||
1619 | "line": 63 | ||
1620 | }, | ||
1621 | "file": "src/components/settings/recipes/RecipesDashboard.js", | ||
1622 | "id": "settings.recipes.customService.openDevDocs", | ||
1623 | "start": { | ||
1624 | "column": 15, | ||
1625 | "line": 60 | ||
1626 | } | ||
1627 | }, | ||
1628 | { | ||
1629 | "defaultMessage": "!!!Custom Service Recipes", | ||
1630 | "end": { | ||
1631 | "column": 3, | ||
1632 | "line": 67 | ||
1633 | }, | ||
1634 | "file": "src/components/settings/recipes/RecipesDashboard.js", | ||
1635 | "id": "settings.recipes.customService.headline.customRecipes", | ||
1636 | "start": { | ||
1637 | "column": 25, | ||
1638 | "line": 64 | ||
1639 | } | ||
1640 | }, | ||
1641 | { | ||
1642 | "defaultMessage": "!!!Community Services", | ||
1643 | "end": { | ||
1644 | "column": 3, | ||
1645 | "line": 71 | ||
1646 | }, | ||
1647 | "file": "src/components/settings/recipes/RecipesDashboard.js", | ||
1648 | "id": "settings.recipes.customService.headline.communityRecipes", | ||
1649 | "start": { | ||
1650 | "column": 28, | ||
1651 | "line": 68 | ||
1652 | } | ||
1653 | }, | ||
1654 | { | ||
1655 | "defaultMessage": "!!!Your Development Service Recipes", | ||
1656 | "end": { | ||
1657 | "column": 3, | ||
1658 | "line": 75 | ||
1659 | }, | ||
1660 | "file": "src/components/settings/recipes/RecipesDashboard.js", | ||
1661 | "id": "settings.recipes.customService.headline.devRecipes", | ||
1662 | "start": { | ||
1663 | "column": 22, | ||
1664 | "line": 72 | ||
1517 | } | 1665 | } |
1518 | } | 1666 | } |
1519 | ], | 1667 | ], |
@@ -1525,286 +1673,286 @@ | |||
1525 | "defaultMessage": "!!!Save service", | 1673 | "defaultMessage": "!!!Save service", |
1526 | "end": { | 1674 | "end": { |
1527 | "column": 3, | 1675 | "column": 3, |
1528 | "line": 25 | 1676 | "line": 27 |
1529 | }, | 1677 | }, |
1530 | "file": "src/components/settings/services/EditServiceForm.js", | 1678 | "file": "src/components/settings/services/EditServiceForm.js", |
1531 | "id": "settings.service.form.saveButton", | 1679 | "id": "settings.service.form.saveButton", |
1532 | "start": { | 1680 | "start": { |
1533 | "column": 15, | 1681 | "column": 15, |
1534 | "line": 22 | 1682 | "line": 24 |
1535 | } | 1683 | } |
1536 | }, | 1684 | }, |
1537 | { | 1685 | { |
1538 | "defaultMessage": "!!!Delete Service", | 1686 | "defaultMessage": "!!!Delete Service", |
1539 | "end": { | 1687 | "end": { |
1540 | "column": 3, | 1688 | "column": 3, |
1541 | "line": 29 | 1689 | "line": 31 |
1542 | }, | 1690 | }, |
1543 | "file": "src/components/settings/services/EditServiceForm.js", | 1691 | "file": "src/components/settings/services/EditServiceForm.js", |
1544 | "id": "settings.service.form.deleteButton", | 1692 | "id": "settings.service.form.deleteButton", |
1545 | "start": { | 1693 | "start": { |
1546 | "column": 17, | 1694 | "column": 17, |
1547 | "line": 26 | 1695 | "line": 28 |
1548 | } | 1696 | } |
1549 | }, | 1697 | }, |
1550 | { | 1698 | { |
1551 | "defaultMessage": "!!!Available services", | 1699 | "defaultMessage": "!!!Available services", |
1552 | "end": { | 1700 | "end": { |
1553 | "column": 3, | 1701 | "column": 3, |
1554 | "line": 33 | 1702 | "line": 35 |
1555 | }, | 1703 | }, |
1556 | "file": "src/components/settings/services/EditServiceForm.js", | 1704 | "file": "src/components/settings/services/EditServiceForm.js", |
1557 | "id": "settings.service.form.availableServices", | 1705 | "id": "settings.service.form.availableServices", |
1558 | "start": { | 1706 | "start": { |
1559 | "column": 21, | 1707 | "column": 21, |
1560 | "line": 30 | 1708 | "line": 32 |
1561 | } | 1709 | } |
1562 | }, | 1710 | }, |
1563 | { | 1711 | { |
1564 | "defaultMessage": "!!!Your services", | 1712 | "defaultMessage": "!!!Your services", |
1565 | "end": { | 1713 | "end": { |
1566 | "column": 3, | 1714 | "column": 3, |
1567 | "line": 37 | 1715 | "line": 39 |
1568 | }, | 1716 | }, |
1569 | "file": "src/components/settings/services/EditServiceForm.js", | 1717 | "file": "src/components/settings/services/EditServiceForm.js", |
1570 | "id": "settings.service.form.yourServices", | 1718 | "id": "settings.service.form.yourServices", |
1571 | "start": { | 1719 | "start": { |
1572 | "column": 16, | 1720 | "column": 16, |
1573 | "line": 34 | 1721 | "line": 36 |
1574 | } | 1722 | } |
1575 | }, | 1723 | }, |
1576 | { | 1724 | { |
1577 | "defaultMessage": "!!!Add {name}", | 1725 | "defaultMessage": "!!!Add {name}", |
1578 | "end": { | 1726 | "end": { |
1579 | "column": 3, | 1727 | "column": 3, |
1580 | "line": 41 | 1728 | "line": 43 |
1581 | }, | 1729 | }, |
1582 | "file": "src/components/settings/services/EditServiceForm.js", | 1730 | "file": "src/components/settings/services/EditServiceForm.js", |
1583 | "id": "settings.service.form.addServiceHeadline", | 1731 | "id": "settings.service.form.addServiceHeadline", |
1584 | "start": { | 1732 | "start": { |
1585 | "column": 22, | 1733 | "column": 22, |
1586 | "line": 38 | 1734 | "line": 40 |
1587 | } | 1735 | } |
1588 | }, | 1736 | }, |
1589 | { | 1737 | { |
1590 | "defaultMessage": "!!!Edit {name}", | 1738 | "defaultMessage": "!!!Edit {name}", |
1591 | "end": { | 1739 | "end": { |
1592 | "column": 3, | 1740 | "column": 3, |
1593 | "line": 45 | 1741 | "line": 47 |
1594 | }, | 1742 | }, |
1595 | "file": "src/components/settings/services/EditServiceForm.js", | 1743 | "file": "src/components/settings/services/EditServiceForm.js", |
1596 | "id": "settings.service.form.editServiceHeadline", | 1744 | "id": "settings.service.form.editServiceHeadline", |
1597 | "start": { | 1745 | "start": { |
1598 | "column": 23, | 1746 | "column": 23, |
1599 | "line": 42 | 1747 | "line": 44 |
1600 | } | 1748 | } |
1601 | }, | 1749 | }, |
1602 | { | 1750 | { |
1603 | "defaultMessage": "!!!Hosted", | 1751 | "defaultMessage": "!!!Hosted", |
1604 | "end": { | 1752 | "end": { |
1605 | "column": 3, | 1753 | "column": 3, |
1606 | "line": 49 | 1754 | "line": 51 |
1607 | }, | 1755 | }, |
1608 | "file": "src/components/settings/services/EditServiceForm.js", | 1756 | "file": "src/components/settings/services/EditServiceForm.js", |
1609 | "id": "settings.service.form.tabHosted", | 1757 | "id": "settings.service.form.tabHosted", |
1610 | "start": { | 1758 | "start": { |
1611 | "column": 13, | 1759 | "column": 13, |
1612 | "line": 46 | 1760 | "line": 48 |
1613 | } | 1761 | } |
1614 | }, | 1762 | }, |
1615 | { | 1763 | { |
1616 | "defaultMessage": "!!!Self hosted ⭐️", | 1764 | "defaultMessage": "!!!Self hosted ⭐️", |
1617 | "end": { | 1765 | "end": { |
1618 | "column": 3, | 1766 | "column": 3, |
1619 | "line": 53 | 1767 | "line": 55 |
1620 | }, | 1768 | }, |
1621 | "file": "src/components/settings/services/EditServiceForm.js", | 1769 | "file": "src/components/settings/services/EditServiceForm.js", |
1622 | "id": "settings.service.form.tabOnPremise", | 1770 | "id": "settings.service.form.tabOnPremise", |
1623 | "start": { | 1771 | "start": { |
1624 | "column": 16, | 1772 | "column": 16, |
1625 | "line": 50 | 1773 | "line": 52 |
1626 | } | 1774 | } |
1627 | }, | 1775 | }, |
1628 | { | 1776 | { |
1629 | "defaultMessage": "!!!Use the hosted {name} service.", | 1777 | "defaultMessage": "!!!Use the hosted {name} service.", |
1630 | "end": { | 1778 | "end": { |
1631 | "column": 3, | 1779 | "column": 3, |
1632 | "line": 57 | 1780 | "line": 59 |
1633 | }, | 1781 | }, |
1634 | "file": "src/components/settings/services/EditServiceForm.js", | 1782 | "file": "src/components/settings/services/EditServiceForm.js", |
1635 | "id": "settings.service.form.useHostedService", | 1783 | "id": "settings.service.form.useHostedService", |
1636 | "start": { | 1784 | "start": { |
1637 | "column": 20, | 1785 | "column": 20, |
1638 | "line": 54 | 1786 | "line": 56 |
1639 | } | 1787 | } |
1640 | }, | 1788 | }, |
1641 | { | 1789 | { |
1642 | "defaultMessage": "!!!Could not validate custom {name} server.", | 1790 | "defaultMessage": "!!!Could not validate custom {name} server.", |
1643 | "end": { | 1791 | "end": { |
1644 | "column": 3, | 1792 | "column": 3, |
1645 | "line": 61 | 1793 | "line": 63 |
1646 | }, | 1794 | }, |
1647 | "file": "src/components/settings/services/EditServiceForm.js", | 1795 | "file": "src/components/settings/services/EditServiceForm.js", |
1648 | "id": "settings.service.form.customUrlValidationError", | 1796 | "id": "settings.service.form.customUrlValidationError", |
1649 | "start": { | 1797 | "start": { |
1650 | "column": 28, | 1798 | "column": 28, |
1651 | "line": 58 | 1799 | "line": 60 |
1652 | } | 1800 | } |
1653 | }, | 1801 | }, |
1654 | { | 1802 | { |
1655 | "defaultMessage": "!!!To add self hosted services, you need a Franz Premium Supporter Account.", | 1803 | "defaultMessage": "!!!To add self hosted services, you need a Franz Premium Supporter Account.", |
1656 | "end": { | 1804 | "end": { |
1657 | "column": 3, | 1805 | "column": 3, |
1658 | "line": 65 | 1806 | "line": 67 |
1659 | }, | 1807 | }, |
1660 | "file": "src/components/settings/services/EditServiceForm.js", | 1808 | "file": "src/components/settings/services/EditServiceForm.js", |
1661 | "id": "settings.service.form.customUrlPremiumInfo", | 1809 | "id": "settings.service.form.customUrlPremiumInfo", |
1662 | "start": { | 1810 | "start": { |
1663 | "column": 24, | 1811 | "column": 24, |
1664 | "line": 62 | 1812 | "line": 64 |
1665 | } | 1813 | } |
1666 | }, | 1814 | }, |
1667 | { | 1815 | { |
1668 | "defaultMessage": "!!!Upgrade your account", | 1816 | "defaultMessage": "!!!Upgrade your account", |
1669 | "end": { | 1817 | "end": { |
1670 | "column": 3, | 1818 | "column": 3, |
1671 | "line": 69 | 1819 | "line": 71 |
1672 | }, | 1820 | }, |
1673 | "file": "src/components/settings/services/EditServiceForm.js", | 1821 | "file": "src/components/settings/services/EditServiceForm.js", |
1674 | "id": "settings.service.form.customUrlUpgradeAccount", | 1822 | "id": "settings.service.form.customUrlUpgradeAccount", |
1675 | "start": { | 1823 | "start": { |
1676 | "column": 27, | 1824 | "column": 27, |
1677 | "line": 66 | 1825 | "line": 68 |
1678 | } | 1826 | } |
1679 | }, | 1827 | }, |
1680 | { | 1828 | { |
1681 | "defaultMessage": "!!!You will be notified about all new messages in a channel, not just @username, @channel, @here, ...", | 1829 | "defaultMessage": "!!!You will be notified about all new messages in a channel, not just @username, @channel, @here, ...", |
1682 | "end": { | 1830 | "end": { |
1683 | "column": 3, | 1831 | "column": 3, |
1684 | "line": 73 | 1832 | "line": 75 |
1685 | }, | 1833 | }, |
1686 | "file": "src/components/settings/services/EditServiceForm.js", | 1834 | "file": "src/components/settings/services/EditServiceForm.js", |
1687 | "id": "settings.service.form.indirectMessageInfo", | 1835 | "id": "settings.service.form.indirectMessageInfo", |
1688 | "start": { | 1836 | "start": { |
1689 | "column": 23, | 1837 | "column": 23, |
1690 | "line": 70 | 1838 | "line": 72 |
1691 | } | 1839 | } |
1692 | }, | 1840 | }, |
1693 | { | 1841 | { |
1694 | "defaultMessage": "!!!When disabled, all notification sounds and audio playback are muted", | 1842 | "defaultMessage": "!!!When disabled, all notification sounds and audio playback are muted", |
1695 | "end": { | 1843 | "end": { |
1696 | "column": 3, | 1844 | "column": 3, |
1697 | "line": 77 | 1845 | "line": 79 |
1698 | }, | 1846 | }, |
1699 | "file": "src/components/settings/services/EditServiceForm.js", | 1847 | "file": "src/components/settings/services/EditServiceForm.js", |
1700 | "id": "settings.service.form.isMutedInfo", | 1848 | "id": "settings.service.form.isMutedInfo", |
1701 | "start": { | 1849 | "start": { |
1702 | "column": 15, | 1850 | "column": 15, |
1703 | "line": 74 | 1851 | "line": 76 |
1704 | } | 1852 | } |
1705 | }, | 1853 | }, |
1706 | { | 1854 | { |
1707 | "defaultMessage": "!!!Notifications", | 1855 | "defaultMessage": "!!!Notifications", |
1708 | "end": { | 1856 | "end": { |
1709 | "column": 3, | 1857 | "column": 3, |
1710 | "line": 81 | 1858 | "line": 83 |
1711 | }, | 1859 | }, |
1712 | "file": "src/components/settings/services/EditServiceForm.js", | 1860 | "file": "src/components/settings/services/EditServiceForm.js", |
1713 | "id": "settings.service.form.headlineNotifications", | 1861 | "id": "settings.service.form.headlineNotifications", |
1714 | "start": { | 1862 | "start": { |
1715 | "column": 25, | 1863 | "column": 25, |
1716 | "line": 78 | 1864 | "line": 80 |
1717 | } | 1865 | } |
1718 | }, | 1866 | }, |
1719 | { | 1867 | { |
1720 | "defaultMessage": "!!!Unread message badges", | 1868 | "defaultMessage": "!!!Unread message badges", |
1721 | "end": { | 1869 | "end": { |
1722 | "column": 3, | 1870 | "column": 3, |
1723 | "line": 85 | 1871 | "line": 87 |
1724 | }, | 1872 | }, |
1725 | "file": "src/components/settings/services/EditServiceForm.js", | 1873 | "file": "src/components/settings/services/EditServiceForm.js", |
1726 | "id": "settings.service.form.headlineBadges", | 1874 | "id": "settings.service.form.headlineBadges", |
1727 | "start": { | 1875 | "start": { |
1728 | "column": 18, | 1876 | "column": 18, |
1729 | "line": 82 | 1877 | "line": 84 |
1730 | } | 1878 | } |
1731 | }, | 1879 | }, |
1732 | { | 1880 | { |
1733 | "defaultMessage": "!!!General", | 1881 | "defaultMessage": "!!!General", |
1734 | "end": { | 1882 | "end": { |
1735 | "column": 3, | 1883 | "column": 3, |
1736 | "line": 89 | 1884 | "line": 91 |
1737 | }, | 1885 | }, |
1738 | "file": "src/components/settings/services/EditServiceForm.js", | 1886 | "file": "src/components/settings/services/EditServiceForm.js", |
1739 | "id": "settings.service.form.headlineGeneral", | 1887 | "id": "settings.service.form.headlineGeneral", |
1740 | "start": { | 1888 | "start": { |
1741 | "column": 19, | 1889 | "column": 19, |
1742 | "line": 86 | 1890 | "line": 88 |
1743 | } | 1891 | } |
1744 | }, | 1892 | }, |
1745 | { | 1893 | { |
1746 | "defaultMessage": "!!!Delete", | 1894 | "defaultMessage": "!!!Delete", |
1747 | "end": { | 1895 | "end": { |
1748 | "column": 3, | 1896 | "column": 3, |
1749 | "line": 93 | 1897 | "line": 95 |
1750 | }, | 1898 | }, |
1751 | "file": "src/components/settings/services/EditServiceForm.js", | 1899 | "file": "src/components/settings/services/EditServiceForm.js", |
1752 | "id": "settings.service.form.iconDelete", | 1900 | "id": "settings.service.form.iconDelete", |
1753 | "start": { | 1901 | "start": { |
1754 | "column": 14, | 1902 | "column": 14, |
1755 | "line": 90 | 1903 | "line": 92 |
1756 | } | 1904 | } |
1757 | }, | 1905 | }, |
1758 | { | 1906 | { |
1759 | "defaultMessage": "!!!Drop your image, or click here", | 1907 | "defaultMessage": "!!!Drop your image, or click here", |
1760 | "end": { | 1908 | "end": { |
1761 | "column": 3, | 1909 | "column": 3, |
1762 | "line": 97 | 1910 | "line": 99 |
1763 | }, | 1911 | }, |
1764 | "file": "src/components/settings/services/EditServiceForm.js", | 1912 | "file": "src/components/settings/services/EditServiceForm.js", |
1765 | "id": "settings.service.form.iconUpload", | 1913 | "id": "settings.service.form.iconUpload", |
1766 | "start": { | 1914 | "start": { |
1767 | "column": 14, | 1915 | "column": 14, |
1768 | "line": 94 | 1916 | "line": 96 |
1769 | } | 1917 | } |
1770 | }, | 1918 | }, |
1771 | { | 1919 | { |
1772 | "defaultMessage": "!!!HTTP/HTTPS Proxy Settings", | 1920 | "defaultMessage": "!!!HTTP/HTTPS Proxy Settings", |
1773 | "end": { | 1921 | "end": { |
1774 | "column": 3, | 1922 | "column": 3, |
1775 | "line": 101 | 1923 | "line": 103 |
1776 | }, | 1924 | }, |
1777 | "file": "src/components/settings/services/EditServiceForm.js", | 1925 | "file": "src/components/settings/services/EditServiceForm.js", |
1778 | "id": "settings.service.form.proxy.headline", | 1926 | "id": "settings.service.form.proxy.headline", |
1779 | "start": { | 1927 | "start": { |
1780 | "column": 17, | 1928 | "column": 17, |
1781 | "line": 98 | 1929 | "line": 100 |
1782 | } | 1930 | } |
1783 | }, | 1931 | }, |
1784 | { | 1932 | { |
1785 | "defaultMessage": "!!!Please restart Franz after changing proxy Settings.", | 1933 | "defaultMessage": "!!!Please restart Franz after changing proxy Settings.", |
1786 | "end": { | 1934 | "end": { |
1787 | "column": 3, | 1935 | "column": 3, |
1788 | "line": 105 | 1936 | "line": 107 |
1789 | }, | 1937 | }, |
1790 | "file": "src/components/settings/services/EditServiceForm.js", | 1938 | "file": "src/components/settings/services/EditServiceForm.js", |
1791 | "id": "settings.service.form.proxy.restartInfo", | 1939 | "id": "settings.service.form.proxy.restartInfo", |
1792 | "start": { | 1940 | "start": { |
1793 | "column": 20, | 1941 | "column": 20, |
1794 | "line": 102 | 1942 | "line": 104 |
1795 | } | 1943 | } |
1796 | }, | 1944 | }, |
1797 | { | 1945 | { |
1798 | "defaultMessage": "!!!Proxy settings will not be synchronized with the Franz servers.", | 1946 | "defaultMessage": "!!!Proxy settings will not be synchronized with the Franz servers.", |
1799 | "end": { | 1947 | "end": { |
1800 | "column": 3, | 1948 | "column": 3, |
1801 | "line": 109 | 1949 | "line": 111 |
1802 | }, | 1950 | }, |
1803 | "file": "src/components/settings/services/EditServiceForm.js", | 1951 | "file": "src/components/settings/services/EditServiceForm.js", |
1804 | "id": "settings.service.form.proxy.info", | 1952 | "id": "settings.service.form.proxy.info", |
1805 | "start": { | 1953 | "start": { |
1806 | "column": 13, | 1954 | "column": 13, |
1807 | "line": 106 | 1955 | "line": 108 |
1808 | } | 1956 | } |
1809 | } | 1957 | } |
1810 | ], | 1958 | ], |
@@ -1917,117 +2065,117 @@ | |||
1917 | "defaultMessage": "!!!Your services", | 2065 | "defaultMessage": "!!!Your services", |
1918 | "end": { | 2066 | "end": { |
1919 | "column": 3, | 2067 | "column": 3, |
1920 | "line": 17 | 2068 | "line": 18 |
1921 | }, | 2069 | }, |
1922 | "file": "src/components/settings/services/ServicesDashboard.js", | 2070 | "file": "src/components/settings/services/ServicesDashboard.js", |
1923 | "id": "settings.services.headline", | 2071 | "id": "settings.services.headline", |
1924 | "start": { | 2072 | "start": { |
1925 | "column": 12, | 2073 | "column": 12, |
1926 | "line": 14 | 2074 | "line": 15 |
1927 | } | 2075 | } |
1928 | }, | 2076 | }, |
1929 | { | 2077 | { |
1930 | "defaultMessage": "!!!Search service", | 2078 | "defaultMessage": "!!!Search service", |
1931 | "end": { | 2079 | "end": { |
1932 | "column": 3, | 2080 | "column": 3, |
1933 | "line": 21 | 2081 | "line": 22 |
1934 | }, | 2082 | }, |
1935 | "file": "src/components/settings/services/ServicesDashboard.js", | 2083 | "file": "src/components/settings/services/ServicesDashboard.js", |
1936 | "id": "settings.searchService", | 2084 | "id": "settings.searchService", |
1937 | "start": { | 2085 | "start": { |
1938 | "column": 17, | 2086 | "column": 17, |
1939 | "line": 18 | 2087 | "line": 19 |
1940 | } | 2088 | } |
1941 | }, | 2089 | }, |
1942 | { | 2090 | { |
1943 | "defaultMessage": "!!!You haven't added any services yet.", | 2091 | "defaultMessage": "!!!You haven't added any services yet.", |
1944 | "end": { | 2092 | "end": { |
1945 | "column": 3, | 2093 | "column": 3, |
1946 | "line": 25 | 2094 | "line": 26 |
1947 | }, | 2095 | }, |
1948 | "file": "src/components/settings/services/ServicesDashboard.js", | 2096 | "file": "src/components/settings/services/ServicesDashboard.js", |
1949 | "id": "settings.services.noServicesAdded", | 2097 | "id": "settings.services.noServicesAdded", |
1950 | "start": { | 2098 | "start": { |
1951 | "column": 19, | 2099 | "column": 19, |
1952 | "line": 22 | 2100 | "line": 23 |
1953 | } | 2101 | } |
1954 | }, | 2102 | }, |
1955 | { | 2103 | { |
1956 | "defaultMessage": "!!!Sorry, but no service matched your search term.", | 2104 | "defaultMessage": "!!!Sorry, but no service matched your search term.", |
1957 | "end": { | 2105 | "end": { |
1958 | "column": 3, | 2106 | "column": 3, |
1959 | "line": 29 | 2107 | "line": 30 |
1960 | }, | 2108 | }, |
1961 | "file": "src/components/settings/services/ServicesDashboard.js", | 2109 | "file": "src/components/settings/services/ServicesDashboard.js", |
1962 | "id": "settings.recipes.nothingFound", | 2110 | "id": "settings.recipes.nothingFound", |
1963 | "start": { | 2111 | "start": { |
1964 | "column": 18, | 2112 | "column": 18, |
1965 | "line": 26 | 2113 | "line": 27 |
1966 | } | 2114 | } |
1967 | }, | 2115 | }, |
1968 | { | 2116 | { |
1969 | "defaultMessage": "!!!Discover services", | 2117 | "defaultMessage": "!!!Discover services", |
1970 | "end": { | 2118 | "end": { |
1971 | "column": 3, | 2119 | "column": 3, |
1972 | "line": 33 | 2120 | "line": 34 |
1973 | }, | 2121 | }, |
1974 | "file": "src/components/settings/services/ServicesDashboard.js", | 2122 | "file": "src/components/settings/services/ServicesDashboard.js", |
1975 | "id": "settings.services.discoverServices", | 2123 | "id": "settings.services.discoverServices", |
1976 | "start": { | 2124 | "start": { |
1977 | "column": 20, | 2125 | "column": 20, |
1978 | "line": 30 | 2126 | "line": 31 |
1979 | } | 2127 | } |
1980 | }, | 2128 | }, |
1981 | { | 2129 | { |
1982 | "defaultMessage": "!!!Could not load your services", | 2130 | "defaultMessage": "!!!Could not load your services", |
1983 | "end": { | 2131 | "end": { |
1984 | "column": 3, | 2132 | "column": 3, |
1985 | "line": 37 | 2133 | "line": 38 |
1986 | }, | 2134 | }, |
1987 | "file": "src/components/settings/services/ServicesDashboard.js", | 2135 | "file": "src/components/settings/services/ServicesDashboard.js", |
1988 | "id": "settings.services.servicesRequestFailed", | 2136 | "id": "settings.services.servicesRequestFailed", |
1989 | "start": { | 2137 | "start": { |
1990 | "column": 25, | 2138 | "column": 25, |
1991 | "line": 34 | 2139 | "line": 35 |
1992 | } | 2140 | } |
1993 | }, | 2141 | }, |
1994 | { | 2142 | { |
1995 | "defaultMessage": "!!!Try again", | 2143 | "defaultMessage": "!!!Try again", |
1996 | "end": { | 2144 | "end": { |
1997 | "column": 3, | 2145 | "column": 3, |
1998 | "line": 41 | 2146 | "line": 42 |
1999 | }, | 2147 | }, |
2000 | "file": "src/components/settings/services/ServicesDashboard.js", | 2148 | "file": "src/components/settings/services/ServicesDashboard.js", |
2001 | "id": "settings.account.tryReloadServices", | 2149 | "id": "settings.account.tryReloadServices", |
2002 | "start": { | 2150 | "start": { |
2003 | "column": 21, | 2151 | "column": 21, |
2004 | "line": 38 | 2152 | "line": 39 |
2005 | } | 2153 | } |
2006 | }, | 2154 | }, |
2007 | { | 2155 | { |
2008 | "defaultMessage": "!!!Your changes have been saved", | 2156 | "defaultMessage": "!!!Your changes have been saved", |
2009 | "end": { | 2157 | "end": { |
2010 | "column": 3, | 2158 | "column": 3, |
2011 | "line": 45 | 2159 | "line": 46 |
2012 | }, | 2160 | }, |
2013 | "file": "src/components/settings/services/ServicesDashboard.js", | 2161 | "file": "src/components/settings/services/ServicesDashboard.js", |
2014 | "id": "settings.services.updatedInfo", | 2162 | "id": "settings.services.updatedInfo", |
2015 | "start": { | 2163 | "start": { |
2016 | "column": 15, | 2164 | "column": 15, |
2017 | "line": 42 | 2165 | "line": 43 |
2018 | } | 2166 | } |
2019 | }, | 2167 | }, |
2020 | { | 2168 | { |
2021 | "defaultMessage": "!!!Service has been deleted", | 2169 | "defaultMessage": "!!!Service has been deleted", |
2022 | "end": { | 2170 | "end": { |
2023 | "column": 3, | 2171 | "column": 3, |
2024 | "line": 49 | 2172 | "line": 50 |
2025 | }, | 2173 | }, |
2026 | "file": "src/components/settings/services/ServicesDashboard.js", | 2174 | "file": "src/components/settings/services/ServicesDashboard.js", |
2027 | "id": "settings.services.deletedInfo", | 2175 | "id": "settings.services.deletedInfo", |
2028 | "start": { | 2176 | "start": { |
2029 | "column": 15, | 2177 | "column": 15, |
2030 | "line": 46 | 2178 | "line": 47 |
2031 | } | 2179 | } |
2032 | } | 2180 | } |
2033 | ], | 2181 | ], |
@@ -3271,6 +3419,55 @@ | |||
3271 | { | 3419 | { |
3272 | "descriptors": [ | 3420 | "descriptors": [ |
3273 | { | 3421 | { |
3422 | "defaultMessage": "!!!Changes in Franz {version}", | ||
3423 | "end": { | ||
3424 | "column": 3, | ||
3425 | "line": 23 | ||
3426 | }, | ||
3427 | "file": "src/features/serviceLimit/components/AnnouncementScreen.js", | ||
3428 | "id": "feature.announcements.changelog.headline", | ||
3429 | "start": { | ||
3430 | "column": 12, | ||
3431 | "line": 20 | ||
3432 | } | ||
3433 | } | ||
3434 | ], | ||
3435 | "path": "src/features/serviceLimit/components/AnnouncementScreen.json" | ||
3436 | }, | ||
3437 | { | ||
3438 | "descriptors": [ | ||
3439 | { | ||
3440 | "defaultMessage": "!!!You have added {amount} of {limit} services. Please upgrade your account to add more services.", | ||
3441 | "end": { | ||
3442 | "column": 3, | ||
3443 | "line": 14 | ||
3444 | }, | ||
3445 | "file": "src/features/serviceLimit/components/LimitReachedInfobox.js", | ||
3446 | "id": "feature.serviceLimit.limitReached", | ||
3447 | "start": { | ||
3448 | "column": 16, | ||
3449 | "line": 11 | ||
3450 | } | ||
3451 | }, | ||
3452 | { | ||
3453 | "defaultMessage": "!!!Upgrade account", | ||
3454 | "end": { | ||
3455 | "column": 3, | ||
3456 | "line": 18 | ||
3457 | }, | ||
3458 | "file": "src/features/serviceLimit/components/LimitReachedInfobox.js", | ||
3459 | "id": "premiumFeature.button.upgradeAccount", | ||
3460 | "start": { | ||
3461 | "column": 10, | ||
3462 | "line": 15 | ||
3463 | } | ||
3464 | } | ||
3465 | ], | ||
3466 | "path": "src/features/serviceLimit/components/LimitReachedInfobox.json" | ||
3467 | }, | ||
3468 | { | ||
3469 | "descriptors": [ | ||
3470 | { | ||
3274 | "defaultMessage": "!!!Franz is better together!", | 3471 | "defaultMessage": "!!!Franz is better together!", |
3275 | "end": { | 3472 | "end": { |
3276 | "column": 3, | 3473 | "column": 3, |
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index e2edbd596..0a8e04b21 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json | |||
@@ -5,6 +5,7 @@ | |||
5 | "feature.delayApp.action": "Get a Franz Supporter License", | 5 | "feature.delayApp.action": "Get a Franz Supporter License", |
6 | "feature.delayApp.headline": "Please purchase a Franz Supporter License to skip waiting", | 6 | "feature.delayApp.headline": "Please purchase a Franz Supporter License to skip waiting", |
7 | "feature.delayApp.text": "Franz will continue in {seconds} seconds.", | 7 | "feature.delayApp.text": "Franz will continue in {seconds} seconds.", |
8 | "feature.serviceLimit.limitReached": "You have added {amount} out of {limit} services that are included in your plan. Please upgrade your account to add more services.", | ||
8 | "feature.shareFranz.action.email": "Send as email", | 9 | "feature.shareFranz.action.email": "Send as email", |
9 | "feature.shareFranz.action.facebook": "Share on Facebook", | 10 | "feature.shareFranz.action.facebook": "Share on Facebook", |
10 | "feature.shareFranz.action.twitter": "Share on Twitter", | 11 | "feature.shareFranz.action.twitter": "Share on Twitter", |
@@ -118,6 +119,11 @@ | |||
118 | "service.errorHandler.headline": "Oh no!", | 119 | "service.errorHandler.headline": "Oh no!", |
119 | "service.errorHandler.message": "Error", | 120 | "service.errorHandler.message": "Error", |
120 | "service.errorHandler.text": "{name} has failed to load.", | 121 | "service.errorHandler.text": "{name} has failed to load.", |
122 | "service.restrictedHandler.action": "Upgrade Account", | ||
123 | "service.restrictedHandler.customUrl.headline": "Franz Professional Plan required", | ||
124 | "service.restrictedHandler.customUrl.text": "Please upgrade to the Franz Professional plan to use custom urls & self hosted services.", | ||
125 | "service.restrictedHandler.serviceLimit.headline": "You have reached your service limit.", | ||
126 | "service.restrictedHandler.serviceLimit.text": "Please upgrade your account to use more than {count} services.", | ||
121 | "service.webviewLoader.loading": "Loading", | 127 | "service.webviewLoader.loading": "Loading", |
122 | "services.getStarted": "Get started", | 128 | "services.getStarted": "Get started", |
123 | "services.welcome": "Welcome to Franz", | 129 | "services.welcome": "Welcome to Franz", |
@@ -182,7 +188,13 @@ | |||
182 | "settings.navigation.yourServices": "Your services", | 188 | "settings.navigation.yourServices": "Your services", |
183 | "settings.navigation.yourWorkspaces": "Your workspaces", | 189 | "settings.navigation.yourWorkspaces": "Your workspaces", |
184 | "settings.recipes.all": "All services", | 190 | "settings.recipes.all": "All services", |
185 | "settings.recipes.dev": "Development", | 191 | "settings.recipes.custom": "Custom Services", |
192 | "settings.recipes.customService.headline.communityRecipes": "Community Services", | ||
193 | "settings.recipes.customService.headline.customRecipes": "Custom Service Recipes", | ||
194 | "settings.recipes.customService.headline.devRecipes": "Your Development Service Recipes", | ||
195 | "settings.recipes.customService.intro": "To add a custom service, copy the service recipe to:", | ||
196 | "settings.recipes.customService.openDevDocs": "Developer Documentation", | ||
197 | "settings.recipes.customService.openFolder": "Open folder", | ||
186 | "settings.recipes.headline": "Available services", | 198 | "settings.recipes.headline": "Available services", |
187 | "settings.recipes.missingService": "Missing a service?", | 199 | "settings.recipes.missingService": "Missing a service?", |
188 | "settings.recipes.mostPopular": "Most popular", | 200 | "settings.recipes.mostPopular": "Most popular", |
@@ -329,4 +341,4 @@ | |||
329 | "workspaceDrawer.workspaceFeatureInfo": "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.</p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.</p>", | 341 | "workspaceDrawer.workspaceFeatureInfo": "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.</p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.</p>", |
330 | "workspaceDrawer.workspacesSettingsTooltip": "Edit workspaces settings", | 342 | "workspaceDrawer.workspacesSettingsTooltip": "Edit workspaces settings", |
331 | "workspaces.switchingIndicator.switchingTo": "Switching to" | 343 | "workspaces.switchingIndicator.switchingTo": "Switching to" |
332 | } \ No newline at end of file | 344 | } |
diff --git a/src/i18n/messages/src/components/services/content/ServiceRestricted.json b/src/i18n/messages/src/components/services/content/ServiceRestricted.json new file mode 100644 index 000000000..c1984afe3 --- /dev/null +++ b/src/i18n/messages/src/components/services/content/ServiceRestricted.json | |||
@@ -0,0 +1,67 @@ | |||
1 | [ | ||
2 | { | ||
3 | "id": "service.restrictedHandler.serviceLimit.headline", | ||
4 | "defaultMessage": "!!!You have reached your service limit.", | ||
5 | "file": "src/components/services/content/ServiceRestricted.js", | ||
6 | "start": { | ||
7 | "line": 11, | ||
8 | "column": 24 | ||
9 | }, | ||
10 | "end": { | ||
11 | "line": 14, | ||
12 | "column": 3 | ||
13 | } | ||
14 | }, | ||
15 | { | ||
16 | "id": "service.restrictedHandler.serviceLimit.text", | ||
17 | "defaultMessage": "!!!Please upgrade your account to use more than {count} services.", | ||
18 | "file": "src/components/services/content/ServiceRestricted.js", | ||
19 | "start": { | ||
20 | "line": 15, | ||
21 | "column": 20 | ||
22 | }, | ||
23 | "end": { | ||
24 | "line": 18, | ||
25 | "column": 3 | ||
26 | } | ||
27 | }, | ||
28 | { | ||
29 | "id": "service.restrictedHandler.customUrl.headline", | ||
30 | "defaultMessage": "!!!Franz Professional Plan required", | ||
31 | "file": "src/components/services/content/ServiceRestricted.js", | ||
32 | "start": { | ||
33 | "line": 19, | ||
34 | "column": 21 | ||
35 | }, | ||
36 | "end": { | ||
37 | "line": 22, | ||
38 | "column": 3 | ||
39 | } | ||
40 | }, | ||
41 | { | ||
42 | "id": "service.restrictedHandler.customUrl.text", | ||
43 | "defaultMessage": "!!!Please upgrade to the Franz Professional plan to use custom urls & self hosted services.", | ||
44 | "file": "src/components/services/content/ServiceRestricted.js", | ||
45 | "start": { | ||
46 | "line": 23, | ||
47 | "column": 17 | ||
48 | }, | ||
49 | "end": { | ||
50 | "line": 26, | ||
51 | "column": 3 | ||
52 | } | ||
53 | }, | ||
54 | { | ||
55 | "id": "service.restrictedHandler.action", | ||
56 | "defaultMessage": "!!!Upgrade Account", | ||
57 | "file": "src/components/services/content/ServiceRestricted.js", | ||
58 | "start": { | ||
59 | "line": 27, | ||
60 | "column": 10 | ||
61 | }, | ||
62 | "end": { | ||
63 | "line": 30, | ||
64 | "column": 3 | ||
65 | } | ||
66 | } | ||
67 | ] \ No newline at end of file | ||
diff --git a/src/i18n/messages/src/components/settings/navigation/SettingsNavigation.json b/src/i18n/messages/src/components/settings/navigation/SettingsNavigation.json index 70a989211..7dfb3ce04 100644 --- a/src/i18n/messages/src/components/settings/navigation/SettingsNavigation.json +++ b/src/i18n/messages/src/components/settings/navigation/SettingsNavigation.json | |||
@@ -4,11 +4,11 @@ | |||
4 | "defaultMessage": "!!!Available services", | 4 | "defaultMessage": "!!!Available services", |
5 | "file": "src/components/settings/navigation/SettingsNavigation.js", | 5 | "file": "src/components/settings/navigation/SettingsNavigation.js", |
6 | "start": { | 6 | "start": { |
7 | "line": 13, | 7 | "line": 14, |
8 | "column": 21 | 8 | "column": 21 |
9 | }, | 9 | }, |
10 | "end": { | 10 | "end": { |
11 | "line": 16, | 11 | "line": 17, |
12 | "column": 3 | 12 | "column": 3 |
13 | } | 13 | } |
14 | }, | 14 | }, |
@@ -17,11 +17,11 @@ | |||
17 | "defaultMessage": "!!!Your services", | 17 | "defaultMessage": "!!!Your services", |
18 | "file": "src/components/settings/navigation/SettingsNavigation.js", | 18 | "file": "src/components/settings/navigation/SettingsNavigation.js", |
19 | "start": { | 19 | "start": { |
20 | "line": 17, | 20 | "line": 18, |
21 | "column": 16 | 21 | "column": 16 |
22 | }, | 22 | }, |
23 | "end": { | 23 | "end": { |
24 | "line": 20, | 24 | "line": 21, |
25 | "column": 3 | 25 | "column": 3 |
26 | } | 26 | } |
27 | }, | 27 | }, |
@@ -30,11 +30,11 @@ | |||
30 | "defaultMessage": "!!!Your workspaces", | 30 | "defaultMessage": "!!!Your workspaces", |
31 | "file": "src/components/settings/navigation/SettingsNavigation.js", | 31 | "file": "src/components/settings/navigation/SettingsNavigation.js", |
32 | "start": { | 32 | "start": { |
33 | "line": 21, | 33 | "line": 22, |
34 | "column": 18 | 34 | "column": 18 |
35 | }, | 35 | }, |
36 | "end": { | 36 | "end": { |
37 | "line": 24, | 37 | "line": 25, |
38 | "column": 3 | 38 | "column": 3 |
39 | } | 39 | } |
40 | }, | 40 | }, |
@@ -43,11 +43,11 @@ | |||
43 | "defaultMessage": "!!!Account", | 43 | "defaultMessage": "!!!Account", |
44 | "file": "src/components/settings/navigation/SettingsNavigation.js", | 44 | "file": "src/components/settings/navigation/SettingsNavigation.js", |
45 | "start": { | 45 | "start": { |
46 | "line": 25, | 46 | "line": 26, |
47 | "column": 11 | 47 | "column": 11 |
48 | }, | 48 | }, |
49 | "end": { | 49 | "end": { |
50 | "line": 28, | 50 | "line": 29, |
51 | "column": 3 | 51 | "column": 3 |
52 | } | 52 | } |
53 | }, | 53 | }, |
@@ -56,11 +56,11 @@ | |||
56 | "defaultMessage": "!!!Manage Team", | 56 | "defaultMessage": "!!!Manage Team", |
57 | "file": "src/components/settings/navigation/SettingsNavigation.js", | 57 | "file": "src/components/settings/navigation/SettingsNavigation.js", |
58 | "start": { | 58 | "start": { |
59 | "line": 29, | 59 | "line": 30, |
60 | "column": 8 | 60 | "column": 8 |
61 | }, | 61 | }, |
62 | "end": { | 62 | "end": { |
63 | "line": 32, | 63 | "line": 33, |
64 | "column": 3 | 64 | "column": 3 |
65 | } | 65 | } |
66 | }, | 66 | }, |
@@ -69,11 +69,11 @@ | |||
69 | "defaultMessage": "!!!Settings", | 69 | "defaultMessage": "!!!Settings", |
70 | "file": "src/components/settings/navigation/SettingsNavigation.js", | 70 | "file": "src/components/settings/navigation/SettingsNavigation.js", |
71 | "start": { | 71 | "start": { |
72 | "line": 33, | 72 | "line": 34, |
73 | "column": 12 | 73 | "column": 12 |
74 | }, | 74 | }, |
75 | "end": { | 75 | "end": { |
76 | "line": 36, | 76 | "line": 37, |
77 | "column": 3 | 77 | "column": 3 |
78 | } | 78 | } |
79 | }, | 79 | }, |
@@ -82,11 +82,11 @@ | |||
82 | "defaultMessage": "!!!Invite Friends", | 82 | "defaultMessage": "!!!Invite Friends", |
83 | "file": "src/components/settings/navigation/SettingsNavigation.js", | 83 | "file": "src/components/settings/navigation/SettingsNavigation.js", |
84 | "start": { | 84 | "start": { |
85 | "line": 37, | 85 | "line": 38, |
86 | "column": 17 | 86 | "column": 17 |
87 | }, | 87 | }, |
88 | "end": { | 88 | "end": { |
89 | "line": 40, | 89 | "line": 41, |
90 | "column": 3 | 90 | "column": 3 |
91 | } | 91 | } |
92 | }, | 92 | }, |
@@ -95,11 +95,11 @@ | |||
95 | "defaultMessage": "!!!Logout", | 95 | "defaultMessage": "!!!Logout", |
96 | "file": "src/components/settings/navigation/SettingsNavigation.js", | 96 | "file": "src/components/settings/navigation/SettingsNavigation.js", |
97 | "start": { | 97 | "start": { |
98 | "line": 41, | 98 | "line": 42, |
99 | "column": 10 | 99 | "column": 10 |
100 | }, | 100 | }, |
101 | "end": { | 101 | "end": { |
102 | "line": 44, | 102 | "line": 45, |
103 | "column": 3 | 103 | "column": 3 |
104 | } | 104 | } |
105 | } | 105 | } |
diff --git a/src/i18n/messages/src/components/settings/recipes/RecipesDashboard.json b/src/i18n/messages/src/components/settings/recipes/RecipesDashboard.json index 7d9ed3283..8afaaed50 100644 --- a/src/i18n/messages/src/components/settings/recipes/RecipesDashboard.json +++ b/src/i18n/messages/src/components/settings/recipes/RecipesDashboard.json | |||
@@ -4,11 +4,11 @@ | |||
4 | "defaultMessage": "!!!Available Services", | 4 | "defaultMessage": "!!!Available Services", |
5 | "file": "src/components/settings/recipes/RecipesDashboard.js", | 5 | "file": "src/components/settings/recipes/RecipesDashboard.js", |
6 | "start": { | 6 | "start": { |
7 | "line": 15, | 7 | "line": 20, |
8 | "column": 12 | 8 | "column": 12 |
9 | }, | 9 | }, |
10 | "end": { | 10 | "end": { |
11 | "line": 18, | 11 | "line": 23, |
12 | "column": 3 | 12 | "column": 3 |
13 | } | 13 | } |
14 | }, | 14 | }, |
@@ -17,11 +17,11 @@ | |||
17 | "defaultMessage": "!!!Search service", | 17 | "defaultMessage": "!!!Search service", |
18 | "file": "src/components/settings/recipes/RecipesDashboard.js", | 18 | "file": "src/components/settings/recipes/RecipesDashboard.js", |
19 | "start": { | 19 | "start": { |
20 | "line": 19, | 20 | "line": 24, |
21 | "column": 17 | 21 | "column": 17 |
22 | }, | 22 | }, |
23 | "end": { | 23 | "end": { |
24 | "line": 22, | 24 | "line": 27, |
25 | "column": 3 | 25 | "column": 3 |
26 | } | 26 | } |
27 | }, | 27 | }, |
@@ -30,11 +30,11 @@ | |||
30 | "defaultMessage": "!!!Most popular", | 30 | "defaultMessage": "!!!Most popular", |
31 | "file": "src/components/settings/recipes/RecipesDashboard.js", | 31 | "file": "src/components/settings/recipes/RecipesDashboard.js", |
32 | "start": { | 32 | "start": { |
33 | "line": 23, | 33 | "line": 28, |
34 | "column": 22 | 34 | "column": 22 |
35 | }, | 35 | }, |
36 | "end": { | 36 | "end": { |
37 | "line": 26, | 37 | "line": 31, |
38 | "column": 3 | 38 | "column": 3 |
39 | } | 39 | } |
40 | }, | 40 | }, |
@@ -43,24 +43,24 @@ | |||
43 | "defaultMessage": "!!!All services", | 43 | "defaultMessage": "!!!All services", |
44 | "file": "src/components/settings/recipes/RecipesDashboard.js", | 44 | "file": "src/components/settings/recipes/RecipesDashboard.js", |
45 | "start": { | 45 | "start": { |
46 | "line": 27, | 46 | "line": 32, |
47 | "column": 14 | 47 | "column": 14 |
48 | }, | 48 | }, |
49 | "end": { | 49 | "end": { |
50 | "line": 30, | 50 | "line": 35, |
51 | "column": 3 | 51 | "column": 3 |
52 | } | 52 | } |
53 | }, | 53 | }, |
54 | { | 54 | { |
55 | "id": "settings.recipes.dev", | 55 | "id": "settings.recipes.custom", |
56 | "defaultMessage": "!!!Development", | 56 | "defaultMessage": "!!!Custom Services", |
57 | "file": "src/components/settings/recipes/RecipesDashboard.js", | 57 | "file": "src/components/settings/recipes/RecipesDashboard.js", |
58 | "start": { | 58 | "start": { |
59 | "line": 31, | 59 | "line": 36, |
60 | "column": 14 | 60 | "column": 17 |
61 | }, | 61 | }, |
62 | "end": { | 62 | "end": { |
63 | "line": 34, | 63 | "line": 39, |
64 | "column": 3 | 64 | "column": 3 |
65 | } | 65 | } |
66 | }, | 66 | }, |
@@ -69,11 +69,11 @@ | |||
69 | "defaultMessage": "!!!Sorry, but no service matched your search term.", | 69 | "defaultMessage": "!!!Sorry, but no service matched your search term.", |
70 | "file": "src/components/settings/recipes/RecipesDashboard.js", | 70 | "file": "src/components/settings/recipes/RecipesDashboard.js", |
71 | "start": { | 71 | "start": { |
72 | "line": 35, | 72 | "line": 40, |
73 | "column": 16 | 73 | "column": 16 |
74 | }, | 74 | }, |
75 | "end": { | 75 | "end": { |
76 | "line": 38, | 76 | "line": 43, |
77 | "column": 3 | 77 | "column": 3 |
78 | } | 78 | } |
79 | }, | 79 | }, |
@@ -82,11 +82,11 @@ | |||
82 | "defaultMessage": "!!!Service successfully added", | 82 | "defaultMessage": "!!!Service successfully added", |
83 | "file": "src/components/settings/recipes/RecipesDashboard.js", | 83 | "file": "src/components/settings/recipes/RecipesDashboard.js", |
84 | "start": { | 84 | "start": { |
85 | "line": 39, | 85 | "line": 44, |
86 | "column": 31 | 86 | "column": 31 |
87 | }, | 87 | }, |
88 | "end": { | 88 | "end": { |
89 | "line": 42, | 89 | "line": 47, |
90 | "column": 3 | 90 | "column": 3 |
91 | } | 91 | } |
92 | }, | 92 | }, |
@@ -95,11 +95,89 @@ | |||
95 | "defaultMessage": "!!!Missing a service?", | 95 | "defaultMessage": "!!!Missing a service?", |
96 | "file": "src/components/settings/recipes/RecipesDashboard.js", | 96 | "file": "src/components/settings/recipes/RecipesDashboard.js", |
97 | "start": { | 97 | "start": { |
98 | "line": 43, | 98 | "line": 48, |
99 | "column": 18 | 99 | "column": 18 |
100 | }, | 100 | }, |
101 | "end": { | 101 | "end": { |
102 | "line": 46, | 102 | "line": 51, |
103 | "column": 3 | ||
104 | } | ||
105 | }, | ||
106 | { | ||
107 | "id": "settings.recipes.customService.intro", | ||
108 | "defaultMessage": "!!!To add a custom service, copy the recipe folder into:", | ||
109 | "file": "src/components/settings/recipes/RecipesDashboard.js", | ||
110 | "start": { | ||
111 | "line": 52, | ||
112 | "column": 21 | ||
113 | }, | ||
114 | "end": { | ||
115 | "line": 55, | ||
116 | "column": 3 | ||
117 | } | ||
118 | }, | ||
119 | { | ||
120 | "id": "settings.recipes.customService.openFolder", | ||
121 | "defaultMessage": "!!!Open directory", | ||
122 | "file": "src/components/settings/recipes/RecipesDashboard.js", | ||
123 | "start": { | ||
124 | "line": 56, | ||
125 | "column": 14 | ||
126 | }, | ||
127 | "end": { | ||
128 | "line": 59, | ||
129 | "column": 3 | ||
130 | } | ||
131 | }, | ||
132 | { | ||
133 | "id": "settings.recipes.customService.openDevDocs", | ||
134 | "defaultMessage": "!!!Developer Documentation", | ||
135 | "file": "src/components/settings/recipes/RecipesDashboard.js", | ||
136 | "start": { | ||
137 | "line": 60, | ||
138 | "column": 15 | ||
139 | }, | ||
140 | "end": { | ||
141 | "line": 63, | ||
142 | "column": 3 | ||
143 | } | ||
144 | }, | ||
145 | { | ||
146 | "id": "settings.recipes.customService.headline.customRecipes", | ||
147 | "defaultMessage": "!!!Custom Service Recipes", | ||
148 | "file": "src/components/settings/recipes/RecipesDashboard.js", | ||
149 | "start": { | ||
150 | "line": 64, | ||
151 | "column": 25 | ||
152 | }, | ||
153 | "end": { | ||
154 | "line": 67, | ||
155 | "column": 3 | ||
156 | } | ||
157 | }, | ||
158 | { | ||
159 | "id": "settings.recipes.customService.headline.communityRecipes", | ||
160 | "defaultMessage": "!!!Community Services", | ||
161 | "file": "src/components/settings/recipes/RecipesDashboard.js", | ||
162 | "start": { | ||
163 | "line": 68, | ||
164 | "column": 28 | ||
165 | }, | ||
166 | "end": { | ||
167 | "line": 71, | ||
168 | "column": 3 | ||
169 | } | ||
170 | }, | ||
171 | { | ||
172 | "id": "settings.recipes.customService.headline.devRecipes", | ||
173 | "defaultMessage": "!!!Your Development Service Recipes", | ||
174 | "file": "src/components/settings/recipes/RecipesDashboard.js", | ||
175 | "start": { | ||
176 | "line": 72, | ||
177 | "column": 22 | ||
178 | }, | ||
179 | "end": { | ||
180 | "line": 75, | ||
103 | "column": 3 | 181 | "column": 3 |
104 | } | 182 | } |
105 | } | 183 | } |
diff --git a/src/i18n/messages/src/components/settings/services/EditServiceForm.json b/src/i18n/messages/src/components/settings/services/EditServiceForm.json index 42b741b7a..e66db807d 100644 --- a/src/i18n/messages/src/components/settings/services/EditServiceForm.json +++ b/src/i18n/messages/src/components/settings/services/EditServiceForm.json | |||
@@ -4,11 +4,11 @@ | |||
4 | "defaultMessage": "!!!Save service", | 4 | "defaultMessage": "!!!Save service", |
5 | "file": "src/components/settings/services/EditServiceForm.js", | 5 | "file": "src/components/settings/services/EditServiceForm.js", |
6 | "start": { | 6 | "start": { |
7 | "line": 22, | 7 | "line": 24, |
8 | "column": 15 | 8 | "column": 15 |
9 | }, | 9 | }, |
10 | "end": { | 10 | "end": { |
11 | "line": 25, | 11 | "line": 27, |
12 | "column": 3 | 12 | "column": 3 |
13 | } | 13 | } |
14 | }, | 14 | }, |
@@ -17,11 +17,11 @@ | |||
17 | "defaultMessage": "!!!Delete Service", | 17 | "defaultMessage": "!!!Delete Service", |
18 | "file": "src/components/settings/services/EditServiceForm.js", | 18 | "file": "src/components/settings/services/EditServiceForm.js", |
19 | "start": { | 19 | "start": { |
20 | "line": 26, | 20 | "line": 28, |
21 | "column": 17 | 21 | "column": 17 |
22 | }, | 22 | }, |
23 | "end": { | 23 | "end": { |
24 | "line": 29, | 24 | "line": 31, |
25 | "column": 3 | 25 | "column": 3 |
26 | } | 26 | } |
27 | }, | 27 | }, |
@@ -30,11 +30,11 @@ | |||
30 | "defaultMessage": "!!!Available services", | 30 | "defaultMessage": "!!!Available services", |
31 | "file": "src/components/settings/services/EditServiceForm.js", | 31 | "file": "src/components/settings/services/EditServiceForm.js", |
32 | "start": { | 32 | "start": { |
33 | "line": 30, | 33 | "line": 32, |
34 | "column": 21 | 34 | "column": 21 |
35 | }, | 35 | }, |
36 | "end": { | 36 | "end": { |
37 | "line": 33, | 37 | "line": 35, |
38 | "column": 3 | 38 | "column": 3 |
39 | } | 39 | } |
40 | }, | 40 | }, |
@@ -43,11 +43,11 @@ | |||
43 | "defaultMessage": "!!!Your services", | 43 | "defaultMessage": "!!!Your services", |
44 | "file": "src/components/settings/services/EditServiceForm.js", | 44 | "file": "src/components/settings/services/EditServiceForm.js", |
45 | "start": { | 45 | "start": { |
46 | "line": 34, | 46 | "line": 36, |
47 | "column": 16 | 47 | "column": 16 |
48 | }, | 48 | }, |
49 | "end": { | 49 | "end": { |
50 | "line": 37, | 50 | "line": 39, |
51 | "column": 3 | 51 | "column": 3 |
52 | } | 52 | } |
53 | }, | 53 | }, |
@@ -56,11 +56,11 @@ | |||
56 | "defaultMessage": "!!!Add {name}", | 56 | "defaultMessage": "!!!Add {name}", |
57 | "file": "src/components/settings/services/EditServiceForm.js", | 57 | "file": "src/components/settings/services/EditServiceForm.js", |
58 | "start": { | 58 | "start": { |
59 | "line": 38, | 59 | "line": 40, |
60 | "column": 22 | 60 | "column": 22 |
61 | }, | 61 | }, |
62 | "end": { | 62 | "end": { |
63 | "line": 41, | 63 | "line": 43, |
64 | "column": 3 | 64 | "column": 3 |
65 | } | 65 | } |
66 | }, | 66 | }, |
@@ -69,11 +69,11 @@ | |||
69 | "defaultMessage": "!!!Edit {name}", | 69 | "defaultMessage": "!!!Edit {name}", |
70 | "file": "src/components/settings/services/EditServiceForm.js", | 70 | "file": "src/components/settings/services/EditServiceForm.js", |
71 | "start": { | 71 | "start": { |
72 | "line": 42, | 72 | "line": 44, |
73 | "column": 23 | 73 | "column": 23 |
74 | }, | 74 | }, |
75 | "end": { | 75 | "end": { |
76 | "line": 45, | 76 | "line": 47, |
77 | "column": 3 | 77 | "column": 3 |
78 | } | 78 | } |
79 | }, | 79 | }, |
@@ -82,11 +82,11 @@ | |||
82 | "defaultMessage": "!!!Hosted", | 82 | "defaultMessage": "!!!Hosted", |
83 | "file": "src/components/settings/services/EditServiceForm.js", | 83 | "file": "src/components/settings/services/EditServiceForm.js", |
84 | "start": { | 84 | "start": { |
85 | "line": 46, | 85 | "line": 48, |
86 | "column": 13 | 86 | "column": 13 |
87 | }, | 87 | }, |
88 | "end": { | 88 | "end": { |
89 | "line": 49, | 89 | "line": 51, |
90 | "column": 3 | 90 | "column": 3 |
91 | } | 91 | } |
92 | }, | 92 | }, |
@@ -95,11 +95,11 @@ | |||
95 | "defaultMessage": "!!!Self hosted ⭐️", | 95 | "defaultMessage": "!!!Self hosted ⭐️", |
96 | "file": "src/components/settings/services/EditServiceForm.js", | 96 | "file": "src/components/settings/services/EditServiceForm.js", |
97 | "start": { | 97 | "start": { |
98 | "line": 50, | 98 | "line": 52, |
99 | "column": 16 | 99 | "column": 16 |
100 | }, | 100 | }, |
101 | "end": { | 101 | "end": { |
102 | "line": 53, | 102 | "line": 55, |
103 | "column": 3 | 103 | "column": 3 |
104 | } | 104 | } |
105 | }, | 105 | }, |
@@ -108,11 +108,11 @@ | |||
108 | "defaultMessage": "!!!Use the hosted {name} service.", | 108 | "defaultMessage": "!!!Use the hosted {name} service.", |
109 | "file": "src/components/settings/services/EditServiceForm.js", | 109 | "file": "src/components/settings/services/EditServiceForm.js", |
110 | "start": { | 110 | "start": { |
111 | "line": 54, | 111 | "line": 56, |
112 | "column": 20 | 112 | "column": 20 |
113 | }, | 113 | }, |
114 | "end": { | 114 | "end": { |
115 | "line": 57, | 115 | "line": 59, |
116 | "column": 3 | 116 | "column": 3 |
117 | } | 117 | } |
118 | }, | 118 | }, |
@@ -121,11 +121,11 @@ | |||
121 | "defaultMessage": "!!!Could not validate custom {name} server.", | 121 | "defaultMessage": "!!!Could not validate custom {name} server.", |
122 | "file": "src/components/settings/services/EditServiceForm.js", | 122 | "file": "src/components/settings/services/EditServiceForm.js", |
123 | "start": { | 123 | "start": { |
124 | "line": 58, | 124 | "line": 60, |
125 | "column": 28 | 125 | "column": 28 |
126 | }, | 126 | }, |
127 | "end": { | 127 | "end": { |
128 | "line": 61, | 128 | "line": 63, |
129 | "column": 3 | 129 | "column": 3 |
130 | } | 130 | } |
131 | }, | 131 | }, |
@@ -134,11 +134,11 @@ | |||
134 | "defaultMessage": "!!!To add self hosted services, you need a Franz Premium Supporter Account.", | 134 | "defaultMessage": "!!!To add self hosted services, you need a Franz Premium Supporter Account.", |
135 | "file": "src/components/settings/services/EditServiceForm.js", | 135 | "file": "src/components/settings/services/EditServiceForm.js", |
136 | "start": { | 136 | "start": { |
137 | "line": 62, | 137 | "line": 64, |
138 | "column": 24 | 138 | "column": 24 |
139 | }, | 139 | }, |
140 | "end": { | 140 | "end": { |
141 | "line": 65, | 141 | "line": 67, |
142 | "column": 3 | 142 | "column": 3 |
143 | } | 143 | } |
144 | }, | 144 | }, |
@@ -147,11 +147,11 @@ | |||
147 | "defaultMessage": "!!!Upgrade your account", | 147 | "defaultMessage": "!!!Upgrade your account", |
148 | "file": "src/components/settings/services/EditServiceForm.js", | 148 | "file": "src/components/settings/services/EditServiceForm.js", |
149 | "start": { | 149 | "start": { |
150 | "line": 66, | 150 | "line": 68, |
151 | "column": 27 | 151 | "column": 27 |
152 | }, | 152 | }, |
153 | "end": { | 153 | "end": { |
154 | "line": 69, | 154 | "line": 71, |
155 | "column": 3 | 155 | "column": 3 |
156 | } | 156 | } |
157 | }, | 157 | }, |
@@ -160,11 +160,11 @@ | |||
160 | "defaultMessage": "!!!You will be notified about all new messages in a channel, not just @username, @channel, @here, ...", | 160 | "defaultMessage": "!!!You will be notified about all new messages in a channel, not just @username, @channel, @here, ...", |
161 | "file": "src/components/settings/services/EditServiceForm.js", | 161 | "file": "src/components/settings/services/EditServiceForm.js", |
162 | "start": { | 162 | "start": { |
163 | "line": 70, | 163 | "line": 72, |
164 | "column": 23 | 164 | "column": 23 |
165 | }, | 165 | }, |
166 | "end": { | 166 | "end": { |
167 | "line": 73, | 167 | "line": 75, |
168 | "column": 3 | 168 | "column": 3 |
169 | } | 169 | } |
170 | }, | 170 | }, |
@@ -173,11 +173,11 @@ | |||
173 | "defaultMessage": "!!!When disabled, all notification sounds and audio playback are muted", | 173 | "defaultMessage": "!!!When disabled, all notification sounds and audio playback are muted", |
174 | "file": "src/components/settings/services/EditServiceForm.js", | 174 | "file": "src/components/settings/services/EditServiceForm.js", |
175 | "start": { | 175 | "start": { |
176 | "line": 74, | 176 | "line": 76, |
177 | "column": 15 | 177 | "column": 15 |
178 | }, | 178 | }, |
179 | "end": { | 179 | "end": { |
180 | "line": 77, | 180 | "line": 79, |
181 | "column": 3 | 181 | "column": 3 |
182 | } | 182 | } |
183 | }, | 183 | }, |
@@ -186,11 +186,11 @@ | |||
186 | "defaultMessage": "!!!Notifications", | 186 | "defaultMessage": "!!!Notifications", |
187 | "file": "src/components/settings/services/EditServiceForm.js", | 187 | "file": "src/components/settings/services/EditServiceForm.js", |
188 | "start": { | 188 | "start": { |
189 | "line": 78, | 189 | "line": 80, |
190 | "column": 25 | 190 | "column": 25 |
191 | }, | 191 | }, |
192 | "end": { | 192 | "end": { |
193 | "line": 81, | 193 | "line": 83, |
194 | "column": 3 | 194 | "column": 3 |
195 | } | 195 | } |
196 | }, | 196 | }, |
@@ -199,11 +199,11 @@ | |||
199 | "defaultMessage": "!!!Unread message badges", | 199 | "defaultMessage": "!!!Unread message badges", |
200 | "file": "src/components/settings/services/EditServiceForm.js", | 200 | "file": "src/components/settings/services/EditServiceForm.js", |
201 | "start": { | 201 | "start": { |
202 | "line": 82, | 202 | "line": 84, |
203 | "column": 18 | 203 | "column": 18 |
204 | }, | 204 | }, |
205 | "end": { | 205 | "end": { |
206 | "line": 85, | 206 | "line": 87, |
207 | "column": 3 | 207 | "column": 3 |
208 | } | 208 | } |
209 | }, | 209 | }, |
@@ -212,11 +212,11 @@ | |||
212 | "defaultMessage": "!!!General", | 212 | "defaultMessage": "!!!General", |
213 | "file": "src/components/settings/services/EditServiceForm.js", | 213 | "file": "src/components/settings/services/EditServiceForm.js", |
214 | "start": { | 214 | "start": { |
215 | "line": 86, | 215 | "line": 88, |
216 | "column": 19 | 216 | "column": 19 |
217 | }, | 217 | }, |
218 | "end": { | 218 | "end": { |
219 | "line": 89, | 219 | "line": 91, |
220 | "column": 3 | 220 | "column": 3 |
221 | } | 221 | } |
222 | }, | 222 | }, |
@@ -225,11 +225,11 @@ | |||
225 | "defaultMessage": "!!!Delete", | 225 | "defaultMessage": "!!!Delete", |
226 | "file": "src/components/settings/services/EditServiceForm.js", | 226 | "file": "src/components/settings/services/EditServiceForm.js", |
227 | "start": { | 227 | "start": { |
228 | "line": 90, | 228 | "line": 92, |
229 | "column": 14 | 229 | "column": 14 |
230 | }, | 230 | }, |
231 | "end": { | 231 | "end": { |
232 | "line": 93, | 232 | "line": 95, |
233 | "column": 3 | 233 | "column": 3 |
234 | } | 234 | } |
235 | }, | 235 | }, |
@@ -238,11 +238,11 @@ | |||
238 | "defaultMessage": "!!!Drop your image, or click here", | 238 | "defaultMessage": "!!!Drop your image, or click here", |
239 | "file": "src/components/settings/services/EditServiceForm.js", | 239 | "file": "src/components/settings/services/EditServiceForm.js", |
240 | "start": { | 240 | "start": { |
241 | "line": 94, | 241 | "line": 96, |
242 | "column": 14 | 242 | "column": 14 |
243 | }, | 243 | }, |
244 | "end": { | 244 | "end": { |
245 | "line": 97, | 245 | "line": 99, |
246 | "column": 3 | 246 | "column": 3 |
247 | } | 247 | } |
248 | }, | 248 | }, |
@@ -251,11 +251,11 @@ | |||
251 | "defaultMessage": "!!!HTTP/HTTPS Proxy Settings", | 251 | "defaultMessage": "!!!HTTP/HTTPS Proxy Settings", |
252 | "file": "src/components/settings/services/EditServiceForm.js", | 252 | "file": "src/components/settings/services/EditServiceForm.js", |
253 | "start": { | 253 | "start": { |
254 | "line": 98, | 254 | "line": 100, |
255 | "column": 17 | 255 | "column": 17 |
256 | }, | 256 | }, |
257 | "end": { | 257 | "end": { |
258 | "line": 101, | 258 | "line": 103, |
259 | "column": 3 | 259 | "column": 3 |
260 | } | 260 | } |
261 | }, | 261 | }, |
@@ -264,11 +264,11 @@ | |||
264 | "defaultMessage": "!!!Please restart Franz after changing proxy Settings.", | 264 | "defaultMessage": "!!!Please restart Franz after changing proxy Settings.", |
265 | "file": "src/components/settings/services/EditServiceForm.js", | 265 | "file": "src/components/settings/services/EditServiceForm.js", |
266 | "start": { | 266 | "start": { |
267 | "line": 102, | 267 | "line": 104, |
268 | "column": 20 | 268 | "column": 20 |
269 | }, | 269 | }, |
270 | "end": { | 270 | "end": { |
271 | "line": 105, | 271 | "line": 107, |
272 | "column": 3 | 272 | "column": 3 |
273 | } | 273 | } |
274 | }, | 274 | }, |
@@ -277,11 +277,11 @@ | |||
277 | "defaultMessage": "!!!Proxy settings will not be synchronized with the Franz servers.", | 277 | "defaultMessage": "!!!Proxy settings will not be synchronized with the Franz servers.", |
278 | "file": "src/components/settings/services/EditServiceForm.js", | 278 | "file": "src/components/settings/services/EditServiceForm.js", |
279 | "start": { | 279 | "start": { |
280 | "line": 106, | 280 | "line": 108, |
281 | "column": 13 | 281 | "column": 13 |
282 | }, | 282 | }, |
283 | "end": { | 283 | "end": { |
284 | "line": 109, | 284 | "line": 111, |
285 | "column": 3 | 285 | "column": 3 |
286 | } | 286 | } |
287 | } | 287 | } |
diff --git a/src/i18n/messages/src/components/settings/services/ServicesDashboard.json b/src/i18n/messages/src/components/settings/services/ServicesDashboard.json index 3803c6512..fa661ea2f 100644 --- a/src/i18n/messages/src/components/settings/services/ServicesDashboard.json +++ b/src/i18n/messages/src/components/settings/services/ServicesDashboard.json | |||
@@ -4,11 +4,11 @@ | |||
4 | "defaultMessage": "!!!Your services", | 4 | "defaultMessage": "!!!Your services", |
5 | "file": "src/components/settings/services/ServicesDashboard.js", | 5 | "file": "src/components/settings/services/ServicesDashboard.js", |
6 | "start": { | 6 | "start": { |
7 | "line": 14, | 7 | "line": 15, |
8 | "column": 12 | 8 | "column": 12 |
9 | }, | 9 | }, |
10 | "end": { | 10 | "end": { |
11 | "line": 17, | 11 | "line": 18, |
12 | "column": 3 | 12 | "column": 3 |
13 | } | 13 | } |
14 | }, | 14 | }, |
@@ -17,11 +17,11 @@ | |||
17 | "defaultMessage": "!!!Search service", | 17 | "defaultMessage": "!!!Search service", |
18 | "file": "src/components/settings/services/ServicesDashboard.js", | 18 | "file": "src/components/settings/services/ServicesDashboard.js", |
19 | "start": { | 19 | "start": { |
20 | "line": 18, | 20 | "line": 19, |
21 | "column": 17 | 21 | "column": 17 |
22 | }, | 22 | }, |
23 | "end": { | 23 | "end": { |
24 | "line": 21, | 24 | "line": 22, |
25 | "column": 3 | 25 | "column": 3 |
26 | } | 26 | } |
27 | }, | 27 | }, |
@@ -30,11 +30,11 @@ | |||
30 | "defaultMessage": "!!!You haven't added any services yet.", | 30 | "defaultMessage": "!!!You haven't added any services yet.", |
31 | "file": "src/components/settings/services/ServicesDashboard.js", | 31 | "file": "src/components/settings/services/ServicesDashboard.js", |
32 | "start": { | 32 | "start": { |
33 | "line": 22, | 33 | "line": 23, |
34 | "column": 19 | 34 | "column": 19 |
35 | }, | 35 | }, |
36 | "end": { | 36 | "end": { |
37 | "line": 25, | 37 | "line": 26, |
38 | "column": 3 | 38 | "column": 3 |
39 | } | 39 | } |
40 | }, | 40 | }, |
@@ -43,11 +43,11 @@ | |||
43 | "defaultMessage": "!!!Sorry, but no service matched your search term.", | 43 | "defaultMessage": "!!!Sorry, but no service matched your search term.", |
44 | "file": "src/components/settings/services/ServicesDashboard.js", | 44 | "file": "src/components/settings/services/ServicesDashboard.js", |
45 | "start": { | 45 | "start": { |
46 | "line": 26, | 46 | "line": 27, |
47 | "column": 18 | 47 | "column": 18 |
48 | }, | 48 | }, |
49 | "end": { | 49 | "end": { |
50 | "line": 29, | 50 | "line": 30, |
51 | "column": 3 | 51 | "column": 3 |
52 | } | 52 | } |
53 | }, | 53 | }, |
@@ -56,11 +56,11 @@ | |||
56 | "defaultMessage": "!!!Discover services", | 56 | "defaultMessage": "!!!Discover services", |
57 | "file": "src/components/settings/services/ServicesDashboard.js", | 57 | "file": "src/components/settings/services/ServicesDashboard.js", |
58 | "start": { | 58 | "start": { |
59 | "line": 30, | 59 | "line": 31, |
60 | "column": 20 | 60 | "column": 20 |
61 | }, | 61 | }, |
62 | "end": { | 62 | "end": { |
63 | "line": 33, | 63 | "line": 34, |
64 | "column": 3 | 64 | "column": 3 |
65 | } | 65 | } |
66 | }, | 66 | }, |
@@ -69,11 +69,11 @@ | |||
69 | "defaultMessage": "!!!Could not load your services", | 69 | "defaultMessage": "!!!Could not load your services", |
70 | "file": "src/components/settings/services/ServicesDashboard.js", | 70 | "file": "src/components/settings/services/ServicesDashboard.js", |
71 | "start": { | 71 | "start": { |
72 | "line": 34, | 72 | "line": 35, |
73 | "column": 25 | 73 | "column": 25 |
74 | }, | 74 | }, |
75 | "end": { | 75 | "end": { |
76 | "line": 37, | 76 | "line": 38, |
77 | "column": 3 | 77 | "column": 3 |
78 | } | 78 | } |
79 | }, | 79 | }, |
@@ -82,11 +82,11 @@ | |||
82 | "defaultMessage": "!!!Try again", | 82 | "defaultMessage": "!!!Try again", |
83 | "file": "src/components/settings/services/ServicesDashboard.js", | 83 | "file": "src/components/settings/services/ServicesDashboard.js", |
84 | "start": { | 84 | "start": { |
85 | "line": 38, | 85 | "line": 39, |
86 | "column": 21 | 86 | "column": 21 |
87 | }, | 87 | }, |
88 | "end": { | 88 | "end": { |
89 | "line": 41, | 89 | "line": 42, |
90 | "column": 3 | 90 | "column": 3 |
91 | } | 91 | } |
92 | }, | 92 | }, |
@@ -95,11 +95,11 @@ | |||
95 | "defaultMessage": "!!!Your changes have been saved", | 95 | "defaultMessage": "!!!Your changes have been saved", |
96 | "file": "src/components/settings/services/ServicesDashboard.js", | 96 | "file": "src/components/settings/services/ServicesDashboard.js", |
97 | "start": { | 97 | "start": { |
98 | "line": 42, | 98 | "line": 43, |
99 | "column": 15 | 99 | "column": 15 |
100 | }, | 100 | }, |
101 | "end": { | 101 | "end": { |
102 | "line": 45, | 102 | "line": 46, |
103 | "column": 3 | 103 | "column": 3 |
104 | } | 104 | } |
105 | }, | 105 | }, |
@@ -108,11 +108,11 @@ | |||
108 | "defaultMessage": "!!!Service has been deleted", | 108 | "defaultMessage": "!!!Service has been deleted", |
109 | "file": "src/components/settings/services/ServicesDashboard.js", | 109 | "file": "src/components/settings/services/ServicesDashboard.js", |
110 | "start": { | 110 | "start": { |
111 | "line": 46, | 111 | "line": 47, |
112 | "column": 15 | 112 | "column": 15 |
113 | }, | 113 | }, |
114 | "end": { | 114 | "end": { |
115 | "line": 49, | 115 | "line": 50, |
116 | "column": 3 | 116 | "column": 3 |
117 | } | 117 | } |
118 | } | 118 | } |
diff --git a/src/i18n/messages/src/features/serviceLimit/components/AnnouncementScreen.json b/src/i18n/messages/src/features/serviceLimit/components/AnnouncementScreen.json new file mode 100644 index 000000000..e6e3cef99 --- /dev/null +++ b/src/i18n/messages/src/features/serviceLimit/components/AnnouncementScreen.json | |||
@@ -0,0 +1,15 @@ | |||
1 | [ | ||
2 | { | ||
3 | "id": "feature.announcements.changelog.headline", | ||
4 | "defaultMessage": "!!!Changes in Franz {version}", | ||
5 | "file": "src/features/serviceLimit/components/AnnouncementScreen.js", | ||
6 | "start": { | ||
7 | "line": 20, | ||
8 | "column": 12 | ||
9 | }, | ||
10 | "end": { | ||
11 | "line": 23, | ||
12 | "column": 3 | ||
13 | } | ||
14 | } | ||
15 | ] \ No newline at end of file | ||
diff --git a/src/i18n/messages/src/features/serviceLimit/components/LimitReachedInfobox.json b/src/i18n/messages/src/features/serviceLimit/components/LimitReachedInfobox.json new file mode 100644 index 000000000..df5bc03e8 --- /dev/null +++ b/src/i18n/messages/src/features/serviceLimit/components/LimitReachedInfobox.json | |||
@@ -0,0 +1,28 @@ | |||
1 | [ | ||
2 | { | ||
3 | "id": "feature.serviceLimit.limitReached", | ||
4 | "defaultMessage": "!!!You have added {amount} of {limit} services. Please upgrade your account to add more services.", | ||
5 | "file": "src/features/serviceLimit/components/LimitReachedInfobox.js", | ||
6 | "start": { | ||
7 | "line": 11, | ||
8 | "column": 16 | ||
9 | }, | ||
10 | "end": { | ||
11 | "line": 14, | ||
12 | "column": 3 | ||
13 | } | ||
14 | }, | ||
15 | { | ||
16 | "id": "premiumFeature.button.upgradeAccount", | ||
17 | "defaultMessage": "!!!Upgrade account", | ||
18 | "file": "src/features/serviceLimit/components/LimitReachedInfobox.js", | ||
19 | "start": { | ||
20 | "line": 15, | ||
21 | "column": 10 | ||
22 | }, | ||
23 | "end": { | ||
24 | "line": 18, | ||
25 | "column": 3 | ||
26 | } | ||
27 | } | ||
28 | ] \ No newline at end of file | ||
diff --git a/src/models/Service.js b/src/models/Service.js index 88bce3360..848a84aa2 100644 --- a/src/models/Service.js +++ b/src/models/Service.js | |||
@@ -4,6 +4,11 @@ import normalizeUrl from 'normalize-url'; | |||
4 | 4 | ||
5 | const debug = require('debug')('Franz:Service'); | 5 | const debug = require('debug')('Franz:Service'); |
6 | 6 | ||
7 | export const RESTRICTION_TYPES = { | ||
8 | SERVICE_LIMIT: 0, | ||
9 | CUSTOM_URL: 1, | ||
10 | }; | ||
11 | |||
7 | export default class Service { | 12 | export default class Service { |
8 | id = ''; | 13 | id = ''; |
9 | 14 | ||
@@ -59,6 +64,12 @@ export default class Service { | |||
59 | 64 | ||
60 | @observable errorMessage = ''; | 65 | @observable errorMessage = ''; |
61 | 66 | ||
67 | @observable isUsingCustomUrl = false; | ||
68 | |||
69 | @observable isServiceAccessRestricted = false; | ||
70 | |||
71 | @observable restrictionType = null; | ||
72 | |||
62 | constructor(data, recipe) { | 73 | constructor(data, recipe) { |
63 | if (!data) { | 74 | if (!data) { |
64 | console.error('Service config not valid'); | 75 | console.error('Service config not valid'); |
@@ -111,6 +122,10 @@ export default class Service { | |||
111 | this.unreadDirectMessageCount = 0; | 122 | this.unreadDirectMessageCount = 0; |
112 | this.unreadIndirectMessageCount = 0; | 123 | this.unreadIndirectMessageCount = 0; |
113 | } | 124 | } |
125 | |||
126 | if (this.recipe.hasCustomUrl && this.customUrl) { | ||
127 | this.isUsingCustomUrl = true; | ||
128 | } | ||
114 | }); | 129 | }); |
115 | } | 130 | } |
116 | 131 | ||
diff --git a/src/stores/FeaturesStore.js b/src/stores/FeaturesStore.js index e7832088b..27334c9a2 100644 --- a/src/stores/FeaturesStore.js +++ b/src/stores/FeaturesStore.js | |||
@@ -16,6 +16,8 @@ import workspaces from '../features/workspaces'; | |||
16 | import shareFranz from '../features/shareFranz'; | 16 | import shareFranz from '../features/shareFranz'; |
17 | import announcements from '../features/announcements'; | 17 | import announcements from '../features/announcements'; |
18 | import settingsWS from '../features/settingsWS'; | 18 | import settingsWS from '../features/settingsWS'; |
19 | import serviceLimit from '../features/serviceLimit'; | ||
20 | import communityRecipes from '../features/communityRecipes'; | ||
19 | 21 | ||
20 | import { DEFAULT_FEATURES_CONFIG } from '../config'; | 22 | import { DEFAULT_FEATURES_CONFIG } from '../config'; |
21 | 23 | ||
@@ -75,5 +77,7 @@ export default class FeaturesStore extends Store { | |||
75 | shareFranz(this.stores, this.actions); | 77 | shareFranz(this.stores, this.actions); |
76 | announcements(this.stores, this.actions); | 78 | announcements(this.stores, this.actions); |
77 | settingsWS(this.stores, this.actions); | 79 | settingsWS(this.stores, this.actions); |
80 | serviceLimit(this.stores, this.actions); | ||
81 | communityRecipes(this.stores, this.actions); | ||
78 | } | 82 | } |
79 | } | 83 | } |
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 109ac5cd7..513295b5e 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js | |||
@@ -13,6 +13,8 @@ import CachedRequest from './lib/CachedRequest'; | |||
13 | import { matchRoute } from '../helpers/routing-helpers'; | 13 | import { matchRoute } from '../helpers/routing-helpers'; |
14 | import { gaEvent, statsEvent } from '../lib/analytics'; | 14 | import { gaEvent, statsEvent } from '../lib/analytics'; |
15 | import { workspaceStore } from '../features/workspaces'; | 15 | import { workspaceStore } from '../features/workspaces'; |
16 | import { serviceLimitStore } from '../features/serviceLimit'; | ||
17 | import { RESTRICTION_TYPES } from '../models/Service'; | ||
16 | 18 | ||
17 | const debug = require('debug')('Franz:ServiceStore'); | 19 | const debug = require('debug')('Franz:ServiceStore'); |
18 | 20 | ||
@@ -75,6 +77,7 @@ export default class ServicesStore extends Store { | |||
75 | this._saveActiveService.bind(this), | 77 | this._saveActiveService.bind(this), |
76 | this._logoutReaction.bind(this), | 78 | this._logoutReaction.bind(this), |
77 | this._handleMuteSettings.bind(this), | 79 | this._handleMuteSettings.bind(this), |
80 | this._restrictServiceAccess.bind(this), | ||
78 | ]); | 81 | ]); |
79 | 82 | ||
80 | // Just bind this | 83 | // Just bind this |
@@ -98,7 +101,10 @@ export default class ServicesStore extends Store { | |||
98 | if (this.stores.user.isLoggedIn) { | 101 | if (this.stores.user.isLoggedIn) { |
99 | const services = this.allServicesRequest.execute().result; | 102 | const services = this.allServicesRequest.execute().result; |
100 | if (services) { | 103 | if (services) { |
101 | return observable(services.slice().slice().sort((a, b) => a.order - b.order)); | 104 | return observable(services.slice().slice().sort((a, b) => a.order - b.order).map((s, index) => { |
105 | s.index = index; | ||
106 | return s; | ||
107 | })); | ||
102 | } | 108 | } |
103 | } | 109 | } |
104 | return []; | 110 | return []; |
@@ -153,6 +159,8 @@ export default class ServicesStore extends Store { | |||
153 | 159 | ||
154 | // Actions | 160 | // Actions |
155 | @action async _createService({ recipeId, serviceData, redirect = true }) { | 161 | @action async _createService({ recipeId, serviceData, redirect = true }) { |
162 | if (serviceLimitStore.userHasReachedServiceLimit) return; | ||
163 | |||
156 | const data = this._cleanUpTeamIdAndCustomUrl(recipeId, serviceData); | 164 | const data = this._cleanUpTeamIdAndCustomUrl(recipeId, serviceData); |
157 | 165 | ||
158 | const response = await this.createServiceRequest.execute(recipeId, data)._promise; | 166 | const response = await this.createServiceRequest.execute(recipeId, data)._promise; |
@@ -678,6 +686,33 @@ export default class ServicesStore extends Store { | |||
678 | return serviceData; | 686 | return serviceData; |
679 | } | 687 | } |
680 | 688 | ||
689 | _restrictServiceAccess() { | ||
690 | const { features } = this.stores.features; | ||
691 | const { userHasReachedServiceLimit, serviceLimit } = this.stores.serviceLimit; | ||
692 | |||
693 | this.all.map((service, index) => { | ||
694 | if (userHasReachedServiceLimit) { | ||
695 | service.isServiceAccessRestricted = index >= serviceLimit; | ||
696 | service.restrictionType = RESTRICTION_TYPES.SERVICE_LIMIT; | ||
697 | |||
698 | if (index >= serviceLimit) { | ||
699 | debug('Restricting access to server due to service limit'); | ||
700 | } | ||
701 | } | ||
702 | |||
703 | if (service.isUsingCustomUrl) { | ||
704 | service.isServiceAccessRestricted = features.isCustomUrlIncludedInCurrentPlan; | ||
705 | service.restrictionType = RESTRICTION_TYPES.CUSTOM_URL; | ||
706 | |||
707 | if (features.isCustomUrlIncludedInCurrentPlan) { | ||
708 | debug('Restricting access to server due to custom url'); | ||
709 | } | ||
710 | } | ||
711 | |||
712 | return service; | ||
713 | }); | ||
714 | } | ||
715 | |||
681 | // Helper | 716 | // Helper |
682 | _initializeServiceRecipeInWebview(serviceId) { | 717 | _initializeServiceRecipeInWebview(serviceId) { |
683 | const service = this.one(serviceId); | 718 | const service = this.one(serviceId); |
diff --git a/src/stores/index.js b/src/stores/index.js index 1912418a2..c9ec77612 100644 --- a/src/stores/index.js +++ b/src/stores/index.js | |||
@@ -12,6 +12,8 @@ import RequestStore from './RequestStore'; | |||
12 | import GlobalErrorStore from './GlobalErrorStore'; | 12 | import GlobalErrorStore from './GlobalErrorStore'; |
13 | import { workspaceStore } from '../features/workspaces'; | 13 | import { workspaceStore } from '../features/workspaces'; |
14 | import { announcementsStore } from '../features/announcements'; | 14 | import { announcementsStore } from '../features/announcements'; |
15 | import { serviceLimitStore } from '../features/serviceLimit'; | ||
16 | import { communityRecipesStore } from '../features/communityRecipes'; | ||
15 | 17 | ||
16 | export default (api, actions, router) => { | 18 | export default (api, actions, router) => { |
17 | const stores = {}; | 19 | const stores = {}; |
@@ -31,6 +33,8 @@ export default (api, actions, router) => { | |||
31 | globalError: new GlobalErrorStore(stores, api, actions), | 33 | globalError: new GlobalErrorStore(stores, api, actions), |
32 | workspaces: workspaceStore, | 34 | workspaces: workspaceStore, |
33 | announcements: announcementsStore, | 35 | announcements: announcementsStore, |
36 | serviceLimit: serviceLimitStore, | ||
37 | communityRecipes: communityRecipesStore, | ||
34 | }); | 38 | }); |
35 | // Initialize all stores | 39 | // Initialize all stores |
36 | Object.keys(stores).forEach((name) => { | 40 | Object.keys(stores).forEach((name) => { |
diff --git a/src/styles/recipes.scss b/src/styles/recipes.scss index 84222e1fe..56a248e98 100644 --- a/src/styles/recipes.scss +++ b/src/styles/recipes.scss | |||
@@ -12,7 +12,7 @@ | |||
12 | display: flex; | 12 | display: flex; |
13 | flex-flow: row wrap; | 13 | flex-flow: row wrap; |
14 | height: auto; | 14 | height: auto; |
15 | min-height: 70%; | 15 | // min-height: 70%; |
16 | 16 | ||
17 | &.recipes__list--disabled { | 17 | &.recipes__list--disabled { |
18 | filter: grayscale(100%); | 18 | filter: grayscale(100%); |