-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
foursquare-provider.js
179 lines (152 loc) · 4.33 KB
/
foursquare-provider.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import FSQIcon from './foursquare-icon';
import {Provider, KEPLER_FORMAT} from '@kepler.gl/cloud-providers';
import {Auth0Client} from '@auth0/auth0-spa-js';
const NAME = 'foursquare';
const DISPLAY_NAME = 'Foursquare';
const APP_NAME = 'Kepler.gl';
const FOURSQUARE_PRIVATE_STORAGE_ENABLED = true;
const FOURSQUARE_AUTH_AUDIENCE = 'https://foursquare.com/api/';
const FOURSQUARE_AUTH_SCOPE = 'openid profile email';
// Foursquare stores kepler maps using kepler.gl-raw as ImportSource
const FOURSQUARE_KEPLER_GL_IMPORT_SOURCE = 'kepler.gl-raw';
/**
* Converts a FSQ map model to cloud provider map item
* @param model Foursquare Map
* @return {MapItem} Map
*/
function convertFSQModelToMapItem(model, baseApi) {
return {
id: model.id,
title: model.name,
thumbnail: model.previewReadPath,
updatedAt: model.updatedAt,
description: model.description,
loadParams: {
id: model.id,
path: `${baseApi}/${model.id}`
}
};
}
function extractMapFromFSQResponse(response) {
const {
latestState: {data}
} = response;
return data;
}
export default class FoursquareProvider extends Provider {
constructor({clientId, authDomain, apiURL, userMapsURL}) {
super({name: NAME, displayName: DISPLAY_NAME, icon: FSQIcon});
this.icon = FSQIcon;
this.appName = APP_NAME;
this.apiURL = apiURL;
this._auth0 = new Auth0Client({
domain: authDomain,
clientId: clientId,
scope: FOURSQUARE_AUTH_SCOPE,
authorizationParams: {
redirect_uri: window.location.origin,
audience: FOURSQUARE_AUTH_AUDIENCE
},
cacheLocation: 'localstorage'
});
// the domain needs to be passed as input param
this._folderLink = userMapsURL;
this.isNew = true;
}
hasPrivateStorage() {
return FOURSQUARE_PRIVATE_STORAGE_ENABLED;
}
async getUser() {
return this._auth0.getUser();
}
async login() {
return this._auth0.loginWithPopup();
}
async logout() {
return this._auth0.logout({
// this make sure after logging out the sdk will not redirect the user
openUrl: false
});
}
async uploadMap({mapData, options = {}}) {
// TODO: handle replace
const mode = options.overwrite ? 'overwrite' : 'add';
const method = options.overwrite ? 'PUT' : 'POST';
const {map, thumbnail} = mapData;
const {title = '', description = '', id} = map.info;
const headers = await this.getHeaders();
const payload = {
name: title,
description,
importSource: FOURSQUARE_KEPLER_GL_IMPORT_SOURCE,
latestState: {
data: map
}
};
const mapResponse = await fetch(
`${this.apiURL}/v1/maps${mode === 'overwrite' ? `/${id}` : ''}`,
{
method,
headers,
body: JSON.stringify(payload)
}
);
const createMap = await mapResponse.json();
await fetch(`${this.apiURL}/v1/maps/${createMap.id}/thumbnail`, {
method: 'PUT',
headers: {
...headers,
'Content-Type': 'image/png'
},
body: thumbnail
});
return map;
}
async listMaps() {
const headers = await this.getHeaders();
const response = await fetch(
`${this.apiURL}/v1/maps?importSource=${FOURSQUARE_KEPLER_GL_IMPORT_SOURCE}`,
{
method: 'GET',
mode: 'cors',
headers
}
);
const data = await response.json();
return data.items.map(map => convertFSQModelToMapItem(map, `${this.apiURL}/v1/maps`));
}
async downloadMap(loadParams) {
const {id} = loadParams;
if (!id) {
return Promise.reject('No Map is was provider as part of loadParams');
}
const headers = await this.getHeaders();
const response = await fetch(`${this.apiURL}/v1/maps/${id}`, {
method: 'GET',
headers
});
const map = await response.json();
return Promise.resolve({
map: extractMapFromFSQResponse(map),
format: KEPLER_FORMAT
});
}
getMapUrl(loadParams) {
const {id} = loadParams;
return `${this.apiURL}/v1/maps/${id}`;
}
getManagementUrl() {
return this._folderLink;
}
async getAccessToken() {
return this._auth0.getTokenSilently();
}
async getHeaders() {
const accessToken = await this.getAccessToken();
return {
Authorization: `Bearer ${accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json'
};
}
}