Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add VDataIterator to labs #16839

Merged
merged 19 commits into from
May 19, 2023
Merged

feat: add VDataIterator to labs #16839

merged 19 commits into from
May 19, 2023

Conversation

nekosaur
Copy link
Member

@nekosaur nekosaur commented Mar 5, 2023

Description

adds data-iterator to labs

closes #13478

Markup:

<template>
  <v-data-iterator
    v-model="selected"
    :items="items"
    :items-per-page="4"
    :sort-by="sortBy"
    :search="search"
    item-value="name"
    return-object
  >
    <template v-slot:header>
      <v-toolbar
        dark
        color="blue darken-3"
        class="mb-1"
      >
        <v-text-field
          v-model="search"
          clearable
          hide-details
          prepend-inner-icon="mdi-magnify"
          label="Search"
          variant="solo"
        ></v-text-field>
        <v-spacer></v-spacer>
        <v-select
          v-model="sortKey"
          flat
          solo-inverted
          hide-details
          :items="keys"
          prepend-inner-icon="mdi-magnify"
          label="Sort by"
        ></v-select>
        <v-spacer></v-spacer>
        <v-btn-toggle
          v-model="sortOrder"
          mandatory
        >
          <v-btn
            size="large"
            depressed
            color="blue"
            value="asc"
          >
            <v-icon>mdi-arrow-up</v-icon>
          </v-btn>
          <v-btn
            size="large"
            depressed
            color="blue"
            value="desc"
          >
            <v-icon>mdi-arrow-down</v-icon>
          </v-btn>
        </v-btn-toggle>
      </v-toolbar>
    </template>

    <template v-slot:default="{ items, isSelected, toggleSelect }">
      <v-row>
        <v-col
          v-for="item in items"
          :key="item.raw.name"
          cols="12"
          sm="6"
          md="4"
          lg="3"
        >
          <v-card class="fill-height">
            <v-card-title class="subheading font-weight-bold d-flex align-center justify-space-between">
              {{ item.raw.name }}
              <v-checkbox-btn :model-value="isSelected(item)" @click="toggleSelect(item)"></v-checkbox-btn>
            </v-card-title>

            <v-divider></v-divider>

            <v-list density="compact">
              <v-list-item title="Calories" :subtitle="String(item.raw.calories)"></v-list-item>
              <v-list-item title="Fat" :subtitle="String(item.raw.fat)"></v-list-item>
              <v-list-item title="Carbs" :subtitle="String(item.raw.carbs)"></v-list-item>
              <v-list-item title="Protein" :subtitle="String(item.raw.protein)"></v-list-item>
              <v-list-item title="Sodium" :subtitle="String(item.raw.sodium)"></v-list-item>
              <v-list-item title="Calcium" :subtitle="String(item.raw.calcium)"></v-list-item>
              <v-list-item title="Iron" :subtitle="String(item.raw.iron)"></v-list-item>
            </v-list>
          </v-card>
        </v-col>
      </v-row>
    </template>

    <template v-slot:footer="{ prevPage, nextPage, pageCount, page, setItemsPerPage, itemsPerPage }">
      <div class="d-flex align-center justify-space-around pa-4">
        <span class="grey--text">Items per page</span>
        <v-menu offset-y>
          <template v-slot:activator="{ props }">
            <v-btn
              dark
              text
              color="primary"
              class="ml-2"
              v-bind="props"
            >
              {{ itemsPerPage }}
              <v-icon>mdi-chevron-down</v-icon>
            </v-btn>
          </template>
          <v-list>
            <v-list-item
              v-for="(number, index) in itemsPerPageArray"
              :key="index"
              @click="setItemsPerPage(number)"
            >
              <v-list-item-title>{{ number }}</v-list-item-title>
            </v-list-item>
          </v-list>
        </v-menu>

        <v-spacer></v-spacer>

        <span
          class="mr-4
          grey--text"
        >
          Page {{ page }} of {{ pageCount }}
        </span>
        <v-btn
          fab
          dark
          color="blue darken-3"
          class="mr-1"
          @click="prevPage"
        >
          <v-icon>mdi-chevron-left</v-icon>
        </v-btn>
        <v-btn
          fab
          dark
          color="blue darken-3"
          class="ml-1"
          @click="nextPage"
        >
          <v-icon>mdi-chevron-right</v-icon>
        </v-btn>
      </div>
    </template>
  </v-data-iterator>
  <pre>{{ selected }}</pre>
</template>

<script>
  export default {
    data: () => ({
      selected: [],
      itemsPerPageArray: [4, 8, 12],
      search: '',
      filter: {},
      sortKey: 'name',
      sortOrder: 'asc',
      keys: [
        'name',
        'calories',
        'fat',
        'carbs',
        'protein',
        'sodium',
        'calcium',
        'iron',
      ],
      items: [
        {
          name: 'Frozen Yogurt',
          calories: 159,
          fat: 6.0,
          carbs: 24,
          protein: 4.0,
          sodium: 87,
          calcium: '14%',
          iron: '1%',
        },
        {
          name: 'Ice cream sandwich',
          calories: 237,
          fat: 9.0,
          carbs: 37,
          protein: 4.3,
          sodium: 129,
          calcium: '8%',
          iron: '1%',
        },
        {
          name: 'Eclair',
          calories: 262,
          fat: 16.0,
          carbs: 23,
          protein: 6.0,
          sodium: 337,
          calcium: '6%',
          iron: '7%',
        },
        {
          name: 'Cupcake',
          calories: 305,
          fat: 3.7,
          carbs: 67,
          protein: 4.3,
          sodium: 413,
          calcium: '3%',
          iron: '8%',
        },
        {
          name: 'Gingerbread',
          calories: 356,
          fat: 16.0,
          carbs: 49,
          protein: 3.9,
          sodium: 327,
          calcium: '7%',
          iron: '16%',
        },
        {
          name: 'Jelly bean',
          calories: 375,
          fat: 0.0,
          carbs: 94,
          protein: 0.0,
          sodium: 50,
          calcium: '0%',
          iron: '0%',
        },
        {
          name: 'Lollipop',
          calories: 392,
          fat: 0.2,
          carbs: 98,
          protein: 0,
          sodium: 38,
          calcium: '0%',
          iron: '2%',
        },
        {
          name: 'Honeycomb',
          calories: 408,
          fat: 3.2,
          carbs: 87,
          protein: 6.5,
          sodium: 562,
          calcium: '0%',
          iron: '45%',
        },
        {
          name: 'Donut',
          calories: 452,
          fat: 25.0,
          carbs: 51,
          protein: 4.9,
          sodium: 326,
          calcium: '2%',
          iron: '22%',
        },
        {
          name: 'KitKat',
          calories: 518,
          fat: 26.0,
          carbs: 65,
          protein: 7,
          sodium: 54,
          calcium: '12%',
          iron: '6%',
        },
      ],
    }),
    computed: {
      filteredKeys () {
        return this.keys.filter(key => key !== 'Name')
      },
      sortBy () {
        return [{
          key: this.sortKey,
          order: this.sortOrder,
        }]
      },
    },
  }
</script>

@nekosaur
Copy link
Member Author

Made some effort to not reuse InternalItem since it's not applicable everywhere and we have a number of variants.

InternalItem (now ListItem) has title, value, props, children
DataTableItem has value, columns
DataIteratorItem has value

We still use useFilter for all of them, but added transform option to be able to specify which part of item is the "root" of the searchable object

@nekosaur nekosaur marked this pull request as ready for review May 13, 2023 20:58
@johnleider johnleider added T: feature A new feature C: VDataIterator VDataiterator labels May 14, 2023
@johnleider johnleider added this to the v3.x.x milestone May 14, 2023
johnleider
johnleider previously approved these changes May 17, 2023
results.forEach(({ index, matches }) => {
const item = transformedItems[index]
const item = originalItems[index]
filteredItems.value.push(item)
filteredMatches.value.set(item.value, matches)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is expecting InternalItem

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean

multiSort: Boolean,
mustSort: Boolean,
locale: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this take the global locale default value into account?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, yes. We should probably remove that prop and use locale composable instead. I don't think it's a good idea to have 3 different ways of setting the locale. Global + v-locale-provider using composable should be enough.

@KaelWD KaelWD modified the milestones: v3.x.x, v3.3.0 (Icarus) May 19, 2023
@KaelWD KaelWD changed the title feat: data-iterator feat: add VDataIterator to labs May 19, 2023
@KaelWD KaelWD merged commit 31a8f4d into dev May 19, 2023
18 checks passed
@KaelWD KaelWD deleted the feat/v3-data-iterator branch May 19, 2023 11:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: VDataIterator VDataiterator T: feature A new feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants