Skip to content
GitLab
Projects
Groups
Topics
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Register
Sign in
Toggle navigation
Menu
Paulo Avila
petruz-tasks
Commits
7c57e406
Commit
7c57e406
authored
Jul 10, 2026
by
Paulo Avila
Browse files
criação de nova data de conclusao e formatação de data
parent
987e8471
Changes
8
Hide whitespace changes
Inline
Side-by-side
src/app/(app)/dashboard/page.tsx
View file @
7c57e406
...
@@ -14,7 +14,7 @@ import { Progress } from "@/components/ui/progress";
...
@@ -14,7 +14,7 @@ import { Progress } from "@/components/ui/progress";
import
{
Button
}
from
"
@/components/ui/button
"
;
import
{
Button
}
from
"
@/components/ui/button
"
;
import
{
DueBadge
}
from
"
@/components/tasks/due-badge
"
;
import
{
DueBadge
}
from
"
@/components/tasks/due-badge
"
;
import
{
STATUS_CHIPS
}
from
"
@/components/tasks/task-utils
"
;
import
{
STATUS_CHIPS
}
from
"
@/components/tasks/task-utils
"
;
import
{
formatDate
}
from
"
@/lib/dates
"
;
import
{
formatDate
Short
}
from
"
@/lib/dates
"
;
import
{
cn
}
from
"
@/lib/utils
"
;
import
{
cn
}
from
"
@/lib/utils
"
;
export
const
metadata
=
{
title
:
"
Painel — Petruz Tasks
"
};
export
const
metadata
=
{
title
:
"
Painel — Petruz Tasks
"
};
...
@@ -147,7 +147,7 @@ export default async function DashboardPage() {
...
@@ -147,7 +147,7 @@ export default async function DashboardPage() {
</
p
>
</
p
>
<
p
className
=
"text-xs text-muted-foreground"
>
<
p
className
=
"text-xs text-muted-foreground"
>
{
task
.
AssigneeName
??
"
Sem responsável
"
}
·
{
"
"
}
{
task
.
AssigneeName
??
"
Sem responsável
"
}
·
{
"
"
}
{
formatDate
(
task
.
DueDate
)
}
{
formatDate
Short
(
task
.
DueDate
)
}
</
p
>
</
p
>
</
div
>
</
div
>
<
DueBadge
<
DueBadge
...
...
src/components/tasks/task-board.tsx
View file @
7c57e406
import
{
CalendarClock
,
CalendarPlus
,
Pencil
}
from
"
lucide-react
"
;
import
{
CalendarCheck
,
CalendarClock
,
CalendarPlus
,
Pencil
}
from
"
lucide-react
"
;
import
{
TASK_STATUSES
}
from
"
@/lib/constants
"
;
import
{
TASK_STATUSES
}
from
"
@/lib/constants
"
;
import
type
{
Task
,
WorkspaceMember
}
from
"
@/lib/data
"
;
import
type
{
Task
,
WorkspaceMember
}
from
"
@/lib/data
"
;
import
{
formatDate
}
from
"
@/lib/dates
"
;
import
{
formatDate
Short
}
from
"
@/lib/dates
"
;
import
{
canEditTask
}
from
"
@/lib/permissions
"
;
import
{
canEditTask
}
from
"
@/lib/permissions
"
;
import
{
Button
}
from
"
@/components/ui/button
"
;
import
{
Button
}
from
"
@/components/ui/button
"
;
import
{
Card
,
CardContent
}
from
"
@/components/ui/card
"
;
import
{
Card
,
CardContent
}
from
"
@/components/ui/card
"
;
...
@@ -106,16 +106,25 @@ export function TaskBoard({
...
@@ -106,16 +106,25 @@ export function TaskBoard({
title
=
"Início"
title
=
"Início"
>
>
<
CalendarPlus
className
=
"h-3 w-3"
/>
<
CalendarPlus
className
=
"h-3 w-3"
/>
{
formatDate
(
task
.
StartDate
)
}
{
formatDate
Short
(
task
.
StartDate
)
}
</
span
>
</
span
>
)
}
)
}
{
task
.
DueDate
&&
(
{
task
.
DueDate
&&
(
<
span
<
span
className
=
"flex items-center gap-1"
className
=
"flex items-center gap-1"
title
=
"
Venciment
o"
title
=
"
Previsão de términ
o"
>
>
<
CalendarClock
className
=
"h-3 w-3"
/>
<
CalendarClock
className
=
"h-3 w-3"
/>
{
formatDate
(
task
.
DueDate
)
}
{
formatDateShort
(
task
.
DueDate
)
}
</
span
>
)
}
{
task
.
CompletedDate
&&
(
<
span
className
=
"flex items-center gap-1 text-green-600 dark:text-green-400"
title
=
"Concluída em"
>
<
CalendarCheck
className
=
"h-3 w-3"
/>
{
formatDateShort
(
task
.
CompletedDate
)
}
</
span
>
</
span
>
)
}
)
}
</
div
>
</
div
>
...
...
src/components/tasks/task-dialog.tsx
View file @
7c57e406
...
@@ -40,6 +40,7 @@ export interface TaskFormValues {
...
@@ -40,6 +40,7 @@ export interface TaskFormValues {
assigneeId
:
number
|
null
;
assigneeId
:
number
|
null
;
startDate
:
string
|
null
;
// yyyy-MM-dd
startDate
:
string
|
null
;
// yyyy-MM-dd
dueDate
:
string
|
null
;
// yyyy-MM-dd
dueDate
:
string
|
null
;
// yyyy-MM-dd
completedDate
:
string
|
null
;
// yyyy-MM-dd
progress
:
number
;
progress
:
number
;
}
}
...
@@ -224,18 +225,40 @@ export function TaskDialog({
...
@@ -224,18 +225,40 @@ export function TaskDialog({
name
=
"startDate"
name
=
"startDate"
type
=
"date"
type
=
"date"
defaultValue
=
{
task
?.
startDate
??
""
}
defaultValue
=
{
task
?.
startDate
??
""
}
disabled
=
{
Boolean
(
task
)
}
/>
/>
</
div
>
</
div
>
<
div
className
=
"space-y-2"
>
<
div
className
=
"space-y-2"
>
<
Label
htmlFor
=
"task-due"
>
Venciment
o
</
Label
>
<
Label
htmlFor
=
"task-due"
>
Previsão de términ
o
</
Label
>
<
Input
<
Input
id
=
"task-due"
id
=
"task-due"
name
=
"dueDate"
name
=
"dueDate"
type
=
"date"
type
=
"date"
defaultValue
=
{
task
?.
dueDate
??
""
}
defaultValue
=
{
task
?.
dueDate
??
""
}
disabled
=
{
Boolean
(
task
)
}
/>
/>
</
div
>
</
div
>
</
div
>
</
div
>
{
task
&&
(
<
p
className
=
"-mt-2 text-xs text-muted-foreground"
>
Início e previsão de término não podem ser alterados após a
criação.
</
p
>
)
}
{
task
?.
completedDate
&&
(
<
div
className
=
"space-y-2"
>
<
Label
htmlFor
=
"task-completed"
>
Concluída em
</
Label
>
<
Input
id
=
"task-completed"
type
=
"date"
defaultValue
=
{
task
.
completedDate
}
disabled
/>
<
p
className
=
"text-xs text-muted-foreground"
>
Preenchida automaticamente ao concluir a tarefa.
</
p
>
</
div
>
)
}
<
div
className
=
"space-y-2"
>
<
div
className
=
"space-y-2"
>
<
Label
htmlFor
=
"task-progress"
>
Progresso (%)
</
Label
>
<
Label
htmlFor
=
"task-progress"
>
Progresso (%)
</
Label
>
<
Input
<
Input
...
...
src/components/tasks/task-table.tsx
View file @
7c57e406
...
@@ -4,7 +4,7 @@ import { Fragment, useState } from "react";
...
@@ -4,7 +4,7 @@ import { Fragment, useState } from "react";
import
{
AlertTriangle
,
ChevronRight
,
Pencil
,
Plus
}
from
"
lucide-react
"
;
import
{
AlertTriangle
,
ChevronRight
,
Pencil
,
Plus
}
from
"
lucide-react
"
;
import
type
{
Task
,
WorkspaceMember
}
from
"
@/lib/data
"
;
import
type
{
Task
,
WorkspaceMember
}
from
"
@/lib/data
"
;
import
{
TASK_STATUSES
}
from
"
@/lib/constants
"
;
import
{
TASK_STATUSES
}
from
"
@/lib/constants
"
;
import
{
formatDate
,
getDueInfo
}
from
"
@/lib/dates
"
;
import
{
formatDate
Short
,
getDueInfo
}
from
"
@/lib/dates
"
;
import
{
canEditTask
}
from
"
@/lib/permissions
"
;
import
{
canEditTask
}
from
"
@/lib/permissions
"
;
import
{
initials
,
toFormValues
}
from
"
./task-utils
"
;
import
{
initials
,
toFormValues
}
from
"
./task-utils
"
;
import
{
Avatar
,
AvatarFallback
}
from
"
@/components/ui/avatar
"
;
import
{
Avatar
,
AvatarFallback
}
from
"
@/components/ui/avatar
"
;
...
@@ -27,7 +27,7 @@ import { TaskProgress } from "./task-progress";
...
@@ -27,7 +27,7 @@ import { TaskProgress } from "./task-progress";
import
{
TaskProgressEditor
}
from
"
./task-progress-editor
"
;
import
{
TaskProgressEditor
}
from
"
./task-progress-editor
"
;
import
{
TaskStatusSelect
}
from
"
./task-status-select
"
;
import
{
TaskStatusSelect
}
from
"
./task-status-select
"
;
const
COLUMN_COUNT
=
7
;
const
COLUMN_COUNT
=
8
;
export
function
TaskTable
({
export
function
TaskTable
({
tasks
,
tasks
,
...
@@ -147,7 +147,10 @@ export function TaskTable({
...
@@ -147,7 +147,10 @@ export function TaskTable({
Início
Início
</
TableHead
>
</
TableHead
>
<
TableHead
className
=
"whitespace-nowrap text-[11px] font-semibold uppercase tracking-wider text-muted-foreground"
>
<
TableHead
className
=
"whitespace-nowrap text-[11px] font-semibold uppercase tracking-wider text-muted-foreground"
>
Vencimento
Previsão
</
TableHead
>
<
TableHead
className
=
"whitespace-nowrap text-[11px] font-semibold uppercase tracking-wider text-muted-foreground"
>
Conclusão
</
TableHead
>
</
TableHead
>
<
TableHead
className
=
"w-[80px]"
/>
<
TableHead
className
=
"w-[80px]"
/>
</
TableRow
>
</
TableRow
>
...
@@ -252,18 +255,29 @@ export function TaskTable({
...
@@ -252,18 +255,29 @@ export function TaskTable({
)
}
)
}
</
TableCell
>
</
TableCell
>
<
TableCell
className
=
"py-3"
>
<
TableCell
className
=
"py-3"
>
<
span
className
=
"text-sm text-muted-foreground"
>
<
span
className
=
"
whitespace-nowrap
text-sm text-muted-foreground"
>
{
formatDate
(
task
.
StartDate
)
}
{
formatDate
Short
(
task
.
StartDate
)
}
</
span
>
</
span
>
</
TableCell
>
</
TableCell
>
<
TableCell
className
=
"py-3"
>
<
TableCell
className
=
"py-3"
>
<
div
className
=
"flex items-center gap-2"
>
<
div
className
=
"flex items-center gap-2"
>
<
span
className
=
"text-sm text-muted-foreground"
>
<
span
className
=
"
whitespace-nowrap
text-sm text-muted-foreground"
>
{
formatDate
(
task
.
DueDate
)
}
{
formatDate
Short
(
task
.
DueDate
)
}
</
span
>
</
span
>
<
DueBadge
dueDate
=
{
task
.
DueDate
}
status
=
{
task
.
Status
}
/>
<
DueBadge
dueDate
=
{
task
.
DueDate
}
status
=
{
task
.
Status
}
/>
</
div
>
</
div
>
</
TableCell
>
</
TableCell
>
<
TableCell
className
=
"py-3"
>
<
span
className
=
"whitespace-nowrap text-sm text-muted-foreground"
>
{
task
.
CompletedDate
?
(
<
span
className
=
"text-green-600 dark:text-green-400"
>
{
formatDateShort
(
task
.
CompletedDate
)
}
</
span
>
)
:
(
"
—
"
)
}
</
span
>
</
TableCell
>
<
TableCell
className
=
"py-3"
>
<
TableCell
className
=
"py-3"
>
{
editable
&&
(
{
editable
&&
(
<
div
className
=
"flex items-center justify-end transition-opacity md:opacity-0 md:group-hover:opacity-100"
>
<
div
className
=
"flex items-center justify-end transition-opacity md:opacity-0 md:group-hover:opacity-100"
>
...
@@ -370,8 +384,10 @@ export function TaskTable({
...
@@ -370,8 +384,10 @@ export function TaskTable({
</
span
>
</
span
>
)
}
)
}
<
div
className
=
"flex items-center gap-1.5"
>
<
div
className
=
"flex items-center gap-1.5"
>
<
span
className
=
"text-xs text-muted-foreground"
>
<
span
className
=
"whitespace-nowrap text-xs text-muted-foreground"
>
{
formatDate
(
sub
.
DueDate
)
}
{
sub
.
CompletedDate
?
`✓
${
formatDateShort
(
sub
.
CompletedDate
)}
`
:
formatDateShort
(
sub
.
DueDate
)
}
</
span
>
</
span
>
<
DueBadge
<
DueBadge
dueDate
=
{
sub
.
DueDate
}
dueDate
=
{
sub
.
DueDate
}
...
...
src/components/tasks/task-utils.ts
View file @
7c57e406
...
@@ -22,6 +22,7 @@ export function toFormValues(task: Task): TaskFormValues {
...
@@ -22,6 +22,7 @@ export function toFormValues(task: Task): TaskFormValues {
assigneeId
:
task
.
AssigneeId
,
assigneeId
:
task
.
AssigneeId
,
startDate
:
toISODate
(
task
.
StartDate
),
startDate
:
toISODate
(
task
.
StartDate
),
dueDate
:
toISODate
(
task
.
DueDate
),
dueDate
:
toISODate
(
task
.
DueDate
),
completedDate
:
toISODate
(
task
.
CompletedDate
),
progress
:
task
.
Progress
,
progress
:
task
.
Progress
,
};
};
}
}
...
...
src/lib/data.ts
View file @
7c57e406
...
@@ -41,6 +41,7 @@ export interface Task {
...
@@ -41,6 +41,7 @@ export interface Task {
CreatedById
:
number
;
CreatedById
:
number
;
StartDate
:
Date
|
null
;
StartDate
:
Date
|
null
;
DueDate
:
Date
|
null
;
DueDate
:
Date
|
null
;
CompletedDate
:
Date
|
null
;
Progress
:
number
;
Progress
:
number
;
CreatedAt
:
Date
;
CreatedAt
:
Date
;
SubtaskCount
:
number
;
SubtaskCount
:
number
;
...
@@ -257,7 +258,7 @@ const TASK_SELECT = `
...
@@ -257,7 +258,7 @@ const TASK_SELECT = `
SELECT t.Id, t.WorkspaceId, t.Title, t.Description, t.Status, t.Priority,
SELECT t.Id, t.WorkspaceId, t.Title, t.Description, t.Status, t.Priority,
t.Entry,
t.Entry,
t.AssigneeId, a.Name AS AssigneeName, t.CreatedById,
t.AssigneeId, a.Name AS AssigneeName, t.CreatedById,
t.StartDate, t.DueDate, t.Progress, t.CreatedAt, w.Name AS WorkspaceName,
t.StartDate, t.DueDate,
t.CompletedDate,
t.Progress, t.CreatedAt, w.Name AS WorkspaceName,
(SELECT COUNT(*) FROM dbo.Tasks s WHERE s.Entry = t.Id) AS SubtaskCount,
(SELECT COUNT(*) FROM dbo.Tasks s WHERE s.Entry = t.Id) AS SubtaskCount,
(SELECT COUNT(*) FROM dbo.Tasks s WHERE s.Entry = t.Id AND s.Status = 'done') AS SubtaskDone
(SELECT COUNT(*) FROM dbo.Tasks s WHERE s.Entry = t.Id AND s.Status = 'done') AS SubtaskDone
FROM dbo.Tasks t
FROM dbo.Tasks t
...
@@ -319,13 +320,17 @@ export async function createTask(
...
@@ -319,13 +320,17 @@ export async function createTask(
.
input
(
"
progress
"
,
sql
.
Int
,
input
.
progress
)
.
input
(
"
progress
"
,
sql
.
Int
,
input
.
progress
)
.
input
(
"
createdById
"
,
sql
.
Int
,
createdById
)
.
input
(
"
createdById
"
,
sql
.
Int
,
createdById
)
.
query
(
.
query
(
`INSERT INTO dbo.Tasks (WorkspaceId, Title, Description, Status, Priority, Entry, AssigneeId, StartDate, DueDate, Progress, CreatedById)
`INSERT INTO dbo.Tasks (WorkspaceId, Title, Description, Status, Priority, Entry, AssigneeId, StartDate, DueDate, CompletedDate, Progress, CreatedById)
VALUES (@workspaceId, @title, @description, @status, @priority, @entry, @assigneeId, @startDate, @dueDate, @progress, @createdById)`
VALUES (@workspaceId, @title, @description, @status, @priority, @entry, @assigneeId, @startDate, @dueDate,
CASE WHEN @status = 'done' THEN CAST(GETDATE() AS DATE) ELSE NULL END,
@progress, @createdById)`
);
);
}
}
export
async
function
updateTask
(
id
:
number
,
input
:
TaskInput
):
Promise
<
void
>
{
export
async
function
updateTask
(
id
:
number
,
input
:
TaskInput
):
Promise
<
void
>
{
const
pool
=
await
getPool
();
const
pool
=
await
getPool
();
// Início e vencimento são imutáveis após a criação: não entram no UPDATE.
// CompletedDate é gerenciada pelo status (preenche ao concluir, limpa ao reabrir).
await
pool
await
pool
.
request
()
.
request
()
.
input
(
"
id
"
,
sql
.
Int
,
id
)
.
input
(
"
id
"
,
sql
.
Int
,
id
)
...
@@ -334,14 +339,14 @@ export async function updateTask(id: number, input: TaskInput): Promise<void> {
...
@@ -334,14 +339,14 @@ export async function updateTask(id: number, input: TaskInput): Promise<void> {
.
input
(
"
status
"
,
sql
.
NVarChar
(
20
),
input
.
status
)
.
input
(
"
status
"
,
sql
.
NVarChar
(
20
),
input
.
status
)
.
input
(
"
priority
"
,
sql
.
NVarChar
(
10
),
input
.
priority
)
.
input
(
"
priority
"
,
sql
.
NVarChar
(
10
),
input
.
priority
)
.
input
(
"
assigneeId
"
,
sql
.
Int
,
input
.
assigneeId
)
.
input
(
"
assigneeId
"
,
sql
.
Int
,
input
.
assigneeId
)
.
input
(
"
startDate
"
,
sql
.
Date
,
input
.
startDate
)
.
input
(
"
dueDate
"
,
sql
.
Date
,
input
.
dueDate
)
.
input
(
"
progress
"
,
sql
.
Int
,
input
.
progress
)
.
input
(
"
progress
"
,
sql
.
Int
,
input
.
progress
)
.
query
(
.
query
(
`UPDATE dbo.Tasks
`UPDATE dbo.Tasks
SET Title = @title, Description = @description, Status = @status,
SET Title = @title, Description = @description, Status = @status,
Priority = @priority, AssigneeId = @assigneeId,
Priority = @priority, AssigneeId = @assigneeId, Progress = @progress,
StartDate = @startDate, DueDate = @dueDate, Progress = @progress,
CompletedDate = CASE WHEN @status = 'done'
THEN COALESCE(CompletedDate, CAST(GETDATE() AS DATE))
ELSE NULL END,
UpdatedAt = SYSUTCDATETIME()
UpdatedAt = SYSUTCDATETIME()
WHERE Id = @id`
WHERE Id = @id`
);
);
...
@@ -357,7 +362,13 @@ export async function updateTaskStatus(
...
@@ -357,7 +362,13 @@ export async function updateTaskStatus(
.
input
(
"
id
"
,
sql
.
Int
,
id
)
.
input
(
"
id
"
,
sql
.
Int
,
id
)
.
input
(
"
status
"
,
sql
.
NVarChar
(
20
),
status
)
.
input
(
"
status
"
,
sql
.
NVarChar
(
20
),
status
)
.
query
(
.
query
(
`UPDATE dbo.Tasks SET Status = @status, UpdatedAt = SYSUTCDATETIME() WHERE Id = @id`
`UPDATE dbo.Tasks
SET Status = @status,
CompletedDate = CASE WHEN @status = 'done'
THEN COALESCE(CompletedDate, CAST(GETDATE() AS DATE))
ELSE NULL END,
UpdatedAt = SYSUTCDATETIME()
WHERE Id = @id`
);
);
}
}
...
...
src/lib/dates.ts
View file @
7c57e406
...
@@ -18,6 +18,14 @@ export function formatDate(date: Date | string | null): string {
...
@@ -18,6 +18,14 @@ export function formatDate(date: Date | string | null): string {
return
`
${
day
}
/
${
month
}
/
${
year
}
`
;
return
`
${
day
}
/
${
month
}
/
${
year
}
`
;
}
}
/** Formato curto dd/MM para exibição resumida das datas das tarefas. */
export
function
formatDateShort
(
date
:
Date
|
string
|
null
):
string
{
const
iso
=
toISODate
(
date
);
if
(
!
iso
)
return
"
—
"
;
const
[,
month
,
day
]
=
iso
.
split
(
"
-
"
);
return
`
${
day
}
/
${
month
}
`
;
}
function
isoToLocalDate
(
iso
:
string
):
Date
{
function
isoToLocalDate
(
iso
:
string
):
Date
{
const
[
year
,
month
,
day
]
=
iso
.
split
(
"
-
"
).
map
(
Number
);
const
[
year
,
month
,
day
]
=
iso
.
split
(
"
-
"
).
map
(
Number
);
return
new
Date
(
year
,
month
-
1
,
day
);
return
new
Date
(
year
,
month
-
1
,
day
);
...
...
src/lib/db-init.ts
View file @
7c57e406
...
@@ -47,6 +47,7 @@ const DDL_STATEMENTS: string[] = [
...
@@ -47,6 +47,7 @@ const DDL_STATEMENTS: string[] = [
CreatedById INT NOT NULL REFERENCES dbo.Users(Id),
CreatedById INT NOT NULL REFERENCES dbo.Users(Id),
StartDate DATE NULL,
StartDate DATE NULL,
DueDate DATE NULL,
DueDate DATE NULL,
CompletedDate DATE NULL,
Progress INT NOT NULL DEFAULT 0,
Progress INT NOT NULL DEFAULT 0,
CreatedAt DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME(),
CreatedAt DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME(),
UpdatedAt DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME()
UpdatedAt DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME()
...
@@ -56,6 +57,15 @@ const DDL_STATEMENTS: string[] = [
...
@@ -56,6 +57,15 @@ const DDL_STATEMENTS: string[] = [
`IF COL_LENGTH('dbo.Tasks', 'Progress') IS NULL
`IF COL_LENGTH('dbo.Tasks', 'Progress') IS NULL
ALTER TABLE dbo.Tasks ADD Progress INT NOT NULL DEFAULT 0`
,
ALTER TABLE dbo.Tasks ADD Progress INT NOT NULL DEFAULT 0`
,
// Data de conclusão (preenchida ao mudar o status para 'done')
`IF COL_LENGTH('dbo.Tasks', 'CompletedDate') IS NULL
ALTER TABLE dbo.Tasks ADD CompletedDate DATE NULL`
,
// Preenche a data de conclusão de tarefas já concluídas sem data
`UPDATE dbo.Tasks
SET CompletedDate = CAST(UpdatedAt AS DATE)
WHERE Status = 'done' AND CompletedDate IS NULL`
,
`IF OBJECT_ID('dbo.Subtasks', 'U') IS NULL
`IF OBJECT_ID('dbo.Subtasks', 'U') IS NULL
CREATE TABLE dbo.Subtasks (
CREATE TABLE dbo.Subtasks (
Id INT IDENTITY(1,1) PRIMARY KEY,
Id INT IDENTITY(1,1) PRIMARY KEY,
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment