Skip to content

Commit 887962c

Browse files
App: Learn
Improved Object Validations with New ValidateObject
1 parent 5f759d6 commit 887962c

10 files changed

+174
-10
lines changed

kolibri/plugins/learn/assets/src/views/AlsoInThis.vue

+23-10
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,11 @@
110110

111111
<script>
112112
113-
import isBoolean from 'lodash/isBoolean';
114113
import TimeDuration from 'kolibri-common/components/TimeDuration';
115114
import useKResponsiveWindow from 'kolibri-design-system/lib/composables/useKResponsiveWindow';
116115
import MissingResourceAlert from 'kolibri-common/components/MissingResourceAlert';
117116
import LearningActivityIcon from 'kolibri-common/components/ResourceDisplayAndSearch/LearningActivityIcon.vue';
117+
import { validateObject } from 'kolibri/utils/objectSpecs';
118118
import useContentNodeProgress from '../composables/useContentNodeProgress';
119119
import useContentLink from '../composables/useContentLink';
120120
import ProgressBar from './ProgressBar';
@@ -148,18 +148,31 @@
148148
type: Array,
149149
required: true,
150150
default: () => [],
151+
/** Content node with the following properties: id, is_leaf, title */
152+
validator: function (nodes) {
153+
return nodes.every(node =>
154+
validateObject(node, {
155+
id: { type: String, required: true },
156+
title: { type: String, required: true },
157+
duration: { type: Number, required: false },
158+
progress: { type: Number, required: false, default: 0 },
159+
is_leaf: { type: Boolean, required: true },
160+
learning_activities: { type: Array, required: false },
161+
}),
162+
);
163+
},
151164
},
152-
/** Content node with the following properties: id, is_leaf, title */
153165
nextFolder: {
154-
type: Object, // or falsy
166+
type: Object,
155167
required: false,
156-
default: () => {},
157-
validator(node) {
158-
if (!node) {
159-
return true;
160-
} // falsy ok
161-
const { id, is_leaf, title } = node;
162-
return id && isBoolean(is_leaf) && title;
168+
default: () => ({}),
169+
validator: function (node) {
170+
if (!node) return true; // falsy values are acceptable
171+
return validateObject(node, {
172+
id: { type: String, required: true },
173+
is_leaf: { type: Boolean, required: true },
174+
title: { type: String, required: true },
175+
});
163176
},
164177
},
165178
isLesson: {

kolibri/plugins/learn/assets/src/views/BrowseResourceMetadata.vue

+20
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@
244244
import LearnerNeeds from 'kolibri-constants/labels/Needs';
245245
import ContentNodeResource from 'kolibri-common/apiResources/ContentNodeResource';
246246
import LearningActivityIcon from 'kolibri-common/components/ResourceDisplayAndSearch/LearningActivityIcon.vue';
247+
import { validateObject } from 'kolibri/utils/objectSpecs';
247248
import useContentLink from '../composables/useContentLink';
248249
import commonLearnStrings from './commonLearnStrings';
249250
import ContentNodeThumbnail from './thumbnails/ContentNodeThumbnail';
@@ -265,6 +266,25 @@
265266
content: {
266267
type: Object,
267268
required: true,
269+
validator(val) {
270+
return validateObject(val, {
271+
id: { type: String, required: true },
272+
title: { type: String, required: true },
273+
description: { type: String, required: false },
274+
duration: { type: Number, required: false },
275+
grade_levels: { type: Array, required: false },
276+
lang: { type: Object, required: false },
277+
accessibility_labels: { type: Array, required: false, default: () => [] },
278+
learner_needs: { type: Array, required: false, default: () => [] },
279+
author: { type: String, required: false },
280+
license_owner: { type: String, required: false },
281+
license_name: { type: String, required: false },
282+
license_description: { type: String, required: false },
283+
ancestors: { type: Array, required: false, default: () => [] },
284+
files: { type: Array, required: false, default: () => [] },
285+
is_leaf: { type: Boolean, required: true },
286+
});
287+
},
268288
},
269289
showLocationsInChannel: {
270290
type: Boolean,

kolibri/plugins/learn/assets/src/views/CardList.vue

+23
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
import camelCase from 'lodash/camelCase';
128128
import useKResponsiveWindow from 'kolibri-design-system/lib/composables/useKResponsiveWindow';
129129
import useChannels from 'kolibri-common/composables/useChannels';
130+
import { validateObject } from 'kolibri/utils/objectSpecs';
130131
import LearningActivityLabel from './LearningActivityLabel';
131132
import LearningActivityDuration from './LearningActivityDuration';
132133
import commonLearnStrings from './commonLearnStrings';
@@ -157,6 +158,28 @@
157158
contentNode: {
158159
type: Object,
159160
required: true,
161+
validator(val) {
162+
return validateObject(val, {
163+
id: { type: String, required: true },
164+
title: { type: String, required: true },
165+
description: { type: String, required: false },
166+
duration: { type: Number, required: false },
167+
grade_levels: { type: Array, required: false },
168+
lang: { type: Object, required: false },
169+
accessibility_labels: { type: Array, required: false, default: () => [] },
170+
learner_needs: { type: Array, required: false, default: () => [] },
171+
author: { type: String, required: false },
172+
license_owner: { type: String, required: false },
173+
license_name: { type: String, required: false },
174+
license_description: { type: String, required: false },
175+
ancestors: { type: Array, required: false, default: () => [] },
176+
files: { type: Array, required: false, default: () => [] },
177+
is_leaf: { type: Boolean, required: true },
178+
copies: { type: Array, required: false, default: () => [] },
179+
channel_id: { type: String, required: false },
180+
categories: { type: Array, required: false, default: () => [] },
181+
});
182+
},
160183
},
161184
to: {
162185
type: Object,

kolibri/plugins/learn/assets/src/views/ChannelCardGroupGrid.vue

+14
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
<script>
2626
2727
import useKResponsiveWindow from 'kolibri-design-system/lib/composables/useKResponsiveWindow';
28+
import { validateObject } from 'kolibri/utils/objectSpecs';
2829
import useCardLayoutSpan from '../composables/useCardLayoutSpan';
2930
import useContentLink from '../composables/useContentLink';
3031
import ChannelCard from './ChannelCard';
@@ -48,6 +49,19 @@
4849
contents: {
4950
type: Array,
5051
required: true,
52+
validator: function (contents) {
53+
return contents.every(content =>
54+
validateObject(content, {
55+
id: { type: String, required: true },
56+
title: { type: String, required: false },
57+
name: { type: String, required: false },
58+
thumbnail: { type: String, required: false },
59+
tagline: { type: String, required: false },
60+
description: { type: String, required: false },
61+
num_coach_contents: { type: Number, required: false },
62+
}),
63+
);
64+
},
5165
},
5266
deviceId: {
5367
type: String,

kolibri/plugins/learn/assets/src/views/CopiesModal.vue

+20
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
<script>
4141
4242
import commonCoreStrings from 'kolibri/uiText/commonCoreStrings';
43+
import { validateObject } from 'kolibri/utils/objectSpecs';
4344
import useContentLink from '../composables/useContentLink';
4445
4546
export default {
@@ -53,6 +54,25 @@
5354
copies: {
5455
type: Array,
5556
required: true,
57+
validator: function (copies) {
58+
return copies.every(copy =>
59+
validateObject(copy, {
60+
id: { type: String, required: true },
61+
title: { type: String, required: true },
62+
ancestors: {
63+
type: Array,
64+
required: true,
65+
validator: function (ancestors) {
66+
return ancestors.every(ancestor =>
67+
validateObject(ancestor, {
68+
title: { type: String, required: true },
69+
}),
70+
);
71+
},
72+
},
73+
}),
74+
);
75+
},
5676
},
5777
},
5878
methods: {

kolibri/plugins/learn/assets/src/views/CurrentlyViewedResourceMetadata.vue

+31
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@
156156
licenseLongName,
157157
licenseDescriptionForConsumer,
158158
} from 'kolibri/uiText/licenses';
159+
import { validateObject } from 'kolibri/utils/objectSpecs';
159160
import commonLearnStrings from './commonLearnStrings';
160161
import ContentNodeThumbnail from './thumbnails/ContentNodeThumbnail';
161162
@@ -176,6 +177,36 @@
176177
content: {
177178
type: Object,
178179
required: true,
180+
validator(val) {
181+
return validateObject(val, {
182+
title: { type: String, required: true },
183+
description: { type: String, required: false },
184+
duration: { type: Number, required: false },
185+
grade_levels: { type: Array, required: false },
186+
lang: {
187+
type: Object,
188+
required: false,
189+
validator: function (lang) {
190+
return validateObject(lang, {
191+
lang_name: { type: String, required: true },
192+
});
193+
},
194+
},
195+
author: {
196+
type: String,
197+
required: false,
198+
},
199+
license_owner: {
200+
type: String,
201+
required: false,
202+
},
203+
files: {
204+
type: Array,
205+
required: false,
206+
default: () => [],
207+
},
208+
});
209+
},
179210
},
180211
},
181212
data() {

kolibri/plugins/learn/assets/src/views/HybridLearningLessonCard.vue

+10
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
4040
import { validateLinkObject } from 'kolibri/utils/validators';
4141
import commonCoreStrings from 'kolibri/uiText/commonCoreStrings';
42+
import { validateObject } from 'kolibri/utils/objectSpecs';
4243
import ProgressBar from './ProgressBar';
4344
import LearningActivityLabel from './LearningActivityLabel';
4445
import commonLearnStrings from './commonLearnStrings';
@@ -56,6 +57,15 @@
5657
content: {
5758
type: Object,
5859
required: true,
60+
validator: function (content) {
61+
return validateObject(content, {
62+
id: { type: String, required: true },
63+
title: { type: String, required: true },
64+
thumbnail: { type: String, required: false },
65+
description: { type: String, required: false },
66+
num_coach_contents: { type: Number, required: false },
67+
});
68+
},
5969
},
6070
link: {
6171
type: Object,

kolibri/plugins/learn/assets/src/views/LibraryAndChannelBrowserMainContent.vue

+11
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
<script>
3434
3535
import useKResponsiveWindow from 'kolibri-design-system/lib/composables/useKResponsiveWindow';
36+
import { validateObject } from 'kolibri/utils/objectSpecs';
3637
import useContentLink from '../composables/useContentLink';
3738
import CardGrid from './cards/CardGrid';
3839
import ResourceCard from './cards/ResourceCard';
@@ -66,6 +67,16 @@
6667
contents: {
6768
type: Array,
6869
required: true,
70+
validator: function (contents) {
71+
return contents.every(content =>
72+
validateObject(content, {
73+
id: { type: String, required: true },
74+
title: { type: String, required: true },
75+
is_leaf: { type: Boolean, required: true },
76+
copies: { type: Array, required: false, default: () => [] },
77+
}),
78+
);
79+
},
6980
},
7081
currentCardViewStyle: {
7182
type: String,

kolibri/plugins/learn/assets/src/views/cards/BaseCard.vue

+2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565

6666
<script>
6767
68+
import { validateLinkObject } from 'kolibri/utils/validators';
6869
import CardLink from './CardLink.vue';
6970
7071
/**
@@ -86,6 +87,7 @@
8687
to: {
8788
type: Object,
8889
required: true,
90+
validator: validateLinkObject,
8991
},
9092
title: {
9193
type: String,

packages/kolibri/components/DownloadButton.vue

+20
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
<script>
2222
2323
import useUser from 'kolibri/composables/useUser';
24+
import { validateObject } from 'kolibri/utils/objectSpecs';
2425
import { getRenderableFiles } from './internal/ContentRenderer/utils';
2526
import { getFilePresetString } from './internal/filePresetStrings';
2627
@@ -37,6 +38,25 @@
3738
files: {
3839
type: Array,
3940
default: () => [],
41+
validator: function (files) {
42+
return files.every(file =>
43+
validateObject(file, {
44+
checksum: { type: String, required: true },
45+
extension: { type: String, required: true },
46+
preset: { type: String, required: true },
47+
lang: {
48+
type: Object,
49+
required: false,
50+
validator: function (lang) {
51+
return validateObject(lang, {
52+
lang_name: { type: String, required: true },
53+
});
54+
},
55+
},
56+
storage_url: { type: String, required: true },
57+
}),
58+
);
59+
},
4060
},
4161
nodeTitle: {
4262
type: String,

0 commit comments

Comments
 (0)