Merge branch 'main' into koda/ticket-create-notification-action
# Conflicts: # resources/js/pages/projects/settings/Notifications.vue
This commit is contained in:
@@ -67,6 +67,41 @@ props.notificationActions.forEach((notificationAction) => {
|
||||
const selectedChannel = (notificationAction: NotificationActionModel): string =>
|
||||
editChannelState[notificationAction.id] ?? notificationAction.channel;
|
||||
|
||||
const notificationActionAllowedMentions = (
|
||||
notificationAction: NotificationActionModel,
|
||||
): string[] => {
|
||||
const allowedMentions =
|
||||
notificationAction.channel_configuration['allowed_mentions'];
|
||||
|
||||
if (!Array.isArray(allowedMentions)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return allowedMentions
|
||||
.filter(
|
||||
(allowedMention): allowedMention is string =>
|
||||
typeof allowedMention === 'string',
|
||||
)
|
||||
.map((allowedMention) => allowedMention.trim().toLowerCase())
|
||||
.filter((allowedMention) => allowedMention !== '');
|
||||
};
|
||||
|
||||
const allowedMentionsError = (
|
||||
errors: Record<string, string>,
|
||||
): string | undefined => {
|
||||
const generalError = errors['channel_configuration.allowed_mentions'];
|
||||
|
||||
if (generalError !== undefined) {
|
||||
return generalError;
|
||||
}
|
||||
|
||||
const itemErrorKey = Object.keys(errors).find((key) =>
|
||||
key.startsWith('channel_configuration.allowed_mentions.'),
|
||||
);
|
||||
|
||||
return itemErrorKey === undefined ? undefined : errors[itemErrorKey];
|
||||
};
|
||||
|
||||
const notificationActionTimestamp = (
|
||||
notificationAction: NotificationActionModel,
|
||||
): string => {
|
||||
@@ -210,7 +245,9 @@ const notificationActionTimestamp = (
|
||||
</div>
|
||||
|
||||
<div class="grid gap-2">
|
||||
<Label for="create-notification-channel">
|
||||
<Label
|
||||
for="create-notification-channel"
|
||||
>
|
||||
Channel
|
||||
</Label>
|
||||
<select
|
||||
@@ -232,7 +269,9 @@ const notificationActionTimestamp = (
|
||||
</div>
|
||||
|
||||
<div class="grid gap-2">
|
||||
<Label for="create-notification-delivery-url">
|
||||
<Label
|
||||
for="create-notification-delivery-url"
|
||||
>
|
||||
Delivery URL
|
||||
</Label>
|
||||
<Input
|
||||
@@ -246,7 +285,55 @@ const notificationActionTimestamp = (
|
||||
never rendered back to the browser after
|
||||
save.
|
||||
</p>
|
||||
<InputError :message="errors.delivery_url" />
|
||||
<InputError
|
||||
:message="errors.delivery_url"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-2">
|
||||
<Label>Allowed mentions</Label>
|
||||
<div
|
||||
:class="[
|
||||
'grid gap-2',
|
||||
createChannelState.value !==
|
||||
'discord'
|
||||
? 'hidden'
|
||||
: '',
|
||||
]"
|
||||
>
|
||||
<label
|
||||
v-for="allowedMentionOption in discordAllowedMentionOptions"
|
||||
:key="`create-allowed-mention-${allowedMentionOption.value}`"
|
||||
class="border-border flex items-center gap-2 rounded-lg border px-3 py-2"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="channel_configuration[allowed_mentions][]"
|
||||
:value="
|
||||
allowedMentionOption.value
|
||||
"
|
||||
:disabled="
|
||||
createChannelState.value !==
|
||||
'discord'
|
||||
"
|
||||
class="border-input text-primary focus:ring-ring size-4 rounded"
|
||||
/>
|
||||
<span>
|
||||
{{ allowedMentionOption.label }}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<p class="text-muted-foreground text-sm">
|
||||
{{
|
||||
createChannelState.value ===
|
||||
'discord'
|
||||
? 'Pick which Discord mention types are allowed. Leave all unchecked to keep mentions fully disabled.'
|
||||
: 'Allowed mentions are only used when the channel is Discord.'
|
||||
}}
|
||||
</p>
|
||||
<InputError
|
||||
:message="allowedMentionsError(errors)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-2">
|
||||
@@ -393,7 +480,11 @@ const notificationActionTimestamp = (
|
||||
</Badge>
|
||||
</div>
|
||||
<CardDescription>
|
||||
{{ notificationActionTimestamp(notificationAction) }}
|
||||
{{
|
||||
notificationActionTimestamp(
|
||||
notificationAction,
|
||||
)
|
||||
}}
|
||||
</CardDescription>
|
||||
</div>
|
||||
</CardHeader>
|
||||
@@ -405,25 +496,19 @@ const notificationActionTimestamp = (
|
||||
[project.id, notificationAction.id],
|
||||
)
|
||||
"
|
||||
:error-bag="
|
||||
`updateNotificationAction-${notificationAction.id}`
|
||||
"
|
||||
:error-bag="`updateNotificationAction-${notificationAction.id}`"
|
||||
class="space-y-4"
|
||||
v-slot="{ errors, processing }"
|
||||
>
|
||||
<div class="grid gap-4 md:grid-cols-2">
|
||||
<div class="grid gap-2">
|
||||
<Label
|
||||
:for="
|
||||
`notification-name-${notificationAction.id}`
|
||||
"
|
||||
:for="`notification-name-${notificationAction.id}`"
|
||||
>
|
||||
Name
|
||||
</Label>
|
||||
<Input
|
||||
:id="
|
||||
`notification-name-${notificationAction.id}`
|
||||
"
|
||||
:id="`notification-name-${notificationAction.id}`"
|
||||
name="name"
|
||||
:default-value="
|
||||
notificationAction.name
|
||||
@@ -434,16 +519,12 @@ const notificationActionTimestamp = (
|
||||
|
||||
<div class="grid gap-2">
|
||||
<Label
|
||||
:for="
|
||||
`notification-delivery-url-${notificationAction.id}`
|
||||
"
|
||||
:for="`notification-delivery-url-${notificationAction.id}`"
|
||||
>
|
||||
Delivery URL
|
||||
</Label>
|
||||
<Input
|
||||
:id="
|
||||
`notification-delivery-url-${notificationAction.id}`
|
||||
"
|
||||
:id="`notification-delivery-url-${notificationAction.id}`"
|
||||
name="delivery_url"
|
||||
type="url"
|
||||
:placeholder="
|
||||
@@ -468,16 +549,12 @@ const notificationActionTimestamp = (
|
||||
|
||||
<div class="grid gap-2">
|
||||
<Label
|
||||
:for="
|
||||
`notification-event-type-${notificationAction.id}`
|
||||
"
|
||||
:for="`notification-event-type-${notificationAction.id}`"
|
||||
>
|
||||
Event type
|
||||
</Label>
|
||||
<select
|
||||
:id="
|
||||
`notification-event-type-${notificationAction.id}`
|
||||
"
|
||||
:id="`notification-event-type-${notificationAction.id}`"
|
||||
name="event_type"
|
||||
:default-value="
|
||||
notificationAction.event_type
|
||||
@@ -499,16 +576,12 @@ const notificationActionTimestamp = (
|
||||
|
||||
<div class="grid gap-2">
|
||||
<Label
|
||||
:for="
|
||||
`notification-channel-${notificationAction.id}`
|
||||
"
|
||||
:for="`notification-channel-${notificationAction.id}`"
|
||||
>
|
||||
Channel
|
||||
</Label>
|
||||
<select
|
||||
:id="
|
||||
`notification-channel-${notificationAction.id}`
|
||||
"
|
||||
:id="`notification-channel-${notificationAction.id}`"
|
||||
name="channel"
|
||||
v-model="
|
||||
editChannelState[
|
||||
@@ -529,18 +602,70 @@ const notificationActionTimestamp = (
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-2">
|
||||
<Label>Allowed mentions</Label>
|
||||
<div
|
||||
:class="[
|
||||
'grid gap-2',
|
||||
selectedChannel(
|
||||
notificationAction,
|
||||
) !== 'discord'
|
||||
? 'hidden'
|
||||
: '',
|
||||
]"
|
||||
>
|
||||
<label
|
||||
v-for="allowedMentionOption in discordAllowedMentionOptions"
|
||||
:key="`notification-allowed-mention-${notificationAction.id}-${allowedMentionOption.value}`"
|
||||
class="border-border flex items-center gap-2 rounded-lg border px-3 py-2"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="channel_configuration[allowed_mentions][]"
|
||||
:value="
|
||||
allowedMentionOption.value
|
||||
"
|
||||
:default-checked="
|
||||
notificationActionAllowedMentions(
|
||||
notificationAction,
|
||||
).includes(
|
||||
allowedMentionOption.value,
|
||||
)
|
||||
"
|
||||
:disabled="
|
||||
selectedChannel(
|
||||
notificationAction,
|
||||
) !== 'discord'
|
||||
"
|
||||
class="border-input text-primary focus:ring-ring size-4 rounded"
|
||||
/>
|
||||
<span>
|
||||
{{ allowedMentionOption.label }}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<p class="text-muted-foreground text-sm">
|
||||
{{
|
||||
selectedChannel(
|
||||
notificationAction,
|
||||
) === 'discord'
|
||||
? 'Pick which Discord mention types are allowed. Leave all unchecked to keep mentions fully disabled.'
|
||||
: 'Allowed mentions are only used when the channel is Discord.'
|
||||
}}
|
||||
</p>
|
||||
<InputError
|
||||
:message="allowedMentionsError(errors)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-2">
|
||||
<Label
|
||||
:for="
|
||||
`notification-message-template-${notificationAction.id}`
|
||||
"
|
||||
:for="`notification-message-template-${notificationAction.id}`"
|
||||
>
|
||||
Discord message template
|
||||
</Label>
|
||||
<textarea
|
||||
:id="
|
||||
`notification-message-template-${notificationAction.id}`
|
||||
"
|
||||
:id="`notification-message-template-${notificationAction.id}`"
|
||||
name="message_template"
|
||||
rows="4"
|
||||
:value="
|
||||
@@ -548,13 +673,15 @@ const notificationActionTimestamp = (
|
||||
''
|
||||
"
|
||||
:disabled="
|
||||
selectedChannel(notificationAction) !==
|
||||
'discord'
|
||||
selectedChannel(
|
||||
notificationAction,
|
||||
) !== 'discord'
|
||||
"
|
||||
:class="[
|
||||
'border-input bg-background shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 min-h-28 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px]',
|
||||
selectedChannel(notificationAction) !==
|
||||
'discord'
|
||||
selectedChannel(
|
||||
notificationAction,
|
||||
) !== 'discord'
|
||||
? 'hidden'
|
||||
: 'block',
|
||||
]"
|
||||
@@ -562,8 +689,9 @@ const notificationActionTimestamp = (
|
||||
/>
|
||||
<p class="text-muted-foreground text-sm">
|
||||
{{
|
||||
selectedChannel(notificationAction) ===
|
||||
'discord'
|
||||
selectedChannel(
|
||||
notificationAction,
|
||||
) === 'discord'
|
||||
? 'Available for Discord actions only. Use the fixed variables listed in the sidebar.'
|
||||
: 'Discord message templates are only used when the channel is Discord.'
|
||||
}}
|
||||
@@ -578,9 +706,7 @@ const notificationActionTimestamp = (
|
||||
>
|
||||
<div class="grid gap-2">
|
||||
<Label
|
||||
:for="
|
||||
`notification-enabled-${notificationAction.id}`
|
||||
"
|
||||
:for="`notification-enabled-${notificationAction.id}`"
|
||||
class="flex items-center gap-3"
|
||||
>
|
||||
<input
|
||||
@@ -589,9 +715,7 @@ const notificationActionTimestamp = (
|
||||
value="0"
|
||||
/>
|
||||
<input
|
||||
:id="
|
||||
`notification-enabled-${notificationAction.id}`
|
||||
"
|
||||
:id="`notification-enabled-${notificationAction.id}`"
|
||||
type="checkbox"
|
||||
name="enabled"
|
||||
value="1"
|
||||
|
||||
@@ -109,6 +109,7 @@ export type ProjectRepositorySettingsPageProps = {
|
||||
export type ProjectNotificationSettingsPageProps = {
|
||||
channelOptions: NotificationActionOptionModel[];
|
||||
eventTypeOptions: NotificationActionOptionModel[];
|
||||
discordAllowedMentionOptions: NotificationActionOptionModel[];
|
||||
notificationActions: NotificationActionModel[];
|
||||
project: ProjectModel;
|
||||
status?: string | null;
|
||||
|
||||
Reference in New Issue
Block a user