Skip to content

Commit

Permalink
migrations: create the migration module
Browse files Browse the repository at this point in the history
Co-Authored-by: Johnny Mariéthoz <[email protected]>
  • Loading branch information
jma committed Oct 24, 2024
1 parent 1ed7763 commit 867383f
Show file tree
Hide file tree
Showing 25 changed files with 1,675 additions and 5 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
"@ngx-loading-bar/http-client": "^6.0.0",
"@ngx-loading-bar/router": "^6.0.0",
"@ngx-translate/core": "^15.0.0",
"@rero/ng-core": "^17.2.3",
"@rero/ng-core": "^17.3.0",
"@swimlane/ngx-charts": "^20.5.0",
"@vpoppy/ngx-translate-extract": "^9.0.0",
"bootstrap": "^4.6.2",
Expand Down
4 changes: 4 additions & 0 deletions projects/admin/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ import { PERMISSIONS } from '@rero/shared';
import { PermissionGuard } from './guard/permission.guard';

const routes: Routes = [
{
path: 'migrations',
loadChildren: () => import('./migration/migration.module').then(m => m.MigrationModule)
},
{
path: '',
component: FrontpageComponent
Expand Down
9 changes: 9 additions & 0 deletions projects/admin/src/app/menu/menu-definition/menu-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,15 @@ export const MENU_APP: IMenuParent[] = [
permissions: [PERMISSIONS.PERM_MANAGEMENT]
}
},
{
name: 'Migrations',
router_link: ['/', 'migrations', 'records', 'migrations'],
attributes: { id: 'permissions-menu' },
extras: { iconClass: 'fa fa-cloud-upload' },
access: {
permissions: [PERMISSIONS.MIG_ACCESS]
}
},
]
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!--
RERO ILS UI
Copyright (C) 2024 RERO
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, version 3 of the License.
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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
@if (record) {
<h5>
<a
[routerLink]="[detailUrl.link]"
[queryParams]="{ migration: record.metadata.migration_id }"
>{{ record.id }}
{{status}}
&nbsp;<p-badge
[severity]="status === 'complete'? 'success': status.endsWith('error') ? 'danger': 'secondary'"
[value]="record.metadata.conversion.status | translate"
/></a>
</h5>
@if (record?.metadata?.conversion?.json?.title) {
{{ record.metadata.conversion.json.title | mainTitle }}
}
<div>
<i
><small
><span translate>Modification date</span>&nbsp;{{
record?.metadata?.updated_at | dateTranslate : "medium"
}}</small
></i
>
</div>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* RERO ILS UI
* Copyright (C) 2024 RERO
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import { Component, Input } from '@angular/core';

@Component({
selector: 'admin-migration-data',
templateUrl: './migration-data.component.html',
})
export class MigrationDataBriefComponent {
// current record
@Input() record: any;

// detail URL
@Input() detailUrl: { link: string; external: boolean };

/**
* Get the conversion status.
*/
get status() {
return this.record?.metadata?.conversion?.status;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<!--
RERO ILS UI
Copyright (C) 2020-2024 RERO
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, version 3 of the License.
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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
@if (record()) {
<h5>
{{ record().id }}
&nbsp;<p-badge
[severity]="status() === 'complete'? 'success': status().endsWith('error') ? 'danger': 'secondary'"
[value]="record().conversion.status | translate"
/>
</h5>
<i
><small
><span translate>Modification date</span>&nbsp;{{
record()?.updated_at | dateTranslate : "medium"
}}</small
></i
>
<hr />
@if (messages()) {
<p-messages [escape]="false" [value]="messages()" [enableService]="false" [closable]="false" />
}
<div class="text-sm grid data">
<div class="markdown col" [innerHTML]="record().raw | markdown"></div>
<div
class="json col"
[innerHTML]="record()?.conversion?.json | json | highlightJson"
></div>
</div>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* RERO ILS UI
* Copyright (C) 2024 RERO
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

::ng-deep {
.markdown td,
.markdown th {
padding: 0 10px;
vertical-align: top;
}
tbody tr:nth-child(odd) {
background-color: #f8fafc;
}
}

.data {
.col {
max-height: 600px;
overflow: auto;
}
.json {
border-left: 1px solid gray;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* RERO ILS UI
* Copyright (C) 2024 RERO
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import { HttpClient } from '@angular/common/http';
import { Component, computed, inject } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { ActivatedRoute } from '@angular/router';
import { ApiService, Record } from '@rero/ng-core';
import { of, switchMap } from 'rxjs';

@Component({
selector: 'admin-migration-data',
templateUrl: './migration-data.component.html',
styleUrl: './migration-data.component.scss',
})
export class MigrationDataDetailComponent {

// services
protected route: ActivatedRoute = inject(ActivatedRoute);
protected http: HttpClient = inject(HttpClient);
protected apiService: ApiService = inject(ApiService);

// current record from the route params
record = toSignal<any>(
this.route.paramMap.pipe(
switchMap(() => {
// route params
const docType = this.route.snapshot.params.type;
const id = this.route.snapshot.params.pid;
const migrationId = this.route.snapshot.queryParams.migration;
// nothing to do
if (docType == null || id == null || migrationId == null) {
return of(null);
}
// get the record from the backend
return this.http.get<Record>(
`${this.apiService.getEndpointByType(docType, true)}/${id}?migration=${migrationId}`
);
})
)
);

// log messages from the backend
messages = computed((): {severity: string, detail: string}[] => this.getMessages());

// conversion status
status = computed((): string => this.record()?.conversion?.status);

/** Get the list of the log message from the record
*
* @returns the list messages on the primeng format.
*/
getMessages(): {severity: string, detail: string}[] {
const messages = [];
if (this.record()?.conversion.logs) {
['info', 'warning', 'error'].map((field) => {
const log = this.record().conversion.logs[field];
if (log) {
messages.push({
severity: field == 'warning' ? 'warn' : field,
detail: log.join('<br/>'),
});
}
});
}
return messages;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* RERO ILS UI
* Copyright (C) 2024 RERO
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import { inject, Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

/**
* Highlight a JSON structure.
*
* Copied from the SONAR project.
*/
@Pipe({
name: 'highlightJson',
})
export class HighlightJsonPipe implements PipeTransform {

// services
protected sanitizer: DomSanitizer = inject(DomSanitizer);

/**
* Highlight a JSON structure.
*
* @param value Json structure.
* @return Highlighted string.
*/
transform(value: string): any {
if (value == null) {
return;
}
let json = value
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/(?:\r\n|\r|\n)/g, '<br>')
.replace(/( )/g, '&thinsp;');

json = json.replace(
/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g,
(match: any) => {
let cls = 'text-gray-600';
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'text-cyan-600';
} else {
cls = 'text-orange-600';
}
} else if (/true|false/.test(match)) {
cls = 'text-blue-600';
} else if (/null/.test(match)) {
cls = 'text-blue-600';
}
return `<span class="${cls}">${match}</span>`;
}
);
const html = this.sanitizer.bypassSecurityTrustHtml(json);
return html;
}
}
Loading

0 comments on commit 867383f

Please sign in to comment.