mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-20 07:26:19 +00:00
@@ -6,6 +6,7 @@ export class CatalogNode implements ICatalogNode
|
|||||||
private _depth: number = 0;
|
private _depth: number = 0;
|
||||||
private _localization: string = '';
|
private _localization: string = '';
|
||||||
private _pageId: number = -1;
|
private _pageId: number = -1;
|
||||||
|
private _parentId: number = -1;
|
||||||
private _pageName: string = '';
|
private _pageName: string = '';
|
||||||
private _iconId: number = 0;
|
private _iconId: number = 0;
|
||||||
private _children: ICatalogNode[];
|
private _children: ICatalogNode[];
|
||||||
@@ -21,6 +22,7 @@ export class CatalogNode implements ICatalogNode
|
|||||||
this._parent = parent;
|
this._parent = parent;
|
||||||
this._localization = node.localization;
|
this._localization = node.localization;
|
||||||
this._pageId = node.pageId;
|
this._pageId = node.pageId;
|
||||||
|
this._parentId = node.parentId;
|
||||||
this._pageName = node.pageName;
|
this._pageName = node.pageName;
|
||||||
this._iconId = node.icon;
|
this._iconId = node.icon;
|
||||||
this._children = [];
|
this._children = [];
|
||||||
@@ -82,6 +84,11 @@ export class CatalogNode implements ICatalogNode
|
|||||||
return this._pageId;
|
return this._pageId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get parentId(): number
|
||||||
|
{
|
||||||
|
return this._parentId;
|
||||||
|
}
|
||||||
|
|
||||||
public get pageName(): string
|
public get pageName(): string
|
||||||
{
|
{
|
||||||
return this._pageName;
|
return this._pageName;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export interface ICatalogNode
|
|||||||
readonly isLeaf: boolean;
|
readonly isLeaf: boolean;
|
||||||
readonly localization: string;
|
readonly localization: string;
|
||||||
readonly pageId: number;
|
readonly pageId: number;
|
||||||
|
readonly parentId: number;
|
||||||
readonly pageName: string;
|
readonly pageName: string;
|
||||||
readonly iconId: number;
|
readonly iconId: number;
|
||||||
readonly children: ICatalogNode[];
|
readonly children: ICatalogNode[];
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ export interface IPageEditData
|
|||||||
{
|
{
|
||||||
pageId?: number;
|
pageId?: number;
|
||||||
caption: string;
|
caption: string;
|
||||||
|
captionSave: string;
|
||||||
parentId: number;
|
parentId: number;
|
||||||
catalogMode: string;
|
catalogMode: string;
|
||||||
pageLayout: string;
|
pageLayout: string;
|
||||||
|
iconImage: number;
|
||||||
enabled: string;
|
enabled: string;
|
||||||
visible: string;
|
visible: string;
|
||||||
minRank: number;
|
minRank: number;
|
||||||
@@ -177,7 +179,7 @@ export const CatalogAdminProvider: FC<{ children: ReactNode }> = ({ children })
|
|||||||
setLastError(null);
|
setLastError(null);
|
||||||
pendingActionRef.current = 'savePage';
|
pendingActionRef.current = 'savePage';
|
||||||
SendMessageComposer(new CatalogAdminSavePageComposer(
|
SendMessageComposer(new CatalogAdminSavePageComposer(
|
||||||
data.pageId || 0, data.caption, data.caption, data.pageLayout, 0,
|
data.pageId || 0, data.caption, data.captionSave, data.pageLayout, data.iconImage,
|
||||||
data.minRank, data.visible === '1', data.enabled === '1',
|
data.minRank, data.visible === '1', data.enabled === '1',
|
||||||
data.orderNum, data.parentId,
|
data.orderNum, data.parentId,
|
||||||
data.pageHeadline || '', data.pageTeaser || '', data.pageTextDetails || '', currentType, data.catalogMode
|
data.pageHeadline || '', data.pageTeaser || '', data.pageTextDetails || '', currentType, data.catalogMode
|
||||||
@@ -190,7 +192,7 @@ export const CatalogAdminProvider: FC<{ children: ReactNode }> = ({ children })
|
|||||||
setLastError(null);
|
setLastError(null);
|
||||||
pendingActionRef.current = 'createPage';
|
pendingActionRef.current = 'createPage';
|
||||||
SendMessageComposer(new CatalogAdminCreatePageComposer(
|
SendMessageComposer(new CatalogAdminCreatePageComposer(
|
||||||
data.caption, data.caption, data.pageLayout, 0,
|
data.caption, data.captionSave, data.pageLayout, data.iconImage,
|
||||||
data.minRank, data.visible === '1', data.enabled === '1',
|
data.minRank, data.visible === '1', data.enabled === '1',
|
||||||
data.orderNum, data.parentId, currentType, data.catalogMode
|
data.orderNum, data.parentId, currentType, data.catalogMode
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ const CatalogClassicViewInner: FC<{}> = () =>
|
|||||||
<div className="flex items-center gap-2 mb-1">
|
<div className="flex items-center gap-2 mb-1">
|
||||||
<button
|
<button
|
||||||
className="flex items-center gap-1 text-[9px] text-success hover:text-green-800 cursor-pointer transition-colors"
|
className="flex items-center gap-1 text-[9px] text-success hover:text-green-800 cursor-pointer transition-colors"
|
||||||
onClick={ () => catalogAdmin.createPage({ caption: 'New Category', catalogMode: currentType, pageLayout: 'default_3x3', minRank: 1, visible: '1', enabled: '1', orderNum: 99, parentId: rootNode.pageId }) }
|
onClick={ () => catalogAdmin.createPage({ caption: 'New Category', captionSave: 'New Category', catalogMode: currentType, pageLayout: 'default_3x3', iconImage: 0, minRank: 1, visible: '1', enabled: '1', orderNum: 99, parentId: rootNode.pageId }) }
|
||||||
>
|
>
|
||||||
<FaPlus className="text-[8px]" />
|
<FaPlus className="text-[8px]" />
|
||||||
<span>{ LocalizeText('catalog.admin.new') }</span>
|
<span>{ LocalizeText('catalog.admin.new') }</span>
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ const CatalogModernViewInner: FC<{}> = () =>
|
|||||||
<button
|
<button
|
||||||
className="flex items-center gap-1 text-[9px] text-success hover:text-green-800 cursor-pointer transition-colors"
|
className="flex items-center gap-1 text-[9px] text-success hover:text-green-800 cursor-pointer transition-colors"
|
||||||
title={ LocalizeText('catalog.admin.new.root.category') }
|
title={ LocalizeText('catalog.admin.new.root.category') }
|
||||||
onClick={ () => catalogAdmin.createPage({ caption: 'New Category', catalogMode: currentType, pageLayout: 'default_3x3', minRank: 1, visible: '1', enabled: '1', orderNum: 99, parentId: rootNode.pageId }) }
|
onClick={ () => catalogAdmin.createPage({ caption: 'New Category', captionSave: 'New Category', catalogMode: currentType, pageLayout: 'default_3x3', iconImage: 0, minRank: 1, visible: '1', enabled: '1', orderNum: 99, parentId: rootNode.pageId }) }
|
||||||
>
|
>
|
||||||
<FaPlus className="text-[8px]" />
|
<FaPlus className="text-[8px]" />
|
||||||
<span className="whitespace-nowrap">{ LocalizeText('catalog.admin.new') }</span>
|
<span className="whitespace-nowrap">{ LocalizeText('catalog.admin.new') }</span>
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ const LAYOUT_OPTIONS = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const MODE_OPTIONS = [
|
const MODE_OPTIONS = [
|
||||||
{ value: CatalogType.NORMAL, label: 'Normale' },
|
{ value: 'NORMAL', label: 'Normal' },
|
||||||
{ value: 'BOTH', label: 'Entrambi' }
|
{ value: 'BUILDER', label: 'Builder' },
|
||||||
|
{ value: 'BOTH', label: 'Both' }
|
||||||
];
|
];
|
||||||
|
|
||||||
export const CatalogAdminPageEditView: FC<{}> = () =>
|
export const CatalogAdminPageEditView: FC<{}> = () =>
|
||||||
@@ -30,17 +31,15 @@ export const CatalogAdminPageEditView: FC<{}> = () =>
|
|||||||
const loading = catalogAdmin?.loading ?? false;
|
const loading = catalogAdmin?.loading ?? false;
|
||||||
|
|
||||||
const [ caption, setCaption ] = useState('');
|
const [ caption, setCaption ] = useState('');
|
||||||
const [ catalogMode, setCatalogMode ] = useState(CatalogType.NORMAL);
|
const [ captionSave, setCaptionSave ] = useState('');
|
||||||
|
const [ catalogMode, setCatalogMode ] = useState<string>('NORMAL');
|
||||||
const [ pageLayout, setPageLayout ] = useState('default_3x3');
|
const [ pageLayout, setPageLayout ] = useState('default_3x3');
|
||||||
|
const [ iconImage, setIconImage ] = useState(0);
|
||||||
const [ minRank, setMinRank ] = useState(1);
|
const [ minRank, setMinRank ] = useState(1);
|
||||||
const [ visible, setVisible ] = useState('1');
|
const [ visible, setVisible ] = useState('1');
|
||||||
const [ enabled, setEnabled ] = useState('1');
|
const [ enabled, setEnabled ] = useState('1');
|
||||||
const [ orderNum, setOrderNum ] = useState(0);
|
const [ orderNum, setOrderNum ] = useState(0);
|
||||||
|
const [ parentId, setParentId ] = useState(-1);
|
||||||
// Resolve what we're editing:
|
|
||||||
// 1. editingPageNode (explicit node from sidebar click)
|
|
||||||
// 2. editingRootPage (root button)
|
|
||||||
// 3. current active page (from "Modifica Pagina" in layout)
|
|
||||||
const targetNode = editingPageNode
|
const targetNode = editingPageNode
|
||||||
? editingPageNode
|
? editingPageNode
|
||||||
: editingRootPage
|
: editingRootPage
|
||||||
@@ -62,12 +61,18 @@ export const CatalogAdminPageEditView: FC<{}> = () =>
|
|||||||
if(!editingPageData || !targetNode) return;
|
if(!editingPageData || !targetNode) return;
|
||||||
|
|
||||||
setCaption(targetNode.localization || '');
|
setCaption(targetNode.localization || '');
|
||||||
setCatalogMode(currentType === CatalogType.BUILDER ? CatalogType.BUILDER : (currentType || CatalogType.NORMAL));
|
setCaptionSave(targetNode.pageName || targetNode.localization || '');
|
||||||
|
setCatalogMode(currentType === CatalogType.BUILDER ? 'BUILDER' : 'NORMAL');
|
||||||
setPageLayout(currentPage?.layoutCode || 'default_3x3');
|
setPageLayout(currentPage?.layoutCode || 'default_3x3');
|
||||||
|
setIconImage(targetNode.iconId ?? 0);
|
||||||
setVisible(targetNode.isVisible ? '1' : '0');
|
setVisible(targetNode.isVisible ? '1' : '0');
|
||||||
setEnabled('1');
|
setEnabled('1');
|
||||||
setMinRank(1);
|
setMinRank(1);
|
||||||
setOrderNum(0);
|
setOrderNum(0);
|
||||||
|
const wireParentId = targetNode.parentId;
|
||||||
|
setParentId(typeof wireParentId === 'number' && wireParentId !== -1
|
||||||
|
? wireParentId
|
||||||
|
: (targetNode.parent ? targetNode.parent.pageId : -1));
|
||||||
}, [ editingPageData, targetNode, currentPage, currentType ]);
|
}, [ editingPageData, targetNode, currentPage, currentType ]);
|
||||||
|
|
||||||
if(!editingPageData || !targetNode) return null;
|
if(!editingPageData || !targetNode) return null;
|
||||||
@@ -78,18 +83,18 @@ export const CatalogAdminPageEditView: FC<{}> = () =>
|
|||||||
{
|
{
|
||||||
if(!catalogAdmin?.savePage) return;
|
if(!catalogAdmin?.savePage) return;
|
||||||
|
|
||||||
const parentNode = targetNode.parent;
|
|
||||||
|
|
||||||
const data: IPageEditData = {
|
const data: IPageEditData = {
|
||||||
pageId: targetPageId,
|
pageId: targetPageId,
|
||||||
caption,
|
caption,
|
||||||
|
captionSave,
|
||||||
catalogMode,
|
catalogMode,
|
||||||
pageLayout,
|
pageLayout,
|
||||||
|
iconImage,
|
||||||
minRank,
|
minRank,
|
||||||
visible,
|
visible,
|
||||||
enabled,
|
enabled,
|
||||||
orderNum,
|
orderNum,
|
||||||
parentId: parentNode ? parentNode.pageId : -1,
|
parentId,
|
||||||
};
|
};
|
||||||
|
|
||||||
catalogAdmin.savePage(data);
|
catalogAdmin.savePage(data);
|
||||||
@@ -111,7 +116,7 @@ export const CatalogAdminPageEditView: FC<{}> = () =>
|
|||||||
<div className="bg-white rounded border-2 border-card-grid-item-border p-2.5 mb-2">
|
<div className="bg-white rounded border-2 border-card-grid-item-border p-2.5 mb-2">
|
||||||
<div className="flex items-center justify-between mb-2">
|
<div className="flex items-center justify-between mb-2">
|
||||||
<span className="text-[11px] font-bold text-primary uppercase tracking-wide">
|
<span className="text-[11px] font-bold text-primary uppercase tracking-wide">
|
||||||
{ isRoot ? LocalizeText('catalog.admin.edit.root') : `${ LocalizeText('catalog.admin.edit') } ${ targetNode.localization } (#${ targetPageId })` }
|
{ isRoot ? LocalizeText('catalog.admin.edit.root') : `${ LocalizeText('catalog.admin.edit') } ${ targetNode.localization }` }
|
||||||
</span>
|
</span>
|
||||||
<FaTimes className="text-muted cursor-pointer hover:text-danger text-[10px]" onClick={ closeForm } />
|
<FaTimes className="text-muted cursor-pointer hover:text-danger text-[10px]" onClick={ closeForm } />
|
||||||
</div>
|
</div>
|
||||||
@@ -125,13 +130,19 @@ export const CatalogAdminPageEditView: FC<{}> = () =>
|
|||||||
<label className="text-[9px] text-muted uppercase font-bold">Min Rank</label>
|
<label className="text-[9px] text-muted uppercase font-bold">Min Rank</label>
|
||||||
<input className={ inputClass } min={ 1 } type="number" value={ minRank } onChange={ e => setMinRank(parseInt(e.target.value) || 1) } />
|
<input className={ inputClass } min={ 1 } type="number" value={ minRank } onChange={ e => setMinRank(parseInt(e.target.value) || 1) } />
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex flex-col gap-0.5 col-span-2">
|
||||||
|
<label className="text-[9px] text-muted uppercase font-bold">Caption Save (Localisation Key)</label>
|
||||||
|
<input className={ inputClass } value={ captionSave } onChange={ e => setCaptionSave(e.target.value) } />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-0.5">
|
||||||
|
<label className="text-[9px] text-muted uppercase font-bold">Icon Image</label>
|
||||||
|
<input className={ inputClass } min={ 0 } type="number" value={ iconImage } onChange={ e => setIconImage(parseInt(e.target.value) || 0) } />
|
||||||
|
</div>
|
||||||
<div className="flex flex-col gap-0.5">
|
<div className="flex flex-col gap-0.5">
|
||||||
<label className="text-[9px] text-muted uppercase font-bold">Mode</label>
|
<label className="text-[9px] text-muted uppercase font-bold">Mode</label>
|
||||||
{ currentType === CatalogType.BUILDER
|
<select className={ inputClass } value={ catalogMode } onChange={ e => setCatalogMode(e.target.value) }>
|
||||||
? <div className={ `${ inputClass } flex items-center min-h-[28px] bg-gray-100 text-muted` }>Builders Club</div>
|
{ MODE_OPTIONS.map(option => <option key={ option.value } value={ option.value }>{ option.label }</option>) }
|
||||||
: <select className={ inputClass } value={ catalogMode } onChange={ e => setCatalogMode(e.target.value) }>
|
</select>
|
||||||
{ MODE_OPTIONS.map(option => <option key={ option.value } value={ option.value }>{ option.label }</option>) }
|
|
||||||
</select> }
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-0.5">
|
<div className="flex flex-col gap-0.5">
|
||||||
<label className="text-[9px] text-muted uppercase font-bold">Layout</label>
|
<label className="text-[9px] text-muted uppercase font-bold">Layout</label>
|
||||||
@@ -143,6 +154,10 @@ export const CatalogAdminPageEditView: FC<{}> = () =>
|
|||||||
<label className="text-[9px] text-muted uppercase font-bold">{ LocalizeText('catalog.admin.order') }</label>
|
<label className="text-[9px] text-muted uppercase font-bold">{ LocalizeText('catalog.admin.order') }</label>
|
||||||
<input className={ inputClass } min={ 0 } type="number" value={ orderNum } onChange={ e => setOrderNum(parseInt(e.target.value) || 0) } />
|
<input className={ inputClass } min={ 0 } type="number" value={ orderNum } onChange={ e => setOrderNum(parseInt(e.target.value) || 0) } />
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex flex-col gap-0.5">
|
||||||
|
<label className="text-[9px] text-muted uppercase font-bold">Parent ID</label>
|
||||||
|
<input className={ inputClass } disabled={ isRoot } type="number" value={ parentId } onChange={ e => setParentId(parseInt(e.target.value) || -1) } />
|
||||||
|
</div>
|
||||||
<div className="flex items-end gap-2 pb-0.5">
|
<div className="flex items-end gap-2 pb-0.5">
|
||||||
<label className="flex items-center gap-1 text-[10px] cursor-pointer">
|
<label className="flex items-center gap-1 text-[10px] cursor-pointer">
|
||||||
<input className="accent-primary" checked={ visible === '1' } type="checkbox" onChange={ e => setVisible(e.target.checked ? '1' : '0') } />
|
<input className="accent-primary" checked={ visible === '1' } type="checkbox" onChange={ e => setVisible(e.target.checked ? '1' : '0') } />
|
||||||
|
|||||||
@@ -101,8 +101,10 @@ export const CatalogNavigationItemView: FC<CatalogNavigationItemViewProps> = pro
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
catalogAdmin.createPage({
|
catalogAdmin.createPage({
|
||||||
caption: 'New Page',
|
caption: 'New Page',
|
||||||
|
captionSave: 'New Page',
|
||||||
catalogMode: currentType,
|
catalogMode: currentType,
|
||||||
pageLayout: 'default_3x3',
|
pageLayout: 'default_3x3',
|
||||||
|
iconImage: 0,
|
||||||
minRank: 1,
|
minRank: 1,
|
||||||
visible: '1',
|
visible: '1',
|
||||||
enabled: '1',
|
enabled: '1',
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export const CatalogLayoutVipBuyView: FC<CatalogLayoutProps> = props =>
|
|||||||
const giftSuccessTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
const giftSuccessTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||||
|
|
||||||
const isSelfGift = giftMode && !!ownUserName && giftRecipient.trim().toLowerCase() === ownUserName.toLowerCase();
|
const isSelfGift = giftMode && !!ownUserName && giftRecipient.trim().toLowerCase() === ownUserName.toLowerCase();
|
||||||
|
|
||||||
const onCatalogEvent = useCallback((event: CatalogEvent) =>
|
const onCatalogEvent = useCallback((event: CatalogEvent) =>
|
||||||
{
|
{
|
||||||
switch(event.type)
|
switch(event.type)
|
||||||
@@ -148,7 +149,6 @@ export const CatalogLayoutVipBuyView: FC<CatalogLayoutProps> = props =>
|
|||||||
setPendingOffer(offer);
|
setPendingOffer(offer);
|
||||||
setGiftError(null);
|
setGiftError(null);
|
||||||
setGiftSuccess(false);
|
setGiftSuccess(false);
|
||||||
|
|
||||||
if(!offer?.giftable) setGiftMode(false);
|
if(!offer?.giftable) setGiftMode(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user