diff options
author | Stefan Malzner <stefan@adlk.io> | 2017-10-13 12:29:40 +0200 |
---|---|---|
committer | Stefan Malzner <stefan@adlk.io> | 2017-10-13 12:29:40 +0200 |
commit | 58cda9cc7fb79ca9df6746de7f9662bc08dc156a (patch) | |
tree | 1211600c2a5d3b5f81c435c6896618111a611720 /src/components/settings/recipes | |
download | ferdium-app-58cda9cc7fb79ca9df6746de7f9662bc08dc156a.tar.gz ferdium-app-58cda9cc7fb79ca9df6746de7f9662bc08dc156a.tar.zst ferdium-app-58cda9cc7fb79ca9df6746de7f9662bc08dc156a.zip |
initial commit
Diffstat (limited to 'src/components/settings/recipes')
-rw-r--r-- | src/components/settings/recipes/RecipeItem.js | 34 | ||||
-rw-r--r-- | src/components/settings/recipes/RecipesDashboard.js | 151 |
2 files changed, 185 insertions, 0 deletions
diff --git a/src/components/settings/recipes/RecipeItem.js b/src/components/settings/recipes/RecipeItem.js new file mode 100644 index 000000000..7b2f64d26 --- /dev/null +++ b/src/components/settings/recipes/RecipeItem.js | |||
@@ -0,0 +1,34 @@ | |||
1 | import React, { Component } from 'react'; | ||
2 | import PropTypes from 'prop-types'; | ||
3 | import { observer } from 'mobx-react'; | ||
4 | |||
5 | import RecipePreviewModel from '../../../models/RecipePreview'; | ||
6 | |||
7 | @observer | ||
8 | export default class RecipeItem extends Component { | ||
9 | static propTypes = { | ||
10 | recipe: PropTypes.instanceOf(RecipePreviewModel).isRequired, | ||
11 | onClick: PropTypes.func.isRequired, | ||
12 | }; | ||
13 | |||
14 | render() { | ||
15 | const { recipe, onClick } = this.props; | ||
16 | |||
17 | return ( | ||
18 | <button | ||
19 | className="recipe-teaser" | ||
20 | onClick={onClick} | ||
21 | > | ||
22 | {recipe.local && ( | ||
23 | <span className="recipe-teaser__dev-badge">dev</span> | ||
24 | )} | ||
25 | <img | ||
26 | src={recipe.icons.svg} | ||
27 | className="recipe-teaser__icon" | ||
28 | alt="" | ||
29 | /> | ||
30 | <span className="recipe-teaser__label">{recipe.name}</span> | ||
31 | </button> | ||
32 | ); | ||
33 | } | ||
34 | } | ||
diff --git a/src/components/settings/recipes/RecipesDashboard.js b/src/components/settings/recipes/RecipesDashboard.js new file mode 100644 index 000000000..02ea04e35 --- /dev/null +++ b/src/components/settings/recipes/RecipesDashboard.js | |||
@@ -0,0 +1,151 @@ | |||
1 | import React, { Component } from 'react'; | ||
2 | import PropTypes from 'prop-types'; | ||
3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; | ||
4 | import { defineMessages, intlShape } from 'react-intl'; | ||
5 | import { Link } from 'react-router'; | ||
6 | |||
7 | import SearchInput from '../../ui/SearchInput'; | ||
8 | import Infobox from '../../ui/Infobox'; | ||
9 | import RecipeItem from './RecipeItem'; | ||
10 | import Loader from '../../ui/Loader'; | ||
11 | import Appear from '../../ui/effects/Appear'; | ||
12 | |||
13 | const messages = defineMessages({ | ||
14 | headline: { | ||
15 | id: 'settings.recipes.headline', | ||
16 | defaultMessage: '!!!Available Services', | ||
17 | }, | ||
18 | mostPopularRecipes: { | ||
19 | id: 'settings.recipes.mostPopular', | ||
20 | defaultMessage: '!!!Most popular', | ||
21 | }, | ||
22 | allRecipes: { | ||
23 | id: 'settings.recipes.all', | ||
24 | defaultMessage: '!!!All services', | ||
25 | }, | ||
26 | devRecipes: { | ||
27 | id: 'settings.recipes.dev', | ||
28 | defaultMessage: '!!!Development', | ||
29 | }, | ||
30 | nothingFound: { | ||
31 | id: 'settings.recipes.nothingFound', | ||
32 | defaultMessage: '!!!Sorry, but no service matched your search term.', | ||
33 | }, | ||
34 | servicesSuccessfulAddedInfo: { | ||
35 | id: 'settings.recipes.servicesSuccessfulAddedInfo', | ||
36 | defaultMessage: '!!!Service successfully added', | ||
37 | }, | ||
38 | }); | ||
39 | |||
40 | @observer | ||
41 | export default class RecipesDashboard extends Component { | ||
42 | static propTypes = { | ||
43 | recipes: MobxPropTypes.arrayOrObservableArray.isRequired, | ||
44 | isLoading: PropTypes.bool.isRequired, | ||
45 | hasLoadedRecipes: PropTypes.bool.isRequired, | ||
46 | showAddServiceInterface: PropTypes.func.isRequired, | ||
47 | searchRecipes: PropTypes.func.isRequired, | ||
48 | resetSearch: PropTypes.func.isRequired, | ||
49 | serviceStatus: MobxPropTypes.arrayOrObservableArray.isRequired, | ||
50 | devRecipesCount: PropTypes.number.isRequired, | ||
51 | searchNeedle: PropTypes.string, | ||
52 | }; | ||
53 | |||
54 | static defaultProps = { | ||
55 | searchNeedle: '', | ||
56 | } | ||
57 | |||
58 | static contextTypes = { | ||
59 | intl: intlShape, | ||
60 | }; | ||
61 | |||
62 | render() { | ||
63 | const { | ||
64 | recipes, | ||
65 | isLoading, | ||
66 | hasLoadedRecipes, | ||
67 | showAddServiceInterface, | ||
68 | searchRecipes, | ||
69 | resetSearch, | ||
70 | serviceStatus, | ||
71 | devRecipesCount, | ||
72 | searchNeedle, | ||
73 | } = this.props; | ||
74 | const { intl } = this.context; | ||
75 | |||
76 | return ( | ||
77 | <div className="settings__main"> | ||
78 | <div className="settings__header"> | ||
79 | <SearchInput | ||
80 | className="settings__search-header" | ||
81 | defaultValue={intl.formatMessage(messages.headline)} | ||
82 | onChange={e => searchRecipes(e)} | ||
83 | onReset={() => resetSearch()} | ||
84 | throttle | ||
85 | /> | ||
86 | </div> | ||
87 | <div className="settings__body recipes"> | ||
88 | {serviceStatus.length > 0 && serviceStatus.includes('created') && ( | ||
89 | <Appear> | ||
90 | <Infobox | ||
91 | type="success" | ||
92 | icon="checkbox-marked-circle-outline" | ||
93 | dismissable | ||
94 | > | ||
95 | {intl.formatMessage(messages.servicesSuccessfulAddedInfo)} | ||
96 | </Infobox> | ||
97 | </Appear> | ||
98 | )} | ||
99 | {!searchNeedle && ( | ||
100 | <div className="recipes__navigation"> | ||
101 | <Link | ||
102 | to="/settings/recipes" | ||
103 | className="badge" | ||
104 | activeClassName="badge--primary" | ||
105 | > | ||
106 | {intl.formatMessage(messages.mostPopularRecipes)} | ||
107 | </Link> | ||
108 | <Link | ||
109 | to="/settings/recipes/all" | ||
110 | className="badge" | ||
111 | activeClassName="badge--primary" | ||
112 | > | ||
113 | {intl.formatMessage(messages.allRecipes)} | ||
114 | </Link> | ||
115 | {devRecipesCount > 0 && ( | ||
116 | <Link | ||
117 | to="/settings/recipes/dev" | ||
118 | className="badge" | ||
119 | activeClassName="badge--primary" | ||
120 | > | ||
121 | {intl.formatMessage(messages.devRecipes)} ({devRecipesCount}) | ||
122 | </Link> | ||
123 | )} | ||
124 | </div> | ||
125 | )} | ||
126 | {isLoading ? ( | ||
127 | <Loader /> | ||
128 | ) : ( | ||
129 | <div className="recipes__list"> | ||
130 | {hasLoadedRecipes && recipes.length === 0 && ( | ||
131 | <p className="align-middle settings__empty-state"> | ||
132 | <span className="emoji"> | ||
133 | <img src="./assets/images/emoji/dontknow.png" alt="" /> | ||
134 | </span> | ||
135 | {intl.formatMessage(messages.nothingFound)} | ||
136 | </p> | ||
137 | )} | ||
138 | {recipes.map(recipe => ( | ||
139 | <RecipeItem | ||
140 | key={recipe.id} | ||
141 | recipe={recipe} | ||
142 | onClick={() => showAddServiceInterface({ recipeId: recipe.id })} | ||
143 | /> | ||
144 | ))} | ||
145 | </div> | ||
146 | )} | ||
147 | </div> | ||
148 | </div> | ||
149 | ); | ||
150 | } | ||
151 | } | ||