frappe-ui 0.1.99 → 0.1.101

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frappe-ui",
3
- "version": "0.1.99",
3
+ "version": "0.1.101",
4
4
  "description": "A set of components and utilities for rapid UI development",
5
5
  "main": "./src/index.js",
6
6
  "scripts": {
@@ -29,7 +29,11 @@
29
29
  :id="id"
30
30
  v-bind="{ ...controlAttrs, size }"
31
31
  />
32
- <TextInput v-else :id="id" v-bind="{ ...controlAttrs, type, size }">
32
+ <TextInput
33
+ v-else
34
+ :id="id"
35
+ v-bind="{ ...controlAttrs, type, size, required }"
36
+ >
33
37
  <template #prefix v-if="$slots.prefix">
34
38
  <slot name="prefix" />
35
39
  </template>
@@ -22,6 +22,7 @@
22
22
  :disabled="disabled"
23
23
  :id="id"
24
24
  :value="modelValue"
25
+ :required="required"
25
26
  @input="handleChange"
26
27
  @change="handleChange"
27
28
  v-bind="attrsWithoutClassStyle"
@@ -53,6 +54,7 @@ interface TextInputProps {
53
54
  id?: string
54
55
  modelValue?: string | number
55
56
  debounce?: number
57
+ required?: boolean
56
58
  }
57
59
 
58
60
  defineOptions({
@@ -145,7 +145,7 @@ describe('useCall', () => {
145
145
  const call = useCall<Response>({
146
146
  url: url('/api/v2/method/post'),
147
147
  method: 'POST',
148
- refetch: true,
148
+ refetch: false,
149
149
  immediate: false,
150
150
  })
151
151
 
@@ -88,11 +88,15 @@ export function useCall<TResponse, TParams extends BasicParams = undefined>(
88
88
  canAbort,
89
89
  aborted,
90
90
  abort,
91
- execute,
91
+ execute: _execute,
92
92
  onFetchResponse,
93
93
  onFetchError,
94
94
  } = result
95
95
 
96
+ function execute(): Promise<TResponse | null> {
97
+ return _execute().then((r) => data.value)
98
+ }
99
+
96
100
  onFetchResponse(() => {
97
101
  resolve()
98
102
  promise.value = makePromise()
@@ -107,7 +111,9 @@ export function useCall<TResponse, TParams extends BasicParams = undefined>(
107
111
  if (beforeSubmit) {
108
112
  beforeSubmit(params)
109
113
  }
110
- submitParams.value = params
114
+ if (params != null) {
115
+ submitParams.value = params
116
+ }
111
117
  if (!refetch) {
112
118
  return execute()
113
119
  }
@@ -122,14 +128,14 @@ export function useCall<TResponse, TParams extends BasicParams = undefined>(
122
128
 
123
129
  const _data = computed(() => {
124
130
  if (normalizedCacheKey && (out.loading || !out.isFinished)) {
125
- let data = cachedResponse.value as TResponse
131
+ let cachedData = cachedResponse.value as TResponse
126
132
  if (transform) {
127
- let returnValue = transform(data)
133
+ let returnValue = transform(cachedData)
128
134
  if (returnValue !== undefined) {
129
- data = returnValue
135
+ cachedData = returnValue
130
136
  }
131
137
  }
132
- return data
138
+ return cachedData
133
139
  }
134
140
  return data.value
135
141
  })
@@ -100,7 +100,7 @@ export function useDoc<TDoc extends { name: string }, TMethods = {}>(
100
100
 
101
101
  let callOptions: UseCallOptions = {
102
102
  immediate: false,
103
- refetch: true,
103
+ refetch: false,
104
104
  method: 'POST',
105
105
  ...option,
106
106
  baseUrl,
@@ -1,7 +1,9 @@
1
- import { Reactive, Ref } from 'vue'
1
+ import { MaybeRefOrGetter, Reactive, Ref } from 'vue'
2
2
  import { CacheKey } from '../useCall/types'
3
3
 
4
4
  export type Field = string
5
+ export type LinkField = `${Field}.${Field}` | `${Field}.${Field} as ${string}`
6
+ export type FieldWithAlias = `${Field} as ${string}`
5
7
 
6
8
  export type ChildTableField = {
7
9
  [key: string]: Field[]
@@ -25,9 +27,9 @@ export type OrderBy =
25
27
 
26
28
  export interface UseListOptions<T> {
27
29
  doctype: string
28
- fields?: Array<keyof T | ChildTableField>
29
- filters?: Reactive<Filters>
30
- orderBy?: OrderBy
30
+ fields?: Array<keyof T | ChildTableField | LinkField | FieldWithAlias | '*'>
31
+ filters?: MaybeRefOrGetter<Filters>
32
+ orderBy?: MaybeRefOrGetter<OrderBy>
31
33
  start?: number
32
34
  limit?: number
33
35
  groupBy?: Field
@@ -44,7 +46,4 @@ export interface UseListOptions<T> {
44
46
  onError?: (error: Error) => void
45
47
  }
46
48
 
47
- export interface UseListResponse<T> {
48
- result: T[]
49
- has_next_page: boolean
50
- }
49
+ export type UseListResponse<T> = T[]
@@ -27,7 +27,7 @@ describe('useList', () => {
27
27
  // Verify initial state
28
28
  expect(users.data).toBe(null)
29
29
  expect(users.error).toBe(null)
30
- expect(users.hasNextPage).toBe(false)
30
+ expect(users.hasNextPage).toBe(true)
31
31
  expect(typeof users.fetch).toBe('function')
32
32
 
33
33
  // fetch
@@ -46,11 +46,12 @@ export function useList<T extends { name: string }>(
46
46
  const _limit = ref(limit || 20)
47
47
 
48
48
  const _url = computed(() => {
49
- const parsedFilters = parseFilters(filters || {})
49
+ const parsedFilters = parseFilters(filters ? toValue(filters) : {})
50
+ const _fields = fields ? toValue(fields) : []
50
51
  const params = makeGetParams({
51
- fields: fields?.length ? JSON.stringify(fields) : null,
52
+ fields: _fields.length ? JSON.stringify(_fields) : null,
52
53
  filters: parsedFilters ? JSON.stringify(parsedFilters) : null,
53
- order_by: orderBy,
54
+ order_by: toValue(orderBy),
54
55
  start: _start.value,
55
56
  limit: _limit.value,
56
57
  group_by: groupBy,
@@ -64,14 +65,20 @@ export function useList<T extends { name: string }>(
64
65
  })
65
66
 
66
67
  const allData: Ref<T[] | null> = ref(null)
68
+ const hasNextPage = ref(true)
69
+ const hasPreviousPage = computed(() => _start.value > 0)
67
70
 
68
71
  const fetchOptions: UseFetchOptions = {
69
72
  immediate,
70
73
  refetch,
71
- initialData: initialData
72
- ? { result: initialData, has_next_page: false }
73
- : null,
74
- afterFetch: handleAfterFetch<T>({ ...options, allData, _start }),
74
+ initialData: initialData || null,
75
+ afterFetch: handleAfterFetch<T>({
76
+ ...options,
77
+ allData,
78
+ _start,
79
+ _limit,
80
+ hasNextPage,
81
+ }),
75
82
  onFetchError: handleFetchError<T>(options),
76
83
  }
77
84
 
@@ -94,24 +101,16 @@ export function useList<T extends { name: string }>(
94
101
  let data = cachedResponse.value
95
102
  if (data) {
96
103
  if (transform) {
97
- let returnValue = transform(data.result as T[])
104
+ let returnValue = transform(data as T[])
98
105
  if (returnValue !== undefined) {
99
106
  return returnValue
100
107
  }
101
108
  }
102
- return data.result
109
+ return data
103
110
  }
104
111
  }
105
112
  return allData.value
106
113
  })
107
- const hasNextPage = computed(() => {
108
- if (normalizedCacheKey && (out.loading || !out.isFinished)) {
109
- let data = cachedResponse.value
110
- return data?.has_next_page ?? false
111
- }
112
- return data.value?.has_next_page ?? false
113
- })
114
- const hasPreviousPage = computed(() => _start.value > 0)
115
114
 
116
115
  if (normalizedCacheKey) {
117
116
  idbStore.get(normalizedCacheKey).then((data) => {
@@ -247,7 +246,7 @@ export function useList<T extends { name: string }>(
247
246
 
248
247
  let out = reactive({
249
248
  data: result,
250
- hasNextPage,
249
+ hasNextPage: readonly(hasNextPage),
251
250
  hasPreviousPage,
252
251
  start: readonly(_start),
253
252
  limit: readonly(_limit),
@@ -283,15 +282,24 @@ function handleAfterFetch<T extends { name: string }>({
283
282
  cacheKey,
284
283
  allData,
285
284
  _start,
285
+ _limit,
286
+ hasNextPage,
286
287
  }: UseListOptions<T> & {
287
288
  allData: Ref<T[] | null>
288
289
  _start: Ref<number>
290
+ _limit: Ref<number>
291
+ hasNextPage: Ref<boolean>
289
292
  }) {
290
293
  return function (ctx: AfterFetchContext) {
291
- let resultData = (ctx.data.result as T[]).map((item) => ({
292
- ...item,
293
- name: String(item.name),
294
- }))
294
+ let resultData = ctx.data
295
+ if (resultData[0]?.name) {
296
+ resultData = resultData.map((item) => ({
297
+ ...item,
298
+ name: String(item.name),
299
+ }))
300
+ }
301
+ hasNextPage.value = resultData.length < _limit.value ? false : true
302
+
295
303
  if (transform) {
296
304
  const returnValue = transform(resultData)
297
305
  if (Array.isArray(returnValue)) {
@@ -300,11 +308,11 @@ function handleAfterFetch<T extends { name: string }>({
300
308
  }
301
309
 
302
310
  if (_start.value === 0) {
303
- allData.value = resultData
311
+ allData.value = resultData as T[]
304
312
  } else {
305
313
  allData.value = [...(allData.value || []), ...resultData]
306
314
  }
307
- ctx.data.result = allData.value
315
+ ctx.data = allData.value
308
316
 
309
317
  let normalizedCacheKey = normalizeCacheKey(cacheKey, 'useList')
310
318
  if (normalizedCacheKey) {
@@ -1,6 +1,7 @@
1
1
  import { reactive, unref } from 'vue'
2
2
  import { useCall } from '../useCall/useCall'
3
3
  import { UseCallOptions } from '../useCall/types'
4
+ import { docStore } from '../docStore'
4
5
 
5
6
  type UseNewDocOptions = Omit<
6
7
  UseCallOptions,
@@ -18,7 +19,11 @@ export function useNewDoc<T extends object>(
18
19
  ) {
19
20
  let doc = reactive<NewDoc<T>>(initialValues)
20
21
 
21
- const out = useCall<T>({
22
+ type DocResponse = T & {
23
+ name: string
24
+ }
25
+
26
+ const out = useCall<DocResponse>({
22
27
  url: `/api/v2/document/${doctype}`,
23
28
  method: 'POST',
24
29
  params() {
@@ -34,8 +39,19 @@ export function useNewDoc<T extends object>(
34
39
  ...options,
35
40
  })
36
41
 
42
+ function submit() {
43
+ return out
44
+ .submit()
45
+ .then((doc) =>
46
+ docStore
47
+ .setDoc({ doctype, ...(doc as DocResponse) })
48
+ .then(() => docStore.getDoc(doctype, doc.name.toString()).value as T),
49
+ )
50
+ }
51
+
37
52
  return reactive({
38
53
  ...out,
54
+ submit,
39
55
  doc,
40
56
  })
41
57
  }
@@ -59,10 +59,7 @@ export const handlers = [
59
59
  let result = getUsers(listParams)
60
60
 
61
61
  return HttpResponse.json({
62
- data: {
63
- result,
64
- has_next_page: true,
65
- },
62
+ data: result,
66
63
  })
67
64
  }),
68
65