@platforma-sdk/ui-vue 1.28.1 → 1.28.3

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.
Files changed (46) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/lib.js +8424 -8044
  3. package/dist/lib.js.map +1 -1
  4. package/dist/lib.umd.cjs +18 -18
  5. package/dist/lib.umd.cjs.map +1 -1
  6. package/dist/src/components/BlockLayout.vue.d.ts +1 -1
  7. package/dist/src/components/BlockLayout.vue.d.ts.map +1 -1
  8. package/dist/src/components/PlAgDataTable/PlAgDataTable.vue.d.ts +2 -2
  9. package/dist/src/lib.d.ts +0 -1
  10. package/dist/src/lib.d.ts.map +1 -1
  11. package/dist/src/plugins/Monetization/LimitCard.vue.d.ts +10 -0
  12. package/dist/src/plugins/Monetization/LimitCard.vue.d.ts.map +1 -0
  13. package/dist/src/plugins/Monetization/MonetizationSidebar.vue.d.ts +3 -0
  14. package/dist/src/plugins/Monetization/MonetizationSidebar.vue.d.ts.map +1 -0
  15. package/dist/src/plugins/Monetization/RunStatus.vue.d.ts +6 -0
  16. package/dist/src/plugins/Monetization/RunStatus.vue.d.ts.map +1 -0
  17. package/dist/src/plugins/Monetization/UserCabinetCard.vue.d.ts +6 -0
  18. package/dist/src/plugins/Monetization/UserCabinetCard.vue.d.ts.map +1 -0
  19. package/dist/src/plugins/Monetization/index.d.ts +3 -0
  20. package/dist/src/plugins/Monetization/index.d.ts.map +1 -0
  21. package/dist/src/plugins/Monetization/useButtonTarget.d.ts +2 -0
  22. package/dist/src/plugins/Monetization/useButtonTarget.d.ts.map +1 -0
  23. package/dist/src/plugins/Monetization/useInfo.d.ts +21 -0
  24. package/dist/src/plugins/Monetization/useInfo.d.ts.map +1 -0
  25. package/dist/src/plugins/Monetization/validation.d.ts +224 -0
  26. package/dist/src/plugins/Monetization/validation.d.ts.map +1 -0
  27. package/dist/src/types.d.ts +0 -5
  28. package/dist/src/types.d.ts.map +1 -1
  29. package/dist/style.css +1 -1
  30. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  31. package/package.json +2 -2
  32. package/src/components/BlockLayout.vue +3 -0
  33. package/src/lib.ts +0 -2
  34. package/src/plugins/.gitkeep +0 -0
  35. package/src/plugins/Monetization/LimitCard.vue +162 -0
  36. package/src/plugins/Monetization/MonetizationSidebar.vue +241 -0
  37. package/src/plugins/Monetization/RunStatus.vue +79 -0
  38. package/src/plugins/Monetization/UserCabinetCard.vue +195 -0
  39. package/src/plugins/Monetization/index.ts +5 -0
  40. package/src/plugins/Monetization/useButtonTarget.ts +23 -0
  41. package/src/plugins/Monetization/useInfo.ts +42 -0
  42. package/src/plugins/Monetization/validation.ts +53 -0
  43. package/src/types.ts +0 -6
  44. package/dist/src/composition/useWatchFetch.d.ts +0 -24
  45. package/dist/src/composition/useWatchFetch.d.ts.map +0 -1
  46. package/src/composition/useWatchFetch.ts +0 -63
@@ -0,0 +1,5 @@
1
+ import MonetizationSidebar from './MonetizationSidebar.vue';
2
+
3
+ export {
4
+ MonetizationSidebar,
5
+ };
@@ -0,0 +1,23 @@
1
+ import { ref, nextTick, onMounted, onUpdated } from 'vue';
2
+
3
+ export function useButtonTarget() {
4
+ const target = ref<string>();
5
+
6
+ const selector = '.pl-block-page__title__append';
7
+
8
+ const check = () => {
9
+ nextTick(() => {
10
+ target.value = document.querySelector(selector) ? selector : undefined;
11
+ if (!target.value) {
12
+ console.error(
13
+ `[Monetization] use #title slot to place monetization button`,
14
+ );
15
+ }
16
+ });
17
+ };
18
+
19
+ onMounted(check);
20
+ onUpdated(check);
21
+
22
+ return target;
23
+ }
@@ -0,0 +1,42 @@
1
+ import { computed, watch, ref } from 'vue';
2
+ import { useSdkPlugin } from '../../defineApp';
3
+ import { Response } from './validation';
4
+
5
+ export function useInfo() {
6
+ const sdk = useSdkPlugin();
7
+
8
+ const app = computed(() => (sdk.loaded ? sdk.useApp() : undefined));
9
+
10
+ const hasMonetization = computed(() => '__mnzDate' in (app.value?.model?.args as Record<string, unknown>));
11
+
12
+ const mnzInfo = computed(() => Response.safeParse(app.value?.model.outputs['__mnzInfo']));
13
+
14
+ const currentInfo = computed<Response | undefined>(() => mnzInfo.value?.data);
15
+
16
+ const info = ref<Response | undefined>(undefined);
17
+
18
+ const error = computed(() => mnzInfo.value?.error ?? info.value?.response?.error);
19
+
20
+ watch([currentInfo], ([i]) => {
21
+ if (i) {
22
+ info.value = i;
23
+ }
24
+ }, { immediate: true });
25
+
26
+ const result = computed(() => info.value?.response?.result);
27
+
28
+ const canRun = computed(() => !!result.value?.canRun);
29
+
30
+ watch(canRun, (v) => {
31
+ if (v && hasMonetization.value) {
32
+ (app.value?.model.args as Record<string, unknown>)['__mnzCanRun'] = v;
33
+ }
34
+ });
35
+
36
+ return {
37
+ hasMonetization,
38
+ result,
39
+ error,
40
+ canRun,
41
+ };
42
+ }
@@ -0,0 +1,53 @@
1
+ import { z } from 'zod';
2
+
3
+ const MonetizationTrial = z.literal('trial');
4
+ const MonetizationFree = z.literal('free');
5
+ const MonetizationSinglePayment = z.literal('single_payment');
6
+ const MonetizationSubscription = z.literal('subscription');
7
+
8
+ const MonetizationType = z.union([
9
+ MonetizationTrial,
10
+ MonetizationFree,
11
+ MonetizationSinglePayment,
12
+ MonetizationSubscription,
13
+ z.literal('base'), // outdated
14
+ ]);
15
+
16
+ const DryRunResult = z.object({
17
+ productKey: z.string(),
18
+ productName: z.string().default('Unknown product'),
19
+ canRun: z.boolean(),
20
+ status: z.union([
21
+ z.literal('select-tariff'),
22
+ z.literal('active'),
23
+ z.literal('payment_required'),
24
+ z.unknown(),
25
+ ]),
26
+ mnz: z.object({
27
+ type: MonetizationType.optional(),
28
+ details: z.object({
29
+ spentRuns: z.number(),
30
+ runsToSpend: z.number(),
31
+ willRemainAfterRun: z.number().nullable(),
32
+ subscription: z.unknown(),
33
+ }),
34
+ }),
35
+ }, { message: 'Invalid CreateProductStatResult' });
36
+
37
+ type DryRunResult = z.infer<typeof DryRunResult>;
38
+
39
+ const Response = z.object({
40
+ httpError: z.string().optional(),
41
+ response: z.object({
42
+ result: DryRunResult.optional(),
43
+ error: z.unknown().optional(),
44
+ }).optional(),
45
+ }).optional();
46
+
47
+ type Response = z.infer<typeof Response>;
48
+
49
+ export {
50
+ MonetizationType,
51
+ DryRunResult,
52
+ Response,
53
+ };
package/src/types.ts CHANGED
@@ -92,12 +92,6 @@ export type ExtendSettings<Href extends `/${string}` = `/${string}`> = {
92
92
  routes: Routes<Href>;
93
93
  };
94
94
 
95
- export type FetchResult<V, E = unknown> = {
96
- loading: boolean;
97
- value: V | undefined;
98
- error: E;
99
- };
100
-
101
95
  // Results (ValueOrErrors)
102
96
 
103
97
  export type UnwrapValueOrError<W> = W extends {
@@ -1,24 +0,0 @@
1
- import type { WatchSource, WatchOptions } from 'vue';
2
- import type { FetchResult } from '../types';
3
- /**
4
- * Watch any reactive source and perform an asynchronous operation
5
- *
6
- * @example
7
- * ```ts
8
- * const v = useWatchFetch(
9
- * watchSource,
10
- * async (sourceValue) => {
11
- * return await fetchDataFromApi(sourceValue);
12
- * }
13
- * );
14
- *
15
- * // Usage in a template
16
- * <template>
17
- * <div v-if="v.loading">Loading...</div>
18
- * <div v-else-if="v.error">Error: {{ v.error.message }}</div>
19
- * <div v-else>Data: {{ v.value }}</div>
20
- * </template>
21
- * ```
22
- */
23
- export declare function useWatchFetch<S, V>(watchSource: WatchSource<S>, doFetch: (s: S) => Promise<V>, watchOptions?: WatchOptions): FetchResult<V>;
24
- //# sourceMappingURL=useWatchFetch.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useWatchFetch.d.ts","sourceRoot":"","sources":["../../../src/composition/useWatchFetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,KAAK,CAAC;AAGrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAI5C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,EAAE,YAAY,GAAG,WAAW,CAAC,CAAC,CAAC,CAmC3I"}
@@ -1,63 +0,0 @@
1
- import type { WatchSource, WatchOptions } from 'vue';
2
- import { reactive, watch, ref, computed } from 'vue';
3
- import { exclusiveRequest } from '@milaboratories/helpers';
4
- import type { FetchResult } from '../types';
5
-
6
- // TODO Should we keep the old value while fetching the new value?
7
-
8
- /**
9
- * Watch any reactive source and perform an asynchronous operation
10
- *
11
- * @example
12
- * ```ts
13
- * const v = useWatchFetch(
14
- * watchSource,
15
- * async (sourceValue) => {
16
- * return await fetchDataFromApi(sourceValue);
17
- * }
18
- * );
19
- *
20
- * // Usage in a template
21
- * <template>
22
- * <div v-if="v.loading">Loading...</div>
23
- * <div v-else-if="v.error">Error: {{ v.error.message }}</div>
24
- * <div v-else>Data: {{ v.value }}</div>
25
- * </template>
26
- * ```
27
- */
28
- export function useWatchFetch<S, V>(watchSource: WatchSource<S>, doFetch: (s: S) => Promise<V>, watchOptions?: WatchOptions): FetchResult<V> {
29
- const loadingRef = ref(0);
30
-
31
- const data = reactive({
32
- loading: computed(() => loadingRef.value > 0),
33
- loadingRef,
34
- value: undefined as V,
35
- error: undefined,
36
- }) as FetchResult<V>;
37
-
38
- const exclusive = exclusiveRequest(doFetch);
39
-
40
- watch(
41
- watchSource,
42
- async (s) => {
43
- data.error = undefined;
44
- loadingRef.value++;
45
- exclusive(s)
46
- .then((res) => {
47
- if (res.ok) {
48
- data.value = res.value;
49
- }
50
- })
51
- .catch((err) => {
52
- data.value = undefined;
53
- data.error = err;
54
- })
55
- .finally(() => {
56
- loadingRef.value--;
57
- });
58
- },
59
- Object.assign({ immediate: true, deep: true }, watchOptions ?? {}),
60
- );
61
-
62
- return data;
63
- }