Skip to content

Commit 164f654

Browse files
committed
WIP
1 parent 985df0d commit 164f654

File tree

13 files changed

+160
-61
lines changed

13 files changed

+160
-61
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DoctrineMigrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Doctrine\Migrations\AbstractMigration;
9+
10+
/**
11+
* Auto-generated Migration: Please modify to your needs!
12+
*/
13+
final class Version20250923095101 extends AbstractMigration
14+
{
15+
public function getDescription(): string
16+
{
17+
return '';
18+
}
19+
20+
public function up(Schema $schema): void
21+
{
22+
// this up() migration is auto-generated, please modify it to your needs
23+
$this->addSql(<<<'SQL'
24+
ALTER TABLE asset_title_attribute ADD "target" SMALLINT NULL
25+
SQL);
26+
$this->addSql(<<<'SQL'
27+
UPDATE asset_title_attribute SET "target" = 1
28+
SQL);
29+
$this->addSql(<<<'SQL'
30+
ALTER TABLE asset_title_attribute ALTER COLUMN "target" SET NOT NULL
31+
SQL);
32+
}
33+
34+
public function down(Schema $schema): void
35+
{
36+
// this down() migration is auto-generated, please modify it to your needs
37+
$this->addSql(<<<'SQL'
38+
ALTER TABLE asset_title_attribute DROP "target"
39+
SQL);
40+
}
41+
}

databox/api/src/Asset/Attribute/AssetTitleResolver.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use App\Entity\Core\Asset;
99
use App\Entity\Core\AssetTitleAttribute;
1010
use App\Entity\Core\Attribute;
11+
use App\Model\AssetTypeEnum;
1112
use Doctrine\ORM\EntityManagerInterface;
1213
use Psr\Log\LoggerInterface;
1314

@@ -24,9 +25,14 @@ public function __construct(
2425

2526
public function resolveTitle(Asset $asset, AttributeIndex $attributesIndex, array $preferredLocales): Attribute|string|null
2627
{
28+
$target = $asset->isStory() ? AssetTypeEnum::Story : AssetTypeEnum::Asset;
2729
if (empty($asset->getTitle()) || $this->hasTitleOverride($asset->getWorkspaceId())) {
2830
$titleAttrs = $this->getTitleAttributes($asset->getWorkspaceId());
2931
foreach ($titleAttrs as $attrTitle) {
32+
if (!$attrTitle->isForTarget($target)) {
33+
continue;
34+
}
35+
3036
$attributeDefinition = $attrTitle->getDefinition();
3137
if ($attributeDefinition->isMultiple()) {
3238
$this->logger->warning(sprintf('Cannot use multiple attribute definition "%s" as title', $attributeDefinition->getId()));

databox/api/src/Controller/Admin/AssetTitleAttributeCrudController.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use EasyCorp\Bundle\EasyAdminBundle\Config\Filters;
1010
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
1111
use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField;
12+
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
1213
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField;
1314
use EasyCorp\Bundle\EasyAdminBundle\Filter\BooleanFilter;
1415
use EasyCorp\Bundle\EasyAdminBundle\Filter\EntityFilter;
@@ -46,6 +47,7 @@ public function configureFields(string $pageName): iterable
4647
yield AssociationField::new('definition');
4748
yield IntegerField::new('priority');
4849
yield BooleanField::new('overrides');
50+
yield ChoiceField::new('target');
4951

5052
}
5153
}

databox/api/src/Entity/Core/AssetTitleAttribute.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace App\Entity\Core;
66

77
use Alchemy\CoreBundle\Entity\AbstractUuidEntity;
8+
use App\Model\AssetTypeEnum;
89
use App\Validator\SameWorkspaceConstraint;
910
use Doctrine\DBAL\Types\Types;
1011
use Doctrine\ORM\Mapping as ORM;
@@ -26,6 +27,9 @@ class AssetTitleAttribute extends AbstractUuidEntity
2627
#[ORM\Column(type: Types::SMALLINT, nullable: false)]
2728
private int $priority = 0;
2829

30+
#[ORM\Column(type: Types::SMALLINT, nullable: false, enumType: AssetTypeEnum::class)]
31+
private AssetTypeEnum $target = AssetTypeEnum::Asset;
32+
2933
/**
3034
* Whether to override "title" attribute set on asset.
3135
*/
@@ -71,4 +75,19 @@ public function setOverrides(bool $overrides): void
7175
{
7276
$this->overrides = $overrides;
7377
}
78+
79+
public function getTarget(): AssetTypeEnum
80+
{
81+
return $this->target;
82+
}
83+
84+
public function isForTarget(AssetTypeEnum $target): bool
85+
{
86+
return ($this->target->value & $target->value) === $target->value;
87+
}
88+
89+
public function setTarget(AssetTypeEnum $target): void
90+
{
91+
$this->target = $target;
92+
}
7493
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace App\Model;
4+
5+
enum AssetTypeEnum: int
6+
{
7+
case Asset = 1;
8+
case Story = 2;
9+
case Both = 3;
10+
}

databox/client/src/components/AssetList/Layouts/Grid/AssetItem.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ export default function AssetItem<Item extends AssetOrAssetContainer>({
133133
)}
134134
{asset.collections && asset.collections.length > 0 && (
135135
<AssetCollectionList
136+
asset={asset}
136137
onOpenAsset={onOpen}
137138
collections={asset.collections!}
138139
/>

databox/client/src/components/AssetList/types.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ export type OnAddToBasket = (asset: Asset, e?: MouseEvent) => void;
99
export type OnSelectionChange<Item extends AssetOrAssetContainer> = (
1010
items: Item[]
1111
) => void;
12-
export type OnOpen = (asset: Asset, renditionId?: string) => void;
12+
export type OnOpen = (
13+
asset: Asset,
14+
renditionId?: string,
15+
storyAssetId?: string
16+
) => void;
1317
export type OnToggle<Item extends AssetOrAssetContainer> = (
1418
item: Item,
1519
e?: MouseEvent

databox/client/src/components/AssetSearch/AssetSearch.tsx

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,13 @@ import {Fab} from '@mui/material';
77
import AddIcon from '@mui/icons-material/Add';
88
import {useAuth} from '@alchemy/react-auth';
99
import UploadModal from '../Upload/UploadModal';
10-
import {modalRoutes, Routing} from '../../routes';
11-
import {useNavigateToModal} from '../Routing/ModalLink';
12-
import {OnOpen} from '../AssetList/types';
13-
import {AssetContextState} from '../Media/Asset/assetTypes.ts';
10+
import {useOpenAsset} from './useOpenAsset.ts';
1411

1512
type Props = {};
1613

1714
export default function AssetSearch({}: Props) {
1815
const resultContext = React.useContext(ResultContext);
1916
const {openModal} = useModals();
20-
const navigateToModal = useNavigateToModal();
2117
const authContext = useAuth();
2218

2319
const openDebug = resultContext.debug
@@ -36,33 +32,9 @@ export default function AssetSearch({}: Props) {
3632
});
3733
}, []);
3834

39-
const onOpen = useCallback<OnOpen>(
40-
(asset, renditionId): void => {
41-
if (!renditionId) {
42-
renditionId = asset.original?.id;
43-
}
44-
45-
navigateToModal(
46-
modalRoutes.assets.routes.view,
47-
{
48-
id: asset.id,
49-
renditionId: renditionId || Routing.UnknownRendition,
50-
},
51-
{
52-
state: {
53-
assetsContext: resultContext.pages
54-
.flat()
55-
.map(a => [
56-
a.id,
57-
a.original?.id,
58-
]) as AssetContextState,
59-
},
60-
}
61-
);
62-
// eslint-disable-next-line
63-
},
64-
[navigateToModal, resultContext]
65-
);
35+
const onOpen = useOpenAsset({
36+
resultContext,
37+
});
6638

6739
return (
6840
<>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import {useCallback} from 'react';
2+
import {OnOpen} from '../AssetList/types.ts';
3+
import {modalRoutes, Routing} from '../../routes.ts';
4+
import {AssetContextState} from '../Media/Asset/assetTypes.ts';
5+
import {useNavigateToModal} from '../Routing/ModalLink.tsx';
6+
import {TResultContext} from '../Media/Search/ResultContext.tsx';
7+
8+
type Props = {
9+
resultContext?: TResultContext;
10+
};
11+
12+
export function useOpenAsset({resultContext}: Props) {
13+
const navigateToModal = useNavigateToModal();
14+
15+
return useCallback<OnOpen>(
16+
(asset, renditionId, storyAssetId): void => {
17+
if (!renditionId) {
18+
renditionId = asset.original?.id;
19+
}
20+
21+
navigateToModal(
22+
modalRoutes.assets.routes.view,
23+
{
24+
id: asset.id,
25+
renditionId: renditionId || Routing.UnknownRendition,
26+
},
27+
{
28+
state: {
29+
storyAssetId,
30+
assetsContext: resultContext?.pages
31+
.flat()
32+
.map(a => [
33+
a.id,
34+
a.original?.id,
35+
]) as AssetContextState,
36+
},
37+
}
38+
);
39+
// eslint-disable-next-line
40+
},
41+
[navigateToModal, resultContext]
42+
);
43+
}

databox/client/src/components/Basket/BasketViewDialog.tsx

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import {StackedModalProps, useParams} from '@alchemy/navigation';
22
import {AppDialog} from '@alchemy/phrasea-ui';
33
import {Basket, BasketAsset} from '../../types';
44
import {Trans, useTranslation} from 'react-i18next';
5-
import React, {useCallback} from 'react';
5+
import React from 'react';
66
import {getBasket, getBasketAssets} from '../../api/basket';
7-
import {useCloseModal, useNavigateToModal} from '../Routing/ModalLink';
7+
import {useCloseModal} from '../Routing/ModalLink';
88
import AssetList from '../AssetList/AssetList';
99
import {BasketSelectionContext} from '../../context/BasketSelectionContext';
1010
import DisplayProvider from '../Media/DisplayProvider';
@@ -21,18 +21,17 @@ import BasketsPanel from './BasketsPanel';
2121
import {leftPanelWidth} from '../../themes/base';
2222
import {ZIndex} from '../../themes/zIndex';
2323
import Box from '@mui/material/Box';
24-
import {ActionsContext, OnOpen} from '../AssetList/types';
25-
import {modalRoutes, Routing} from '../../routes';
24+
import {ActionsContext} from '../AssetList/types';
2625
import BasketItem from './BasketItem';
2726
import {createDefaultActionsContext} from '../AssetList/actionContext.ts';
27+
import {useOpenAsset} from '../AssetSearch/useOpenAsset.ts';
2828

2929
type Props = {} & StackedModalProps;
3030

3131
export default function BasketViewDialog({modalIndex, open}: Props) {
3232
const {t} = useTranslation();
3333
const {id} = useParams();
3434
const closeModal = useCloseModal();
35-
const navigateToModal = useNavigateToModal();
3635

3736
const [data, setData] = React.useState<Basket>();
3837
const [pagination, setPagination] = React.useState<Pagination<BasketAsset>>(
@@ -53,16 +52,7 @@ export default function BasketViewDialog({modalIndex, open}: Props) {
5352
[loadItems, pagination]
5453
);
5554

56-
const onOpen = useCallback<OnOpen>(
57-
(asset, renditionId): void => {
58-
navigateToModal(modalRoutes.assets.routes.view, {
59-
id: asset.id,
60-
renditionId: renditionId || Routing.UnknownRendition,
61-
});
62-
// eslint-disable-next-line
63-
},
64-
[navigateToModal]
65-
);
55+
const onOpen = useOpenAsset({});
6656

6757
React.useEffect(() => {
6858
getBasket(id!).then(setData);

0 commit comments

Comments
 (0)