Compare commits

...
Author SHA1 Message Date
sriram veeraghantaandGitHub 05894c5b9c Merge pull request #6121 from makeplane/preview
release: v0.24.0
2024-11-29 19:36:12 +05:30
Prateek ShouryaandGitHub 5926c9e8e9 fix: comment images in profile activity page (#6123) 2024-11-29 19:20:31 +05:30
Prateek ShouryaandGitHub 5aeedd1e5a [WEB-2610] fix: workspace redirection from admin app (#6122) 2024-11-29 19:02:13 +05:30
sriram veeraghanta 7725b200f7 fix: changelog redirection 2024-11-29 18:13:29 +05:30
sriram veeraghanta 2c69538617 fix: hypermode text typo changes 2024-11-29 17:47:46 +05:30
pablohashescobar 41bd98dd63 fix: instance collect 2024-11-29 17:41:06 +05:30
sriram veeraghanta bf1c326b44 Merge branch 'preview' of github.com:makeplane/plane into preview 2024-11-29 17:36:00 +05:30
sriram veeraghanta 3d1485461d fix: lockfile udpated 2024-11-29 17:35:47 +05:30
rahulrameshaandGitHub 4251b114c3 chore: enable no load by default (#5968)
* enable no load by default

* remove help section brackets

* fallback to server with mentions
2024-11-29 14:55:39 +05:30
Prateek ShouryaandGitHub 712339a638 minor improvements for workspace management (#6099)
* minor improvements for workspace management

* typo fix
2024-11-29 14:53:30 +05:30
13 changed files with 1823 additions and 1970 deletions
+3 -1
View File
@@ -38,6 +38,8 @@ export const WorkspaceCreateForm = () => {
getValues,
formState: { errors, isSubmitting, isValid },
} = useForm<IWorkspace>({ defaultValues, mode: "onChange" });
// derived values
const workspaceBaseURL = encodeURI(WEB_BASE_URL || window.location.origin + "/");
const handleCreateWorkspace = async (formData: IWorkspace) => {
await workspaceService
@@ -124,7 +126,7 @@ export const WorkspaceCreateForm = () => {
<div className="flex flex-col gap-1">
<h4 className="text-sm text-custom-text-300">Set your workspace&apos;s URL</h4>
<div className="flex gap-0.5 w-full items-center rounded-md border-[0.5px] border-custom-border-200 px-3">
<span className="whitespace-nowrap text-sm text-custom-text-200">{WEB_BASE_URL}/</span>
<span className="whitespace-nowrap text-sm text-custom-text-200">{workspaceBaseURL}</span>
<Controller
control={control}
name="slug"
@@ -1,5 +1,4 @@
import { observer } from "mobx-react";
import Link from "next/link";
import { ExternalLink } from "lucide-react";
// helpers
import { Tooltip } from "@plane/ui";
@@ -20,9 +19,9 @@ export const WorkspaceListItem = observer(({ workspaceId }: TWorkspaceListItemPr
if (!workspace) return null;
return (
<Link
<a
key={workspaceId}
href={encodeURI(WEB_BASE_URL + "/" + workspace.slug)}
href={`${WEB_BASE_URL}/${encodeURIComponent(workspace.slug)}`}
target="_blank"
className="group flex items-center justify-between p-4 gap-2.5 truncate border border-custom-border-200/70 hover:border-custom-border-200 hover:bg-custom-background-90 rounded-md"
>
@@ -77,6 +76,6 @@ export const WorkspaceListItem = observer(({ workspaceId }: TWorkspaceListItemPr
<div className="flex-shrink-0">
<ExternalLink size={14} className="text-custom-text-400 group-hover:text-custom-text-200" />
</div>
</Link>
</a>
);
});
+2 -1
View File
@@ -30,7 +30,8 @@ export class WorkspaceService extends APIService {
* @returns Promise<any>
*/
async workspaceSlugCheck(slug: string): Promise<any> {
return this.get(`/api/instances/workspace-slug-check/?slug=${slug}`)
const params = new URLSearchParams({ slug });
return this.get(`/api/instances/workspace-slug-check/?${params.toString()}`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
+3 -3
View File
@@ -14,7 +14,7 @@ export interface IWorkspaceStore {
// computed
workspaceIds: string[];
// helper actions
hydrate: (data: any) => void;
hydrate: (data: Record<string, IWorkspace>) => void;
getWorkspaceById: (workspaceId: string) => IWorkspace | undefined;
// fetch actions
fetchWorkspaces: () => Promise<IWorkspace[]>;
@@ -59,9 +59,9 @@ export class WorkspaceStore implements IWorkspaceStore {
// helper actions
/**
* @description Hydrates the workspaces
* @param data - any
* @param data - Record<string, IWorkspace>
*/
hydrate = (data: any) => {
hydrate = (data: Record<string, IWorkspace>) => {
if (data) this.workspaces = data;
};
@@ -18,6 +18,9 @@ class WorkspaceSerializer(BaseSerializer):
# Check if the slug is restricted
if value in RESTRICTED_WORKSPACE_SLUGS:
raise serializers.ValidationError("Slug is not valid")
# Check uniqueness case-insensitively
if Workspace.objects.filter(slug__iexact=value).exists():
raise serializers.ValidationError("Slug is already in use")
return value
class Meta:
@@ -25,7 +25,7 @@ class InstanceWorkSpaceAvailabilityCheckEndpoint(BaseAPIView):
)
workspace = (
Workspace.objects.filter(slug=slug).exists()
Workspace.objects.filter(slug__iexact=slug).exists()
or slug in RESTRICTED_WORKSPACE_SLUGS
)
return Response({"status": not workspace}, status=status.HTTP_200_OK)
+25 -7
View File
@@ -1,23 +1,33 @@
# Python imports
import os
import atexit
# Third party imports
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.instrumentation.django import DjangoInstrumentor
import os
# Global variable to track initialization
_TRACER_PROVIDER = None
def init_tracer():
"""Initialize OpenTelemetry with proper shutdown handling"""
global _TRACER_PROVIDER
# Check if already initialized to prevent double initialization
if trace.get_tracer_provider().__class__.__name__ == "TracerProvider":
return
# If already initialized, return existing provider
if _TRACER_PROVIDER is not None:
return _TRACER_PROVIDER
# Configure the tracer provider
service_name = os.environ.get("SERVICE_NAME", "plane-ce-api")
resource = Resource.create({"service.name": service_name})
tracer_provider = TracerProvider(resource=resource)
# Set as global tracer provider
trace.set_tracer_provider(tracer_provider)
# Configure the OTLP exporter
@@ -29,12 +39,20 @@ def init_tracer():
# Initialize Django instrumentation
DjangoInstrumentor().instrument()
# Store provider globally
_TRACER_PROVIDER = tracer_provider
# Register shutdown handler
atexit.register(shutdown_tracer)
return tracer_provider
def shutdown_tracer():
"""Shutdown OpenTelemetry tracers and processors"""
provider = trace.get_tracer_provider()
global _TRACER_PROVIDER
if hasattr(provider, "shutdown"):
provider.shutdown()
if _TRACER_PROVIDER is not None:
if hasattr(_TRACER_PROVIDER, "shutdown"):
_TRACER_PROVIDER.shutdown()
_TRACER_PROVIDER = None
+8 -1
View File
@@ -3,7 +3,14 @@ import * as React from "react";
import { ISvgIcons } from "./type";
export const WorkspaceIcon: React.FC<ISvgIcons> = ({ className }) => (
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" className={className}>
<svg
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
role="img"
aria-label="Workspace icon"
>
<path
fillRule="evenodd"
clipRule="evenodd"
-3
View File
@@ -31,7 +31,4 @@ export const filterActivityOnSelectedFilters = (
): TIssueActivityComment[] =>
activity.filter((activity) => filter.includes(activity.activity_type as TActivityFilters));
// boolean to decide if the local db cache is enabled
export const ENABLE_LOCAL_DB_CACHE = false;
export const ENABLE_ISSUE_DEPENDENCIES = false;
@@ -1,7 +1,6 @@
import { useEffect } from "react";
import { observer } from "mobx-react";
import Link from "next/link";
import { useParams } from "next/navigation";
import useSWR from "swr";
// icons
import { History, MessageSquare } from "lucide-react";
@@ -31,8 +30,6 @@ type Props = {
export const ProfileActivityListPage: React.FC<Props> = observer((props) => {
const { cursor, perPage, updateResultsCount, updateTotalPages, updateEmptyState } = props;
// params
const { workspaceSlug } = useParams();
// store hooks
const { data: currentUser } = useUser();
@@ -106,7 +103,7 @@ export const ProfileActivityListPage: React.FC<Props> = observer((props) => {
activityItem?.new_value !== "" ? activityItem.new_value : activityItem.old_value
}
containerClassName="text-xs bg-custom-background-100"
workspaceSlug={workspaceSlug?.toString() ?? ""}
workspaceSlug={activityItem?.workspace_detail?.slug.toString() ?? ""}
projectId={activityItem.project ?? ""}
/>
</div>
@@ -16,7 +16,6 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
// plane web components
import { PlaneVersionNumber } from "@/plane-web/components/global";
import { WorkspaceEditionBadge } from "@/plane-web/components/workspace";
import { ENABLE_LOCAL_DB_CACHE } from "@/plane-web/constants/issues";
export interface WorkspaceHelpSectionProps {
setSidebarActive?: React.Dispatch<React.SetStateAction<boolean>>;
@@ -111,23 +110,21 @@ export const SidebarHelpSection: React.FC<WorkspaceHelpSectionProps> = observer(
</a>
</CustomMenu.MenuItem>
<div className="my-1 border-t border-custom-border-200" />
{ENABLE_LOCAL_DB_CACHE && (
<CustomMenu.MenuItem>
<div
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
}}
className="flex w-full items-center justify-between text-xs hover:bg-custom-background-80"
>
<span className="racking-tight">Local Cache</span>
<ToggleSwitch
value={canUseLocalDB}
onChange={() => toggleLocalDB(workspaceSlug?.toString(), projectId?.toString())}
/>
</div>
</CustomMenu.MenuItem>
)}
<CustomMenu.MenuItem>
<div
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
}}
className="flex w-full items-center justify-between text-xs hover:bg-custom-background-80"
>
<span className="racking-tight">Hyper Mode</span>
<ToggleSwitch
value={canUseLocalDB}
onChange={() => toggleLocalDB(workspaceSlug?.toString(), projectId?.toString())}
/>
</div>
</CustomMenu.MenuItem>
<CustomMenu.MenuItem>
<button
type="button"
@@ -138,13 +135,14 @@ export const SidebarHelpSection: React.FC<WorkspaceHelpSectionProps> = observer(
</button>
</CustomMenu.MenuItem>
<CustomMenu.MenuItem>
<button
<a
target="_blank"
type="button"
onClick={() => setIsChangeLogOpen(true)}
href="https://plane.so/changelog/community"
className="flex w-full items-center justify-start text-xs hover:bg-custom-background-80"
>
<span className="text-xs">What&apos;s new</span>
</button>
</a>
</CustomMenu.MenuItem>
<CustomMenu.MenuItem>
<a
@@ -173,8 +171,9 @@ export const SidebarHelpSection: React.FC<WorkspaceHelpSectionProps> = observer(
<Tooltip tooltipContent={`${isCollapsed ? "Expand" : "Hide"}`} isMobile={isMobile}>
<button
type="button"
className={`grid place-items-center rounded-md p-1 text-custom-text-200 outline-none hover:bg-custom-background-90 hover:text-custom-text-100 ${isCollapsed ? "w-full" : ""
}`}
className={`grid place-items-center rounded-md p-1 text-custom-text-200 outline-none hover:bg-custom-background-90 hover:text-custom-text-100 ${
isCollapsed ? "w-full" : ""
}`}
onClick={() => toggleSidebar()}
>
<MoveLeft className={`h-4 w-4 duration-300 ${isCollapsed ? "rotate-180" : ""}`} />
+1 -2
View File
@@ -9,7 +9,6 @@ import { TUserPermissions } from "@plane/types/src/enums";
import { API_BASE_URL } from "@/helpers/common.helper";
// local
import { persistence } from "@/local-db/storage.sqlite";
import { ENABLE_LOCAL_DB_CACHE } from "@/plane-web/constants/issues";
import { EUserPermissions } from "@/plane-web/constants/user-permissions";
// services
import { AuthService } from "@/services/auth.service";
@@ -278,6 +277,6 @@ export class UserStore implements IUserStore {
}
get localDBEnabled() {
return ENABLE_LOCAL_DB_CACHE && this.userSettings.canUseLocalDB;
return this.userSettings.canUseLocalDB;
}
}
+1751 -1920
View File
File diff suppressed because it is too large Load Diff