Env swap #21

Merged
danieljsummers merged 30 commits from env-swap into help-wanted 2021-08-10 03:23:50 +00:00
3 changed files with 129 additions and 19 deletions
Showing only changes of commit 7e0f98d249 - Show all commits

View File

@ -77,6 +77,30 @@ export interface Profile {
skills : Skill[] skills : Skill[]
} }
/** The data required to update a profile */
export interface ProfileForm {
/** Whether the citizen to whom this profile belongs is actively seeking employment */
isSeekingEmployment : boolean
/** Whether this profile should appear in the public search */
isPublic : boolean
/** The user's real name */
realName : string
/** The ID of the continent on which the citizen is located */
continentId : string
/** The area within that continent where the citizen is located */
region : string
/** If the citizen is available for remote work */
remoteWork : boolean
/** If the citizen is seeking full-time employment */
fullTime : boolean
/** The user's professional biography */
biography : string
/** The user's past experience */
experience : string | undefined
/** The skills for the user */
skills : Skill[]
}
/** The data required to show a viewable profile */ /** The data required to show a viewable profile */
export interface ProfileForView { export interface ProfileForView {
/** The profile itself */ /** The profile itself */

View File

@ -0,0 +1,45 @@
<template>
<v-row>
<v-col cols="2" md="1">
<br>
<v-btn color="danger" variant="outlined" title="Delete" @click="$emit('remove')">&minus;</v-btn>
</v-col>
<v-col cols="10" md="6">
<label :for="`skillDesc${skill.id}`" class="jjj-label">Skill</label>
<input type="text" :id="`skillDesc${skill.id}`" maxlength="100"
placeholder="A skill (language, design technique, process, etc.)"
:value="skill.description" @input="updateValue('description', $event.target.value)">
</v-col>
<v-col cols="12" md="5">
<label :for="`skillNotes${skill.id}`" class="jjj-label">Notes</label>
<input type="text" :id="`skillNotes${skill.id}`" maxlength="100"
placeholder="A further description of the skill (100 characters max)"
:value="skill.notes" @input="updateValue('notes', $event.target.value)">
</v-col>
</v-row>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { Skill } from '@/api'
export default defineComponent({
name: 'ProfileSkillEdit',
props: {
modelValue: {
type: Object,
required: true
}
},
emits: ['remove', 'update:modelValue'],
setup (props, { emit }) {
/** The skill being edited */
const skill : Skill = { ...props.modelValue as Skill }
return {
skill,
updateValue: (key : string, value : string) => emit('update:modelValue', { ...skill, [key]: value })
}
}
})
</script>

View File

@ -8,7 +8,7 @@
<v-row> <v-row>
<v-col cols="12" sm="10" md="8" lg="6"> <v-col cols="12" sm="10" md="8" lg="6">
<label for="realName">Real Name</label> <label for="realName">Real Name</label>
<input type="text" id="realName" v-model="realName" maxlength="255" <input type="text" id="realName" v-model="profile.realName" maxlength="255"
placeholder="Leave blank to use your NAS display name"> placeholder="Leave blank to use your NAS display name">
</v-col> </v-col>
</v-row> </v-row>
@ -60,12 +60,10 @@
<hr> <hr>
<h4> <h4>
Skills &nbsp; Skills &nbsp;
<button type="button" class="btn btn-outline-primary" @onclick="AddNewSkill">Add a Skill</button> <v-btn color="primary" variant="outlined" @click="addSkill">Add a Skill</v-btn>
</h4> </h4>
@foreach (var skill in ProfileForm.Skills) <profile-skill-edit v-for="(skill, idx) in profile.skills" :key="skill.id" v-model="profile.skills[idx]"
{ @remove="removeSkill(skill.id)" />
[SkillEdit Skill=@skill OnRemove=@RemoveSkill /]
}
<hr> <hr>
<h4>Experience</h4> <h4>Experience</h4>
<p> <p>
@ -111,16 +109,19 @@
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, Ref, ref } from 'vue' import { computed, defineComponent, Ref, ref } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import api, { LogOnSuccess, Profile } from '@/api' import api, { Citizen, LogOnSuccess, Profile, ProfileForm } from '@/api'
import { useStore } from '@/store'
import MarkdownEditor from '@/components/MarkdownEditor.vue' import MarkdownEditor from '@/components/MarkdownEditor.vue'
import LoadData from '@/components/LoadData.vue' import LoadData from '@/components/LoadData.vue'
import { useStore } from '@/store' import ProfileSkillEdit from '@/components/profile/SkillEdit.vue'
export default defineComponent({ export default defineComponent({
name: 'EditProfile', name: 'EditProfile',
components: { components: {
LoadData, LoadData,
MarkdownEditor MarkdownEditor,
ProfileSkillEdit
}, },
setup () { setup () {
const store = useStore() const store = useStore()
@ -132,11 +133,23 @@ export default defineComponent({
/** Whether this is a new profile */ /** Whether this is a new profile */
const isNew = ref(false) const isNew = ref(false)
/** The user's current profile */ /** The starting values for a new employment profile */
const profile : Ref<Profile | undefined> = ref(undefined) const newProfile : Profile = {
id: user.citizenId,
seekingEmployment: false,
isPublic: false,
continentId: '',
region: '',
remoteWork: false,
fullTime: false,
biography: '',
lastUpdatedOn: '',
experience: undefined,
skills: []
}
/** The user's real name */ /** The user's current profile (plus a few items, adapted for editing) */
const realName : Ref<string | undefined> = ref(undefined) const profile : Ref<ProfileForm | undefined> = ref(undefined)
/** Retrieve the user's profile and their real name */ /** Retrieve the user's profile and their real name */
const retrieveData = async (errors : string[]) => { const retrieveData = async (errors : string[]) => {
@ -146,16 +159,43 @@ export default defineComponent({
errors.push(profileResult) errors.push(profileResult)
} else if (typeof profileResult === 'undefined') { } else if (typeof profileResult === 'undefined') {
isNew.value = true isNew.value = true
} else {
profile.value = profileResult
// console.info(JSON.stringify(profile))
} }
const nameResult = await api.citizen.retrieve(user.citizenId, user) const nameResult = await api.citizen.retrieve(user.citizenId, user)
if (typeof nameResult === 'string') { if (typeof nameResult === 'string') {
errors.push(nameResult) errors.push(nameResult)
} else if (typeof nameResult !== 'undefined') {
realName.value = nameResult.realName || ''
} }
if (errors.length > 0) return
const p = isNew.value ? newProfile : profileResult as Profile
profile.value = {
isSeekingEmployment: p.seekingEmployment,
isPublic: p.isPublic,
continentId: p.continentId,
region: p.region,
remoteWork: p.remoteWork,
fullTime: p.fullTime,
biography: p.biography,
experience: p.experience,
skills: p.skills,
realName: typeof nameResult !== 'undefined' ? (nameResult as Citizen).realName || '' : ''
}
}
/** The ID for new skills */
let newSkillId = 0
/** Add a skill to the profile */
const addSkill = () => {
const form = profile.value as ProfileForm
form.skills.push({ id: `new${newSkillId}`, description: '', notes: undefined })
newSkillId++
profile.value = form
}
/** Remove the given skill from the profile */
const removeSkill = (skillId : string) => {
const form = profile.value as ProfileForm
form.skills = form.skills.filter(s => s.id !== skillId)
profile.value = form
} }
return { return {
@ -163,8 +203,9 @@ export default defineComponent({
user, user,
isNew, isNew,
profile, profile,
realName,
continents: computed(() => store.state.continents), continents: computed(() => store.state.continents),
addSkill,
removeSkill,
viewProfile: () => router.push(`/profile/view/${user.citizenId}`) viewProfile: () => router.push(`/profile/view/${user.citizenId}`)
} }
} }