| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- using Inversion;
- using Spry;
- using Spry.Authentication;
- using Statum;
- using ClankerSaddle.Services;
- namespace ClankerSaddle {
- /** Sealed stack id carried by the stack actions. */
- public class StackActionPrivate : Object {
- public int64 stack_id { get; set; }
- }
- /** Sealed stack-member identity carried by {@link RemoveStackMemberAction}. */
- public class StackMemberActionPrivate : Object {
- public int64 stack_id { get; set; }
- public int64 member_id { get; set; }
- }
- /** Sealed stack + project identity for {@link ApplyStackToProjectAction}. */
- public class StackProjectApplyPrivate : Object {
- public int64 stack_id { get; set; }
- public int64 project_id { get; set; }
- }
- /** Sealed stack + goal identity for {@link ApplyStackToGoalAction}. */
- public class StackGoalApplyPrivate : Object {
- public int64 stack_id { get; set; }
- public int64 goal_id { get; set; }
- }
- /**
- * Creates a stack from the stacks form (name required, unique;
- * summary optional).
- */
- public class CreateStackAction : StatumAction {
- private StackService stacks = inject<StackService>();
- private UserService users = inject<UserService>();
- public override async DirectiveBuilder handle() throws GLib.Error {
- var guard = yield SpryAuth.require_login(directives(), request, users);
- if (guard != null) {
- return (!)guard;
- }
- string name = Forms.field(request, "name");
- if (name.length == 0) {
- return directives().notify("error", "A stack name is required").navigate("/stacks");
- }
- try {
- var stack = yield stacks.create_stack(name,
- Forms.field(request, "summary"));
- return directives().notify("success", @"Stack '$(stack.name)' created")
- .navigate(@"/stacks/$(stack.id)");
- } catch (Error e) {
- return directives().notify("error", @"Could not create the stack: $(e.message)").navigate("/stacks");
- }
- }
- }
- /**
- * Saves a stack's editable fields (name, summary); the id comes
- * from the sealed {@link StackActionPrivate} blob (the hidden form
- * field is a fallback). An empty summary clears the stored one.
- */
- public class UpdateStackAction : TypedStatumAction<StackActionPrivate> {
- private StackService stacks = inject<StackService>();
- private UserService users = inject<UserService>();
- protected override Type private_type { get { return typeof(StackActionPrivate); } }
- public override async DirectiveBuilder handle() throws GLib.Error {
- var guard = yield SpryAuth.require_login(directives(), request, users);
- if (guard != null) {
- return (!)guard;
- }
- var ctx = request_private;
- int64 stack_id = ctx != null ? ((!)ctx).stack_id : Forms.integer(request, "stack_id", 0);
- if (stack_id <= 0) {
- return directives().navigate("/stacks");
- }
- try {
- yield stacks.update_stack(stack_id,
- Forms.optional(request, "name"),
- request.form != null ? Forms.field(request, "summary") : null);
- return directives().notify("success", "Stack saved")
- .navigate(@"/stacks/$(stack_id)");
- } catch (Error e) {
- return directives().notify("error", @"Could not save the stack: $(e.message)")
- .navigate(@"/stacks/$(stack_id)");
- }
- }
- }
- /** Deletes a stack; the id comes from the sealed private blob. */
- public class DeleteStackAction : TypedStatumAction<StackActionPrivate> {
- private StackService stacks = inject<StackService>();
- private UserService users = inject<UserService>();
- protected override Type private_type { get { return typeof(StackActionPrivate); } }
- public override async DirectiveBuilder handle() throws GLib.Error {
- var guard = yield SpryAuth.require_login(directives(), request, users);
- if (guard != null) {
- return (!)guard;
- }
- var ctx = request_private;
- if (ctx == null) {
- return directives().navigate("/stacks");
- }
- try {
- yield stacks.delete_stack(((!)ctx).stack_id);
- return directives().notify("success", "Stack deleted").navigate("/stacks");
- } catch (Error e) {
- return directives().notify("error", @"Could not delete the stack: $(e.message)")
- .navigate("/stacks/$(((!)ctx).stack_id)");
- }
- }
- }
- /**
- * Adds a project to a stack; the stack id is sealed, the target
- * and relationship come from the form selects.
- */
- public class AddStackMemberAction : TypedStatumAction<StackActionPrivate> {
- private StackService stacks = inject<StackService>();
- private UserService users = inject<UserService>();
- protected override Type private_type { get { return typeof(StackActionPrivate); } }
- public override async DirectiveBuilder handle() throws GLib.Error {
- var guard = yield SpryAuth.require_login(directives(), request, users);
- if (guard != null) {
- return (!)guard;
- }
- var ctx = request_private;
- int64 stack_id = ctx != null ? ((!)ctx).stack_id : Forms.integer(request, "stack_id", 0);
- int64 project_id = Forms.integer(request, "project_id", 0);
- if (stack_id <= 0 || project_id <= 0) {
- return directives().notify("error", "Pick a project to add").navigate(@"/stacks/$(stack_id)");
- }
- try {
- yield stacks.add_member(stack_id, project_id,
- Forms.field(request, "relationship"));
- return directives().notify("success", "Project added to the stack")
- .navigate(@"/stacks/$(stack_id)");
- } catch (Error e) {
- return directives().notify("error", @"Could not add the project: $(e.message)")
- .navigate(@"/stacks/$(stack_id)");
- }
- }
- }
- /**
- * Removes a stack member; both ids come from the sealed private
- * blob.
- */
- public class RemoveStackMemberAction : TypedStatumAction<StackMemberActionPrivate> {
- private StackService stacks = inject<StackService>();
- private UserService users = inject<UserService>();
- protected override Type private_type { get { return typeof(StackMemberActionPrivate); } }
- public override async DirectiveBuilder handle() throws GLib.Error {
- var guard = yield SpryAuth.require_login(directives(), request, users);
- if (guard != null) {
- return (!)guard;
- }
- var ctx = request_private;
- if (ctx == null) {
- return directives().navigate("/stacks");
- }
- try {
- yield stacks.remove_member(((!)ctx).member_id);
- return directives().notify("success", "Project removed from the stack")
- .navigate(@"/stacks/$(((!)ctx).stack_id)");
- } catch (Error e) {
- return directives().notify("error", @"Could not remove the project: $(e.message)")
- .navigate(@"/stacks/$(((!)ctx).stack_id)");
- }
- }
- }
- /**
- * Applies a stack to a project (the project page's "Apply stack"
- * action): the stack's members land as project_links rows,
- * skipping exact duplicates. The stack comes from the form select;
- * the project id is sealed.
- */
- public class ApplyStackToProjectAction : TypedStatumAction<ProjectActionPrivate> {
- private StackService stacks = inject<StackService>();
- private UserService users = inject<UserService>();
- protected override Type private_type { get { return typeof(ProjectActionPrivate); } }
- public override async DirectiveBuilder handle() throws GLib.Error {
- var guard = yield SpryAuth.require_login(directives(), request, users);
- if (guard != null) {
- return (!)guard;
- }
- var ctx = request_private;
- int64 project_id = ctx != null ? ((!)ctx).project_id : Forms.integer(request, "project_id", 0);
- int64 stack_id = Forms.integer(request, "stack_id", 0);
- if (project_id <= 0 || stack_id <= 0) {
- return directives().notify("error", "Pick a stack to apply").navigate(@"/projects/$(project_id)");
- }
- try {
- int64 added = yield stacks.apply_to_project(stack_id, project_id);
- return directives().notify("success",
- added > 0
- ? @"Stack applied — $(added) link(s) added"
- : "Stack applied — nothing new to add")
- .navigate(@"/projects/$(project_id)");
- } catch (Error e) {
- return directives().notify("error", @"Could not apply the stack: $(e.message)")
- .navigate(@"/projects/$(project_id)");
- }
- }
- }
- /**
- * Applies a stack to a goal (the goal page's "Apply stack"
- * action): the stack's members land as goal_links rows, skipping
- * exact duplicates. The stack comes from the form select; the
- * goal id is sealed.
- */
- public class ApplyStackToGoalAction : SealedGoalAction {
- private StackService stacks = inject<StackService>();
- private UserService users = inject<UserService>();
- public override async DirectiveBuilder handle() throws GLib.Error {
- var guard = yield SpryAuth.require_login(directives(), request, users);
- if (guard != null) {
- return (!)guard;
- }
- int64 goal_id = sealed_goal_id();
- int64 stack_id = Forms.integer(request, "stack_id", 0);
- if (goal_id <= 0 || stack_id <= 0) {
- return directives().notify("error", "Pick a stack to apply").navigate(@"/goals/$(goal_id)");
- }
- try {
- int64 added = yield stacks.apply_to_goal(stack_id, goal_id);
- return directives().notify("success",
- added > 0
- ? @"Stack applied — $(added) link(s) added"
- : "Stack applied — nothing new to add")
- .navigate(@"/goals/$(goal_id)");
- } catch (Error e) {
- return directives().notify("error", @"Could not apply the stack: $(e.message)")
- .navigate(@"/goals/$(goal_id)");
- }
- }
- }
- }
|