@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 +138 -15
- package/attrs.js +2 -1
- package/package.json +1 -1
- package/toolbox.js +10 -6
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
|
|
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: '
|
|
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: '
|
|
3955
|
+
label: 'Audit duration',
|
|
3842
3956
|
editable: true,
|
|
3843
3957
|
required: true,
|
|
3844
3958
|
instruction:
|
|
3845
|
-
'Time
|
|
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
|
|
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: '
|
|
4004
|
+
label: 'Audit duration',
|
|
3890
4005
|
required: true,
|
|
3891
4006
|
editable: true,
|
|
3892
|
-
instruction:
|
|
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: '
|
|
4030
|
+
label: 'Audit Attribution Influence',
|
|
3915
4031
|
editable: true,
|
|
3916
4032
|
required: true,
|
|
3917
|
-
instruction:
|
|
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
|
|
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:
|
|
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:
|
|
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: '
|
|
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: '
|
|
4006
|
-
instruction: '
|
|
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 =
|
|
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
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]
|