diff --git a/src/scheduler/scheduleRow.component.ts b/src/scheduler/scheduleRow.component.ts
new file mode 100644
index 0000000..beb3607
--- /dev/null
+++ b/src/scheduler/scheduleRow.component.ts
@@ -0,0 +1,138 @@
+// vim: set tw=80 ts=2 sw=2 sts=2 :
+import { CurrencyPipe } from '@angular/common';
+import { Component, Inject, Input, Output, EventEmitter, OnInit } from '@angular/core';
+
+import { Logger } from '@nsalaun/ng-logger';
+import { ToastrService } from 'ngx-toastr';
+
+import { ScheduleService } from './schedule.service';
+import { Schedule } from './schedule';
+
+var scheduleFormTmpl = require('./schedule.form.tmpl.html'),
+ scheduleDeleteTmpl = require('./schedule.delete.tmpl.html');
+
+@Component({
+ selector: 'tr[schedule-row]',
+ host: {
+ "[id]": "schedule.id",
+ },
+ template: `
+
{{ schedule.start_date | date: "yyyy-MM-dd" }} |
+
+
+{{ schedule.stop_date | date: "yyyy-MM-dd" }} |
+
+{{ schedule.day }} |
+
+{{ schedule.frequency }} |
+
+{{ schedule.label }} |
+
+{{ schedule.value | currency:"EUR":true }} |
+
+{{ schedule.category }} |
+
+
+
+
+
+
+
+
+
+ |
+ `
+})
+export class ScheduleRowComponent {
+ @Input('schedule-row') schedule: Schedule;
+ @Output() needsReload: EventEmitter = new EventEmitter();
+
+ constructor(
+ private scheduleService: ScheduleService,
+ private logger: Logger,
+ private toastrService: ToastrService,
+ @Inject('$modal') private $modal
+ ) {}
+
+ save(schedule: Schedule) {
+ return this.scheduleService.create(schedule).subscribe((schedule: Schedule) => {
+ this.toastrService.success('Schedule #' + schedule.id + ' saved.');
+
+ this.needsReload.emit();
+ }, result => {
+ this.toastrService.error(
+ 'Error while saving schedule: ' + result.message
+ );
+ });
+ }
+
+ confirmDelete() {
+ var title = "Delete schedule #" + this.schedule.id;
+
+ this.$modal({
+ templateUrl: scheduleDeleteTmpl,
+ controller: function($scope, title, schedule, $delete) {
+ $scope.title = title;
+ $scope.operation = schedule;
+ $scope.$delete = () => {
+ $scope.$hide();
+ $delete($scope.operation);
+ };
+ },
+ locals: {
+ title: title,
+ schedule: this.schedule,
+ $delete: (schedule) => {
+ this.delete(schedule);
+ }
+ }
+ });
+ }
+
+ delete(schedule: Schedule) {
+ var id = schedule.id;
+
+ return this.scheduleService.delete(schedule).subscribe(() => {
+ this.toastrService.success('Schedule #' + id + ' deleted.');
+
+ this.needsReload.emit();
+ }, result => {
+ this.toastrService.error(
+ 'An error occurred while trying to delete schedule #' + id + ':
'
+ + result.message
+ );
+ });
+ }
+
+ modify() {
+ // FIXME Alexis Lahouze 2017-06-15 i18n
+ var title = "Modify schedule #" + this.schedule.id;
+
+ this.$modal({
+ templateUrl: scheduleFormTmpl,
+ controller: function($scope, title, schedule, $save) {
+ $scope.title = title;
+ $scope.operation = schedule;
+ $scope.$save = () => {
+ $scope.$hide();
+ $save($scope.operation);
+ };
+ },
+ locals: {
+ title: title,
+ schedule: this.schedule,
+ $save: (operation) => {
+ this.save(operation);
+ }
+ }
+ });
+ }
+}