mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Customizable stripe plans.
Summary: - Reading plans from Stripe, and allowing Stripe to define custom plans. - Storing product features (aka limits) in Stripe, that override those in db. - Adding hierarchical data in Stripe. All features are defined at Product level but can be overwritten on Price levels. - New options for Support user to -- Override product for team site (if he is added as a billing manager) -- Override subscription and customer id for a team site -- Attach an "offer", an custom plan configured in stripe that a team site can use -- Enabling wire transfer for subscription by allowing subscription to be created without a payment method (which is customizable) Test Plan: Updated and new. Reviewers: georgegevoian Reviewed By: georgegevoian Differential Revision: https://phab.getgrist.com/D4201
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import {theme} from 'app/client/ui2018/cssVars';
|
||||
import {DomArg, keyframes, styled} from 'grainjs';
|
||||
import {DomArg, keyframes, Observable, observable, styled} from 'grainjs';
|
||||
|
||||
const rotate360 = keyframes(`
|
||||
from { transform: rotate(45deg); }
|
||||
@@ -42,6 +42,21 @@ export function loadingDots(...args: DomArg<HTMLDivElement>[]) {
|
||||
);
|
||||
}
|
||||
|
||||
export function watchPromise<T extends (...args: any[]) => any>(fun: T): T & {busy: Observable<boolean>} {
|
||||
const loading = observable(false);
|
||||
const result = async (...args: any) => {
|
||||
loading.set(true);
|
||||
try {
|
||||
return await fun(...args);
|
||||
} finally {
|
||||
if (!loading.isDisposed()) {
|
||||
loading.set(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
return Object.assign(result, {busy: loading}) as any;
|
||||
}
|
||||
|
||||
const cssLoadingDotsContainer = styled('div', `
|
||||
--dot-size: 10px;
|
||||
display: inline-flex;
|
||||
|
||||
@@ -416,8 +416,8 @@ export function confirmModal(
|
||||
*/
|
||||
export function promptModal(
|
||||
title: string,
|
||||
onConfirm: (text: string) => Promise<unknown>,
|
||||
btnText: string,
|
||||
onConfirm: (text: string) => Promise<void>,
|
||||
btnText?: string,
|
||||
initial?: string,
|
||||
placeholder?: string,
|
||||
onCancel?: () => void
|
||||
@@ -429,7 +429,7 @@ export function promptModal(
|
||||
const options: ISaveModalOptions = {
|
||||
title,
|
||||
body: txtInput,
|
||||
saveLabel: btnText,
|
||||
saveLabel: btnText || t('Save'),
|
||||
saveFunc: () => {
|
||||
// Mark that confirm was invoked.
|
||||
confirmed = true;
|
||||
|
||||
Reference in New Issue
Block a user