@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.
- package/CHANGELOG.md +16 -0
- package/dist/lib.js +8424 -8044
- package/dist/lib.js.map +1 -1
- package/dist/lib.umd.cjs +18 -18
- package/dist/lib.umd.cjs.map +1 -1
- package/dist/src/components/BlockLayout.vue.d.ts +1 -1
- package/dist/src/components/BlockLayout.vue.d.ts.map +1 -1
- package/dist/src/components/PlAgDataTable/PlAgDataTable.vue.d.ts +2 -2
- package/dist/src/lib.d.ts +0 -1
- package/dist/src/lib.d.ts.map +1 -1
- package/dist/src/plugins/Monetization/LimitCard.vue.d.ts +10 -0
- package/dist/src/plugins/Monetization/LimitCard.vue.d.ts.map +1 -0
- package/dist/src/plugins/Monetization/MonetizationSidebar.vue.d.ts +3 -0
- package/dist/src/plugins/Monetization/MonetizationSidebar.vue.d.ts.map +1 -0
- package/dist/src/plugins/Monetization/RunStatus.vue.d.ts +6 -0
- package/dist/src/plugins/Monetization/RunStatus.vue.d.ts.map +1 -0
- package/dist/src/plugins/Monetization/UserCabinetCard.vue.d.ts +6 -0
- package/dist/src/plugins/Monetization/UserCabinetCard.vue.d.ts.map +1 -0
- package/dist/src/plugins/Monetization/index.d.ts +3 -0
- package/dist/src/plugins/Monetization/index.d.ts.map +1 -0
- package/dist/src/plugins/Monetization/useButtonTarget.d.ts +2 -0
- package/dist/src/plugins/Monetization/useButtonTarget.d.ts.map +1 -0
- package/dist/src/plugins/Monetization/useInfo.d.ts +21 -0
- package/dist/src/plugins/Monetization/useInfo.d.ts.map +1 -0
- package/dist/src/plugins/Monetization/validation.d.ts +224 -0
- package/dist/src/plugins/Monetization/validation.d.ts.map +1 -0
- package/dist/src/types.d.ts +0 -5
- package/dist/src/types.d.ts.map +1 -1
- package/dist/style.css +1 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/components/BlockLayout.vue +3 -0
- package/src/lib.ts +0 -2
- package/src/plugins/.gitkeep +0 -0
- package/src/plugins/Monetization/LimitCard.vue +162 -0
- package/src/plugins/Monetization/MonetizationSidebar.vue +241 -0
- package/src/plugins/Monetization/RunStatus.vue +79 -0
- package/src/plugins/Monetization/UserCabinetCard.vue +195 -0
- package/src/plugins/Monetization/index.ts +5 -0
- package/src/plugins/Monetization/useButtonTarget.ts +23 -0
- package/src/plugins/Monetization/useInfo.ts +42 -0
- package/src/plugins/Monetization/validation.ts +53 -0
- package/src/types.ts +0 -6
- package/dist/src/composition/useWatchFetch.d.ts +0 -24
- package/dist/src/composition/useWatchFetch.d.ts.map +0 -1
- package/src/composition/useWatchFetch.ts +0 -63
|
@@ -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
|
-
}
|