class ProjectsList(BaseListView): """ The project list view is compound of : * the list of projects with action buttons (view, delete ...) * an action menu with: * links * an add projectform popup * a searchform """ add_template_vars = ('title', 'stream_actions', 'addform') title = u"Liste des projets" schema = get_list_schema() default_sort = "created_at" default_direction = "desc" sort_columns = { 'name': Project.name, "code": Project.code, "created_at": Project.created_at, } def query(self): company = self.request.context # We can't have projects without having customers if not company.customers: redirect_to_customerslist(self.request, company) main_query = DBSESSION().query(distinct(Project.id), Project) main_query = main_query.outerjoin(Project.customers) return main_query.filter(Project.company_id == company.id) def filter_archived(self, query, appstruct): archived = appstruct.get('archived', False) if archived in (False, colander.null): query = query.filter(Project.archived == False) return query def filter_name_or_customer(self, query, appstruct): search = appstruct['search'] if search: query = query.filter( or_( Project.name.like("%" + search + "%"), Project.customers.any( Customer.name.like("%" + search + "%")))) return query @property def addform(self): res = None if self.request.has_permission('add_project'): form = get_project_form(self.request) res = form.render() return res def stream_actions(self, project): """ Stream actions available for the given project :param obj project: A Project instance :rtype: generator """ yield (self.request.route_path("project", id=project.id), u"Voir/Modifier", u"Voir/Modifier", u"pencil", {}) if self.request.has_permission('add_estimation', project): yield (self.request.route_path("project_estimations", id=project.id), u"Nouveau devis", u"Créer un devis", u"file", {}) if self.request.has_permission('add_invoice', project): yield (self.request.route_path("project_invoices", id=project.id), u"Nouvelle facture", u"Créer une facture", u"file", {}) if self.request.has_permission('edit_project', project): if project.archived: yield (self.request.route_path("project", id=project.id, _query=dict(action="archive")), u"Désarchiver le projet", u"Désarchiver le projet", u"book", {}) else: yield (self.request.route_path("project", id=project.id, _query=dict(action="archive")), u"Archiver le projet", u"Archiver le projet", u"book", {}) if self.request.has_permission('delete_project', project): yield (self.request.route_path("project", id=project.id, _query=dict(action="delete")), u"Supprimer", u"Supprimer ce projet", u"trash", { "onclick": (u"return confirm('Êtes-vous sûr de " "vouloir supprimer ce projet ?')") })
class ProjectListView(BaseListView, TreeMixin): """ The project list view is compound of : * the list of projects with action buttons (view, delete ...) * an action menu with: * links * an add projectform popup * a searchform """ add_template_vars = ('title', 'stream_actions', 'add_url') title = u"Liste des projets" schema = get_list_schema() default_sort = "created_at" default_direction = "desc" sort_columns = { 'name': Project.name, "code": Project.code, "created_at": Project.created_at, } route_name = COMPANY_PROJECTS_ROUTE item_route_name = PROJECT_ITEM_ROUTE @property def tree_url(self): """ Compile the url to be used in the breadcrumb for this view The context can be either : A Project A Business A Task """ if isinstance(self.context, Company): cid = self.context.id elif isinstance(self.context, Project): cid = self.context.company_id elif hasattr(self.context, 'project'): cid = self.context.project.company_id else: raise Exception( u"Can't retrieve company id for breadcrumb generation %s" % (self.context, )) return self.request.route_path(self.route_name, id=cid) def query(self): company = self.request.context # We can't have projects without having customers if not company.customers: redirect_to_customerslist(self.request, company) main_query = DBSESSION().query(distinct(Project.id), Project) main_query = main_query.outerjoin(Project.customers) return main_query.filter(Project.company_id == company.id) def filter_archived(self, query, appstruct): archived = appstruct.get('archived', False) if archived in (False, colander.null): query = query.filter(Project.archived == False) return query def filter_name_or_customer(self, query, appstruct): search = appstruct['search'] if search: query = query.filter( or_( Project.name.like("%" + search + "%"), Project.customers.any( Customer.label.like("%" + search + "%")))) return query def filter_project_type(self, query, appstruct): val = appstruct.get('project_type_id') if val: query = query.filter(Project.project_type_id == val) return query def stream_actions(self, project): """ Stream actions available for the given project :param obj project: A Project instance :rtype: generator """ yield Link( self._get_item_url(project), u"Voir/Modifier", icon=u"pencil", ) if self.request.has_permission('add_estimation', project): yield Link( self.request.route_path( PROJECT_ITEM_ESTIMATION_ROUTE, id=project.id, _query={'action': 'add'}, ), u"Nouveau devis", icon=u"file", ) if self.request.has_permission('add_invoice', project): yield Link( self.request.route_path( PROJECT_ITEM_INVOICE_ROUTE, id=project.id, _query={'action': 'add'}, ), u"Nouvelle facture", icon=u"file", ) if self.request.has_permission('edit_project', project): if project.archived: yield Link( self._get_item_url(project, action='archive'), u"Désarchiver le projet", icon=u"book", ) else: yield Link( self._get_item_url(project, action='archive'), u"Archiver le projet", icon=u"book", ) if self.request.has_permission('delete_project', project): yield Link( self._get_item_url(project, action='delete'), u"Supprimer", icon=u"trash", confirm=u'Êtes-vous sûr de vouloir supprimer ce projet ?') @property def add_url(self): return self.request.route_path(COMPANY_PROJECTS_ROUTE, id=self.context.id, _query={'action': 'add'})
class ProjectsList(BaseListView): """ The project list view is compound of : * the list of projects with action buttons (view, delete ...) * an action menu with: * links * an add projectform popup * a searchform """ add_template_vars = ( 'title', 'item_actions', ) title = u"Liste des projets" schema = get_list_schema() default_sort = "name" sort_columns = { 'name': Project.name, "code": Project.code, } def query(self): company = self.request.context # We can't have projects without having customers if not company.customers: redirect_to_customerslist(self.request, company) main_query = DBSESSION().query(distinct(Project.id), Project) main_query = main_query.outerjoin(Project.customers) return main_query.filter(Project.company_id == company.id) def filter_archived(self, query, appstruct): archived = appstruct['archived'] return query.filter(Project.archived == archived) def filter_name_or_customer(self, query, appstruct): search = appstruct['search'] if search: query = query.filter( or_( Project.name.like("%" + search + "%"), Project.customers.any( Customer.name.like("%" + search + "%")))) return query def populate_actionmenu(self, appstruct): populate_actionmenu(self.request) if has_permission('add', self.request.context, self.request): form = get_project_form(self.request) popup = PopUp('add', u"Ajouter un projet", form.render()) self.request.popups = {popup.name: popup} self.request.actionmenu.add(popup.open_btn()) self.request.actionmenu.add(self._get_archived_btn(appstruct)) def _get_archived_btn(self, appstruct): """ return the show archived button """ archived = appstruct['archived'] if not archived: url = self.request.current_route_path(_query=dict(archived="true")) link = HTML.a(u"Afficher les projets archivés", href=url) else: url = self.request.current_route_path(_query=dict( archived="false")) link = HTML.a(u"Afficher les projets actifs", href=url) return StaticWidget(link) @property def item_actions(self): """ return action buttons builder """ return self._get_actions() def _get_actions(self): """ Return action buttons with permission handling """ btns = [] btns.append( ItemActionLink(u"Voir", "view", css='btn btn-default btn-sm', path="project", icon="search")) btns.append( ItemActionLink( u"Devis", "edit", css="btn btn-default btn-sm", title=u"Nouveau devis", path="project_estimations", icon="file", )) btns.append( ItemActionLink( u"Facture", "edit", css="btn btn-default btn-sm", title=u"Nouvelle facture", path="project_invoices", icon="file", )) if self.request.params.get('archived', '0') in ('0', 'false'): btns.append( ItemActionLink( u"Archiver", "edit", css="btn btn-default btn-sm", confirm=u'Êtes-vous sûr de vouloir archiver ce projet ?', path="project", title=u"Archiver le projet", _query=dict(action="archive"), icon="book", )) else: btns.append( ItemActionLink( u"Désarchiver", "edit", css="btn btn-default btn-sm", path="project", title=u"Désarchiver le projet", _query=dict(action="archive"), icon="book", )) del_link = ItemActionLink( u"Supprimer", "edit", css="btn btn-danger", confirm=u'Êtes-vous sûr de vouloir supprimer ce projet ?', path="project", title=u"Supprimer le projet", _query=dict(action="delete"), icon="trash") def is_deletable_perm(context, req): """ Return True if the current item (context) is deletable """ return context.is_deletable() del_link.set_special_perm_func(is_deletable_perm) btns.append(del_link) return btns