| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- using Invercargill;
- using Invercargill.DataStructures;
- using Spry;
- using Spry.Authentication;
- using Statum;
- using ClankerSaddle.Data;
- using ClankerSaddle.Services;
- namespace ClankerSaddle {
- /** A project row on the projects list, with task counts and a link to its page. */
- public class ProjectRowView : Object {
- public int64 id { get; set; }
- public string name { get; set; default = ""; }
- public string git_url { get; set; default = ""; }
- public string default_branch { get; set; default = ""; }
- public string summary { get; set; default = ""; }
- public int64 open_tasks { get; set; }
- public int64 done_tasks { get; set; }
- }
- /** Public data of the `projects` slot. */
- public class ProjectsPublic : Object {
- public Statum.Model.ActionDto create { get; set; }
- }
- /**
- * Entrypoint for /projects: lists every project with open/done task
- * counts and authors the create-project action (login required).
- */
- public class ProjectsEntrypoint : StatumEntrypoint {
- private ProjectService project_service = Inversion.inject<ProjectService>();
- private TaskService task_service = Inversion.inject<TaskService>();
- private UserService users = Inversion.inject<UserService>();
- public override async DirectiveBuilder handle() throws GLib.Error {
- var guard = yield SpryAuth.require_login(directives(), request, users);
- if (guard != null) {
- return (!)guard;
- }
- var rows = new Vector<ProjectRowView>();
- var tasks = yield task_service.list_tasks(null, null);
- foreach (var project in yield project_service.list_projects()) {
- var view = new ProjectRowView() {
- id = project.id,
- name = project.name,
- git_url = project.git_url,
- default_branch = project.default_branch,
- summary = project.summary ?? ""
- };
- foreach (var task in tasks) {
- if (task.project_id != project.id) {
- continue;
- }
- if (task.status == STATUS_DONE || task.status == STATUS_FAILED) {
- view.done_tasks++;
- } else {
- view.open_tasks++;
- }
- }
- rows.add(view);
- }
- var pub = new ProjectsPublic();
- pub.create = action_registry.author<CreateProjectAction>();
- var props = (PropertyDictionary) GObjectMapping.to_properties(pub);
- props["projects"] = StateJson.list<ProjectRowView>(rows.to_immutable_buffer());
- var slot = state_service.new_slot(Scope.PAGE, new State() {
- type_name = "projects",
- public_data = props,
- private_data = new PropertyDictionary()
- });
- return directives().set(slot);
- }
- }
- /** A linked project on the project detail page, with a remove action. */
- public class ProjectLinkView : Object {
- public int64 link_id { get; set; }
- public int64 project_id { get; set; }
- public string name { get; set; default = ""; }
- public string git_url { get; set; default = ""; }
- public string relationship { get; set; default = ""; }
- public bool co_developed { get; set; }
- public Statum.Model.ActionDto? remove { get; set; }
- }
- /** A task row on the project detail page. */
- public class ProjectTaskRowView : Object {
- public int64 id { get; set; }
- public string title { get; set; default = ""; }
- public string status { get; set; default = ""; }
- public int64 priority { get; set; }
- public bool is_design_task { get; set; }
- }
- /** A rule attached to the project, with its detach action. */
- public class ProjectRuleRowView : Object {
- public int64 link_id { get; set; }
- public int64 rule_id { get; set; }
- public string name { get; set; default = ""; }
- public string body { get; set; default = ""; }
- public Statum.Model.ActionDto? detach { get; set; }
- }
- /** A rule option in the attach selects (project and task pages). */
- public class RuleOptionView : Object {
- public int64 id { get; set; }
- public string name { get; set; default = ""; }
- }
- /** Public data of the `project` slot. */
- public class ProjectDetailPublic : Object {
- public bool exists { get; set; }
- public int64 id { get; set; }
- public string name { get; set; default = ""; }
- public string git_url { get; set; default = ""; }
- public string default_branch { get; set; default = ""; }
- public string summary { get; set; default = ""; }
- public string created_display { get; set; default = ""; }
- public Statum.Model.ActionDto? update { get; set; }
- public Statum.Model.ActionDto? add_link { get; set; }
- public Statum.Model.ActionDto? attach_rule { get; set; }
- }
- /**
- * Entrypoint for /projects/{project_id}: the project's editable card,
- * its co-developed/reference links (with remove actions), its rules
- * (with detach actions and the attach form), the other projects
- * available for linking, and its task list.
- */
- public class ProjectDetailEntrypoint : StatumEntrypoint {
- private ProjectService project_service = Inversion.inject<ProjectService>();
- private TaskService task_service = Inversion.inject<TaskService>();
- private RuleService rule_service = Inversion.inject<RuleService>();
- private UserService users = Inversion.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 project_id = int64.parse(request.route("project_id") ?? "0");
- var project = yield project_service.get_project(project_id);
- if (project == null) {
- return directives().set_typed<ProjectDetailPublic>("project", Scope.PAGE,
- new ProjectDetailPublic() { exists = false });
- }
- var sealed = new ProjectActionPrivate() { project_id = project_id };
- var pub = new ProjectDetailPublic() {
- exists = true,
- id = ((!)project).id,
- name = ((!)project).name,
- git_url = ((!)project).git_url,
- default_branch = ((!)project).default_branch,
- summary = ((!)project).summary ?? "",
- created_display = ((!)project).created_at != null
- ? ((!)((!)project).created_at).format("%Y-%m-%d %H:%M") : "",
- update = action_registry.author_private<UpdateProjectAction, ProjectActionPrivate>(sealed),
- add_link = action_registry.author_private<AddProjectLinkAction, ProjectActionPrivate>(sealed),
- attach_rule = action_registry.author_private<AttachProjectRuleAction, ProjectActionPrivate>(sealed)
- };
- var links = new Vector<ProjectLinkView>();
- foreach (var link in yield project_service.list_links(project_id)) {
- var linked = yield project_service.get_project(link.linked_project_id);
- if (linked == null) {
- continue;
- }
- var private_blob = new ProjectLinkActionPrivate() {
- project_id = project_id,
- link_id = link.id
- };
- links.add(new ProjectLinkView() {
- link_id = link.id,
- project_id = link.linked_project_id,
- name = ((!)linked).name,
- git_url = ((!)linked).git_url,
- relationship = link.relationship,
- co_developed = link.relationship == LINK_CO_DEVELOPED,
- remove = action_registry.author_private<RemoveProjectLinkAction, ProjectLinkActionPrivate>(private_blob)
- });
- }
- var linkable = new Vector<ProjectRowView>();
- foreach (var other in yield project_service.list_projects()) {
- if (other.id != project_id) {
- linkable.add(new ProjectRowView() {
- id = other.id,
- name = other.name,
- git_url = other.git_url,
- default_branch = other.default_branch,
- summary = other.summary ?? ""
- });
- }
- }
- var task_rows = new Vector<ProjectTaskRowView>();
- foreach (var task in yield task_service.list_tasks(null, project_id)) {
- task_rows.add(new ProjectTaskRowView() {
- id = task.id,
- title = task.title,
- status = task.status,
- priority = task.priority,
- is_design_task = task.is_design_task
- });
- }
- var rule_rows = new Vector<ProjectRuleRowView>();
- foreach (var link in yield rule_service.list_project_attachments(project_id)) {
- var rule = yield rule_service.get_rule(link.rule_id);
- if (rule == null) {
- continue;
- }
- var private_blob = new ProjectRuleActionPrivate() {
- project_id = project_id,
- link_id = link.id
- };
- rule_rows.add(new ProjectRuleRowView() {
- link_id = link.id,
- rule_id = link.rule_id,
- name = ((!)rule).name,
- body = ((!)rule).body,
- detach = action_registry.author_private<DetachProjectRuleAction, ProjectRuleActionPrivate>(private_blob)
- });
- }
- var rule_options = new Vector<RuleOptionView>();
- foreach (var rule in yield rule_service.list_rules()) {
- rule_options.add(new RuleOptionView() {
- id = rule.id,
- name = rule.name
- });
- }
- var props = (PropertyDictionary) GObjectMapping.to_properties(pub);
- props["links"] = StateJson.list<ProjectLinkView>(links.to_immutable_buffer());
- props["linkable"] = StateJson.list<ProjectRowView>(linkable.to_immutable_buffer());
- props["tasks"] = StateJson.list<ProjectTaskRowView>(task_rows.to_immutable_buffer());
- props["rules"] = StateJson.list<ProjectRuleRowView>(rule_rows.to_immutable_buffer());
- props["rule_options"] = StateJson.list<RuleOptionView>(rule_options.to_immutable_buffer());
- var slot = state_service.new_slot(Scope.PAGE, new State() {
- type_name = "project",
- public_data = props,
- private_data = new PropertyDictionary()
- });
- return directives().set(slot);
- }
- }
- }
|