Browse Source

fix tags for projects and reqs, and add GUI for them.

master
Gisle Aune 1 year ago
parent
commit
97ad87680a
  1. 2
      frontend/src/lib/components/controls/StatusSelect.svelte
  2. 2
      frontend/src/lib/modals/ItemCreateModal.svelte
  3. 15
      frontend/src/lib/modals/ProjectCreateEditModal.svelte
  4. 10
      frontend/src/lib/modals/RequirementCreateModal.svelte
  5. 6
      frontend/src/lib/models/project.ts
  6. 69
      ports/mysql/projects.go

2
frontend/src/lib/components/controls/StatusSelect.svelte

@ -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">

2
frontend/src/lib/modals/ItemCreateModal.svelte

@ -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;

15
frontend/src/lib/modals/ProjectCreateEditModal.svelte

@ -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>

10
frontend/src/lib/modals/RequirementCreateModal.svelte

@ -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>

6
frontend/src/lib/models/project.ts

@ -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[]
}

69
ports/mysql/projects.go

@ -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 {

Loading…
Cancel
Save