Browse Source

add project subtraction amounts.

main
Gisle Aune 4 years ago
parent
commit
c5af5860bf
  1. 3
      api/project.go
  2. 5
      database/postgres/project.go
  3. 11
      migrations/postgres/20210405234346_add_project_column_subtract_amount.sql
  4. 30
      models/project.go
  5. 69
      svelte-ui/src/components/Progress.svelte
  6. 3
      svelte-ui/src/components/ProgressNumbers.svelte
  7. 16
      svelte-ui/src/components/ProjectProgress.svelte
  8. 6
      svelte-ui/src/forms/ProjectForm.svelte
  9. 3
      svelte-ui/src/models/project.ts

3
api/project.go

@ -63,6 +63,9 @@ func Project(g *gin.RouterGroup, db database.Database) {
if project.Active && project.StatusTag != nil { if project.Active && project.StatusTag != nil {
project.StatusTag = nil project.StatusTag = nil
} }
if project.SubtractAmount < 0 {
project.SubtractAmount = 0
}
return &models.ProjectResult{ return &models.ProjectResult{
Project: project, Project: project,

5
database/postgres/project.go

@ -75,9 +75,9 @@ func (r *projectRepository) List(ctx context.Context, filter models.ProjectFilte
func (r *projectRepository) Insert(ctx context.Context, project models.Project) error { func (r *projectRepository) Insert(ctx context.Context, project models.Project) error {
_, err := r.db.NamedExecContext(ctx, ` _, err := r.db.NamedExecContext(ctx, `
INSERT INTO project( INSERT INTO project(
project_id, user_id, name, description, icon, active, created_time, start_time, end_time, status_tag, favorite
project_id, user_id, name, description, icon, active, created_time, start_time, end_time, subtract_amount, status_tag, favorite
) VALUES ( ) VALUES (
:project_id, :user_id, :name, :description, :icon, :active, :created_time, :start_time, :end_time, :status_tag, :favorite
:project_id, :user_id, :name, :description, :icon, :active, :created_time, :start_time, :end_time, :subtract_amount, :status_tag, :favorite
) )
`, &project) `, &project)
if err != nil { if err != nil {
@ -96,6 +96,7 @@ func (r *projectRepository) Update(ctx context.Context, project models.Project)
active = :active, active = :active,
start_time = :start_time, start_time = :start_time,
end_time = :end_time, end_time = :end_time,
subtract_amount = :subtract_amount,
status_tag = :status_tag, status_tag = :status_tag,
favorite = :favorite favorite = :favorite
WHERE project_id=:project_id WHERE project_id=:project_id

11
migrations/postgres/20210405234346_add_project_column_subtract_amount.sql

@ -0,0 +1,11 @@
-- +goose Up
-- +goose StatementBegin
ALTER TABLE project
ADD COLUMN subtract_amount INT NOT NULL DEFAULT 0;
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
ALTER TABLE project
DROP COLUMN IF EXISTS subtract_amount;
-- +goose StatementEnd

30
models/project.go

@ -6,17 +6,18 @@ import (
) )
type Project struct { type Project struct {
ID string `json:"id" db:"project_id"`
UserID string `json:"-" db:"user_id"`
Name string `json:"name" db:"name"`
Description string `json:"description" db:"description"`
Icon string `json:"icon" db:"icon"`
Active bool `json:"active" db:"active"`
CreatedTime time.Time `json:"createdTime" db:"created_time"`
StartTime *time.Time `json:"startTime" db:"start_time"`
EndTime *time.Time `json:"endTime" db:"end_time"`
StatusTag *string `json:"statusTag" db:"status_tag"`
Favorite bool `json:"favorite" db:"favorite"`
ID string `json:"id" db:"project_id"`
UserID string `json:"-" db:"user_id"`
Name string `json:"name" db:"name"`
Description string `json:"description" db:"description"`
Icon string `json:"icon" db:"icon"`
Active bool `json:"active" db:"active"`
CreatedTime time.Time `json:"createdTime" db:"created_time"`
StartTime *time.Time `json:"startTime" db:"start_time"`
EndTime *time.Time `json:"endTime" db:"end_time"`
SubtractAmount int `json:"subtractAmount" db:"subtract_amount"`
StatusTag *string `json:"statusTag" db:"status_tag"`
Favorite bool `json:"favorite" db:"favorite"`
} }
func (project *Project) Update(update ProjectUpdate) { func (project *Project) Update(update ProjectUpdate) {
@ -46,6 +47,12 @@ func (project *Project) Update(update ProjectUpdate) {
if update.ClearEndTime { if update.ClearEndTime {
project.EndTime = nil project.EndTime = nil
} }
if update.SubtractAmount != nil {
project.SubtractAmount = *update.SubtractAmount
if project.SubtractAmount < 0 {
project.SubtractAmount = 0
}
}
if update.StatusTag != nil { if update.StatusTag != nil {
project.StatusTag = update.StatusTag project.StatusTag = update.StatusTag
} }
@ -70,6 +77,7 @@ type ProjectUpdate struct {
ClearStartTime bool `json:"clearStartTime"` ClearStartTime bool `json:"clearStartTime"`
EndTime *time.Time `json:"endTime"` EndTime *time.Time `json:"endTime"`
ClearEndTime bool `json:"clearEndTime"` ClearEndTime bool `json:"clearEndTime"`
SubtractAmount *int `json:"subtractAmount"`
StatusTag *string `json:"statusTag"` StatusTag *string `json:"statusTag"`
ClearStatusTag bool `json:"clearStatusTag"` ClearStatusTag bool `json:"clearStatusTag"`
Favorite *bool `json:"favorite"` Favorite *bool `json:"favorite"`

69
svelte-ui/src/components/Progress.svelte

@ -28,39 +28,46 @@
let title = ""; let title = "";
$: { $: {
let level = Math.floor(count / target);
if (level >= COLORS.length - 1 || (level > 1 && green)) {
offs = 0;
ons = target;
offClass = "gold";
onClass = "diamond";
} else {
if (count > 0 && count == (level * target)) {
level -= 1;
if (count > 0 && target > 0) {
let level = Math.floor(count / target);
if (level >= COLORS.length - 1 || (level > 1 && green)) {
offs = 0;
ons = target;
offClass = "gold";
onClass = "diamond";
} else {
if (count > 0 && count == (level * target)) {
level -= 1;
}
ons = count - (level * target);
offs = target - ons;
offClass = COLORS[level];
onClass = COLORS[level + 1];
} }
ons = count - (level * target);
offs = target - ons;
offClass = COLORS[level];
onClass = COLORS[level + 1];
}
if (green) {
onClass = "green"
offClass = "none"
}
if (gray) {
onClass = "gray"
offClass = "none"
}
if (contextColor) {
onClass = "sccpb"
offClass = "none"
}
if (green) {
onClass = "green"
offClass = "none"
}
if (gray) {
onClass = "gray"
offClass = "none"
}
if (contextColor) {
onClass = "sccpb"
offClass = "none"
// Mark it non-segmented if the target is too high. This prevents a clunky progress bar,
// or a browser freeze if you set the target very high.
nonSegmented = (target >= 60);
} else {
offClass = "none";
nonSegmented = false;
ons = 0;
offs = 1;
} }
// Mark it non-segmented if the target is too high. This prevents a clunky progress bar,
// or a browser freeze if you set the target very high.
nonSegmented = (target >= 60);
} }
$: { $: {
@ -94,10 +101,10 @@
<div style="flex: {offs}" class={"non-segmented off " + offClass}></div> <div style="flex: {offs}" class={"non-segmented off " + offClass}></div>
{/if} {/if}
{:else} {:else}
{#each {length: ons} as _}
{#each {length: Math.max(ons, 0)} as _}
<div class={"on " + onClass}></div> <div class={"on " + onClass}></div>
{/each} {/each}
{#each {length: offs} as _}
{#each {length: Math.max(offs, 0)} as _}
<div class={"off " + offClass}></div> <div class={"off " + offClass}></div>
{/each} {/each}
{/if} {/if}

3
svelte-ui/src/components/ProgressNumbers.svelte

@ -23,6 +23,9 @@
progressTarget = Math.max((project.tasks||[]).map(t => t.itemAmount * (t.item.groupWeight || 1)).reduce((n,m) => n+m, 0), 1); progressTarget = Math.max((project.tasks||[]).map(t => t.itemAmount * (t.item.groupWeight || 1)).reduce((n,m) => n+m, 0), 1);
progressAmount = Math.max(progressAmount - project.subtractAmount, 0);
progressTarget = Math.max(progressTarget - project.subtractAmount, 0);
if (project.endTime) { if (project.endTime) {
const start = Date.parse(project.startTime || project.createdTime); const start = Date.parse(project.startTime || project.createdTime);
const end = Date.parse(project.endTime); const end = Date.parse(project.endTime);

16
svelte-ui/src/components/ProjectProgress.svelte

@ -5,6 +5,7 @@
interface ProjectLike { interface ProjectLike {
tasks?: TaskResult[] tasks?: TaskResult[]
statusTag?: string statusTag?: string
subtractAmount?: number,
} }
export let project: ProjectLike; export let project: ProjectLike;
@ -12,11 +13,16 @@
let progressAmount: number; let progressAmount: number;
let progressTarget: number; let progressTarget: number;
$: progressAmount = (project.tasks||[]).map(t => (t.active || t.statusTag === "to do" || t.statusTag === "on hold")
? Math.min(t.completedAmount, t.itemAmount) * (t.item.groupWeight || 1)
: t.itemAmount * (t.item.groupWeight || 1)
).reduce((n,m) => n+m, 0);
$: progressTarget = Math.max((project.tasks||[]).map(t => t.itemAmount * (t.item.groupWeight || 1)).reduce((n,m) => n+m, 0), 1);
$: {
progressAmount = (project.tasks||[]).map(t => (t.active || t.statusTag === "to do" || t.statusTag === "on hold")
? Math.min(t.completedAmount, t.itemAmount) * (t.item.groupWeight || 1)
: t.itemAmount * (t.item.groupWeight || 1)
).reduce((n,m) => n+m, 0);
progressTarget = Math.max((project.tasks||[]).map(t => t.itemAmount * (t.item.groupWeight || 1)).reduce((n,m) => n+m, 0), 1);
progressAmount = Math.max(progressAmount - (project.subtractAmount||0), 0);
progressTarget = Math.max(progressTarget - (project.subtractAmount||0), 0);
}
</script> </script>
<Progress thin contextColor count={progressAmount} target={progressTarget} /> <Progress thin contextColor count={progressAmount} target={progressTarget} />

6
svelte-ui/src/forms/ProjectForm.svelte

@ -26,6 +26,7 @@
createdTime: "", createdTime: "",
tasks: [], tasks: [],
favorite: false, favorite: false,
subtractAmount: 0,
} }
let verb = "Add"; let verb = "Add";
if (md.name === "project.edit" || md.name === "project.delete") { if (md.name === "project.edit" || md.name === "project.delete") {
@ -42,6 +43,7 @@
let statusTag = project.statusTag || ""; let statusTag = project.statusTag || "";
let icon = project.icon; let icon = project.icon;
let favorite = project.favorite; let favorite = project.favorite;
let subtractAmount = project.subtractAmount;
let error = null; let error = null;
let loading = false; let loading = false;
@ -57,6 +59,7 @@
startTime: ( startTime == "" ) ? null : new Date(startTime), startTime: ( startTime == "" ) ? null : new Date(startTime),
endTime: ( endTime == "" ) ? null : new Date(endTime), endTime: ( endTime == "" ) ? null : new Date(endTime),
statusTag: statusTag !== "" ? statusTag : null, statusTag: statusTag !== "" ? statusTag : null,
subtractAmount: Math.min(subtractAmount, 0),
name, description, icon, favorite, name, description, icon, favorite,
}).then(() => { }).then(() => {
@ -85,6 +88,7 @@
active: statusTag === "", active: statusTag === "",
statusTag: statusTag || null, statusTag: statusTag || null,
clearStatusTag: statusTag === "", clearStatusTag: statusTag === "",
subtractAmount: subtractAmount,
name, description, icon, favorite, name, description, icon, favorite,
}).then(() => { }).then(() => {
@ -119,6 +123,8 @@
{#if endTime != ""} {#if endTime != ""}
<label for="endTime">Start time</label> <label for="endTime">Start time</label>
<StartTimeSelect disabled={deletion} bind:value={startTime} /> <StartTimeSelect disabled={deletion} bind:value={startTime} />
<label for="subtractAmount">Subtract progress</label>
<input disabled={deletion} name="subtractAmount" type="number" bind:value={subtractAmount} />
{/if} {/if}
<label for="statusTag">Status</label> <label for="statusTag">Status</label>
<StatusTagSelect disabled={deletion} isProject bind:value={statusTag} /> <StatusTagSelect disabled={deletion} isProject bind:value={statusTag} />

3
svelte-ui/src/models/project.ts

@ -9,6 +9,7 @@ export default interface Project {
active: boolean active: boolean
createdTime: string createdTime: string
favorite: boolean favorite: boolean
subtractAmount: number
startTime?: string startTime?: string
endTime?: string endTime?: string
statusTag?: string statusTag?: string
@ -30,6 +31,7 @@ export interface ProjectInput {
description: string description: string
icon: IconName icon: IconName
active: boolean active: boolean
subtractAmount: number
startTime?: string | Date startTime?: string | Date
endTime?: string | Date endTime?: string | Date
statusTag?: string statusTag?: string
@ -47,5 +49,6 @@ export interface ProjectUpdate {
clearEndTime?: boolean clearEndTime?: boolean
statusTag?: string statusTag?: string
clearStatusTag?: boolean clearStatusTag?: boolean
subtractAmount?: number
favorite?: boolean favorite?: boolean
} }
Loading…
Cancel
Save