@01-edu/shared 1.1.1 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/attrs-defs.js +68 -2
  2. package/attrs.js +57 -22
  3. package/package.json +1 -1
package/attrs-defs.js CHANGED
@@ -63,7 +63,7 @@ const firstOfGroup = (a, _i, children) => {
63
63
  }
64
64
 
65
65
  const getObjectPath = object => {
66
- const core = getCoreOfSattelite(object)
66
+ const [core] = getCoreOfSattelite(object) || []
67
67
  if (!core) return object.name
68
68
  // special case only for projects with a core requirement set
69
69
  // const coreName = getCoreName(object)
@@ -919,7 +919,7 @@ relationAttrs.difficultyMod = {
919
919
 
920
920
  const getName = ({ name }) => name
921
921
  const getProjectName = object => {
922
- const core = getCoreOfSattelite(object)
922
+ const [core] = getCoreOfSattelite(object) || []
923
923
  if (!core) return object.name
924
924
  // only for projects with a core, and which name starts by the core name:
925
925
  // remove the core name from the name to avoid repetition
@@ -4114,6 +4114,72 @@ relationAttrs.week = {
4114
4114
  },
4115
4115
  }
4116
4116
 
4117
+ const checkRaidLimitation = ({ object, value }) => {
4118
+ const raids = Object.values(object.parent.children).filter(
4119
+ ({ type, key }) => key !== object.key && type === 'raid',
4120
+ )
4121
+ for (const { attrs } of raids) {
4122
+ if (attrs.branch === value) {
4123
+ throw Error('Raids should have their unique branch')
4124
+ }
4125
+ }
4126
+ }
4127
+ const checkBranchLimitation = ({ object, value, limit = 9 }) => {
4128
+ const contentInBranch = Object.values(object.parent.children).filter(
4129
+ ({ key, attrs }) => key !== object.key && attrs.branch === value,
4130
+ )
4131
+ // + 1 for the current branch being added
4132
+ if (contentInBranch.length + 1 > limit) {
4133
+ throw Error(`The limit of content in a branch is ${limit}`)
4134
+ }
4135
+ }
4136
+
4137
+ const sharedBranchOptions = {
4138
+ label: 'Base Branch',
4139
+ instruction: 'From 1 to 4',
4140
+ description: 'Changing branch can disrupt the piscine timeline.',
4141
+ required: true,
4142
+ editable: true,
4143
+ }
4144
+
4145
+ const getBranchOptions = (object, limit = 9) => {
4146
+ const branchCounts = {}
4147
+ for (const child of Object.values(object.parent.children || {})) {
4148
+ const branch = child.attrs.branch
4149
+ branchCounts[branch] = (branchCounts[branch] || 0) + 1
4150
+ }
4151
+ const allBranches = [1, 2, 3, 4]
4152
+ return allBranches.filter(branch => (branchCounts[branch] || 0) < limit)
4153
+ }
4154
+
4155
+ const sharedBranch = Literal(1, {
4156
+ ...sharedBranchOptions,
4157
+ options: getBranchOptions,
4158
+ check: (value, object) => {
4159
+ checkNumberInBetween(value, 1, 4)
4160
+ checkBranchLimitation({ object, value })
4161
+ },
4162
+ })
4163
+
4164
+ const raidSharedBranch = Literal(1, {
4165
+ ...sharedBranchOptions,
4166
+ options: [1, 2, 3, 4],
4167
+ check: (value, object) => {
4168
+ checkNumberInBetween(value, 1, 4)
4169
+ checkRaidLimitation({ object, value })
4170
+ checkBranchLimitation({ object, value })
4171
+ },
4172
+ })
4173
+ relationAttrs.branch = {
4174
+ piscine: {
4175
+ quest: sharedBranch,
4176
+ project: sharedBranch,
4177
+ raid: raidSharedBranch,
4178
+ sharedBranch,
4179
+ exam: sharedBranch,
4180
+ },
4181
+ }
4182
+
4117
4183
  const sharedZeroXpIndex = Literal(0, {
4118
4184
  required: true,
4119
4185
  private: true,
package/attrs.js CHANGED
@@ -344,42 +344,77 @@ const expandAttr = (key, value, defs, object, getUser) => {
344
344
  }
345
345
  }
346
346
 
347
- export const expandAttrs = (object, getUser) => {
347
+ // same as the `expandDynamicAttrs` this function would resolve dynamic attributes
348
+ // the special use of this function is that we can resolve certain attributes
349
+ // by providing a filter function
350
+ export const partialExpandDynamicAttrs = (object, getUser, filterFn) => {
348
351
  if (!object.children) return (object.children = {})
352
+ if (!Object.keys(object.children).length) return
349
353
 
350
- for (const [key, defs] of getDefaultAttrsEntries(object)) {
351
- if (object.attrs[key] === null) {
352
- console.warn(`value is null for ${object.name} - ${key} - ${object.id}`)
353
- }
354
- expandAttr(key, object.attrs, defs, object, getUser)
354
+ const defautlAttrs = getDefaultAttrsEntries(object)
355
+ const filteredDefaultAttrs = defautlAttrs.filter(filterFn)
356
+
357
+ processAttributes(filteredDefaultAttrs, object, getUser)
358
+ let prev
359
+ for (const child of Object.values(object.children)) {
360
+ child.parent = object
361
+ prev && (prev.next = child) && (child.prev = prev)
362
+ prev = child
363
+
364
+ const childDefaultAttrs = getDefaultAttrsEntries(child)
365
+ const childRelAttrs = getDefaultRelAttrsEntries(object.type, child.type)
366
+ const [filteredChildAttrs, filteredRelAttrs] = [
367
+ childDefaultAttrs.filter(filterFn),
368
+ childRelAttrs.filter(filterFn),
369
+ ]
370
+
371
+ // apply missing default functions
372
+ // a function can only be missing if it require the user,
373
+ // the event or current time
374
+ processAttributes(filteredChildAttrs, child, getUser)
375
+ processAttributes(filteredRelAttrs, child, getUser)
376
+ partialExpandDynamicAttrs(child, getUser, filterFn)
355
377
  }
378
+ }
356
379
 
380
+ // this function allows us to resolve dynamic attributes
381
+ // by converting them into functions that can be re-evaluated
382
+ // this enables attributes to return updated values when re-checked
383
+ // without requiring additional api queries
384
+ // so the result can be recalculated as needed
385
+ export const expandDynamicAttrs = (object, getUser) => {
386
+ if (!object.children) return (object.children = {})
387
+ if (!Object.keys(object.children).length) return
388
+
389
+ const defautlAttrs = getDefaultAttrsEntries(object)
390
+
391
+ processAttributes(defautlAttrs, object, getUser)
357
392
  let prev
358
393
  for (const child of Object.values(object.children)) {
359
394
  child.parent = object
360
395
  prev && (prev.next = child) && (child.prev = prev)
361
396
  prev = child
362
397
 
398
+ const childDefaultAttrs = getDefaultAttrsEntries(child)
399
+ const childRelAttrs = getDefaultRelAttrsEntries(object.type, child.type)
400
+
363
401
  // apply missing default functions
364
402
  // a function can only be missing if it require the user,
365
403
  // the event or current time
366
- for (const [key, defs] of getDefaultAttrsEntries(child)) {
367
- if (child.attrs[key] === null) {
368
- console.warn(`value is null for ${child.name} - ${key} - ${child.id}`)
369
- }
370
- expandAttr(key, child.attrs, defs, child, getUser)
371
- }
372
- for (const [key, defs] of getDefaultRelAttrsEntries(
373
- object.type,
374
- child.type,
375
- )) {
376
- if (child.attrs[key] === null) {
377
- console.warn(`value is null for ${child.name} - ${key} - ${child.id}`)
378
- }
379
- expandAttr(key, child.attrs, defs, child, getUser)
380
- }
404
+ processAttributes(childDefaultAttrs, child, getUser)
405
+ processAttributes(childRelAttrs, child, getUser)
406
+ expandDynamicAttrs(child, getUser)
407
+ }
408
+ }
381
409
 
382
- expandAttrs(child, getUser)
410
+ const processAttributes = (attrEntries, targetObject, getUser) => {
411
+ for (const [key, defs] of attrEntries) {
412
+ if (targetObject.attrs[key] === null) {
413
+ console.warn(
414
+ `value is null for ${targetObject.name} - ${key} - ${targetObject.id}`,
415
+ )
416
+ }
417
+ expandAttr(key, targetObject.attrs, defs, targetObject, getUser)
383
418
  }
384
419
  }
385
420
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@01-edu/shared",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "type": "module",
5
5
  "description": "",
6
6
  "scripts": {