mirror of
https://github.com/formbricks/formbricks.git
synced 2026-05-06 02:46:46 -05:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b863238f15 | |||
| 28280899ea | |||
| bc63870289 | |||
| 9a04e95d15 | |||
| 9d9f38515d |
@@ -155,3 +155,31 @@ jobs:
|
||||
commit_sha: ${{ github.sha }}
|
||||
is_prerelease: ${{ github.event.release.prerelease }}
|
||||
make_latest: ${{ needs.check-latest-release.outputs.is_latest == 'true' }}
|
||||
|
||||
linear-release-complete:
|
||||
name: Mark Linear release as complete
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
needs:
|
||||
- docker-build-community
|
||||
- docker-build-cloud
|
||||
- helm-chart-release
|
||||
- move-stable-tag
|
||||
if: ${{ !github.event.release.prerelease }}
|
||||
steps:
|
||||
- name: Harden the runner
|
||||
uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Complete Linear release
|
||||
uses: linear/linear-release-action@0353b5fa8c00326913966f00557d68f8f30b8b6b # v0.7.0
|
||||
with:
|
||||
access_key: ${{ secrets.LINEAR_ACCESS_KEY }}
|
||||
command: complete
|
||||
version: ${{ github.event.release.tag_name }}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
name: Linear Release Sync
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
linear-release:
|
||||
name: Sync release to Linear
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Harden the runner
|
||||
uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Sync Linear release
|
||||
uses: linear/linear-release-action@0353b5fa8c00326913966f00557d68f8f30b8b6b # v0.7.0
|
||||
with:
|
||||
access_key: ${{ secrets.LINEAR_ACCESS_KEY }}
|
||||
@@ -4,7 +4,7 @@ import { z } from "zod";
|
||||
import { logger } from "@formbricks/logger";
|
||||
import { OperationNotAllowedError } from "@formbricks/types/errors";
|
||||
import { IS_FORMBRICKS_CLOUD } from "@/lib/constants";
|
||||
import { gethasNoOrganizations } from "@/lib/instance/service";
|
||||
import { getHasNoOrganizations } from "@/lib/instance/service";
|
||||
import { createMembership } from "@/lib/membership/service";
|
||||
import { createOrganization } from "@/lib/organization/service";
|
||||
import { capturePostHogEvent } from "@/lib/posthog";
|
||||
@@ -21,7 +21,7 @@ export const createOrganizationAction = authenticatedActionClient
|
||||
.inputSchema(ZCreateOrganizationAction)
|
||||
.action(
|
||||
withAuditLogging("created", "organization", async ({ ctx, parsedInput }) => {
|
||||
const hasNoOrganizations = await gethasNoOrganizations();
|
||||
const hasNoOrganizations = await getHasNoOrganizations();
|
||||
const isMultiOrgEnabled = await getIsMultiOrgEnabled();
|
||||
|
||||
if (!hasNoOrganizations && !isMultiOrgEnabled) {
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { getServerSession } from "next-auth";
|
||||
import { redirect } from "next/navigation";
|
||||
import { getHasNoOrganizations, getIsFreshInstance } from "@/lib/instance/service";
|
||||
import { authOptions } from "@/modules/auth/lib/authOptions";
|
||||
|
||||
const Page = async () => {
|
||||
const [session, isFreshInstance, hasNoOrganizations] = await Promise.all([
|
||||
getServerSession(authOptions),
|
||||
getIsFreshInstance(),
|
||||
getHasNoOrganizations(),
|
||||
]);
|
||||
|
||||
if (isFreshInstance) {
|
||||
return redirect("/setup/intro");
|
||||
}
|
||||
|
||||
if (hasNoOrganizations) {
|
||||
if (session) {
|
||||
return redirect("/setup/organization/create");
|
||||
}
|
||||
|
||||
return redirect("/auth/login?callbackUrl=%2Fsetup%2Forganization%2Fcreate");
|
||||
}
|
||||
|
||||
return redirect("/");
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -19,7 +19,7 @@ export const getIsFreshInstance = reactCache(async (): Promise<boolean> => {
|
||||
});
|
||||
|
||||
// Function to check if there are any organizations in the database
|
||||
export const gethasNoOrganizations = reactCache(async (): Promise<boolean> => {
|
||||
export const getHasNoOrganizations = reactCache(async (): Promise<boolean> => {
|
||||
try {
|
||||
const organizationCount = await prisma.organization.count();
|
||||
return organizationCount === 0;
|
||||
|
||||
@@ -1,14 +1,29 @@
|
||||
import { getServerSession } from "next-auth";
|
||||
import { notFound } from "next/navigation";
|
||||
import { getIsFreshInstance } from "@/lib/instance/service";
|
||||
import { notFound, redirect } from "next/navigation";
|
||||
import { getHasNoOrganizations, getIsFreshInstance } from "@/lib/instance/service";
|
||||
import { authOptions } from "@/modules/auth/lib/authOptions";
|
||||
|
||||
export const FreshInstanceLayout = async ({ children }: { children: React.ReactNode }) => {
|
||||
const session = await getServerSession(authOptions);
|
||||
const isFreshInstance = await getIsFreshInstance();
|
||||
|
||||
if (session || !isFreshInstance) {
|
||||
if (!isFreshInstance) {
|
||||
const hasNoOrganizations = await getHasNoOrganizations();
|
||||
|
||||
if (hasNoOrganizations) {
|
||||
if (session) {
|
||||
return redirect("/setup/organization/create");
|
||||
}
|
||||
|
||||
return redirect("/auth/login?callbackUrl=%2Fsetup%2Forganization%2Fcreate");
|
||||
}
|
||||
|
||||
return notFound();
|
||||
}
|
||||
|
||||
if (session) {
|
||||
return notFound();
|
||||
}
|
||||
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import { getServerSession } from "next-auth";
|
||||
import { notFound } from "next/navigation";
|
||||
import { AuthenticationError } from "@formbricks/types/errors";
|
||||
import { IS_FORMBRICKS_CLOUD } from "@/lib/constants";
|
||||
import { gethasNoOrganizations } from "@/lib/instance/service";
|
||||
import { getHasNoOrganizations } from "@/lib/instance/service";
|
||||
import { getOrganizationsByUserId } from "@/lib/organization/service";
|
||||
import { getUser } from "@/lib/user/service";
|
||||
import { getTranslate } from "@/lingodotdev/server";
|
||||
@@ -29,7 +29,7 @@ export const CreateOrganizationPage = async () => {
|
||||
return <ClientLogout />;
|
||||
}
|
||||
|
||||
const hasNoOrganizations = await gethasNoOrganizations();
|
||||
const hasNoOrganizations = await getHasNoOrganizations();
|
||||
const isMultiOrgEnabled = await getIsMultiOrgEnabled();
|
||||
const userOrganizations = await getOrganizationsByUserId(session.user.id);
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ metadata:
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if .Values.deployment.replicas }}
|
||||
{{- if and (not .Values.autoscaling.enabled) (not (kindIs "invalid" .Values.deployment.replicas)) }}
|
||||
replicas: {{ .Values.deployment.replicas }}
|
||||
{{- end }}
|
||||
selector:
|
||||
|
||||
@@ -83,7 +83,7 @@ deployment:
|
||||
# Additional pod annotations
|
||||
additionalPodAnnotations: {}
|
||||
|
||||
# Number of replicas
|
||||
# Number of replicas when autoscaling is disabled
|
||||
replicas: 1
|
||||
|
||||
# Image pull secrets for private container registries
|
||||
|
||||
@@ -67,12 +67,15 @@ function OpenText({
|
||||
);
|
||||
};
|
||||
|
||||
const descriptionId = description ? `${inputId}-description` : undefined;
|
||||
|
||||
return (
|
||||
<div className="w-full space-y-4" id={elementId} dir={dir}>
|
||||
{/* Headline */}
|
||||
<ElementHeader
|
||||
headline={headline}
|
||||
description={description}
|
||||
descriptionId={descriptionId}
|
||||
required={required}
|
||||
requiredLabel={requiredLabel}
|
||||
htmlFor={inputId}
|
||||
@@ -90,6 +93,7 @@ function OpenText({
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
aria-required={required}
|
||||
aria-describedby={descriptionId}
|
||||
dir={dir}
|
||||
rows={rows}
|
||||
disabled={disabled}
|
||||
@@ -105,6 +109,7 @@ function OpenText({
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
aria-required={required}
|
||||
aria-describedby={descriptionId}
|
||||
dir={dir}
|
||||
disabled={disabled}
|
||||
errorMessage={errorMessage}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { cn, stripInlineStyles } from "@/lib/utils";
|
||||
interface ElementHeaderProps extends React.ComponentProps<"div"> {
|
||||
headline: string;
|
||||
description?: string;
|
||||
descriptionId?: string;
|
||||
required?: boolean;
|
||||
/** Custom label for the required indicator. Defaults to "Required" */
|
||||
requiredLabel?: string;
|
||||
@@ -44,6 +45,7 @@ const isValidHTML = (str: string): boolean => {
|
||||
function ElementHeader({
|
||||
headline,
|
||||
description,
|
||||
descriptionId,
|
||||
required = false,
|
||||
requiredLabel = "Required",
|
||||
htmlFor,
|
||||
@@ -91,7 +93,7 @@ function ElementHeader({
|
||||
|
||||
{/* Description/Subheader */}
|
||||
{description ? (
|
||||
<Label htmlFor={htmlFor} variant="description">
|
||||
<Label id={descriptionId} variant="description">
|
||||
{description}
|
||||
</Label>
|
||||
) : null}
|
||||
|
||||
@@ -63,7 +63,11 @@ export function CalElement({
|
||||
elementId={element.id}
|
||||
/>
|
||||
<CalEmbed key={element.id} element={element} onSuccessfulBooking={onSuccessfulBooking} />
|
||||
{errorMessage ? <span className="text-red-500">{errorMessage}</span> : null}
|
||||
{errorMessage ? (
|
||||
<span className="text-red-500" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
{errorMessage}
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
|
||||
@@ -61,7 +61,7 @@ export function OpenTextElement({
|
||||
<form key={element.id} onSubmit={handleOnSubmit} className="w-full">
|
||||
<OpenText
|
||||
elementId={element.id}
|
||||
inputId={element.id}
|
||||
inputId={`${element.id}-input`}
|
||||
headline={getLocalizedValue(element.headline, languageCode)}
|
||||
description={element.subheader ? getLocalizedValue(element.subheader, languageCode) : undefined}
|
||||
placeholder={getLocalizedValue(element.placeholder, languageCode)}
|
||||
|
||||
Reference in New Issue
Block a user