Skip to content

Instantly share code, notes, and snippets.

@nathanchicken
Last active September 20, 2022 17:15
Show Gist options
  • Save nathanchicken/846cb972025cff056594d5ab05c91ce0 to your computer and use it in GitHub Desktop.
Save nathanchicken/846cb972025cff056594d5ab05c91ce0 to your computer and use it in GitHub Desktop.
global-base/components/base-checkbox-matrix.vue
<template>
<div
id="matrix-wrapper"
:style="{
'--grid-rows': roles.length + 1,
'--grid-columns': entities.length + 1,
}"
>
<div>
<pre>{{ this.value }}</pre>
</div>
<div class="checkbox-matrix">
<div class="matrix-heading">
<div v-for="entity in entities" class="matrix-heading-item">
<p>{{ entity.name }}</p>
</div>
</div>
<div class="matrix-row">
<div v-for="role in roles" class="matrix-inside-row">
<div class="matrix-roles">
<p>{{ role.label }}</p>
</div>
<div v-for="entity in entities" class="matrix-checks">
<base-checkbox
type="checkbox"
:label="`${role.name} for ${entity.name}`"
@change="emitinternal(role.value, entity.id, isChecked)"
:value="getIsChecked(entity.id, role.value)"
/>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
/**
* [{
* id: '1234',
* name :'1s and 2s',
* },
*
* {
* id: '7890', name: '7s and 8s'
*
* },
*
* { id: 'abc', name: 'alpha' } ]
*/
entities: {
type: Array,
default: () => [],
},
// ['platform_admin', 'platform_manager']
roles: {
type: Array,
default: () => [],
},
value: {
type: Array,
default: () => [],
},
},
model: {
event: 'update',
},
data () {
return {
internal: [],
}
},
watch: {
value: {
immediate: true,
deep: true,
handler (value) {
this.internal = value
},
},
},
methods: {
/**
* Check if a role is active for the particular entity
*/
getIsChecked (entityId, role) {
const entity = this.getEntity(entityId)
if (entity) {
return this.roleIsChecked(role, entity.roles)
} else {
return false
}
},
roleIsChecked (role, listOfRoles = []) {
return listOfRoles.includes(role)
},
getEntity (id) {
return this.internal.find(({ entity }) => entity === id)
},
addEntity (entityId) {
const entity = {
id: entityId,
roles: [],
}
this.internal.push(entity)
return entity
},
computeinternal (role, entityId, isChecked) {
let entity = this.getEntity(entityId)
if (!entity) {
entity = this.addEntity(entityId)
}
const wasChecked = this.roleIsChecked(role, entity.roles)
if (isChecked && !wasChecked) {
// Add it to the roles
entity.roles.push(role)
} else if (!isChecked && wasChecked) {
// remove it from the roles
entity.roles = entity.roles.filter(_role => _role !== role)
}
},
emitinternal (role, entity, isChecked) {
this.computeinternal(role, entity, isChecked)
this.$emit('update', this.internal)
},
},
}
</script>
<style scoped>
.checkbox-matrix {
display: grid;
grid-template-rows: repeat(var(--grid-rows), 1fr);
grid-template-columns: repeat(var(--grid-columns), 1fr);
}
.matrix-heading {
grid-row: 1 / calc(var(--grid-rows) - 1);
grid-column: 2 / calc(var(--grid-columns) + 1);
display: flex;
align-items: center;
}
.matrix-heading-item {
flex: 1;
}
.matrix-row {
grid-row: 2 / calc(var(--grid-rows) + 1);
grid-column: 1 / calc(var(--grid-columns) + 1);
}
.matrix-inside-row {
display: flex;
align-items: center;
}
.matrix-checks {
flex: 1;
}
.matrix-roles {
flex: 1;
}
</style>
<template>
<div
id="matrix-wrapper"
:style="{
'--grid-rows': roles.length + 1,
'--grid-columns': entities.length + 1,
}"
>
<div>
<pre>{{ this.value }}</pre>
</div>
<div class="checkbox-matrix">
<div class="matrix-heading">
<div v-for="entity in entities" class="matrix-heading-item">
<p>{{ entity.name }}</p>
</div>
</div>
<div class="matrix-row">
<div v-for="role in roles" class="matrix-inside-row">
<div class="matrix-roles">
<p>{{ role.label }}</p>
</div>
<div v-for="entity in entities" class="matrix-checks">
<input
type="checkbox"
@change="emitinternal(role.value, entity.id, $event.target.checked)"
:checked="getIsChecked(entity.id, role.value)"
/>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
/**
* [{
* id: '1234',
* name :'1s and 2s',
* },
*
* {
* id: '7890', name: '7s and 8s'
*
* },
*
* { id: 'abc', name: 'alpha' } ]
*/
entities: {
type: Array,
default: () => [],
},
// ['platform_admin', 'platform_manager']
roles: {
type: Array,
default: () => [],
},
value: {
type: Array,
default: () => [],
},
},
model: {
event: 'update',
},
data () {
return {
internal: [],
}
},
watch: {
value: {
immediate: true,
deep: true,
handler (value) {
this.internal = value
},
},
},
methods: {
/**
* Check if a role is active for the particular entity
*/
getIsChecked (entityId, role) {
const entity = this.getEntity(entityId)
if (entity) {
return this.roleIsChecked(role, entity.roles)
} else {
return false
}
},
roleIsChecked (role, listOfRoles = []) {
return listOfRoles.includes(role)
},
getEntity (id) {
return this.internal.find(({ entity }) => entity === id)
},
addEntity (entityId) {
const entity = {
id: entityId,
roles: [],
}
this.internal.push(entity)
return entity
},
computeinternal (role, entityId, isChecked) {
let entity = this.getEntity(entityId)
if (!entity) {
entity = this.addEntity(entityId)
}
const wasChecked = this.roleIsChecked(role, entity.roles)
if (isChecked && !wasChecked) {
// Add it to the roles
entity.roles.push(role)
} else if (!isChecked && wasChecked) {
// remove it from the roles
entity.roles = entity.roles.filter(_role => _role !== role)
}
},
emitinternal (role, entity, isChecked) {
this.computeinternal(role, entity, isChecked)
this.$emit('update', this.internal)
},
},
}
</script>
<style scoped>
.checkbox-matrix {
display: grid;
grid-template-rows: repeat(var(--grid-rows), 1fr);
grid-template-columns: repeat(var(--grid-columns), 1fr);
}
.matrix-heading {
grid-row: 1 / calc(var(--grid-rows) - 1);
grid-column: 2 / calc(var(--grid-columns) + 1);
display: flex;
align-items: center;
}
.matrix-heading-item {
flex: 1;
}
.matrix-row {
grid-row: 2 / calc(var(--grid-rows) + 1);
grid-column: 1 / calc(var(--grid-columns) + 1);
}
.matrix-inside-row {
display: flex;
align-items: center;
}
.matrix-checks {
flex: 1;
}
.matrix-roles {
flex: 1;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment