@01-edu/shared 1.2.2 → 1.2.4

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.
package/attrs-defs.js CHANGED
@@ -2665,11 +2665,122 @@ const sharedRanksDefinitions = {
2665
2665
  }
2666
2666
  },
2667
2667
  }
2668
+
2669
+ types.relatesToContent = Literal('', {
2670
+ label: 'Content',
2671
+ instruction:
2672
+ 'Select a child object to link this learning path status to. Each child can only be linked once.',
2673
+ editable: true,
2674
+ restrictive: true,
2675
+ options: (object, value) => {
2676
+ const learnPathStatus = object.attrs?.learnPathStatus
2677
+ ?.flatMap(({ relatesTo }) => relatesTo)
2678
+ .filter(v => v !== value)
2679
+
2680
+ const options = object.children ? Object.keys(object.children) : []
2681
+ return !learnPathStatus
2682
+ ? options
2683
+ : options.filter(k => !learnPathStatus.includes(k))
2684
+ },
2685
+ })
2686
+
2687
+ types.relatesToArray = TypeObject({
2688
+ label: 'Relates to',
2689
+ instruction:
2690
+ 'Link one or more child objects to this learning path status. You can add multiple links by clicking the add button. If student did at least one he will have that status',
2691
+ editable: true,
2692
+ required: true,
2693
+ restrictive: true,
2694
+ value: (...args) => [
2695
+ mapValues(types.relatesToArray.type, subDef =>
2696
+ getDefaultValue(subDef, ...args),
2697
+ ),
2698
+ ],
2699
+ type: [types.relatesToContent],
2700
+ })
2701
+
2702
+ types.learnerPathStatusName = Literal('', {
2703
+ label: 'Name',
2704
+ editable: true,
2705
+ required: true,
2706
+ primary: true,
2707
+ })
2708
+ types.definitionRelatesTo = TypeObject({
2709
+ label: 'Status Definition',
2710
+ type: {
2711
+ name: types.learnerPathStatusName,
2712
+ milestone: Literal('', {
2713
+ label: 'Hover description',
2714
+ instruction:
2715
+ 'Text that appears when users hover over this item. Use this to provide additional context or helpful information.',
2716
+ editable: true,
2717
+ }),
2718
+ relatesTo: types.relatesToArray,
2719
+ },
2720
+ check: (value, object) => {
2721
+ const { relatesTo: currentRelatesTo, name } = value
2722
+ const { learnPathStatus } = object.attrs
2723
+ const previousValue = learnPathStatus.find(
2724
+ ({ relatesTo }) =>
2725
+ !(
2726
+ currentRelatesTo.length !== relatesTo.length ||
2727
+ currentRelatesTo.some((val, i) => val !== relatesTo[i])
2728
+ ),
2729
+ )
2730
+ if (!previousValue) return
2731
+
2732
+ const isDifferent =
2733
+ previousValue.relatesTo.length !== currentRelatesTo.length ||
2734
+ previousValue.relatesTo.some((val, i) => val !== currentRelatesTo[i])
2735
+
2736
+ const hasSameKey = previousValue.name === name
2737
+ if (!isDifferent && hasSameKey) return
2738
+
2739
+ const definitionsWithSameName = object.attrs.learnPathStatus?.find(
2740
+ v => v.name === name,
2741
+ )
2742
+ if (definitionsWithSameName) {
2743
+ throw Error(
2744
+ `Name "${name}" is already set for a learner path status! A given name can only be attributed once.`,
2745
+ )
2746
+ }
2747
+ },
2748
+ })
2749
+
2750
+ const learnPathStatus = {
2751
+ label: 'Learner Path Status',
2752
+ instruction: 'List of Learner Status During Campus Steps',
2753
+ editable: true,
2754
+ restrictive: true,
2755
+ value: (...args) => [
2756
+ mapValues(types.learnPathStatus.type, subDef =>
2757
+ getDefaultValue(subDef, ...args),
2758
+ ),
2759
+ ],
2760
+ type: [types.definitionRelatesTo],
2761
+ check: (definition, object) => {
2762
+ if (!object.childrenRelation.length) {
2763
+ throw Error('Must contain at least one relation')
2764
+ }
2765
+ if (!definition?.length || !Array.isArray(definition)) {
2766
+ throw Error('Must be a non empty array')
2767
+ }
2768
+ },
2769
+ }
2770
+
2668
2771
  attrs.ranksDefinitions = {
2669
2772
  module: sharedRanksDefinitions,
2670
2773
  piscine: sharedRanksDefinitions,
2671
2774
  }
2672
2775
 
2776
+ attrs.learnPathStatus = {
2777
+ // the learn path status will define what the student is during the steps
2778
+ // - applicant (user that registered to the platform and passed the onboarding steps, up until being accepted to participate on the selection piscine/program)
2779
+ // - candidate (user that is participating on the selection piscine)
2780
+ // - learner (user that succeeded on the selection piscine and is participating on the module event)
2781
+ campus: learnPathStatus,
2782
+ }
2783
+
2673
2784
  const sharedRegistrationDuration = {
2674
2785
  label: 'Registration duration (to an event)',
2675
2786
  required: true,
@@ -3742,13 +3853,16 @@ types.adminSelectionValidation = TypeObject({
3742
3853
  options: ['admin_selection'],
3743
3854
  }),
3744
3855
  },
3745
- label: 'Admin selection evaluation',
3856
+ label: 'Admin selection',
3857
+ description: 'Admins manually select which submissions move forward.',
3746
3858
  })
3747
3859
 
3748
3860
  const getTesterImage = ({ attrs }) =>
3749
3861
  attrs.language && `ghcr.io/01-edu/test-${attrs.language}`
3750
3862
  types.testerValidation = TypeObject({
3751
- label: 'Tester evaluation',
3863
+ label: 'Automatic testing',
3864
+ description:
3865
+ 'The solution submitted by the user will be automatically tested and a result will immediately be available.',
3752
3866
  type: {
3753
3867
  type: Literal('tester', {
3754
3868
  required: true,
@@ -3838,11 +3952,11 @@ const sharedTypesForm = {
3838
3952
  ...Functions({ 'README in audit folder': getAuditPath }),
3839
3953
  }
3840
3954
  types.adminAuditValidationDelay = Literal(0, {
3841
- label: 'Delay',
3955
+ label: 'Audit duration',
3842
3956
  editable: true,
3843
3957
  required: true,
3844
3958
  instruction:
3845
- 'Time allowed to complete the audit before it expires. "0s" equals no delay.', // TODO: convert to MS'
3959
+ 'Time that the admins have to complete an audit before it expires', // TODO: convert to MS
3846
3960
  })
3847
3961
  types.adminAuditValidationRequired = Literal(1, {
3848
3962
  label: 'Number required',
@@ -3862,7 +3976,8 @@ types.adminAuditValidationRatio = Literal(1, {
3862
3976
  })
3863
3977
 
3864
3978
  types.adminAuditValidation = TypeObject({
3865
- label: 'Admin audit evaluation',
3979
+ label: 'Admin audit',
3980
+ description: 'Only admins can evaluate this content.',
3866
3981
  type: {
3867
3982
  type: Literal('admin_audit', {
3868
3983
  required: true,
@@ -3886,10 +4001,11 @@ types.adminAuditValidation = TypeObject({
3886
4001
  })
3887
4002
 
3888
4003
  types.userAuditValidationDelay = Literal((2 * WEEK) / MIN, {
3889
- label: 'Delay',
4004
+ label: 'Audit duration',
3890
4005
  required: true,
3891
4006
  editable: true,
3892
- instruction: 'Time allowed to complete the audit before it expires', // TODO: convert to MS
4007
+ instruction:
4008
+ 'Time that the users have to complete an audit before it expires', // TODO: convert to MS
3893
4009
  })
3894
4010
  types.userAuditValidationRequired = Literal(5, {
3895
4011
  label: 'Number required',
@@ -3911,10 +4027,11 @@ types.userAuditValidationRatio = Literal(2, {
3911
4027
  })
3912
4028
 
3913
4029
  types.matchInfluence = TypeObject({
3914
- label: 'Match Algorithm Influence',
4030
+ label: 'Audit Attribution Influence',
3915
4031
  editable: true,
3916
4032
  required: true,
3917
- instruction: 'Adjust weights in the Match algorithm',
4033
+ instruction:
4034
+ 'Adjust the weights in the match algorithm to influence how audits are attributed',
3918
4035
  type: {
3919
4036
  auditsRatio: Literal(2.0, {
3920
4037
  label: 'Current Audit Ratio',
@@ -3940,7 +4057,9 @@ types.matchInfluence = TypeObject({
3940
4057
  })
3941
4058
 
3942
4059
  types.userAuditValidation = TypeObject({
3943
- label: 'User audit evaluation',
4060
+ label: 'User audit',
4061
+ description:
4062
+ 'Users will be assigned as auditors to peer-review the project submission. You can customise the rules of audit attribution and requirements for the group to succeed.',
3944
4063
  type: {
3945
4064
  type: Literal('user_audit', {
3946
4065
  required: true,
@@ -3967,19 +4086,23 @@ types.userAuditValidation = TypeObject({
3967
4086
  editable: true,
3968
4087
  type: 'array',
3969
4088
  label: 'Pre questions',
3970
- instruction: 'List of questions that appears before the main audit',
4089
+ instruction:
4090
+ 'Define a set of questions that appear before the main audit. Go to “edit & preview” mode to visualize the question content',
3971
4091
  },
3972
4092
  postQuestions: {
3973
4093
  editable: true,
3974
4094
  type: 'array',
3975
4095
  label: 'Post questions',
3976
- instruction: 'List of questions that appears after the main audit',
4096
+ instruction:
4097
+ 'Define a set of questions that appear after the main audit. Go to “edit & preview” mode to visualize the question content',
3977
4098
  },
3978
4099
  },
3979
4100
  })
3980
4101
 
3981
4102
  types.raidAuditorValidation = TypeObject({
3982
- label: 'User audit evaluation (dedicated for event)',
4103
+ label: 'Dedicated auditors for event',
4104
+ description:
4105
+ 'Define a list of users that will audit the content. This list is created on each event related to this content, and needs to be available before the event ends.',
3983
4106
  type: {
3984
4107
  type: Literal('dedicated_auditors_for_event', {
3985
4108
  required: true,
@@ -4002,8 +4125,8 @@ types.raidAuditorValidation = TypeObject({
4002
4125
  })
4003
4126
 
4004
4127
  const sharedValidations = {
4005
- label: 'Evaluated by',
4006
- instruction: 'List of evaluations to complete in order',
4128
+ label: 'Evaluations required',
4129
+ instruction: 'Define the evaluation methods for this content',
4007
4130
  check: value => {
4008
4131
  if (!value.length) throw Error('must have at least one element')
4009
4132
  },
package/attrs.js CHANGED
@@ -37,7 +37,8 @@ const typeChecker = (defs, value, object, key) => {
37
37
  check?.(value, object, key)
38
38
 
39
39
  if (options) {
40
- const opts = typeof options === 'function' ? options(object) : options
40
+ const opts =
41
+ typeof options === 'function' ? options(object, value) : options
41
42
  if (opts.length === 1) {
42
43
  if (opts[0] !== value) {
43
44
  throw Error(`${key} must be ${opts[0]} but was ${value}`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@01-edu/shared",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "type": "module",
5
5
  "description": "",
6
6
  "scripts": {
package/toolbox.js CHANGED
@@ -64,12 +64,6 @@ export const handleKeyDownEvent = args => {
64
64
  }
65
65
  }
66
66
 
67
- export const swap = (arr, i, j) => {
68
- const newArr = [...arr] // don’t mutate the original
69
- ;[newArr[i], newArr[j]] = [newArr[j], newArr[i]]
70
- return newArr
71
- }
72
-
73
67
  export const last = array => array[array.length - 1]
74
68
 
75
69
  export const upperFirst = str =>
@@ -215,6 +209,16 @@ export const toDateFormatWithTime = (d, separator = 'T') => {
215
209
 
216
210
  return `${toDateFormat(date)}${separator}${hh}:${mm}`
217
211
  }
212
+
213
+ export const toPermanentDateFormatWithTime = (d, separator = 'T') => {
214
+ const date = toDate(d)
215
+ const hh = String(date.getHours()).padStart(2, '0')
216
+ const mm = String(date.getMinutes()).padStart(2, '0')
217
+ const month = (date.getMonth() + 1).toString().padStart(2, '0')
218
+ const day = date.getDate().toString().padStart(2, '0')
219
+
220
+ return `${date.getFullYear()}-${month}-${day}${separator}${hh}:${mm}`
221
+ }
218
222
  export const displayDateTime = dateTime => toDateFormatWithTime(dateTime, ' | ')
219
223
 
220
224
  export const getMonthName = month => monthNames[month]