@@ -32,8 +32,10 @@ AddEmployeeModal(
|
|||||||
td(
|
td(
|
||||||
v-for="(date, dIndex) in row.dates"
|
v-for="(date, dIndex) in row.dates"
|
||||||
:key="dIndex"
|
:key="dIndex"
|
||||||
:class="{'bg-secondary bg-opacity-10' : row.dates[dIndex] === null, 'selected' : isSelected(new Coordinates(mIndex, rIndex, eIndex, dIndex))}"
|
:class="{'bg-secondary bg-opacity-10' : row.dates[dIndex] === null, 'selected' : isSelected(mIndex, rIndex, eIndex, dIndex)}"
|
||||||
@click="select(new Coordinates(mIndex, rIndex, eIndex, dIndex), $event)"
|
@click.exact="select(mIndex, rIndex, eIndex, dIndex)"
|
||||||
|
@click.ctrl.exact="ctrlSelect(mIndex, rIndex, eIndex, dIndex)"
|
||||||
|
@click.shift.exact="shiftSelect(mIndex, rIndex, eIndex, dIndex)"
|
||||||
)
|
)
|
||||||
tr()
|
tr()
|
||||||
td.text-end
|
td.text-end
|
||||||
@@ -51,11 +53,11 @@ AddEmployeeModal(
|
|||||||
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { toRef, watch, computed, ref, h, render } from 'vue'
|
import { watch, computed, ref } from 'vue'
|
||||||
import type { Ref, ComputedRef } from 'vue'
|
import type { Ref, ComputedRef } from 'vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { useEmployees } from '../stores/employees'
|
import { useEmployees } from '../stores/employees'
|
||||||
import { addMonths, eachMonthOfInterval, subDays, addDays, format, getISODay, getYear, getMonth, isValid, eachDayOfInterval, getDaysInMonth } from 'date-fns'
|
import { addMonths, eachMonthOfInterval, subDays, addDays, format, getISODay, getYear, getMonth, getDaysInMonth } from 'date-fns'
|
||||||
import { de } from 'date-fns/locale'
|
import { de } from 'date-fns/locale'
|
||||||
import AddEmployeeModal from './AddEmployeeModal.vue'
|
import AddEmployeeModal from './AddEmployeeModal.vue'
|
||||||
import Coordinates from '../types/coordinates'
|
import Coordinates from '../types/coordinates'
|
||||||
@@ -132,7 +134,7 @@ AddEmployeeModal(
|
|||||||
const scheduleData : Ref<ScheduleData> = ref(getScheduleData())
|
const scheduleData : Ref<ScheduleData> = ref(getScheduleData())
|
||||||
const { employees } = storeToRefs(store)
|
const { employees } = storeToRefs(store)
|
||||||
|
|
||||||
const selected : Ref<Coordinates[]> = ref([])
|
const selected : Ref<Set<string>> = ref(new Set())
|
||||||
const shiftAnchor : Ref<Coordinates | undefined> = ref(undefined)
|
const shiftAnchor : Ref<Coordinates | undefined> = ref(undefined)
|
||||||
/**
|
/**
|
||||||
* End Refs
|
* End Refs
|
||||||
@@ -186,22 +188,11 @@ AddEmployeeModal(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSelected(c : Coordinates) : boolean {
|
function isSelected(m : number, r : number, e : number, d : number) : boolean {
|
||||||
return selected.value.some(el => {
|
return selected.value.has(Coordinates.toString(m,r,e,d))
|
||||||
return el.toString() === c.toString()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
function removeFromSelected(c : Coordinates) : boolean {
|
function removeFromSelected(m : number, r : number, e : number, d : number) : boolean {
|
||||||
let i = selected.value.findIndex(e => {
|
return selected.value.delete(Coordinates.toString(m,r,e,d))
|
||||||
return e.toString() === c.toString()
|
|
||||||
})
|
|
||||||
|
|
||||||
if (i > -1){
|
|
||||||
selected.value.splice(i, 1)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -214,33 +205,43 @@ AddEmployeeModal(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function select(coord : Coordinates, e : MouseEvent) {
|
function select(m : number, r : number, e : number, d : number) : void {
|
||||||
if(e.ctrlKey){
|
if(selected.value.size > 1 || !isSelected(m,r,e,d)) {
|
||||||
if(isSelected(coord)){
|
selected.value.clear()
|
||||||
removeFromSelected(coord)
|
selected.value.add(Coordinates.toString(m,r,e,d))
|
||||||
shiftAnchor.value = selected.value[selected.value.length - 1]
|
shiftAnchor.value = new Coordinates(m,r,e,d)
|
||||||
}
|
|
||||||
else {
|
|
||||||
selected.value.push(coord)
|
|
||||||
shiftAnchor.value = coord
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(e.shiftKey && shiftAnchor.value !== undefined &&
|
|
||||||
shiftAnchor.value.mIndex === coord.mIndex &&
|
|
||||||
shiftAnchor.value.rIndex === coord.rIndex
|
|
||||||
){
|
|
||||||
// TODO: #8 Figure out how to select all cells between anchor and click
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(selected.value.length > 1 || !isSelected(coord)) {
|
selected.value.clear()
|
||||||
selected.value = []
|
shiftAnchor.value = undefined
|
||||||
selected.value.push(coord)
|
}
|
||||||
shiftAnchor.value = coord
|
}
|
||||||
}
|
|
||||||
else {
|
function ctrlSelect(m : number, r : number, e : number, d : number) : void {
|
||||||
selected.value = []
|
if(isSelected(m,r,e,d)){
|
||||||
shiftAnchor.value = undefined
|
removeFromSelected(m,r,e,d)
|
||||||
|
shiftAnchor.value = new Coordinates(m,r,e,d)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
selected.value.add(Coordinates.toString(m,r,e,d))
|
||||||
|
shiftAnchor.value = new Coordinates(m,r,e,d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function shiftSelect(m : number, r : number, e : number, d : number) : void {
|
||||||
|
if(shiftAnchor.value !== undefined &&
|
||||||
|
shiftAnchor.value.mIndex === m &&
|
||||||
|
shiftAnchor.value.rIndex === r &&
|
||||||
|
shiftAnchor.value.toString() === [...selected.value].pop()
|
||||||
|
){
|
||||||
|
// TODO: #8 Figure out how to select all cells between anchor and click
|
||||||
|
let [eBig, eSmall] : number[] = shiftAnchor.value.eIndex > e ? [shiftAnchor.value.eIndex, e] : [e, shiftAnchor.value.eIndex]
|
||||||
|
let [dBig, dSmall] : number[] = shiftAnchor.value.dIndex > d ? [shiftAnchor.value.dIndex, d] : [d, shiftAnchor.value.dIndex]
|
||||||
|
|
||||||
|
for(let eIt = eSmall; eIt <= eBig; eIt++){
|
||||||
|
for(let dIt = dSmall; dIt <= dBig; dIt++){
|
||||||
|
selected.value.add(Coordinates.toString(m,r,eIt,dIt))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -256,7 +257,13 @@ AddEmployeeModal(
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
table {
|
table {
|
||||||
table-layout: fixed
|
table-layout: fixed;
|
||||||
|
-ms-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
table td {
|
table td {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|||||||
33
src/types/coordinates.ts
Normal file
33
src/types/coordinates.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
export default class Coordinates {
|
||||||
|
mIndex : number
|
||||||
|
rIndex : number
|
||||||
|
eIndex : number
|
||||||
|
dIndex : number
|
||||||
|
|
||||||
|
constructor(m : number, r : number, e : number, d : number){
|
||||||
|
this.mIndex = m
|
||||||
|
this.rIndex = r
|
||||||
|
this.eIndex = e
|
||||||
|
this.dIndex = d
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() : string {
|
||||||
|
return `${this.mIndex}-${this.rIndex}-${this.eIndex}-${this.dIndex}`
|
||||||
|
}
|
||||||
|
|
||||||
|
static toString(m : number, r : number, e : number, d : number) : string {
|
||||||
|
return `${m}-${r}-${e}-${d}`
|
||||||
|
}
|
||||||
|
|
||||||
|
static stringToCoord(strRepr : string) : Coordinates | undefined {
|
||||||
|
let re = /^[0-9]+-[0-9]+-[0-9]+-[0-9]+$/
|
||||||
|
let numbers = []
|
||||||
|
|
||||||
|
if(re.test(strRepr)){
|
||||||
|
numbers = strRepr.split('-')
|
||||||
|
|
||||||
|
return new Coordinates(+numbers[0], +numbers[1], +numbers[2], +numbers[3])
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user