diff options
Diffstat (limited to 'src/components/settings/services/ServicesDashboard.tsx')
-rw-r--r-- | src/components/settings/services/ServicesDashboard.tsx | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/src/components/settings/services/ServicesDashboard.tsx b/src/components/settings/services/ServicesDashboard.tsx new file mode 100644 index 000000000..36057902f --- /dev/null +++ b/src/components/settings/services/ServicesDashboard.tsx | |||
@@ -0,0 +1,188 @@ | |||
1 | import { Component, ReactElement } from 'react'; | ||
2 | import { observer } from 'mobx-react'; | ||
3 | import { Link } from 'react-router-dom'; | ||
4 | import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl'; | ||
5 | import { To } from 'history'; | ||
6 | import SearchInput from '../../ui/SearchInput'; | ||
7 | import Infobox from '../../ui/Infobox'; | ||
8 | import Loader from '../../ui/Loader'; | ||
9 | import FAB from '../../ui/FAB'; | ||
10 | import ServiceItem from './ServiceItem'; | ||
11 | import Appear from '../../ui/effects/Appear'; | ||
12 | import { H1 } from '../../ui/headline'; | ||
13 | import Service from '../../../models/Service'; | ||
14 | |||
15 | const messages = defineMessages({ | ||
16 | headline: { | ||
17 | id: 'settings.services.headline', | ||
18 | defaultMessage: 'Your services', | ||
19 | }, | ||
20 | searchService: { | ||
21 | id: 'settings.searchService', | ||
22 | defaultMessage: 'Search service', | ||
23 | }, | ||
24 | noServicesAdded: { | ||
25 | id: 'settings.services.noServicesAdded', | ||
26 | defaultMessage: 'Start by adding a service.', | ||
27 | }, | ||
28 | noServiceFound: { | ||
29 | id: 'settings.services.nothingFound', | ||
30 | defaultMessage: 'Sorry, but no service matched your search term.', | ||
31 | }, | ||
32 | discoverServices: { | ||
33 | id: 'settings.services.discoverServices', | ||
34 | defaultMessage: 'Discover services', | ||
35 | }, | ||
36 | servicesRequestFailed: { | ||
37 | id: 'settings.services.servicesRequestFailed', | ||
38 | defaultMessage: 'Could not load your services', | ||
39 | }, | ||
40 | tryReloadServices: { | ||
41 | id: 'settings.account.tryReloadServices', | ||
42 | defaultMessage: 'Try again', | ||
43 | }, | ||
44 | updatedInfo: { | ||
45 | id: 'settings.services.updatedInfo', | ||
46 | defaultMessage: 'Your changes have been saved', | ||
47 | }, | ||
48 | deletedInfo: { | ||
49 | id: 'settings.services.deletedInfo', | ||
50 | defaultMessage: 'Service has been deleted', | ||
51 | }, | ||
52 | }); | ||
53 | |||
54 | interface IProps extends WrappedComponentProps { | ||
55 | services: Service[]; | ||
56 | isLoading: boolean; | ||
57 | // toggleService: any; // TODO - - [TECH DEBT] check it later | ||
58 | filterServices: any; | ||
59 | resetFilter: () => void; | ||
60 | goTo: (to: To, state?: any) => void; | ||
61 | servicesRequestFailed: boolean; | ||
62 | retryServicesRequest: () => void; | ||
63 | status: any; | ||
64 | searchNeedle: string | null; | ||
65 | } | ||
66 | |||
67 | @observer | ||
68 | class ServicesDashboard extends Component<IProps> { | ||
69 | render(): ReactElement { | ||
70 | const { | ||
71 | services, | ||
72 | isLoading, | ||
73 | // toggleService, // TODO - - [TECH DEBT] check it later | ||
74 | filterServices, | ||
75 | resetFilter, | ||
76 | goTo, | ||
77 | servicesRequestFailed, | ||
78 | retryServicesRequest, | ||
79 | status, | ||
80 | searchNeedle = '', | ||
81 | intl, | ||
82 | } = this.props; | ||
83 | |||
84 | return ( | ||
85 | <div className="settings__main"> | ||
86 | <div className="settings__header"> | ||
87 | <H1>{intl.formatMessage(messages.headline)}</H1> | ||
88 | </div> | ||
89 | <div className="settings__body"> | ||
90 | {(services.length > 0 || searchNeedle) && !isLoading && ( | ||
91 | <SearchInput | ||
92 | placeholder={intl.formatMessage(messages.searchService)} | ||
93 | onChange={needle => filterServices({ needle })} | ||
94 | onReset={() => resetFilter()} | ||
95 | autoFocus | ||
96 | /> | ||
97 | )} | ||
98 | {!isLoading && servicesRequestFailed && ( | ||
99 | <Infobox | ||
100 | icon="alert" | ||
101 | type="danger" | ||
102 | ctaLabel={intl.formatMessage(messages.tryReloadServices)} | ||
103 | ctaLoading={isLoading} | ||
104 | ctaOnClick={retryServicesRequest} | ||
105 | > | ||
106 | {intl.formatMessage(messages.servicesRequestFailed)} | ||
107 | </Infobox> | ||
108 | )} | ||
109 | |||
110 | {status.length > 0 && status.includes('updated') && ( | ||
111 | <Appear> | ||
112 | <Infobox | ||
113 | type="success" | ||
114 | icon="checkbox-marked-circle-outline" | ||
115 | dismissible | ||
116 | > | ||
117 | {intl.formatMessage(messages.updatedInfo)} | ||
118 | </Infobox> | ||
119 | </Appear> | ||
120 | )} | ||
121 | |||
122 | {status.length > 0 && status.includes('service-deleted') && ( | ||
123 | <Appear> | ||
124 | <Infobox | ||
125 | type="success" | ||
126 | icon="checkbox-marked-circle-outline" | ||
127 | dismissible | ||
128 | > | ||
129 | {intl.formatMessage(messages.deletedInfo)} | ||
130 | </Infobox> | ||
131 | </Appear> | ||
132 | )} | ||
133 | |||
134 | {!isLoading && services.length === 0 && !searchNeedle && ( | ||
135 | <div className="align-middle settings__empty-state"> | ||
136 | <p className="settings__empty-text"> | ||
137 | <span className="emoji"> | ||
138 | <img src="./assets/images/emoji/star.png" alt="" /> | ||
139 | </span> | ||
140 | {intl.formatMessage(messages.noServicesAdded)} | ||
141 | </p> | ||
142 | <Link to="/settings/recipes" className="button"> | ||
143 | {intl.formatMessage(messages.discoverServices)} | ||
144 | </Link> | ||
145 | </div> | ||
146 | )} | ||
147 | {!isLoading && services.length === 0 && searchNeedle && ( | ||
148 | <div className="align-middle settings__empty-state"> | ||
149 | <p className="settings__empty-text"> | ||
150 | <span className="emoji"> | ||
151 | <img src="./assets/images/emoji/dontknow.png" alt="" /> | ||
152 | </span> | ||
153 | {intl.formatMessage(messages.noServiceFound)} | ||
154 | </p> | ||
155 | </div> | ||
156 | )} | ||
157 | {isLoading ? ( | ||
158 | <Loader /> | ||
159 | ) : ( | ||
160 | <table className="service-table" role="grid"> | ||
161 | <tbody> | ||
162 | {services.map(service => ( | ||
163 | <ServiceItem | ||
164 | key={service.id} | ||
165 | service={service} | ||
166 | // TODO - - [TECH DEBT][PROPS NOT USED IN COMPONENT] check it later | ||
167 | // toggleAction={() => | ||
168 | // toggleService({ serviceId: service.id }) | ||
169 | // } | ||
170 | goToServiceForm={() => | ||
171 | goTo(`/settings/services/edit/${service.id}`) | ||
172 | } | ||
173 | /> | ||
174 | ))} | ||
175 | </tbody> | ||
176 | </table> | ||
177 | )} | ||
178 | |||
179 | <FAB className="FAB-class"> | ||
180 | <Link to="/settings/recipes">+</Link> | ||
181 | </FAB> | ||
182 | </div> | ||
183 | </div> | ||
184 | ); | ||
185 | } | ||
186 | } | ||
187 | |||
188 | export default injectIntl(ServicesDashboard); | ||