mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
Merge pull request #2308 from makeplane/develop
promote: develop to stage release
This commit is contained in:
commit
7c125075b1
@ -33,8 +33,7 @@ def create_issue_relation(apps, schema_editor):
|
||||
def update_issue_priority_choice(apps, schema_editor):
|
||||
IssueModel = apps.get_model("db", "Issue")
|
||||
updated_issues = []
|
||||
for obj in IssueModel.objects.all():
|
||||
if obj.priority is None:
|
||||
for obj in IssueModel.objects.filter(priority=None):
|
||||
obj.priority = "none"
|
||||
updated_issues.append(obj)
|
||||
IssueModel.objects.bulk_update(updated_issues, ["priority"], batch_size=100)
|
||||
|
@ -1,42 +0,0 @@
|
||||
# Generated by Django 4.2.3 on 2023-09-15 06:55
|
||||
|
||||
from django.db import migrations, models
|
||||
from django.conf import settings
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("db", "0044_auto_20230913_0709"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="GlobalView",
|
||||
fields=[
|
||||
("created_at", models.DateTimeField(auto_now_add=True, verbose_name="Created At"),),
|
||||
("updated_at", models.DateTimeField(auto_now=True, verbose_name="Last Modified At"),),
|
||||
("id", models.UUIDField(db_index=True, default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True,),),
|
||||
("name", models.CharField(max_length=255, verbose_name="View Name")),
|
||||
("description", models.TextField(blank=True, verbose_name="View Description"),),
|
||||
("query", models.JSONField(verbose_name="View Query")),
|
||||
("access", models.PositiveSmallIntegerField(choices=[(0, "Private"), (1, "Public")], default=1),),
|
||||
("query_data", models.JSONField(default=dict)),
|
||||
("created_by", models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="%(class)s_created_by", to=settings.AUTH_USER_MODEL, verbose_name="Created By",),),
|
||||
("updated_by", models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="%(class)s_updated_by", to=settings.AUTH_USER_MODEL, verbose_name="Last Modified By",),),
|
||||
("workspace", models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name="global_views", to="db.workspace",),),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Global View",
|
||||
"verbose_name_plural": "Global Views",
|
||||
"db_table": "global_views",
|
||||
"ordering": ("-created_at",),
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="issueactivity",
|
||||
name="epoch",
|
||||
field=models.FloatField(null=True),
|
||||
),
|
||||
]
|
@ -0,0 +1,79 @@
|
||||
# Generated by Django 4.2.5 on 2023-09-29 10:14
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import plane.db.models.workspace
|
||||
import uuid
|
||||
|
||||
|
||||
def update_issue_activity_priority(apps, schema_editor):
|
||||
IssueActivity = apps.get_model("db", "IssueActivity")
|
||||
updated_issue_activity = []
|
||||
for obj in IssueActivity.objects.filter(field="priority"):
|
||||
# Set the old and new value to none if it is empty for Priority
|
||||
obj.new_value = obj.new_value or "none"
|
||||
obj.old_value = obj.old_value or "none"
|
||||
updated_issue_activity.append(obj)
|
||||
IssueActivity.objects.bulk_update(
|
||||
updated_issue_activity,
|
||||
["new_value", "old_value"],
|
||||
batch_size=2000,
|
||||
)
|
||||
|
||||
def update_issue_activity_blocked(apps, schema_editor):
|
||||
IssueActivity = apps.get_model("db", "IssueActivity")
|
||||
updated_issue_activity = []
|
||||
for obj in IssueActivity.objects.filter(field="blocks"):
|
||||
# Set the field to blocked_by
|
||||
obj.field = "blocked_by"
|
||||
updated_issue_activity.append(obj)
|
||||
IssueActivity.objects.bulk_update(
|
||||
updated_issue_activity,
|
||||
["field"],
|
||||
batch_size=1000,
|
||||
)
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('db', '0044_auto_20230913_0709'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='GlobalView',
|
||||
fields=[
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')),
|
||||
('updated_at', models.DateTimeField(auto_now=True, verbose_name='Last Modified At')),
|
||||
('id', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)),
|
||||
('name', models.CharField(max_length=255, verbose_name='View Name')),
|
||||
('description', models.TextField(blank=True, verbose_name='View Description')),
|
||||
('query', models.JSONField(verbose_name='View Query')),
|
||||
('access', models.PositiveSmallIntegerField(choices=[(0, 'Private'), (1, 'Public')], default=1)),
|
||||
('query_data', models.JSONField(default=dict)),
|
||||
('sort_order', models.FloatField(default=65535)),
|
||||
('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created_by', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
|
||||
('updated_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated_by', to=settings.AUTH_USER_MODEL, verbose_name='Last Modified By')),
|
||||
('workspace', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='global_views', to='db.workspace')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Global View',
|
||||
'verbose_name_plural': 'Global Views',
|
||||
'db_table': 'global_views',
|
||||
'ordering': ('-created_at',),
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='workspacemember',
|
||||
name='issue_props',
|
||||
field=models.JSONField(default=plane.db.models.workspace.get_issue_props),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='issueactivity',
|
||||
name='epoch',
|
||||
field=models.FloatField(null=True),
|
||||
),
|
||||
migrations.RunPython(update_issue_activity_priority),
|
||||
migrations.RunPython(update_issue_activity_blocked),
|
||||
]
|
@ -1,26 +0,0 @@
|
||||
# Generated by Django 4.2.5 on 2023-09-26 10:15
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def update_issue_activity(apps, schema_editor):
|
||||
IssueActivity = apps.get_model("db", "IssueActivity")
|
||||
updated_issue_activity = []
|
||||
for obj in IssueActivity.objects.all():
|
||||
obj.epoch = int(obj.created_at.timestamp())
|
||||
updated_issue_activity.append(obj)
|
||||
IssueActivity.objects.bulk_update(
|
||||
updated_issue_activity,
|
||||
["epoch"],
|
||||
batch_size=5000,
|
||||
)
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('db', '0045_auto_20230915_0655'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(update_issue_activity),
|
||||
]
|
@ -1,44 +0,0 @@
|
||||
# Generated by Django 4.2.5 on 2023-09-26 10:29
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def update_issue_activity_priority(apps, schema_editor):
|
||||
IssueActivity = apps.get_model("db", "IssueActivity")
|
||||
updated_issue_activity = []
|
||||
for obj in IssueActivity.objects.filter(field="priority"):
|
||||
# Set the old and new value to none if it is empty for Priority
|
||||
obj.new_value = obj.new_value or "none"
|
||||
obj.old_value = obj.old_value or "none"
|
||||
updated_issue_activity.append(obj)
|
||||
IssueActivity.objects.bulk_update(
|
||||
updated_issue_activity,
|
||||
["new_value", "old_value"],
|
||||
batch_size=1000,
|
||||
)
|
||||
|
||||
def update_issue_activity_blocked(apps, schema_editor):
|
||||
IssueActivity = apps.get_model("db", "IssueActivity")
|
||||
updated_issue_activity = []
|
||||
for obj in IssueActivity.objects.filter(field="blocks"):
|
||||
# Set the field to blocked_by
|
||||
obj.field = "blocked_by"
|
||||
updated_issue_activity.append(obj)
|
||||
IssueActivity.objects.bulk_update(
|
||||
updated_issue_activity,
|
||||
["field"],
|
||||
batch_size=1000,
|
||||
)
|
||||
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('db', '0046_auto_20230926_1015'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(update_issue_activity_priority),
|
||||
migrations.RunPython(update_issue_activity_blocked),
|
||||
]
|
@ -1,24 +0,0 @@
|
||||
# Generated by Django 4.2.5 on 2023-09-27 11:18
|
||||
|
||||
from django.db import migrations, models
|
||||
import plane.db.models.workspace
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('db', '0047_auto_20230926_1029'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='globalview',
|
||||
name='sort_order',
|
||||
field=models.FloatField(default=65535),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='workspacemember',
|
||||
name='issue_props',
|
||||
field=models.JSONField(default=plane.db.models.workspace.get_issue_props),
|
||||
),
|
||||
]
|
@ -299,8 +299,6 @@ export const WorkspaceFiltersList: React.FC<Props> = ({
|
||||
: key === "project"
|
||||
? filters.project?.map((projectId) => {
|
||||
const currentProject = project?.find((p) => p.id === projectId);
|
||||
console.log("currentProject", currentProject);
|
||||
console.log("currentProject", projectId);
|
||||
return (
|
||||
<p
|
||||
key={currentProject?.id}
|
||||
|
@ -12,7 +12,6 @@ import { CustomMenu } from "components/ui";
|
||||
import viewsService from "services/views.service";
|
||||
// types
|
||||
import { IView } from "types";
|
||||
import { IWorkspaceView } from "types/workspace-views";
|
||||
// fetch keys
|
||||
import { VIEWS_LIST } from "constants/fetch-keys";
|
||||
// hooks
|
||||
@ -21,18 +20,12 @@ import useToast from "hooks/use-toast";
|
||||
import { truncateText } from "helpers/string.helper";
|
||||
|
||||
type Props = {
|
||||
view: IView | IWorkspaceView;
|
||||
viewType: "project" | "workspace";
|
||||
view: IView;
|
||||
handleEditView: () => void;
|
||||
handleDeleteView: () => void;
|
||||
};
|
||||
|
||||
export const SingleViewItem: React.FC<Props> = ({
|
||||
view,
|
||||
viewType,
|
||||
handleEditView,
|
||||
handleDeleteView,
|
||||
}) => {
|
||||
export const SingleViewItem: React.FC<Props> = ({ view, handleEditView, handleDeleteView }) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
@ -88,10 +81,7 @@ export const SingleViewItem: React.FC<Props> = ({
|
||||
});
|
||||
};
|
||||
|
||||
const viewRedirectionUrl =
|
||||
viewType === "project"
|
||||
? `/${workspaceSlug}/projects/${projectId}/views/${view.id}`
|
||||
: `/${workspaceSlug}/workspace-views/issues?globalViewId=${view.id}`;
|
||||
const viewRedirectionUrl = `/${workspaceSlug}/projects/${projectId}/views/${view.id}`;
|
||||
|
||||
return (
|
||||
<div className="group hover:bg-custom-background-90 border-b border-custom-border-200">
|
||||
@ -126,8 +116,7 @@ export const SingleViewItem: React.FC<Props> = ({
|
||||
filters
|
||||
</p>
|
||||
|
||||
{viewType === "project" ? (
|
||||
view.is_favorite ? (
|
||||
{view.is_favorite ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
@ -149,8 +138,7 @@ export const SingleViewItem: React.FC<Props> = ({
|
||||
>
|
||||
<StarIcon className="h-4 w-4 " color="rgb(var(--color-text-200))" />
|
||||
</button>
|
||||
)
|
||||
) : null}
|
||||
)}
|
||||
<CustomMenu width="auto" ellipsis>
|
||||
<CustomMenu.MenuItem
|
||||
onClick={(e: any) => {
|
||||
|
110
web/components/workspace/views/single-workspace-view-item.tsx
Normal file
110
web/components/workspace/views/single-workspace-view-item.tsx
Normal file
@ -0,0 +1,110 @@
|
||||
import React from "react";
|
||||
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
// icons
|
||||
import { TrashIcon, PencilIcon } from "@heroicons/react/24/outline";
|
||||
import { PhotoFilterOutlined } from "@mui/icons-material";
|
||||
//components
|
||||
import { CustomMenu } from "components/ui";
|
||||
import { IWorkspaceView } from "types/workspace-views";
|
||||
// helpers
|
||||
import { truncateText } from "helpers/string.helper";
|
||||
|
||||
type Props = {
|
||||
view: IWorkspaceView;
|
||||
handleEditView: () => void;
|
||||
handleDeleteView: () => void;
|
||||
};
|
||||
|
||||
export const SingleWorkspaceViewItem: React.FC<Props> = ({
|
||||
view,
|
||||
handleEditView,
|
||||
handleDeleteView,
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
const viewRedirectionUrl = `/${workspaceSlug}/workspace-views/issues?globalViewId=${view.id}`;
|
||||
|
||||
return (
|
||||
<div className="group hover:bg-custom-background-90 border-b border-custom-border-200">
|
||||
<Link href={viewRedirectionUrl}>
|
||||
<a className="flex items-center justify-between relative rounded px-5 py-4 w-full">
|
||||
<div className="flex items-center justify-between w-full">
|
||||
<div className="flex items-center gap-4">
|
||||
<div
|
||||
className={`flex items-center justify-center h-10 w-10 rounded bg-custom-background-90 group-hover:bg-custom-background-100`}
|
||||
>
|
||||
<PhotoFilterOutlined className="!text-base !leading-6" />
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<p className="truncate text-sm leading-4 font-medium">
|
||||
{truncateText(view.name, 75)}
|
||||
</p>
|
||||
{view?.description && (
|
||||
<p className="text-xs text-custom-text-200">{view.description}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="ml-2 flex flex-shrink-0">
|
||||
<div className="flex items-center gap-4">
|
||||
<p className="rounded bg-custom-background-80 py-1 px-2 text-xs text-custom-text-200 opacity-0 group-hover:opacity-100">
|
||||
{view.query_data.filters && Object.keys(view.query_data.filters).length > 0
|
||||
? `${Object.keys(view.query_data.filters)
|
||||
.map((key: string) =>
|
||||
view.query_data.filters[key as keyof typeof view.query_data.filters] !==
|
||||
null
|
||||
? isNaN(
|
||||
(
|
||||
view.query_data.filters[
|
||||
key as keyof typeof view.query_data.filters
|
||||
] as any
|
||||
).length
|
||||
)
|
||||
? 0
|
||||
: (
|
||||
view.query_data.filters[
|
||||
key as keyof typeof view.query_data.filters
|
||||
] as any
|
||||
).length
|
||||
: 0
|
||||
)
|
||||
.reduce((curr, prev) => curr + prev, 0)} filters`
|
||||
: "0 filters"}
|
||||
</p>
|
||||
<CustomMenu width="auto" ellipsis>
|
||||
<CustomMenu.MenuItem
|
||||
onClick={(e: any) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
handleEditView();
|
||||
}}
|
||||
>
|
||||
<span className="flex items-center justify-start gap-2">
|
||||
<PencilIcon className="h-3.5 w-3.5" />
|
||||
<span>Edit View</span>
|
||||
</span>
|
||||
</CustomMenu.MenuItem>
|
||||
<CustomMenu.MenuItem
|
||||
onClick={(e: any) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
handleDeleteView();
|
||||
}}
|
||||
>
|
||||
<span className="flex items-center justify-start gap-2">
|
||||
<TrashIcon className="h-3.5 w-3.5" />
|
||||
<span>Delete View</span>
|
||||
</span>
|
||||
</CustomMenu.MenuItem>
|
||||
</CustomMenu>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
@ -107,7 +107,6 @@ const ProjectViews: NextPage = () => {
|
||||
<SingleViewItem
|
||||
key={view.id}
|
||||
view={view}
|
||||
viewType="project"
|
||||
handleEditView={() => handleEditView(view)}
|
||||
handleDeleteView={() => handleDeleteView(view)}
|
||||
/>
|
||||
|
@ -11,7 +11,7 @@ import workspaceService from "services/workspace.service";
|
||||
// layouts
|
||||
import { WorkspaceAuthorizationLayout } from "layouts/auth-layout";
|
||||
// components
|
||||
import { SingleViewItem } from "components/views";
|
||||
import { SingleWorkspaceViewItem } from "components/workspace/views/single-workspace-view-item";
|
||||
import { WorkspaceIssuesViewOptions } from "components/issues/workspace-views/workspace-issue-view-option";
|
||||
import { CreateUpdateWorkspaceViewModal } from "components/workspace/views/modal";
|
||||
import { DeleteWorkspaceViewModal } from "components/workspace/views/delete-workspace-view-modal";
|
||||
@ -169,10 +169,9 @@ const WorkspaceViews: NextPage = () => {
|
||||
filteredOptions.length > 0 ? (
|
||||
<div>
|
||||
{filteredOptions.map((view) => (
|
||||
<SingleViewItem
|
||||
<SingleWorkspaceViewItem
|
||||
key={view.id}
|
||||
view={view}
|
||||
viewType="workspace"
|
||||
handleEditView={() => handleEditView(view)}
|
||||
handleDeleteView={() => handleDeleteView(view)}
|
||||
/>
|
||||
|
Loading…
Reference in New Issue
Block a user