Skip to content

Commit

Permalink
Merge pull request #890 from oslokommune/add_contributors_to_objective
Browse files Browse the repository at this point in the history
Add contributors to objective
  • Loading branch information
simenheg authored Oct 17, 2023
2 parents 6926ff5 + a964f05 commit 01d4de9
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 17 deletions.
41 changes: 41 additions & 0 deletions firestore.indexes.json
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,24 @@
"order": "DESCENDING"
}
]
},
{
"collectionGroup": "objectiveContributors",
"queryScope": "COLLECTION",
"fields": [
{
"fieldPath": "archived",
"order": "ASCENDING"
},
{
"fieldPath": "item",
"order": "ASCENDING"
},
{
"fieldPath": "objective",
"order": "ASCENDING"
}
]
}
],
"fieldOverrides": [
Expand Down Expand Up @@ -469,6 +487,29 @@
"queryScope": "COLLECTION_GROUP"
}
]
},
{
"collectionGroup": "objectiveContributors",
"fieldPath": "auto",
"ttl": false,
"indexes": [
{
"order": "ASCENDING",
"queryScope": "COLLECTION"
},
{
"order": "DESCENDING",
"queryScope": "COLLECTION"
},
{
"arrayConfig": "CONTAINS",
"queryScope": "COLLECTION"
},
{
"arrayConfig": "CONTAINS",
"queryScope": "COLLECTION_GROUP"
}
]
}
]
}
142 changes: 125 additions & 17 deletions src/components/drawers/EditKeyResult.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,15 @@
:rows="2"
:label="$t('fields.description')"
/>
<!-- TODO: Include when related views have been implemented -->
<!--form-component
<form-component
v-if="isOrganization || isDepartment"
v-model="thisKeyResult.parent"
v-model="contributor"
name="owner"
input-type="select"
:select-options="ownerOptions"
:label="$t('fields.owner')"
rules="required"
/-->
/>
</template>

<template v-else-if="pageIndex === 2">
Expand Down Expand Up @@ -166,11 +165,15 @@
import { mapState } from 'vuex';
import { db } from '@/config/firebaseConfig';
import KeyResult from '@/db/KeyResult';
import { isDepartment, isOrganization } from '@/util/getActiveItemType';
import ObjectiveContributors from '@/db/ObjectiveContributors';
import { PktButton } from '@oslokommune/punkt-vue2';
import { FormSection, BtnSave, BtnDelete } from '@/components/generic/form';
import ArchivedRestore from '@/components/ArchivedRestore.vue';
import PagedDrawerWrapper from '@/components/drawers/PagedDrawerWrapper.vue';
import getActiveItemType, {
isDepartment,
isOrganization,
} from '@/util/getActiveItemType';
export default {
name: 'EditKeyResult',
Expand Down Expand Up @@ -212,6 +215,7 @@ export default {
},
pageCount: 2,
loading: false,
contributor: null,
}),
computed: {
Expand All @@ -229,7 +233,7 @@ export default {
if (isDepartment(this.activeItem)) {
return this.departments.find((d) => d.id === this.activeItem.id);
}
return {};
return this.products.find((p) => p.id === this.activeItem.id);
},
children() {
if (isOrganization(this.activeItem)) {
Expand All @@ -242,7 +246,7 @@ export default {
(product) => product.department.id === this.activeItem.id
);
}
return {};
return [];
},
thisLevelOption() {
return {
Expand Down Expand Up @@ -289,22 +293,28 @@ export default {
...snapshot.data(),
};
this.thisKeyResult.id = this.keyResult.id;
this.contributor = this.ownerOptions.find(
(o) => o.name === this.keyResult.parent.name
);
this.loading = false;
});
},
},
// thisLevel: {
// immediate: true,
// async handler() {
// // Set currentLevel as default option for key result owner
// if (!this.keyResult.id) {
// this.thisKeyResult.parent = this.thisLevelOption;
// }
// },
// },
thisLevel: {
immediate: true,
async handler() {
// Set currentLevel as default option for key result owner
if (!this.keyResult?.id) {
this.contributor = this.thisLevelOption;
}
},
},
},
methods: {
isDepartment,
isOrganization,
async save() {
const { pageIndex, next } = this.$refs.drawer;
Expand All @@ -316,7 +326,9 @@ export default {
try {
const { name, description, unit, weight, startValue, targetValue } =
this.thisKeyResult;
const parent = this.activeItemRef;
const parent = db.doc(this.contributor.value);
const data = {
name,
description: description || '',
Expand All @@ -340,6 +352,7 @@ export default {
this.thisKeyResult.objective = objectiveRef;
this.$emit('create', this.thisKeyResult);
}
await this.syncObjectiveContributor();
this.$refs.drawer.next();
} catch (error) {
console.log(error);
Expand All @@ -355,6 +368,7 @@ export default {
this.loading = true;
try {
await KeyResult.archive(this.thisKeyResult.id);
await this.syncObjectiveContributor();
this.thisKeyResult.archived = true;
this.$emit('archive', this.thisKeyResult);
} catch (error) {
Expand All @@ -368,6 +382,7 @@ export default {
async restore() {
try {
await KeyResult.restore(this.thisKeyResult.id);
await this.syncObjectiveContributor();
this.thisKeyResult.archived = false;
this.$emit('restore', this.thisKeyResult);
} catch {
Expand All @@ -377,6 +392,99 @@ export default {
}
},
async getObjectiveContributors() {
const objectiveRef = await db.doc(`objectives/${this.objective.id}`);
const objectiveContributors = await db
.collection('objectiveContributors')
.where('objective', '==', objectiveRef)
.where('archived', '==', false)
.get()
.then((snapshot) => snapshot.docs)
.then((docs) => docs.map((d) => d.data()));
const contributors = await Promise.all(
objectiveContributors.map(async (con) => {
return {
ref: await con.item.get(),
name: await con.item.get().then((snapshot) => snapshot.data().name),
};
})
);
return contributors;
},
async getKeyResultOwners() {
const objectiveRef = await db.doc(`objectives/${this.objective.id}`);
const keyResults = await db
.collection('keyResults')
.where('objective', '==', objectiveRef)
.where('archived', '==', false)
.get()
.then((snapshot) => snapshot.docs)
.then((docs) => docs.map((d) => d.data()));
const keyResultNames = await Promise.all(
keyResults.map(async (owner) => {
return {
ref: await owner.parent.get(),
name: await owner.parent.get().then((snapshot) => snapshot.data().name),
};
})
);
return keyResultNames;
},
async syncObjectiveContributor() {
const keyResultOwners = await this.getKeyResultOwners();
const contributors = await this.getObjectiveContributors();
let redundantContributors = [...contributors];
let keyResWithNoContributor = [...keyResultOwners];
// Filter out already present links
contributors.forEach((c) => {
keyResultOwners.forEach((k) => {
if (c.name === k.name) {
redundantContributors = redundantContributors.filter(
(con) => con.name !== c.name
);
keyResWithNoContributor = keyResWithNoContributor.filter(
(kr) => kr.name !== k.name
);
}
});
});
// We only need one contributor element per unique keyRes parent (here mapped by name)
const uniqueKeyResWithNoContributor = keyResWithNoContributor.filter(
(value, index, self) => index === self.findIndex((t) => t.name === value.name)
);
// Add missing contributor
uniqueKeyResWithNoContributor.forEach((k) => {
this.createObjectiveContributor(k.ref);
});
// Remove redundant contributors
redundantContributors.forEach((c) => {
this.removeObjectiveContributor(c.ref);
});
},
createObjectiveContributor(item) {
const itemType = getActiveItemType(item.data());
const itemRef = db.doc(`${itemType}s/${item.id}`);
const objectiveRef = db.doc(`objectives/${this.objective.id}`);
ObjectiveContributors.create(itemRef, objectiveRef);
},
async removeObjectiveContributor(item) {
const itemType = getActiveItemType(item.data());
const itemRef = db.doc(`${itemType}s/${item.id}`);
const objectiveRef = db.doc(`objectives/${this.objective.id}`);
return ObjectiveContributors.remove(itemRef, objectiveRef);
},
close(e) {
this.$emit('close', e);
},
Expand Down
12 changes: 12 additions & 0 deletions src/db/ObjectiveContributors/ObjectiveContributors.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@ const create = async (itemRef, objectiveRef) => {
throw new Error(`Cannot find objcetive with ID ${objectiveRef.id}`);
}

const contributors = await db
.collection('objectiveContributors')
.where('objective', '==', objectiveRef)
.where('item', '==', itemRef)
.get()
.then((snapshot) => snapshot.docs.map((doc) => doc.ref));

// Avoid creating duplicates
if (contributors.length > 0) {
return contributors[0];
}

const data = { item: itemRef, objective: objectiveRef };

validateCreateProps(props, data);
Expand Down

0 comments on commit 01d4de9

Please sign in to comment.