Commit 6973fdc1 authored by Дмитрий Малюгин's avatar Дмитрий Малюгин 🕓
Browse files

feat: finish adding data types to 'Table' and paginator

parent d627e322
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -116,10 +116,14 @@ const tableColumns: ITableColumn[] = [
  {
    name: 'Is gay?',
    type: 'checkbox',
    filterable: true,
    sortable: true,
  },
  {
    name: 'Status',
    type: 'select',
    filterable: true,
    sortable: true,
    options: {
      options: [{ value: 'Married' }, { value: 'Oh no...(s)he is dead' }],
      theme: 'black',
@@ -128,6 +132,8 @@ const tableColumns: ITableColumn[] = [
  {
    name: 'Children',
    type: 'rating',
    filterable: true,
    sortable: true,
    options: {
      theme: 'yellow',
    },
@@ -135,6 +141,8 @@ const tableColumns: ITableColumn[] = [
  {
    name: 'Job progress',
    type: 'progressBar',
    filterable: true,
    sortable: true,
    options: {
      theme: 'red',
      size: 'small',
@@ -143,7 +151,8 @@ const tableColumns: ITableColumn[] = [
  {
    name: 'Strength',
    type: 'knob',
    options: {},
    filterable: true,
    sortable: true,
  },
];
const tableData = ref([
@@ -164,6 +173,7 @@ const selectOptions = [
];
const knob = ref(0);
const pbValue = ref(0);
const openDrawer = () => (visibleDrawer.value = true);
</script>

<template>
@@ -200,7 +210,6 @@ const pbValue = ref(0);
    v-model="tableData"
    theme="black"
    stripedRows
    editable
    paginator
    :no-editing-settings="{
      cells: [[0, 0]],
@@ -208,7 +217,7 @@ const pbValue = ref(0);
    :handlers="[
      {
        cell: [0, 0],
        handler: () => (visibleDrawer = true),
        handler: () => openDrawer(),
      },
    ]"
  ></Table>
+1 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ export interface ITableColumn {
  name: string;
  options?: ITableColumnOptions;
  type?: TTableColumnType;
  width?: number;
  editable?: boolean;
  filterable?: boolean;
  sortable?: boolean;
+3 −23
Original line number Diff line number Diff line
@@ -95,28 +95,8 @@ export const Simple: Story = {
      },
    ],
    data: [
      [
        {
          value: 'Pete',
        },
        {
          value: '30',
        },
        {
          value: 'Chess',
        },
      ],
      [
        {
          value: 'John',
        },
        {
          value: '25',
        },
        {
          value: 'Football',
        },
      ],
      ['Pete', '30', 'Chess'],
      ['John', '25', 'Football'],
    ],
  },
};
@@ -133,6 +113,7 @@ export const Full: Story = {
        type: 'number',
        filterable: true,
        sortable: true,
        width: '50px',
      },
      {
        name: 'Hobbies',
@@ -154,7 +135,6 @@ export const Full: Story = {
        type: 'select',
        options: {
          options: [{ value: 'Married' }, { value: 'Oh no...(s)he is dead' }],
          theme: 'sky',
        },
      },
      {
+120 −77
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ import { calcAdditionalHeight, calcGap, calcRows } from '@components/Table/helpe
import TableHeader from '@components/Table/components/TableHeader.vue';
import TableCell from '@components/Table/components/TableCell.vue';
import Paginator from '@components/Paginator/Paginator.vue';
import ToggleSwitch from '@components/ToggleSwitch/ToggleSwitch.vue';

const props = withDefaults(defineProps<ITableProps>(), {
  size: 'normal',
@@ -18,7 +19,10 @@ const data = defineModel() as Ref<unknown[][]>;
const emit = defineEmits(['updateData']);

const table = ref();
const currentPage = ref(1);
const currentPage = ref<number>(1);
const itemsPerPage = ref<number>(10);
const isEditMode = ref<boolean>(props.editable);

const columns = ref(props.columns);
const sortStateActive = ref<[number, string] | []>([]);
const indexColumnToFilter = ref<number>(0);
@@ -49,6 +53,8 @@ const sortState = computed<string[]>(() => {
const rows = computed<unknown[][]>(() =>
  calcRows(
    data.value,
    currentPage.value,
    itemsPerPage.value,
    sortStateActive.value,
    props.multipleSort,
    indexColumnToFilter.value,
@@ -58,7 +64,7 @@ const rows = computed<unknown[][]>(() =>
  ),
);
const types = computed(() => props.columns.map((column) => column.type));

const paginatorContainerHeight = computed(() => (props.paginator || props.editable ? '50px' : '0'));
const themeColor = computed(() => convertThemeToColor(props.theme, props.darknessTheme));
const color = computed(() =>
  props.textColor
@@ -107,7 +113,6 @@ const updateData = (newValue: Ref<unknown>, rowIndex: number, columnIndex: numbe
</script>

<template>
  <div :style="`background-color: ${themeColor}; color: ${color}`">
  <table
    :class="{
      tableLines: showAllLines,
@@ -135,6 +140,7 @@ const updateData = (newValue: Ref<unknown>, rowIndex: number, columnIndex: numbe
        :showAllLines="!!showAllLines"
        :center="!!center"
        :fontSize="fontSize"
        :isEditMode="isEditMode"
        @changeColumnSortMode="changeColumnSortMode"
        @setFilter="setFilter"
        @cancelFilter="cancelFilter"
@@ -146,45 +152,58 @@ const updateData = (newValue: Ref<unknown>, rowIndex: number, columnIndex: numbe
        :key="rowIndex"
        :class="{
          noEdit:
              !editable ||
            !isEditMode ||
            (noEditingSettings?.rows && noEditingSettings?.rows.find((i) => data?.[i]?.join('') === row.join(''))),
        }"
      >
        <td
          v-for="(item, columnIndex) of row"
          :key="columnIndex"
            @click="handlers?.find((i) => i.cell?.[0] === rowIndex && i.cell?.[1] === columnIndex)?.handler"
          @click="
            handlers ? handlers?.find((i) => i.cell?.[0] === rowIndex && i.cell?.[1] === columnIndex)?.handler() : null
          "
          :class="{
            leftBorder: showAllLines,
              darkRow: stripedRows && rowIndex % 2,
              noEdit: !editable || (noEditingSettings?.columns && ~noEditingSettings.columns?.indexOf(columnIndex)),
              pointer: handlers?.find((i) => i.cell?.[0] === rowIndex && i.cell?.[1] === columnIndex),
            darkRow: stripedRows && !(rowIndex % 2),
            noEdit: !isEditMode || (noEditingSettings?.columns && ~noEditingSettings.columns?.indexOf(columnIndex)),
            pointer: handlers && handlers?.find((i) => i.cell?.[0] === rowIndex && i.cell?.[1] === columnIndex),
          }"
          :style="`padding: calc(${initGap} / 2 + ${additionalHeightFromSize}) ${initGap}`"
        >
          <TableCell
            :item="item"
            :types="types"
              :columns="columns"
            :column="columns[columnIndex]"
            :rowIndex="rowIndex"
            :columnIndex="columnIndex"
            :center="center"
              :editable="editable"
            :isEditMode="isEditMode"
            :noEditingSettings="noEditingSettings?.cells"
            :fontSize="fontSize"
            :initGap="initGap"
            :knobWidth="knobWidth"
              :noEdit="!!handlers?.find((i) => i.cell?.[0] === rowIndex && i.cell?.[1] === columnIndex)"
            :noEdit="
              handlers ? !!handlers?.find((i) => i.cell?.[0] === rowIndex && i.cell?.[1] === columnIndex) : false
            "
            :theme="theme"
            @updateData="updateData"
          />
        </td>
      </tr>
    </tbody>
  </table>
  <div class="paginatorContainer">
    <section v-if="editable" class="editMenu">
      <p class="editText">Edit mode:</p>
      <ToggleSwitch v-model="isEditMode" negativeTheme="red" />
    </section>
    <Paginator
      v-show="paginator"
      v-model="currentPage"
      v-model:current="currentPage"
      v-model:itemsPerPage="itemsPerPage"
      :theme="theme"
      :total="data.length"
      :itemsPerPageOptions="[2, 5]"
      v-bind="paginatorOptions"
      class="paginator"
    />
@@ -194,10 +213,35 @@ const updateData = (newValue: Ref<unknown>, rowIndex: number, columnIndex: numbe
<style scoped>
.table {
  border-collapse: collapse;
}
table * {
  position: relative;
  * {
    font-size: v-bind(fontSize);
  }
}
.table::after {
  content: '';
  position: absolute;
  top: 100%;
  z-index: -1;
  width: 100%;
  height: v-bind(paginatorContainerHeight);
  background-color: v-bind(themeColor);
}
.editMenu {
  display: flex;
  align-items: center;
  gap: 10px;
  width: max-content;
  padding: 10px;
}
.editText {
  color: v-bind(color);
}
.paginatorContainer {
  height: 50px;
  display: flex;
  align-items: center;
}
tr {
  position: relative;
}
@@ -216,15 +260,14 @@ tr::after {
}
.cell {
  display: flex;
  width: 100%;
  height: 100%;
  margin: 0 auto;
}
.cellCenter {
  justify-content: center;
  align-items: center;
}
.paginator {
  display: block;
  margin: 0 auto;
}
.leftBorder {
+73 −40
Original line number Diff line number Diff line
@@ -6,19 +6,22 @@ import Select from '@components/Select/Select.vue';
import Rating from '@components/Rating/Rating.vue';
import ProgressBar from '@components/ProgressBar/ProgressBar.vue';
import Knob from '@components/Knob/Knob.vue';
import type { TThemeColor } from '@interfaces/common';

interface IProps {
  item: unknown;
  types: (TTableColumnType | undefined)[];
  columns: ITableColumn[];
  column: ITableColumn;
  rowIndex: number;
  columnIndex: number;
  center: boolean | undefined;
  editable: boolean;
  isEditMode: boolean;
  fontSize: string;
  initGap: string;
  knobWidth: string;
  noEditingSettings: [number, number][] | undefined;
  noEdit: boolean;
  theme: TThemeColor;
}
defineProps<IProps>();
defineEmits(['updateData']);
@@ -26,14 +29,16 @@ defineEmits(['updateData']);

<template>
  <div
    :style="`width: calc(${column.width ?? 'auto'} - 2 * ${initGap})`"
    :class="[
      'cell',
      {
        cellCenter: center,
        noEdit:
          noEdit ||
          !editable ||
          noEditingSettings?.find((i: [number, number]) => i[0] === rowIndex && i[1] === columnIndex),
          !isEditMode ||
          (noEditingSettings &&
            noEditingSettings?.find((i: [number, number]) => i[0] === rowIndex && i[1] === columnIndex)),
      },
    ]"
  >
@@ -43,11 +48,12 @@ defineEmits(['updateData']);
      @input="(event) => $emit('updateData', event.target, rowIndex, columnIndex)"
      :id="`${rowIndex}-${columnIndex}`"
      :type="types[columnIndex]"
      :style="`display: inline; width: 100%; text-align: ${center ? 'center' : 'auto'}`"
      :style="`width: 100%; text-align: ${center ? 'center' : 'auto'}`"
    />
    <div v-else-if="isEditMode">
      <Checkbox
      v-else-if="types[columnIndex] === 'checkbox'"
      v-bind="filterCheckboxProps(columns[columnIndex].options)"
        v-if="types[columnIndex] === 'checkbox'"
        v-bind="filterCheckboxProps(column.options)"
        :active="item as boolean"
        @update="$emit('updateData', $event, rowIndex, columnIndex)"
      />
@@ -55,32 +61,59 @@ defineEmits(['updateData']);
        v-else-if="types[columnIndex] === 'select'"
        noBorder
        noSelectedBackground
      v-bind="filterSelectProps(columns[columnIndex].options)"
        v-bind="filterSelectProps(column.options)"
        width="150px"
        :theme="theme"
        :selected="item as string"
        @update="$emit('updateData', $event, rowIndex, columnIndex)"
      />
      <Rating
        v-else-if="types[columnIndex] === 'rating'"
      v-bind="columns[columnIndex].options"
        v-bind="column.options"
        :value="item as number"
        @update="$emit('updateData', $event, rowIndex, columnIndex)"
      />
      <ProgressBar
        v-else-if="types[columnIndex] === 'progressBar'"
      v-bind="columns[columnIndex].options"
        v-bind="column.options"
        :value="item as number"
        @update="$emit('updateData', $event, rowIndex, columnIndex)"
      />
      <Knob
        v-else-if="types[columnIndex] === 'knob'"
      v-bind="columns[columnIndex].options"
        v-bind="column.options"
        :value="item as number"
        :width="knobWidth"
        :fontSize="fontSize"
        @update="$emit('updateData', $event, rowIndex, columnIndex)"
      />
    </div>
    <div v-else>
      <Checkbox
        v-if="types[columnIndex] === 'checkbox'"
        v-bind="filterCheckboxProps(column.options)"
        :active="item as boolean"
      />
      <Select
        v-else-if="types[columnIndex] === 'select'"
        noBorder
        noSelectedBackground
        v-bind="filterSelectProps(column.options)"
        width="150px"
        :theme="theme"
        :selected="item as string"
      />
      <Rating v-else-if="types[columnIndex] === 'rating'" v-bind="column.options" :value="item as number" />
      <ProgressBar v-else-if="types[columnIndex] === 'progressBar'" v-bind="column.options" :value="item as number" />
      <Knob
        v-else-if="types[columnIndex] === 'knob'"
        v-bind="column.options"
        :value="item as number"
        :width="knobWidth"
        :fontSize="fontSize"
      />
    </div>
  </div>
</template>

<style scoped>
Loading