Adminbereich: wie modifiziere/erweitere ich Spalten von Entities für sw-entity-listing

Ich habe einen neuen Menüpunkt im Adminbereich ergänzt, der eine eigene Tabelle tabellarisch ausgeben soll. Dazu greife ich über ein repository auf die Tabelle zu (wie hier beschrieben Using the data handling - Shopware Developer) und gebe das dann über aus. Das funktioniert auch.
Ich möchte zum einen anstatt true/false Icons (Check/Cross) oder ähnliches anzeigen. Außerdem möchte ich eine neue Spalte („computed column“) ergänzen. Aktuell gibt es 2 Spalten startDate und endDate und die neue Spalte soll Duration heißen und die Differenz dazu sein, bspw. sollte dann sowas drin stehen wie „3h 41min“. Ich habe in der Doku nichts gefunden, wie sich das realisieren ließe.

import template from './abas-catalog-sync-list.html.twig';

const { Component, Data, Context } = Shopware;
const { Criteria } = Data;

Component.register('abas-catalog-sync-list', {
  template,

  inject: [
    'repositoryFactory',
  ],

  data() {
    return {
      result: undefined,
    };
  },

  metaInfo() {
    return {
      title: this.$createTitle(),
    };
  },

  computed: {
    abasSyncResultRepository() {
      return this.repositoryFactory.create('abas_sync_result');
    },

    columns() {
      return [{
        property: 'syncName',
        dataIndex: 'syncName',
        label: this.$tc('abas-catalog-sync.list.columns.syncName'),
        allowResize: true,
      }, {
        property: 'success',
        dataIndex: 'success',
        label: this.$tc('abas-catalog-sync.list.columns.success'),
        allowResize: true,
      }, {
        property: 'startDate',
        dataIndex: 'startDate',
        label: this.$tc('abas-catalog-sync.list.columns.startDate'),
        allowResize: true,
      }, {
        property: 'endDate',
        dataIndex: 'endDate',
        label: this.$tc('abas-catalog-sync.list.columns.endDate'),
        allowResize: true,
      }, {
        property: 'error',
        dataIndex: 'error',
        label: this.$tc('abas-catalog-sync.list.columns.error'),
        allowResize: true,
      }];
    },
  },

  created() {
    const criteria = new Criteria();
    criteria.addFilter(Criteria.equalsAny('abas_sync_result.syncName', ['CatalogSync', 'MediaSync']));
    criteria.addSorting(
      Criteria.sort('abas_sync_result.startDate', 'DESC'),
    );

    return this.abasSyncResultRepository
      .search(criteria, Context.api)
      .then((result) => {
        this.result = result;

        return result;
      });
  },
});
{% block abas_catalog_sync_list %}
    <sw-page class="abas-catalog-sync-list">
        <template slot="content">
            {% block abas_catalog_sync_list_content %}
                <sw-entity-listing
                    v-if="result"
                    :items="result"
                    :repository="abasSyncResultRepository"
                    :showSelection="true"
                    :columns="columns"
                    :allowDelete="true">
                </sw-entity-listing>
            {% endblock %}
        </template>
    </sw-page>
{% endblock %}

Die Tabelle sieht moment so aus:

Verstehe deine Frage nicht ganz. Du möchtest dem computed columns Array eine weitere Spalte hinzufügen? Falls ja, wieso machst du es dann nicht einfach, in dem du ein weiteres Spaltenobjekt dem Array hinzufügst?

{
        property: 'duration',
        dataIndex: 'duration',
        label: this.$tc('abas-catalog-sync.list.columns.duration'),
        allowResize: true,
      }

duration müsstest du dann dem result hinzufügen, wenn es nicht aus dem Repository kommt.

Im Store gibt es ein kostenloses TrackingNumber Plugin, da kannst du dich vermutlich daran orientieren.

Ich möchte eine Tabelle von MySQL tabellarisch ausgeben und die Ausgabe modifizieren und erweitern.
Da es bspw. „duration“ nicht als physische column gibt, habe ich es als „computed column“ bezeichnet (ggf. etwas irreführend, da es im Code auch columns innerhalb von computed gibt).
Wie ich in der Ausgabe-Tabelle eine neue Spalte hinzufüge ist offensichtlich bekannt, das habe ich bei den anderen ja auch hinbekommen. Ich weiß aber aktuell noch nicht, wie diese Ausgabe-Spalte mit Daten befülle.

Das result-Objekt ist Shopware-spezifisch, mit Proxies und. Co. Daher weiß ich nicht, ob und wie man das um „duration“ erweitern kann.

Ich habs jetzt nicht getestet. Denke aber das Rendern der Spalte muss im Twig Template erfolgen.

Innerhalb des sw-entity-listing das Template für „duration“ angeben, z. B.:

<template #column-duration="{ item }">
   {{ ausgabe von duration }}
</template>
2 „Gefällt mir“

Danke dir, damit funktioniert es.

Sollten andere über das gleiche/ähnliche Problem stolpern, so sieht der Code dann aus:

import template from './abas-catalog-sync-list.html.twig';

const { Component, Data, Context } = Shopware;
const { Criteria } = Data;

Component.register('abas-catalog-sync-list', {
  template,

  inject: [
    'repositoryFactory',
  ],

  data() {
    return {
      result: undefined,
    };
  },

  metaInfo() {
    return {
      title: this.$createTitle(),
    };
  },

  computed: {
    abasSyncResultRepository() {
      return this.repositoryFactory.create('abas_sync_result');
    },

    columns() {
      return [{
        property: 'syncName',
        dataIndex: 'syncName',
        label: this.$tc('abas-catalog-sync.list.columns.syncName'),
        allowResize: true,
      }, {
        property: 'success',
        dataIndex: 'success',
        label: this.$tc('abas-catalog-sync.list.columns.success'),
        allowResize: true,
      }, {
        property: 'startDate',
        dataIndex: 'startDate',
        label: this.$tc('abas-catalog-sync.list.columns.startDate'),
        allowResize: true,
      }, {
        property: 'endDate',
        dataIndex: 'endDate',
        label: this.$tc('abas-catalog-sync.list.columns.endDate'),
        allowResize: true,
      }, {
        property: 'duration',
        dataIndex: 'duration',
        label: this.$tc('abas-catalog-sync.list.columns.duration'),
        allowResize: true,
      }, {
        property: 'error',
        dataIndex: 'error',
        label: this.$tc('abas-catalog-sync.list.columns.error'),
        allowResize: true,
      }];
    },
  },

  created() {
    const criteria = new Criteria();
    criteria.addFilter(Criteria.equalsAny('abas_sync_result.syncName', ['CatalogSync', 'RecursiveCatalogSync', 'StockSync', 'MediaSync']));
    criteria.addSorting(
      Criteria.sort('abas_sync_result.startDate', 'DESC'),
    );

    return this.abasSyncResultRepository
      .search(criteria, Context.api)
      .then((result) => {
        this.result = result;

        return result;
      });
  },

  methods: {
    getDuration(item) {
      const startDate = new Date(item.startDate);
      const endDate = new Date(item.endDate);

      return endDate.getTime() - startDate.getTime();
    },
  },
});
{% block abas_catalog_sync_list %}
    <sw-page class="abas-catalog-sync-list">
        <template slot="content">
            {% block abas_catalog_sync_list_content %}
                <sw-entity-listing
                    v-if="result"
                    :items="result"
                    :repository="abasSyncResultRepository"
                    :showSelection="true"
                    :columns="columns"
                    :allowDelete="true">
                    <template #column-duration="{ item }">
                        {{ getDuration(item) }}
                    </template>
                </sw-entity-listing>
            {% endblock %}
        </template>
    </sw-page>
{% endblock %}