Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
. "$global:rootDir\Helpers\EndpointsClass.ps1"
. "$global:rootDir\Helpers\WriteInformationClass.ps1"
. "$global:rootDir\Helpers\BaseExportService.ps1"

# Your workspace ID: this is where we point to the workspace where we want to export from
[int]$workspaceId = 1022188

# Export settings parameters
# Your view ID: view will provide us with available data to export, requires folder to be visible there.
# Your folder ID: our targetted folder. If you want to export from the workspace root, the ID is different from the workspace ID.
# ExportSourceType: ExportFolder or ExportFolderWithSubfolders
[int]$viewId = 1003684
[int]$folderID = 1003697
[bool]$withSubfolders = $true

# ArtifactIds: Example: 1003668 - Extracted Text, 1003677 - Folder Name, 1003676 - Artifact ID, 1003667 - Control Number
$fulltextPrecedenceFieldsArtifactIds = '[1003668,1003677]'

# Aliases can use only artifact IDs that are in the fieldArtifactIDs list
# Key is the artifact ID of the field, value is the alias
$fieldArtifactIds = '[1003676,1003667]'
$aliases = '{
"1003676": "Artifact ID - Field1",
"1003667": "Control Number - Field2"
}'

# Job related data
$jobId = New-Guid
[string]$applicationName = "Export-Service-Sample-Powershell"
[string]$applicationId = "Sample-Job-" + $MyInvocation.MyCommand.Name.Replace(".ps1", "")
[int]$exportSourceType = if ($withSubfolders) { 3 } else { 2 }

# Export job settings
[string]$exportJobSettings =
'{
"settings": {
"ExportSourceSettings": {
"ArtifactTypeID":10,
"ExportSourceType":' + $exportSourceType + ',
"ExportSourceArtifactID":' + $folderID + ',
"ViewID":' + $viewId + ',
"StartAtDocumentNumber":1
},
"ExportArtifactSettings": {
"FileNamePattern":"{identifier}",
"ExportNative":true,
"ExportPdf":true,
"ExportImages":true,
"ExportFullText":true,
"ExportMultiChoicesAsNested":false,
"ImageExportSettings": {
"ImagePrecedenceArtifactIDs":[-1],
"TypeOfImage":2,
},
"FullTextExportSettings": {
"ExportFullTextAsFile":true,
"TextFileEncoding":"utf-8",
"PrecedenceFieldsArtifactIDs":' + $fulltextPrecedenceFieldsArtifactIds + '
},
"NativeFilesExportSettings": {
"NativePrecedenceArtifactIDs":[-1]
},
"FieldArtifactIDs":' + $fieldArtifactIds + ',
"FieldAliases":' + $aliases + ',
"ApplyFileNamePatternToImages":false
},
"ExportOutputSettings": {
"LoadFileSettings": {
"LoadFileFormat":"CSV",
"ImageLoadFileFormat":"IPRO",
"PdfLoadFileFormat":"IPRO",
"Encoding":"utf-8",
"DelimitersSettings": {
"NestedValueDelimiter":"B",
"RecordDelimiter":"E",
"QuoteDelimiter":"D",
"NewlineDelimiter":"C",
"MultiRecordDelimiter":"A"
},
"ExportMsAccess": false
},
"VolumeSettings": {
"VolumePrefix":"VOL_FOLDER",
"VolumeStartNumber":"1",
"VolumeMaxSizeInMegabytes":100,
"VolumeDigitPadding":5
},
"SubdirectorySettings": {
"SubdirectoryStartNumber":1,
"MaxNumberOfFilesInDirectory":100,
"ImageSubdirectoryPrefix":"IMAGE_",
"NativeSubdirectoryPrefix":"NATIVE_",
"FullTextSubdirectoryPrefix":"FULLTEXT_",
"PdfSubdirectoryPrefix":"PDFS_",
"SubdirectoryDigitPadding":5
},
"CreateArchive":false,
"FolderStructure":0
}
},
"applicationName":"' + $applicationName + '",
"correlationID":"' + $applicationId + '"
}'

# Create, run export job and display export job result
$global:Endpoints = [Endpoints]::new($workspaceId)
$global:WriteInformation = [WriteInformation]::new()
$global:BaseExportService = [BaseExportService]::new()

Context "Exports native, fulltext, images and PDF files from folder" {
Describe "Create export job" {
$global:BaseExportService.createExportJob($jobId, $exportJobSettings)
}

Describe "Start export job" {
$global:BaseExportService.startExportJob($jobId)
}

Describe "Wait for export job to be completed" {
$global:BaseExportService.waitForExportJobToBeCompleted($jobId)
}

Describe "Export job summary" {
$global:BaseExportService.exportJobResult($jobId)
}
}

93 changes: 30 additions & 63 deletions Relativity.Export.Samples.RelConsole/Helpers/Logger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,6 @@ public Logger(string[] args)
_args = args;
}

public void PrintJobJson(ExportJobSettings settings, bool print = false)
{
if (!_args.Contains("-json"))
{
if (!print)
return;
}

// create JSON for preview
var serializerOptions = new JsonSerializerOptions()
{
WriteIndented = true,
};

var json = JsonSerializer.Serialize(settings, serializerOptions);

var panel = new Panel(new JsonText(json))
.RoundedBorder()
.BorderColor(Color.Orange1)
.Header("[aquamarine1]Job JSON[/]", Justify.Center);

AnsiConsole.Write(panel);
}


public void LogWarning(string message, bool hideTimeStamp = false)
{
Log(new SampleLog(LogLevel.Warning, $"[orange1]{message}[/]", hideTimeStamp));
Expand Down Expand Up @@ -95,61 +70,53 @@ public void Log(SampleLog log)
AnsiConsole.Write(table);
}

public void PrintSampleData(Dictionary<string, string> data)
public void PrintJobJson(ExportJobSettings settings, bool print = false)
{
if (!_args.Contains("-json"))
{
if (!print)
return;
}

// create JSON for preview
var serializerOptions = new JsonSerializerOptions()
{
WriteIndented = true,
};

var json = JsonSerializer.Serialize(settings, serializerOptions);

var panel = new Panel(new JsonText(json))
.RoundedBorder()
.BorderColor(Color.Orange1)
.Header("[aquamarine1]Job JSON[/]", Justify.Center);

AnsiConsole.Write(panel);
}

public void PrintDictionaryData<K, V>(Dictionary<K, V> data, string header) where K : notnull
{
var dataGrid = new Grid()
.AddColumn(new GridColumn().NoWrap())
.AddColumn(new GridColumn().NoWrap());

foreach (var record in data)
{
dataGrid.AddRow(new Markup[]
{
dataGrid.AddRow(
[
new Markup($"[orange1]{record.Key}[/]"),
new Markup(record.Value)
});
new Markup(record.Value?.ToString() ?? "#null")
]);
}

var sampleData = new Panel(dataGrid)
.RoundedBorder()
.BorderColor(Color.Orange1)
.Header("[aquamarine1]Sample Data[/]", Justify.Center);
.Header($"[aquamarine1]{header}[/]", Justify.Center);

AnsiConsole.Write(sampleData);
}

public void PrintExportJobResult(string finalMessage, ExportJob exportJob)
{
int processed = exportJob.ProcessedRecords - exportJob.RecordsWithErrors - exportJob.RecordsWithWarnings ?? 0;

LogInformation(finalMessage, hideTimeStamp: true);
AnsiConsole.WriteLine();
AnsiConsole.Write(new BreakdownChart()
.Width(60)
.AddItem("Processed", processed, Color.Green)
.AddItem("Records with errors", exportJob.RecordsWithErrors ?? 0, Color.Red)
.AddItem("Records with warnings", exportJob.RecordsWithWarnings ?? 0, Color.Yellow));
AnsiConsole.WriteLine();
}

public void PrintBulkExportJobResult(string finalMessage, List<ExportStatus?> exportStatuses)
{
int successJobs = exportStatuses.Count(s => s == ExportStatus.Completed);
int failedJobs = exportStatuses.Count(s => s == ExportStatus.Failed);
int cancelledJobs = exportStatuses.Count(s => s == ExportStatus.Cancelled);
int completedWithErrorsJobs = exportStatuses.Count(s => s == ExportStatus.CompletedWithErrors);

LogInformation(string.IsNullOrEmpty(finalMessage) ? "Bulk export completed" : finalMessage, hideTimeStamp: true);
AnsiConsole.WriteLine();
AnsiConsole.Write(new BreakdownChart()
.Width(60)
.AddItem("Success", successJobs, Color.Green)
.AddItem("Completed With Errors", completedWithErrorsJobs, Color.OrangeRed1)
.AddItem("Failed", failedJobs, Color.Red)
.AddItem("Cancelled", cancelledJobs, Color.Yellow));
AnsiConsole.WriteLine();
}

private string LevelToMessage(LogLevel logLevel) => logLevel switch
{
LogLevel.Information => "[bold][aquamarine1]<INFO>[/][/]",
Expand Down
49 changes: 49 additions & 0 deletions Relativity.Export.Samples.RelConsole/Helpers/LoggerExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using Relativity.Export.V1.Model;
using Spectre.Console;

namespace Relativity.Export.Samples.RelConsole.Helpers;

public static class LoggerExtensions
{
public static void PrintAliases(this Logger logger, Dictionary<int, string> data)
{
logger.PrintDictionaryData(data, "Field Aliases");
}

public static void PrintSampleData(this Logger logger, Dictionary<string, string> data)
{
logger.PrintDictionaryData(data, "Sample Data");
}

public static void PrintExportJobResult(this Logger logger, string finalMessage, ExportJob exportJob)
{
int processed = exportJob.ProcessedRecords - exportJob.RecordsWithErrors - exportJob.RecordsWithWarnings ?? 0;

logger.LogInformation(finalMessage, hideTimeStamp: true);
AnsiConsole.WriteLine();
AnsiConsole.Write(new BreakdownChart()
.Width(60)
.AddItem("Processed", processed, Color.Green)
.AddItem("Records with errors", exportJob.RecordsWithErrors ?? 0, Color.Red)
.AddItem("Records with warnings", exportJob.RecordsWithWarnings ?? 0, Color.Yellow));
AnsiConsole.WriteLine();
}

public static void PrintBulkExportJobResult(this Logger logger, string finalMessage, List<ExportStatus?> exportStatuses)
{
int successJobs = exportStatuses.Count(s => s == ExportStatus.Completed);
int failedJobs = exportStatuses.Count(s => s == ExportStatus.Failed);
int cancelledJobs = exportStatuses.Count(s => s == ExportStatus.Cancelled);
int completedWithErrorsJobs = exportStatuses.Count(s => s == ExportStatus.CompletedWithErrors);

logger.LogInformation(string.IsNullOrEmpty(finalMessage) ? "Bulk export completed" : finalMessage, hideTimeStamp: true);
AnsiConsole.WriteLine();
AnsiConsole.Write(new BreakdownChart()
.Width(60)
.AddItem("Success", successJobs, Color.Green)
.AddItem("Completed With Errors", completedWithErrorsJobs, Color.OrangeRed1)
.AddItem("Failed", failedJobs, Color.Red)
.AddItem("Cancelled", cancelledJobs, Color.Yellow));
AnsiConsole.WriteLine();
}
}
29 changes: 13 additions & 16 deletions Relativity.Export.Samples.RelConsole/Helpers/OutputHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public static class OutputHelper
{
private static string[] _args = default!;
private static Dictionary<int, MethodInfo> _sampleRunner = new();
private static List<SampleMetadata> _samples = new();
private static StatusContext _statusContext = default!;
private static object _statusLock = new();

Expand All @@ -19,17 +20,15 @@ public static async Task StartAsync(string[] args, string relativityUrl, string
try
{
_args = args;
List<SampleMetadata> samples;
int selectedSampleId = -1;
bool isSampleValid = args.Length > 0 && Int32.TryParse(args[0], out selectedSampleId);

samples = GetSamples(isSampleValid ? selectedSampleId : -1);
GetSamples(isSampleValid ? selectedSampleId : -1);

if (!args.Contains("-noui"))
{

var samplesPanel = GetSamplesPanel(samples);
var metadataPanel = GetSampleMetadataPanel(samples.FirstOrDefault(s => s.ID == selectedSampleId));
var samplesPanel = GetSamplesPanel();
var metadataPanel = GetSampleMetadataPanel(_samples.FirstOrDefault(s => s.ID == selectedSampleId));

Columns[] dataColumns =
[
Expand Down Expand Up @@ -126,9 +125,9 @@ public static void ClearStatus()
}
}

private static List<SampleMetadata> GetSamples(int selectedSampleId)
private static void GetSamples(int selectedSampleId)
{
List<SampleMetadata> samples = new();
_samples = new();
var sampleMethods = Assembly.GetExecutingAssembly()
.GetTypes()
.SelectMany(type => type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
Expand All @@ -155,11 +154,9 @@ private static List<SampleMetadata> GetSamples(int selectedSampleId)
!string.IsNullOrEmpty(data.Description) ? data.Description : "No description",
sampleID == selectedSampleId); // is sample currently selected

samples.Add(sampleMetadata);
_sampleRunner.Add(i + 1, sampleMethods[i]);
_samples.Add(sampleMetadata);
_sampleRunner.Add(sampleID, sampleMethods[i]);
}

return samples;
}

private static Panel GetSampleMetadataPanel(SampleMetadata? sample)
Expand Down Expand Up @@ -201,20 +198,20 @@ private static Panel GetSampleMetadataPanel(SampleMetadata? sample)
return metadataPanel;
}

private static Panel GetSamplesPanel(List<SampleMetadata> samplesMetadata)
private static Panel GetSamplesPanel()
{
var samplesTable = new Table()
.Expand();

samplesTable.AddColumns("ID", "Name");

foreach (var sample in samplesMetadata.OrderBy(s => s.ID))
foreach (var sample in _samples)
{
IRenderable[] rows = new IRenderable[]
{
IRenderable[] rows =
[
new Markup(sample.ID.ToString(), new Style(sample.IsSelected ? Color.Aquamarine1 : Color.Orange1)),
new Markup(sample.Name, new Style(sample.IsSelected ? Color.Aquamarine1 : Color.Orange1))
};
];

samplesTable.AddRow(rows);
}
Expand Down
Loading