[ABANDONED] React/Redux front end for the Flexor social network.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

283 lines
8.4 KiB

5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
4 years ago
4 years ago
  1. // apps.ts
  2. // Copyright (C) 2020 Dwayne Harris
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation, either version 3 of the License, or
  6. // (at your option) any later version.
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU General Public License for more details.
  11. // You should have received a copy of the GNU General Public License
  12. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  13. import { apiFetch } from '../api'
  14. import { setEntities } from '../actions/entities'
  15. import { startRequest, finishRequest } from '../actions/requests'
  16. import { setFieldNotification } from '../actions/forms'
  17. import { listSet, listAppend } from '../actions/lists'
  18. import { objectToQuerystring } from '../utils'
  19. import { normalize } from '../utils/normalization'
  20. import { EntityListKey, Entity } from '../types'
  21. import { AppThunkAction, RequestKey, EntityType, App, AvailabilityResponse, NotificationType }from '../types'
  22. interface AppsResponse {
  23. apps: App[]
  24. continuation?: string
  25. }
  26. export const fetchApps = (sort?: string, continuation?: string): AppThunkAction => async dispatch => {
  27. dispatch(startRequest(RequestKey.FetchApps))
  28. try {
  29. const response = await apiFetch<AppsResponse>({
  30. path: `/v1/apps?${objectToQuerystring({ sort, continuation })}`,
  31. })
  32. const apps = normalize(response.apps, EntityType.App)
  33. dispatch(setEntities(apps.entities))
  34. if (continuation) {
  35. dispatch(listAppend(EntityListKey.Apps, apps.keys, response.continuation))
  36. } else {
  37. dispatch(listSet(EntityListKey.Apps, apps.keys, response.continuation))
  38. }
  39. dispatch(finishRequest(RequestKey.FetchApps, true))
  40. } catch (err) {
  41. dispatch(finishRequest(RequestKey.FetchApps, false))
  42. throw err
  43. }
  44. }
  45. export const fetchCreatedApps = (sort?: string): AppThunkAction => async dispatch => {
  46. dispatch(startRequest(RequestKey.FetchSelfApps))
  47. try {
  48. const response = await apiFetch<AppsResponse>({
  49. path: `/v1/self/apps?${objectToQuerystring({ sort })}`,
  50. })
  51. const apps = normalize(response.apps, EntityType.App)
  52. dispatch(setEntities(apps.entities))
  53. dispatch(listSet(EntityListKey.CreatedApps, apps.keys))
  54. dispatch(finishRequest(RequestKey.FetchSelfApps, true))
  55. } catch (err) {
  56. dispatch(finishRequest(RequestKey.FetchSelfApps, false))
  57. throw err
  58. }
  59. }
  60. export const checkAppAvailability = (name: string): AppThunkAction => async dispatch => {
  61. dispatch(startRequest(RequestKey.FetchAppAvailability))
  62. try {
  63. const { id, available } = await apiFetch<AvailabilityResponse>({
  64. path: '/v1/app/available',
  65. method: 'post',
  66. body: {
  67. name,
  68. },
  69. })
  70. if (available) {
  71. dispatch(setFieldNotification('name', NotificationType.Success, `${id} is available`))
  72. } else {
  73. dispatch(setFieldNotification('name', NotificationType.Error, `${id} isn't available`))
  74. }
  75. dispatch(finishRequest(RequestKey.FetchAppAvailability, true))
  76. } catch (err) {
  77. dispatch(finishRequest(RequestKey.FetchAppAvailability, false))
  78. throw err
  79. }
  80. }
  81. interface AppOptions {
  82. name: string
  83. about?: string
  84. websiteUrl?: string
  85. companyName?: string
  86. version: string
  87. composerUrl?: string
  88. rendererUrl?: string
  89. imageUrl?: string
  90. coverImageUrl?: string
  91. iconImageUrl?: string
  92. }
  93. interface CreateAppResponse {
  94. id: string
  95. }
  96. export const createApp = (options: AppOptions): AppThunkAction<string> => async dispatch => {
  97. const { name, about, websiteUrl, companyName, version, composerUrl, rendererUrl, imageUrl, coverImageUrl, iconImageUrl } = options
  98. dispatch(startRequest(RequestKey.CreateApp))
  99. try {
  100. const { id } = await apiFetch<CreateAppResponse>({
  101. path: '/v1/app',
  102. method: 'post',
  103. body: {
  104. name,
  105. about,
  106. websiteUrl,
  107. companyName,
  108. version,
  109. composerUrl,
  110. rendererUrl,
  111. imageUrl,
  112. coverImageUrl,
  113. iconImageUrl,
  114. },
  115. })
  116. dispatch(finishRequest(RequestKey.CreateApp, true))
  117. return id
  118. } catch (err) {
  119. dispatch(finishRequest(RequestKey.CreateApp, false))
  120. throw err
  121. }
  122. }
  123. export const updateApp = (id: string, options: AppOptions): AppThunkAction => async dispatch => {
  124. const { name, about, websiteUrl, companyName, version, composerUrl, rendererUrl, imageUrl, coverImageUrl, iconImageUrl } = options
  125. dispatch(startRequest(RequestKey.UpdateApp))
  126. try {
  127. await apiFetch({
  128. path: `/v1/app/${id}`,
  129. method: 'put',
  130. body: {
  131. name,
  132. about,
  133. websiteUrl,
  134. companyName,
  135. version,
  136. composerUrl,
  137. rendererUrl,
  138. imageUrl,
  139. coverImageUrl,
  140. iconImageUrl,
  141. },
  142. })
  143. dispatch(finishRequest(RequestKey.UpdateApp, true))
  144. } catch (err) {
  145. dispatch(finishRequest(RequestKey.UpdateApp, false))
  146. throw err
  147. }
  148. }
  149. export const fetchApp = (id: string): AppThunkAction => async dispatch => {
  150. dispatch(startRequest(RequestKey.FetchApp))
  151. try {
  152. const app = await apiFetch<App>({
  153. path: `/v1/app/${id}`,
  154. method: 'get',
  155. })
  156. const apps = normalize([app], EntityType.App)
  157. dispatch(setEntities(apps.entities))
  158. dispatch(finishRequest(RequestKey.FetchApp, true))
  159. } catch (err) {
  160. dispatch(finishRequest(RequestKey.FetchApp, false))
  161. throw err
  162. }
  163. }
  164. export const installApp = (id: string): AppThunkAction => async dispatch => {
  165. dispatch(startRequest(RequestKey.InstallApp))
  166. try {
  167. await apiFetch({
  168. path: `/v1/app/${id}/install`,
  169. method: 'post'
  170. })
  171. dispatch(finishRequest(RequestKey.InstallApp, true))
  172. } catch (err) {
  173. dispatch(finishRequest(RequestKey.InstallApp, false))
  174. throw err
  175. }
  176. }
  177. export const uninstallApp = (id: string): AppThunkAction => async dispatch => {
  178. dispatch(startRequest(RequestKey.UninstallApp))
  179. try {
  180. await apiFetch({
  181. path: `/v1/app/${id}/uninstall`,
  182. method: 'post'
  183. })
  184. dispatch(finishRequest(RequestKey.UninstallApp, true))
  185. } catch (err) {
  186. dispatch(finishRequest(RequestKey.UninstallApp, false))
  187. throw err
  188. }
  189. }
  190. interface FetchPendingAppsResponse {
  191. apps: Entity[]
  192. continuation?: string
  193. }
  194. export const fetchPendingApps = (continuation?: string): AppThunkAction => async dispatch => {
  195. dispatch(startRequest(RequestKey.FetchPendingApps))
  196. try {
  197. const response = await apiFetch<FetchPendingAppsResponse>({
  198. path: `/v1/apps/pending?${objectToQuerystring({ continuation })}`,
  199. method: 'get',
  200. })
  201. const apps = normalize(response.apps, EntityType.App)
  202. dispatch(setEntities(apps.entities))
  203. dispatch(listSet(EntityListKey.PendingApps, apps.keys, response.continuation))
  204. dispatch(finishRequest(RequestKey.FetchPendingApps, true))
  205. } catch (err) {
  206. dispatch(finishRequest(RequestKey.FetchPendingApps, false))
  207. throw err
  208. }
  209. }
  210. export const activateApp = (id: string): AppThunkAction => async dispatch => {
  211. dispatch(startRequest(RequestKey.ActivateApp))
  212. try {
  213. await apiFetch({
  214. path: `/v1/app/${id}/activate`,
  215. method: 'post',
  216. })
  217. dispatch(finishRequest(RequestKey.ActivateApp, true))
  218. } catch (err) {
  219. dispatch(finishRequest(RequestKey.ActivateApp, false))
  220. throw err
  221. }
  222. }
  223. export const setPreinstall = (id: string): AppThunkAction => async dispatch => {
  224. dispatch(startRequest(RequestKey.SetPreinstall))
  225. try {
  226. await apiFetch({
  227. path: `/v1/app/${id}/preinstall`,
  228. method: 'post',
  229. })
  230. dispatch(finishRequest(RequestKey.SetPreinstall, true))
  231. } catch (err) {
  232. dispatch(finishRequest(RequestKey.SetPreinstall, false))
  233. throw err
  234. }
  235. }