opf/openproject

View on GitHub
frontend/src/app/shared/components/op-view-select/op-static-queries.service.ts

Summary

Maintainability
C
1 day
Test Coverage
// -- copyright
// OpenProject is an open source project management software.
// Copyright (C) 2012-2024 the OpenProject GmbH
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
//
// See COPYRIGHT and LICENSE files for more details.
//++

import { QueryResource } from 'core-app/features/hal/resources/query-resource';
import { I18nService } from 'core-app/core/i18n/i18n.service';
import { Injectable } from '@angular/core';
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
import { CurrentProjectService } from 'core-app/core/current-project/current-project.service';
import { StateService } from '@uirouter/core';
import { CurrentUserService } from 'core-app/core/current-user/current-user.service';
import { IOpSidemenuItem } from 'core-app/shared/components/sidemenu/sidemenu.component';
import { ViewType } from 'core-app/shared/components/op-view-select/op-view-select.component';
import { BannersService } from 'core-app/core/enterprise/banners.service';

interface IStaticQuery extends IOpSidemenuItem {
  view:ViewType;
}

@Injectable()
export class StaticQueriesService {
  private staticQueries:IStaticQuery[] = [];

  constructor(
    private readonly I18n:I18nService,
    private readonly $state:StateService,
    private readonly CurrentProject:CurrentProjectService,
    private readonly PathHelper:PathHelperService,
    private readonly CurrentUser:CurrentUserService,
    private readonly bannersService:BannersService,
  ) {
    this.staticQueries = this.buildQueries();
  }

  public text = {
    assignee: this.I18n.t('js.work_packages.properties.assignee'),
    author: this.I18n.t('js.work_packages.properties.author'),
    created_at: this.I18n.t('js.work_packages.properties.createdAt'),
    updated_at: this.I18n.t('js.work_packages.properties.updatedAt'),
    status: this.I18n.t('js.work_packages.properties.status'),
    work_packages: this.I18n.t('js.label_work_package_plural'),
    gantt: this.I18n.t('js.gantt_chart.label'),
    latest_activity: this.I18n.t('js.work_packages.default_queries.latest_activity'),
    created_by_me: this.I18n.t('js.work_packages.default_queries.created_by_me'),
    assigned_to_me: this.I18n.t('js.work_packages.default_queries.assigned_to_me'),
    recently_created: this.I18n.t('js.work_packages.default_queries.recently_created'),
    all_open: this.I18n.t('js.work_packages.default_queries.all_open'),
    shared_with_users: this.I18n.t('js.work_packages.default_queries.shared_with_users'),
    shared_with_me: this.I18n.t('js.work_packages.default_queries.shared_with_me'),
    summary: this.I18n.t('js.work_packages.default_queries.summary'),
    overdue: this.I18n.t('js.notifications.date_alerts.overdue'),
  };

  public getStaticName(query:QueryResource):string {
    if (this.$state.params.query_props) {
      const queryProps = JSON.parse(this.$state.params.query_props) as { pa:unknown, pp:unknown }&unknown;
      delete queryProps.pp;
      delete queryProps.pa;
      const queryPropsString = JSON.stringify(queryProps);

      const matched = this.staticQueries.find((item) => {
        const uiParams = item.uiParams as { query_id:string, query_props:string };
        return uiParams && uiParams.query_props === queryPropsString;
      });

      if (matched) {
        return matched.title;
      }

      if (this.$state.params.name) {
        const nameKey = this.$state.params.name as string;
        return this.I18n.t(`js.queries.${nameKey}`);
      }
    }

    // Try to detect the all open filter
    if (query.filters.length === 1 // Only one filter
      && query.filters[0].id === 'status' // that is status
      && query.filters[0].operator.id === 'o') { // and is open
      return this.text.all_open;
    }

    // Otherwise, fall back to work packages
    return this.text.work_packages;
  }

  public buildQueries():IStaticQuery[] {
    let items:IStaticQuery[] = [
      {
        title: this.text.all_open,
        uiSref: 'work-packages',
        uiParams: { query_id: undefined, query_props: undefined },
        view: 'WorkPackagesTable',
      },
      {
        title: this.text.latest_activity,
        uiSref: 'work-packages',
        uiParams: {
          query_id: undefined,
          query_props: '{"c":["id","subject","type","status","assignee","updatedAt"],"hi":false,"g":"","t":"updatedAt:desc","f":[{"n":"status","o":"*","v":[]}]}',
        },
        view: 'WorkPackagesTable',
      },
      {
        title: this.text.recently_created,
        uiSref: 'work-packages',
        uiParams: {
          query_id: undefined,
          query_props: '{"c":["id","subject","type","status","assignee","createdAt"],"hi":false,"g":"","t":"createdAt:desc","f":[{"n":"status","o":"o","v":[]}]}',
        },
        view: 'WorkPackagesTable',
      },
      {
        title: this.text.overdue,
        uiSref: 'work-packages',
        uiParams: {
          query_id: undefined,
          query_props: '{"c":["id","type","subject","status","startDate","dueDate","duration"],"hi":false,"g":"","t":"createdAt:desc","f":[{"n":"dueDate","o":"<t-","v":["1"]},{"n":"status","o":"o","v":[]}]}',
        },
        view: 'WorkPackagesTable',
      },
      {
        title: this.text.all_open,
        uiSref: 'bim.partitioned.list',
        uiParams: {
          query_id: undefined,
          query_props: '{"c":["id","subject","bcfThumbnail","type","status","assignee","updatedAt"],"t":"id:desc"}',
        },
        view: 'Bim',
      },
      {
        title: this.text.latest_activity,
        uiSref: 'bim.partitioned.list',
        uiParams: {
          query_id: undefined,
          query_props: '{"c":["id","subject","bcfThumbnail","type","status","assignee","updatedAt"],"t":"updatedAt:desc","f":[{"n":"status","o":"o","v":[]}]}',
        },
        view: 'Bim',
      },
      {
        title: this.text.recently_created,
        uiSref: 'bim.partitioned.list',
        uiParams: {
          query_id: undefined,
          query_props: '{"c":["id","subject","bcfThumbnail","type","status","assignee","createdAt"],"t":"createdAt:desc","f":[{"n":"status","o":"o","v":[]}]}',
        },
        view: 'Bim',
      },
    ];

    const projectIdentifier = this.CurrentProject.identifier;
    if (projectIdentifier) {
      items = [
        ...items,
        ...this.projectDependentQueries(projectIdentifier),
      ];
    }

    if (this.CurrentUser.isLoggedIn) {
      items = [
        ...items,
        ...this.userDependentQueries(),
      ];
    }

    return items;
  }

  public getStaticQueriesForView(view:ViewType):IOpSidemenuItem[] {
    return this.staticQueries
      .filter((query) => query.view === view);
  }

  private projectDependentQueries(projectIdentifier:string):IStaticQuery[] {
    return [
      {
        title: this.text.summary,
        href: `${this.PathHelper.projectWorkPackagesPath(projectIdentifier)}/report`,
        view: 'WorkPackagesTable',
      },
    ];
  }

  private userDependentQueries():IStaticQuery[] {
    return [
      {
        title: this.text.created_by_me,
        uiSref: 'work-packages',
        uiParams: {
          query_id: undefined,
          query_props: '{"c":["id","subject","type","status","assignee","updatedAt"],"hi":false,"g":"","t":"updatedAt:desc,id:asc","f":[{"n":"status","o":"o","v":[]},{"n":"author","o":"=","v":["me"]}]}',
        },
        view: 'WorkPackagesTable',
      },
      {
        title: this.text.assigned_to_me,
        uiSref: 'work-packages',
        uiParams: {
          query_id: undefined,
          query_props: '{"c":["id","subject","type","status","author","updatedAt"],"hi":false,"g":"","t":"updatedAt:desc,id:asc","f":[{"n":"status","o":"o","v":[]},{"n":"assigneeOrGroup","o":"=","v":["me"]}]}',
        },
        view: 'WorkPackagesTable',
      },
      {
        title: this.text.shared_with_users,
        view: 'WorkPackagesTable',
        isEnterprise: true,
        ...this.eeGuardedShareRoute,
      },
      {
        title: this.text.shared_with_me,
        view: 'WorkPackagesTable',
        isEnterprise: true,
        ...this.eeGuardedShareWithMeRoute,
      },
      {
        title: this.text.created_by_me,
        uiSref: 'bim.partitioned.list',
        uiParams: {
          query_id: undefined,
          query_props: '{"c":["id","subject","bcfThumbnail","type","status","assignee","updatedAt"],"t":"id:desc","f":[{"n":"status","o":"o","v":[]},{"n":"author","o":"=","v":["me"]}]}',
        },
        view: 'Bim',
      },
      {
        title: this.text.assigned_to_me,
        uiSref: 'bim.partitioned.list',
        uiParams: {
          query_id: undefined,
          query_props: '{"c":["id","subject","bcfThumbnail","type","status","author","updatedAt"],"t":"id:desc","f":[{"n":"status","o":"o","v":[]},{"n":"assigneeOrGroup","o":"=","v":["me"]}]}',
        },
        view: 'Bim',
      },
    ];
  }

  private get eeGuardedShareWithMeRoute() {
    if (this.bannersService.eeShowBanners) {
      return { uiSref: 'work-packages.share_upsale', uiParams: null, uiOptions: { inherit: false } };
    }

    return {
      uiSref: 'work-packages',
      uiParams: {
        query_id: undefined,
        query_props: '{"c":["id","subject","type","project"],"hi":false,"g":"","t":"updatedAt:desc,id:asc","f":[{"n":"sharedWithMe","o":"=","v":"t"}]}',
      },
    };
  }

  private get eeGuardedShareRoute() {
    if (this.bannersService.eeShowBanners) {
      return { uiSref: 'work-packages.share_upsale', uiParams: null, uiOptions: { inherit: false } };
    }

    return {
      uiSref: 'work-packages',
      uiParams: {
        query_id: undefined,
        query_props: '{"c":["id","subject","type","project","sharedWithUsers"],"hi":false,"g":"","t":"updatedAt:desc,id:asc","f":[{"n":"sharedWithUser","o":"*","v":[]}]}',
      },
    };
  }
}