I'm using vue 3 composition api, and I do have a 'working' dashboard layout with 2 'widgets'
My issue is that my data overflows the panel as it responds to me shrinking the browser.
As you can see in the shot below, i am trying to make this scroll, but the attempt is not working in a narrower browser.
Here is my component code:
<template>
<v-container class="task-container">
<h1>My Tasks</h1>
<br />
<!-- Column headers row -->
<v-row>
<v-col
v-for="(header, index) in headers"
:key="index"
:cols="header === 'Title' ? 4 : 2"
>
<strong>{{ header }}</strong>
</v-col>
</v-row>
<!-- Task rows -->
<v-row v-for="(task, index) in taskList" :key="index">
<v-col cols="2">{{ getStatusText(task.status) }}</v-col>
<v-col cols="2"><span v-date-format="task.dueDate"></span></v-col>
<v-col cols="4">
{{ task.title }}
</v-col>
<v-col cols="2">{{ task.assigneeBusinessInfo.name }}</v-col>
</v-row>
</v-container>
</template>
<script setup>
import { ref, onMounted } from "vue";
import TaskService from "@/services/task.service";
import router from "@/router/index"; // Assuming you have a router setup
const taskList = ref([]);
async function fetchMyTasks() {
try {
const data = await new TaskService().getAllTasks();
// Order taskList by status and then by dueDate
taskList.value = data.data.sort((a, b) => {
if (a.status !== b.status) {
return (
customStatusOrder.indexOf(a.status) -
customStatusOrder.indexOf(b.status)
);
} else {
return new Date(a.dueDate) - new Date(b.dueDate);
}
});
console.log("task data", taskList.value);
} catch (error) {
console.error("Error fetching data:", error);
}
}
onMounted(async () => {
await fetchMyTasks();
});
// Define column headers
const headers = ref(["Status", "Due Date", "Title", "Assignee"]);
// Status mapping data with custom order
const statusData = [
{ text: "To Do", value: "Open" },
{ text: "In Progress", value: "InProgress" },
{ text: "Testing", value: "Testing" },
{ text: "Done", value: "Close" },
];
// Custom order for status
const customStatusOrder = ["Open", "InProgress", "Testing", "Close"];
// Function to get status text based on value
function getStatusText(status) {
const statusInfo = statusData.find((item) => item.value === status);
return statusInfo ? statusInfo.text : "";
}
</script>
And my parent page:
<template>
<v-container
:class="{
'px-0': true,
'px-2': breakpoint === 'xs' || breakpoint === 'sm',
'pb-12': true,
}"
>
<div class="dashboard70">
<div class="page34">
<div
:class="{
'workload-parent': true,
'flex-column': breakpoint === 'xs',
}"
>
<div class="heading92">
<div class="dashboard73">Dashboard</div>
<div class="embrace-the-simplicity">
Embrace the simplicity of managing multiple campaigns, track
progress with precision, and uncover the key drivers of success.
</div>
</div>
<div
:class="{
inputsbutton18: true,
'align-self-end': breakpoint === 'xs',
}"
>
<div
v-if="
props.userPermissions.isBrand === true ||
props.userPermissions.isAgency === true
"
class="button343"
@click="onCreateCampaignClick()"
>
<div class="text174">
<b class="curae28">Create Campaign</b>
</div>
</div>
<div v-else>
<div class="text174"></div>
</div>
</div>
</div>
<v-row no-gutters class="w-100">
<v-col cols="12" lg="6">
<div
:class="{
'column-115': true,
'pr-4': lgAndUp,
}"
>
<div class="category35">
<div class="widgets-parent">
<div class="widgets">Campaigns</div>
<div class="active-campaigns3">My campaigns</div>
</div>
<img
class="iconschart-pie41"
alt=""
src="/iconsellipsisvertical.svg"
/>
</div>
<div class="campaign-card-parent2">
<CampaignCard
v-for="campaign in allCampaigns"
:key="campaign.id"
:campaign="campaign"
@update:reloadCampaigns="() => fetchCampaigns()"
/>
</div>
</div>
</v-col>
<v-col
cols="12"
lg="6"
:class="{
'mt-12': mdAndDown,
}"
>
<div
:class="{
'column-115': true,
'pl-4': lgAndUp,
}"
>
<div class="category35">
<div class="widgets-parent">
<div class="widgets">Widgets</div>
<div class="active-campaigns3">
Customize what you need most
</div>
</div>
<img
class="iconsbell-alert28"
alt=""
src="/iconspencil1.svg"
@click="onIconspencilClick"
/>
</div>
<div class="frame-parent288">
<div class="frame-wrapper10">
<!-- DASHBOARD GOES HERE -->
<ejs-dashboardlayout
ref="dashboard"
id="api_dashboard"
:columns="16"
:allowResizing="true"
>
<e-panels>
<e-panel
:row="0"
:col="0"
:sizeX="8"
:sizeY="6"
:content="'calevents'"
>
<template v-slot:calevents>
<WidgetCalendar></WidgetCalendar>
</template>
</e-panel>
<e-panel
:row="0"
:col="0"
:sizeX="8"
:sizeY="6"
:content="'taskevents'"
>
<template v-slot:taskevents>
<WidgetTask></WidgetTask>
</template>
</e-panel>
</e-panels>
</ejs-dashboardlayout>
</div>
</div>
</div>
</v-col>
</v-row>
</div>
</div>
</v-container>
</template>
<script setup>
import { useRouter } from "vue-router";
import CampaignService from "@/services/campaign.service";
import CampaignCard from "@/components/CampaignCard.vue";
import WidgetTask from "./WidgetTask.vue";
import WidgetCalendar from "./WidgetCalendar.vue";
import { ref, onMounted, computed } from "vue";
import {
DashboardLayoutComponent as EjsDashboardlayout,
PanelDirective as EPanel,
PanelsDirective as EPanels,
} from "@syncfusion/ej2-vue-layouts";
import { useDisplay } from "vuetify";
const { name, lgAndUp, mdAndDown } = useDisplay();
const breakpoint = computed(() => {
return name.value; // 'xs', 'sm', 'md', 'lg', 'xl','xxl'
});
const dashboard = ref(null);
const spacing = ref([5, 5]);
const allCampaigns = ref([]);
const router = useRouter();
const props = defineProps({
userPermissions: {
type: Object,
required: true,
},
handleError: {
type: Function,
required: true,
},
handleSuccess: {
type: Function,
required: true,
},
});
function onIconspencilClick() {
// Please sync "Edit widgets" to the project
}
function onCreateCampaignClick() {
router.push("/createcampaign");
}
async function fetchCampaigns() {
const campaigns = await new CampaignService().getMyCampaigns();
allCampaigns.value = campaigns.data;
}
onMounted(async () => {
if (!props.userPermissions.isLoggedIn) {
// Clear localStorage
localStorage.clear();
// Redirect to the login route
router.push("/login");
}
await fetchCampaigns();
});
</script>