mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 01:25:55 +02:00
added support for configuring columns in part table which are enabled by default as well as their order.
This commit is contained in:
parent
39009a71d5
commit
9d54001f89
5 changed files with 419 additions and 296 deletions
|
@ -35,7 +35,7 @@
|
||||||
PassEnv DEMO_MODE NO_URL_REWRITE_AVAILABLE FIXER_API_KEY BANNER
|
PassEnv DEMO_MODE NO_URL_REWRITE_AVAILABLE FIXER_API_KEY BANNER
|
||||||
# In old version the SAML sp private key env, was wrongly named SAMLP_SP_PRIVATE_KEY, keep it for backward compatibility
|
# In old version the SAML sp private key env, was wrongly named SAMLP_SP_PRIVATE_KEY, keep it for backward compatibility
|
||||||
PassEnv SAML_ENABLED SAML_ROLE_MAPPING SAML_UPDATE_GROUP_ON_LOGIN SAML_IDP_ENTITY_ID SAML_IDP_SINGLE_SIGN_ON_SERVICE SAML_IDP_SINGLE_LOGOUT_SERVICE SAML_IDP_X509_CERT SAML_SP_ENTITY_ID SAML_SP_X509_CERT SAML_SP_PRIVATE_KEY SAMLP_SP_PRIVATE_KEY
|
PassEnv SAML_ENABLED SAML_ROLE_MAPPING SAML_UPDATE_GROUP_ON_LOGIN SAML_IDP_ENTITY_ID SAML_IDP_SINGLE_SIGN_ON_SERVICE SAML_IDP_SINGLE_LOGOUT_SERVICE SAML_IDP_X509_CERT SAML_SP_ENTITY_ID SAML_SP_X509_CERT SAML_SP_PRIVATE_KEY SAMLP_SP_PRIVATE_KEY
|
||||||
PassEnv TABLE_DEFAULT_PAGE_SIZE
|
PassEnv TABLE_DEFAULT_PAGE_SIZE TABLE_PART_DEFAULT_COLUMNS
|
||||||
|
|
||||||
PassEnv PROVIDER_DIGIKEY_CLIENT_ID PROVIDER_DIGIKEY_SECRET PROVIDER_DIGIKEY_CURRENCY PROVIDER_DIGIKEY_LANGUAGE PROVIDER_DIGIKEY_COUNTRY
|
PassEnv PROVIDER_DIGIKEY_CLIENT_ID PROVIDER_DIGIKEY_SECRET PROVIDER_DIGIKEY_CURRENCY PROVIDER_DIGIKEY_LANGUAGE PROVIDER_DIGIKEY_COUNTRY
|
||||||
PassEnv PROVIDER_ELEMENT14_KEY PROVIDER_ELEMENT14_STORE_ID
|
PassEnv PROVIDER_ELEMENT14_KEY PROVIDER_ELEMENT14_STORE_ID
|
||||||
|
|
|
@ -54,6 +54,7 @@ parameters:
|
||||||
# Table settings
|
# Table settings
|
||||||
######################################################################################################################
|
######################################################################################################################
|
||||||
partdb.table.default_page_size: '%env(int:TABLE_DEFAULT_PAGE_SIZE)%' # The default number of entries shown per page in tables
|
partdb.table.default_page_size: '%env(int:TABLE_DEFAULT_PAGE_SIZE)%' # The default number of entries shown per page in tables
|
||||||
|
partdb.table.default_part_columns: '%env(trim:string:TABLE_PART_DEFAULT_COLUMNS)%' # The default columns in part tables and their order
|
||||||
|
|
||||||
######################################################################################################################
|
######################################################################################################################
|
||||||
# Sidebar
|
# Sidebar
|
||||||
|
|
|
@ -211,6 +211,12 @@ services:
|
||||||
arguments:
|
arguments:
|
||||||
$saml_enabled: '%partdb.saml.enabled%'
|
$saml_enabled: '%partdb.saml.enabled%'
|
||||||
|
|
||||||
|
####################################################################################################################
|
||||||
|
# Table settings
|
||||||
|
####################################################################################################################
|
||||||
|
App\DataTables\PartsDataTable:
|
||||||
|
arguments:
|
||||||
|
$default_part_columns: '%partdb.table.default_part_columns%'
|
||||||
|
|
||||||
####################################################################################################################
|
####################################################################################################################
|
||||||
# Label system
|
# Label system
|
||||||
|
|
|
@ -46,6 +46,7 @@ The following configuration options can only be changed by the server administra
|
||||||
|
|
||||||
### Table related settings
|
### Table related settings
|
||||||
* `TABLE_DEFAULT_PAGE_SIZE`: The default page size for tables. This is the number of rows which are shown per page. Set to `-1` to disable pagination and show all rows at once.
|
* `TABLE_DEFAULT_PAGE_SIZE`: The default page size for tables. This is the number of rows which are shown per page. Set to `-1` to disable pagination and show all rows at once.
|
||||||
|
* `TABLE_PART_DEFAULT_COLUMNS`: The default columns in part tables loading table for first time. Also specify default order of the columns. Specify as comma separated string. Available columns are: `name`, `id`, `ipn`, `description`, `category`, `footprint`, `manufacturer`, `storelocation`, `amount`, `minamount`, `partUnit`, `addedDate`, `lastModified`, `needs_review`, `favorite`, `manufacturing_status`, `manufacturer_product_number`, `mass`, `tags`, `attachments`, `edit`.
|
||||||
|
|
||||||
### History/Eventlog related settings
|
### History/Eventlog related settings
|
||||||
The following options are used to configure, which (and how much) data is written to the system log:
|
The following options are used to configure, which (and how much) data is written to the system log:
|
||||||
|
|
|
@ -33,6 +33,7 @@ use Doctrine\ORM\Query;
|
||||||
use Doctrine\ORM\Tools\Pagination\Paginator;
|
use Doctrine\ORM\Tools\Pagination\Paginator;
|
||||||
use Omines\DataTablesBundle\Adapter\Doctrine\Event\ORMAdapterQueryEvent;
|
use Omines\DataTablesBundle\Adapter\Doctrine\Event\ORMAdapterQueryEvent;
|
||||||
use Omines\DataTablesBundle\Adapter\Doctrine\ORMAdapterEvents;
|
use Omines\DataTablesBundle\Adapter\Doctrine\ORMAdapterEvents;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
use Symfony\Bundle\SecurityBundle\Security;
|
use Symfony\Bundle\SecurityBundle\Security;
|
||||||
use App\Entity\Parts\Storelocation;
|
use App\Entity\Parts\Storelocation;
|
||||||
use App\DataTables\Column\EntityColumn;
|
use App\DataTables\Column\EntityColumn;
|
||||||
|
@ -62,7 +63,7 @@ use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
final class PartsDataTable implements DataTableTypeInterface
|
final class PartsDataTable implements DataTableTypeInterface
|
||||||
{
|
{
|
||||||
public function __construct(private readonly EntityURLGenerator $urlGenerator, private readonly TranslatorInterface $translator, private readonly AmountFormatter $amountFormatter, private readonly PartDataTableHelper $partDataTableHelper, private readonly Security $security)
|
public function __construct(private readonly EntityURLGenerator $urlGenerator, private readonly TranslatorInterface $translator, private readonly AmountFormatter $amountFormatter, private readonly PartDataTableHelper $partDataTableHelper, private readonly Security $security, private readonly string $default_part_columns, protected LoggerInterface $logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,44 +104,73 @@ final class PartsDataTable implements DataTableTypeInterface
|
||||||
'label' => '',
|
'label' => '',
|
||||||
'className' => 'no-colvis',
|
'className' => 'no-colvis',
|
||||||
'render' => fn($value, Part $context) => $this->partDataTableHelper->renderPicture($context),
|
'render' => fn($value, Part $context) => $this->partDataTableHelper->renderPicture($context),
|
||||||
])
|
|
||||||
->add('name', TextColumn::class, [
|
|
||||||
'label' => $this->translator->trans('part.table.name'),
|
|
||||||
'render' => fn($value, Part $context) => $this->partDataTableHelper->renderName($context),
|
|
||||||
])
|
|
||||||
->add('id', TextColumn::class, [
|
|
||||||
'label' => $this->translator->trans('part.table.id'),
|
|
||||||
'visible' => false,
|
|
||||||
])
|
|
||||||
->add('ipn', TextColumn::class, [
|
|
||||||
'label' => $this->translator->trans('part.table.ipn'),
|
|
||||||
'visible' => false,
|
|
||||||
])
|
|
||||||
->add('description', MarkdownColumn::class, [
|
|
||||||
'label' => $this->translator->trans('part.table.description'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
// internal array of $dataTable->add(...) parameters. Parameters will be later passed to the method
|
||||||
|
// after sorting columns according to TABLE_PART_DEFAULT_COLUMNS option.
|
||||||
|
$columns = [];
|
||||||
|
|
||||||
|
$columns['name'] = [
|
||||||
|
'name', TextColumn::class,
|
||||||
|
[
|
||||||
|
'label' => $this->translator->trans('part.table.name'),
|
||||||
|
'render' => fn($value, Part $context) => $this->partDataTableHelper->renderName($context),
|
||||||
|
]
|
||||||
|
];
|
||||||
|
$columns['id'] = [
|
||||||
|
'id', TextColumn::class,
|
||||||
|
[
|
||||||
|
'label' => $this->translator->trans('part.table.id'),
|
||||||
|
'visible' => false,
|
||||||
|
]
|
||||||
|
];
|
||||||
|
$columns['ipn'] = [
|
||||||
|
'ipn', TextColumn::class,
|
||||||
|
[
|
||||||
|
'label' => $this->translator->trans('part.table.ipn'),
|
||||||
|
'visible' => false,
|
||||||
|
]
|
||||||
|
];
|
||||||
|
$columns['description'] = [
|
||||||
|
'description', MarkdownColumn::class,
|
||||||
|
[
|
||||||
|
'label' => $this->translator->trans('part.table.description'),
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
if ($this->security->isGranted('@categories.read')) {
|
if ($this->security->isGranted('@categories.read')) {
|
||||||
$dataTable->add('category', EntityColumn::class, [
|
$columns['category'] = [
|
||||||
|
'category', EntityColumn::class,
|
||||||
|
[
|
||||||
'label' => $this->translator->trans('part.table.category'),
|
'label' => $this->translator->trans('part.table.category'),
|
||||||
'property' => 'category',
|
'property' => 'category',
|
||||||
]);
|
]
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->security->isGranted('@footprints.read')) {
|
if ($this->security->isGranted('@footprints.read')) {
|
||||||
$dataTable->add('footprint', EntityColumn::class, [
|
$columns['footprint'] = [
|
||||||
|
'footprint', EntityColumn::class,
|
||||||
|
[
|
||||||
'property' => 'footprint',
|
'property' => 'footprint',
|
||||||
'label' => $this->translator->trans('part.table.footprint'),
|
'label' => $this->translator->trans('part.table.footprint'),
|
||||||
]);
|
]
|
||||||
|
];
|
||||||
}
|
}
|
||||||
if ($this->security->isGranted('@manufacturers.read')) {
|
if ($this->security->isGranted('@manufacturers.read')) {
|
||||||
$dataTable->add('manufacturer', EntityColumn::class, [
|
$columns['manufacturer'] = [
|
||||||
|
'manufacturer', EntityColumn::class,
|
||||||
|
[
|
||||||
'property' => 'manufacturer',
|
'property' => 'manufacturer',
|
||||||
'label' => $this->translator->trans('part.table.manufacturer'),
|
'label' => $this->translator->trans('part.table.manufacturer'),
|
||||||
]);
|
]
|
||||||
|
];
|
||||||
}
|
}
|
||||||
if ($this->security->isGranted('@storelocations.read')) {
|
if ($this->security->isGranted('@storelocations.read')) {
|
||||||
$dataTable->add('storelocation', TextColumn::class, [
|
$columns['storelocation'] = [
|
||||||
|
'storelocation', TextColumn::class,
|
||||||
|
[
|
||||||
'label' => $this->translator->trans('part.table.storeLocations'),
|
'label' => $this->translator->trans('part.table.storeLocations'),
|
||||||
'orderField' => 'storelocations.name',
|
'orderField' => 'storelocations.name',
|
||||||
'render' => function ($value, Part $context): string {
|
'render' => function ($value, Part $context): string {
|
||||||
|
@ -160,10 +190,13 @@ final class PartsDataTable implements DataTableTypeInterface
|
||||||
|
|
||||||
return implode('<br>', $tmp);
|
return implode('<br>', $tmp);
|
||||||
},
|
},
|
||||||
]);
|
]
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$dataTable->add('amount', TextColumn::class, [
|
$columns['amount'] = [
|
||||||
|
'amount', TextColumn::class,
|
||||||
|
[
|
||||||
'label' => $this->translator->trans('part.table.amount'),
|
'label' => $this->translator->trans('part.table.amount'),
|
||||||
'render' => function ($value, Part $context) {
|
'render' => function ($value, Part $context) {
|
||||||
$amount = $context->getAmountSum();
|
$amount = $context->getAmountSum();
|
||||||
|
@ -203,38 +236,59 @@ final class PartsDataTable implements DataTableTypeInterface
|
||||||
return $ret;
|
return $ret;
|
||||||
},
|
},
|
||||||
'orderField' => 'amountSum'
|
'orderField' => 'amountSum'
|
||||||
])
|
]
|
||||||
->add('minamount', TextColumn::class, [
|
];
|
||||||
|
$columns['minamount'] = [
|
||||||
|
'minamount', TextColumn::class,
|
||||||
|
[
|
||||||
'label' => $this->translator->trans('part.table.minamount'),
|
'label' => $this->translator->trans('part.table.minamount'),
|
||||||
'visible' => false,
|
'visible' => false,
|
||||||
'render' => fn($value, Part $context): string => htmlspecialchars($this->amountFormatter->format($value, $context->getPartUnit())),
|
'render' => fn($value, Part $context): string => htmlspecialchars($this->amountFormatter->format($value, $context->getPartUnit())),
|
||||||
]);
|
]
|
||||||
|
];
|
||||||
|
|
||||||
if ($this->security->isGranted('@footprints.read')) {
|
if ($this->security->isGranted('@footprints.read')) {
|
||||||
$dataTable->add('partUnit', TextColumn::class, [
|
$columns['partUnit'] = [
|
||||||
|
'partUnit', TextColumn::class,
|
||||||
|
[
|
||||||
'field' => 'partUnit.name',
|
'field' => 'partUnit.name',
|
||||||
'label' => $this->translator->trans('part.table.partUnit'),
|
'label' => $this->translator->trans('part.table.partUnit'),
|
||||||
'visible' => false,
|
'visible' => false,
|
||||||
]);
|
]
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$dataTable->add('addedDate', LocaleDateTimeColumn::class, [
|
$columns['addedDate'] = [
|
||||||
|
'addedDate', LocaleDateTimeColumn::class,
|
||||||
|
[
|
||||||
'label' => $this->translator->trans('part.table.addedDate'),
|
'label' => $this->translator->trans('part.table.addedDate'),
|
||||||
'visible' => false,
|
'visible' => false,
|
||||||
])
|
]
|
||||||
->add('lastModified', LocaleDateTimeColumn::class, [
|
];
|
||||||
|
$columns['lastModified'] = [
|
||||||
|
'lastModified', LocaleDateTimeColumn::class,
|
||||||
|
[
|
||||||
'label' => $this->translator->trans('part.table.lastModified'),
|
'label' => $this->translator->trans('part.table.lastModified'),
|
||||||
'visible' => false,
|
'visible' => false,
|
||||||
])
|
]
|
||||||
->add('needs_review', PrettyBoolColumn::class, [
|
];
|
||||||
|
$columns['needs_review'] = [
|
||||||
|
'needs_review', PrettyBoolColumn::class,
|
||||||
|
[
|
||||||
'label' => $this->translator->trans('part.table.needsReview'),
|
'label' => $this->translator->trans('part.table.needsReview'),
|
||||||
'visible' => false,
|
'visible' => false,
|
||||||
])
|
]
|
||||||
->add('favorite', PrettyBoolColumn::class, [
|
];
|
||||||
|
$columns['favorite'] = [
|
||||||
|
'favorite', PrettyBoolColumn::class,
|
||||||
|
[
|
||||||
'label' => $this->translator->trans('part.table.favorite'),
|
'label' => $this->translator->trans('part.table.favorite'),
|
||||||
'visible' => false,
|
'visible' => false,
|
||||||
])
|
]
|
||||||
->add('manufacturing_status', EnumColumn::class, [
|
];
|
||||||
|
$columns['manufacturing_status'] = [
|
||||||
|
'manufacturing_status', EnumColumn::class,
|
||||||
|
[
|
||||||
'label' => $this->translator->trans('part.table.manufacturingStatus'),
|
'label' => $this->translator->trans('part.table.manufacturingStatus'),
|
||||||
'visible' => false,
|
'visible' => false,
|
||||||
'class' => ManufacturingStatus::class,
|
'class' => ManufacturingStatus::class,
|
||||||
|
@ -245,33 +299,94 @@ final class PartsDataTable implements DataTableTypeInterface
|
||||||
|
|
||||||
return $this->translator->trans($status->toTranslationKey());
|
return $this->translator->trans($status->toTranslationKey());
|
||||||
} ,
|
} ,
|
||||||
])
|
]
|
||||||
->add('manufacturer_product_number', TextColumn::class, [
|
];
|
||||||
|
$columns['manufacturer_product_number'] = [
|
||||||
|
'manufacturer_product_number', TextColumn::class,
|
||||||
|
[
|
||||||
'label' => $this->translator->trans('part.table.mpn'),
|
'label' => $this->translator->trans('part.table.mpn'),
|
||||||
'visible' => false,
|
'visible' => false,
|
||||||
])
|
]
|
||||||
->add('mass', SIUnitNumberColumn::class, [
|
];
|
||||||
|
$columns['mass'] = [
|
||||||
|
'mass', SIUnitNumberColumn::class,
|
||||||
|
[
|
||||||
'label' => $this->translator->trans('part.table.mass'),
|
'label' => $this->translator->trans('part.table.mass'),
|
||||||
'visible' => false,
|
'visible' => false,
|
||||||
'unit' => 'g'
|
'unit' => 'g'
|
||||||
])
|
]
|
||||||
->add('tags', TagsColumn::class, [
|
];
|
||||||
|
$columns['tags'] = [
|
||||||
|
'tags', TagsColumn::class,
|
||||||
|
[
|
||||||
'label' => $this->translator->trans('part.table.tags'),
|
'label' => $this->translator->trans('part.table.tags'),
|
||||||
'visible' => false,
|
'visible' => false,
|
||||||
])
|
]
|
||||||
->add('attachments', PartAttachmentsColumn::class, [
|
];
|
||||||
|
$columns['attachments'] = [
|
||||||
|
'attachments', PartAttachmentsColumn::class,
|
||||||
|
[
|
||||||
'label' => $this->translator->trans('part.table.attachments'),
|
'label' => $this->translator->trans('part.table.attachments'),
|
||||||
'visible' => false,
|
'visible' => false,
|
||||||
])
|
]
|
||||||
->add('edit', IconLinkColumn::class, [
|
];
|
||||||
|
$columns['edit'] = [
|
||||||
|
'edit', IconLinkColumn::class,
|
||||||
|
[
|
||||||
'label' => $this->translator->trans('part.table.edit'),
|
'label' => $this->translator->trans('part.table.edit'),
|
||||||
'visible' => false,
|
'visible' => false,
|
||||||
'href' => fn($value, Part $context) => $this->urlGenerator->editURL($context),
|
'href' => fn($value, Part $context) => $this->urlGenerator->editURL($context),
|
||||||
'disabled' => fn($value, Part $context) => !$this->security->isGranted('edit', $context),
|
'disabled' => fn($value, Part $context) => !$this->security->isGranted('edit', $context),
|
||||||
'title' => $this->translator->trans('part.table.edit.title'),
|
'title' => $this->translator->trans('part.table.edit.title'),
|
||||||
])
|
]
|
||||||
|
];
|
||||||
|
|
||||||
->addOrderBy('name')
|
$visible_columns_ids = array_map("trim", explode(",", $this->default_part_columns));
|
||||||
|
$allowed_configurable_columns_ids = ["name", "id", "ipn", "description", "category", "footprint", "manufacturer",
|
||||||
|
"storelocation", "amount", "minamount", "partUnit", "addedDate", "lastModified", "needs_review", "favorite",
|
||||||
|
"manufacturing_status", "manufacturer_product_number", "mass", "tags", "attachments", "edit"
|
||||||
|
];
|
||||||
|
$processed_columns = [];
|
||||||
|
|
||||||
|
foreach ($visible_columns_ids as $col_id) {
|
||||||
|
if (!in_array($col_id, $allowed_configurable_columns_ids) || !isset($columns[$col_id])) {
|
||||||
|
$this->logger->warning("Configuration option TABLE_PART_DEFAULT_COLUMNS specify invalid column '$col_id'. Collumn is skipped.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($col_id, $processed_columns)) {
|
||||||
|
$this->logger->warning("Configuration option TABLE_PART_DEFAULT_COLUMNS specify column '$col_id' multiple time. Only first occurence is used.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$options = [];
|
||||||
|
if (count($columns[$col_id]) >= 3) {
|
||||||
|
$options = $columns[$col_id][2];
|
||||||
|
}
|
||||||
|
$options["visible"] = true;
|
||||||
|
$dataTable->add($col_id, $columns[$col_id][1], $options);
|
||||||
|
|
||||||
|
$processed_columns[] = $col_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add remaining non-visible columns
|
||||||
|
foreach ($allowed_configurable_columns_ids as $col_id) {
|
||||||
|
if (in_array($col_id, $processed_columns)) {
|
||||||
|
// column already processed
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$options = [];
|
||||||
|
if (count($columns[$col_id]) >= 3) {
|
||||||
|
$options = $columns[$col_id][2];
|
||||||
|
}
|
||||||
|
$options["visible"] = false;
|
||||||
|
$dataTable->add($col_id, $columns[$col_id][1], $options);
|
||||||
|
|
||||||
|
$processed_columns[] = $col_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dataTable->addOrderBy('name')
|
||||||
->createAdapter(TwoStepORMAdapater::class, [
|
->createAdapter(TwoStepORMAdapater::class, [
|
||||||
'filter_query' => $this->getFilterQuery(...),
|
'filter_query' => $this->getFilterQuery(...),
|
||||||
'detail_query' => $this->getDetailQuery(...),
|
'detail_query' => $this->getDetailQuery(...),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue