Last active
September 20, 2022 17:15
-
-
Save nathanchicken/846cb972025cff056594d5ab05c91ce0 to your computer and use it in GitHub Desktop.
global-base/components/base-checkbox-matrix.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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