@plusscommunities/pluss-maintenance-web-a 1.1.30 → 1.1.31
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/dist/index.cjs.js +264 -97
- package/dist/index.esm.js +264 -97
- package/dist/index.umd.js +264 -97
- package/package.json +1 -1
- package/src/apis/maintenanceActions.js +7 -0
- package/src/screens/Job.js +117 -16
package/src/screens/Job.js
CHANGED
|
@@ -35,6 +35,9 @@ class Job extends Component {
|
|
|
35
35
|
assignees: [],
|
|
36
36
|
externalSync: null,
|
|
37
37
|
loadingExternalSync: false,
|
|
38
|
+
retryingSync: false,
|
|
39
|
+
retrySyncError: null,
|
|
40
|
+
retrySyncInitiated: false,
|
|
38
41
|
};
|
|
39
42
|
}
|
|
40
43
|
|
|
@@ -86,6 +89,25 @@ class Job extends Component {
|
|
|
86
89
|
}
|
|
87
90
|
};
|
|
88
91
|
|
|
92
|
+
onRetrySync = async () => {
|
|
93
|
+
const { job } = this.state;
|
|
94
|
+
if (!job || this.state.retryingSync) return;
|
|
95
|
+
|
|
96
|
+
this.setState({ retryingSync: true, retrySyncError: null });
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
await maintenanceActions.retrySync(job.id);
|
|
100
|
+
// Refresh job data to get updated history
|
|
101
|
+
await this.getJob();
|
|
102
|
+
this.setState({ retryingSync: false, retrySyncInitiated: true });
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.error('onRetrySync', error);
|
|
105
|
+
const errorMessage =
|
|
106
|
+
(error && error.response && error.response.data && error.response.data.error) || 'Failed to retry sync. Please try again.';
|
|
107
|
+
this.setState({ retryingSync: false, retrySyncError: errorMessage });
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
89
111
|
getStatusType = (status) => {
|
|
90
112
|
const { statusTypes } = this.props;
|
|
91
113
|
let statusType = statusTypes.find((s) => s.text === status);
|
|
@@ -852,34 +874,113 @@ class Job extends Component {
|
|
|
852
874
|
);
|
|
853
875
|
}
|
|
854
876
|
|
|
877
|
+
hasSyncFailureWithoutSuccess() {
|
|
878
|
+
const { job } = this.state;
|
|
879
|
+
if (!job || !job.history) return false;
|
|
880
|
+
|
|
881
|
+
const history = job.history || [];
|
|
882
|
+
const hasSuccess = history.some((entry) => entry.EntryType === 'ExternalIDSet');
|
|
883
|
+
const hasFailure = history.some((entry) => entry.EntryType === 'ExternalIDSetFailed');
|
|
884
|
+
|
|
885
|
+
return hasFailure && !hasSuccess;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
renderRetrySyncButton() {
|
|
889
|
+
const { auth } = this.props;
|
|
890
|
+
const { retryingSync, retrySyncInitiated } = this.state;
|
|
891
|
+
|
|
892
|
+
// Only show for users with maintenance tracking permission
|
|
893
|
+
if (!Session.validateAccess(auth.site, values.permissionMaintenanceTracking, auth)) return null;
|
|
894
|
+
|
|
895
|
+
// Only show if there's a failure without success and retry hasn't been initiated
|
|
896
|
+
if (!this.hasSyncFailureWithoutSuccess() || retrySyncInitiated) return null;
|
|
897
|
+
|
|
898
|
+
// Show spinner while retrying
|
|
899
|
+
if (retryingSync) {
|
|
900
|
+
return <FontAwesome style={{ fontSize: 20, color: Colours.COLOUR_DUSK_LIGHT, marginLeft: 8 }} name="spinner fa-pulse fa-fw" />;
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
return (
|
|
904
|
+
<div className="statusLabel pointer" onClick={this.onRetrySync} style={{ backgroundColor: Colours.COLOUR_RED, marginLeft: 8 }}>
|
|
905
|
+
<span className="statusLabel_text">Retry Sync</span>
|
|
906
|
+
</div>
|
|
907
|
+
);
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
renderExternalSyncStatus() {
|
|
911
|
+
const { retrySyncError, retrySyncInitiated } = this.state;
|
|
912
|
+
|
|
913
|
+
// Show error message if retry failed
|
|
914
|
+
if (retrySyncError) {
|
|
915
|
+
return (
|
|
916
|
+
<Components.Text type="body">
|
|
917
|
+
<FontAwesome className="userStatusIcon" name="times-circle" style={{ color: Colours.COLOUR_RED }} /> {retrySyncError}
|
|
918
|
+
</Components.Text>
|
|
919
|
+
);
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
// Show success message if retry was initiated
|
|
923
|
+
if (retrySyncInitiated) {
|
|
924
|
+
return (
|
|
925
|
+
<Components.Text type="body">
|
|
926
|
+
<FontAwesome className="userStatusIcon" name="check-circle" style={{ color: Colours.COLOUR_GREEN }} /> Sync retry initiated. Check
|
|
927
|
+
back shortly for results.
|
|
928
|
+
</Components.Text>
|
|
929
|
+
);
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
// Show failure message with instruction
|
|
933
|
+
if (this.hasSyncFailureWithoutSuccess()) {
|
|
934
|
+
return (
|
|
935
|
+
<Components.Text type="body">
|
|
936
|
+
<FontAwesome className="userStatusIcon" name="times-circle" style={{ color: Colours.COLOUR_RED }} /> External sync failed. Use the
|
|
937
|
+
retry button to attempt again.
|
|
938
|
+
</Components.Text>
|
|
939
|
+
);
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
return null;
|
|
943
|
+
}
|
|
944
|
+
|
|
855
945
|
renderExternalSync() {
|
|
856
946
|
const { externalSync, loadingExternalSync } = this.state;
|
|
857
947
|
|
|
858
|
-
//
|
|
859
|
-
|
|
948
|
+
// Check if we should show this section at all
|
|
949
|
+
const hasExternalSyncData = externalSync && !loadingExternalSync;
|
|
950
|
+
const hasSyncFailure = this.hasSyncFailureWithoutSuccess();
|
|
951
|
+
|
|
952
|
+
// Show section if we have sync data OR if there's a failure that can be retried
|
|
953
|
+
if (!hasExternalSyncData && !hasSyncFailure) return null;
|
|
860
954
|
|
|
861
955
|
return (
|
|
862
956
|
<div className="padding-32 paddingVertical-40 bottomDivideBorder relative">
|
|
863
957
|
<div className="newTopBar clearfix flex flex-reverse">
|
|
958
|
+
{this.renderRetrySyncButton()}
|
|
864
959
|
<Components.Text type="formTitleSmall" className="flex-1">
|
|
865
960
|
External Sync
|
|
866
961
|
</Components.Text>
|
|
867
962
|
</div>
|
|
868
963
|
<div className="marginTop-16">
|
|
869
|
-
{
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
964
|
+
{hasExternalSyncData ? (
|
|
965
|
+
<>
|
|
966
|
+
{externalSync.systemType && (
|
|
967
|
+
<Components.Text type="body" className="marginBottom-8">
|
|
968
|
+
<strong>System:</strong> {externalSync.systemType}
|
|
969
|
+
</Components.Text>
|
|
970
|
+
)}
|
|
971
|
+
{externalSync.externalId && (
|
|
972
|
+
<Components.Text type="body" className="marginBottom-8">
|
|
973
|
+
<strong>External ID:</strong> {externalSync.externalId}
|
|
974
|
+
</Components.Text>
|
|
975
|
+
)}
|
|
976
|
+
{externalSync.syncedAt && (
|
|
977
|
+
<Components.Text type="body" className="marginBottom-8">
|
|
978
|
+
<strong>Synced:</strong> {moment.utc(externalSync.syncedAt).local().format('D MMM YYYY h:mma')}
|
|
979
|
+
</Components.Text>
|
|
980
|
+
)}
|
|
981
|
+
</>
|
|
982
|
+
) : (
|
|
983
|
+
this.renderExternalSyncStatus()
|
|
883
984
|
)}
|
|
884
985
|
</div>
|
|
885
986
|
</div>
|