· 6 years ago · Apr 24, 2020, 01:32 PM
1/* eslint-disable max-len */
2/* eslint-disable no-restricted-syntax */
3
4/**
5 * mediaService module for AlaKysy React App
6 * handles all HTTP request related manipulating files used in AlaKysy React App
7 * (c) Peetu 'ppedro' Pasanen
8 */
9
10import axios from 'axios';
11
12let userToken = '';
13
14// WBMA API BASE URL
15const API_URL = 'http://media.mw.metropolia.fi/wbma';
16
17/**
18 * Sets the global userToken variable which is used in authenticated API calls
19 * @param {Object.key.string} token
20 */
21const setUserToken = ({ token }) => {
22 userToken = token;
23};
24
25/**
26 * Returns all file objects from API that have the given tag
27 *
28 * Takes in an object as parameter which holds one key:
29 * @param {Object.key.string} tag
30 */
31const getFilesByTag = async ({ tag }) => {
32 const request = await axios.get(`${ API_URL }/tags/${ tag }`);
33 return request.data;
34};
35
36/**
37 * Returns thumbnail information for a single image with file_id
38 *
39 * Takes in an object as parameter which holds one key:
40 * @param {Object.key} fileID
41 */
42const getThumbnailsForFileId = async ({ fileID }) => {
43 const request = await axios.get(`${ API_URL }/media/${ fileID }`);
44 return request.data.thumbnails;
45};
46
47/**
48 * Requests a specific file from API with given file_id
49 *
50 * Takes in an object as parameter with a single key:
51 * @param {Object.key.number} fileID
52 */
53const getOneFile = async ({ fileID }) => {
54 try {
55 const requestFile = await axios({
56 method: 'GET',
57 url: `${ API_URL }/media/${ fileID }`,
58 });
59
60 const requestThumbnails = await getThumbnailsForFileId({ fileID });
61
62 requestFile.data.thumbnails = requestThumbnails;
63
64 return requestFile.data;
65 } catch (error) {
66 console.log('GetOneFileError: ', error.message);
67 }
68};
69
70/**
71 * Handles uploading a file to the API and adding app tags to it
72 * First we upload the file which if succesful yields a file_id response
73 * We then use this file_id to add tags to the file:
74 * - AKTGHV_CityID_locationID is used in categorizing the added content by city
75 * - AKTGHV_CategoryID_categoryID is used in categorizing the added content by category:
76 * food, culture etc.
77 *
78 * Takes in an object as a parameter which has three keys:
79 * @param {Object.key.object} uploadObject the object which holds the title: string, description: string and file: object
80 * @param {Object.key.number} locationID holds the integer id value for a city, generated from /util/locations.js
81 * @param {Object.key.number} categoryID holds the integer id value for a category, generated from /util/categories.js
82 *
83 * auth:
84 * @param {string} userToken this a variable defined in global scope inside this file and is set when the user is logged in
85 */
86const uploadAndTag = async ({ uploadObject, locationID, categoryID }) => {
87 const formData = new FormData();
88 formData.append('title', uploadObject.title);
89 formData.append('description', uploadObject.description);
90 formData.append('file', uploadObject.file);
91
92 try {
93 const request = await axios({
94 method: 'POST',
95 url: `${ API_URL }/media`,
96 headers: {
97 'x-access-token': userToken,
98 },
99 data: formData,
100 });
101
102 if (request.data.file_id) {
103 await axios({
104 method: 'POST',
105 url: `${ API_URL }/tags`,
106 headers: {
107 'x-access-token': userToken,
108 },
109 data: {
110 file_id: request.data.file_id,
111 tag: 'AKTGHV',
112 },
113 });
114
115 await axios({
116 method: 'POST',
117 url: `${ API_URL }/tags`,
118 headers: {
119 'x-access-token': userToken,
120 },
121 data: {
122 file_id: request.data.file_id,
123 tag: `AKTGHV_CityID_${ locationID }`,
124 },
125 });
126
127 await axios({
128 method: 'POST',
129 url: `${ API_URL }/tags`,
130 headers: {
131 'x-access-token': userToken,
132 },
133 data: {
134 file_id: request.data.file_id,
135 tag: `AKTGHV_CategoryID_${ categoryID }`,
136 },
137 });
138 } else {
139 throw new Error('File upload failed.');
140 }
141
142 return request.data.file_id;
143 } catch (error) {
144 console.log('UploadError: ', error.message);
145 }
146};
147
148/**
149 * Handles updating a file in the API
150 *
151 * Takes in an object as parameter with two keys:
152 * @param {Object.key.number} fileID
153 * @param {Object.key.object} updateObject
154 */
155const updatePicture = async ({ updateObject, fileID }) => {
156 try {
157 await axios({
158 method: 'PUT',
159 url: `${ API_URL }/media/${ fileID }`,
160 headers: {
161 'Content-Type': 'application/json',
162 'x-access-token': userToken,
163 },
164 data: JSON.stringify(updateObject),
165 });
166 } catch (error) {
167 console.log('UpdateError: ', error.message);
168 }
169};
170
171/**
172 * Handles deleting a file from the API
173 * We first delete the file, and then all tags related to that file_id
174 *
175 * After deleting the file we get all tags related to that file_id,
176 * then we use Array.map and Promise.all chaining to delete the tags
177 *
178 * Takes in an object as parameter which holds one key:
179 * @param {Object.key.number} fileID holds the numeric file_id value for the file to be deleted
180 *
181 * auth:
182 * @param {string} userToken this a variable defined in global scope inside this file and is set when the user is logged in
183 */
184const deletePicture = async ({ fileID }) => {
185 try {
186 // first delete the picture
187 await axios({
188 method: 'DELETE',
189 url: `${ API_URL }/media/${ fileID }`,
190 headers: {
191 'x-access-token': userToken,
192 },
193 });
194
195 // then get and delete tags added to the picture
196 await axios({
197 method: 'GET',
198 url: `${ API_URL }/tags/file/${ fileID }`,
199 }).then((tags) => {
200 return Promise.all(tags.data.map((tag) => {
201 return axios({
202 method: 'DELETE',
203 url: `${ API_URL }/tags/${ tag.id }`,
204 headers: {
205 'x-access-token': userToken,
206 },
207 });
208 }));
209 });
210 } catch (error) {
211 console.log('DeleteError: ', error.message);
212 }
213};
214
215/**
216 * Handles getting all files and adding thumbnails to the array
217 * We first get the array of files from the api by the given tag
218 *
219 * We then use Array.map and Promise chaining to fetch thumbnail data
220 * and appending it to the image objects
221 *
222 * Function then returns a sorted (newest first) array of files
223 *
224 * Takes in an object as parameter which holds one key:
225 * @param {Object.key.string} tag
226 */
227const getFilesWithThumbs = async ({ tag }) => {
228 const data = getFilesByTag({ tag })
229 .then((response) => {
230 return Promise.all(response.map((image) => {
231 return getThumbnailsForFileId({ fileID: image.file_id })
232 .then((thumbnails) => {
233 return {
234 ...image,
235 thumbnails,
236 };
237 });
238 }));
239 }).then((endData) => endData.sort((a, b) => new Date(b.time_added) - new Date(a.time_added)));
240 return data;
241};
242
243const getFileFavourites = async ({ fileID }) => {
244 const request = await axios.get(`${ API_URL }/favourites/file/${ fileID }`);
245 return request.data;
246};
247
248const addFileFavourite = async ({ fileID }) => {
249 const request = await axios({
250 method: 'POST',
251 url: `${ API_URL }/favourites`,
252 data: JSON.stringify({
253 file_id: fileID,
254 }),
255 headers: {
256 'x-access-token': userToken,
257 },
258 });
259 return request.data;
260};
261
262const removeFileFavourite = async ({ fileID }) => {
263 const request = await axios({
264 method: 'DELETE',
265 url: `${ API_URL }/favourites/file/${ fileID }`,
266 headers: {
267 'x-access-token': userToken,
268 },
269 });
270 return request.data;
271};
272
273export default {
274 setUserToken,
275 getFilesByTag,
276 getFilesWithThumbs,
277 getFileFavourites,
278 addFileFavourite,
279 removeFileFavourite,
280 uploadAndTag,
281 updatePicture,
282 deletePicture,
283 getOneFile,
284};