Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/core/src/Actions/Channels/DeleteChannel.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@
/**
* Delete a channel. Channels with order history are kept — mark them
* Inactive in the admin instead — so historical orders keep their context.
* The default channel is also kept: make another channel the default first.
*/
class DeleteChannel implements DeletesChannel
{
public function execute(Channel $channel): void
{
if ($channel->default) {
throw new ChannelActionException('Cannot delete the default channel. Make another channel the default first.');
}

if ($channel->hasOrderHistory()) {
throw new ChannelActionException('Cannot delete a channel with order history.');
}
Expand Down
7 changes: 7 additions & 0 deletions packages/core/src/Actions/Channels/UpdateChannel.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
namespace Lunar\Core\Actions\Channels;

use Lunar\Core\Contracts\Actions\Channels\UpdatesChannel;
use Lunar\Core\Exceptions\ChannelActionException;
use Lunar\Core\Models\Channel;

/**
* Update a channel, ensuring at most one channel is ever marked default.
* The default flag moves by promoting another channel, never by unsetting —
* so a store with channels always has a default.
*/
class UpdateChannel implements UpdatesChannel
{
Expand All @@ -15,6 +18,10 @@ class UpdateChannel implements UpdatesChannel
*/
public function execute(Channel $channel, array $attributes): Channel
{
if ($channel->default && array_key_exists('default', $attributes) && ! $attributes['default']) {
throw new ChannelActionException('Cannot unset the default channel. Make another channel the default instead.');
}

$attributes['handle'] ??= $attributes['name'] ?? $channel->handle;

if ($attributes['default'] ?? false) {
Expand Down
34 changes: 34 additions & 0 deletions packages/panel/resources/js/components/Toggle.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { describe, expect, it } from 'vitest';
import { mount } from '@vue/test-utils';
import Toggle from './Toggle.vue';

describe('Toggle', () => {
it('emits toggle when the switch is clicked', async () => {
const wrapper = mount(Toggle, { props: { on: false } });

await wrapper.find('button').trigger('click');

expect(wrapper.emitted('toggle')).toHaveLength(1);
});

it('emits toggle when clicked while on', async () => {
const wrapper = mount(Toggle, { props: { on: true } });

await wrapper.find('button').trigger('click');

expect(wrapper.emitted('toggle')).toHaveLength(1);
});

it('does not emit toggle when disabled', async () => {
const wrapper = mount(Toggle, { props: { on: true, disabled: true } });

await wrapper.find('button').trigger('click');

expect(wrapper.emitted('toggle')).toBeUndefined();
});

it('reflects the on prop in the switch state', () => {
expect(mount(Toggle, { props: { on: true } }).find('button').attributes('data-state')).toBe('checked');
expect(mount(Toggle, { props: { on: false } }).find('button').attributes('data-state')).toBe('unchecked');
});
});
10 changes: 6 additions & 4 deletions packages/panel/resources/js/components/Toggle.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
<script setup lang="ts">
import { SwitchRoot, SwitchThumb } from 'reka-ui';

defineProps<{ on?: boolean }>();
defineProps<{ on?: boolean; disabled?: boolean }>();
const emit = defineEmits<{ toggle: [] }>();
</script>

<template>
<SwitchRoot
:checked="on"
:model-value="on"
:disabled="disabled"
:class="[
'relative inline-block w-[34px] h-5 rounded-full cursor-pointer transition-colors duration-150 shrink-0 border border-transparent focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-sage/35',
'relative inline-block w-[34px] h-5 rounded-full transition-colors duration-150 shrink-0 border border-transparent focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-sage/35',
disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer',
on ? 'bg-ink-900' : 'bg-line-strong',
]"
@update:checked="emit('toggle')"
@update:model-value="emit('toggle')"
>
<SwitchThumb
:class="[
Expand Down
19 changes: 14 additions & 5 deletions packages/panel/resources/js/pages/settings/channels/Edit.vue
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ const submit = (): void => {
form.put(props.urls.update);
};

// The default channel cannot be deleted or un-defaulted; promote another channel instead.
const deleteBlockedReason = computed<string>(() => {
if (props.channel.default) return t('channels.delete_blocked_default');
if (props.hasOrderHistory) return t('channels.delete_blocked');
return '';
});

const deleting = ref(false);

const confirmDestroy = (): void => {
Expand All @@ -57,8 +64,8 @@ const confirmDestroy = (): void => {
<template>
<SettingsShell :title="t('channels.edit_title', { name: channel.name })" :breadcrumbs="breadcrumbs">
<template #actions>
<Tooltip :text="hasOrderHistory ? t('channels.delete_blocked') : ''">
<Button variant="ghost" icon="trash" :disabled="hasOrderHistory" @click="deleting = true">{{ t('common.delete') }}</Button>
<Tooltip :text="deleteBlockedReason">
<Button variant="ghost" icon="trash" :disabled="!!deleteBlockedReason" @click="deleting = true">{{ t('common.delete') }}</Button>
</Tooltip>
<Button variant="primary" icon="check" size="sm" :disabled="form.processing" @click="submit">{{ t('common.save') }}</Button>
</template>
Expand All @@ -84,11 +91,13 @@ const confirmDestroy = (): void => {

<Section :title="t('channels.section_state')">
<div class="flex flex-col gap-4">
<label class="flex items-center gap-3 cursor-pointer">
<Toggle :on="form.default" @toggle="form.default = !form.default" />
<label class="flex items-center gap-3" :class="channel.default ? 'cursor-not-allowed' : 'cursor-pointer'">
<Toggle :on="form.default" :disabled="channel.default" @toggle="form.default = !form.default" />
<div>
<div class="text-[12.5px] text-ink-900 font-medium">{{ t('channels.default_channel') }}</div>
<div class="text-[11px] text-ink-500">{{ t('channels.default_channel_hint') }}</div>
<div class="text-[11px] text-ink-500">
{{ channel.default ? t('channels.default_locked_hint') : t('channels.default_channel_hint') }}
</div>
</div>
</label>
<div class="max-w-[220px]">
Expand Down
3 changes: 3 additions & 0 deletions packages/panel/resources/lang/ar/channels.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
'field_status' => 'الحالة',
'default_channel' => 'القناة الافتراضية',
'default_channel_hint' => 'يُستخدم عندما لا يحدد الطلب قناة بشكل صريح.',
'default_locked_hint' => 'هذه هي القناة الافتراضية. لتغييرها، اجعل قناة أخرى هي الافتراضية.',
'default_unset_blocked' => 'لا يمكن إلغاء تعيين القناة الافتراضية. اجعل قناة أخرى هي الافتراضية بدلاً من ذلك.',

'section_details' => 'التفاصيل',
'section_state' => 'الحالة',
Expand All @@ -30,6 +32,7 @@
'confirm_delete_title' => 'هل تريد حذف القناة؟',
'confirm_delete_body' => 'سيتم حذف "{name}" نهائيًا.',
'delete_blocked' => 'لا يمكن حذف قناة لها سجل طلبات.',
'delete_blocked_default' => 'لا يمكن حذف القناة الافتراضية. اجعل قناة أخرى هي الافتراضية أولاً.',

'flash_created' => 'تم إنشاء القناة.',
'flash_updated' => 'تم تحديث القناة.',
Expand Down
3 changes: 3 additions & 0 deletions packages/panel/resources/lang/bg/channels.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
'field_status' => 'Статус',
'default_channel' => 'Канал по подразбиране',
'default_channel_hint' => 'Използва се, когато заявката не избере изрично друг.',
'default_locked_hint' => 'Това е каналът по подразбиране. За да го промените, направете друг канал по подразбиране.',
'default_unset_blocked' => 'Каналът по подразбиране не може да бъде премахнат. Вместо това направете друг канал по подразбиране.',

'section_details' => 'Детайли',
'section_state' => 'Състояние',
Expand All @@ -30,6 +32,7 @@
'confirm_delete_title' => 'Изтриване на канал?',
'confirm_delete_body' => '"{name}" ще бъде премахнат за постоянно.',
'delete_blocked' => 'Не може да се изтрие канал с история на поръчки.',
'delete_blocked_default' => 'Каналът по подразбиране не може да бъде изтрит. Първо направете друг канал по подразбиране.',

'flash_created' => 'Каналът е създаден.',
'flash_updated' => 'Каналът е актуализиран.',
Expand Down
3 changes: 3 additions & 0 deletions packages/panel/resources/lang/de/channels.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
'field_status' => 'Status',
'default_channel' => 'Standardkanal',
'default_channel_hint' => 'Wird verwendet, wenn eine Anfrage keinen explizit auswählt.',
'default_locked_hint' => 'Dies ist der Standardkanal. Um dies zu ändern, machen Sie einen anderen Kanal zum Standard.',
'default_unset_blocked' => 'Der Standardkanal kann nicht deaktiviert werden. Machen Sie stattdessen einen anderen Kanal zum Standard.',

'section_details' => 'Details',
'section_state' => 'Status',
Expand All @@ -30,6 +32,7 @@
'confirm_delete_title' => 'Kanal löschen?',
'confirm_delete_body' => '"{name}" wird dauerhaft entfernt.',
'delete_blocked' => 'Ein Kanal mit Bestellhistorie kann nicht gelöscht werden.',
'delete_blocked_default' => 'Der Standardkanal kann nicht gelöscht werden. Machen Sie zuerst einen anderen Kanal zum Standard.',

'flash_created' => 'Kanal erstellt.',
'flash_updated' => 'Kanal aktualisiert.',
Expand Down
3 changes: 3 additions & 0 deletions packages/panel/resources/lang/en/channels.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
'field_status' => 'Status',
'default_channel' => 'Default channel',
'default_channel_hint' => "Used when a request doesn't pick one explicitly.",
'default_locked_hint' => 'This is the default channel. To change it, make another channel the default.',
'default_unset_blocked' => 'The default channel cannot be unset. Make another channel the default instead.',

'section_details' => 'Details',
'section_state' => 'State',
Expand All @@ -30,6 +32,7 @@
'confirm_delete_title' => 'Delete channel?',
'confirm_delete_body' => '"{name}" will be permanently removed.',
'delete_blocked' => 'Cannot delete a channel with order history.',
'delete_blocked_default' => 'The default channel cannot be deleted. Make another channel the default first.',

'flash_created' => 'Channel created.',
'flash_updated' => 'Channel updated.',
Expand Down
3 changes: 3 additions & 0 deletions packages/panel/resources/lang/es/channels.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
'field_status' => 'Estado',
'default_channel' => 'Canal predeterminado',
'default_channel_hint' => 'Se utiliza cuando una solicitud no selecciona uno explícitamente.',
'default_locked_hint' => 'Este es el canal predeterminado. Para cambiarlo, establece otro canal como predeterminado.',
'default_unset_blocked' => 'No se puede desactivar el canal predeterminado. Establece otro canal como predeterminado en su lugar.',

'section_details' => 'Detalles',
'section_state' => 'Estado',
Expand All @@ -30,6 +32,7 @@
'confirm_delete_title' => '¿Eliminar canal?',
'confirm_delete_body' => '"{name}" se eliminará permanentemente.',
'delete_blocked' => 'No se puede eliminar un canal con historial de pedidos.',
'delete_blocked_default' => 'No se puede eliminar el canal predeterminado. Establece primero otro canal como predeterminado.',

'flash_created' => 'Canal creado.',
'flash_updated' => 'Canal actualizado.',
Expand Down
3 changes: 3 additions & 0 deletions packages/panel/resources/lang/fa/channels.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
'field_status' => 'وضعیت',
'default_channel' => 'کانال پیش‌فرض',
'default_channel_hint' => 'زمانی استفاده می‌شود که یک درخواست به‌طور صریح کانالی را انتخاب نکند.',
'default_locked_hint' => 'این کانال پیش‌فرض است. برای تغییر آن، کانال دیگری را پیش‌فرض کنید.',
'default_unset_blocked' => 'کانال پیش‌فرض را نمی‌توان غیرفعال کرد. در عوض کانال دیگری را پیش‌فرض کنید.',

'section_details' => 'جزئیات',
'section_state' => 'وضعیت',
Expand All @@ -30,6 +32,7 @@
'confirm_delete_title' => 'کانال حذف شود؟',
'confirm_delete_body' => '"{name}" به‌طور دائم حذف خواهد شد.',
'delete_blocked' => 'حذف کانالی که دارای سابقه سفارش است امکان‌پذیر نیست.',
'delete_blocked_default' => 'کانال پیش‌فرض قابل حذف نیست. ابتدا کانال دیگری را پیش‌فرض کنید.',

'flash_created' => 'کانال ایجاد شد.',
'flash_updated' => 'کانال به‌روزرسانی شد.',
Expand Down
3 changes: 3 additions & 0 deletions packages/panel/resources/lang/fr/channels.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
'field_status' => 'Statut',
'default_channel' => 'Canal par défaut',
'default_channel_hint' => "Utilisé lorsqu'une requête n'en sélectionne pas explicitement.",
'default_locked_hint' => 'Ceci est le canal par défaut. Pour le changer, définissez un autre canal par défaut.',
'default_unset_blocked' => 'Impossible de désactiver le canal par défaut. Définissez plutôt un autre canal par défaut.',

'section_details' => 'Détails',
'section_state' => 'État',
Expand All @@ -30,6 +32,7 @@
'confirm_delete_title' => 'Supprimer le canal ?',
'confirm_delete_body' => '« {name} » sera définitivement supprimé.',
'delete_blocked' => 'Impossible de supprimer un canal ayant un historique de commandes.',
'delete_blocked_default' => "Impossible de supprimer le canal par défaut. Définissez d'abord un autre canal par défaut.",

'flash_created' => 'Canal créé.',
'flash_updated' => 'Canal mis à jour.',
Expand Down
3 changes: 3 additions & 0 deletions packages/panel/resources/lang/hr/channels.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
'field_status' => 'Status',
'default_channel' => 'Zadani kanal',
'default_channel_hint' => 'Koristi se kada zahtjev izričito ne odabere kanal.',
'default_locked_hint' => 'Ovo je zadani kanal. Da biste to promijenili, postavite drugi kanal kao zadani.',
'default_unset_blocked' => 'Zadani kanal nije moguće poništiti. Umjesto toga postavite drugi kanal kao zadani.',

'section_details' => 'Detalji',
'section_state' => 'Stanje',
Expand All @@ -30,6 +32,7 @@
'confirm_delete_title' => 'Izbrisati kanal?',
'confirm_delete_body' => '"{name}" bit će trajno uklonjen.',
'delete_blocked' => 'Nije moguće izbrisati kanal s poviješću narudžbi.',
'delete_blocked_default' => 'Zadani kanal nije moguće izbrisati. Najprije postavite drugi kanal kao zadani.',

'flash_created' => 'Kanal je kreiran.',
'flash_updated' => 'Kanal je ažuriran.',
Expand Down
3 changes: 3 additions & 0 deletions packages/panel/resources/lang/hu/channels.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
'field_status' => 'Állapot',
'default_channel' => 'Alapértelmezett csatorna',
'default_channel_hint' => 'Akkor kerül felhasználásra, ha egy kérés nem választ ki kifejezetten egyet.',
'default_locked_hint' => 'Ez az alapértelmezett csatorna. A módosításhoz tegyen egy másik csatornát alapértelmezetté.',
'default_unset_blocked' => 'Az alapértelmezett csatorna nem kapcsolható ki. Tegyen inkább egy másik csatornát alapértelmezetté.',

'section_details' => 'Részletek',
'section_state' => 'Állapot',
Expand All @@ -30,6 +32,7 @@
'confirm_delete_title' => 'Törli a csatornát?',
'confirm_delete_body' => '"{name}" véglegesen eltávolításra kerül.',
'delete_blocked' => 'Nem törölhető olyan csatorna, amelynek rendelési előzményei vannak.',
'delete_blocked_default' => 'Az alapértelmezett csatorna nem törölhető. Előbb tegyen egy másik csatornát alapértelmezetté.',

'flash_created' => 'A csatorna létrehozva.',
'flash_updated' => 'A csatorna frissítve.',
Expand Down
3 changes: 3 additions & 0 deletions packages/panel/resources/lang/mn/channels.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
'field_status' => 'Төлөв',
'default_channel' => 'Үндсэн суваг',
'default_channel_hint' => 'Хүсэлт тодорхой суваг сонгоогүй үед ашиглагдана.',
'default_locked_hint' => 'Энэ бол үндсэн суваг. Өөрчлөхийн тулд өөр сувгийг үндсэн болгоно уу.',
'default_unset_blocked' => 'Үндсэн сувгийг болиулах боломжгүй. Оронд нь өөр сувгийг үндсэн болгоно уу.',

'section_details' => 'Дэлгэрэнгүй',
'section_state' => 'Төлөв',
Expand All @@ -30,6 +32,7 @@
'confirm_delete_title' => 'Сувгийг устгах уу?',
'confirm_delete_body' => '"{name}" бүрмөсөн устах болно.',
'delete_blocked' => 'Захиалгын түүхтэй сувгийг устгах боломжгүй.',
'delete_blocked_default' => 'Үндсэн сувгийг устгах боломжгүй. Эхлээд өөр сувгийг үндсэн болгоно уу.',

'flash_created' => 'Суваг үүсгэгдлээ.',
'flash_updated' => 'Суваг шинэчлэгдлээ.',
Expand Down
3 changes: 3 additions & 0 deletions packages/panel/resources/lang/nl/channels.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
'field_status' => 'Status',
'default_channel' => 'Standaardkanaal',
'default_channel_hint' => 'Wordt gebruikt wanneer een verzoek er niet expliciet één kiest.',
'default_locked_hint' => 'Dit is het standaardkanaal. Maak een ander kanaal standaard om dit te wijzigen.',
'default_unset_blocked' => 'Het standaardkanaal kan niet worden uitgeschakeld. Maak in plaats daarvan een ander kanaal standaard.',

'section_details' => 'Details',
'section_state' => 'Status',
Expand All @@ -30,6 +32,7 @@
'confirm_delete_title' => 'Kanaal verwijderen?',
'confirm_delete_body' => '"{name}" wordt permanent verwijderd.',
'delete_blocked' => 'Kan geen kanaal verwijderen met bestelgeschiedenis.',
'delete_blocked_default' => 'Het standaardkanaal kan niet worden verwijderd. Maak eerst een ander kanaal standaard.',

'flash_created' => 'Kanaal aangemaakt.',
'flash_updated' => 'Kanaal bijgewerkt.',
Expand Down
3 changes: 3 additions & 0 deletions packages/panel/resources/lang/pl/channels.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
'field_status' => 'Status',
'default_channel' => 'Domyślny kanał',
'default_channel_hint' => 'Używany, gdy żądanie nie wybiera go jawnie.',
'default_locked_hint' => 'To jest domyślny kanał. Aby to zmienić, ustaw inny kanał jako domyślny.',
'default_unset_blocked' => 'Nie można wyłączyć domyślnego kanału. Zamiast tego ustaw inny kanał jako domyślny.',

'section_details' => 'Szczegóły',
'section_state' => 'Stan',
Expand All @@ -30,6 +32,7 @@
'confirm_delete_title' => 'Usunąć kanał?',
'confirm_delete_body' => '"{name}" zostanie trwale usunięty.',
'delete_blocked' => 'Nie można usunąć kanału z historią zamówień.',
'delete_blocked_default' => 'Nie można usunąć domyślnego kanału. Najpierw ustaw inny kanał jako domyślny.',

'flash_created' => 'Kanał utworzony.',
'flash_updated' => 'Kanał zaktualizowany.',
Expand Down
3 changes: 3 additions & 0 deletions packages/panel/resources/lang/pt_BR/channels.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
'field_status' => 'Status',
'default_channel' => 'Canal padrão',
'default_channel_hint' => 'Usado quando uma solicitação não escolhe um explicitamente.',
'default_locked_hint' => 'Este é o canal padrão. Para alterá-lo, defina outro canal como padrão.',
'default_unset_blocked' => 'O canal padrão não pode ser desativado. Em vez disso, defina outro canal como padrão.',

'section_details' => 'Detalhes',
'section_state' => 'Estado',
Expand All @@ -30,6 +32,7 @@
'confirm_delete_title' => 'Excluir canal?',
'confirm_delete_body' => '"{name}" será removido permanentemente.',
'delete_blocked' => 'Não é possível excluir um canal com histórico de pedidos.',
'delete_blocked_default' => 'O canal padrão não pode ser excluído. Defina outro canal como padrão primeiro.',

'flash_created' => 'Canal criado.',
'flash_updated' => 'Canal atualizado.',
Expand Down
Loading
Loading