@opensalt/ob3-definer 1.0.0

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 (45) hide show
  1. package/.vscode/extensions.json +3 -0
  2. package/LICENSE +21 -0
  3. package/README.md +86 -0
  4. package/dist/favicon.svg +7 -0
  5. package/dist/index.html +20 -0
  6. package/dist/ob3-definer.css +1 -0
  7. package/dist/ob3-definer.js +32 -0
  8. package/formkit.config.js +27 -0
  9. package/index.html +19 -0
  10. package/jsconfig.json +8 -0
  11. package/package.json +35 -0
  12. package/public/favicon.svg +7 -0
  13. package/src/App.vue +19 -0
  14. package/src/assets/base.css +86 -0
  15. package/src/assets/main.css +24 -0
  16. package/src/assets/style.scss +33 -0
  17. package/src/components/AchievementCriteria.vue +78 -0
  18. package/src/components/AchievementDefiner.vue +212 -0
  19. package/src/components/AchievementImage.vue +116 -0
  20. package/src/components/AchievementType.vue +111 -0
  21. package/src/components/AdditionalTab.vue +32 -0
  22. package/src/components/AddressComponent.vue +118 -0
  23. package/src/components/AlignmentComponent.vue +141 -0
  24. package/src/components/AlignmentsComponent.vue +13 -0
  25. package/src/components/AlignmentsTab.vue +18 -0
  26. package/src/components/BasicTab.vue +55 -0
  27. package/src/components/CreatorProfile.vue +166 -0
  28. package/src/components/CriterionLevels.vue +97 -0
  29. package/src/components/DetailTab.vue +72 -0
  30. package/src/components/IndividualName.vue +63 -0
  31. package/src/components/MarkdownRenderer.vue +20 -0
  32. package/src/components/OtherIdentifiers.vue +116 -0
  33. package/src/components/RelatedList.vue +89 -0
  34. package/src/components/ResultDescription.vue +120 -0
  35. package/src/components/ResultType.vue +94 -0
  36. package/src/components/TagList.vue +121 -0
  37. package/src/components/ValueList.vue +144 -0
  38. package/src/inputs/innerLabelTextInput.js +62 -0
  39. package/src/inputs/innerLabelTextareaInput.js +57 -0
  40. package/src/inputs/selectInputGroup.js +76 -0
  41. package/src/main.js +50 -0
  42. package/src/stores/credential.js +292 -0
  43. package/test-index.html +17 -0
  44. package/trial-key +3 -0
  45. package/vite.config.js +39 -0
@@ -0,0 +1,111 @@
1
+ <script setup>
2
+ import {onMounted, ref, watch} from "vue";
3
+
4
+ const model = defineModel({ default: ''});
5
+ const achievementType = ref('');
6
+ const typeExt = ref('');
7
+
8
+ onMounted(() => {
9
+ if (model.value && model.value.substring(0, 4) === 'ext:') {
10
+ achievementType.value = 'other';
11
+ typeExt.value = model.value.substring(4);
12
+
13
+ return;
14
+ }
15
+
16
+ achievementType.value = model.value ? model.value : '';
17
+ typeExt.value = '';
18
+ });
19
+
20
+ watch(achievementType, (value) => {
21
+ if (value === 'other') {
22
+ model.value = 'ext:'+typeExt.value;
23
+
24
+ return;
25
+ }
26
+
27
+ model.value = value;
28
+ });
29
+
30
+ watch(typeExt, (value) => {
31
+ if (achievementType.value === 'other') {
32
+ model.value = 'ext:'+value;
33
+
34
+ return;
35
+ }
36
+
37
+ model.value = achievementType.value;
38
+ });
39
+ </script>
40
+
41
+ <template>
42
+ <FormKit
43
+ type="select"
44
+ label="Credential Type"
45
+ v-model="achievementType"
46
+ name="achievementType"
47
+ input-class="$reset formkit-input form-select"
48
+ inner-class=""
49
+ placeholder="Select the Credential Type"
50
+ help="The type of the credential"
51
+ :options="{
52
+ '': 'Select the Credential Type',
53
+ 'Achievement': 'Achievement',
54
+ 'ApprenticeshipCertificate': 'Apprenticeship Certificate',
55
+ 'Assessment': 'Assessment',
56
+ 'Assignment': 'Assignment',
57
+ 'AssociateDegree': 'Associate Degree',
58
+ 'Award': 'Award',
59
+ 'Badge': 'Badge',
60
+ 'BachelorDegree': 'Bachelor Degree',
61
+ 'Certificate': 'Certificate',
62
+ 'CertificateOfCompletion': 'Certificate Of Completion',
63
+ 'Certification': 'Certification',
64
+ 'CommunityService': 'Community Service',
65
+ 'Competency': 'Competency',
66
+ 'Course': 'Course',
67
+ 'CoCurricular': 'Co-Curricular',
68
+ 'Degree': 'Degree',
69
+ 'Diploma': 'Diploma',
70
+ 'DoctoralDegree': 'Doctoral Degree',
71
+ 'Fieldwork': 'Fieldwork',
72
+ 'GeneralEducationDevelopment': 'General Education Development',
73
+ 'JourneymanCertificate': 'Journeyman Certificate',
74
+ 'LearningProgram': 'Learning Program',
75
+ 'License': 'License',
76
+ 'Membership': 'Membership',
77
+ 'ProfessionalDoctorate': 'Professional Doctorate',
78
+ 'QualityAssuranceCredential': 'Quality Assurance Credential',
79
+ 'MasterCertificate': 'Master Certificate',
80
+ 'MasterDegree': 'Master Degree',
81
+ 'MicroCredential': 'Micro Credential',
82
+ 'ResearchDoctorate': 'Research Doctorate',
83
+ 'SecondarySchoolDiploma': 'Secondary School Diploma',
84
+ 'other': 'Other (ext:)',
85
+ }"
86
+ />
87
+ <FormKit
88
+ v-if="achievementType === 'other'"
89
+ type="innerLabelTextInput"
90
+ label="Extended Type"
91
+ v-model="typeExt"
92
+ name="typeExt"
93
+ aria-label="Extended Alignment Type"
94
+ inner-class="input-group ms-3 me-5 pe-3"
95
+ outer-class="$reset"
96
+ label-class="visually-hidden"
97
+ before="ext:"
98
+ :validation="[['matches', '/^[a-z|A-Z|0-9|.|-|_]+$/'], ['required']]"
99
+ help="Extended value for Credential Type"
100
+ >
101
+ <template #prefix>
102
+ <span class="input-group-text" aria-label="ext:">ext:</span>
103
+ </template>
104
+ </FormKit>
105
+ </template>
106
+
107
+ <style scoped>
108
+ [data-placeholder="true"] {
109
+ color: #999;
110
+ }
111
+ </style>
@@ -0,0 +1,32 @@
1
+ <script setup>
2
+ import TagList from "@/components/TagList.vue";
3
+ import RelatedList from "@/components/RelatedList.vue";
4
+ import OtherIdentifiers from "@/components/OtherIdentifiers.vue";
5
+ import CreatorProfile from "@/components/CreatorProfile.vue";
6
+
7
+ const model = defineModel({ default: {} });
8
+ </script>
9
+
10
+ <template>
11
+ <div class="tab-pane fade show active" id="tab-additional" role="tabpanel" aria-labelledby="additional-tab">
12
+ <FormKit
13
+ type="text"
14
+ name="id"
15
+ label="ID"
16
+ v-model="model.id"
17
+ help="Unique URI for the Achievement."
18
+ />
19
+
20
+ <TagList v-model="model.tag"/>
21
+
22
+ <RelatedList v-model="model.related" />
23
+
24
+ <OtherIdentifiers v-model="model.otherIdentifier"/>
25
+
26
+ <CreatorProfile v-model="model.creator" />
27
+ </div>
28
+ </template>
29
+
30
+ <style scoped>
31
+
32
+ </style>
@@ -0,0 +1,118 @@
1
+ <script setup>
2
+ import {onBeforeMount, ref} from "vue";
3
+
4
+ const model = defineModel({ default: {} });
5
+ const show = ref(false);
6
+
7
+ onBeforeMount(() => {
8
+ if (Object.keys(model).length > 0) {
9
+ show.value = true;
10
+ }
11
+ });
12
+ </script>
13
+
14
+ <template>
15
+ <FormKit
16
+ type="group"
17
+ name="address"
18
+ v-model="model"
19
+ >
20
+ <FormKit
21
+ type="checkbox"
22
+ label="Include address"
23
+ v-model="show"
24
+ wrapper-class="form-check form-switch"
25
+ input-class="$reset form-check-input"
26
+ label-class="$reset form-check-label"
27
+ role="switch"
28
+ ignore="true"
29
+ />
30
+
31
+ <div v-show="show">
32
+ <FormKit
33
+ type="hidden"
34
+ name="type"
35
+ :value="[ 'Address' ]"
36
+ />
37
+
38
+ <FormKit
39
+ type="text"
40
+ label="Street Address"
41
+ name="streetAddress"
42
+ help="Street address of the creator."
43
+ />
44
+
45
+ <FormKit
46
+ type="text"
47
+ label="Post Office Box Number"
48
+ name="postOfficeBoxNumber"
49
+ help="A post office box number for PO box addresses."
50
+ />
51
+
52
+ <FormKit
53
+ type="text"
54
+ label="City"
55
+ name="addressLocality"
56
+ help="A locality within the region."
57
+ />
58
+
59
+ <FormKit
60
+ type="text"
61
+ label="State"
62
+ name="addressRegion"
63
+ help="The region within the country."
64
+ />
65
+
66
+ <FormKit
67
+ type="text"
68
+ label="Postal Code"
69
+ name="postalCode"
70
+ help="A postal code."
71
+ />
72
+
73
+ <FormKit
74
+ type="text"
75
+ label="Country"
76
+ name="addressCountry"
77
+ help="Country name."
78
+ />
79
+
80
+ <FormKit
81
+ type="text"
82
+ label="Country Code"
83
+ name="addressCountryCode"
84
+ help="Country code. The value must be a ISO 3166-1 alpha-2 country code, such as 'US'."
85
+ />
86
+
87
+ <FormKit
88
+ type="group"
89
+ label="Geo"
90
+ name="geo"
91
+ v-if="false"
92
+ >
93
+ <FormKit
94
+ type="hidden"
95
+ name="type"
96
+ :value="'GeoCoordinates'"
97
+ />
98
+
99
+ <FormKit
100
+ type="text"
101
+ label="Latitude"
102
+ name="latitude"
103
+ help="The latitude of the geographic point."
104
+ />
105
+ <FormKit
106
+ type="text"
107
+ label="Longitude"
108
+ name="longitude"
109
+ help="The longitude of the geographic point."
110
+ />
111
+ </FormKit>
112
+ </div>
113
+ </FormKit>
114
+ </template>
115
+
116
+ <style scoped>
117
+
118
+ </style>
@@ -0,0 +1,141 @@
1
+ <script setup>
2
+ const alignment = defineModel({ default: {} });
3
+ </script>
4
+
5
+ <template>
6
+ <FormKit
7
+ #default="{ items, node, value }"
8
+ type="list"
9
+ v-model="alignment"
10
+ name="alignment"
11
+ dynamic
12
+ >
13
+ <h5>Alignments
14
+ <button type="button" @click="() => node.input(value.concat({}))" class="btn btn-sm btn-primary ms-3">
15
+ Add Alignment
16
+ </button>
17
+ </h5>
18
+
19
+ <FormKit
20
+ type="group"
21
+ wrapper-class="card"
22
+ v-for="(item, index) in items"
23
+ :key="item"
24
+ :index="index"
25
+ >
26
+ <div class="card mb-3">
27
+ <h5 class="card-header">Target {{index+1}}
28
+ <button type="button" @click="() => node.input(value.filter((_, i) => i !== index))" class="btn btn-secondary btn-sm float-end">
29
+ Remove
30
+ </button>
31
+ </h5>
32
+
33
+ <div class="card-body pb-0">
34
+ <FormKit
35
+ type="hidden"
36
+ name="type"
37
+ :value="[ 'Alignment' ]"
38
+ />
39
+
40
+ <FormKit
41
+ type="innerLabelTextInput"
42
+ label="Name"
43
+ name="targetName"
44
+ inner-class="input-group"
45
+ label-class="input-group-text"
46
+ wrapper-class="required"
47
+ validation="required:trim"
48
+ help="Name of the alignment."
49
+ />
50
+
51
+ <FormKit
52
+ type="innerLabelTextInput"
53
+ label="URL"
54
+ name="targetUrl"
55
+ inner-class="input-group"
56
+ label-class="input-group-text"
57
+ wrapper-class="required"
58
+ validation="required:trim|url"
59
+ help="URL linking to the official description of the alignment target, for example an individual standard within an educatinoal framework."
60
+ />
61
+
62
+ <FormKit
63
+ type="innerLabelTextInput"
64
+ label="Framework"
65
+ name="targetFramework"
66
+ inner-class="input-group"
67
+ label-class="input-group-text"
68
+ help="Name of the framework for the alignment target."
69
+ />
70
+
71
+ <FormKit
72
+ type="innerLabelTextareaInput"
73
+ label="Description"
74
+ name="description"
75
+ rows="2"
76
+ inner-class="input-group"
77
+ label-class="input-group-text"
78
+ help="Short description of the alignment target."
79
+ />
80
+
81
+ <FormKit
82
+ type="innerLabelTextInput"
83
+ label="Code"
84
+ name="targetCode"
85
+ inner-class="input-group"
86
+ label-class="input-group-text"
87
+ help="If applicable, a locally unique string identifier that identifies the alignment target within its framework and/or targetUrl."
88
+ />
89
+
90
+ <FormKit
91
+ type="selectInputGroup"
92
+ label="Alignment Type"
93
+ name="targetType"
94
+ inner-class="input-group"
95
+ label-class="input-group-text"
96
+ input-class="$reset formkit-input form-select"
97
+ placeholder="Target Type"
98
+ :options="{
99
+ '': '',
100
+ 'CFItem': 'CFItem',
101
+ 'CFRubric': 'CFRubric',
102
+ 'CFRubricCriterion': 'CFRubricCriterion',
103
+ 'CFRubricCriterionLevel': 'CFRubricCriterionLevel',
104
+ 'ceasn:Competency': 'ceasn:Competency',
105
+ 'ceterms:Credential': 'ceterms:Credential',
106
+ 'CTDL': 'CTDL',
107
+ 'other': 'Other (ext:)',
108
+ }"
109
+ help="The type of the alignment target node."
110
+ >
111
+ <template #suffix>
112
+ <FormKit
113
+ v-if="value[index].targetType === 'other'"
114
+ type="innerLabelTextInput"
115
+ label="Extended Type"
116
+ name="typeExt"
117
+ aria-label="Extended Alignment Type"
118
+ inner-class="input-group ms-3 me-5 pe-3"
119
+ outer-class="$reset"
120
+ label-class="visually-hidden"
121
+ before="ext:"
122
+ :validation="[['matches', '/^[a-z|A-Z|0-9|.|-|_]+$/']]"
123
+ placeholder="Name of extended type"
124
+ >
125
+ <template #prefix>
126
+ <span class="input-group-text" id="extended-prefix" aria-label="ext:">ext:</span>
127
+ </template>
128
+ </FormKit>
129
+ </template>
130
+ </FormKit>
131
+ </div>
132
+ </div>
133
+ </FormKit>
134
+ </FormKit>
135
+ </template>
136
+
137
+ <style>
138
+ .input-group>.form-label {
139
+ margin-bottom: 0;
140
+ }
141
+ </style>
@@ -0,0 +1,13 @@
1
+ <script setup>
2
+ import AlignmentComponent from "@/components/AlignmentComponent.vue";
3
+
4
+ const alignment = defineModel({ default: {} });
5
+ </script>
6
+
7
+ <template>
8
+ <AlignmentComponent v-model="alignment"/>
9
+ </template>
10
+
11
+ <style scoped>
12
+
13
+ </style>
@@ -0,0 +1,18 @@
1
+ <script setup>
2
+ import AlignmentsComponent from "@/components/AlignmentsComponent.vue";
3
+ import ResultDescription from "@/components/ResultDescription.vue";
4
+
5
+ const model = defineModel({ default: {} });
6
+ </script>
7
+
8
+ <template>
9
+ <div class="tab-pane fade show active" id="tab-alignments" role="tabpanel" aria-labelledby="alignments-tab">
10
+ <ResultDescription v-model="model.resultDescription"/>
11
+
12
+ <AlignmentsComponent v-model="model.alignment"/>
13
+ </div>
14
+ </template>
15
+
16
+ <style scoped>
17
+
18
+ </style>
@@ -0,0 +1,55 @@
1
+ <script setup>
2
+ import AchievementImage from "@/components/AchievementImage.vue";
3
+ import AchievementType from "@/components/AchievementType.vue";
4
+ import AchievementCriteria from "@/components/AchievementCriteria.vue";
5
+
6
+ const model = defineModel({ default: {
7
+ /* name: '',
8
+ achievementType: null,
9
+ image: null,
10
+ description: '',
11
+ criteria: { },*/
12
+ } });
13
+ </script>
14
+
15
+ <template>
16
+ <div class="tab-pane fade show active" id="tab-basic" role="tabpanel" aria-labelledby="basic-tab">
17
+ <div class="card mb-3">
18
+ <div class="card-body">
19
+ <p class="mb-0">
20
+ This tab contains all of the required fields for a credential.<br/>
21
+ <em>Credential Type</em> and <em>Image</em> are not required, but it is suggested that all credentials have them.
22
+ </p>
23
+ </div>
24
+ </div>
25
+
26
+ <FormKit
27
+ type="text"
28
+ label="Credential Name"
29
+ name="name"
30
+ wrapper-class="required"
31
+ validation="required:trim"
32
+ v-model="model.name"
33
+ help="The name of the credential."
34
+ />
35
+
36
+ <AchievementType v-model="model.achievementType" />
37
+ <AchievementImage v-model="model.image"/>
38
+
39
+ <FormKit
40
+ type="textarea"
41
+ label="Description"
42
+ name="description"
43
+ wrapper-class="required"
44
+ rows="5"
45
+ validation="required:trim"
46
+ v-model="model.description"
47
+ help="A short description of the achievement."
48
+ />
49
+
50
+ <AchievementCriteria
51
+ v-model="model.criteria"
52
+ />
53
+ </div>
54
+ </template>
55
+
@@ -0,0 +1,166 @@
1
+ <script setup>
2
+ import {onBeforeMount, ref} from "vue";
3
+ import AddressComponent from "@/components/AddressComponent.vue";
4
+ import CredentialImage from "@/components/AchievementImage.vue";
5
+ import OtherIdentifiers from "@/components/OtherIdentifiers.vue";
6
+
7
+ const creator=defineModel({ default: {} });
8
+ const creatorIs=ref('noCreator');
9
+
10
+ onBeforeMount(() => {
11
+ if (Object.keys(creator.value).length === 0) {
12
+ creator.value = 'noCreator';
13
+
14
+ return;
15
+ }
16
+
17
+ // Default to organization
18
+ creatorIs.value = 'organization';
19
+
20
+ if (creator.value.dateOfBirth || null) {
21
+ creatorIs.value = 'individual';
22
+ }
23
+ });
24
+ </script>
25
+
26
+ <template>
27
+ <div class="card">
28
+ <h5 class="card-header">
29
+ <formKit
30
+ type="select"
31
+ label="Creator"
32
+ v-model="creatorIs"
33
+ input-class="$reset formkit-input form-select"
34
+ :options="{
35
+ noCreator: 'Do not add a creator field',
36
+ organization: 'The creator is an Organization',
37
+ individual: 'The creator is a Person',
38
+ }"
39
+ ignore="true"
40
+ />
41
+ </h5>
42
+
43
+ <FormKit
44
+ type="group"
45
+ name="creator"
46
+ v-model="creator"
47
+ v-if="creatorIs !== 'noCreator'"
48
+ >
49
+ <div class="card-body">
50
+ <FormKit
51
+ type="text"
52
+ label="ID"
53
+ name="id"
54
+ wrapper-class="required"
55
+ validation="required:trim"
56
+ help="Unique URI for the creator."
57
+ />
58
+
59
+ <FormKit
60
+ type="hidden"
61
+ name="type"
62
+ :value="[ 'Profile' ]"
63
+ />
64
+
65
+ <FormKit
66
+ type="text"
67
+ label="Name"
68
+ name="name"
69
+ help="The name of the entity or organization."
70
+ />
71
+
72
+ <FormKit
73
+ type="text"
74
+ label="Description"
75
+ name="description"
76
+ help="A short description of the issuer entity or organization."
77
+ />
78
+
79
+ <CredentialImage
80
+ help="An image that represents the creator. Must be a PNG or SVG image."
81
+ v-model="creator.image"
82
+ />
83
+
84
+ <FormKit
85
+ type="text"
86
+ label="Official"
87
+ name="official"
88
+ help="If the entity is an organization, `official` is the name of an authorized official of the organization."
89
+ v-if="creatorIs === 'organization'"
90
+ />
91
+
92
+ <FormKit
93
+ type="text"
94
+ label="URL"
95
+ name="url"
96
+ validation="url"
97
+ help="The homepage or social media profile of the entity, whether individual or institutional. Should be a URL/URI Accessible via HTTP."
98
+ />
99
+
100
+ <FormKit
101
+ type="text"
102
+ label="Email"
103
+ name="email"
104
+ validation="email"
105
+ help="An email address for the creator."
106
+ />
107
+
108
+ <FormKit
109
+ type="text"
110
+ label="Phone"
111
+ name="phone"
112
+ help="A phone number for the creator."
113
+ />
114
+
115
+ <AddressComponent
116
+ v-model="creator.address"
117
+ />
118
+
119
+ <FormKit
120
+ type="text"
121
+ label="Date of Birth"
122
+ name="dateOfBirth"
123
+ format="yyyy-MM-dd"
124
+ help="Birthdate of the person."
125
+ v-if="creatorIs === 'individual'"
126
+ />
127
+
128
+ <OtherIdentifiers
129
+ label="Other Identifiers"
130
+ v-model="creator.otherIdentifier"
131
+ help="Other unique identifiers for the creator."
132
+ />
133
+
134
+ <FormKit
135
+ type="text"
136
+ label="Parent Org"
137
+ name="parentOrg"
138
+ placeholder="--TO BE EXPANDED--"
139
+ v-if="false"
140
+ />
141
+
142
+ <FormKit
143
+ type="text"
144
+ label="Endorsement JWT"
145
+ name="endorsementJwt"
146
+ help="Allows endorsers to make specific claims about the individual or organization represented by this profile. These endorsements are signed with the VC-JWT proof format."
147
+ placeholder="--TO BE EXPANDED --"
148
+ v-if="false"
149
+ />
150
+
151
+ <FormKit
152
+ type="text"
153
+ label="Endorsement"
154
+ name="endorsement"
155
+ help="Allows endorsers to make specific claims about the individual or organization represented by this profile."
156
+ placeholder="--TO BE EXPANDED --"
157
+ v-if="false"
158
+ />
159
+ </div>
160
+ </FormKit>
161
+ </div>
162
+ </template>
163
+
164
+ <style scoped>
165
+
166
+ </style>