mirror of
https://gitlab.com/wgp/dougal/software.git
synced 2025-12-06 08: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