mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-17 12:42:15 +01:00
add select and deselect all on time and detailed reporting view
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import preset from '../../../../vendor/filament/filament/tailwind.config.preset'
|
import preset from '../../../../vendor/filament/filament/tailwind.config.preset';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
presets: [preset],
|
presets: [preset],
|
||||||
@@ -7,4 +7,4 @@ export default {
|
|||||||
'./resources/views/filament/**/*.blade.php',
|
'./resources/views/filament/**/*.blade.php',
|
||||||
'./vendor/filament/**/*.blade.php',
|
'./vendor/filament/**/*.blade.php',
|
||||||
],
|
],
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -5,15 +5,19 @@ import TimeEntryMassUpdateModal from '@/Components/Common/TimeEntry/TimeEntryMas
|
|||||||
import type { TimeEntry } from '@/packages/api/src';
|
import type { TimeEntry } from '@/packages/api/src';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { twMerge } from 'tailwind-merge';
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
import { Checkbox, InputLabel } from '@/packages/ui/src';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
selectedTimeEntries: TimeEntry[];
|
selectedTimeEntries: TimeEntry[];
|
||||||
deleteSelected: () => void;
|
deleteSelected: () => void;
|
||||||
class?: string;
|
class?: string;
|
||||||
|
allSelected: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
submit: [];
|
submit: [];
|
||||||
|
selectAll: [];
|
||||||
|
unselectAll: [];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const showMassUpdateModal = ref(false);
|
const showMassUpdateModal = ref(false);
|
||||||
@@ -25,14 +29,31 @@ const showMassUpdateModal = ref(false);
|
|||||||
@submit="emit('submit')"
|
@submit="emit('submit')"
|
||||||
v-model:show="showMassUpdateModal"></TimeEntryMassUpdateModal>
|
v-model:show="showMassUpdateModal"></TimeEntryMassUpdateModal>
|
||||||
<MainContainer
|
<MainContainer
|
||||||
v-if="selectedTimeEntries.length > 0"
|
|
||||||
:class="
|
:class="
|
||||||
twMerge(
|
twMerge(
|
||||||
props.class,
|
props.class,
|
||||||
'text-sm py-1.5 font-medium border-b border-t border-border-primary flex items-center space-x-3'
|
'text-sm py-1.5 font-medium border-b border-t border-border-secondary flex items-center space-x-3'
|
||||||
)
|
)
|
||||||
">
|
">
|
||||||
<div>{{ selectedTimeEntries.length }} selected</div>
|
<Checkbox
|
||||||
|
:checked="allSelected"
|
||||||
|
id="selectAll"
|
||||||
|
@update:checked="
|
||||||
|
allSelected ? emit('unselectAll') : emit('selectAll')
|
||||||
|
">
|
||||||
|
</Checkbox>
|
||||||
|
<InputLabel
|
||||||
|
for="selectAll"
|
||||||
|
class="select-none text-text-secondary"
|
||||||
|
v-if="selectedTimeEntries.length > 0">
|
||||||
|
{{ selectedTimeEntries.length }} selected
|
||||||
|
</InputLabel>
|
||||||
|
<InputLabel
|
||||||
|
for="selectAll"
|
||||||
|
class="text-text-secondary select-none"
|
||||||
|
v-else
|
||||||
|
>Select All</InputLabel
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="text-text-tertiary flex space-x-1 items-center hover:text-text-secondary transition focus-visible:ring-2 outline-0 focus-visible:text-text-primary focus-visible:ring-white/80 rounded h-full px-2"
|
class="text-text-tertiary flex space-x-1 items-center hover:text-text-secondary transition focus-visible:ring-2 outline-0 focus-visible:text-text-primary focus-visible:ring-white/80 rounded h-full px-2"
|
||||||
@click="showMassUpdateModal = true"
|
@click="showMassUpdateModal = true"
|
||||||
|
|||||||
@@ -339,7 +339,12 @@ async function clearSelectionAndState() {
|
|||||||
<TimeEntryMassActionRow
|
<TimeEntryMassActionRow
|
||||||
:selected-time-entries="selectedTimeEntries"
|
:selected-time-entries="selectedTimeEntries"
|
||||||
@submit="clearSelectionAndState"
|
@submit="clearSelectionAndState"
|
||||||
:delete-selected="deleteSelected"></TimeEntryMassActionRow>
|
:delete-selected="deleteSelected"
|
||||||
|
@select-all="selectedTimeEntries = [...timeEntries]"
|
||||||
|
@unselect-all="selectedTimeEntries = []"
|
||||||
|
:all-selected="
|
||||||
|
selectedTimeEntries.length === timeEntries.length
|
||||||
|
"></TimeEntryMassActionRow>
|
||||||
<div class="w-full relative">
|
<div class="w-full relative">
|
||||||
<div v-for="entry in timeEntries" :key="entry.id">
|
<div v-for="entry in timeEntries" :key="entry.id">
|
||||||
<TimeEntryRow
|
<TimeEntryRow
|
||||||
|
|||||||
@@ -136,6 +136,9 @@ function deleteSelected() {
|
|||||||
<TimeEntryMassActionRow
|
<TimeEntryMassActionRow
|
||||||
:selected-time-entries="selectedTimeEntries"
|
:selected-time-entries="selectedTimeEntries"
|
||||||
@submit="clearSelectionAndState"
|
@submit="clearSelectionAndState"
|
||||||
|
:all-selected="selectedTimeEntries.length === timeEntries.length"
|
||||||
|
@select-all="selectedTimeEntries = [...timeEntries]"
|
||||||
|
@unselect-all="selectedTimeEntries = []"
|
||||||
:delete-selected="deleteSelected"></TimeEntryMassActionRow>
|
:delete-selected="deleteSelected"></TimeEntryMassActionRow>
|
||||||
<TimeEntryGroupedTable
|
<TimeEntryGroupedTable
|
||||||
v-model:selected="selectedTimeEntries"
|
v-model:selected="selectedTimeEntries"
|
||||||
|
|||||||
@@ -35,5 +35,5 @@ const proxyChecked = computed({
|
|||||||
type="checkbox"
|
type="checkbox"
|
||||||
:id="id"
|
:id="id"
|
||||||
:value="value"
|
:value="value"
|
||||||
class="rounded bg-input-background border-input-border text-indigo-600 shadow-sm focus:ring-indigo-500" />
|
class="h-4 w-4 rounded bg-card-background border-input-border text-accent-500/80 focus:ring-accent-500/80" />
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineProps({
|
import { twMerge } from 'tailwind-merge';
|
||||||
value: String,
|
|
||||||
});
|
const props = defineProps<{
|
||||||
|
value?: string;
|
||||||
|
class?: string;
|
||||||
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<label class="block font-medium text-sm text-white">
|
<label
|
||||||
|
:class="twMerge('block font-medium text-sm text-white', props.class)">
|
||||||
<span v-if="value">{{ value }}</span>
|
<span v-if="value">{{ value }}</span>
|
||||||
<span v-else><slot /></span>
|
<span v-else><slot /></span>
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
@@ -8,7 +8,11 @@ import {
|
|||||||
} from './vite-module-loader.js';
|
} from './vite-module-loader.js';
|
||||||
|
|
||||||
async function getConfig() {
|
async function getConfig() {
|
||||||
const paths = ['resources/js/app.ts', 'resources/css/app.css', 'resources/css/filament/admin/theme.css'];
|
const paths = [
|
||||||
|
'resources/js/app.ts',
|
||||||
|
'resources/css/app.css',
|
||||||
|
'resources/css/filament/admin/theme.css',
|
||||||
|
];
|
||||||
const modulePaths = await collectModuleAssetsPaths('extensions');
|
const modulePaths = await collectModuleAssetsPaths('extensions');
|
||||||
const additionalPlugins = await collectModulePlugins('extensions');
|
const additionalPlugins = await collectModulePlugins('extensions');
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user