retold-remote 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/css/retold-remote.css +3 -0
- package/html/index.html +1 -1
- package/package.json +1 -1
- package/source/Pict-Application-RetoldRemote.js +21 -2
- package/source/cli/RetoldRemote-Server-Setup.js +129 -0
- package/source/providers/Pict-Provider-AISortManager.js +456 -0
- package/source/providers/Pict-Provider-CollectionManager.js +266 -0
- package/source/server/RetoldRemote-AISortService.js +879 -0
- package/source/server/RetoldRemote-CollectionService.js +161 -2
- package/source/server/RetoldRemote-FileOperationService.js +560 -0
- package/source/server/RetoldRemote-MediaService.js +12 -0
- package/source/server/RetoldRemote-MetadataCache.js +411 -0
- package/source/views/PictView-Remote-CollectionsPanel.js +435 -36
- package/source/views/PictView-Remote-Layout.js +2 -0
- package/source/views/PictView-Remote-SettingsPanel.js +156 -0
- package/source/views/PictView-Remote-TopBar.js +86 -0
- package/web-application/css/retold-remote.css +3 -0
- package/web-application/index.html +1 -1
- package/web-application/retold-remote.js +402 -34
- package/web-application/retold-remote.js.map +1 -1
- package/web-application/retold-remote.min.js +32 -15
- package/web-application/retold-remote.min.js.map +1 -1
|
@@ -927,6 +927,272 @@ class CollectionManagerProvider extends libPictProvider
|
|
|
927
927
|
tmpTags.indexOf(tmpQuery) >= 0;
|
|
928
928
|
});
|
|
929
929
|
}
|
|
930
|
+
|
|
931
|
+
// -- Operation Plan Methods -------------------------------------------
|
|
932
|
+
|
|
933
|
+
/**
|
|
934
|
+
* Create an operation-plan collection with pre-populated items.
|
|
935
|
+
*
|
|
936
|
+
* @param {string} pName - Plan name
|
|
937
|
+
* @param {Array} pItems - Items with Operation and DestinationPath set
|
|
938
|
+
* @param {Function} [fCallback] - Optional callback(pError, pCollection)
|
|
939
|
+
*/
|
|
940
|
+
createOperationPlan(pName, pItems, fCallback)
|
|
941
|
+
{
|
|
942
|
+
let tmpSelf = this;
|
|
943
|
+
let tmpCallback = (typeof fCallback === 'function') ? fCallback : () => {};
|
|
944
|
+
let tmpGUID = this.fable.getUUID();
|
|
945
|
+
|
|
946
|
+
let tmpCollectionData =
|
|
947
|
+
{
|
|
948
|
+
Name: pName || 'Sort Plan',
|
|
949
|
+
CollectionType: 'operation-plan',
|
|
950
|
+
Items: pItems || []
|
|
951
|
+
};
|
|
952
|
+
|
|
953
|
+
fetch('/api/collections/' + encodeURIComponent(tmpGUID),
|
|
954
|
+
{
|
|
955
|
+
method: 'PUT',
|
|
956
|
+
headers: { 'Content-Type': 'application/json' },
|
|
957
|
+
body: JSON.stringify(tmpCollectionData)
|
|
958
|
+
})
|
|
959
|
+
.then((pResponse) => pResponse.json())
|
|
960
|
+
.then((pData) =>
|
|
961
|
+
{
|
|
962
|
+
let tmpRemote = tmpSelf._getRemote();
|
|
963
|
+
|
|
964
|
+
// Open the panel and navigate to this collection
|
|
965
|
+
tmpRemote.ActiveCollectionGUID = tmpGUID;
|
|
966
|
+
tmpRemote.ActiveCollection = pData;
|
|
967
|
+
tmpRemote.CollectionsPanelMode = 'detail';
|
|
968
|
+
|
|
969
|
+
if (!tmpRemote.CollectionsPanelOpen)
|
|
970
|
+
{
|
|
971
|
+
tmpSelf.togglePanel();
|
|
972
|
+
}
|
|
973
|
+
else
|
|
974
|
+
{
|
|
975
|
+
let tmpPanel = tmpSelf._getPanelView();
|
|
976
|
+
if (tmpPanel)
|
|
977
|
+
{
|
|
978
|
+
tmpPanel.renderContent();
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
// Refresh the list
|
|
983
|
+
tmpSelf.fetchCollections();
|
|
984
|
+
|
|
985
|
+
let tmpToast = tmpSelf._getToast();
|
|
986
|
+
if (tmpToast)
|
|
987
|
+
{
|
|
988
|
+
tmpToast.show('Sort plan created: ' + (pData.Name || pName));
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
return tmpCallback(null, pData);
|
|
992
|
+
})
|
|
993
|
+
.catch((pError) =>
|
|
994
|
+
{
|
|
995
|
+
tmpSelf.log.error('Failed to create operation plan: ' + pError.message);
|
|
996
|
+
return tmpCallback(pError);
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
/**
|
|
1001
|
+
* Execute all pending operations in a collection.
|
|
1002
|
+
*
|
|
1003
|
+
* @param {string} pGUID - Collection GUID
|
|
1004
|
+
* @param {Function} [fCallback] - Optional callback(pError, pResult)
|
|
1005
|
+
*/
|
|
1006
|
+
executeCollectionOperations(pGUID, fCallback)
|
|
1007
|
+
{
|
|
1008
|
+
let tmpSelf = this;
|
|
1009
|
+
let tmpCallback = (typeof fCallback === 'function') ? fCallback : () => {};
|
|
1010
|
+
|
|
1011
|
+
fetch('/api/collections/' + encodeURIComponent(pGUID) + '/execute',
|
|
1012
|
+
{
|
|
1013
|
+
method: 'POST',
|
|
1014
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1015
|
+
body: JSON.stringify({})
|
|
1016
|
+
})
|
|
1017
|
+
.then((pResponse) => pResponse.json())
|
|
1018
|
+
.then((pData) =>
|
|
1019
|
+
{
|
|
1020
|
+
let tmpRemote = tmpSelf._getRemote();
|
|
1021
|
+
|
|
1022
|
+
if (pData.Collection && tmpRemote.ActiveCollectionGUID === pGUID)
|
|
1023
|
+
{
|
|
1024
|
+
tmpRemote.ActiveCollection = pData.Collection;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
let tmpPanel = tmpSelf._getPanelView();
|
|
1028
|
+
if (tmpPanel)
|
|
1029
|
+
{
|
|
1030
|
+
tmpPanel.renderContent();
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
let tmpToast = tmpSelf._getToast();
|
|
1034
|
+
if (tmpToast)
|
|
1035
|
+
{
|
|
1036
|
+
if (pData.TotalFailed > 0)
|
|
1037
|
+
{
|
|
1038
|
+
tmpToast.show('Moved ' + pData.TotalMoved + ' files (' + pData.TotalFailed + ' failed)');
|
|
1039
|
+
}
|
|
1040
|
+
else
|
|
1041
|
+
{
|
|
1042
|
+
tmpToast.show('Successfully moved ' + pData.TotalMoved + ' files');
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
return tmpCallback(null, pData);
|
|
1047
|
+
})
|
|
1048
|
+
.catch((pError) =>
|
|
1049
|
+
{
|
|
1050
|
+
tmpSelf.log.error('Failed to execute operations: ' + pError.message);
|
|
1051
|
+
let tmpToast = tmpSelf._getToast();
|
|
1052
|
+
if (tmpToast)
|
|
1053
|
+
{
|
|
1054
|
+
tmpToast.show('Failed to execute operations: ' + pError.message);
|
|
1055
|
+
}
|
|
1056
|
+
return tmpCallback(pError);
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
/**
|
|
1061
|
+
* Undo the last batch of operations for a collection.
|
|
1062
|
+
*
|
|
1063
|
+
* @param {string} pGUID - Collection GUID
|
|
1064
|
+
* @param {Function} [fCallback] - Optional callback(pError, pResult)
|
|
1065
|
+
*/
|
|
1066
|
+
undoCollectionOperations(pGUID, fCallback)
|
|
1067
|
+
{
|
|
1068
|
+
let tmpSelf = this;
|
|
1069
|
+
let tmpCallback = (typeof fCallback === 'function') ? fCallback : () => {};
|
|
1070
|
+
let tmpRemote = this._getRemote();
|
|
1071
|
+
|
|
1072
|
+
let tmpCollection = tmpRemote.ActiveCollection;
|
|
1073
|
+
if (!tmpCollection || !tmpCollection.OperationBatchGUID)
|
|
1074
|
+
{
|
|
1075
|
+
let tmpToast = tmpSelf._getToast();
|
|
1076
|
+
if (tmpToast)
|
|
1077
|
+
{
|
|
1078
|
+
tmpToast.show('No batch to undo');
|
|
1079
|
+
}
|
|
1080
|
+
return tmpCallback(new Error('No batch to undo'));
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
fetch('/api/files/undo-batch',
|
|
1084
|
+
{
|
|
1085
|
+
method: 'POST',
|
|
1086
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1087
|
+
body: JSON.stringify({ BatchGUID: tmpCollection.OperationBatchGUID })
|
|
1088
|
+
})
|
|
1089
|
+
.then((pResponse) => pResponse.json())
|
|
1090
|
+
.then((pData) =>
|
|
1091
|
+
{
|
|
1092
|
+
// Reset operation statuses back to pending
|
|
1093
|
+
if (tmpCollection.Items)
|
|
1094
|
+
{
|
|
1095
|
+
for (let i = 0; i < tmpCollection.Items.length; i++)
|
|
1096
|
+
{
|
|
1097
|
+
if (tmpCollection.Items[i].OperationStatus === 'completed')
|
|
1098
|
+
{
|
|
1099
|
+
tmpCollection.Items[i].OperationStatus = 'pending';
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
tmpCollection.OperationBatchGUID = null;
|
|
1104
|
+
|
|
1105
|
+
// Save updated collection
|
|
1106
|
+
tmpSelf.updateCollection(tmpCollection);
|
|
1107
|
+
|
|
1108
|
+
let tmpPanel = tmpSelf._getPanelView();
|
|
1109
|
+
if (tmpPanel)
|
|
1110
|
+
{
|
|
1111
|
+
tmpPanel.renderContent();
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
let tmpToast = tmpSelf._getToast();
|
|
1115
|
+
if (tmpToast)
|
|
1116
|
+
{
|
|
1117
|
+
tmpToast.show('Undo complete: ' + pData.TotalReversed + ' files restored');
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
return tmpCallback(null, pData);
|
|
1121
|
+
})
|
|
1122
|
+
.catch((pError) =>
|
|
1123
|
+
{
|
|
1124
|
+
tmpSelf.log.error('Failed to undo operations: ' + pError.message);
|
|
1125
|
+
let tmpToast = tmpSelf._getToast();
|
|
1126
|
+
if (tmpToast)
|
|
1127
|
+
{
|
|
1128
|
+
tmpToast.show('Failed to undo: ' + pError.message);
|
|
1129
|
+
}
|
|
1130
|
+
return tmpCallback(pError);
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
/**
|
|
1135
|
+
* Update a single item's destination path in the active collection.
|
|
1136
|
+
*
|
|
1137
|
+
* @param {string} pItemID - Item ID
|
|
1138
|
+
* @param {string} pNewDestPath - New destination path
|
|
1139
|
+
*/
|
|
1140
|
+
setItemDestination(pItemID, pNewDestPath)
|
|
1141
|
+
{
|
|
1142
|
+
let tmpRemote = this._getRemote();
|
|
1143
|
+
let tmpCollection = tmpRemote.ActiveCollection;
|
|
1144
|
+
|
|
1145
|
+
if (!tmpCollection || !tmpCollection.Items)
|
|
1146
|
+
{
|
|
1147
|
+
return;
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
for (let i = 0; i < tmpCollection.Items.length; i++)
|
|
1151
|
+
{
|
|
1152
|
+
if (tmpCollection.Items[i].ID === pItemID)
|
|
1153
|
+
{
|
|
1154
|
+
tmpCollection.Items[i].DestinationPath = pNewDestPath;
|
|
1155
|
+
break;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
// Save to server in background
|
|
1160
|
+
this.updateCollection(tmpCollection);
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
/**
|
|
1164
|
+
* Skip an item's operation (set status to 'skipped').
|
|
1165
|
+
*
|
|
1166
|
+
* @param {string} pItemID - Item ID
|
|
1167
|
+
*/
|
|
1168
|
+
skipItemOperation(pItemID)
|
|
1169
|
+
{
|
|
1170
|
+
let tmpRemote = this._getRemote();
|
|
1171
|
+
let tmpCollection = tmpRemote.ActiveCollection;
|
|
1172
|
+
|
|
1173
|
+
if (!tmpCollection || !tmpCollection.Items)
|
|
1174
|
+
{
|
|
1175
|
+
return;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
for (let i = 0; i < tmpCollection.Items.length; i++)
|
|
1179
|
+
{
|
|
1180
|
+
if (tmpCollection.Items[i].ID === pItemID)
|
|
1181
|
+
{
|
|
1182
|
+
tmpCollection.Items[i].OperationStatus = 'skipped';
|
|
1183
|
+
break;
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
let tmpPanel = this._getPanelView();
|
|
1188
|
+
if (tmpPanel)
|
|
1189
|
+
{
|
|
1190
|
+
tmpPanel.renderContent();
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
// Save to server in background
|
|
1194
|
+
this.updateCollection(tmpCollection);
|
|
1195
|
+
}
|
|
930
1196
|
}
|
|
931
1197
|
|
|
932
1198
|
CollectionManagerProvider.default_configuration = _DefaultProviderConfiguration;
|