@globalbrain/sefirot 4.45.0 → 4.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/blocks/lens/Rule.ts +5 -0
- package/lib/blocks/lens/components/LensCatalog.vue +4 -0
- package/lib/blocks/lens/validation/RuleMapper.ts +12 -1
- package/lib/validation/rules/index.ts +1 -0
- package/lib/validation/rules/slackChannelLink.ts +15 -0
- package/lib/validation/validators/index.ts +1 -0
- package/lib/validation/validators/slackChannelLink.ts +52 -0
- package/package.json +1 -1
package/lib/blocks/lens/Rule.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export type Rule =
|
|
2
2
|
| MaxLengthRule
|
|
3
3
|
| RequiredRule
|
|
4
|
+
| SlackChannelLinkRule
|
|
4
5
|
| SlackChannelNameRule
|
|
5
6
|
| BeforeRule
|
|
6
7
|
| BeforeOrEqualRule
|
|
@@ -16,6 +17,10 @@ export interface RequiredRule {
|
|
|
16
17
|
type: 'required'
|
|
17
18
|
}
|
|
18
19
|
|
|
20
|
+
export interface SlackChannelLinkRule {
|
|
21
|
+
type: 'slack_channel_link'
|
|
22
|
+
}
|
|
23
|
+
|
|
19
24
|
export interface SlackChannelNameRule {
|
|
20
25
|
type: 'slack_channel_name'
|
|
21
26
|
offset: number
|
|
@@ -3,6 +3,7 @@ import { useDebounceFn, useElementSize } from '@vueuse/core'
|
|
|
3
3
|
import { computed, ref, watch } from 'vue'
|
|
4
4
|
import SDivider from '../../../components/SDivider.vue'
|
|
5
5
|
import { useQuery } from '../../../composables/Api'
|
|
6
|
+
import { useLang } from '../../../composables/Lang'
|
|
6
7
|
import { usePower } from '../../../composables/Power'
|
|
7
8
|
import { type FieldData } from '../FieldData'
|
|
8
9
|
import { type LensQuery, type LensQuerySort } from '../LensQuery'
|
|
@@ -180,12 +181,15 @@ const _overrides = ref(props.overrides ?? {})
|
|
|
180
181
|
const page = ref(1)
|
|
181
182
|
const perPage = ref(100)
|
|
182
183
|
|
|
184
|
+
const lang = useLang()
|
|
185
|
+
|
|
183
186
|
const { data: result, execute: refresh, loading } = useQuery(async (http) => {
|
|
184
187
|
const input = {
|
|
185
188
|
entity: props.entity ?? '__no_entity__',
|
|
186
189
|
select: withIndexField(_select.value),
|
|
187
190
|
filters: createInputFilters(queryFilter.value, _filters.value),
|
|
188
191
|
sort: _sort.value.length > 0 ? _sort.value : defaultSort.value ?? [],
|
|
192
|
+
settings: { lang },
|
|
189
193
|
page: page.value,
|
|
190
194
|
perPage: perPage.value
|
|
191
195
|
}
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { type ValidationArgs, type ValidationRuleWithParams } from '@vuelidate/core'
|
|
2
2
|
import { type Day, day } from '../../../support/Day'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
after,
|
|
5
|
+
afterOrEqual,
|
|
6
|
+
before,
|
|
7
|
+
beforeOrEqual,
|
|
8
|
+
maxLength,
|
|
9
|
+
required,
|
|
10
|
+
slackChannelLink,
|
|
11
|
+
slackChannelName
|
|
12
|
+
} from '../../../validation/rules'
|
|
4
13
|
import { type Rule } from '../Rule'
|
|
5
14
|
|
|
6
15
|
/**
|
|
@@ -19,6 +28,8 @@ function mapRule(rule: Rule): ValidationRuleWithParams {
|
|
|
19
28
|
return maxLength(rule.length)
|
|
20
29
|
case 'required':
|
|
21
30
|
return required()
|
|
31
|
+
case 'slack_channel_link':
|
|
32
|
+
return slackChannelLink()
|
|
22
33
|
case 'slack_channel_name':
|
|
23
34
|
return slackChannelName({ offset: rule.offset })
|
|
24
35
|
case 'before':
|
|
@@ -24,6 +24,7 @@ export { requiredIf } from './requiredIf'
|
|
|
24
24
|
export { requiredYmd } from './requiredYmd'
|
|
25
25
|
export { requiredYmdIf } from './requiredYmdIf'
|
|
26
26
|
export { rule } from './rule'
|
|
27
|
+
export { slackChannelLink } from './slackChannelLink'
|
|
27
28
|
export { slackChannelName } from './slackChannelName'
|
|
28
29
|
export { url } from './url'
|
|
29
30
|
export { ymd } from './ymd'
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createRule } from '../Rule'
|
|
2
|
+
import { slackChannelLink as baseSlackChannelLink } from '../validators'
|
|
3
|
+
|
|
4
|
+
export const message = {
|
|
5
|
+
en: 'The slack channel link is invalid.',
|
|
6
|
+
ja: 'Slackチャンネルリンクの形式が正しくありません。'
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function slackChannelLink(msg?: string) {
|
|
10
|
+
return createRule({
|
|
11
|
+
message: ({ lang }) => msg ?? message[lang],
|
|
12
|
+
optional: true,
|
|
13
|
+
validation: baseSlackChannelLink
|
|
14
|
+
})
|
|
15
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const channelIdRE = /^[CG][A-Z0-9]{6,}$/
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Checks that the value identifies a Slack channel. Accepts a channel link as
|
|
5
|
+
* copied from Slack (`https://<workspace>.slack.com/archives/<id>`, with or
|
|
6
|
+
* without a trailing message path), a browser URL
|
|
7
|
+
* (`https://app.slack.com/client/<team-id>/<id>`), or a raw channel ID.
|
|
8
|
+
* Mirrors the backend `slack_channel_link` rule definition.
|
|
9
|
+
*/
|
|
10
|
+
export function slackChannelLink(value: unknown): boolean {
|
|
11
|
+
return typeof value === 'string' && extractChannelId(value) !== null
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function extractChannelId(value: string): string | null {
|
|
15
|
+
const trimmed = value.trim()
|
|
16
|
+
|
|
17
|
+
if (channelIdRE.test(trimmed)) {
|
|
18
|
+
return trimmed
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return extractChannelIdFromUrl(trimmed)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function extractChannelIdFromUrl(value: string): string | null {
|
|
25
|
+
let url: URL
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
url = new URL(value)
|
|
29
|
+
} catch {
|
|
30
|
+
return null
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (url.protocol !== 'https:') {
|
|
34
|
+
return null
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (url.hostname !== 'slack.com' && !url.hostname.endsWith('.slack.com')) {
|
|
38
|
+
return null
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const segments = url.pathname.split('/').filter((segment) => segment !== '')
|
|
42
|
+
|
|
43
|
+
let candidate: string | undefined
|
|
44
|
+
|
|
45
|
+
if (segments[0] === 'archives') {
|
|
46
|
+
candidate = segments[1]
|
|
47
|
+
} else if (url.hostname === 'app.slack.com' && segments[0] === 'client') {
|
|
48
|
+
candidate = segments[2]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return candidate !== undefined && channelIdRE.test(candidate) ? candidate : null
|
|
52
|
+
}
|