fix tags for projects and reqs, and add GUI for them.
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -9,8 +9,6 @@
|
||||
import Icon, { type IconName } from "../layout/Icon.svelte";
|
||||
|
||||
export let status: Status;
|
||||
|
||||
console.log(STATUS_ENTRIES, status)
|
||||
</script>
|
||||
|
||||
<div class="status-select">
|
||||
|
||||
@@ -111,7 +111,7 @@ import ScheduledDateInput from "$lib/components/controls/ScheduledDateInput.svel
|
||||
stats: ctxStats.map(s => inputStats.find(s2 => s2.statId === s.statId) || s),
|
||||
acquiredTime: formatFormTime(current.acquiredTime),
|
||||
scheduledDate: current.scheduledDate,
|
||||
tags: current.tags,
|
||||
tags: [...current.tags],
|
||||
};
|
||||
itemId = current.id;
|
||||
scopeId = current.scopeId;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
import { getProjectListContext } from "$lib/components/contexts/ProjectListContext.svelte";
|
||||
import { getScopeContext } from "$lib/components/contexts/ScopeContext.svelte";
|
||||
import StatusSelect from "$lib/components/controls/StatusSelect.svelte";
|
||||
import TagInput from "$lib/components/controls/TagInput.svelte";
|
||||
import type Project from "$lib/models/project";
|
||||
import type { ProjectEntry, ProjectInput, Requirement, RequirementInput } from "$lib/models/project";
|
||||
import Status from "$lib/models/status";
|
||||
@@ -24,6 +25,7 @@
|
||||
let project: ProjectInput
|
||||
let projectId: number
|
||||
let oldStats: RequirementInput["stats"]
|
||||
let oldTags: string[]
|
||||
|
||||
let error: string
|
||||
let loading: boolean
|
||||
@@ -53,6 +55,7 @@
|
||||
description: "",
|
||||
status: Status.Available,
|
||||
createdTime: void(0),
|
||||
tags: [],
|
||||
}
|
||||
|
||||
show = true;
|
||||
@@ -63,8 +66,10 @@
|
||||
name: current.name,
|
||||
description: current.description,
|
||||
status: current.status,
|
||||
tags: [...current.tags],
|
||||
}
|
||||
|
||||
oldTags = current.tags;
|
||||
projectId = current.id;
|
||||
show = true;
|
||||
}
|
||||
@@ -80,7 +85,14 @@
|
||||
projectId = newProject.id
|
||||
break;
|
||||
case "Edit":
|
||||
await sl3(fetch).updateProject($scope.id, projectId, project);
|
||||
const submission = {
|
||||
...project,
|
||||
addTags: project.tags.filter(t => !oldTags.includes(t)),
|
||||
removeTags: oldTags.filter(t => !project.tags.includes(t)),
|
||||
tags: void(0),
|
||||
}
|
||||
|
||||
await sl3(fetch).updateProject($scope.id, projectId, submission);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -113,6 +125,7 @@
|
||||
<textarea name="description" bind:value={project.description} />
|
||||
<label for="stats">Status</label>
|
||||
<StatusSelect bind:status={project.status} />
|
||||
<TagInput bind:value={project.tags} />
|
||||
</ModalBody>
|
||||
</Modal>
|
||||
</form>
|
||||
@@ -9,6 +9,7 @@
|
||||
import { getScopeContext } from "$lib/components/contexts/ScopeContext.svelte";
|
||||
import StatInput from "$lib/components/controls/StatInput.svelte";
|
||||
import StatusSelect from "$lib/components/controls/StatusSelect.svelte";
|
||||
import TagInput from "$lib/components/controls/TagInput.svelte";
|
||||
import Checkbox from "$lib/components/layout/Checkbox.svelte";
|
||||
import type { ProjectEntry, Requirement, RequirementInput } from "$lib/models/project";
|
||||
import Status from "$lib/models/status";
|
||||
@@ -24,6 +25,7 @@
|
||||
let requirementId: number
|
||||
let oldStats: RequirementInput["stats"]
|
||||
let showAggregateRequired: boolean
|
||||
let oldTags: string[]
|
||||
|
||||
let error: string
|
||||
let loading: boolean
|
||||
@@ -57,6 +59,7 @@
|
||||
status: Status.Available,
|
||||
isCoarse: false,
|
||||
aggregateRequired: 0,
|
||||
tags: [],
|
||||
}
|
||||
|
||||
projectId = project.id;
|
||||
@@ -71,8 +74,10 @@
|
||||
stats: current.stats.map(s => ({acquired: s.acquired, required: s.required, statId: s.id})),
|
||||
isCoarse: current.isCoarse,
|
||||
aggregateRequired: current.aggregateRequired,
|
||||
tags: [...current.tags],
|
||||
}
|
||||
|
||||
oldTags = [...current.tags];
|
||||
oldStats = [...requirement.stats];
|
||||
projectId = project.id;
|
||||
requirementId = current.id;
|
||||
@@ -95,7 +100,9 @@
|
||||
case "Edit":
|
||||
const submission: Partial<RequirementInput> = {
|
||||
...requirement,
|
||||
stats: statDiff(oldStats, requirement.stats, -1)
|
||||
stats: statDiff(oldStats, requirement.stats, -1),
|
||||
addTags: requirement.tags.filter(t => !oldTags.includes(t)),
|
||||
removeTags: oldTags.filter(t => !requirement.tags.includes(t)),
|
||||
};
|
||||
|
||||
await sl3(fetch).updateRequirement($scope.id, projectId, requirementId, submission);
|
||||
@@ -130,6 +137,7 @@
|
||||
<label for="aggregateRequired">Aggregate Required (Zero for old behavior)</label>
|
||||
<input name="aggregateRequired" type="number" bind:value={requirement.aggregateRequired} />
|
||||
{/if}
|
||||
<TagInput bind:value={requirement.tags} />
|
||||
</ModalBody>
|
||||
<ModalBody>
|
||||
<label for="stats">Status</label>
|
||||
|
||||
@@ -27,6 +27,9 @@ export interface ProjectInput {
|
||||
name: string
|
||||
description: string
|
||||
status: number
|
||||
tags: string[]
|
||||
addTags?: string[]
|
||||
removeTags?: string[]
|
||||
}
|
||||
|
||||
export interface Requirement {
|
||||
@@ -52,4 +55,7 @@ export interface RequirementInput {
|
||||
isCoarse: boolean
|
||||
aggregateRequired: number
|
||||
stats: StatValueInput[]
|
||||
tags: string[]
|
||||
addTags?: string[]
|
||||
removeTags?: string[]
|
||||
}
|
||||
+67
-2
@@ -237,9 +237,16 @@ func (r *projectRepository) Insert(ctx context.Context, project entities.Project
|
||||
}
|
||||
|
||||
func (r *projectRepository) Update(ctx context.Context, project entities.Project, update models.ProjectUpdate) error {
|
||||
tx, err := r.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
q := r.q.WithTx(tx)
|
||||
|
||||
project.Update(update)
|
||||
|
||||
return r.q.UpdateProject(ctx, mysqlcore.UpdateProjectParams{
|
||||
err = q.UpdateProject(ctx, mysqlcore.UpdateProjectParams{
|
||||
OwnerID: project.OwnerID,
|
||||
Name: project.Name,
|
||||
Status: int(project.Status),
|
||||
@@ -248,6 +255,33 @@ func (r *projectRepository) Update(ctx context.Context, project entities.Project
|
||||
ID: project.ID,
|
||||
ScopeID: project.ScopeID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, tag := range update.RemoveTags {
|
||||
err := q.DeleteTag(ctx, mysqlcore.DeleteTagParams{
|
||||
ObjectKind: tagObjectKindProject,
|
||||
ObjectID: project.ID,
|
||||
TagName: tag,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, tag := range update.AddTags {
|
||||
err = q.InsertTag(ctx, mysqlcore.InsertTagParams{
|
||||
ObjectKind: tagObjectKindProject,
|
||||
ObjectID: project.ID,
|
||||
TagName: tag,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (r *projectRepository) Delete(ctx context.Context, project entities.Project) error {
|
||||
@@ -488,9 +522,16 @@ func (r *projectRepository) CreateRequirement(ctx context.Context, requirement e
|
||||
}
|
||||
|
||||
func (r *projectRepository) UpdateRequirement(ctx context.Context, requirement entities.Requirement, update models.RequirementUpdate) error {
|
||||
tx, err := r.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
q := r.q.WithTx(tx)
|
||||
|
||||
requirement.Update(update)
|
||||
|
||||
return r.q.UpdateProjectRequirement(ctx, mysqlcore.UpdateProjectRequirementParams{
|
||||
_ = q.UpdateProjectRequirement(ctx, mysqlcore.UpdateProjectRequirementParams{
|
||||
Name: requirement.Name,
|
||||
Status: int(requirement.Status),
|
||||
Description: requirement.Description,
|
||||
@@ -499,6 +540,30 @@ func (r *projectRepository) UpdateRequirement(ctx context.Context, requirement e
|
||||
ScopeID: requirement.ScopeID,
|
||||
AggregateRequired: requirement.AggregateRequired,
|
||||
})
|
||||
|
||||
for _, tag := range update.RemoveTags {
|
||||
err := q.DeleteTag(ctx, mysqlcore.DeleteTagParams{
|
||||
ObjectKind: tagObjectKindRequirement,
|
||||
ObjectID: requirement.ID,
|
||||
TagName: tag,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, tag := range update.AddTags {
|
||||
err = q.InsertTag(ctx, mysqlcore.InsertTagParams{
|
||||
ObjectKind: tagObjectKindRequirement,
|
||||
ObjectID: requirement.ID,
|
||||
TagName: tag,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (r *projectRepository) DeleteRequirement(ctx context.Context, requirement entities.Requirement) error {
|
||||
|
||||
Reference in New Issue
Block a user