bsw/jbe@0: Issue = mondelefant.new_class() bsw/jbe@0: Issue.table = 'issue' bsw/jbe@0: bsw@549: local new_selector = Issue.new_selector bsw@549: bsw@549: function Issue:new_selector() bsw@549: local selector = new_selector(self) bsw@935: selector:add_field("justify_interval(admission_time)::text", "admission_time_text") bsw@935: selector:add_field("justify_interval(discussion_time)::text", "discussion_time_text") bsw@935: selector:add_field("justify_interval(verification_time)::text", "verification_time_text") bsw@935: selector:add_field("justify_interval(voting_time)::text", "voting_time_text") bsw@935: selector:add_field("justify_interval(coalesce(issue.fully_frozen + issue.voting_time, issue.half_frozen + issue.verification_time, issue.accepted + issue.discussion_time, issue.created + issue.admission_time) - now())", "state_time_left") bsw@935: selector:add_field("justify_interval(now() - issue.closed)", "closed_ago") bsw@549: return selector bsw@549: end bsw@549: bsw/jbe@0: Issue:add_reference{ bsw/jbe@0: mode = 'm1', bsw/jbe@0: to = "Area", bsw/jbe@0: this_key = 'area_id', bsw/jbe@0: that_key = 'id', bsw/jbe@0: ref = 'area', bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Issue:add_reference{ bsw/jbe@0: mode = 'm1', bsw/jbe@0: to = "Policy", bsw/jbe@0: this_key = 'policy_id', bsw/jbe@0: that_key = 'id', bsw/jbe@0: ref = 'policy', bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Issue:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Initiative", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'issue_id', bsw/jbe@0: ref = 'initiatives', bsw@551: back_ref = 'issue', bsw@962: default_order = 'initiative.admitted DESC, initiative.rank, initiative.harmonic_weight DESC NULLS LAST, id' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Issue:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Interest", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'issue_id', bsw/jbe@0: ref = 'interests', bsw/jbe@0: back_ref = 'issue', bsw/jbe@0: default_order = '"id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Issue:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Supporter", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'issue_id', bsw/jbe@0: ref = 'supporters', bsw/jbe@0: back_ref = 'issue', bsw/jbe@0: default_order = '"id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Issue:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "DirectVoter", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'issue_id', bsw/jbe@0: ref = 'direct_voters', bsw/jbe@0: back_ref = 'issue', bsw/jbe@0: default_order = '"member_id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Issue:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Vote", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'issue_id', bsw/jbe@0: ref = 'votes', bsw/jbe@0: back_ref = 'issue', bsw/jbe@0: default_order = '"member_id", "initiative_id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Issue:add_reference{ bsw@2: mode = '1m', bsw@2: to = "Delegation", bsw@2: this_key = 'id', bsw@2: that_key = 'issue_id', bsw@2: ref = 'delegations', bsw@2: back_ref = 'issue' bsw@2: } bsw@2: bsw@2: Issue:add_reference{ bsw/jbe@0: mode = 'mm', bsw/jbe@0: to = "Member", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'id', bsw/jbe@0: connected_by_table = 'interest', bsw/jbe@0: connected_by_this_key = 'issue_id', bsw/jbe@0: connected_by_that_key = 'member_id', bsw/jbe@0: ref = 'members' bsw/jbe@0: } bsw/jbe@0: bsw@3: Issue:add_reference{ bsw@3: mode = 'mm', bsw@3: to = "Member", bsw@3: this_key = 'id', bsw@3: that_key = 'id', bsw@3: connected_by_table = 'direct_interest_snapshot', bsw@3: connected_by_this_key = 'issue_id', bsw@3: connected_by_that_key = 'member_id', bsw@3: ref = 'interested_members_snapshot' bsw@3: } bsw@3: bsw/jbe@6: Issue:add_reference{ bsw/jbe@6: mode = 'mm', bsw/jbe@6: to = "Member", bsw/jbe@6: this_key = 'id', bsw/jbe@6: that_key = 'id', bsw/jbe@6: connected_by_table = 'direct_voter', bsw/jbe@6: connected_by_this_key = 'issue_id', bsw/jbe@6: connected_by_that_key = 'member_id', bsw/jbe@6: ref = 'direct_voters' bsw/jbe@6: } bsw/jbe@6: bsw@525: Issue:add_reference{ bsw@525: mode = "11", bsw@525: to = mondelefant.class_prototype, bsw@525: this_key = "id", bsw@525: that_key = "issue_id", bsw@547: ref = "member_info", bsw@525: back_ref = "issue", bsw@525: selector_generator = function(list, options) bsw@547: assert(options.member_id, "member_id mandatory for member_info") bsw@525: local ids = { sep = ", " } bsw@525: for i, object in ipairs(list) do bsw@525: local id = object.id bsw@525: if id ~= nil then bsw@525: ids[#ids+1] = {"?", id} bsw@525: end bsw@525: end bsw@525: local sub_selector = Issue:get_db_conn():new_selector() bsw@525: if #ids == 0 then bsw@525: return sub_selector:empty_list_mode() bsw@525: end bsw@525: sub_selector:from("issue") bsw@525: sub_selector:add_field("issue.id", "issue_id") bsw@529: sub_selector:add_field{ '(delegation_info(?, null, null, issue.id, ?)).*', options.member_id, options.trustee_id } bsw@525: sub_selector:add_where{ 'issue.id IN ($)', ids } bsw@525: bsw@525: local selector = Issue:get_db_conn():new_selector() bsw@547: selector:add_from("issue") bsw@547: selector:join(sub_selector, "delegation_info", "delegation_info.issue_id = issue.id") bsw@525: selector:left_join("member", "first_trustee", "first_trustee.id = delegation_info.first_trustee_id") bsw@525: selector:left_join("member", "other_trustee", "other_trustee.id = delegation_info.other_trustee_id") bsw@525: selector:add_field("delegation_info.*") bsw@525: selector:add_field("first_trustee.name", "first_trustee_name") bsw@525: selector:add_field("other_trustee.name", "other_trustee_name") bsw@547: selector:left_join("direct_voter", nil, { "direct_voter.issue_id = issue.id AND direct_voter.member_id = ?", options.member_id }) bsw@547: selector:add_field("direct_voter.member_id NOTNULL", "direct_voted") bsw@886: selector:left_join("non_voter", nil, { "non_voter.issue_id = issue.id AND non_voter.member_id = ?", options.member_id }) bsw@886: selector:add_field("non_voter.member_id NOTNULL", "non_voter") bsw@525: return selector bsw@525: end bsw@525: } bsw@525: bsw@547: function Issue.list:load_everything_for_member_id(member_id) bsw@547: local areas = self:load("area") bsw@547: areas:load("unit") bsw@547: self:load("policy") bsw@551: if member_id then bsw@551: self:load("member_info", { member_id = member_id }) bsw@551: end bsw@551: local initiatives = self:load("initiatives") bsw@551: initiatives:load_everything_for_member_id(member_id) bsw@525: end bsw@525: bsw@548: function Issue.object:load_everything_for_member_id(member_id) bsw@548: local areas = self:load("area") bsw@548: areas:load("unit") bsw@548: self:load("policy") bsw@551: if member_id then bsw@551: self:load("member_info", { member_id = member_id }) bsw@551: end bsw@551: local initiatives = self:load("initiatives") bsw@551: initiatives:load_everything_for_member_id(member_id) bsw@548: end bsw@548: bsw@972: bsw@972: bsw/jbe@0: function Issue:get_state_name_for_state(value) bsw@2: local state_name_table = { bsw@972: admission = _"New", bsw@972: discussion = _"Discussion", bsw@896: verification = _"Frozen", bsw@972: voting = _"Voting", bsw@973: canceled_revoked_before_accepted = _"Canceled (before accepted due to revocation)", bsw@973: canceled_issue_not_accepted = _"Canceled (issue not accepted)", bsw@973: canceled_after_revocation_during_discussion = _"Canceled (during discussion due to revocation)", bsw@973: canceled_after_revocation_during_verification = _"Canceled (during verification due to revocation)", bsw@972: calculation = _"Calculation", bsw@973: canceled_no_initiative_admitted = _"Canceled (no initiative admitted)", bsw@972: finished_without_winner = _"Finished (without winner)", bsw@972: finished_with_winner = _"Finished (with winner)" bsw@2: } bsw@10: return state_name_table[value] or value or '' bsw/jbe@0: end bsw/jbe@0: bsw@972: bsw@972: bsw@2: function Issue:get_search_selector(search_string) bsw/jbe@0: return self:new_selector() bsw/jbe@0: :join('"initiative"', nil, '"initiative"."issue_id" = "issue"."id"') bsw/jbe@6: :join('"draft"', nil, '"draft"."initiative_id" = "initiative"."id"') bsw/jbe@6: :add_where{ '"initiative"."text_search_data" @@ "text_search_query"(?) OR "draft"."text_search_data" @@ "text_search_query"(?)', search_string, search_string } bsw/jbe@6: :add_group_by('"issue"."id"') bsw@976: :add_group_by('"issue"."area_id"') bsw@976: :add_group_by('"issue"."policy_id"') bsw@977: :add_group_by('"issue"."state"') bsw@977: :add_group_by('"issue"."phase_finished"') bsw@976: :add_group_by('"issue"."created"') bsw@976: :add_group_by('"issue"."accepted"') bsw@976: :add_group_by('"issue"."half_frozen"') bsw@976: :add_group_by('"issue"."fully_frozen"') bsw@976: :add_group_by('"issue"."closed"') bsw@976: :add_group_by('"issue"."status_quo_schulze_rank"') bsw@976: :add_group_by('"issue"."cleaned"') bsw@976: :add_group_by('"issue"."snapshot"') bsw@976: :add_group_by('"issue"."latest_snapshot_event"') bsw@976: :add_group_by('"issue"."population"') bsw@976: :add_group_by('"issue"."voter_count"') bsw@976: :add_group_by('"issue"."admission_time"') bsw@976: :add_group_by('"issue"."discussion_time"') bsw@976: :add_group_by('"issue"."verification_time"') bsw@976: :add_group_by('"issue"."voting_time"') bsw@976: --:set_distinct() bsw/jbe@0: end bsw/jbe@0: bsw@75: function Issue:modify_selector_for_state(initiatives_selector, state) bsw@51: if state == "new" then bsw@75: initiatives_selector:add_where("issue.accepted ISNULL AND issue.closed ISNULL") bsw@51: elseif state == "accepted" then bsw@75: initiatives_selector:add_where("issue.accepted NOTNULL AND issue.half_frozen ISNULL AND issue.closed ISNULL") bsw@51: elseif state == "frozen" then bsw@75: initiatives_selector:add_where("issue.half_frozen NOTNULL AND issue.fully_frozen ISNULL AND issue.closed ISNULL") bsw@51: elseif state == "voting" then bsw@75: initiatives_selector:add_where("issue.fully_frozen NOTNULL AND issue.closed ISNULL") bsw@51: elseif state == "finished" then bsw@75: initiatives_selector:add_where("issue.fully_frozen NOTNULL AND issue.closed NOTNULL") bsw@973: elseif state == "canceled" then bsw@75: initiatives_selector:add_where("issue.fully_frozen ISNULL AND issue.closed NOTNULL") bsw@75: else bsw@75: error("Invalid state") bsw@51: end bsw@51: end bsw@51: bsw@2: bsw@2: function Issue.object_get:state_name() bsw@2: return Issue:get_state_name_for_state(self.state) bsw@2: end bsw@2: bsw@2: function Issue.object_get:next_states_names() bsw@2: local next_states = self.next_states bsw@2: if not next_states then bsw@2: return bsw@2: end bsw@2: local state_names = {} bsw@2: for i, state in ipairs(self.next_states) do bsw@2: state_names[#state_names+1] = Issue:get_state_name_for_state(state) bsw@2: end bsw@2: return table.concat(state_names, ", ") bsw@525: end bsw@525: bsw@525: function Issue.object_get:etherpad_url() bsw@525: return config.etherpad.base_url .. "p/" .. config.etherpad.group_id .. "$Issue" .. self.id bsw@551: end