@laboratoria/sdk-js 5.3.2 → 6.0.0-beta.0
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/laboratoria-sdk-es.js +9017 -0
- package/dist/laboratoria-sdk-umd.js +1486 -2
- package/package.json +23 -22
- package/.babelrc +0 -5
- package/dist/laboratoria-sdk-esm.js +0 -2
- package/dist/laboratoria-sdk-esm.js.LICENSE.txt +0 -101
- package/dist/laboratoria-sdk-umd.js.LICENSE.txt +0 -101
- package/examples/esm.html +0 -4
- package/examples/umd.html +0 -4
- package/index.js +0 -64
- package/lib/client.js +0 -25
- package/lib/core.js +0 -373
- package/lib/curriculum.js +0 -59
- package/lib/model.js +0 -343
- package/lib/roles.js +0 -10
- package/lib/util.js +0 -68
- package/schemas/core.json +0 -1945
- package/webpack.config.mjs +0 -28
@@ -1,101 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @license
|
3
|
-
* Copyright 2017 Google LLC
|
4
|
-
*
|
5
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
* you may not use this file except in compliance with the License.
|
7
|
-
* You may obtain a copy of the License at
|
8
|
-
*
|
9
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
*
|
11
|
-
* Unless required by applicable law or agreed to in writing, software
|
12
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
* See the License for the specific language governing permissions and
|
15
|
-
* limitations under the License.
|
16
|
-
*/
|
17
|
-
|
18
|
-
/**
|
19
|
-
* @license
|
20
|
-
* Copyright 2019 Google LLC
|
21
|
-
*
|
22
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
23
|
-
* you may not use this file except in compliance with the License.
|
24
|
-
* You may obtain a copy of the License at
|
25
|
-
*
|
26
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
27
|
-
*
|
28
|
-
* Unless required by applicable law or agreed to in writing, software
|
29
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
30
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
31
|
-
* See the License for the specific language governing permissions and
|
32
|
-
* limitations under the License.
|
33
|
-
*/
|
34
|
-
|
35
|
-
/**
|
36
|
-
* @license
|
37
|
-
* Copyright 2020 Google LLC
|
38
|
-
*
|
39
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
40
|
-
* you may not use this file except in compliance with the License.
|
41
|
-
* You may obtain a copy of the License at
|
42
|
-
*
|
43
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
44
|
-
*
|
45
|
-
* Unless required by applicable law or agreed to in writing, software
|
46
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
47
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
48
|
-
* See the License for the specific language governing permissions and
|
49
|
-
* limitations under the License.
|
50
|
-
*/
|
51
|
-
|
52
|
-
/**
|
53
|
-
* @license
|
54
|
-
* Copyright 2020 Google LLC.
|
55
|
-
*
|
56
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
57
|
-
* you may not use this file except in compliance with the License.
|
58
|
-
* You may obtain a copy of the License at
|
59
|
-
*
|
60
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
61
|
-
*
|
62
|
-
* Unless required by applicable law or agreed to in writing, software
|
63
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
64
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
65
|
-
* See the License for the specific language governing permissions and
|
66
|
-
* limitations under the License.
|
67
|
-
*/
|
68
|
-
|
69
|
-
/**
|
70
|
-
* @license
|
71
|
-
* Copyright 2021 Google LLC
|
72
|
-
*
|
73
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
74
|
-
* you may not use this file except in compliance with the License.
|
75
|
-
* You may obtain a copy of the License at
|
76
|
-
*
|
77
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
78
|
-
*
|
79
|
-
* Unless required by applicable law or agreed to in writing, software
|
80
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
81
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
82
|
-
* See the License for the specific language governing permissions and
|
83
|
-
* limitations under the License.
|
84
|
-
*/
|
85
|
-
|
86
|
-
/**
|
87
|
-
* @license
|
88
|
-
* Copyright 2022 Google LLC
|
89
|
-
*
|
90
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
91
|
-
* you may not use this file except in compliance with the License.
|
92
|
-
* You may obtain a copy of the License at
|
93
|
-
*
|
94
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
95
|
-
*
|
96
|
-
* Unless required by applicable law or agreed to in writing, software
|
97
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
98
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
99
|
-
* See the License for the specific language governing permissions and
|
100
|
-
* limitations under the License.
|
101
|
-
*/
|
package/examples/esm.html
DELETED
package/examples/umd.html
DELETED
package/index.js
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
import { initializeApp } from 'firebase/app';
|
2
|
-
import {
|
3
|
-
getAuth,
|
4
|
-
onAuthStateChanged,
|
5
|
-
signInWithEmailAndPassword,
|
6
|
-
signOut,
|
7
|
-
sendPasswordResetEmail,
|
8
|
-
} from 'firebase/auth';
|
9
|
-
import { createAPI as createCoreAPI } from './lib/core';
|
10
|
-
import { createAPI as createCurriculumAPI } from './lib/curriculum';
|
11
|
-
|
12
|
-
export * from './lib/util';
|
13
|
-
|
14
|
-
export const createApp = ({
|
15
|
-
firebaseApiKey = 'AIzaSyAXbaEbpq8NOfn0r8mIrcoHvoGRkJThwdc',
|
16
|
-
firebaseProject = 'laboratoria-la',
|
17
|
-
coreApiUrl = 'https://us-central1-outpost-272720.cloudfunctions.net/core-api',
|
18
|
-
} = {}) => {
|
19
|
-
const firebaseApp = initializeApp({
|
20
|
-
apiKey: firebaseApiKey,
|
21
|
-
authDomain: `${firebaseProject}.firebaseapp.com`,
|
22
|
-
databaseURL: `https://${firebaseProject}.firebaseio.com`,
|
23
|
-
projectId: firebaseProject,
|
24
|
-
});
|
25
|
-
|
26
|
-
const firebaseAuth = getAuth(firebaseApp);
|
27
|
-
const state = { authUser: undefined, user: undefined };
|
28
|
-
const coreAPI = createCoreAPI(coreApiUrl, state);
|
29
|
-
const curriculumAPI = createCurriculumAPI();
|
30
|
-
|
31
|
-
const authAPI = {
|
32
|
-
onChange: fn => onAuthStateChanged(firebaseAuth, (authUser) => {
|
33
|
-
if (!authUser) {
|
34
|
-
Object.assign(state, { authUser: null, user: null });
|
35
|
-
return fn(state);
|
36
|
-
}
|
37
|
-
Object.assign(state, { authUser });
|
38
|
-
coreAPI.user.findById(authUser.uid)
|
39
|
-
.then((user) => {
|
40
|
-
Object.assign(state, { user });
|
41
|
-
fn(state);
|
42
|
-
})
|
43
|
-
.catch((err) => {
|
44
|
-
console.error(err);
|
45
|
-
Object.assign(state, { authUser: null, user: null });
|
46
|
-
fn(state);
|
47
|
-
});
|
48
|
-
}),
|
49
|
-
signIn: (email, password) => signInWithEmailAndPassword(
|
50
|
-
firebaseAuth,
|
51
|
-
email,
|
52
|
-
password,
|
53
|
-
),
|
54
|
-
signOut: () => signOut(firebaseAuth),
|
55
|
-
sendPasswordResetEmail: email => sendPasswordResetEmail(firebaseAuth, email),
|
56
|
-
};
|
57
|
-
|
58
|
-
return {
|
59
|
-
...curriculumAPI,
|
60
|
-
...coreAPI,
|
61
|
-
auth: authAPI,
|
62
|
-
firebaseApp,
|
63
|
-
};
|
64
|
-
};
|
package/lib/client.js
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
export const createClient = (baseUrl, authUser) => async (url, opts = {}) => {
|
2
|
-
const token = authUser ? await authUser.getIdToken() : null;
|
3
|
-
const resp = await fetch(`${baseUrl}${url}`, {
|
4
|
-
mode: 'cors',
|
5
|
-
...opts,
|
6
|
-
headers: {
|
7
|
-
...(token && { authorization: `Bearer ${token}` }),
|
8
|
-
...(opts.body && { 'content-type': 'application/json' }),
|
9
|
-
...opts.headers,
|
10
|
-
},
|
11
|
-
...(opts.body && { body: JSON.stringify(opts.body) }),
|
12
|
-
});
|
13
|
-
|
14
|
-
const body = await resp.json();
|
15
|
-
|
16
|
-
if (resp.status > 202) {
|
17
|
-
throw Object.assign(new Error(body?.message || `HTTP Error ${resp.status}`), {
|
18
|
-
status: resp.status,
|
19
|
-
code: body?.code,
|
20
|
-
body,
|
21
|
-
});
|
22
|
-
}
|
23
|
-
|
24
|
-
return body;
|
25
|
-
};
|
package/lib/core.js
DELETED
@@ -1,373 +0,0 @@
|
|
1
|
-
import md5 from 'blueimp-md5';
|
2
|
-
import { createModels, extendSchemaDefinitions } from './model';
|
3
|
-
import { createClient } from './client.js';
|
4
|
-
import schema from '../schemas/core.json';
|
5
|
-
|
6
|
-
const ONE_HOUR = 60 * 60 * 1000;
|
7
|
-
const ONE_DAY = 24 * ONE_HOUR;
|
8
|
-
|
9
|
-
const extended = {
|
10
|
-
Country: {
|
11
|
-
primaryKey: 'code',
|
12
|
-
plural: 'countries',
|
13
|
-
searchProps: ['code', 'name', "timeZone"],
|
14
|
-
getOptionLabel: ({ code, name }) => `${code} / ${name}`,
|
15
|
-
},
|
16
|
-
ActivityLogEntry: {
|
17
|
-
plural: 'activityLog',
|
18
|
-
},
|
19
|
-
User: {
|
20
|
-
primaryKey: 'uid',
|
21
|
-
inputProps: [
|
22
|
-
'firstName',
|
23
|
-
'lastName',
|
24
|
-
'email',
|
25
|
-
'password',
|
26
|
-
'lang',
|
27
|
-
'identifiesAsFemale',
|
28
|
-
'dateOfBirth',
|
29
|
-
'country',
|
30
|
-
'identificationNumber',
|
31
|
-
'mobileNumber',
|
32
|
-
'github',
|
33
|
-
'linkedin',
|
34
|
-
'bio',
|
35
|
-
'role',
|
36
|
-
'signupCohort',
|
37
|
-
'disabled',
|
38
|
-
'referralSource',
|
39
|
-
],
|
40
|
-
searchProps: ['firstName', 'lastName', 'email'],
|
41
|
-
getOptionLabel: ({ firstName, lastName, email }) => `${firstName} ${lastName} (${email})`,
|
42
|
-
properties: {
|
43
|
-
email: {
|
44
|
-
inputType: 'email',
|
45
|
-
},
|
46
|
-
mobileNumber: {
|
47
|
-
inputType: 'phone',
|
48
|
-
},
|
49
|
-
bio: {
|
50
|
-
inputType: 'textarea',
|
51
|
-
},
|
52
|
-
},
|
53
|
-
parse: (props) => {
|
54
|
-
const avatar = (
|
55
|
-
props.github
|
56
|
-
? `https://github.com/${props.github}.png?size=`
|
57
|
-
: `https://www.gravatar.com/avatar/${md5(props.email)}?s=`
|
58
|
-
);
|
59
|
-
return {
|
60
|
-
...props,
|
61
|
-
fullName: `${props.firstName || ''}${props.lastName ? ` ${props.lastName}` : ''}`,
|
62
|
-
avatar: size => `${avatar}${size}`,
|
63
|
-
isStaff: ['staff', 'manager', 'finance', 'admin'].includes(props.role),
|
64
|
-
isManager: ['manager', 'finance', 'admin'].includes(props.role),
|
65
|
-
isFinance: ['finance', 'admin'].includes(props.role),
|
66
|
-
isAdmin: props.role === 'admin',
|
67
|
-
};
|
68
|
-
},
|
69
|
-
},
|
70
|
-
Track: {
|
71
|
-
searchProps: ['name'],
|
72
|
-
},
|
73
|
-
Program: {
|
74
|
-
searchProps: ['name'],
|
75
|
-
},
|
76
|
-
Stage: {
|
77
|
-
searchProps: ['name'],
|
78
|
-
},
|
79
|
-
Cohort: {
|
80
|
-
inputProps: [
|
81
|
-
'program',
|
82
|
-
'stage',
|
83
|
-
'lang',
|
84
|
-
'name',
|
85
|
-
'start',
|
86
|
-
'end',
|
87
|
-
'timeZone',
|
88
|
-
'startTime',
|
89
|
-
'endTime',
|
90
|
-
'vacancies',
|
91
|
-
'admissionStart',
|
92
|
-
'admissionEnd',
|
93
|
-
'placementStart',
|
94
|
-
'admissionCountries',
|
95
|
-
],
|
96
|
-
searchProps: ['name'],
|
97
|
-
getOptionLabel: ({ id, name, stage }) => (
|
98
|
-
`${name}${!stage ? '' : ` - ${stage.name}`} (id: ${id})`
|
99
|
-
),
|
100
|
-
properties: {},
|
101
|
-
// Status:
|
102
|
-
// - `draft`: El cohort todavía no tiene fecha de inicio o fin de admisión.
|
103
|
-
// - `planned`: El cohort ya tiene fechas de inicio y fin de admisión, pero el
|
104
|
-
// período de admisiones todavía no ha comenzado.
|
105
|
-
// - `admission_started`: El periodo de admisión está abierto.
|
106
|
-
// - `admission_ended`: El período de admisión ya terminó, pero todavía no
|
107
|
-
// comienza el bootcamp.
|
108
|
-
// - `started`: El cohort está en período de bootcamp.
|
109
|
-
// - `ended`: El cohort ya terminó su bootcamp.
|
110
|
-
// - `placement_started`: El cohort se encuentra en período de placement (aka
|
111
|
-
// _placement_season_).
|
112
|
-
// - `placement_ended`: El período de placement ya terminó.
|
113
|
-
parse: (props) => {
|
114
|
-
const now = Date.now();
|
115
|
-
|
116
|
-
let status;
|
117
|
-
|
118
|
-
if (props.placementStart) {
|
119
|
-
const placementDuration = props.placementDuration || 270;
|
120
|
-
const placementEnd = new Date(
|
121
|
-
+props.placementStart
|
122
|
-
+ placementDuration * 24 * 60 * 60 * 1000
|
123
|
-
)
|
124
|
-
|
125
|
-
if (placementEnd < now) {
|
126
|
-
status = 'placement_ended';
|
127
|
-
} else if (props.placementStart < now) {
|
128
|
-
status = 'placement_started';
|
129
|
-
}
|
130
|
-
}
|
131
|
-
|
132
|
-
if (!status && props.end < now) {
|
133
|
-
status = 'ended';
|
134
|
-
}
|
135
|
-
|
136
|
-
if (!status && props.start < now) {
|
137
|
-
status = 'started';
|
138
|
-
}
|
139
|
-
|
140
|
-
// NOTA: La fecha de cierre de admisiones se guarda por defecto con la
|
141
|
-
// hora 00:00:00, pero semánticamente en realidad queremos expersar que
|
142
|
-
// las postulaciones están abiertas inclusive ese día, hasta las 23:59:59,
|
143
|
-
// con lo cual sumamos un día a la fecha de cierre para no excluir el
|
144
|
-
// último día.
|
145
|
-
const admissionEnd = (
|
146
|
-
props.admissionEnd
|
147
|
-
? +props.admissionEnd + ONE_DAY
|
148
|
-
: false
|
149
|
-
);
|
150
|
-
if (!status && admissionEnd && admissionEnd < now) {
|
151
|
-
status = 'admission_ended';
|
152
|
-
}
|
153
|
-
|
154
|
-
if (!status && props.admissionStart && props.admissionStart < now) {
|
155
|
-
status = 'admission_started';
|
156
|
-
}
|
157
|
-
|
158
|
-
if (!status && props.admissionStart && props.admissionEnd) {
|
159
|
-
status = 'planned';
|
160
|
-
}
|
161
|
-
|
162
|
-
if (!status) {
|
163
|
-
status = 'draft'
|
164
|
-
}
|
165
|
-
|
166
|
-
const size = (
|
167
|
-
props.start > now && props.vacancies
|
168
|
-
? props.vacancies
|
169
|
-
: props._count?.students || props.students?.length || 0
|
170
|
-
);
|
171
|
-
|
172
|
-
return {
|
173
|
-
...props,
|
174
|
-
status,
|
175
|
-
size,
|
176
|
-
};
|
177
|
-
},
|
178
|
-
},
|
179
|
-
Student: {
|
180
|
-
inputProps: [
|
181
|
-
'cohort',
|
182
|
-
'user',
|
183
|
-
],
|
184
|
-
searchProps: [],
|
185
|
-
},
|
186
|
-
Dropout: {
|
187
|
-
inputProps: [
|
188
|
-
'cohort',
|
189
|
-
'user',
|
190
|
-
'date',
|
191
|
-
'reason',
|
192
|
-
'reasonDetail',
|
193
|
-
'lastProject',
|
194
|
-
'completedProjects',
|
195
|
-
'notes',
|
196
|
-
'staffSad',
|
197
|
-
'covidRelated',
|
198
|
-
],
|
199
|
-
searchProps: [
|
200
|
-
'user.uid',
|
201
|
-
'user.firstName',
|
202
|
-
'user.lastName',
|
203
|
-
'user.email',
|
204
|
-
'cohort.name',
|
205
|
-
],
|
206
|
-
},
|
207
|
-
Contract: {
|
208
|
-
inputProps: [
|
209
|
-
'user',
|
210
|
-
'country',
|
211
|
-
'isEmployment',
|
212
|
-
'feeAmount',
|
213
|
-
'hoursPerWeek',
|
214
|
-
'start',
|
215
|
-
'end',
|
216
|
-
'isTrial',
|
217
|
-
'checkPilot',
|
218
|
-
'source',
|
219
|
-
],
|
220
|
-
searchProps: [
|
221
|
-
'user.firstName',
|
222
|
-
'user.lastName',
|
223
|
-
'user.email',
|
224
|
-
],
|
225
|
-
getOptionLabel: ({ id, user }) => `${user?.firstName} (id: ${id})`,
|
226
|
-
},
|
227
|
-
Gig: {
|
228
|
-
inputProps: [
|
229
|
-
'cohort',
|
230
|
-
'user',
|
231
|
-
'contract',
|
232
|
-
'role',
|
233
|
-
'hoursPerWeek',
|
234
|
-
'start',
|
235
|
-
'end',
|
236
|
-
],
|
237
|
-
},
|
238
|
-
Application: {
|
239
|
-
inputProps: [
|
240
|
-
'user',
|
241
|
-
'cohort',
|
242
|
-
'dateOfBirth',
|
243
|
-
'country',
|
244
|
-
'locality',
|
245
|
-
'nationality',
|
246
|
-
'isAllowedToWork',
|
247
|
-
'hasValidIdDocument',
|
248
|
-
'householdSize',
|
249
|
-
'children',
|
250
|
-
'householdIncome',
|
251
|
-
'racialIdentity',
|
252
|
-
'educationLevel',
|
253
|
-
'schoolType',
|
254
|
-
'educationSubject',
|
255
|
-
'university',
|
256
|
-
'isStudying',
|
257
|
-
'englishLevel',
|
258
|
-
'workStatus',
|
259
|
-
'isLookingForWork',
|
260
|
-
'monthsLookingForWork',
|
261
|
-
'monthsUnemployed',
|
262
|
-
'workRole',
|
263
|
-
'freelance',
|
264
|
-
'workFormal',
|
265
|
-
'workIncome',
|
266
|
-
'isReady',
|
267
|
-
'bypassFilters',
|
268
|
-
],
|
269
|
-
properties: {
|
270
|
-
locality: {
|
271
|
-
isRequired: true,
|
272
|
-
},
|
273
|
-
englishLevel: {
|
274
|
-
isRequired: true,
|
275
|
-
},
|
276
|
-
isReady: {
|
277
|
-
isRequired: false,
|
278
|
-
},
|
279
|
-
bypassFilters: {
|
280
|
-
isRequired: false,
|
281
|
-
},
|
282
|
-
},
|
283
|
-
// Status:
|
284
|
-
// - `active`: Postulación en progreso.
|
285
|
-
// - `rejected`: Postulación rechazada por filtros (ingresos y/o educación).
|
286
|
-
// - `ready`: Retos completados y postulación _enviada_ (confirmada). Llegado a
|
287
|
-
// este estado se considera que la postulación está lista para el siguiente
|
288
|
-
// paso, por ejemplo entrevista.
|
289
|
-
// - `admission_ended`: Período de admisión del cohort seleccionado ya ha
|
290
|
-
// terminado, pero la postulación todavía no ha expirado, así que la postulante
|
291
|
-
// todavía puede continuar cambiando de cohort, siempre y cuando haya uno
|
292
|
-
// abierto dentro del período de validez de 90 días desde la creación de la
|
293
|
-
// postulación.
|
294
|
-
// - `expired`: Se pasaron los 90 días. La postulación ya no puede ser
|
295
|
-
// completada.
|
296
|
-
// - `cancelled`: La postulante canceló su propia postulación. (Todavía no
|
297
|
-
// implementado).
|
298
|
-
parse: (props) => {
|
299
|
-
const hasFailedFilters = (
|
300
|
-
typeof props.hasFailedFilters === 'boolean'
|
301
|
-
? props.hasFailedFilters
|
302
|
-
: typeof props.failedFilters?.length === 'number'
|
303
|
-
? props.failedFilters.length > 0
|
304
|
-
: undefined
|
305
|
-
);
|
306
|
-
|
307
|
-
if (!props.cohort?.admissionEnd || typeof hasFailedFilters === 'undefined') {
|
308
|
-
return props;
|
309
|
-
}
|
310
|
-
|
311
|
-
const now = Date.now();
|
312
|
-
let status;
|
313
|
-
|
314
|
-
if (props.isReady) {
|
315
|
-
status = 'ready';
|
316
|
-
} else if (hasFailedFilters && !props.bypassFilters) {
|
317
|
-
status = 'rejected';
|
318
|
-
} else if (props.createdAt < (now - 90 * ONE_DAY)) {
|
319
|
-
status = 'expired';
|
320
|
-
} else if (props.cohort?.status !== 'admission_started') {
|
321
|
-
status = 'admission_ended';
|
322
|
-
} else {
|
323
|
-
status = 'active';
|
324
|
-
}
|
325
|
-
|
326
|
-
return {
|
327
|
-
...props,
|
328
|
-
status,
|
329
|
-
};
|
330
|
-
},
|
331
|
-
},
|
332
|
-
IscedLevel: {
|
333
|
-
parse: (props) => {
|
334
|
-
const level = Math.floor(props.id / 10);
|
335
|
-
return {
|
336
|
-
...props,
|
337
|
-
level,
|
338
|
-
completed: (level * 10) < props.id,
|
339
|
-
};
|
340
|
-
},
|
341
|
-
},
|
342
|
-
EducationLevel: {
|
343
|
-
searchProps: [
|
344
|
-
'label',
|
345
|
-
],
|
346
|
-
},
|
347
|
-
University: {
|
348
|
-
plural: 'universities',
|
349
|
-
searchProps: ['name'],
|
350
|
-
},
|
351
|
-
Job: {
|
352
|
-
// inputProps: [],
|
353
|
-
// properties: {},
|
354
|
-
},
|
355
|
-
Company: {
|
356
|
-
plural: 'companies',
|
357
|
-
// inputProps: [],
|
358
|
-
// properties: {},
|
359
|
-
},
|
360
|
-
};
|
361
|
-
|
362
|
-
export const createAPI = (url, state) => ({
|
363
|
-
...createModels(url, state, {
|
364
|
-
...schema,
|
365
|
-
definitions: extendSchemaDefinitions(schema, extended),
|
366
|
-
}),
|
367
|
-
gcpLog: {
|
368
|
-
getEntries: async (q) => {
|
369
|
-
const req = createClient(url, state.authUser);
|
370
|
-
return await req(`/gcp-logs?q=${JSON.stringify(q)}`);
|
371
|
-
},
|
372
|
-
},
|
373
|
-
});
|
package/lib/curriculum.js
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
const releasesUrl = 'https://api.github.com/repos/Laboratoria/bootcamp/releases';
|
2
|
-
const rawUrl = 'https://raw.githubusercontent.com/Laboratoria/bootcamp';
|
3
|
-
|
4
|
-
const getLatestVersion = () => fetch(`${releasesUrl}/latest`)
|
5
|
-
.then(resp => resp.json())
|
6
|
-
.then(({ tag_name }) => tag_name);
|
7
|
-
|
8
|
-
const fetchProjects = async tag => (
|
9
|
-
fetch(`${rawUrl}/${tag || await getLatestVersion()}/dist/projects.json`)
|
10
|
-
.then(resp => resp.json())
|
11
|
-
);
|
12
|
-
|
13
|
-
const fetchProject = async (slug, tag) => (
|
14
|
-
fetch(`${rawUrl}/${tag || await getLatestVersion()}/dist/projects/${slug}.json`)
|
15
|
-
.then(resp => resp.json())
|
16
|
-
);
|
17
|
-
|
18
|
-
const fetchTopics = async tag => (
|
19
|
-
fetch(`${rawUrl}/${tag || await getLatestVersion()}/dist/topics.json`)
|
20
|
-
.then(resp => resp.json())
|
21
|
-
);
|
22
|
-
|
23
|
-
const fetchTopic = async (slug, tag) => (
|
24
|
-
fetch(`${rawUrl}/${tag || await getLatestVersion()}/dist/topics/${slug}.json`)
|
25
|
-
.then(resp => resp.json())
|
26
|
-
);
|
27
|
-
|
28
|
-
const fetchLearningObjectives = async tag => (
|
29
|
-
fetch(`${rawUrl}/${tag || await getLatestVersion()}/dist/learning-objectives.json`)
|
30
|
-
.then(resp => resp.json())
|
31
|
-
);
|
32
|
-
|
33
|
-
const filterByLocaleAndTrack = opts => arr => arr.filter((obj) => {
|
34
|
-
if (opts.locale && opts.locale !== obj.locale) {
|
35
|
-
return false;
|
36
|
-
}
|
37
|
-
if (opts.track && opts.track !== obj.track) {
|
38
|
-
return false;
|
39
|
-
}
|
40
|
-
return true;
|
41
|
-
});
|
42
|
-
|
43
|
-
export const createAPI = () => {
|
44
|
-
return {
|
45
|
-
project: {
|
46
|
-
findMany: (opts = {}) => fetchProjects(opts.tag)
|
47
|
-
.then(filterByLocaleAndTrack(opts)),
|
48
|
-
findById: (slug, opts = {}) => fetchProject(slug, opts.tag),
|
49
|
-
},
|
50
|
-
topic: {
|
51
|
-
findMany: (opts = {}) => fetchTopics(opts.tag)
|
52
|
-
.then(filterByLocaleAndTrack(opts)),
|
53
|
-
findById: (slug, opts = {}) => fetchTopic(slug, opts.tag),
|
54
|
-
},
|
55
|
-
learningObjective: {
|
56
|
-
findMany: (opts = {}) => fetchLearningObjectives(opts.tag),
|
57
|
-
},
|
58
|
-
};
|
59
|
-
};
|