Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integration with Stripe for premium features + some new features #335

Merged
merged 106 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
bee6ea5
basic stripe low-code implementation
DonKoko Aug 2, 2023
7a88715
Merge branch 'main' into premium
DonKoko Aug 4, 2023
412998a
adding route for subscription
DonKoko Aug 4, 2023
7ce1485
subscription endpoint, fetching prices and products from stripe and r…
DonKoko Aug 4, 2023
032e0ed
adding customerId to User and stripe cusomer creating documentation
DonKoko Aug 4, 2023
77de176
further layout of subscriptions page, customer portal functionality, …
DonKoko Aug 7, 2023
2bcba08
fixing some UI issues, moving features list to product metadata in st…
DonKoko Aug 7, 2023
4a8b76c
adding slogan
DonKoko Aug 7, 2023
addb051
merge with main and fix conflicts
DonKoko Aug 9, 2023
7e13cb1
getting customer and subscription from stripe
DonKoko Aug 9, 2023
ad9743e
adding schema for tiers
DonKoko Aug 9, 2023
5ed21bc
adding Tier model
DonKoko Aug 9, 2023
3ff4ecd
handling webhook for checkout.session.completed & customer.subscripti…
DonKoko Aug 10, 2023
067e8da
webhook for stopped subscription:
DonKoko Aug 10, 2023
48b9f37
clean up webhook code
DonKoko Aug 10, 2023
ef898f7
Merge remote-tracking branch 'origin/main' into premium
DonKoko Aug 11, 2023
cb8e32f
added tierLimit table as well as migration that creates tier limit ma…
DonKoko Aug 11, 2023
2639746
Merge remote-tracking branch 'origin/main' into premium
DonKoko Aug 15, 2023
52787cf
export & import buttons, adjusting some migrations
DonKoko Aug 15, 2023
a3ea18b
import/export routes + some adjustments to new asset button
DonKoko Aug 15, 2023
6c4c0bc
file exporting:
DonKoko Aug 15, 2023
4a083d1
Merge remote-tracking branch 'origin/main' into premium
DonKoko Aug 16, 2023
5ad2301
fixing webhook issue as well as making assets export
DonKoko Aug 16, 2023
e37ac9c
adding tags and qrcode to export
DonKoko Aug 16, 2023
f78022f
Merge remote-tracking branch 'origin/main' into premium
DonKoko Aug 17, 2023
655f9a0
making progress on import feature
DonKoko Aug 17, 2023
d913817
CSV importing errors handling & queries
DonKoko Aug 18, 2023
7932538
mend
DonKoko Aug 18, 2023
038d820
developed and integrated UI of subscriptions page
hunar1312 Aug 21, 2023
83fecc7
developed Successful subscription modal
hunar1312 Aug 21, 2023
a24b44d
Merge branch 'premium' into hunar/premium-frontend
hunar1312 Aug 21, 2023
5d764fc
few improvements
hunar1312 Aug 21, 2023
41d94d7
conditional creating of related entries for the purpose of importing …
DonKoko Aug 21, 2023
d7a9a10
minor ui improvements
hunar1312 Aug 22, 2023
e4e4f89
Merge pull request #308 from Shelf-nu/hunar/premium-frontend
DonKoko Aug 22, 2023
2b664c3
small front-end adjustments, adjusing how errors are handled, fixing …
DonKoko Aug 22, 2023
d7782ca
working on setting tags for content import
DonKoko Aug 22, 2023
357b31b
finializing tags and asset import from own content
DonKoko Aug 22, 2023
b42802a
Merge remote-tracking branch 'origin/main' into premium
DonKoko Aug 23, 2023
7d87e7f
finalizing import of content and working on import of backup
DonKoko Aug 24, 2023
ef82fbd
developed all UI screens for custom fields using hardcoded data
hunar1312 Aug 28, 2023
543fd16
removing unnecessary code for frontend
hunar1312 Aug 28, 2023
8822388
Merge remote-tracking branch 'origin/main' into premium and fix confl…
DonKoko Aug 28, 2023
dd7f20f
mend
DonKoko Aug 28, 2023
3d87434
adding migrations for custom fields as well as the tables that store …
DonKoko Aug 28, 2023
26c5ba4
Merge branch 'premium' into hunar/custom-fields
DonKoko Aug 28, 2023
969aa52
Merge branch 'main' into premium
DonKoko Aug 29, 2023
160a3d9
importing assets from backup
DonKoko Aug 30, 2023
10a8163
Merge branch 'premium' into hunar/custom-fields
DonKoko Aug 30, 2023
af51a99
crud on custom fields
hunar1312 Sep 1, 2023
da13b1d
Merge branch 'hunar/custom-fields' of https://github.com/Shelf-nu/she…
hunar1312 Sep 1, 2023
d19e49e
fixed some types in custom fields form, updated loader for custom fie…
DonKoko Sep 1, 2023
87e1b23
updating type select field
hunar1312 Sep 1, 2023
fba8c55
Merge remote-tracking branch 'origin/main' into premium
DonKoko Sep 1, 2023
989b4eb
asserting deletion is a delete request and displaying custom fields o…
hunar1312 Sep 1, 2023
8fe7ab3
fixed ts error
hunar1312 Sep 1, 2023
db96610
Merge branch 'main' into premium
DonKoko Sep 4, 2023
64ac293
developed edit custom field functionality (frontend + backend)
hunar1312 Sep 4, 2023
1bfcab5
importing backup remaining fields
DonKoko Sep 4, 2023
f1e23bf
comming soon for team upgrade button
DonKoko Sep 4, 2023
8a767ae
Merge branch 'premium' into hunar/custom-fields
DonKoko Sep 4, 2023
bdebc03
fixed route navigation in custom field list component
hunar1312 Sep 5, 2023
fd4cc4a
Merge branch 'hunar/custom-fields' of https://github.com/Shelf-nu/she…
hunar1312 Sep 5, 2023
75e4d98
creating schema with custom fields
DonKoko Sep 5, 2023
c7e6c37
adjusting validations to work with optional fields as well
DonKoko Sep 5, 2023
26875b9
adjusting custom field schema, creating some helper functions, updati…
DonKoko Sep 5, 2023
9f7b2a6
updating assets custom fields + some other small changes
DonKoko Sep 5, 2023
e64513a
added help text component for text field type selection in custom fie…
hunar1312 Sep 6, 2023
737d351
updated logic for hint text for custom field type
hunar1312 Sep 6, 2023
a281578
resolved requested changes
hunar1312 Sep 6, 2023
a812d99
fixing issue with inferring of types in the mergedSchema function
DonKoko Sep 6, 2023
beaf4db
update
hunar1312 Sep 6, 2023
bb5f668
Merge pull request #334 from Shelf-nu/hunar/custom-fields-alt
DonKoko Sep 6, 2023
46266b6
Merge pull request #321 from Shelf-nu/hunar/custom-fields
DonKoko Sep 6, 2023
f1cd4d1
fixing https://github.com/advisories/GHSA-hpx4-r86g-5jrg
DonKoko Sep 6, 2023
9618461
added active flag on CustomField, removed cascade deleting on AssetCu…
DonKoko Sep 6, 2023
11538c0
creating generic helpers to determine weather users can perform certa…
DonKoko Sep 6, 2023
a1e534f
adding some more server side assertions weather a user can perform pr…
DonKoko Sep 6, 2023
2887174
small fix
DonKoko Sep 6, 2023
466a680
Merge branch 'main' into premium
DonKoko Sep 7, 2023
d1afadb
fixing some small feedback, adding custom fields to export and import…
DonKoko Sep 7, 2023
c34a82e
disabled deletion of custom fields and added the concept of active/in…
hunar1312 Sep 7, 2023
8e865cc
asset import + custom fields based on template
DonKoko Sep 7, 2023
10f554a
UI update
hunar1312 Sep 8, 2023
6e6b128
fixed active switch
hunar1312 Sep 8, 2023
785a618
Merge branch 'premium' into hunar/custom-fields
DonKoko Sep 8, 2023
17b9836
resolved all feedbacks
hunar1312 Sep 8, 2023
3a8a732
Merge branch 'hunar/custom-fields' of https://github.com/Shelf-nu/she…
hunar1312 Sep 8, 2023
0728ab5
fixing details of importing from content with custom fields
DonKoko Sep 8, 2023
f471630
Merge pull request #338 from Shelf-nu/hunar/custom-fields
DonKoko Sep 8, 2023
804edfc
Merge branch 'main' into premium
DonKoko Sep 8, 2023
874fbd7
Merge branch 'main' into premium
DonKoko Sep 8, 2023
e95dd56
changing button color
DonKoko Sep 8, 2023
8fab3d3
small adjustments
DonKoko Sep 11, 2023
ff36b51
only show subscriptions menu item when premium is enabled
DonKoko Sep 12, 2023
ec60166
Merge remote-tracking branch 'origin/main' into premium
DonKoko Sep 12, 2023
b7ff175
fixing issues reported in #307
DonKoko Sep 12, 2023
24a976c
mend
DonKoko Sep 12, 2023
bfb5694
ui updates in custom fields list
hunar1312 Sep 12, 2023
d67529a
Merge pull request #352 from Shelf-nu/hunar/premium-ui-updates
DonKoko Sep 12, 2023
6c898f1
custom fields index
DonKoko Sep 12, 2023
fbbae06
Merge branch 'main' into premium
DonKoko Sep 13, 2023
d2635e4
fixing TS issue
DonKoko Sep 13, 2023
25d7038
fixed issues with parsing of custom fields for schema validation
DonKoko Sep 13, 2023
6b64713
Merge branch 'main' into premium
DonKoko Sep 13, 2023
5e121e9
fixing some small issues found when testing
DonKoko Sep 13, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions app/atoms/custom-fields.new.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { ChangeEvent } from "react";
import { atom } from "jotai";

export const titleAtom = atom("Untitled custom field");
export const updateTitleAtom = atom(
null,
(_get, set, event: ChangeEvent<HTMLInputElement>) =>
set(titleAtom, event.target.value)
);
83 changes: 83 additions & 0 deletions app/components/assets/custom-fields-inputs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import type { CustomField } from "@prisma/client";
import { Link, useLoaderData, useNavigation } from "@remix-run/react";
import type { Zorm } from "react-zorm";
import type { z } from "zod";
import type { loader } from "~/routes/_layout+/assets.$assetId_.edit";
import { isFormProcessing } from "~/utils";
import { zodFieldIsRequired } from "~/utils/zod";
import FormRow from "../forms/form-row";
import Input from "../forms/input";
import { SearchIcon } from "../icons";
import { Button } from "../shared";

export default function AssetCustomFields({
zo,
schema,
}: {
zo: Zorm<z.ZodObject<any, any, any>>;
schema: z.ZodObject<any, any, any>;
}) {
/** Get the custom fields from the loader */
const { customFields } = useLoaderData();

const { customFields: customFieldsValues } =
useLoaderData<typeof loader>()?.asset || [];

const navigation = useNavigation();
const disabled = isFormProcessing(navigation.state);

return (
<div className="border-b pb-6">
<div className="mb-6 border-b pb-5">
<h2 className="mb-1 text-[18px] font-semibold">Custom Fields</h2>
<Link
to="/settings/custom-fields"
className="font-medium text-primary-600"
>
Manage custom fields
</Link>
</div>
{customFields.length > 0 ? (
customFields.map((field: CustomField) => (
<FormRow
key={field.id}
rowLabel={field.name}
subHeading={field.helpText ? <p>{field.helpText}</p> : undefined}
className="border-b-0"
required={zodFieldIsRequired(schema.shape[`cf-${field.id}`])}
>
<Input
hideLabel
type={field.type.toLowerCase()}
label={field.name}
name={`cf-${field.id}`}
error={zo.errors[`cf-${field.id}`]()?.message}
disabled={disabled}
defaultValue={
customFieldsValues?.find(
(cfv) => cfv.customFieldId === field.id
)?.value || ""
}
className="w-full"
required={zodFieldIsRequired(schema.shape[`cf-${field.id}`])}
/>
</FormRow>
))
) : (
<div>
<div className=" mx-auto max-w-[640px] rounded-xl border border-gray-300 bg-white px-5 py-10 text-center">
<div>
<div className="mb-4 inline-flex items-center justify-center rounded-full border-8 border-solid border-gray-50 bg-gray-100 p-2 text-gray-600">
<SearchIcon />
</div>
<h4 className="mb-6 text-base">No active custom fields</h4>
<Button to="/settings/custom-fields/new" variant="primary">
Create custom fields
</Button>
</div>
</div>
</div>
)}
</div>
);
}
29 changes: 29 additions & 0 deletions app/components/assets/export-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useLoaderData } from "@remix-run/react";
import type { loader } from "~/routes/_layout+/assets._index";
import { PremiumFeatureButton } from "../subscription/premium-feature-button";

export const ExportButton = ({
canExportAssets,
}: {
canExportAssets: boolean;
}) => {
const { totalItems } = useLoaderData<typeof loader>();
return (
<PremiumFeatureButton
canUseFeature={canExportAssets}
buttonContent={{
title: "Export",
message: "Exporting is not available on the free tier of shelf.",
}}
buttonProps={{
to: `export/assets-${new Date().toISOString().slice(0, 10)}.csv`,
variant: "secondary",
role: "link",
download: true,
reloadDocument: true,
disabled: !canExportAssets || totalItems === 0,
title: totalItems === 0 ? "No assets to export" : "Export assets",
}}
/>
);
};
49 changes: 38 additions & 11 deletions app/components/assets/form.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import type { Asset, Qr } from "@prisma/client";
import { Form, Link, useNavigation } from "@remix-run/react";
import type { Asset, CustomField, Qr } from "@prisma/client";
import { Form, Link, useLoaderData, useNavigation } from "@remix-run/react";
import { useAtom, useAtomValue } from "jotai";
import type { Tag } from "react-tag-autocomplete";
import { useZorm } from "react-zorm";
import { z } from "zod";
import { updateTitleAtom } from "~/atoms/assets.new";
import { fileErrorAtom, validateFileAtom } from "~/atoms/file";
import { isFormProcessing } from "~/utils";

import { mergedSchema } from "~/utils/custom-field-schema";
import { zodFieldIsRequired } from "~/utils/zod";
import AssetCustomFields from "./custom-fields-inputs";

import { CategorySelect } from "../category/category-select";
import FormRow from "../forms/form-row";
import Input from "../forms/input";
Expand Down Expand Up @@ -47,7 +51,27 @@ export const AssetForm = ({
tags,
}: Props) => {
const navigation = useNavigation();
const zo = useZorm("NewQuestionWizardScreen", NewAssetFormSchema);

const { customFields } = useLoaderData();

// console.log(customFields);

const FormSchema = mergedSchema({
baseSchema: NewAssetFormSchema,
customFields: customFields.map(
(cf: CustomField) =>
cf.active && {
id: cf.id,
name: cf.name,
helpText: cf?.helpText || "",
required: cf.required,
type: cf.type.toLowerCase() as "text" | "number" | "date" | "boolean",
}
),
});

const zo = useZorm("NewQuestionWizardScreen", FormSchema);

const disabled = isFormProcessing(navigation.state);

const fileError = useAtomValue(fileErrorAtom);
Expand All @@ -67,7 +91,7 @@ export const AssetForm = ({
<FormRow
rowLabel={"Name"}
className="border-b-0 pb-[10px]"
required={zodFieldIsRequired(NewAssetFormSchema.shape.title)}
required={zodFieldIsRequired(FormSchema.shape.title)}
>
<Input
label="Name"
Expand All @@ -79,7 +103,7 @@ export const AssetForm = ({
onChange={updateTitle}
className="w-full"
defaultValue={title || ""}
required={zodFieldIsRequired(NewAssetFormSchema.shape.title)}
required={zodFieldIsRequired(FormSchema.shape.title)}
/>
</FormRow>

Expand Down Expand Up @@ -111,7 +135,7 @@ export const AssetForm = ({
</p>
}
className="border-b-0 pb-[10px]"
required={zodFieldIsRequired(NewAssetFormSchema.shape.category)}
required={zodFieldIsRequired(FormSchema.shape.category)}
>
<CategorySelect defaultValue={category || undefined} />
</FormRow>
Expand All @@ -127,7 +151,7 @@ export const AssetForm = ({
</p>
}
className="border-b-0 py-[10px]"
required={zodFieldIsRequired(NewAssetFormSchema.shape.tags)}
required={zodFieldIsRequired(FormSchema.shape.tags)}
>
<TagsAutocomplete existingTags={tags || []} />
</FormRow>
Expand All @@ -144,7 +168,7 @@ export const AssetForm = ({
</p>
}
className="pt-[10px]"
required={zodFieldIsRequired(NewAssetFormSchema.shape.newLocationId)}
required={zodFieldIsRequired(FormSchema.shape.newLocationId)}
>
<LocationSelect />
</FormRow>
Expand All @@ -158,7 +182,8 @@ export const AssetForm = ({
asset’s overview page. You can always change it.
</p>
}
required={zodFieldIsRequired(NewAssetFormSchema.shape.description)}
className="border-b-0"
required={zodFieldIsRequired(FormSchema.shape.description)}
>
<Input
inputType="textarea"
Expand All @@ -169,12 +194,14 @@ export const AssetForm = ({
disabled={disabled}
data-test-id="assetDescription"
className="w-full"
required={zodFieldIsRequired(NewAssetFormSchema.shape.description)}
required={zodFieldIsRequired(FormSchema.shape.description)}
/>
</FormRow>
</div>

<div className="text-right">
<AssetCustomFields zo={zo} schema={FormSchema} />

<div className="pt-6 text-right">
<Button type="submit" disabled={disabled}>
{disabled ? <Spinner /> : "Save"}
</Button>
Expand Down
20 changes: 20 additions & 0 deletions app/components/assets/import-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { PremiumFeatureButton } from "../subscription/premium-feature-button";

export const ImportButton = ({
canImportAssets,
}: {
canImportAssets: boolean;
}) => (
<PremiumFeatureButton
canUseFeature={canImportAssets}
buttonContent={{
title: "Import",
message: "Importing is not available on the free tier of shelf.",
}}
buttonProps={{
to: `import`,
variant: "secondary",
role: "link",
}}
/>
);
Loading