mirror of
https://gitlab.com/wgp/dougal/software.git
synced 2025-12-06 10:47:07 +00:00
Add components for editing organisations settings
This commit is contained in:
112
lib/www/client/source/src/components/organisations-item.vue
Normal file
112
lib/www/client/source/src/components/organisations-item.vue
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
<template>
|
||||||
|
<v-row dense no-gutters>
|
||||||
|
|
||||||
|
<v-col>
|
||||||
|
<slot name="prepend"></slot>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col cols="6">
|
||||||
|
<v-text-field
|
||||||
|
class="mr-5"
|
||||||
|
dense
|
||||||
|
label="Name"
|
||||||
|
:value="name"
|
||||||
|
:readonly="true"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col>
|
||||||
|
<v-checkbox
|
||||||
|
class="mr-3"
|
||||||
|
label="Read"
|
||||||
|
v-model="operations.read"
|
||||||
|
:readonly="readonly"
|
||||||
|
></v-checkbox>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col>
|
||||||
|
<v-checkbox
|
||||||
|
class="mr-3"
|
||||||
|
label="Write"
|
||||||
|
v-model="operations.write"
|
||||||
|
:readonly="readonly"
|
||||||
|
></v-checkbox>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col>
|
||||||
|
<v-checkbox
|
||||||
|
class="mr-3"
|
||||||
|
label="Edit"
|
||||||
|
v-model="operations.edit"
|
||||||
|
:readonly="readonly"
|
||||||
|
></v-checkbox>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col>
|
||||||
|
<!-- Just to fill the twelve-column grid -->
|
||||||
|
<!--
|
||||||
|
NOTE: this column could also be used for
|
||||||
|
a popdown menu with additional operations
|
||||||
|
if needed.
|
||||||
|
-->
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col>
|
||||||
|
<slot name="append"></slot>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Organisations } from '@dougal/organisations';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "DougalOrganisationsItem",
|
||||||
|
|
||||||
|
props: {
|
||||||
|
name: String,
|
||||||
|
value: Object,
|
||||||
|
readonly: Boolean,
|
||||||
|
},
|
||||||
|
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
operations: {...this.value}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
value: {
|
||||||
|
handler (newValue) {
|
||||||
|
this.operations = {...this.value};
|
||||||
|
},
|
||||||
|
deep: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
operations: {
|
||||||
|
handler (newValue) {
|
||||||
|
if (["read", "write", "edit"].some( k => newValue[k] != this.value[k] )) {
|
||||||
|
// Only emit if a value has actually changed
|
||||||
|
this.$emit("input", {...newValue});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deep: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
reset () {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted () {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
196
lib/www/client/source/src/components/organisations.vue
Normal file
196
lib/www/client/source/src/components/organisations.vue
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
<template>
|
||||||
|
<v-card>
|
||||||
|
<v-card-title>Organisations</v-card-title>
|
||||||
|
<v-card-subtitle>Organisation access</v-card-subtitle>
|
||||||
|
<v-card-text>
|
||||||
|
<v-form>
|
||||||
|
|
||||||
|
<v-container>
|
||||||
|
|
||||||
|
<dougal-organisations-item v-for="organisation in localOrganisations.names()"
|
||||||
|
:key="organisation"
|
||||||
|
:name="organisation"
|
||||||
|
:value="localOrganisations.get(organisation)"
|
||||||
|
@input="setOrganisation(organisation, $event)"
|
||||||
|
>
|
||||||
|
<template v-slot:append v-if="!readonly">
|
||||||
|
<v-btn
|
||||||
|
class="ml-3"
|
||||||
|
fab
|
||||||
|
text
|
||||||
|
small
|
||||||
|
title="Remove this organisation"
|
||||||
|
>
|
||||||
|
<v-icon
|
||||||
|
color="error"
|
||||||
|
@click="removeOrganisation(organisation)"
|
||||||
|
>mdi-minus</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
</dougal-organisations-item>
|
||||||
|
|
||||||
|
|
||||||
|
<v-row no-gutters class="mb-2" v-if="!readonly">
|
||||||
|
<h4>Add organisation</h4>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<v-row no-gutters class="mb-2" v-if="!readonly">
|
||||||
|
<v-combobox v-if="canCreateOrganisations"
|
||||||
|
label="Organisation"
|
||||||
|
:items="remainingOrganisations"
|
||||||
|
v-model="organisationName"
|
||||||
|
@input.native="organisationName = $event.srcElement.value"
|
||||||
|
@keyup.enter="addOrganisation()"
|
||||||
|
></v-combobox>
|
||||||
|
<v-select v-else
|
||||||
|
label="Organisation"
|
||||||
|
:items="remainingOrganisations"
|
||||||
|
v-model="organisationName"
|
||||||
|
></v-select>
|
||||||
|
<v-btn
|
||||||
|
class="ml-3"
|
||||||
|
fab
|
||||||
|
text
|
||||||
|
small
|
||||||
|
title="Add organisation"
|
||||||
|
:disabled="!(organisationName && organisationName.length)"
|
||||||
|
@click="addOrganisation()"
|
||||||
|
>
|
||||||
|
<v-icon
|
||||||
|
color="primary"
|
||||||
|
>mdi-plus</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
</v-container>
|
||||||
|
</v-form>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions>
|
||||||
|
<!--
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-btn
|
||||||
|
color="secondary"
|
||||||
|
@click="back"
|
||||||
|
>Back</v-btn>
|
||||||
|
-->
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Organisations } from '@dougal/organisations';
|
||||||
|
import DougalOrganisationsItem from './organisations-item';
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "DougalOrganisations",
|
||||||
|
|
||||||
|
components: {
|
||||||
|
DougalOrganisationsItem
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
self: Object,
|
||||||
|
organisations: Object,
|
||||||
|
readonly: Boolean
|
||||||
|
},
|
||||||
|
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
organisationName: "",
|
||||||
|
localOrganisations: this.setLocalOrganisations(this.organisations)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
|
||||||
|
availableOrganisations () {
|
||||||
|
return this.self.organisations.names();
|
||||||
|
},
|
||||||
|
|
||||||
|
// Organisations available to add.
|
||||||
|
// These are the organisations in `availableOrganisations`
|
||||||
|
// minus any that have already been added.
|
||||||
|
// The special value "*" (meaning "every organisation")
|
||||||
|
// is not included.
|
||||||
|
remainingOrganisations () {
|
||||||
|
const orgs = [];
|
||||||
|
|
||||||
|
for (const org of this.availableOrganisations) {
|
||||||
|
if (org != "*" && !this.localOrganisations.has(org)) {
|
||||||
|
orgs.push(org);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return orgs;
|
||||||
|
},
|
||||||
|
|
||||||
|
canCreateOrganisations () {
|
||||||
|
return this.self.organisations.value("*")?.edit ?? false;
|
||||||
|
},
|
||||||
|
|
||||||
|
validationErrors () {
|
||||||
|
const errors = [];
|
||||||
|
|
||||||
|
// Check if there is at least one organisation
|
||||||
|
if (this.localOrganisations.length) {
|
||||||
|
errors.push("ERR_NO_ORGS");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if at least one organisation has edit rights
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
organisations (newValue) {
|
||||||
|
this.localOrganisations = this.setLocalOrganisations(newValue);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
setLocalOrganisations (value) {
|
||||||
|
return new Organisations(this.organisations);
|
||||||
|
},
|
||||||
|
|
||||||
|
setOrganisation(name, value) {
|
||||||
|
this.localOrganisations.set(name, value);
|
||||||
|
this.$emit("update:organisations", new Organisations(this.localOrganisations));
|
||||||
|
},
|
||||||
|
|
||||||
|
addOrganisation () {
|
||||||
|
const key = this.organisationName;
|
||||||
|
if (!this.localOrganisations.has(key)) {
|
||||||
|
this.localOrganisations.set(key);
|
||||||
|
this.$emit("update:organisations", this.localOrganisations);
|
||||||
|
}
|
||||||
|
this.organisationName = "";
|
||||||
|
},
|
||||||
|
|
||||||
|
removeOrganisation (key) {
|
||||||
|
if (this.localOrganisations.has(key)) {
|
||||||
|
this.localOrganisations.remove(key);
|
||||||
|
}
|
||||||
|
this.$emit("update:organisations", this.localOrganisations);
|
||||||
|
},
|
||||||
|
|
||||||
|
reset () {
|
||||||
|
},
|
||||||
|
|
||||||
|
save () {
|
||||||
|
},
|
||||||
|
|
||||||
|
back () {
|
||||||
|
this.$emit('close');
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted () {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user