WIP in app settings

feature/in-app-notifications-settings
Oliver Günther 4 years ago
parent 519cb4e380
commit 0ea21e90c1
No known key found for this signature in database
GPG Key ID: 88872239EB414F99
  1. 8
      app/controllers/my_controller.rb
  2. 44
      app/views/my/mail_notifications.html.erb
  3. 4
      config/initializers/menus.rb
  4. 5
      config/locales/js-en.yml
  5. 4
      config/routes.rb
  6. 2
      frontend/src/app/core/routing/openproject.routes.ts
  7. 38
      frontend/src/app/features/my-account/my-account.lazy-routes.ts
  8. 30
      frontend/src/app/features/my-account/my-account.module.ts
  9. 39
      frontend/src/app/features/my-account/my-account.routes.ts
  10. 9
      frontend/src/app/features/my-account/my-notifications-page/in-app-notifications-tab/in-app-notifications-tab.component.html
  11. 0
      frontend/src/app/features/my-account/my-notifications-page/in-app-notifications-tab/in-app-notifications-tab.component.sass
  12. 36
      frontend/src/app/features/my-account/my-notifications-page/in-app-notifications-tab/in-app-notifications-tab.component.ts
  13. 16
      frontend/src/app/features/my-account/my-notifications-page/my-notifications-page.component.html
  14. 1
      frontend/src/app/features/my-account/my-notifications-page/my-notifications-page.component.sass
  15. 80
      frontend/src/app/features/my-account/my-notifications-page/my-notifications-page.component.ts

@ -45,7 +45,7 @@ class MyController < ApplicationController
menu_item :settings, only: [:settings]
menu_item :password, only: [:password]
menu_item :access_token, only: [:access_token]
menu_item :mail_notifications, only: [:mail_notifications]
menu_item :notifications, only: [:notifications]
def account; end
@ -82,7 +82,11 @@ class MyController < ApplicationController
def access_token; end
# Configure user's mail notifications
def mail_notifications; end
def notifications
render html: '',
layout: 'angular',
locals: { menu_name: :my_menu }
end
def update_mail_notifications
write_email_settings(redirect_to: :mail_notifications)

@ -1,44 +0,0 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2021 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 docs/COPYRIGHT.rdoc for more details.
++#%>
<% html_title(t(:label_my_account), I18n.t('activerecord.attributes.user.mail_notification')) -%>
<% breadcrumb_paths(t(:label_my_account), I18n.t('activerecord.attributes.user.mail_notification')) %>
<%= toolbar title: I18n.t('activerecord.attributes.user.mail_notification') %>
<%= labelled_tabular_form_for @user,
as: :user,
url: { action: 'update_mail_notifications' },
lang: current_language,
html: { id: 'my_account_form', class: 'form -wide-labels' } do %>
<section class="form--section">
<%= render partial: 'users/mail_notifications' %>
</section>
<%= styled_button_tag t(:button_save), class: '-highlight -with-icon icon-checkmark' %>
<% end %>

@ -134,8 +134,8 @@ Redmine::MenuManager.map :my_menu do |menu|
{ controller: '/my', action: 'access_token' },
caption: I18n.t('my_account.access_tokens.access_token'),
icon: 'icon2 icon-key'
menu.push :mail_notifications,
{ controller: '/my', action: 'mail_notifications' },
menu.push :notifications,
{ controller: '/my', action: 'notifications' },
caption: I18n.t('activerecord.attributes.user.mail_notification'),
icon: 'icon2 icon-news'

@ -558,6 +558,11 @@ en:
timeline_button: 'You can activate the <b>Gantt chart</b> to create a timeline for your project.'
timeline: 'Here you can edit your project plan. Create new phases, milestones, and add dependencies. All team members can see and update the latest plan at any time.'
notifications:
in_app: "In-app notifications"
email: "Email notifications"
settings:
enable_app_notifications: "Enable in-app notifications"
password_confirmation:
field_description: 'You need to enter your account password to confirm this change.'

@ -541,11 +541,11 @@ OpenProject::Application.routes.draw do
get '/my/account', action: 'account'
get '/my/settings', action: 'settings'
get '/my/mail_notifications', action: 'mail_notifications'
get '/my/notifications', action: 'notifications'
patch '/my/account', action: 'update_account'
patch '/my/settings', action: 'update_settings'
patch '/my/mail_notifications', action: 'update_mail_notifications'
patch '/my/notifications', action: 'update_mail_notifications'
post '/my/generate_rss_key', action: 'generate_rss_key'
post '/my/generate_api_key', action: 'generate_api_key'

@ -34,6 +34,7 @@ import { FirstRouteService } from "core-app/core/routing/first-route-service";
import { Ng2StateDeclaration, StatesModule } from "@uirouter/angular";
import { appBaseSelector, ApplicationBaseComponent } from "core-app/core/routing/base/application-base.component";
import { BackRoutingService } from "core-app/features/work-packages/components/back-routing/back-routing.service";
import { MY_ACCOUNT_LAZY_ROUTES } from "core-app/features/my-account/my-account.lazy-routes";
export const OPENPROJECT_ROUTES:Ng2StateDeclaration[] = [
{
@ -104,6 +105,7 @@ export const OPENPROJECT_ROUTES:Ng2StateDeclaration[] = [
url: '/copy',
loadChildren: () => import('../../features/projects/openproject-projects.module').then(m => m.OpenprojectProjectsModule)
},
...MY_ACCOUNT_LAZY_ROUTES
];
/**

@ -0,0 +1,38 @@
//-- copyright
// OpenProject is an open source project management software.
// Copyright (C) 2012-2021 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 docs/COPYRIGHT.rdoc for more details.
//++
import { Ng2StateDeclaration } from "@uirouter/angular";
export const MY_ACCOUNT_LAZY_ROUTES:Ng2StateDeclaration[] = [
{
name: 'my_notifications.**',
parent: 'root',
url: '/my/notifications',
loadChildren: () => import('./my-account.module').then(m => m.OpenProjectMyAccountModule)
},
];

@ -0,0 +1,30 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { UIRouterModule } from "@uirouter/angular";
import { MY_ACCOUNT_ROUTES } from "core-app/features/my-account/my-account.routes";
import { MyNotificationsPageComponent } from "core-app/features/my-account/my-notifications-page/my-notifications-page.component";
import { OpenprojectTabsModule } from "core-app/shared/components/tabs/openproject-tabs.module";
import { InAppNotificationsTabComponent } from './my-notifications-page/in-app-notifications-tab/in-app-notifications-tab.component';
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { OpenprojectFieldsModule } from "core-app/shared/components/fields/openproject-fields.module";
import { OPSharedModule } from "core-app/shared/shared.module";
@NgModule({
declarations: [
MyNotificationsPageComponent,
InAppNotificationsTabComponent
],
imports: [
CommonModule,
OpenprojectTabsModule,
OPSharedModule,
FormsModule,
ReactiveFormsModule,
// Routes for /my/*
UIRouterModule.forChild({
states: MY_ACCOUNT_ROUTES
}),
]
})
export class OpenProjectMyAccountModule { }

@ -0,0 +1,39 @@
//-- copyright
// OpenProject is an open source project management software.
// Copyright (C) 2012-2021 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 docs/COPYRIGHT.rdoc for more details.
//++
import { Ng2StateDeclaration } from "@uirouter/angular";
import { MyNotificationsPageComponent } from "core-app/features/my-account/my-notifications-page/my-notifications-page.component";
export const MY_ACCOUNT_ROUTES:Ng2StateDeclaration[] = [
{
name: 'my_notifications',
parent: 'root',
url: '/my/notifications',
component: MyNotificationsPageComponent
},
];

@ -0,0 +1,9 @@
<op-form-field [label]="text.enable">
<input
type="checkbox"
class="op-input"
[formControl]="enabledControl"
slot="input"
autofocus
/>
</op-form-field>

@ -0,0 +1,36 @@
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { TabComponent } from "core-app/features/work-packages/components/wp-table/configuration-modal/tab-portal-outlet";
import { I18nService } from "core-app/core/i18n/i18n.service";
import { FormControl, FormGroup } from "@angular/forms";
@Component({
templateUrl: './in-app-notifications-tab.component.html',
styleUrls: ['./in-app-notifications-tab.component.sass'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class InAppNotificationsTabComponent implements TabComponent, OnInit {
text = {
enable: this.I18n.t('js.notifications.settings.enable_app_notifications'),
};
form = new FormGroup({
enabled: new FormControl(''),
});
get enabledControl() {
return this.form.get('enabled');
}
constructor(
private I18n:I18nService,
) {
}
ngOnInit():void {
}
onSave() {
}
}

@ -0,0 +1,16 @@
<op-scrollable-tabs
*ngIf="tabPortalHost"
[tabs]="tabs"
[currentTabId]="tabPortalHost.currentTab?.id"
(tabSelected)="switchTo($event)"
>
</op-scrollable-tabs>
<div class="tab-content" #tabContentOutlet></div>
<button
class="button -highlight"
[textContent]="text.save"
(click)="saveChanges()"
>
</button>

@ -0,0 +1,80 @@
import {
ApplicationRef,
ChangeDetectionStrategy,
Component,
ComponentFactoryResolver,
ElementRef,
Injector,
OnInit,
ViewChild,
} from '@angular/core';
import {
TabComponent,
TabInterface,
TabPortalOutlet,
} from "core-app/features/work-packages/components/wp-table/configuration-modal/tab-portal-outlet";
import { I18nService } from "core-app/core/i18n/i18n.service";
import { InAppNotificationsTabComponent } from "core-app/features/my-account/my-notifications-page/in-app-notifications-tab/in-app-notifications-tab.component";
@Component({
templateUrl: './my-notifications-page.component.html',
styleUrls: ['./my-notifications-page.component.sass'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MyNotificationsPageComponent implements OnInit {
text = {
save: this.I18n.t('js.button_save'),
};
tabs:TabInterface[] = [
{
id: 'in-app',
name: this.I18n.t('js.notifications.in_app'),
componentClass: InAppNotificationsTabComponent,
},
{
id: 'email',
name: this.I18n.t('js.notifications.email'),
componentClass: InAppNotificationsTabComponent,
},
];
tabPortalHost:TabPortalOutlet;
@ViewChild('tabContentOutlet', { static: true }) tabContentOutlet:ElementRef;
constructor(
private I18n:I18nService,
private componentFactoryResolver:ComponentFactoryResolver,
private appRef:ApplicationRef,
private injector:Injector,
) {
}
ngOnInit():void {
this.tabPortalHost = new TabPortalOutlet(
this.tabs,
this.tabContentOutlet.nativeElement,
this.componentFactoryResolver,
this.appRef,
this.injector,
);
this.switchTo(this.tabs[0]);
}
public switchTo(tab:TabInterface):void {
this.tabPortalHost.switchTo(tab);
}
public saveChanges():void {
this.tabPortalHost.activeComponents.forEach((component:TabComponent) => {
component.onSave();
});
this.submit();
}
private submit():void {
}
}
Loading…
Cancel
Save