panelFreelanceProjects.py (12140B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\info\panels\panelFreelanceProjects.py 2 import uthread2 3 from carbonui import uiconst, TextColor 4 from carbonui.text.styles import TextHeader 5 from carbonui.control.contextMenu.menuData import MenuData 6 from carbonui.primitives.container import Container 7 from characterdata import careerpath 8 from eve.client.script.ui.quickFilter import QuickFilterEdit 9 from freelanceprojects.client import freelance_signals 10 from freelanceprojects.client.api import get_freelance_projects_repository 11 from freelanceprojects.client.ui.admin_browser import FreelanceFilterMenuButtonIcon, FreelanceSortByMenuButtonIcon 12 from freelanceprojects.client.ui.admin_browser_settings import career_path_filter_setting, sort_by_setting, have_participated_in_filter_setting, have_unclaimed_rewards_for_filter_setting, only_my_active_jobs_setting, only_committable_jobs_setting 13 from jobboard.client import ProviderType, get_provider 14 from jobboard.client.features.freelance_projects.no_jobs_container import NoCorporationJobsContainer 15 from jobboard.client.features.freelance_projects.provider_section import FreelanceJobProviderSection 16 from localization import GetByLabel, GetByMessageID 17 from logging import getLogger 18 from threadutils import throttled 19 logger = getLogger('freelance_projects') 20 21 class PanelFreelanceProjects(Container): 22 23 def ApplyAttributes(self, attributes): 24 super(PanelFreelanceProjects, self).ApplyAttributes(attributes) 25 self._activeTasklet = None 26 self._corporation_id = attributes.corporation_id 27 self._reconstruct_thread = None 28 self._jobs_section = None 29 self._viewer_id = attributes.viewer_id 30 self.quick_filter = None 31 self._repository = get_freelance_projects_repository() 32 self._construct_top_container() 33 self._connect_signals() 34 35 def Close(self): 36 self._repository.stopped_viewing(self._viewer_id, [self._corporation_id]) 37 self._disconnect_signals() 38 super(PanelFreelanceProjects, self).Close() 39 40 def _connect_signals(self): 41 freelance_signals.on_storage_invalidated.connect(self._on_storage_invalidated) 42 freelance_signals.on_repository_cleared.connect(self._on_repository_cleared) 43 freelance_signals.on_created.connect(self._on_projects_changed) 44 freelance_signals.on_closed.connect(self._on_projects_changed) 45 freelance_signals.on_expired.connect(self._on_projects_changed) 46 freelance_signals.on_completed.connect(self._on_projects_changed) 47 freelance_signals.on_kicked.connect(self._on_projects_changed) 48 career_path_filter_setting.on_change.connect(self._on_setting_changed) 49 only_my_active_jobs_setting.on_change.connect(self._on_setting_changed) 50 sort_by_setting.on_change.connect(self._on_setting_changed) 51 have_participated_in_filter_setting.on_change.connect(self._on_setting_changed) 52 have_unclaimed_rewards_for_filter_setting.on_change.connect(self._on_setting_changed) 53 only_committable_jobs_setting.on_change.connect(self._on_setting_changed) 54 55 def _disconnect_signals(self): 56 freelance_signals.on_storage_invalidated.disconnect(self._on_storage_invalidated) 57 freelance_signals.on_repository_cleared.disconnect(self._on_repository_cleared) 58 freelance_signals.on_created.disconnect(self._on_projects_changed) 59 freelance_signals.on_closed.disconnect(self._on_projects_changed) 60 freelance_signals.on_expired.disconnect(self._on_projects_changed) 61 freelance_signals.on_completed.disconnect(self._on_projects_changed) 62 freelance_signals.on_kicked.disconnect(self._on_projects_changed) 63 career_path_filter_setting.on_change.disconnect(self._on_setting_changed) 64 only_my_active_jobs_setting.on_change.disconnect(self._on_setting_changed) 65 sort_by_setting.on_change.disconnect(self._on_setting_changed) 66 have_participated_in_filter_setting.on_change.disconnect(self._on_setting_changed) 67 have_unclaimed_rewards_for_filter_setting.on_change.disconnect(self._on_setting_changed) 68 only_committable_jobs_setting.on_change.disconnect(self._on_setting_changed) 69 70 def _on_projects_changed(self, *args): 71 self._reconstruct_content() 72 73 def _on_setting_changed(self, *_args): 74 self._reconstruct_content() 75 76 @throttled(0.5) 77 def _reconstruct_content(self): 78 if not self.display: 79 return 80 self.Load() 81 82 def _construct_top_container(self): 83 self.top_container = Container(name='top_container', parent=self, align=uiconst.TOTOP, height=32, padTop=8, padBottom=8) 84 TextHeader(name='title_label', parent=self.top_container, align=uiconst.TOLEFT, text=GetByLabel('UI/Corporations/FreelanceProjects/PanelTitle'), color=TextColor.HIGHLIGHT, padLeft=4, padRight=4, autoFadeSides=16) 85 self.total_active_projects = TextHeader(name='title_label', parent=self.top_container, align=uiconst.TOLEFT, text=GetByLabel(labelNameAndPath='UI/Corporations/CorporationWindow/Politics/ExtraInfoWrapper', extraInfo='-'), color=TextColor.HIGHLIGHT, autoFadeSides=16) 86 self._construct_filter() 87 self._construct_sort() 88 89 def Load(self): 90 if self._reconstruct_thread and self._reconstruct_thread.is_alive(): 91 self._reconstruct_thread.kill() 92 self._reconstruct_thread = uthread2.start_tasklet(self._load_projects) 93 94 def _construct_filter(self): 95 self.filter_button = FreelanceShowInfoFilterMenuButtonIcon(parent=self.top_container, align=uiconst.TORIGHT, padRight=8) 96 self.quick_filter = QuickFilterEdit(parent=self.top_container, align=uiconst.TORIGHT, width=120) 97 self.quick_filter.ReloadFunction = self._reconstruct_content 98 99 def _construct_sort(self): 100 self.sort_button = FreelanceSortByMenuButtonIcon(parent=self.top_container, align=uiconst.TORIGHT) 101 102 def _load_projects(self): 103 if self._jobs_section and not self._jobs_section.destroyed: 104 self._jobs_section.Close() 105 self._jobs_section = FreelanceJobProviderSection(parent=self, job_provider=get_provider(ProviderType.FREELANCE_PROJECTS), is_relevant=self._is_relevant, sort_jobs=self._sorting_and_filtering_function, corporation_id=self._corporation_id, on_loaded_callback=self._on_loaded, custom_empty_state_func=self._create_empty_state) 106 self._repository.started_viewing(self._viewer_id, [self._corporation_id]) 107 self._repository.request_projects_for_corporation(self._corporation_id, wait=True) 108 self._jobs_section.load() 109 110 def _create_empty_state(self, parent): 111 return NoCorporationJobsContainer(name='alert_container', parent=parent, align=uiconst.TOTOP, get_failures=self._get_failures, display=False) 112 113 def _get_failures(self): 114 storage_ids = self._get_storages() 115 return self._repository.get_storage_failures(storage_ids) 116 117 def _get_storages(self): 118 storage_ids = {self._corporation_id} 119 return storage_ids 120 121 def _is_relevant(self, job): 122 return job.corporation_id == self._corporation_id and job.is_active 123 124 def _on_storage_invalidated(self, storage_id): 125 if storage_id == self._corporation_id and self._jobs_section: 126 self.Load() 127 128 def _on_repository_cleared(self): 129 self.Load() 130 131 def _on_loaded(self): 132 self.total_active_projects.text = GetByLabel('UI/Corporations/CorporationWindow/Politics/ExtraInfoWrapper', extraInfo=self._repository.get_amount_active_for_corporation(self._corporation_id)) 133 134 def _sorting_and_filtering_function(self, jobs): 135 return self._get_projects_sorted(self._get_projects_filtered(jobs)) 136 137 def _get_projects_sorted(self, projects): 138 sortBy = sort_by_setting.get() 139 if sortBy == 'name': 140 return sorted(projects, key=lambda project: project.title.lower()) 141 elif sortBy == 'name_reversed': 142 return sorted(projects, key=lambda project: project.title.lower(), reverse=True) 143 elif sortBy == 'date_created': 144 return sorted(projects, key=lambda project: project.created_time) 145 elif sortBy == 'date_created_reversed': 146 return sorted(projects, key=lambda project: project.created_time, reverse=True) 147 elif sortBy == 'progress': 148 return sorted(projects, key=lambda project: project.progress_percentage) 149 elif sortBy == 'progress_reversed': 150 return sorted(projects, key=lambda project: project.progress_percentage, reverse=True) 151 elif sortBy == 'num_jumps': 152 return sorted(projects, key=lambda project: project.jumps) 153 elif sortBy == 'num_jumps_reversed': 154 return sorted(projects, key=lambda project: project.jumps, reverse=True) 155 elif sortBy == 'time_remaining': 156 return sorted(projects, key=lambda project: (project.expiration_time is None, project.expiration_time)) 157 elif sortBy == 'time_remaining_reversed': 158 return sorted(projects, key=lambda project: (project.expiration_time is None, project.expiration_time), reverse=True) 159 else: 160 logger.warning(u'sort_by method not found: {}'.format(sortBy)) 161 return projects 162 163 def _get_projects_filtered(self, projects): 164 filterStr = self.quick_filter.GetValue() 165 if filterStr: 166 projects = [ project for project in projects if filterStr.lower() in project.title.lower() ] 167 if have_participated_in_filter_setting.is_enabled(): 168 projects = [ project for project in projects if project.personal_progress ] 169 if have_unclaimed_rewards_for_filter_setting.is_enabled(): 170 projects = [ project for project in projects if project.has_claimable_rewards ] 171 if only_my_active_jobs_setting.is_enabled(): 172 projects = [ project for project in projects if project.is_committed ] 173 if only_committable_jobs_setting.is_enabled(): 174 projects = [ project for project in projects if project.can_commit() ] 175 career_path_filter = career_path_filter_setting.get() 176 if career_path_filter is not None: 177 projects = [ project for project in projects if project.career_path == career_path_filter ] 178 return projects 179 180 181 class FreelanceShowInfoFilterMenuButtonIcon(FreelanceFilterMenuButtonIcon): 182 183 def ApplyAttributes(self, attributes): 184 super(FreelanceShowInfoFilterMenuButtonIcon, self).ApplyAttributes(attributes) 185 have_participated_in_filter_setting.on_change.connect(self._on_filter_changed) 186 have_unclaimed_rewards_for_filter_setting.on_change.connect(self._on_filter_changed) 187 only_my_active_jobs_setting.on_change.connect(self._on_filter_changed) 188 only_committable_jobs_setting.on_change.connect(self._on_filter_changed) 189 190 def _is_filter_active(self): 191 return have_participated_in_filter_setting.is_enabled() or have_unclaimed_rewards_for_filter_setting.is_enabled() or career_path_filter_setting.get() is not None or only_my_active_jobs_setting.is_enabled() or only_committable_jobs_setting.is_enabled() 192 193 def GetMenu(self): 194 m = MenuData() 195 m.AddCaption(self.hint) 196 m.AddCheckbox(GetByLabel('UI/Corporations/FreelanceProjects/OnlyMyActiveJobs'), setting=only_my_active_jobs_setting) 197 m.AddCheckbox(GetByLabel('UI/Corporations/FreelanceProjects/OnlyProjectsICanAccept'), setting=only_committable_jobs_setting) 198 m.AddCheckbox(GetByLabel('UI/Corporations/FreelanceProjects/FilterJobsIHaveContributedTo'), setting=have_participated_in_filter_setting) 199 m.AddCheckbox(GetByLabel('UI/Corporations/FreelanceProjects/HaveUnclaimedRewardsFor'), setting=have_unclaimed_rewards_for_filter_setting) 200 m.AddSeparator() 201 m.AddCaption(GetByLabel('Character/CareerPaths/CareerPath')) 202 m.AddRadioButton(GetByLabel('UI/Common/Any'), None, career_path_filter_setting) 203 for c_id, c in careerpath.get_career_paths().iteritems(): 204 m.AddRadioButton(GetByMessageID(c.nameID), c_id, career_path_filter_setting) 205 206 return m