@01-edu/shared 1.1.1 → 1.1.2

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 +53 -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,73 @@ 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
+ const defautlAttrs = getDefaultAttrsEntries(object)
353
+ const filteredDefaultAttrs = defautlAttrs.filter(filterFn)
349
354
 
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)
355
+ processAttributes(filteredDefaultAttrs, object, getUser)
356
+ let prev
357
+ for (const child of Object.values(object.children)) {
358
+ child.parent = object
359
+ prev && (prev.next = child) && (child.prev = prev)
360
+ prev = child
361
+
362
+ const childDefaultAttrs = getDefaultAttrsEntries(child)
363
+ const childRelAttrs = getDefaultRelAttrsEntries(object.type, child.type)
364
+ const [filteredChildAttrs, filteredRelAttrs] = [
365
+ childDefaultAttrs.filter(filterFn),
366
+ childRelAttrs.filter(filterFn),
367
+ ]
368
+
369
+ // apply missing default functions
370
+ // a function can only be missing if it require the user,
371
+ // the event or current time
372
+ processAttributes(filteredChildAttrs, child, getUser)
373
+ processAttributes(filteredRelAttrs, child, getUser)
374
+ partialExpandDynamicAttrs(child, getUser, filterFn)
355
375
  }
376
+ }
356
377
 
378
+ // this function allows us to resolve dynamic attributes
379
+ // by converting them into functions that can be re-evaluated
380
+ // this enables attributes to return updated values when re-checked
381
+ // without requiring additional api queries
382
+ // so the result can be recalculated as needed
383
+ export const expandDynamicAttrs = (object, getUser) => {
384
+ if (!object.children) return (object.children = {})
385
+ const defautlAttrs = getDefaultAttrsEntries(object)
386
+
387
+ processAttributes(defautlAttrs, object, getUser)
357
388
  let prev
358
389
  for (const child of Object.values(object.children)) {
359
390
  child.parent = object
360
391
  prev && (prev.next = child) && (child.prev = prev)
361
392
  prev = child
362
393
 
394
+ const childDefaultAttrs = getDefaultAttrsEntries(child)
395
+ const childRelAttrs = getDefaultRelAttrsEntries(object.type, child.type)
396
+
363
397
  // apply missing default functions
364
398
  // a function can only be missing if it require the user,
365
399
  // 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
- }
400
+ processAttributes(childDefaultAttrs, child, getUser)
401
+ processAttributes(childRelAttrs, child, getUser)
402
+ expandDynamicAttrs(child, getUser)
403
+ }
404
+ }
381
405
 
382
- expandAttrs(child, getUser)
406
+ const processAttributes = (attrEntries, targetObject, getUser) => {
407
+ for (const [key, defs] of attrEntries) {
408
+ if (targetObject.attrs[key] === null) {
409
+ console.warn(
410
+ `value is null for ${targetObject.name} - ${key} - ${targetObject.id}`,
411
+ )
412
+ }
413
+ expandAttr(key, targetObject.attrs, defs, targetObject, getUser)
383
414
  }
384
415
  }
385
416
 
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.2",
4
4
  "type": "module",
5
5
  "description": "",
6
6
  "scripts": {