@overmap-ai/core 1.0.51-add-submitted-at-to-form-revisions.1 → 1.0.51-attachment-creation-flows.1
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/forms/renderer/FormSubmissionBrowser/FormSubmissionBrowser.d.ts +5 -5
- package/dist/forms/renderer/FormSubmissionViewer/FormSubmissionViewer.d.ts +3 -3
- package/dist/overmap-core.js +1231 -500
- package/dist/overmap-core.js.map +1 -1
- package/dist/overmap-core.umd.cjs +1231 -500
- package/dist/overmap-core.umd.cjs.map +1 -1
- package/dist/sdk/sdk.d.ts +6 -1
- package/dist/sdk/services/BaseAttachmentService.d.ts +31 -0
- package/dist/sdk/services/ComponentAttachmentService.d.ts +10 -0
- package/dist/sdk/services/ComponentTypeAttachmentService.d.ts +10 -0
- package/dist/sdk/services/DocumentAttachmentService.d.ts +10 -0
- package/dist/sdk/services/IssueAttachmentService.d.ts +10 -0
- package/dist/sdk/services/ProjectAttachmentService.d.ts +10 -0
- package/dist/sdk/services/UserFormSubmissionService.d.ts +9 -2
- package/dist/sdk/services/index.d.ts +5 -0
- package/dist/store/slices/categorySlice.d.ts +3 -1
- package/dist/store/slices/componentSlice.d.ts +15 -7
- package/dist/store/slices/componentTypeSlice.d.ts +16 -8
- package/dist/store/slices/documentSlice.d.ts +13 -3
- package/dist/store/slices/formRevisionSlice.d.ts +65 -0
- package/dist/store/slices/formSlice.d.ts +110 -0
- package/dist/store/slices/formSubmissionSlice.d.ts +47 -0
- package/dist/store/slices/index.d.ts +3 -1
- package/dist/store/slices/issueSlice.d.ts +36 -22
- package/dist/store/slices/projectFileSlice.d.ts +3 -1
- package/dist/store/slices/projectSlice.d.ts +12 -3
- package/dist/store/slices/utils.d.ts +4 -2
- package/dist/store/slices/workspaceSlice.d.ts +3 -1
- package/dist/store/store.d.ts +10 -4
- package/dist/typings/files.d.ts +11 -1
- package/dist/typings/models/attachments.d.ts +15 -11
- package/dist/typings/models/base.d.ts +7 -0
- package/dist/typings/models/forms.d.ts +6 -11
- package/dist/typings/models/projects.d.ts +4 -5
- package/dist/utils/file.d.ts +2 -0
- package/dist/utils/forms.d.ts +2 -0
- package/package.json +1 -1
- package/dist/store/slices/userFormSlice.d.ts +0 -145
package/dist/overmap-core.js
CHANGED
|
@@ -677,15 +677,15 @@ const wrapMigration = (migrator) => (state) => {
|
|
|
677
677
|
};
|
|
678
678
|
const migrations = [initialVersioning, signOut, signOut, createOutboxState];
|
|
679
679
|
const manifest = Object.fromEntries(migrations.map((migration2, i) => [i, wrapMigration(migration2)]));
|
|
680
|
-
const initialState$
|
|
680
|
+
const initialState$p = {
|
|
681
681
|
accessToken: "",
|
|
682
682
|
refreshToken: "",
|
|
683
683
|
isLoggedIn: false
|
|
684
684
|
};
|
|
685
685
|
const authSlice = createSlice({
|
|
686
686
|
name: "auth",
|
|
687
|
-
initialState: initialState$
|
|
688
|
-
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$
|
|
687
|
+
initialState: initialState$p,
|
|
688
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$p)),
|
|
689
689
|
reducers: {
|
|
690
690
|
setTokens: (state, action) => {
|
|
691
691
|
state.accessToken = action.payload.accessToken;
|
|
@@ -850,6 +850,19 @@ function downloadInMemoryFile(filename, text) {
|
|
|
850
850
|
element.click();
|
|
851
851
|
document.body.removeChild(element);
|
|
852
852
|
}
|
|
853
|
+
const constructUploadedFilePayloads = async (files) => {
|
|
854
|
+
const filePayloads = {};
|
|
855
|
+
for (const file of files) {
|
|
856
|
+
const sha1 = await hashFile(file);
|
|
857
|
+
filePayloads[sha1] = {
|
|
858
|
+
sha1,
|
|
859
|
+
extension: file.name.split(".").pop() || "",
|
|
860
|
+
file_type: file.type,
|
|
861
|
+
size: file.size
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
return Object.values(filePayloads);
|
|
865
|
+
};
|
|
853
866
|
const fileToBlob = async (dataUrl) => {
|
|
854
867
|
return (await fetch(dataUrl)).blob();
|
|
855
868
|
};
|
|
@@ -1416,7 +1429,7 @@ const getLocalRelativeDateString = memoize((date, min, max) => {
|
|
|
1416
1429
|
return getLocalDateString(date);
|
|
1417
1430
|
return relative.format(days, "days");
|
|
1418
1431
|
});
|
|
1419
|
-
const initialState$
|
|
1432
|
+
const initialState$o = {
|
|
1420
1433
|
categories: {},
|
|
1421
1434
|
usedCategoryColors: [],
|
|
1422
1435
|
categoryVisibility: {
|
|
@@ -1426,8 +1439,8 @@ const initialState$m = {
|
|
|
1426
1439
|
};
|
|
1427
1440
|
const categorySlice = createSlice({
|
|
1428
1441
|
name: "categories",
|
|
1429
|
-
initialState: initialState$
|
|
1430
|
-
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$
|
|
1442
|
+
initialState: initialState$o,
|
|
1443
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$o)),
|
|
1431
1444
|
reducers: {
|
|
1432
1445
|
setCategories: (state, action) => {
|
|
1433
1446
|
if (!Array.isArray(action.payload))
|
|
@@ -1560,6 +1573,9 @@ const selectHiddenCategoryCount = (state) => {
|
|
|
1560
1573
|
return hiddenCategoryCount;
|
|
1561
1574
|
};
|
|
1562
1575
|
const categoryReducer = categorySlice.reducer;
|
|
1576
|
+
function setAttachment(state, action) {
|
|
1577
|
+
state.attachments[action.payload.offline_id] = action.payload;
|
|
1578
|
+
}
|
|
1563
1579
|
function setAttachments(state, action) {
|
|
1564
1580
|
state.attachments = {};
|
|
1565
1581
|
for (const attachment of action.payload) {
|
|
@@ -1584,6 +1600,15 @@ function updateAttachment(state, action) {
|
|
|
1584
1600
|
throw new Error(`Attachment ${action.payload.offline_id} does not exist.`);
|
|
1585
1601
|
}
|
|
1586
1602
|
}
|
|
1603
|
+
function updateAttachments(state, action) {
|
|
1604
|
+
for (const attachment of action.payload) {
|
|
1605
|
+
if (attachment.offline_id in state.attachments) {
|
|
1606
|
+
state.attachments[attachment.offline_id] = attachment;
|
|
1607
|
+
} else {
|
|
1608
|
+
throw new Error(`Attachment ${attachment.offline_id} does not exist.`);
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1587
1612
|
function removeAttachment(state, action) {
|
|
1588
1613
|
if (action.payload in state.attachments) {
|
|
1589
1614
|
delete state.attachments[action.payload];
|
|
@@ -1596,14 +1621,14 @@ function removeAttachments(state, action) {
|
|
|
1596
1621
|
delete state.attachments[attachmentId];
|
|
1597
1622
|
}
|
|
1598
1623
|
}
|
|
1599
|
-
const initialState$
|
|
1624
|
+
const initialState$n = {
|
|
1600
1625
|
components: {},
|
|
1601
1626
|
attachments: {}
|
|
1602
1627
|
};
|
|
1603
1628
|
const componentSlice = createSlice({
|
|
1604
1629
|
name: "components",
|
|
1605
|
-
initialState: initialState$
|
|
1606
|
-
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$
|
|
1630
|
+
initialState: initialState$n,
|
|
1631
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$n)),
|
|
1607
1632
|
reducers: {
|
|
1608
1633
|
addComponent: (state, action) => {
|
|
1609
1634
|
state.components[action.payload.offline_id] = action.payload;
|
|
@@ -1617,12 +1642,6 @@ const componentSlice = createSlice({
|
|
|
1617
1642
|
state.components = toOfflineIdRecord(action.payload);
|
|
1618
1643
|
prevComponents = null;
|
|
1619
1644
|
},
|
|
1620
|
-
setComponentAttachments: setAttachments,
|
|
1621
|
-
addComponentAttachment: addAttachment,
|
|
1622
|
-
addComponentAttachments: addAttachments,
|
|
1623
|
-
updateComponentAttachment: updateAttachment,
|
|
1624
|
-
removeComponentAttachment: removeAttachment,
|
|
1625
|
-
removeComponentAttachments: removeAttachments,
|
|
1626
1645
|
updateComponent: (state, action) => {
|
|
1627
1646
|
if (action.payload.offline_id in state.components) {
|
|
1628
1647
|
state.components[action.payload.offline_id] = action.payload;
|
|
@@ -1647,9 +1666,35 @@ const componentSlice = createSlice({
|
|
|
1647
1666
|
}
|
|
1648
1667
|
}
|
|
1649
1668
|
prevComponents = null;
|
|
1650
|
-
}
|
|
1669
|
+
},
|
|
1670
|
+
// Attachments
|
|
1671
|
+
setComponentAttachment: setAttachment,
|
|
1672
|
+
setComponentAttachments: setAttachments,
|
|
1673
|
+
addComponentAttachment: addAttachment,
|
|
1674
|
+
addComponentAttachments: addAttachments,
|
|
1675
|
+
updateComponentAttachment: updateAttachment,
|
|
1676
|
+
updateComponentAttachments: updateAttachments,
|
|
1677
|
+
removeComponentAttachment: removeAttachment,
|
|
1678
|
+
removeComponentAttachments: removeAttachments
|
|
1651
1679
|
}
|
|
1652
1680
|
});
|
|
1681
|
+
const {
|
|
1682
|
+
addComponent,
|
|
1683
|
+
updateComponent,
|
|
1684
|
+
removeComponent,
|
|
1685
|
+
addComponentsInBatches,
|
|
1686
|
+
setComponents,
|
|
1687
|
+
removeAllComponentsOfType,
|
|
1688
|
+
// Attachments
|
|
1689
|
+
setComponentAttachment,
|
|
1690
|
+
setComponentAttachments,
|
|
1691
|
+
addComponentAttachment,
|
|
1692
|
+
addComponentAttachments,
|
|
1693
|
+
updateComponentAttachment,
|
|
1694
|
+
updateComponentAttachments,
|
|
1695
|
+
removeComponentAttachment,
|
|
1696
|
+
removeComponentAttachments
|
|
1697
|
+
} = componentSlice.actions;
|
|
1653
1698
|
let prevComponents = null;
|
|
1654
1699
|
const selectComponents = (state) => {
|
|
1655
1700
|
if (!prevComponents) {
|
|
@@ -1744,28 +1789,14 @@ const selectAttachmentsOfComponentByType = restructureCreateSelectorWithArgs(
|
|
|
1744
1789
|
}
|
|
1745
1790
|
)
|
|
1746
1791
|
);
|
|
1747
|
-
const {
|
|
1748
|
-
addComponent,
|
|
1749
|
-
updateComponent,
|
|
1750
|
-
removeComponent,
|
|
1751
|
-
addComponentsInBatches,
|
|
1752
|
-
setComponents,
|
|
1753
|
-
setComponentAttachments,
|
|
1754
|
-
addComponentAttachment,
|
|
1755
|
-
addComponentAttachments,
|
|
1756
|
-
updateComponentAttachment,
|
|
1757
|
-
removeComponentAttachment,
|
|
1758
|
-
removeComponentAttachments,
|
|
1759
|
-
removeAllComponentsOfType
|
|
1760
|
-
} = componentSlice.actions;
|
|
1761
1792
|
const componentReducer = componentSlice.reducer;
|
|
1762
|
-
const initialState$
|
|
1793
|
+
const initialState$m = {
|
|
1763
1794
|
completionsByComponentId: {}
|
|
1764
1795
|
};
|
|
1765
1796
|
const componentStageCompletionSlice = createSlice({
|
|
1766
1797
|
name: "componentStageCompletions",
|
|
1767
|
-
initialState: initialState$
|
|
1768
|
-
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$
|
|
1798
|
+
initialState: initialState$m,
|
|
1799
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$m)),
|
|
1769
1800
|
reducers: {
|
|
1770
1801
|
addStageCompletion: (state, action) => {
|
|
1771
1802
|
let stageToCompletionDateMapping = state.completionsByComponentId[action.payload.component];
|
|
@@ -1816,13 +1847,13 @@ const selectCompletedStageIdsForComponent = (component) => (state) => {
|
|
|
1816
1847
|
return Object.keys(state.componentStageCompletionReducer.completionsByComponentId[component.offline_id] ?? {});
|
|
1817
1848
|
};
|
|
1818
1849
|
const componentStageCompletionReducer = componentStageCompletionSlice.reducer;
|
|
1819
|
-
const initialState$
|
|
1850
|
+
const initialState$l = {
|
|
1820
1851
|
stages: {}
|
|
1821
1852
|
};
|
|
1822
1853
|
const componentStageSlice = createSlice({
|
|
1823
1854
|
name: "componentStages",
|
|
1824
|
-
initialState: initialState$
|
|
1825
|
-
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$
|
|
1855
|
+
initialState: initialState$l,
|
|
1856
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$l)),
|
|
1826
1857
|
reducers: {
|
|
1827
1858
|
addStages: (state, action) => {
|
|
1828
1859
|
Object.assign(state.stages, toOfflineIdRecord(action.payload));
|
|
@@ -1932,15 +1963,15 @@ const selectStageFormIdsFromStageIds = restructureCreateSelectorWithArgs(
|
|
|
1932
1963
|
);
|
|
1933
1964
|
const { addStages, updateStages, removeStages, linkStageToForm, unlinkStageToForm } = componentStageSlice.actions;
|
|
1934
1965
|
const componentStageReducer = componentStageSlice.reducer;
|
|
1935
|
-
const initialState$
|
|
1966
|
+
const initialState$k = {
|
|
1936
1967
|
componentTypes: {},
|
|
1937
1968
|
hiddenComponentTypeIds: {},
|
|
1938
1969
|
attachments: {}
|
|
1939
1970
|
};
|
|
1940
1971
|
const componentTypeSlice = createSlice({
|
|
1941
1972
|
name: "componentTypes",
|
|
1942
|
-
initialState: initialState$
|
|
1943
|
-
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$
|
|
1973
|
+
initialState: initialState$k,
|
|
1974
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$k)),
|
|
1944
1975
|
reducers: {
|
|
1945
1976
|
addComponentType: (state, action) => {
|
|
1946
1977
|
state.componentTypes[action.payload.offline_id] = action.payload;
|
|
@@ -1948,20 +1979,38 @@ const componentTypeSlice = createSlice({
|
|
|
1948
1979
|
setComponentTypes: (state, action) => {
|
|
1949
1980
|
state.componentTypes = toOfflineIdRecord(action.payload);
|
|
1950
1981
|
},
|
|
1951
|
-
setComponentTypeAttachments: setAttachments,
|
|
1952
|
-
addComponentTypeAttachment: addAttachment,
|
|
1953
|
-
addComponentTypeAttachments: addAttachments,
|
|
1954
|
-
updateComponentTypeAttachment: updateAttachment,
|
|
1955
|
-
removeComponentTypeAttachment: removeAttachment,
|
|
1956
|
-
removeComponentTypeAttachments: removeAttachments,
|
|
1957
1982
|
toggleComponentTypeVisibility: (state, action) => {
|
|
1958
1983
|
state.hiddenComponentTypeIds[action.payload] = !state.hiddenComponentTypeIds[action.payload];
|
|
1959
1984
|
},
|
|
1960
1985
|
deleteComponentType: (state, action) => {
|
|
1961
1986
|
delete state.componentTypes[action.payload];
|
|
1962
|
-
}
|
|
1987
|
+
},
|
|
1988
|
+
// Attachments
|
|
1989
|
+
setComponentTypeAttachment: setAttachment,
|
|
1990
|
+
setComponentTypeAttachments: setAttachments,
|
|
1991
|
+
addComponentTypeAttachment: addAttachment,
|
|
1992
|
+
addComponentTypeAttachments: addAttachments,
|
|
1993
|
+
updateComponentTypeAttachment: updateAttachment,
|
|
1994
|
+
updateComponentTypeAttachments: updateAttachments,
|
|
1995
|
+
removeComponentTypeAttachment: removeAttachment,
|
|
1996
|
+
removeComponentTypeAttachments: removeAttachments
|
|
1963
1997
|
}
|
|
1964
1998
|
});
|
|
1999
|
+
const {
|
|
2000
|
+
addComponentType,
|
|
2001
|
+
setComponentTypes,
|
|
2002
|
+
toggleComponentTypeVisibility,
|
|
2003
|
+
deleteComponentType,
|
|
2004
|
+
// Attachmet
|
|
2005
|
+
setComponentTypeAttachment,
|
|
2006
|
+
setComponentTypeAttachments,
|
|
2007
|
+
addComponentTypeAttachment,
|
|
2008
|
+
addComponentTypeAttachments,
|
|
2009
|
+
updateComponentTypeAttachment,
|
|
2010
|
+
updateComponentTypeAttachments,
|
|
2011
|
+
removeComponentTypeAttachment,
|
|
2012
|
+
removeComponentTypeAttachments
|
|
2013
|
+
} = componentTypeSlice.actions;
|
|
1965
2014
|
const selectComponentTypesMapping = (state) => state.componentTypeReducer.componentTypes;
|
|
1966
2015
|
const selectComponentTypes = createSelector(
|
|
1967
2016
|
[selectComponentTypesMapping],
|
|
@@ -2038,26 +2087,14 @@ const selectAttachmentsOfComponentTypeByType = restructureCreateSelectorWithArgs
|
|
|
2038
2087
|
}
|
|
2039
2088
|
)
|
|
2040
2089
|
);
|
|
2041
|
-
const {
|
|
2042
|
-
addComponentType,
|
|
2043
|
-
setComponentTypes,
|
|
2044
|
-
setComponentTypeAttachments,
|
|
2045
|
-
addComponentTypeAttachment,
|
|
2046
|
-
addComponentTypeAttachments,
|
|
2047
|
-
updateComponentTypeAttachment,
|
|
2048
|
-
removeComponentTypeAttachment,
|
|
2049
|
-
removeComponentTypeAttachments,
|
|
2050
|
-
toggleComponentTypeVisibility,
|
|
2051
|
-
deleteComponentType
|
|
2052
|
-
} = componentTypeSlice.actions;
|
|
2053
2090
|
const componentTypeReducer = componentTypeSlice.reducer;
|
|
2054
|
-
const initialState$
|
|
2091
|
+
const initialState$j = {
|
|
2055
2092
|
workspaces: {},
|
|
2056
2093
|
activeWorkspaceId: null
|
|
2057
2094
|
};
|
|
2058
2095
|
const workspaceSlice = createSlice({
|
|
2059
2096
|
name: "workspace",
|
|
2060
|
-
initialState: initialState$
|
|
2097
|
+
initialState: initialState$j,
|
|
2061
2098
|
// The `reducers` field lets us define reducers and generate associated actions
|
|
2062
2099
|
reducers: {
|
|
2063
2100
|
setWorkspaces: (state, action) => {
|
|
@@ -2114,7 +2151,7 @@ const selectPermittedWorkspaceIds = createSelector(
|
|
|
2114
2151
|
);
|
|
2115
2152
|
const workspaceReducer = workspaceSlice.reducer;
|
|
2116
2153
|
const maxRecentIssues = 10;
|
|
2117
|
-
const initialState$
|
|
2154
|
+
const initialState$i = {
|
|
2118
2155
|
issues: {},
|
|
2119
2156
|
attachments: {},
|
|
2120
2157
|
comments: {},
|
|
@@ -2126,9 +2163,9 @@ const initialState$g = {
|
|
|
2126
2163
|
};
|
|
2127
2164
|
const issueSlice = createSlice({
|
|
2128
2165
|
name: "issues",
|
|
2129
|
-
initialState: initialState$
|
|
2166
|
+
initialState: initialState$i,
|
|
2130
2167
|
extraReducers: (builder) => builder.addCase("RESET", (state) => {
|
|
2131
|
-
Object.assign(state, initialState$
|
|
2168
|
+
Object.assign(state, initialState$i);
|
|
2132
2169
|
}),
|
|
2133
2170
|
reducers: {
|
|
2134
2171
|
setIssues: (state, action) => {
|
|
@@ -2139,7 +2176,6 @@ const issueSlice = createSlice({
|
|
|
2139
2176
|
state.issues[issue.offline_id] = issue;
|
|
2140
2177
|
});
|
|
2141
2178
|
},
|
|
2142
|
-
setIssueAttachments: setAttachments,
|
|
2143
2179
|
setIssueUpdates: (state, action) => {
|
|
2144
2180
|
if (action.payload.filter(onlyUniqueOfflineIds).length !== action.payload.length) {
|
|
2145
2181
|
throw new Error("Tried to use setIssues reducer with duplicate ID's");
|
|
@@ -2159,8 +2195,6 @@ const issueSlice = createSlice({
|
|
|
2159
2195
|
}
|
|
2160
2196
|
state.issues[action.payload.offline_id] = action.payload;
|
|
2161
2197
|
},
|
|
2162
|
-
addIssueAttachment: addAttachment,
|
|
2163
|
-
addIssueAttachments: addAttachments,
|
|
2164
2198
|
addIssueUpdate: (state, action) => {
|
|
2165
2199
|
if (action.payload.offline_id in state.updates) {
|
|
2166
2200
|
throw new Error(`Tried to add duplicate issue update with offline_id: ${action.payload.offline_id}`);
|
|
@@ -2182,7 +2216,6 @@ const issueSlice = createSlice({
|
|
|
2182
2216
|
throw new Error(`Tried to update issue with ID that doesn't exist: ${action.payload.offline_id}`);
|
|
2183
2217
|
}
|
|
2184
2218
|
},
|
|
2185
|
-
updateIssueAttachment: updateAttachment,
|
|
2186
2219
|
removeIssue: (state, action) => {
|
|
2187
2220
|
if (action.payload in state.issues) {
|
|
2188
2221
|
delete state.issues[action.payload];
|
|
@@ -2190,7 +2223,6 @@ const issueSlice = createSlice({
|
|
|
2190
2223
|
throw new Error(`Failed to remove issue because ID doesn't exist: ${action.payload}`);
|
|
2191
2224
|
}
|
|
2192
2225
|
},
|
|
2193
|
-
removeIssueAttachment: removeAttachment,
|
|
2194
2226
|
removeIssueUpdate: (state, action) => {
|
|
2195
2227
|
if (action.payload in state.updates) {
|
|
2196
2228
|
delete state.updates[action.payload];
|
|
@@ -2287,19 +2319,25 @@ const issueSlice = createSlice({
|
|
|
2287
2319
|
if (indexToRemove !== -1) {
|
|
2288
2320
|
state.recentIssueIds.splice(indexToRemove, 1);
|
|
2289
2321
|
}
|
|
2290
|
-
}
|
|
2322
|
+
},
|
|
2323
|
+
// Attachments
|
|
2324
|
+
setIssueAttachment: setAttachment,
|
|
2325
|
+
setIssueAttachments: setAttachments,
|
|
2326
|
+
addIssueAttachment: addAttachment,
|
|
2327
|
+
addIssueAttachments: addAttachments,
|
|
2328
|
+
updateIssueAttachment: updateAttachment,
|
|
2329
|
+
updateIssueAttachments: updateAttachments,
|
|
2330
|
+
removeIssueAttachment: removeAttachment,
|
|
2331
|
+
removeIssueAttachments: removeAttachments
|
|
2291
2332
|
}
|
|
2292
2333
|
});
|
|
2293
2334
|
const {
|
|
2294
|
-
addIssueAttachment,
|
|
2295
|
-
addIssueAttachments,
|
|
2296
2335
|
addIssue,
|
|
2297
2336
|
addIssueUpdate,
|
|
2298
2337
|
addIssueUpdates,
|
|
2299
2338
|
addOrReplaceIssueComment,
|
|
2300
2339
|
addToRecentIssues,
|
|
2301
2340
|
cleanRecentIssues,
|
|
2302
|
-
removeIssueAttachment,
|
|
2303
2341
|
removeAttachmentsOfIssue,
|
|
2304
2342
|
removeIssue,
|
|
2305
2343
|
removeIssueUpdate,
|
|
@@ -2307,13 +2345,20 @@ const {
|
|
|
2307
2345
|
removeRecentIssue,
|
|
2308
2346
|
resetRecentIssues,
|
|
2309
2347
|
setActiveIssueId,
|
|
2310
|
-
setIssueAttachments,
|
|
2311
2348
|
setIssueUpdates,
|
|
2312
2349
|
setIssues,
|
|
2313
2350
|
setVisibleStatuses,
|
|
2314
2351
|
setVisibleUserIds,
|
|
2315
|
-
updateIssueAttachment,
|
|
2316
2352
|
updateIssue,
|
|
2353
|
+
// Attachments
|
|
2354
|
+
setIssueAttachment,
|
|
2355
|
+
setIssueAttachments,
|
|
2356
|
+
addIssueAttachment,
|
|
2357
|
+
addIssueAttachments,
|
|
2358
|
+
updateIssueAttachment,
|
|
2359
|
+
updateIssueAttachments,
|
|
2360
|
+
removeIssueAttachment,
|
|
2361
|
+
removeIssueAttachments,
|
|
2317
2362
|
// Commments
|
|
2318
2363
|
addIssueComment,
|
|
2319
2364
|
addIssueComments,
|
|
@@ -2536,15 +2581,15 @@ const selectRecentIssuesAsSearchResults = createSelector(
|
|
|
2536
2581
|
}
|
|
2537
2582
|
);
|
|
2538
2583
|
const issueReducer = issueSlice.reducer;
|
|
2539
|
-
const initialState$
|
|
2584
|
+
const initialState$h = {
|
|
2540
2585
|
s3Urls: {}
|
|
2541
2586
|
};
|
|
2542
2587
|
const msPerHour = 1e3 * 60 * 60;
|
|
2543
2588
|
const msPerWeek = msPerHour * 24 * 7;
|
|
2544
2589
|
const fileSlice = createSlice({
|
|
2545
2590
|
name: "file",
|
|
2546
|
-
initialState: initialState$
|
|
2547
|
-
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$
|
|
2591
|
+
initialState: initialState$h,
|
|
2592
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$h)),
|
|
2548
2593
|
reducers: {
|
|
2549
2594
|
setUploadUrl: (state, action) => {
|
|
2550
2595
|
const { url, fields, sha1 } = action.payload;
|
|
@@ -2571,7 +2616,7 @@ const selectUploadUrl = (sha1) => (state) => {
|
|
|
2571
2616
|
return url;
|
|
2572
2617
|
};
|
|
2573
2618
|
const fileReducer = fileSlice.reducer;
|
|
2574
|
-
const initialState$
|
|
2619
|
+
const initialState$g = {
|
|
2575
2620
|
// TODO: Change first MapStyle.SATELLITE to MaptStyle.None when project creation map is fixed
|
|
2576
2621
|
mapStyle: MapStyle.SATELLITE,
|
|
2577
2622
|
showTooltips: false,
|
|
@@ -2579,8 +2624,8 @@ const initialState$e = {
|
|
|
2579
2624
|
};
|
|
2580
2625
|
const mapSlice = createSlice({
|
|
2581
2626
|
name: "map",
|
|
2582
|
-
initialState: initialState$
|
|
2583
|
-
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$
|
|
2627
|
+
initialState: initialState$g,
|
|
2628
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$g)),
|
|
2584
2629
|
reducers: {
|
|
2585
2630
|
setMapStyle: (state, action) => {
|
|
2586
2631
|
state.mapStyle = action.payload;
|
|
@@ -2608,6 +2653,14 @@ var OrganizationAccessLevel = /* @__PURE__ */ ((OrganizationAccessLevel2) => {
|
|
|
2608
2653
|
OrganizationAccessLevel2[OrganizationAccessLevel2["ADMIN"] = 2] = "ADMIN";
|
|
2609
2654
|
return OrganizationAccessLevel2;
|
|
2610
2655
|
})(OrganizationAccessLevel || {});
|
|
2656
|
+
var AttachmentModel = /* @__PURE__ */ ((AttachmentModel2) => {
|
|
2657
|
+
AttachmentModel2["Issue"] = "issue";
|
|
2658
|
+
AttachmentModel2["Component"] = "component";
|
|
2659
|
+
AttachmentModel2["ComponentType"] = "component_type";
|
|
2660
|
+
AttachmentModel2["Project"] = "project";
|
|
2661
|
+
AttachmentModel2["Document"] = "document";
|
|
2662
|
+
return AttachmentModel2;
|
|
2663
|
+
})(AttachmentModel || {});
|
|
2611
2664
|
var IssueUpdateChange = /* @__PURE__ */ ((IssueUpdateChange2) => {
|
|
2612
2665
|
IssueUpdateChange2["STATUS"] = "status";
|
|
2613
2666
|
IssueUpdateChange2["PRIORITY"] = "priority";
|
|
@@ -2649,7 +2702,7 @@ var LicenseStatus = /* @__PURE__ */ ((LicenseStatus2) => {
|
|
|
2649
2702
|
LicenseStatus2[LicenseStatus2["PAST_DUE"] = 8] = "PAST_DUE";
|
|
2650
2703
|
return LicenseStatus2;
|
|
2651
2704
|
})(LicenseStatus || {});
|
|
2652
|
-
const initialState$
|
|
2705
|
+
const initialState$f = {
|
|
2653
2706
|
users: {},
|
|
2654
2707
|
currentUser: {
|
|
2655
2708
|
id: 0,
|
|
@@ -2660,8 +2713,8 @@ const initialState$d = {
|
|
|
2660
2713
|
};
|
|
2661
2714
|
const userSlice = createSlice({
|
|
2662
2715
|
name: "users",
|
|
2663
|
-
initialState: initialState$
|
|
2664
|
-
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$
|
|
2716
|
+
initialState: initialState$f,
|
|
2717
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$f)),
|
|
2665
2718
|
reducers: {
|
|
2666
2719
|
setUsers: (state, action) => {
|
|
2667
2720
|
const usersMapping = {};
|
|
@@ -2723,13 +2776,13 @@ const selectUser = (userId) => (state) => {
|
|
|
2723
2776
|
const selectUsersAsMapping = (state) => state.userReducer.users;
|
|
2724
2777
|
const selectFavouriteProjects = (state) => state.userReducer.currentUser.profile.favourite_project_ids;
|
|
2725
2778
|
const userReducer = userSlice.reducer;
|
|
2726
|
-
const initialState$
|
|
2779
|
+
const initialState$e = {
|
|
2727
2780
|
organizationAccesses: {}
|
|
2728
2781
|
};
|
|
2729
2782
|
const organizationAccessSlice = createSlice({
|
|
2730
2783
|
name: "organizationAccess",
|
|
2731
|
-
initialState: initialState$
|
|
2732
|
-
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$
|
|
2784
|
+
initialState: initialState$e,
|
|
2785
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$e)),
|
|
2733
2786
|
reducers: {
|
|
2734
2787
|
setOrganizationAccesses: (state, action) => {
|
|
2735
2788
|
if (!Array.isArray(action.payload))
|
|
@@ -2792,13 +2845,13 @@ const selectOrganizationAccessUserMapping = (state) => {
|
|
|
2792
2845
|
return organizationAccesses;
|
|
2793
2846
|
};
|
|
2794
2847
|
const organizationAccessReducer = organizationAccessSlice.reducer;
|
|
2795
|
-
const initialState$
|
|
2848
|
+
const initialState$d = {
|
|
2796
2849
|
licenses: {}
|
|
2797
2850
|
};
|
|
2798
2851
|
const licenseSlice = createSlice({
|
|
2799
2852
|
name: "license",
|
|
2800
|
-
initialState: initialState$
|
|
2801
|
-
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$
|
|
2853
|
+
initialState: initialState$d,
|
|
2854
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$d)),
|
|
2802
2855
|
reducers: {
|
|
2803
2856
|
setLicenses: (state, action) => {
|
|
2804
2857
|
if (!Array.isArray(action.payload))
|
|
@@ -2843,13 +2896,13 @@ const selectLicensesForProjectsMapping = createSelector(
|
|
|
2843
2896
|
(licenses) => Object.values(licenses).filter((license) => license.project).reduce((accum, license) => ({ ...accum, [license.project]: license }), {})
|
|
2844
2897
|
);
|
|
2845
2898
|
const licenseReducer = licenseSlice.reducer;
|
|
2846
|
-
const initialState$
|
|
2899
|
+
const initialState$c = {
|
|
2847
2900
|
projectAccesses: {}
|
|
2848
2901
|
};
|
|
2849
2902
|
const projectAccessSlice = createSlice({
|
|
2850
2903
|
name: "projectAccess",
|
|
2851
|
-
initialState: initialState$
|
|
2852
|
-
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$
|
|
2904
|
+
initialState: initialState$c,
|
|
2905
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$c)),
|
|
2853
2906
|
reducers: {
|
|
2854
2907
|
setProjectAccesses: (state, action) => {
|
|
2855
2908
|
if (!Array.isArray(action.payload))
|
|
@@ -2917,7 +2970,7 @@ const selectProjectAccessUserMapping = (state) => {
|
|
|
2917
2970
|
return projectAccesses;
|
|
2918
2971
|
};
|
|
2919
2972
|
const projectAccessReducer = projectAccessSlice.reducer;
|
|
2920
|
-
const initialState$
|
|
2973
|
+
const initialState$b = {
|
|
2921
2974
|
projects: {},
|
|
2922
2975
|
activeProjectId: null,
|
|
2923
2976
|
recentProjectIds: [],
|
|
@@ -2927,7 +2980,7 @@ const initialState$9 = {
|
|
|
2927
2980
|
};
|
|
2928
2981
|
const projectSlice = createSlice({
|
|
2929
2982
|
name: "projects",
|
|
2930
|
-
initialState: initialState$
|
|
2983
|
+
initialState: initialState$b,
|
|
2931
2984
|
reducers: {
|
|
2932
2985
|
setProjects: (state, action) => {
|
|
2933
2986
|
const projectsMap = {};
|
|
@@ -2995,11 +3048,13 @@ const projectSlice = createSlice({
|
|
|
2995
3048
|
throw new Error("Update form submissions count: no active project");
|
|
2996
3049
|
}
|
|
2997
3050
|
},
|
|
2998
|
-
//
|
|
3051
|
+
// Attachments
|
|
3052
|
+
setProjectAttachment: setAttachment,
|
|
2999
3053
|
setProjectAttachments: setAttachments,
|
|
3000
3054
|
addProjectAttachment: addAttachment,
|
|
3001
3055
|
addProjectAttachments: addAttachments,
|
|
3002
3056
|
updateProjectAttachment: updateAttachment,
|
|
3057
|
+
updateProjectAttachments: updateAttachments,
|
|
3003
3058
|
removeProjectAttachment: removeAttachment,
|
|
3004
3059
|
removeProjectAttachments: removeAttachments
|
|
3005
3060
|
}
|
|
@@ -3014,11 +3069,13 @@ const {
|
|
|
3014
3069
|
acceptProjectInvite,
|
|
3015
3070
|
addActiveProjectIssuesCount,
|
|
3016
3071
|
addActiveProjectFormSubmissionsCount,
|
|
3017
|
-
//
|
|
3072
|
+
// Attachments
|
|
3073
|
+
setProjectAttachment,
|
|
3018
3074
|
setProjectAttachments,
|
|
3019
3075
|
addProjectAttachment,
|
|
3020
3076
|
addProjectAttachments,
|
|
3021
3077
|
updateProjectAttachment,
|
|
3078
|
+
updateProjectAttachments,
|
|
3022
3079
|
removeProjectAttachment,
|
|
3023
3080
|
removeProjectAttachments
|
|
3024
3081
|
} = projectSlice.actions;
|
|
@@ -3089,6 +3146,9 @@ const selectAllProjectAttachments = createSelector(
|
|
|
3089
3146
|
[selectProjectAttachmentMapping],
|
|
3090
3147
|
(mapping) => Object.values(mapping)
|
|
3091
3148
|
);
|
|
3149
|
+
const selectProjectAttachment = (attachmentId) => (state) => {
|
|
3150
|
+
return state.projectReducer.attachments[attachmentId];
|
|
3151
|
+
};
|
|
3092
3152
|
const selectAttachmentsOfProject = restructureCreateSelectorWithArgs(
|
|
3093
3153
|
createSelector(
|
|
3094
3154
|
[selectAllProjectAttachments, (_state, projectId) => projectId],
|
|
@@ -3114,14 +3174,14 @@ const selectAttachmentsOfProjectByType = restructureCreateSelectorWithArgs(
|
|
|
3114
3174
|
}
|
|
3115
3175
|
)
|
|
3116
3176
|
);
|
|
3117
|
-
const initialState$
|
|
3177
|
+
const initialState$a = {
|
|
3118
3178
|
organizations: {},
|
|
3119
3179
|
activeOrganizationId: null
|
|
3120
3180
|
};
|
|
3121
3181
|
const organizationSlice = createSlice({
|
|
3122
3182
|
name: "organizations",
|
|
3123
|
-
initialState: initialState$
|
|
3124
|
-
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$
|
|
3183
|
+
initialState: initialState$a,
|
|
3184
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
|
|
3125
3185
|
reducers: {
|
|
3126
3186
|
setOrganizations: (state, action) => {
|
|
3127
3187
|
for (const org of action.payload) {
|
|
@@ -3240,14 +3300,14 @@ const createOfflineAction = (request2, baseUrl) => {
|
|
|
3240
3300
|
}
|
|
3241
3301
|
};
|
|
3242
3302
|
};
|
|
3243
|
-
const initialState$
|
|
3303
|
+
const initialState$9 = {
|
|
3244
3304
|
deletedRequests: [],
|
|
3245
3305
|
latestRetryTime: 0
|
|
3246
3306
|
};
|
|
3247
3307
|
const outboxSlice = createSlice({
|
|
3248
3308
|
name: "outbox",
|
|
3249
|
-
initialState: initialState$
|
|
3250
|
-
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$
|
|
3309
|
+
initialState: initialState$9,
|
|
3310
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$9)),
|
|
3251
3311
|
reducers: {
|
|
3252
3312
|
// enqueueActions is a reducer that does nothing but enqueue API request to the Redux Offline outbox
|
|
3253
3313
|
// Whenever an issue is being created, a reducer addIssue() is responsible for adding it to the offline store
|
|
@@ -3279,7 +3339,7 @@ const selectDeletedRequests = (state) => state.outboxReducer.deletedRequests;
|
|
|
3279
3339
|
const selectLatestRetryTime = (state) => state.outboxReducer.latestRetryTime;
|
|
3280
3340
|
const { enqueueRequest, markForDeletion, markAsDeleted, _setLatestRetryTime } = outboxSlice.actions;
|
|
3281
3341
|
const outboxReducer = outboxSlice.reducer;
|
|
3282
|
-
const initialState$
|
|
3342
|
+
const initialState$8 = {
|
|
3283
3343
|
projectFiles: {},
|
|
3284
3344
|
activeProjectFileId: null,
|
|
3285
3345
|
isImportingProjectFile: false,
|
|
@@ -3287,8 +3347,8 @@ const initialState$6 = {
|
|
|
3287
3347
|
};
|
|
3288
3348
|
const projectFileSlice = createSlice({
|
|
3289
3349
|
name: "projectFiles",
|
|
3290
|
-
initialState: initialState$
|
|
3291
|
-
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$
|
|
3350
|
+
initialState: initialState$8,
|
|
3351
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$8)),
|
|
3292
3352
|
reducers: {
|
|
3293
3353
|
addOrReplaceProjectFiles: (state, action) => {
|
|
3294
3354
|
for (let fileObj of action.payload) {
|
|
@@ -3389,12 +3449,12 @@ const selectProjectFiles = createSelector(
|
|
|
3389
3449
|
const selectActiveProjectFileId = (state) => state.projectFileReducer.activeProjectFileId;
|
|
3390
3450
|
const selectIsImportingProjectFile = (state) => state.projectFileReducer.isImportingProjectFile;
|
|
3391
3451
|
const projectFileReducer = projectFileSlice.reducer;
|
|
3392
|
-
const initialState$
|
|
3452
|
+
const initialState$7 = {
|
|
3393
3453
|
isRehydrated: false
|
|
3394
3454
|
};
|
|
3395
3455
|
const rehydratedSlice = createSlice({
|
|
3396
3456
|
name: "rehydrated",
|
|
3397
|
-
initialState: initialState$
|
|
3457
|
+
initialState: initialState$7,
|
|
3398
3458
|
// The `reducers` field lets us define reducers and generate associated actions
|
|
3399
3459
|
reducers: {
|
|
3400
3460
|
setRehydrated: (state, action) => {
|
|
@@ -3404,7 +3464,7 @@ const rehydratedSlice = createSlice({
|
|
|
3404
3464
|
});
|
|
3405
3465
|
const selectRehydrated = (state) => state.rehydratedReducer.isRehydrated;
|
|
3406
3466
|
const rehydratedReducer = rehydratedSlice.reducer;
|
|
3407
|
-
const initialState$
|
|
3467
|
+
const initialState$6 = {
|
|
3408
3468
|
useIssueTemplate: false,
|
|
3409
3469
|
placementMode: false,
|
|
3410
3470
|
enableClustering: false,
|
|
@@ -3421,8 +3481,8 @@ const initialState$4 = {
|
|
|
3421
3481
|
};
|
|
3422
3482
|
const settingSlice = createSlice({
|
|
3423
3483
|
name: "settings",
|
|
3424
|
-
initialState: initialState$
|
|
3425
|
-
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$
|
|
3484
|
+
initialState: initialState$6,
|
|
3485
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$6)),
|
|
3426
3486
|
reducers: {
|
|
3427
3487
|
setEnableDuplicateIssues: (state, action) => {
|
|
3428
3488
|
state.useIssueTemplate = action.payload;
|
|
@@ -3468,146 +3528,231 @@ const selectAppearance = (state) => state.settingReducer.appearance;
|
|
|
3468
3528
|
const settingReducer = settingSlice.reducer;
|
|
3469
3529
|
const selectIsFetchingInitialData = (state) => state.settingReducer.isFetchingInitialData;
|
|
3470
3530
|
const selectIsLoading = (state) => state.settingReducer.isLoading;
|
|
3471
|
-
const
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
if (
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
return;
|
|
3483
|
-
}
|
|
3484
|
-
if (revision.revision === "Pending") {
|
|
3485
|
-
if (preferPending) {
|
|
3486
|
-
LATEST_REVISION_CACHE[revision.form] = revision;
|
|
3487
|
-
}
|
|
3488
|
-
return;
|
|
3489
|
-
}
|
|
3490
|
-
const cachedRevision = (_a2 = LATEST_REVISION_CACHE[revision.form]) == null ? void 0 : _a2.revision;
|
|
3491
|
-
if (revision.revision > (typeof cachedRevision === "number" ? cachedRevision : -1)) {
|
|
3492
|
-
LATEST_REVISION_CACHE[revision.form] = revision;
|
|
3531
|
+
const formRevisionSortFn = (formRevisionA, formRevisionB) => {
|
|
3532
|
+
const revisionA = formRevisionA.revision;
|
|
3533
|
+
const revisionB = formRevisionB.revision;
|
|
3534
|
+
if (revisionA === "Pending" && revisionB === "Pending") {
|
|
3535
|
+
return formRevisionA.submitted_at < formRevisionB.submitted_at ? -1 : 1;
|
|
3536
|
+
} else if (revisionA === "Pending") {
|
|
3537
|
+
return 1;
|
|
3538
|
+
} else if (revisionB === "Pending") {
|
|
3539
|
+
return -1;
|
|
3540
|
+
} else {
|
|
3541
|
+
return revisionA < revisionB ? -1 : 1;
|
|
3493
3542
|
}
|
|
3494
|
-
}
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
}
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
revisionAttachments: {}
|
|
3504
|
-
};
|
|
3505
|
-
const userFormSlice = createSlice({
|
|
3506
|
-
name: "userForms",
|
|
3507
|
-
initialState: initialState$3,
|
|
3508
|
-
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$3)),
|
|
3543
|
+
};
|
|
3544
|
+
const initialState$5 = {
|
|
3545
|
+
formRevisions: {},
|
|
3546
|
+
attachments: {}
|
|
3547
|
+
};
|
|
3548
|
+
const formRevisionsSlice = createSlice({
|
|
3549
|
+
name: "formRevisions",
|
|
3550
|
+
initialState: initialState$5,
|
|
3551
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$5)),
|
|
3509
3552
|
reducers: {
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
action.payload.
|
|
3513
|
-
state.userForms[userForm.offline_id] = userForm;
|
|
3514
|
-
});
|
|
3515
|
-
},
|
|
3516
|
-
addUserForm: (state, action) => {
|
|
3517
|
-
state.userForms[action.payload.offline_id] = action.payload;
|
|
3518
|
-
},
|
|
3519
|
-
addUserForms: (state, action) => {
|
|
3520
|
-
action.payload.forEach((userForm) => {
|
|
3521
|
-
state.userForms[userForm.offline_id] = userForm;
|
|
3522
|
-
});
|
|
3523
|
-
},
|
|
3524
|
-
addUserFormRevisions: (state, action) => {
|
|
3525
|
-
action.payload.forEach((userFormRevision) => {
|
|
3526
|
-
state.revisions[userFormRevision.offline_id] = userFormRevision;
|
|
3527
|
-
considerCachingRevision(userFormRevision);
|
|
3528
|
-
});
|
|
3553
|
+
// revision related actions
|
|
3554
|
+
setFormRevision: (state, action) => {
|
|
3555
|
+
state.formRevisions[action.payload.offline_id] = action.payload;
|
|
3529
3556
|
},
|
|
3530
|
-
|
|
3531
|
-
state.
|
|
3532
|
-
|
|
3557
|
+
setFormRevisions: (state, action) => {
|
|
3558
|
+
state.formRevisions = {};
|
|
3559
|
+
for (const revision of action.payload) {
|
|
3560
|
+
state.formRevisions[revision.offline_id] = revision;
|
|
3561
|
+
}
|
|
3533
3562
|
},
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3563
|
+
addFormRevision: (state, action) => {
|
|
3564
|
+
if (state.formRevisions[action.payload.offline_id] !== void 0) {
|
|
3565
|
+
throw new Error(`Revision with offline_id ${action.payload.offline_id} already exists`);
|
|
3566
|
+
}
|
|
3567
|
+
state.formRevisions[action.payload.offline_id] = action.payload;
|
|
3537
3568
|
},
|
|
3538
|
-
|
|
3569
|
+
addFormRevisions: (state, action) => {
|
|
3539
3570
|
for (const userFormRevision of action.payload) {
|
|
3540
|
-
|
|
3541
|
-
|
|
3571
|
+
if (state.formRevisions[userFormRevision.offline_id] !== void 0) {
|
|
3572
|
+
throw new Error(`Revision with offline_id ${userFormRevision.offline_id} already exists`);
|
|
3573
|
+
}
|
|
3542
3574
|
}
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
state.submissions[action.payload.offline_id] = action.payload;
|
|
3546
|
-
},
|
|
3547
|
-
addUserFormSubmissionAttachment: (state, action) => {
|
|
3548
|
-
const submissionId = action.payload.submission;
|
|
3549
|
-
const submissionAttachments = state.submissionAttachments[submissionId];
|
|
3550
|
-
if (submissionAttachments) {
|
|
3551
|
-
submissionAttachments.push(action.payload);
|
|
3552
|
-
} else {
|
|
3553
|
-
state.submissionAttachments[submissionId] = [action.payload];
|
|
3575
|
+
for (const userFormRevision of action.payload) {
|
|
3576
|
+
state.formRevisions[userFormRevision.offline_id] = userFormRevision;
|
|
3554
3577
|
}
|
|
3555
3578
|
},
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
revisionAttachments.push(action.payload);
|
|
3561
|
-
} else {
|
|
3562
|
-
state.revisionAttachments[revisionId] = [action.payload];
|
|
3579
|
+
// UserFormRevisions do not get updated
|
|
3580
|
+
deleteFormRevision: (state, action) => {
|
|
3581
|
+
if (state.formRevisions[action.payload] === void 0) {
|
|
3582
|
+
throw new Error(`Revision with offline_id ${action.payload} does not exist`);
|
|
3563
3583
|
}
|
|
3584
|
+
delete state.formRevisions[action.payload];
|
|
3564
3585
|
},
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
const submissionAttachments = state.submissionAttachments[submissionId];
|
|
3570
|
-
if (submissionAttachments) {
|
|
3571
|
-
submissionAttachments.push(attachment);
|
|
3572
|
-
} else {
|
|
3573
|
-
state.submissionAttachments[submissionId] = [attachment];
|
|
3586
|
+
deleteFormRevisions: (state, action) => {
|
|
3587
|
+
for (const offlineId of action.payload) {
|
|
3588
|
+
if (state.formRevisions[offlineId] === void 0) {
|
|
3589
|
+
throw new Error(`Revision with offline_id ${offlineId} does not exist`);
|
|
3574
3590
|
}
|
|
3575
3591
|
}
|
|
3592
|
+
for (const offlineId of action.payload) {
|
|
3593
|
+
delete state.formRevisions[offlineId];
|
|
3594
|
+
}
|
|
3576
3595
|
},
|
|
3577
|
-
|
|
3578
|
-
|
|
3596
|
+
// attachment related actions
|
|
3597
|
+
setFormRevisionAttachments: (state, action) => {
|
|
3598
|
+
state.attachments = {};
|
|
3579
3599
|
for (const attachment of action.payload) {
|
|
3580
|
-
|
|
3581
|
-
const revisionAttachments = state.revisionAttachments[revisionId];
|
|
3582
|
-
if (revisionAttachments) {
|
|
3583
|
-
revisionAttachments.push(attachment);
|
|
3584
|
-
} else {
|
|
3585
|
-
state.revisionAttachments[revisionId] = [attachment];
|
|
3586
|
-
}
|
|
3600
|
+
state.attachments[attachment.offline_id] = attachment;
|
|
3587
3601
|
}
|
|
3588
3602
|
},
|
|
3589
|
-
|
|
3590
|
-
|
|
3603
|
+
addFormRevisionAttachment: (state, action) => {
|
|
3604
|
+
if (state.attachments[action.payload.offline_id] !== void 0) {
|
|
3605
|
+
throw new Error(`Attachment with offline_id ${action.payload.offline_id} already exists`);
|
|
3606
|
+
}
|
|
3607
|
+
state.attachments[action.payload.offline_id] = action.payload;
|
|
3591
3608
|
},
|
|
3592
|
-
|
|
3593
|
-
for (const
|
|
3594
|
-
|
|
3609
|
+
addFormRevisionAttachments: (state, action) => {
|
|
3610
|
+
for (const attachment of action.payload) {
|
|
3611
|
+
if (state.attachments[attachment.offline_id] !== void 0) {
|
|
3612
|
+
throw new Error(`Attachment with offline_id ${attachment.offline_id} already exists`);
|
|
3613
|
+
}
|
|
3614
|
+
}
|
|
3615
|
+
for (const attachment of action.payload) {
|
|
3616
|
+
state.attachments[attachment.offline_id] = attachment;
|
|
3595
3617
|
}
|
|
3596
3618
|
},
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3619
|
+
deleteFormRevisionAttachment: (state, action) => {
|
|
3620
|
+
if (state.attachments[action.payload] === void 0) {
|
|
3621
|
+
throw new Error(`Attachment with offline_id ${action.payload} does not exist`);
|
|
3600
3622
|
}
|
|
3623
|
+
delete state.attachments[action.payload];
|
|
3601
3624
|
},
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3625
|
+
deleteFormRevisionAttachments: (state, action) => {
|
|
3626
|
+
for (const offlineId of action.payload) {
|
|
3627
|
+
if (state.attachments[offlineId] === void 0) {
|
|
3628
|
+
throw new Error(`Attachment with offline_id ${offlineId} does not exist`);
|
|
3629
|
+
}
|
|
3630
|
+
}
|
|
3631
|
+
for (const offlineId of action.payload) {
|
|
3632
|
+
delete state.attachments[offlineId];
|
|
3633
|
+
}
|
|
3634
|
+
}
|
|
3635
|
+
}
|
|
3636
|
+
});
|
|
3637
|
+
const {
|
|
3638
|
+
setFormRevision,
|
|
3639
|
+
setFormRevisions,
|
|
3640
|
+
addFormRevision,
|
|
3641
|
+
addFormRevisions,
|
|
3642
|
+
deleteFormRevision,
|
|
3643
|
+
deleteFormRevisions,
|
|
3644
|
+
setFormRevisionAttachments,
|
|
3645
|
+
addFormRevisionAttachment,
|
|
3646
|
+
addFormRevisionAttachments,
|
|
3647
|
+
deleteFormRevisionAttachment,
|
|
3648
|
+
deleteFormRevisionAttachments
|
|
3649
|
+
} = formRevisionsSlice.actions;
|
|
3650
|
+
const selectFormRevisionMapping = (state) => state.formRevisionReducer.formRevisions;
|
|
3651
|
+
const selectFormRevisions = createSelector(
|
|
3652
|
+
[selectFormRevisionMapping],
|
|
3653
|
+
(formRevisions) => Object.values(formRevisions)
|
|
3654
|
+
);
|
|
3655
|
+
const selectFormRevision = (formRevisionId) => (state) => {
|
|
3656
|
+
return state.formRevisionReducer.formRevisions[formRevisionId];
|
|
3657
|
+
};
|
|
3658
|
+
const _selectLatestFormRevision = (formRevisions, formId2) => {
|
|
3659
|
+
let ret = null;
|
|
3660
|
+
for (const candidate of Object.values(formRevisions)) {
|
|
3661
|
+
if (candidate.form === formId2 && (!ret || ret.revision < candidate.revision)) {
|
|
3662
|
+
ret = candidate;
|
|
3663
|
+
}
|
|
3664
|
+
}
|
|
3665
|
+
if (!ret) {
|
|
3666
|
+
throw new Error("No form revision found for form " + formId2);
|
|
3667
|
+
}
|
|
3668
|
+
return ret;
|
|
3669
|
+
};
|
|
3670
|
+
const selectLatestFormRevisionOfForm = restructureCreateSelectorWithArgs(
|
|
3671
|
+
createSelector([selectFormRevisions, (_state, formId2) => formId2], (revisions, formId2) => {
|
|
3672
|
+
return revisions.filter((revision) => revision.form === formId2).sort(formRevisionSortFn).pop();
|
|
3673
|
+
})
|
|
3674
|
+
);
|
|
3675
|
+
const selectFormRevisionsOfForm = restructureCreateSelectorWithArgs(
|
|
3676
|
+
createSelector([selectFormRevisions, (_state, formId2) => formId2], (revisions, formId2) => {
|
|
3677
|
+
return revisions.filter((revision) => {
|
|
3678
|
+
return revision.form === formId2;
|
|
3679
|
+
});
|
|
3680
|
+
})
|
|
3681
|
+
);
|
|
3682
|
+
const selectLatestFormRevisionsOfComponentTypes = restructureCreateSelectorWithArgs(
|
|
3683
|
+
createSelector(
|
|
3684
|
+
[
|
|
3685
|
+
(state) => state.formReducer.forms,
|
|
3686
|
+
selectFormRevisionMapping,
|
|
3687
|
+
(_state, componentTypeIds) => componentTypeIds
|
|
3688
|
+
],
|
|
3689
|
+
(userForms, revisions, componentTypeIds) => {
|
|
3690
|
+
const componentTypeIdsSet = new Set(componentTypeIds);
|
|
3691
|
+
const formsOfComponentTypes = {};
|
|
3692
|
+
const ret = {};
|
|
3693
|
+
for (const form of Object.values(userForms)) {
|
|
3694
|
+
if (form.component_type && componentTypeIdsSet.has(form.component_type)) {
|
|
3695
|
+
formsOfComponentTypes[form.offline_id] = form;
|
|
3696
|
+
}
|
|
3697
|
+
}
|
|
3698
|
+
for (const revision of Object.values(revisions)) {
|
|
3699
|
+
const form = formsOfComponentTypes[revision.form];
|
|
3700
|
+
if (!form || !form.component_type || ret[form.component_type] && formRevisionSortFn(ret[form.component_type], revision) > 0)
|
|
3701
|
+
continue;
|
|
3702
|
+
ret[form.component_type] = revision;
|
|
3703
|
+
}
|
|
3704
|
+
return ret;
|
|
3705
|
+
}
|
|
3706
|
+
)
|
|
3707
|
+
);
|
|
3708
|
+
const selectLatestFormRevisionByForm = createSelector([selectFormRevisionMapping], (revisions) => {
|
|
3709
|
+
const latestRevisions = {};
|
|
3710
|
+
for (const revision of Object.values(revisions)) {
|
|
3711
|
+
const formId2 = revision.form;
|
|
3712
|
+
const currentLatestRevision = latestRevisions[formId2];
|
|
3713
|
+
if (!currentLatestRevision || currentLatestRevision.revision < revision.revision) {
|
|
3714
|
+
latestRevisions[formId2] = revision;
|
|
3715
|
+
}
|
|
3716
|
+
}
|
|
3717
|
+
return latestRevisions;
|
|
3718
|
+
});
|
|
3719
|
+
const selectUserFormRevisionAttachmentsMapping = (state) => {
|
|
3720
|
+
return state.formRevisionReducer.attachments;
|
|
3721
|
+
};
|
|
3722
|
+
const selectAttachmentsOfFormRevision = restructureCreateSelectorWithArgs(
|
|
3723
|
+
createSelector(
|
|
3724
|
+
[selectUserFormRevisionAttachmentsMapping, (_state, revisionId) => revisionId],
|
|
3725
|
+
(attachments, revisionId) => {
|
|
3726
|
+
return Object.values(attachments).filter((attachment) => attachment.revision === revisionId);
|
|
3727
|
+
}
|
|
3728
|
+
)
|
|
3729
|
+
);
|
|
3730
|
+
const formRevisionReducer = formRevisionsSlice.reducer;
|
|
3731
|
+
const initialState$4 = {
|
|
3732
|
+
forms: {}
|
|
3733
|
+
};
|
|
3734
|
+
const formSlice = createSlice({
|
|
3735
|
+
name: "forms",
|
|
3736
|
+
initialState: initialState$4,
|
|
3737
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$4)),
|
|
3738
|
+
reducers: {
|
|
3739
|
+
setForms: (state, action) => {
|
|
3740
|
+
state.forms = {};
|
|
3741
|
+
action.payload.forEach((userForm) => {
|
|
3742
|
+
state.forms[userForm.offline_id] = userForm;
|
|
3606
3743
|
});
|
|
3607
3744
|
},
|
|
3745
|
+
addForm: (state, action) => {
|
|
3746
|
+
state.forms[action.payload.offline_id] = action.payload;
|
|
3747
|
+
},
|
|
3748
|
+
addForms: (state, action) => {
|
|
3749
|
+
for (const userForm of action.payload) {
|
|
3750
|
+
state.forms[userForm.offline_id] = userForm;
|
|
3751
|
+
}
|
|
3752
|
+
},
|
|
3608
3753
|
favoriteForm: (state, action) => {
|
|
3609
3754
|
const { formId: formId2 } = action.payload;
|
|
3610
|
-
const form = state.
|
|
3755
|
+
const form = state.forms[formId2];
|
|
3611
3756
|
if (!form) {
|
|
3612
3757
|
throw new Error("No form exists with the id " + formId2);
|
|
3613
3758
|
}
|
|
@@ -3615,48 +3760,23 @@ const userFormSlice = createSlice({
|
|
|
3615
3760
|
},
|
|
3616
3761
|
unfavoriteForm: (state, action) => {
|
|
3617
3762
|
const { formId: formId2 } = action.payload;
|
|
3618
|
-
const form = state.
|
|
3763
|
+
const form = state.forms[formId2];
|
|
3619
3764
|
if (!form) {
|
|
3620
3765
|
throw new Error("No form exists with the id " + formId2);
|
|
3621
3766
|
}
|
|
3622
3767
|
form.favorite = false;
|
|
3623
3768
|
},
|
|
3624
|
-
|
|
3625
|
-
delete state.
|
|
3769
|
+
deleteForm: (state, action) => {
|
|
3770
|
+
delete state.forms[action.payload];
|
|
3626
3771
|
}
|
|
3627
3772
|
}
|
|
3628
3773
|
});
|
|
3629
|
-
const {
|
|
3630
|
-
|
|
3631
|
-
addUserForms,
|
|
3632
|
-
addUserFormRevisions,
|
|
3633
|
-
updateOrCreateUserFormSubmission,
|
|
3634
|
-
addUserFormSubmissions,
|
|
3635
|
-
deleteUserFormSubmission,
|
|
3636
|
-
deleteUserFormSubmissions,
|
|
3637
|
-
favoriteForm,
|
|
3638
|
-
unfavoriteForm,
|
|
3639
|
-
deleteUserForm,
|
|
3640
|
-
deleteUserFormRevision,
|
|
3641
|
-
deleteUserFormRevisions,
|
|
3642
|
-
setUserFormSubmissions,
|
|
3643
|
-
addUserFormRevision,
|
|
3644
|
-
addUserFormSubmissionAttachment,
|
|
3645
|
-
addUserFormRevisionAttachment,
|
|
3646
|
-
setUserFormSubmissionAttachments,
|
|
3647
|
-
setUserFormRevisionAttachments
|
|
3648
|
-
} = userFormSlice.actions;
|
|
3649
|
-
const selectSubmissionAttachments = (submissionId) => (state) => {
|
|
3650
|
-
return state.userFormReducer.submissionAttachments[submissionId] || [];
|
|
3651
|
-
};
|
|
3652
|
-
const selectRevisionAttachments = (revisionId) => (state) => {
|
|
3653
|
-
return state.userFormReducer.revisionAttachments[revisionId] || [];
|
|
3654
|
-
};
|
|
3655
|
-
const selectFilteredUserForms = restructureCreateSelectorWithArgs(
|
|
3774
|
+
const { setForms, addForm, addForms, favoriteForm, unfavoriteForm, deleteForm } = formSlice.actions;
|
|
3775
|
+
const selectFilteredForms = restructureCreateSelectorWithArgs(
|
|
3656
3776
|
createSelector(
|
|
3657
3777
|
[
|
|
3658
|
-
(state) => state.
|
|
3659
|
-
(state) => state.
|
|
3778
|
+
(state) => state.formReducer.forms,
|
|
3779
|
+
(state) => state.formRevisionReducer.formRevisions,
|
|
3660
3780
|
(_state, search) => search
|
|
3661
3781
|
],
|
|
3662
3782
|
(userForms, revisions, search) => {
|
|
@@ -3683,70 +3803,195 @@ const selectFilteredUserForms = restructureCreateSelectorWithArgs(
|
|
|
3683
3803
|
break;
|
|
3684
3804
|
}
|
|
3685
3805
|
}
|
|
3686
|
-
const maxRegularMatches = maxResults - favoriteMatches.length;
|
|
3687
|
-
return [...favoriteMatches, ...regularMatches.slice(0, maxRegularMatches)];
|
|
3806
|
+
const maxRegularMatches = maxResults - favoriteMatches.length;
|
|
3807
|
+
return [...favoriteMatches, ...regularMatches.slice(0, maxRegularMatches)];
|
|
3808
|
+
},
|
|
3809
|
+
// as the argument is an object, we check the first level of properties for equality
|
|
3810
|
+
{ memoizeOptions: { equalityCheck: shallowEqual$1 } }
|
|
3811
|
+
)
|
|
3812
|
+
);
|
|
3813
|
+
const selectForm = (formId2) => (state) => {
|
|
3814
|
+
return state.formReducer.forms[formId2];
|
|
3815
|
+
};
|
|
3816
|
+
const selectFormMapping = (state) => {
|
|
3817
|
+
return state.formReducer.forms;
|
|
3818
|
+
};
|
|
3819
|
+
const selectFormOfComponentType = restructureCreateSelectorWithArgs(
|
|
3820
|
+
createSelector(
|
|
3821
|
+
[selectFormMapping, (_state, componentTypeId) => componentTypeId],
|
|
3822
|
+
(userForms, componentTypeId) => {
|
|
3823
|
+
return Object.values(userForms).find((userForm) => userForm.component_type === componentTypeId);
|
|
3824
|
+
}
|
|
3825
|
+
)
|
|
3826
|
+
);
|
|
3827
|
+
const selectFormsCount = createSelector([selectFormMapping], (userForms) => {
|
|
3828
|
+
return Object.keys(userForms).length;
|
|
3829
|
+
});
|
|
3830
|
+
const selectGeneralFormCount = createSelector([selectFormMapping], (userForms) => {
|
|
3831
|
+
return Object.values(userForms).filter((form) => !form.component_type).length;
|
|
3832
|
+
});
|
|
3833
|
+
const formReducer = formSlice.reducer;
|
|
3834
|
+
const initialState$3 = {
|
|
3835
|
+
formSubmissions: {},
|
|
3836
|
+
attachments: {}
|
|
3837
|
+
};
|
|
3838
|
+
const formSubmissionSlice = createSlice({
|
|
3839
|
+
name: "formSubmissions",
|
|
3840
|
+
initialState: initialState$3,
|
|
3841
|
+
extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$3)),
|
|
3842
|
+
reducers: {
|
|
3843
|
+
setFormSubmission: (state, action) => {
|
|
3844
|
+
state.formSubmissions[action.payload.offline_id] = action.payload;
|
|
3845
|
+
},
|
|
3846
|
+
setFormSubmissions: (state, action) => {
|
|
3847
|
+
state.formSubmissions = {};
|
|
3848
|
+
for (const submission of action.payload) {
|
|
3849
|
+
state.formSubmissions[submission.offline_id] = submission;
|
|
3850
|
+
}
|
|
3851
|
+
},
|
|
3852
|
+
addFormSubmission: (state, action) => {
|
|
3853
|
+
if (action.payload.offline_id in state.formSubmissions) {
|
|
3854
|
+
throw new Error(`Submission with offline_id ${action.payload.offline_id} already exists`);
|
|
3855
|
+
}
|
|
3856
|
+
state.formSubmissions[action.payload.offline_id] = action.payload;
|
|
3857
|
+
},
|
|
3858
|
+
addFormSubmissions: (state, action) => {
|
|
3859
|
+
for (const submission of action.payload) {
|
|
3860
|
+
if (state.formSubmissions[submission.offline_id] !== void 0) {
|
|
3861
|
+
throw new Error(`Submission with offline_id ${submission.offline_id} already exists`);
|
|
3862
|
+
}
|
|
3863
|
+
}
|
|
3864
|
+
for (const submission of action.payload) {
|
|
3865
|
+
state.formSubmissions[submission.offline_id] = submission;
|
|
3866
|
+
}
|
|
3867
|
+
},
|
|
3868
|
+
updateFormSubmission: (state, action) => {
|
|
3869
|
+
if (state.formSubmissions[action.payload.offline_id] === void 0) {
|
|
3870
|
+
throw new Error(`Submission with offline_id ${action.payload.offline_id} does not exist`);
|
|
3871
|
+
}
|
|
3872
|
+
state.formSubmissions[action.payload.offline_id] = action.payload;
|
|
3873
|
+
},
|
|
3874
|
+
updateFormSubmissions: (state, action) => {
|
|
3875
|
+
for (const submission of action.payload) {
|
|
3876
|
+
if (state.formSubmissions[submission.offline_id] === void 0) {
|
|
3877
|
+
throw new Error(`Submission with offline_id ${submission.offline_id} does not exist`);
|
|
3878
|
+
}
|
|
3879
|
+
}
|
|
3880
|
+
for (const submission of action.payload) {
|
|
3881
|
+
state.formSubmissions[submission.offline_id] = submission;
|
|
3882
|
+
}
|
|
3883
|
+
},
|
|
3884
|
+
deleteFormSubmission: (state, action) => {
|
|
3885
|
+
if (state.formSubmissions[action.payload] === void 0) {
|
|
3886
|
+
throw new Error(`Submission with offline_id ${action.payload} does not exist`);
|
|
3887
|
+
}
|
|
3888
|
+
delete state.formSubmissions[action.payload];
|
|
3889
|
+
},
|
|
3890
|
+
deleteFormSubmissions: (state, action) => {
|
|
3891
|
+
for (const offlineId of action.payload) {
|
|
3892
|
+
if (state.formSubmissions[offlineId] === void 0) {
|
|
3893
|
+
throw new Error(`Submission with offline_id ${offlineId} does not exist`);
|
|
3894
|
+
}
|
|
3895
|
+
delete state.formSubmissions[offlineId];
|
|
3896
|
+
}
|
|
3897
|
+
for (const offlineId of action.payload) {
|
|
3898
|
+
delete state.formSubmissions[offlineId];
|
|
3899
|
+
}
|
|
3900
|
+
},
|
|
3901
|
+
// Attachments
|
|
3902
|
+
addFormSubmissionAttachment: (state, action) => {
|
|
3903
|
+
if (state.attachments[action.payload.offline_id] !== void 0) {
|
|
3904
|
+
throw new Error(`Attachment with offline_id ${action.payload.offline_id} already exists`);
|
|
3905
|
+
}
|
|
3906
|
+
state.attachments[action.payload.offline_id] = action.payload;
|
|
3907
|
+
},
|
|
3908
|
+
addFormSubmissionAttachments: (state, action) => {
|
|
3909
|
+
for (const attachment of action.payload) {
|
|
3910
|
+
if (state.attachments[attachment.offline_id] !== void 0) {
|
|
3911
|
+
throw new Error(`Attachment with offline_id ${attachment.offline_id} already exists`);
|
|
3912
|
+
}
|
|
3913
|
+
}
|
|
3914
|
+
for (const attachment of action.payload) {
|
|
3915
|
+
state.attachments[attachment.offline_id] = attachment;
|
|
3916
|
+
}
|
|
3917
|
+
},
|
|
3918
|
+
// We only need a multi set for attachments because they are not updated, only added and deleted
|
|
3919
|
+
setFormSubmissionAttachments: (state, action) => {
|
|
3920
|
+
state.attachments = {};
|
|
3921
|
+
for (const attachment of action.payload) {
|
|
3922
|
+
state.attachments[attachment.offline_id] = attachment;
|
|
3923
|
+
}
|
|
3924
|
+
},
|
|
3925
|
+
updateFormSubmissionAttachments: (state, action) => {
|
|
3926
|
+
for (const attachment of action.payload) {
|
|
3927
|
+
if (state.attachments[attachment.offline_id] === void 0) {
|
|
3928
|
+
throw new Error(`Attachment with offline_id ${attachment.offline_id} does not exist`);
|
|
3929
|
+
}
|
|
3930
|
+
}
|
|
3931
|
+
for (const attachment of action.payload) {
|
|
3932
|
+
state.attachments[attachment.offline_id] = attachment;
|
|
3933
|
+
}
|
|
3688
3934
|
},
|
|
3689
|
-
//
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
)
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3935
|
+
// The delete actions for UserFormSubmissionAttachments are not used in the app, but are included for completeness
|
|
3936
|
+
// Could be used if editing a submission is ever supported, will be applicable for supporting tip tap content in submissions
|
|
3937
|
+
deleteFormSubmissionAttachment: (state, action) => {
|
|
3938
|
+
if (state.attachments[action.payload] === void 0) {
|
|
3939
|
+
throw new Error(`Attachment with offline_id ${action.payload} does not exist`);
|
|
3940
|
+
}
|
|
3941
|
+
delete state.attachments[action.payload];
|
|
3942
|
+
},
|
|
3943
|
+
deleteFormSubmissionAttachments: (state, action) => {
|
|
3944
|
+
for (const offlineId of action.payload) {
|
|
3945
|
+
if (state.attachments[offlineId] === void 0) {
|
|
3946
|
+
throw new Error(`Attachment with offline_id ${offlineId} does not exist`);
|
|
3947
|
+
}
|
|
3948
|
+
delete state.attachments[offlineId];
|
|
3949
|
+
}
|
|
3701
3950
|
}
|
|
3702
3951
|
}
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3952
|
+
});
|
|
3953
|
+
const {
|
|
3954
|
+
setFormSubmission,
|
|
3955
|
+
setFormSubmissions,
|
|
3956
|
+
addFormSubmission,
|
|
3957
|
+
addFormSubmissions,
|
|
3958
|
+
updateFormSubmission,
|
|
3959
|
+
updateFormSubmissions,
|
|
3960
|
+
deleteFormSubmission,
|
|
3961
|
+
deleteFormSubmissions,
|
|
3962
|
+
addFormSubmissionAttachment,
|
|
3963
|
+
addFormSubmissionAttachments,
|
|
3964
|
+
setFormSubmissionAttachments,
|
|
3965
|
+
updateFormSubmissionAttachments,
|
|
3966
|
+
deleteFormSubmissionAttachment,
|
|
3967
|
+
deleteFormSubmissionAttachments
|
|
3968
|
+
} = formSubmissionSlice.actions;
|
|
3969
|
+
const selectFormSubmissionsMapping = (state) => {
|
|
3970
|
+
return state.formSubmissionReducer.formSubmissions;
|
|
3707
3971
|
};
|
|
3708
|
-
const
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
(
|
|
3712
|
-
|
|
3713
|
-
throw new Error("formId is required");
|
|
3714
|
-
}
|
|
3715
|
-
return _selectLatestFormRevision(revisions, formId2);
|
|
3716
|
-
}
|
|
3717
|
-
)
|
|
3718
|
-
);
|
|
3719
|
-
const selectUserForm = (formId2) => (state) => {
|
|
3720
|
-
return state.userFormReducer.userForms[formId2];
|
|
3721
|
-
};
|
|
3722
|
-
const selectSubmissionMapping = (state) => state.userFormReducer.submissions;
|
|
3723
|
-
const selectUserFormSubmission = (submissionId) => (state) => {
|
|
3724
|
-
return state.userFormReducer.submissions[submissionId];
|
|
3725
|
-
};
|
|
3726
|
-
const selectSubmissions = createSelector([selectSubmissionMapping], (submissions) => Object.values(submissions));
|
|
3727
|
-
const selectRevisionMapping = (state) => state.userFormReducer.revisions;
|
|
3728
|
-
const selectRevisions = createSelector([selectRevisionMapping], (revisions) => Object.values(revisions));
|
|
3729
|
-
const selectRevisionsForForm = restructureCreateSelectorWithArgs(
|
|
3730
|
-
createSelector([selectRevisions, (_state, formId2) => formId2], (revisions, formId2) => {
|
|
3731
|
-
return revisions.filter((revision) => {
|
|
3732
|
-
return revision.form === formId2;
|
|
3733
|
-
});
|
|
3734
|
-
})
|
|
3972
|
+
const selectFormSubmissions = createSelector(
|
|
3973
|
+
[selectFormSubmissionsMapping],
|
|
3974
|
+
(submissions) => {
|
|
3975
|
+
return Object.values(submissions);
|
|
3976
|
+
}
|
|
3735
3977
|
);
|
|
3736
|
-
const
|
|
3978
|
+
const selectFormSubmission = (submissionId) => (state) => {
|
|
3979
|
+
return state.formSubmissionReducer.formSubmissions[submissionId];
|
|
3980
|
+
};
|
|
3981
|
+
const selectFormSubmissionsOfForm = restructureCreateSelectorWithArgs(
|
|
3737
3982
|
createSelector(
|
|
3738
|
-
[
|
|
3983
|
+
[selectFormSubmissions, selectFormRevisionMapping, (_state, formId2) => formId2],
|
|
3739
3984
|
(submissions, revisionMapping, formId2) => {
|
|
3740
|
-
return
|
|
3985
|
+
return submissions.filter((submission) => {
|
|
3741
3986
|
const revision = revisionMapping[submission.form_revision];
|
|
3742
3987
|
return (revision == null ? void 0 : revision.form) === formId2;
|
|
3743
3988
|
});
|
|
3744
3989
|
}
|
|
3745
3990
|
)
|
|
3746
3991
|
);
|
|
3747
|
-
const
|
|
3992
|
+
const selectFormSubmissionsOfIssue = restructureCreateSelectorWithArgs(
|
|
3748
3993
|
createSelector(
|
|
3749
|
-
[
|
|
3994
|
+
[selectFormSubmissions, (_state, issueId) => issueId],
|
|
3750
3995
|
(submissions, issueId) => {
|
|
3751
3996
|
return Object.values(submissions).filter((submission) => {
|
|
3752
3997
|
return submission.issue === issueId;
|
|
@@ -3754,9 +3999,9 @@ const selectSubmissionsForIssue = restructureCreateSelectorWithArgs(
|
|
|
3754
3999
|
}
|
|
3755
4000
|
)
|
|
3756
4001
|
);
|
|
3757
|
-
const
|
|
4002
|
+
const selectFormSubmissionsOfComponent = restructureCreateSelectorWithArgs(
|
|
3758
4003
|
createSelector(
|
|
3759
|
-
[
|
|
4004
|
+
[selectFormSubmissions, (_state, componentId) => componentId],
|
|
3760
4005
|
(submissions, componentId) => {
|
|
3761
4006
|
return submissions.filter((submission) => {
|
|
3762
4007
|
return submission.component === componentId;
|
|
@@ -3764,8 +4009,8 @@ const selectSubmissionsForComponent = restructureCreateSelectorWithArgs(
|
|
|
3764
4009
|
}
|
|
3765
4010
|
)
|
|
3766
4011
|
);
|
|
3767
|
-
const
|
|
3768
|
-
[
|
|
4012
|
+
const selectFormSubmissionsByComponents = createSelector(
|
|
4013
|
+
[selectFormSubmissionsMapping, selectComponentsMapping],
|
|
3769
4014
|
(submissions, components) => {
|
|
3770
4015
|
var _a2;
|
|
3771
4016
|
const componentSubmissionMapping = {};
|
|
@@ -3781,54 +4026,18 @@ const selectComponentSubmissionMapping = createSelector(
|
|
|
3781
4026
|
return componentSubmissionMapping;
|
|
3782
4027
|
}
|
|
3783
4028
|
);
|
|
3784
|
-
const
|
|
3785
|
-
return state.
|
|
4029
|
+
const selectFormSubmissionAttachmentsMapping = (state) => {
|
|
4030
|
+
return state.formSubmissionReducer.attachments;
|
|
3786
4031
|
};
|
|
3787
|
-
const
|
|
3788
|
-
createSelector(
|
|
3789
|
-
[selectUserFormMapping, (_state, componentTypeId) => componentTypeId],
|
|
3790
|
-
(userForms, componentTypeId) => {
|
|
3791
|
-
return Object.values(userForms).find((userForm) => userForm.component_type === componentTypeId);
|
|
3792
|
-
}
|
|
3793
|
-
)
|
|
3794
|
-
);
|
|
3795
|
-
const selectLatestRevisionsFromComponentTypeIds = restructureCreateSelectorWithArgs(
|
|
4032
|
+
const selectAttachmentsOfFormSubmission = restructureCreateSelectorWithArgs(
|
|
3796
4033
|
createSelector(
|
|
3797
|
-
[
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
(_state, componentTypeIds) => componentTypeIds
|
|
3801
|
-
],
|
|
3802
|
-
(userForms, revisions, componentTypeIds) => {
|
|
3803
|
-
const componentTypeIdsSet = new Set(componentTypeIds);
|
|
3804
|
-
const ret = {};
|
|
3805
|
-
for (const form of Object.values(userForms)) {
|
|
3806
|
-
if (form.component_type && componentTypeIdsSet.has(form.component_type)) {
|
|
3807
|
-
ret[form.component_type] = _selectLatestFormRevision(revisions, form.offline_id);
|
|
3808
|
-
}
|
|
3809
|
-
}
|
|
3810
|
-
return ret;
|
|
4034
|
+
[selectFormSubmissionAttachmentsMapping, (_state, submissionId) => submissionId],
|
|
4035
|
+
(attachmentsMapping, submissionId) => {
|
|
4036
|
+
return Object.values(attachmentsMapping).filter((attachment) => attachment.submission === submissionId);
|
|
3811
4037
|
}
|
|
3812
4038
|
)
|
|
3813
4039
|
);
|
|
3814
|
-
const
|
|
3815
|
-
const latestRevisions = {};
|
|
3816
|
-
for (const revision of Object.values(revisions)) {
|
|
3817
|
-
const formId2 = revision.form;
|
|
3818
|
-
const currentLatestRevision = latestRevisions[formId2];
|
|
3819
|
-
if (!currentLatestRevision || currentLatestRevision.revision < revision.revision) {
|
|
3820
|
-
latestRevisions[formId2] = revision;
|
|
3821
|
-
}
|
|
3822
|
-
}
|
|
3823
|
-
return latestRevisions;
|
|
3824
|
-
});
|
|
3825
|
-
const selectNumberOfUserForms = createSelector([selectUserFormMapping], (userForms) => {
|
|
3826
|
-
return Object.keys(userForms).length;
|
|
3827
|
-
});
|
|
3828
|
-
const selectNumberOfGeneralUserForms = createSelector([selectUserFormMapping], (userForms) => {
|
|
3829
|
-
return Object.values(userForms).filter((form) => !form.component_type).length;
|
|
3830
|
-
});
|
|
3831
|
-
const userFormReducer = userFormSlice.reducer;
|
|
4040
|
+
const formSubmissionReducer = formSubmissionSlice.reducer;
|
|
3832
4041
|
const initialState$2 = {
|
|
3833
4042
|
emailDomains: {}
|
|
3834
4043
|
};
|
|
@@ -4001,10 +4210,13 @@ const documentSlice = createSlice({
|
|
|
4001
4210
|
delete state.documents[documentId];
|
|
4002
4211
|
}
|
|
4003
4212
|
},
|
|
4213
|
+
// Attachments
|
|
4214
|
+
setDocumentAttachment: setAttachment,
|
|
4004
4215
|
setDocumentAttachments: setAttachments,
|
|
4005
4216
|
addDocumentAttachment: addAttachment,
|
|
4006
4217
|
addDocumentAttachments: addAttachments,
|
|
4007
4218
|
updateDocumentAttachment: updateAttachment,
|
|
4219
|
+
updateDocumentAttachments: updateAttachments,
|
|
4008
4220
|
removeDocumentAttachment: removeAttachment,
|
|
4009
4221
|
removeDocumentAttachments: removeAttachments
|
|
4010
4222
|
}
|
|
@@ -4015,10 +4227,13 @@ const {
|
|
|
4015
4227
|
updateDocuments,
|
|
4016
4228
|
moveDocument,
|
|
4017
4229
|
removeDocuments,
|
|
4230
|
+
// Attachments
|
|
4231
|
+
setDocumentAttachment,
|
|
4018
4232
|
setDocumentAttachments,
|
|
4019
4233
|
addDocumentAttachment,
|
|
4020
4234
|
addDocumentAttachments,
|
|
4021
4235
|
updateDocumentAttachment,
|
|
4236
|
+
updateDocumentAttachments,
|
|
4022
4237
|
removeDocumentAttachment,
|
|
4023
4238
|
removeDocumentAttachments
|
|
4024
4239
|
} = documentSlice.actions;
|
|
@@ -4126,7 +4341,9 @@ const overmapReducers = {
|
|
|
4126
4341
|
projectFileReducer,
|
|
4127
4342
|
rehydratedReducer,
|
|
4128
4343
|
settingReducer,
|
|
4129
|
-
|
|
4344
|
+
formReducer,
|
|
4345
|
+
formRevisionReducer,
|
|
4346
|
+
formSubmissionReducer,
|
|
4130
4347
|
userReducer,
|
|
4131
4348
|
workspaceReducer,
|
|
4132
4349
|
emailDomainsReducer,
|
|
@@ -4179,9 +4396,7 @@ function handleWorkspaceRemoval(draft, action) {
|
|
|
4179
4396
|
throw new Error(`Failed to update index_workspace of issue ${issue.offline_id} to main workspace`);
|
|
4180
4397
|
}
|
|
4181
4398
|
}
|
|
4182
|
-
const indexedForms = Object.values(draft.
|
|
4183
|
-
(form) => form.index_workspace === workspaceId
|
|
4184
|
-
);
|
|
4399
|
+
const indexedForms = Object.values(draft.formReducer.forms).filter((form) => form.index_workspace === workspaceId);
|
|
4185
4400
|
for (const form of indexedForms) {
|
|
4186
4401
|
form.index_workspace = mainWorkspace.offline_id;
|
|
4187
4402
|
}
|
|
@@ -5888,6 +6103,221 @@ class ComponentStageService extends BaseApiService {
|
|
|
5888
6103
|
store.dispatch(addStages(result));
|
|
5889
6104
|
}
|
|
5890
6105
|
}
|
|
6106
|
+
const AttachmentModelMeta = {
|
|
6107
|
+
[AttachmentModel.Issue]: {
|
|
6108
|
+
name: "issue",
|
|
6109
|
+
attachUrlPrefix: "/issues",
|
|
6110
|
+
deleteUrlPrefix: "/issues",
|
|
6111
|
+
fetchUrlPostfix: "/issue-attachments"
|
|
6112
|
+
},
|
|
6113
|
+
[AttachmentModel.Component]: {
|
|
6114
|
+
name: "component",
|
|
6115
|
+
attachUrlPrefix: "/components",
|
|
6116
|
+
deleteUrlPrefix: "/components",
|
|
6117
|
+
fetchUrlPostfix: "/component-attachments"
|
|
6118
|
+
},
|
|
6119
|
+
[AttachmentModel.ComponentType]: {
|
|
6120
|
+
name: "component type",
|
|
6121
|
+
attachUrlPrefix: "/components/types",
|
|
6122
|
+
deleteUrlPrefix: "/components/types",
|
|
6123
|
+
fetchUrlPostfix: "/component-type-attachments"
|
|
6124
|
+
},
|
|
6125
|
+
[AttachmentModel.Project]: {
|
|
6126
|
+
name: "component project",
|
|
6127
|
+
attachUrlPrefix: "/projects",
|
|
6128
|
+
deleteUrlPrefix: "/projects",
|
|
6129
|
+
fetchUrlPostfix: "/attachments"
|
|
6130
|
+
},
|
|
6131
|
+
[AttachmentModel.Document]: {
|
|
6132
|
+
name: "document",
|
|
6133
|
+
attachUrlPrefix: "/documents",
|
|
6134
|
+
deleteUrlPrefix: "/documents",
|
|
6135
|
+
fetchUrlPostfix: "/document-attachments"
|
|
6136
|
+
}
|
|
6137
|
+
};
|
|
6138
|
+
class BaseAttachmentService extends BaseApiService {
|
|
6139
|
+
getNumberOfAttachmentsWithSha1(sha1) {
|
|
6140
|
+
const {
|
|
6141
|
+
issueReducer: issueReducer2,
|
|
6142
|
+
componentReducer: componentReducer2,
|
|
6143
|
+
componentTypeReducer: componentTypeReducer2,
|
|
6144
|
+
documentsReducer: documentsReducer2,
|
|
6145
|
+
projectReducer: projectReducer2,
|
|
6146
|
+
formSubmissionReducer: formSubmissionReducer2,
|
|
6147
|
+
formRevisionReducer: formRevisionReducer2
|
|
6148
|
+
} = this.client.store.getState();
|
|
6149
|
+
const objectsWithSha1 = [].concat(
|
|
6150
|
+
Object.values(issueReducer2.attachments),
|
|
6151
|
+
Object.values(componentReducer2.attachments),
|
|
6152
|
+
Object.values(componentTypeReducer2.attachments),
|
|
6153
|
+
Object.values(documentsReducer2.attachments),
|
|
6154
|
+
Object.values(projectReducer2.attachments),
|
|
6155
|
+
Object.values(formRevisionReducer2.attachments),
|
|
6156
|
+
Object.values(formSubmissionReducer2.attachments)
|
|
6157
|
+
);
|
|
6158
|
+
return objectsWithSha1.filter((object) => object.file_sha1 === sha1).length;
|
|
6159
|
+
}
|
|
6160
|
+
processPresignedUrls(presignedUrls) {
|
|
6161
|
+
for (const [sha1, presignedUrl] of Object.entries(presignedUrls)) {
|
|
6162
|
+
void this.enqueueRequest({
|
|
6163
|
+
url: presignedUrl.url,
|
|
6164
|
+
description: "Upload file to S3",
|
|
6165
|
+
method: HttpMethod.POST,
|
|
6166
|
+
isExternalUrl: true,
|
|
6167
|
+
isAuthNeeded: false,
|
|
6168
|
+
attachmentHash: sha1,
|
|
6169
|
+
// TODO: can we use the sha1 as the blocker?
|
|
6170
|
+
blockers: [`s3-${presignedUrl.fields.key}`],
|
|
6171
|
+
blocks: [sha1],
|
|
6172
|
+
s3url: presignedUrl
|
|
6173
|
+
});
|
|
6174
|
+
}
|
|
6175
|
+
}
|
|
6176
|
+
// Note that currently the fetching of attachments for all models dependds on the active projectId. This may change in the future. And
|
|
6177
|
+
// so for some attachment model services, this method will have to be overridden.
|
|
6178
|
+
async getAttachments(actions) {
|
|
6179
|
+
const { store } = this.client;
|
|
6180
|
+
const activeProjectId = store.getState().projectReducer.activeProjectId;
|
|
6181
|
+
const meta = AttachmentModelMeta[this.attachmentModel];
|
|
6182
|
+
const result = await this.enqueueRequest({
|
|
6183
|
+
description: `Get ${meta.name} attachments`,
|
|
6184
|
+
method: HttpMethod.GET,
|
|
6185
|
+
url: `/projects/${activeProjectId}${meta.fetchUrlPostfix}/`,
|
|
6186
|
+
blocks: [],
|
|
6187
|
+
blockers: []
|
|
6188
|
+
});
|
|
6189
|
+
store.dispatch(actions.setAttachments(result));
|
|
6190
|
+
}
|
|
6191
|
+
async attachFiles(files, modelId, buildOfflineAttachment, actions) {
|
|
6192
|
+
const { store } = this.client;
|
|
6193
|
+
const currentUser = store.getState().userReducer.currentUser;
|
|
6194
|
+
const submittedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
6195
|
+
const offlineAttachments = [];
|
|
6196
|
+
const attachmentPayloads = [];
|
|
6197
|
+
const filePayloads = {};
|
|
6198
|
+
for (const file of files) {
|
|
6199
|
+
const sha1 = await hashFile(file);
|
|
6200
|
+
if (!(sha1 in filePayloads)) {
|
|
6201
|
+
filePayloads[sha1] = {
|
|
6202
|
+
sha1,
|
|
6203
|
+
file_type: file.type,
|
|
6204
|
+
extension: file.name.split(".").pop(),
|
|
6205
|
+
size: file.size
|
|
6206
|
+
};
|
|
6207
|
+
await this.client.files.addCache(file, sha1);
|
|
6208
|
+
}
|
|
6209
|
+
const offlineAttachment = buildOfflineAttachment({
|
|
6210
|
+
file,
|
|
6211
|
+
sha1,
|
|
6212
|
+
submittedAt,
|
|
6213
|
+
createdBy: currentUser.id,
|
|
6214
|
+
description: "",
|
|
6215
|
+
modelId
|
|
6216
|
+
});
|
|
6217
|
+
offlineAttachments.push(offlineAttachment);
|
|
6218
|
+
attachmentPayloads.push({
|
|
6219
|
+
offline_id: offlineAttachment.offline_id,
|
|
6220
|
+
name: offlineAttachment.file_name,
|
|
6221
|
+
sha1: offlineAttachment.file_sha1,
|
|
6222
|
+
description: offlineAttachment.description
|
|
6223
|
+
});
|
|
6224
|
+
}
|
|
6225
|
+
store.dispatch(actions.addAttachments(offlineAttachments));
|
|
6226
|
+
const meta = AttachmentModelMeta[this.attachmentModel];
|
|
6227
|
+
const promise = this.enqueueRequest({
|
|
6228
|
+
description: `Attach files to ${meta.name}`,
|
|
6229
|
+
method: HttpMethod.POST,
|
|
6230
|
+
url: `${meta.attachUrlPrefix}/${modelId}/attach/`,
|
|
6231
|
+
payload: {
|
|
6232
|
+
submitted_at: submittedAt,
|
|
6233
|
+
attachments: attachmentPayloads,
|
|
6234
|
+
files: Object.values(filePayloads)
|
|
6235
|
+
},
|
|
6236
|
+
blocks: offlineAttachments.map((attachment) => attachment.offline_id),
|
|
6237
|
+
blockers: offlineAttachments.map((attachment) => attachment.file_sha1)
|
|
6238
|
+
});
|
|
6239
|
+
promise.then(({ attachments, presigned_urls }) => {
|
|
6240
|
+
store.dispatch(actions.updateAttachments(attachments));
|
|
6241
|
+
this.processPresignedUrls(presigned_urls);
|
|
6242
|
+
}).catch(() => {
|
|
6243
|
+
store.dispatch(actions.removeAttachments(offlineAttachments.map((attachment) => attachment.offline_id)));
|
|
6244
|
+
});
|
|
6245
|
+
return [offlineAttachments, promise.then(({ attachments }) => attachments)];
|
|
6246
|
+
}
|
|
6247
|
+
async deleteAttachment(attachmendId, actions, selectors) {
|
|
6248
|
+
const { store } = this.client;
|
|
6249
|
+
const attachment = selectors.selectAttachment(attachmendId)(store.getState());
|
|
6250
|
+
if (!attachment) {
|
|
6251
|
+
throw new Error(
|
|
6252
|
+
`Attempting to delete attachment with offline_id ${attachmendId} that does not exist in the store`
|
|
6253
|
+
);
|
|
6254
|
+
}
|
|
6255
|
+
store.dispatch(actions.removeAttachment(attachment.offline_id));
|
|
6256
|
+
const meta = AttachmentModelMeta[this.attachmentModel];
|
|
6257
|
+
const promise = this.enqueueRequest({
|
|
6258
|
+
description: "Delete attachment",
|
|
6259
|
+
method: HttpMethod.DELETE,
|
|
6260
|
+
url: `${meta.deleteUrlPrefix}/attachments/${attachmendId}/`,
|
|
6261
|
+
blockers: [attachmendId],
|
|
6262
|
+
blocks: []
|
|
6263
|
+
});
|
|
6264
|
+
promise.then(() => {
|
|
6265
|
+
if (this.getNumberOfAttachmentsWithSha1(attachment.file_sha1) === 0) {
|
|
6266
|
+
void this.client.files.removeCache(attachment.file_sha1);
|
|
6267
|
+
}
|
|
6268
|
+
}).catch(() => {
|
|
6269
|
+
store.dispatch(actions.setAttachment(attachment));
|
|
6270
|
+
});
|
|
6271
|
+
return promise;
|
|
6272
|
+
}
|
|
6273
|
+
}
|
|
6274
|
+
class ComponentAttachmentService extends BaseAttachmentService {
|
|
6275
|
+
constructor() {
|
|
6276
|
+
super(...arguments);
|
|
6277
|
+
__publicField(this, "attachmentModel", AttachmentModel.Component);
|
|
6278
|
+
}
|
|
6279
|
+
buildOfflineAttachment(data) {
|
|
6280
|
+
return offline({
|
|
6281
|
+
file: URL.createObjectURL(data.file),
|
|
6282
|
+
file_sha1: data.sha1,
|
|
6283
|
+
created_by: data.createdBy,
|
|
6284
|
+
file_name: data.file.name,
|
|
6285
|
+
file_type: data.file.type,
|
|
6286
|
+
submitted_at: data.submittedAt,
|
|
6287
|
+
description: data.description,
|
|
6288
|
+
component: data.modelId
|
|
6289
|
+
});
|
|
6290
|
+
}
|
|
6291
|
+
async attachFilesToComponent(files, componentId) {
|
|
6292
|
+
return this.attachFiles(
|
|
6293
|
+
files,
|
|
6294
|
+
componentId,
|
|
6295
|
+
this.buildOfflineAttachment.bind(this),
|
|
6296
|
+
{
|
|
6297
|
+
addAttachments: addComponentAttachments,
|
|
6298
|
+
updateAttachments: updateComponentAttachments,
|
|
6299
|
+
removeAttachments: removeComponentAttachments
|
|
6300
|
+
}
|
|
6301
|
+
);
|
|
6302
|
+
}
|
|
6303
|
+
deleteComponentAttachment(attachmentId) {
|
|
6304
|
+
return this.deleteAttachment(
|
|
6305
|
+
attachmentId,
|
|
6306
|
+
{
|
|
6307
|
+
setAttachment: setComponentAttachment,
|
|
6308
|
+
removeAttachment: removeComponentAttachment
|
|
6309
|
+
},
|
|
6310
|
+
{
|
|
6311
|
+
selectAttachment: selectComponentAttachment
|
|
6312
|
+
}
|
|
6313
|
+
);
|
|
6314
|
+
}
|
|
6315
|
+
async refreshStore() {
|
|
6316
|
+
return this.getAttachments({
|
|
6317
|
+
setAttachments: setComponentAttachments
|
|
6318
|
+
});
|
|
6319
|
+
}
|
|
6320
|
+
}
|
|
5891
6321
|
class ComponentTypeService extends BaseApiService {
|
|
5892
6322
|
add(componentType) {
|
|
5893
6323
|
const offlineComponentType = offline(componentType);
|
|
@@ -5960,6 +6390,53 @@ class ComponentTypeService extends BaseApiService {
|
|
|
5960
6390
|
store.dispatch(setComponentTypes(result));
|
|
5961
6391
|
}
|
|
5962
6392
|
}
|
|
6393
|
+
class ComponentTypeAttachmentService extends BaseAttachmentService {
|
|
6394
|
+
constructor() {
|
|
6395
|
+
super(...arguments);
|
|
6396
|
+
__publicField(this, "attachmentModel", AttachmentModel.ComponentType);
|
|
6397
|
+
}
|
|
6398
|
+
buildOfflineAttachment(data) {
|
|
6399
|
+
return offline({
|
|
6400
|
+
file: URL.createObjectURL(data.file),
|
|
6401
|
+
file_sha1: data.sha1,
|
|
6402
|
+
created_by: data.createdBy,
|
|
6403
|
+
file_name: data.file.name,
|
|
6404
|
+
file_type: data.file.type,
|
|
6405
|
+
submitted_at: data.submittedAt,
|
|
6406
|
+
description: data.description,
|
|
6407
|
+
component_type: data.modelId
|
|
6408
|
+
});
|
|
6409
|
+
}
|
|
6410
|
+
async attachFilesToComponentType(files, componentTypeId) {
|
|
6411
|
+
return this.attachFiles(
|
|
6412
|
+
files,
|
|
6413
|
+
componentTypeId,
|
|
6414
|
+
this.buildOfflineAttachment.bind(this),
|
|
6415
|
+
{
|
|
6416
|
+
addAttachments: addComponentTypeAttachments,
|
|
6417
|
+
updateAttachments: updateComponentTypeAttachments,
|
|
6418
|
+
removeAttachments: removeComponentTypeAttachments
|
|
6419
|
+
}
|
|
6420
|
+
);
|
|
6421
|
+
}
|
|
6422
|
+
deleteComponentTypeAttachment(attachmentId) {
|
|
6423
|
+
return this.deleteAttachment(
|
|
6424
|
+
attachmentId,
|
|
6425
|
+
{
|
|
6426
|
+
setAttachment: setComponentTypeAttachment,
|
|
6427
|
+
removeAttachment: removeComponentTypeAttachment
|
|
6428
|
+
},
|
|
6429
|
+
{
|
|
6430
|
+
selectAttachment: selectComponentTypeAttachment
|
|
6431
|
+
}
|
|
6432
|
+
);
|
|
6433
|
+
}
|
|
6434
|
+
async refreshStore() {
|
|
6435
|
+
return this.getAttachments({
|
|
6436
|
+
setAttachments: setComponentTypeAttachments
|
|
6437
|
+
});
|
|
6438
|
+
}
|
|
6439
|
+
}
|
|
5963
6440
|
class IssueCommentService extends BaseApiService {
|
|
5964
6441
|
// Omit author and submitted_at since these will always be set internally
|
|
5965
6442
|
add(comment) {
|
|
@@ -6056,6 +6533,48 @@ class IssueUpdateService extends BaseApiService {
|
|
|
6056
6533
|
store.dispatch(setIssueUpdates(filteredResult));
|
|
6057
6534
|
}
|
|
6058
6535
|
}
|
|
6536
|
+
class IssueAttachmentService extends BaseAttachmentService {
|
|
6537
|
+
constructor() {
|
|
6538
|
+
super(...arguments);
|
|
6539
|
+
__publicField(this, "attachmentModel", AttachmentModel.Issue);
|
|
6540
|
+
}
|
|
6541
|
+
buildOfflineAttachment(data) {
|
|
6542
|
+
return offline({
|
|
6543
|
+
file: URL.createObjectURL(data.file),
|
|
6544
|
+
file_sha1: data.sha1,
|
|
6545
|
+
created_by: data.createdBy,
|
|
6546
|
+
file_name: data.file.name,
|
|
6547
|
+
file_type: data.file.type,
|
|
6548
|
+
submitted_at: data.submittedAt,
|
|
6549
|
+
description: data.description,
|
|
6550
|
+
issue: data.modelId
|
|
6551
|
+
});
|
|
6552
|
+
}
|
|
6553
|
+
async attachFilesToIssue(files, issueId) {
|
|
6554
|
+
return this.attachFiles(files, issueId, this.buildOfflineAttachment.bind(this), {
|
|
6555
|
+
addAttachments: addIssueAttachments,
|
|
6556
|
+
updateAttachments: updateIssueAttachments,
|
|
6557
|
+
removeAttachments: removeIssueAttachments
|
|
6558
|
+
});
|
|
6559
|
+
}
|
|
6560
|
+
deleteIssueAttachment(attachmentId) {
|
|
6561
|
+
return this.deleteAttachment(
|
|
6562
|
+
attachmentId,
|
|
6563
|
+
{
|
|
6564
|
+
setAttachment: setIssueAttachment,
|
|
6565
|
+
removeAttachment: removeIssueAttachment
|
|
6566
|
+
},
|
|
6567
|
+
{
|
|
6568
|
+
selectAttachment: selectIssueAttachment
|
|
6569
|
+
}
|
|
6570
|
+
);
|
|
6571
|
+
}
|
|
6572
|
+
async refreshStore() {
|
|
6573
|
+
return this.getAttachments({
|
|
6574
|
+
setAttachments: setIssueAttachments
|
|
6575
|
+
});
|
|
6576
|
+
}
|
|
6577
|
+
}
|
|
6059
6578
|
class IssueService extends BaseApiService {
|
|
6060
6579
|
// Basic CRUD functions
|
|
6061
6580
|
// TODO: Once all models are represented in `Created<TModel>`, use `Created` in `OptimisticModelResult`, so we don't
|
|
@@ -6401,6 +6920,7 @@ class MainService extends BaseApiService {
|
|
|
6401
6920
|
const usersResult = await usersResultPromise;
|
|
6402
6921
|
await projectAccessRefreshPromise;
|
|
6403
6922
|
store.dispatch(addUsers(usersResult));
|
|
6923
|
+
void this.client.projectAttachments.refreshStore();
|
|
6404
6924
|
}
|
|
6405
6925
|
let currentWorkspaceId;
|
|
6406
6926
|
const oldWorkspaceId = this.client.store.getState().workspaceReducer.activeWorkspaceId;
|
|
@@ -6413,38 +6933,30 @@ class MainService extends BaseApiService {
|
|
|
6413
6933
|
store.dispatch(setActiveWorkspaceId(currentWorkspaceId));
|
|
6414
6934
|
void this.client.categories.refreshStore().then(() => {
|
|
6415
6935
|
void this.client.issues.refreshStore().then(() => {
|
|
6936
|
+
void this.client.issueAttachments.refreshStore().then();
|
|
6416
6937
|
void this.client.issueComments.refreshStore().then();
|
|
6938
|
+
void this.client.issueUpdates.refreshStore().then();
|
|
6417
6939
|
});
|
|
6418
6940
|
});
|
|
6419
6941
|
void this.client.projectFiles.refreshStore().then();
|
|
6420
6942
|
void this.client.componentTypes.refreshStore().then(() => {
|
|
6421
|
-
void this.client.
|
|
6422
|
-
void this.client.
|
|
6943
|
+
void this.client.componentTypeAttachments.refreshStore().then(() => {
|
|
6944
|
+
void this.client.componentStages.refreshStore().then(() => {
|
|
6945
|
+
void this.client.components.refreshStore(overwrite).then(() => {
|
|
6946
|
+
void this.client.componentAttachments.refreshStore().then();
|
|
6947
|
+
});
|
|
6948
|
+
});
|
|
6949
|
+
void this.client.componentStageCompletions.refreshStore().then();
|
|
6423
6950
|
});
|
|
6424
|
-
void this.client.componentStageCompletions.refreshStore().then();
|
|
6425
6951
|
});
|
|
6426
6952
|
void this.client.userForms.refreshStore().then(() => {
|
|
6427
6953
|
void this.client.userFormSubmissions.refreshStore().then();
|
|
6428
6954
|
});
|
|
6429
6955
|
}
|
|
6430
6956
|
if (currentProjectId) {
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
const {
|
|
6434
|
-
issue_attachments,
|
|
6435
|
-
component_type_attachments,
|
|
6436
|
-
component_attachments,
|
|
6437
|
-
project_attachments,
|
|
6438
|
-
document_attachments
|
|
6439
|
-
} = result;
|
|
6440
|
-
store.dispatch(setIssueAttachments(issue_attachments));
|
|
6441
|
-
store.dispatch(setComponentAttachments(component_attachments));
|
|
6442
|
-
store.dispatch(setComponentTypeAttachments(component_type_attachments));
|
|
6443
|
-
store.dispatch(setProjectAttachments(project_attachments));
|
|
6444
|
-
store.dispatch(setDocumentAttachments(document_attachments));
|
|
6957
|
+
void this.client.documents.refreshStore().then(() => {
|
|
6958
|
+
void this.client.documentAttachments.refreshStore().then();
|
|
6445
6959
|
});
|
|
6446
|
-
void this.client.documents.refreshStore();
|
|
6447
|
-
void this.client.issueUpdates.refreshStore();
|
|
6448
6960
|
}
|
|
6449
6961
|
store.dispatch(setIsFetchingInitialData(false));
|
|
6450
6962
|
if (overwrite) {
|
|
@@ -6608,6 +7120,48 @@ class ProjectFileService extends BaseApiService {
|
|
|
6608
7120
|
});
|
|
6609
7121
|
}
|
|
6610
7122
|
}
|
|
7123
|
+
class ProjectAttachmentService extends BaseAttachmentService {
|
|
7124
|
+
constructor() {
|
|
7125
|
+
super(...arguments);
|
|
7126
|
+
__publicField(this, "attachmentModel", AttachmentModel.Project);
|
|
7127
|
+
}
|
|
7128
|
+
buildOfflineAttachment(data) {
|
|
7129
|
+
return offline({
|
|
7130
|
+
file: URL.createObjectURL(data.file),
|
|
7131
|
+
file_sha1: data.sha1,
|
|
7132
|
+
created_by: data.createdBy,
|
|
7133
|
+
file_name: data.file.name,
|
|
7134
|
+
file_type: data.file.type,
|
|
7135
|
+
submitted_at: data.submittedAt,
|
|
7136
|
+
description: data.description,
|
|
7137
|
+
project: data.modelId
|
|
7138
|
+
});
|
|
7139
|
+
}
|
|
7140
|
+
async attachFilesToProject(files, projectId) {
|
|
7141
|
+
return this.attachFiles(files, projectId, this.buildOfflineAttachment.bind(this), {
|
|
7142
|
+
addAttachments: addProjectAttachments,
|
|
7143
|
+
updateAttachments: updateProjectAttachments,
|
|
7144
|
+
removeAttachments: removeProjectAttachments
|
|
7145
|
+
});
|
|
7146
|
+
}
|
|
7147
|
+
deleteProjectAttachment(attachmentId) {
|
|
7148
|
+
return this.deleteAttachment(
|
|
7149
|
+
attachmentId,
|
|
7150
|
+
{
|
|
7151
|
+
setAttachment: setProjectAttachment,
|
|
7152
|
+
removeAttachment: removeProjectAttachment
|
|
7153
|
+
},
|
|
7154
|
+
{
|
|
7155
|
+
selectAttachment: selectProjectAttachment
|
|
7156
|
+
}
|
|
7157
|
+
);
|
|
7158
|
+
}
|
|
7159
|
+
async refreshStore() {
|
|
7160
|
+
return this.getAttachments({
|
|
7161
|
+
setAttachments: setProjectAttachments
|
|
7162
|
+
});
|
|
7163
|
+
}
|
|
7164
|
+
}
|
|
6611
7165
|
class ProjectService extends BaseApiService {
|
|
6612
7166
|
/**
|
|
6613
7167
|
* Creates a new project. Due to the nature of project creation,
|
|
@@ -6809,7 +7363,7 @@ class UserFormService extends BaseApiService {
|
|
|
6809
7363
|
...revisionAttachmentPayload,
|
|
6810
7364
|
file: URL.createObjectURL(image)
|
|
6811
7365
|
};
|
|
6812
|
-
store.dispatch(
|
|
7366
|
+
store.dispatch(addFormRevisionAttachment(offlinePayload));
|
|
6813
7367
|
return attach;
|
|
6814
7368
|
});
|
|
6815
7369
|
});
|
|
@@ -6845,8 +7399,8 @@ class UserFormService extends BaseApiService {
|
|
|
6845
7399
|
submitted_at: submittedAt
|
|
6846
7400
|
};
|
|
6847
7401
|
const { store } = this.client;
|
|
6848
|
-
store.dispatch(
|
|
6849
|
-
store.dispatch(
|
|
7402
|
+
store.dispatch(addForm(retForm));
|
|
7403
|
+
store.dispatch(addFormRevision(retRevision));
|
|
6850
7404
|
const formPromise = this.enqueueRequest({
|
|
6851
7405
|
description: "Create form",
|
|
6852
7406
|
method: HttpMethod.POST,
|
|
@@ -6864,8 +7418,8 @@ class UserFormService extends BaseApiService {
|
|
|
6864
7418
|
});
|
|
6865
7419
|
const attachImagesPromises = this.getAttachImagePromises(images, offlineRevisionPayload.offline_id);
|
|
6866
7420
|
void formPromise.catch((e) => {
|
|
6867
|
-
store.dispatch(
|
|
6868
|
-
store.dispatch(
|
|
7421
|
+
store.dispatch(deleteForm(retForm.offline_id));
|
|
7422
|
+
store.dispatch(deleteFormRevision(retRevision.offline_id));
|
|
6869
7423
|
throw e;
|
|
6870
7424
|
});
|
|
6871
7425
|
const settledPromise = Promise.all([formPromise, ...attachImagesPromises]).then(() => formPromise);
|
|
@@ -6908,7 +7462,7 @@ class UserFormService extends BaseApiService {
|
|
|
6908
7462
|
form: formId2,
|
|
6909
7463
|
submitted_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
6910
7464
|
};
|
|
6911
|
-
store.dispatch(
|
|
7465
|
+
store.dispatch(addFormRevision(fullRevision));
|
|
6912
7466
|
const promise = this.enqueueRequest({
|
|
6913
7467
|
description: "Create form revision",
|
|
6914
7468
|
method: HttpMethod.PATCH,
|
|
@@ -6922,9 +7476,9 @@ class UserFormService extends BaseApiService {
|
|
|
6922
7476
|
});
|
|
6923
7477
|
const attachImagesPromises = this.getAttachImagePromises(images, offlineRevision.offline_id);
|
|
6924
7478
|
void promise.then((result) => {
|
|
6925
|
-
store.dispatch(
|
|
7479
|
+
store.dispatch(setFormRevision(result));
|
|
6926
7480
|
}).catch(() => {
|
|
6927
|
-
store.dispatch(
|
|
7481
|
+
store.dispatch(deleteFormRevision(fullRevision.offline_id));
|
|
6928
7482
|
});
|
|
6929
7483
|
const settledPromise = Promise.all([promise, ...attachImagesPromises]).then(() => promise);
|
|
6930
7484
|
return [fullRevision, settledPromise];
|
|
@@ -6966,19 +7520,19 @@ class UserFormService extends BaseApiService {
|
|
|
6966
7520
|
async delete(formId2) {
|
|
6967
7521
|
const { store } = this.client;
|
|
6968
7522
|
const state = store.getState();
|
|
6969
|
-
const userForm =
|
|
7523
|
+
const userForm = selectForm(formId2)(state);
|
|
6970
7524
|
if (!userForm) {
|
|
6971
7525
|
throw new Error("Expected userForm to exist");
|
|
6972
7526
|
}
|
|
6973
|
-
const userFormSubmissions =
|
|
7527
|
+
const userFormSubmissions = selectFormSubmissionsOfForm(formId2)(state);
|
|
6974
7528
|
if (userFormSubmissions && userFormSubmissions.length > 0) {
|
|
6975
|
-
store.dispatch(
|
|
7529
|
+
store.dispatch(deleteFormSubmissions(userFormSubmissions.map(({ offline_id }) => offline_id)));
|
|
6976
7530
|
}
|
|
6977
|
-
const userFormRevisions =
|
|
7531
|
+
const userFormRevisions = selectFormRevisionsOfForm(formId2)(state);
|
|
6978
7532
|
if (userFormRevisions && userFormRevisions.length > 0) {
|
|
6979
|
-
store.dispatch(
|
|
7533
|
+
store.dispatch(deleteFormRevisions(userFormRevisions.map(({ offline_id }) => offline_id)));
|
|
6980
7534
|
}
|
|
6981
|
-
store.dispatch(
|
|
7535
|
+
store.dispatch(deleteForm(formId2));
|
|
6982
7536
|
try {
|
|
6983
7537
|
return await this.enqueueRequest({
|
|
6984
7538
|
description: "Delete form",
|
|
@@ -6988,12 +7542,12 @@ class UserFormService extends BaseApiService {
|
|
|
6988
7542
|
blocks: []
|
|
6989
7543
|
});
|
|
6990
7544
|
} catch (e) {
|
|
6991
|
-
store.dispatch(
|
|
7545
|
+
store.dispatch(addForm(userForm));
|
|
6992
7546
|
if (userFormRevisions && userFormRevisions.length > 0) {
|
|
6993
|
-
store.dispatch(
|
|
7547
|
+
store.dispatch(addFormRevisions(userFormRevisions));
|
|
6994
7548
|
}
|
|
6995
7549
|
if (userFormSubmissions && userFormSubmissions.length > 0) {
|
|
6996
|
-
store.dispatch(
|
|
7550
|
+
store.dispatch(addFormSubmissions(userFormSubmissions));
|
|
6997
7551
|
}
|
|
6998
7552
|
throw e;
|
|
6999
7553
|
}
|
|
@@ -7007,16 +7561,15 @@ class UserFormService extends BaseApiService {
|
|
|
7007
7561
|
blockers: [],
|
|
7008
7562
|
blocks: []
|
|
7009
7563
|
});
|
|
7010
|
-
store.dispatch(
|
|
7011
|
-
store.dispatch(
|
|
7012
|
-
store.dispatch(
|
|
7564
|
+
store.dispatch(setForms(Object.values(result.forms)));
|
|
7565
|
+
store.dispatch(setFormRevisions(Object.values(result.revisions)));
|
|
7566
|
+
store.dispatch(setFormRevisionAttachments(Object.values(result.attachments)));
|
|
7013
7567
|
}
|
|
7014
7568
|
}
|
|
7015
7569
|
const isArrayOfFiles = (value) => {
|
|
7016
7570
|
return Array.isArray(value) && value[0] instanceof File;
|
|
7017
7571
|
};
|
|
7018
|
-
const separateFilesFromValues = (
|
|
7019
|
-
const { values } = payload;
|
|
7572
|
+
const separateFilesFromValues = (values) => {
|
|
7020
7573
|
const files = {};
|
|
7021
7574
|
const newValues = {};
|
|
7022
7575
|
for (const key in values) {
|
|
@@ -7031,17 +7584,13 @@ const separateFilesFromValues = (payload) => {
|
|
|
7031
7584
|
newValues[key] = value;
|
|
7032
7585
|
}
|
|
7033
7586
|
}
|
|
7034
|
-
|
|
7035
|
-
...payload,
|
|
7036
|
-
values: newValues
|
|
7037
|
-
};
|
|
7038
|
-
return { payloadWithoutFiles, files };
|
|
7587
|
+
return { values: newValues, files };
|
|
7039
7588
|
};
|
|
7040
7589
|
class UserFormSubmissionService extends BaseApiService {
|
|
7041
7590
|
constructor() {
|
|
7042
7591
|
super(...arguments);
|
|
7043
7592
|
// Attach files to submission, after uploading them to S3
|
|
7044
|
-
__publicField(this, "getAttachFilesPromises", (files,
|
|
7593
|
+
__publicField(this, "getAttachFilesPromises", (files, submission) => {
|
|
7045
7594
|
const { store } = this.client;
|
|
7046
7595
|
return Object.entries(files).map(async ([key, fileArray]) => {
|
|
7047
7596
|
const attachResults = [];
|
|
@@ -7051,24 +7600,27 @@ class UserFormSubmissionService extends BaseApiService {
|
|
|
7051
7600
|
const [fileProps] = await this.client.files.uploadFileToS3(sha1);
|
|
7052
7601
|
const submissionAttachmentPayload = offline({
|
|
7053
7602
|
...fileProps,
|
|
7054
|
-
submission:
|
|
7603
|
+
submission: submission.offline_id,
|
|
7055
7604
|
field_identifier: key
|
|
7056
7605
|
});
|
|
7057
7606
|
const attach = await this.enqueueRequest({
|
|
7058
7607
|
description: "Attach file to form submission",
|
|
7059
7608
|
method: HttpMethod.POST,
|
|
7060
|
-
url: `/forms/submission/${
|
|
7609
|
+
url: `/forms/submission/${submission.offline_id}/attachments/`,
|
|
7061
7610
|
payload: submissionAttachmentPayload,
|
|
7062
|
-
blockers: [
|
|
7063
|
-
|
|
7064
|
-
|
|
7611
|
+
blockers: [
|
|
7612
|
+
submission.component,
|
|
7613
|
+
submission.component_stage,
|
|
7614
|
+
submission.issue,
|
|
7615
|
+
submission.form_revision
|
|
7616
|
+
].filter((x) => x !== void 0),
|
|
7065
7617
|
blocks: [submissionAttachmentPayload.offline_id]
|
|
7066
7618
|
});
|
|
7067
7619
|
const offlinePayload = {
|
|
7068
7620
|
...submissionAttachmentPayload,
|
|
7069
7621
|
file: URL.createObjectURL(file)
|
|
7070
7622
|
};
|
|
7071
|
-
store.dispatch(
|
|
7623
|
+
store.dispatch(addFormSubmissionAttachment(offlinePayload));
|
|
7072
7624
|
attachResults.push(attach);
|
|
7073
7625
|
}
|
|
7074
7626
|
return attachResults;
|
|
@@ -7082,71 +7634,168 @@ class UserFormSubmissionService extends BaseApiService {
|
|
|
7082
7634
|
if (!activeProjectId) {
|
|
7083
7635
|
throw new Error("Expected an active project");
|
|
7084
7636
|
}
|
|
7085
|
-
const {
|
|
7637
|
+
const { values, files } = separateFilesFromValues(payload.values);
|
|
7638
|
+
const offlineSubmission = {
|
|
7639
|
+
...payload,
|
|
7640
|
+
values,
|
|
7641
|
+
created_by: state.userReducer.currentUser.id,
|
|
7642
|
+
submitted_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
7643
|
+
};
|
|
7086
7644
|
const promise = this.enqueueRequest({
|
|
7087
7645
|
description: "Respond to form",
|
|
7088
7646
|
method: HttpMethod.POST,
|
|
7089
7647
|
url: `/forms/revisions/${payload.form_revision}/respond/`,
|
|
7090
|
-
payload: { ...
|
|
7648
|
+
payload: { ...offlineSubmission, project: activeProjectId },
|
|
7091
7649
|
blockers: [payload.issue, payload.component, payload.component_stage, "add-form-entry"].filter(
|
|
7092
7650
|
(x) => x !== void 0
|
|
7093
7651
|
),
|
|
7094
7652
|
blocks: [payload.offline_id]
|
|
7095
7653
|
});
|
|
7096
|
-
const attachFilesPromises = this.getAttachFilesPromises(files,
|
|
7097
|
-
|
|
7098
|
-
const fullOfflineResult = {
|
|
7099
|
-
...payload,
|
|
7100
|
-
created_by: state.userReducer.currentUser.id,
|
|
7101
|
-
created_at: now,
|
|
7102
|
-
updated_at: now
|
|
7103
|
-
};
|
|
7104
|
-
const offlineResultWithoutFiles = {
|
|
7105
|
-
...fullOfflineResult,
|
|
7106
|
-
...payloadWithoutFiles
|
|
7107
|
-
};
|
|
7108
|
-
store.dispatch(updateOrCreateUserFormSubmission(offlineResultWithoutFiles));
|
|
7654
|
+
const attachFilesPromises = this.getAttachFilesPromises(files, offlineSubmission);
|
|
7655
|
+
store.dispatch(addFormSubmission(offlineSubmission));
|
|
7109
7656
|
void promise.then((result) => {
|
|
7110
7657
|
store.dispatch(addActiveProjectFormSubmissionsCount(1));
|
|
7111
|
-
store.dispatch(
|
|
7658
|
+
store.dispatch(setFormSubmission(result));
|
|
7112
7659
|
return result;
|
|
7113
7660
|
}).catch(() => {
|
|
7114
|
-
store.dispatch(
|
|
7661
|
+
store.dispatch(deleteFormSubmission(payload.offline_id));
|
|
7115
7662
|
store.dispatch(addActiveProjectFormSubmissionsCount(-1));
|
|
7116
7663
|
});
|
|
7117
7664
|
const settledPromise = Promise.all([promise, ...attachFilesPromises]).then(() => promise);
|
|
7118
|
-
return [
|
|
7665
|
+
return [offlineSubmission, settledPromise];
|
|
7119
7666
|
}
|
|
7120
|
-
|
|
7667
|
+
// Note currently the bulkAdd method is specific to form submissions for components
|
|
7668
|
+
// TODO: adapt the support bulk adding to any model type
|
|
7669
|
+
async bulkAdd(args) {
|
|
7670
|
+
const { formRevision, values: argsValues, componentOfflineIds } = args;
|
|
7121
7671
|
const { store } = this.client;
|
|
7122
|
-
const
|
|
7123
|
-
|
|
7124
|
-
|
|
7672
|
+
const offlineSubmissions = [];
|
|
7673
|
+
const offlineAttachments = [];
|
|
7674
|
+
const submissionOfflineIds = [];
|
|
7675
|
+
const submissionsPayload = [];
|
|
7676
|
+
const attachmentsPayload = [];
|
|
7677
|
+
const { values, files } = separateFilesFromValues(argsValues);
|
|
7678
|
+
const submittedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7679
|
+
const createdBy = store.getState().userReducer.currentUser.id;
|
|
7680
|
+
for (const component_id of componentOfflineIds) {
|
|
7681
|
+
const submission = offline({
|
|
7682
|
+
form_revision: formRevision,
|
|
7683
|
+
values,
|
|
7684
|
+
created_by: createdBy,
|
|
7685
|
+
submitted_at: submittedAt,
|
|
7686
|
+
component: component_id
|
|
7687
|
+
});
|
|
7688
|
+
submissionOfflineIds.push(submission.offline_id);
|
|
7689
|
+
submissionsPayload.push({ offline_id: submission.offline_id, component_id });
|
|
7690
|
+
offlineSubmissions.push(submission);
|
|
7691
|
+
for (const [fieldIdentifier, fileArray] of Object.entries(files)) {
|
|
7692
|
+
for (const file of fileArray) {
|
|
7693
|
+
const sha1 = await hashFile(file);
|
|
7694
|
+
await this.client.files.addCache(file, sha1);
|
|
7695
|
+
const offlineAttachment = offline({
|
|
7696
|
+
file_name: file.name,
|
|
7697
|
+
file_sha1: sha1,
|
|
7698
|
+
file: URL.createObjectURL(file),
|
|
7699
|
+
submission: submission.offline_id,
|
|
7700
|
+
field_identifier: fieldIdentifier
|
|
7701
|
+
});
|
|
7702
|
+
offlineAttachments.push(offlineAttachment);
|
|
7703
|
+
attachmentsPayload.push({
|
|
7704
|
+
offline_id: offlineAttachment.offline_id,
|
|
7705
|
+
submission_id: submission.offline_id,
|
|
7706
|
+
sha1,
|
|
7707
|
+
name: file.name,
|
|
7708
|
+
field_identifier: fieldIdentifier
|
|
7709
|
+
});
|
|
7710
|
+
}
|
|
7711
|
+
}
|
|
7712
|
+
}
|
|
7713
|
+
const filesRecord = {};
|
|
7714
|
+
for (const file of Object.values(files).flat()) {
|
|
7715
|
+
const sha1 = await hashFile(file);
|
|
7716
|
+
filesRecord[sha1] = {
|
|
7717
|
+
sha1,
|
|
7718
|
+
extension: file.name.split(".").pop() || "",
|
|
7719
|
+
file_type: file.type,
|
|
7720
|
+
size: file.size
|
|
7721
|
+
};
|
|
7125
7722
|
}
|
|
7723
|
+
store.dispatch(addFormSubmissions(offlineSubmissions));
|
|
7724
|
+
store.dispatch(addFormSubmissionAttachments(offlineAttachments));
|
|
7725
|
+
const promise = this.enqueueRequest({
|
|
7726
|
+
description: "Bulk add form submissions",
|
|
7727
|
+
method: HttpMethod.POST,
|
|
7728
|
+
url: `/forms/revisions/${formRevision}/bulk-respond/`,
|
|
7729
|
+
payload: {
|
|
7730
|
+
form_data: values,
|
|
7731
|
+
submitted_at: submittedAt,
|
|
7732
|
+
submissions: submissionsPayload,
|
|
7733
|
+
attachments: attachmentsPayload,
|
|
7734
|
+
files: Object.values(filesRecord)
|
|
7735
|
+
},
|
|
7736
|
+
blockers: componentOfflineIds,
|
|
7737
|
+
blocks: submissionOfflineIds
|
|
7738
|
+
});
|
|
7739
|
+
promise.then(({ submissions, attachments, presigned_urls }) => {
|
|
7740
|
+
store.dispatch(updateFormSubmissions(submissions));
|
|
7741
|
+
store.dispatch(updateFormSubmissionAttachments(attachments));
|
|
7742
|
+
for (const [sha1, presigned_url] of Object.entries(presigned_urls)) {
|
|
7743
|
+
const file = filesRecord[sha1];
|
|
7744
|
+
if (!file)
|
|
7745
|
+
continue;
|
|
7746
|
+
void this.enqueueRequest({
|
|
7747
|
+
url: presigned_url.url,
|
|
7748
|
+
description: "Upload file",
|
|
7749
|
+
method: HttpMethod.POST,
|
|
7750
|
+
isExternalUrl: true,
|
|
7751
|
+
isAuthNeeded: false,
|
|
7752
|
+
attachmentHash: sha1,
|
|
7753
|
+
blockers: [`s3-${file.sha1}.${file.extension}`],
|
|
7754
|
+
blocks: [sha1],
|
|
7755
|
+
s3url: presigned_url
|
|
7756
|
+
});
|
|
7757
|
+
}
|
|
7758
|
+
}).catch(() => {
|
|
7759
|
+
store.dispatch(deleteFormSubmissions(submissionOfflineIds));
|
|
7760
|
+
store.dispatch(deleteFormSubmissionAttachments(offlineAttachments.map((x) => x.offline_id)));
|
|
7761
|
+
});
|
|
7762
|
+
return [offlineSubmissions, promise.then(({ submissions }) => submissions)];
|
|
7763
|
+
}
|
|
7764
|
+
update(submission) {
|
|
7765
|
+
const { store } = this.client;
|
|
7766
|
+
const { values, files } = separateFilesFromValues(submission.values);
|
|
7126
7767
|
const attachFilesPromises = this.getAttachFilesPromises(files, submission);
|
|
7127
|
-
const
|
|
7128
|
-
...
|
|
7129
|
-
|
|
7768
|
+
const offlineSubmission = {
|
|
7769
|
+
...submission,
|
|
7770
|
+
values
|
|
7130
7771
|
};
|
|
7131
|
-
store.
|
|
7772
|
+
const submissionToBeUpdated = store.getState().formSubmissionReducer.formSubmissions[submission.offline_id];
|
|
7773
|
+
store.dispatch(updateFormSubmission(offlineSubmission));
|
|
7132
7774
|
const promise = this.enqueueRequest({
|
|
7133
7775
|
description: "Patch form submission",
|
|
7134
7776
|
method: HttpMethod.PATCH,
|
|
7135
7777
|
url: `/forms/submissions/${submission.offline_id}/`,
|
|
7136
|
-
payload:
|
|
7137
|
-
blockers: [
|
|
7778
|
+
payload: offlineSubmission,
|
|
7779
|
+
blockers: [offlineSubmission.issue, offlineSubmission.component, offlineSubmission.component_stage].filter(
|
|
7138
7780
|
(x) => x !== void 0
|
|
7139
7781
|
),
|
|
7140
|
-
blocks: [
|
|
7782
|
+
blocks: [offlineSubmission.offline_id]
|
|
7783
|
+
});
|
|
7784
|
+
promise.then((createdSubmission) => {
|
|
7785
|
+
store.dispatch(setFormSubmission(createdSubmission));
|
|
7786
|
+
}).catch(() => {
|
|
7787
|
+
store.dispatch(setFormSubmission(submissionToBeUpdated));
|
|
7141
7788
|
});
|
|
7142
|
-
return Promise.all([promise, ...attachFilesPromises]).then(() => promise);
|
|
7789
|
+
return [offlineSubmission, Promise.all([promise, ...attachFilesPromises]).then(() => promise)];
|
|
7143
7790
|
}
|
|
7144
7791
|
async delete(submissionId) {
|
|
7145
7792
|
const { store } = this.client;
|
|
7146
7793
|
const state = store.getState();
|
|
7147
|
-
const submission = state.
|
|
7148
|
-
|
|
7794
|
+
const submission = state.formSubmissionReducer.formSubmissions[submissionId];
|
|
7795
|
+
const submissionAttachments = selectAttachmentsOfFormSubmission(submissionId)(state);
|
|
7796
|
+
store.dispatch(deleteFormSubmission(submissionId));
|
|
7149
7797
|
store.dispatch(addActiveProjectFormSubmissionsCount(-1));
|
|
7798
|
+
store.dispatch(deleteFormSubmissionAttachments(submissionAttachments.map((x) => x.offline_id)));
|
|
7150
7799
|
try {
|
|
7151
7800
|
return await this.enqueueRequest({
|
|
7152
7801
|
description: "Delete user form submissions",
|
|
@@ -7156,10 +7805,9 @@ class UserFormSubmissionService extends BaseApiService {
|
|
|
7156
7805
|
blocks: []
|
|
7157
7806
|
});
|
|
7158
7807
|
} catch (e) {
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
}
|
|
7808
|
+
store.dispatch(addActiveProjectFormSubmissionsCount(1));
|
|
7809
|
+
store.dispatch(addFormSubmission(submission));
|
|
7810
|
+
store.dispatch(addFormSubmissionAttachments(submissionAttachments));
|
|
7163
7811
|
throw e;
|
|
7164
7812
|
}
|
|
7165
7813
|
}
|
|
@@ -7173,7 +7821,7 @@ class UserFormSubmissionService extends BaseApiService {
|
|
|
7173
7821
|
blockers: [],
|
|
7174
7822
|
blocks: []
|
|
7175
7823
|
});
|
|
7176
|
-
store.dispatch(
|
|
7824
|
+
store.dispatch(setFormSubmissions(submissions));
|
|
7177
7825
|
const attachments = await this.enqueueRequest({
|
|
7178
7826
|
description: "Fetch form attachments",
|
|
7179
7827
|
method: HttpMethod.GET,
|
|
@@ -7181,7 +7829,7 @@ class UserFormSubmissionService extends BaseApiService {
|
|
|
7181
7829
|
blockers: [],
|
|
7182
7830
|
blocks: []
|
|
7183
7831
|
});
|
|
7184
|
-
store.dispatch(
|
|
7832
|
+
store.dispatch(setFormSubmissionAttachments(attachments));
|
|
7185
7833
|
}
|
|
7186
7834
|
}
|
|
7187
7835
|
class WorkspaceService extends BaseApiService {
|
|
@@ -7873,6 +8521,48 @@ class DocumentService extends BaseApiService {
|
|
|
7873
8521
|
store.dispatch(setDocuments(result));
|
|
7874
8522
|
}
|
|
7875
8523
|
}
|
|
8524
|
+
class DocumentAttachmentService extends BaseAttachmentService {
|
|
8525
|
+
constructor() {
|
|
8526
|
+
super(...arguments);
|
|
8527
|
+
__publicField(this, "attachmentModel", AttachmentModel.Document);
|
|
8528
|
+
}
|
|
8529
|
+
buildOfflineAttachment(data) {
|
|
8530
|
+
return offline({
|
|
8531
|
+
file: URL.createObjectURL(data.file),
|
|
8532
|
+
file_sha1: data.sha1,
|
|
8533
|
+
created_by: data.createdBy,
|
|
8534
|
+
file_name: data.file.name,
|
|
8535
|
+
file_type: data.file.type,
|
|
8536
|
+
submitted_at: data.submittedAt,
|
|
8537
|
+
description: data.description,
|
|
8538
|
+
document: data.modelId
|
|
8539
|
+
});
|
|
8540
|
+
}
|
|
8541
|
+
async attachFilesToDocument(files, documentId) {
|
|
8542
|
+
return this.attachFiles(files, documentId, this.buildOfflineAttachment.bind(this), {
|
|
8543
|
+
addAttachments: addDocumentAttachments,
|
|
8544
|
+
updateAttachments: updateDocumentAttachments,
|
|
8545
|
+
removeAttachments: removeDocumentAttachments
|
|
8546
|
+
});
|
|
8547
|
+
}
|
|
8548
|
+
deleteDocumentAttachment(attachmentId) {
|
|
8549
|
+
return this.deleteAttachment(
|
|
8550
|
+
attachmentId,
|
|
8551
|
+
{
|
|
8552
|
+
setAttachment: setDocumentAttachment,
|
|
8553
|
+
removeAttachment: removeDocumentAttachment
|
|
8554
|
+
},
|
|
8555
|
+
{
|
|
8556
|
+
selectAttachment: selectDocumentAttachment
|
|
8557
|
+
}
|
|
8558
|
+
);
|
|
8559
|
+
}
|
|
8560
|
+
async refreshStore() {
|
|
8561
|
+
return this.getAttachments({
|
|
8562
|
+
setAttachments: setDocumentAttachments
|
|
8563
|
+
});
|
|
8564
|
+
}
|
|
8565
|
+
}
|
|
7876
8566
|
class AgentService extends BaseApiService {
|
|
7877
8567
|
/**
|
|
7878
8568
|
* Prompt the agent with a message.
|
|
@@ -7920,20 +8610,25 @@ class OvermapSDK {
|
|
|
7920
8610
|
__publicField(this, "issues", new IssueService(this));
|
|
7921
8611
|
__publicField(this, "issueComments", new IssueCommentService(this));
|
|
7922
8612
|
__publicField(this, "issueUpdates", new IssueUpdateService(this));
|
|
8613
|
+
__publicField(this, "issueAttachments", new IssueAttachmentService(this));
|
|
7923
8614
|
__publicField(this, "workspaces", new WorkspaceService(this));
|
|
7924
8615
|
__publicField(this, "main", new MainService(this));
|
|
7925
8616
|
__publicField(this, "components", new ComponentService(this));
|
|
8617
|
+
__publicField(this, "componentAttachments", new ComponentAttachmentService(this));
|
|
7926
8618
|
__publicField(this, "componentTypes", new ComponentTypeService(this));
|
|
8619
|
+
__publicField(this, "componentTypeAttachments", new ComponentTypeAttachmentService(this));
|
|
7927
8620
|
__publicField(this, "componentStages", new ComponentStageService(this));
|
|
7928
8621
|
__publicField(this, "componentStageCompletions", new ComponentStageCompletionService(this));
|
|
7929
8622
|
__publicField(this, "userForms", new UserFormService(this));
|
|
7930
8623
|
__publicField(this, "userFormSubmissions", new UserFormSubmissionService(this));
|
|
7931
8624
|
__publicField(this, "projects", new ProjectService(this));
|
|
7932
8625
|
__publicField(this, "projectFiles", new ProjectFileService(this));
|
|
8626
|
+
__publicField(this, "projectAttachments", new ProjectAttachmentService(this));
|
|
7933
8627
|
__publicField(this, "emailVerification", new EmailVerificationService(this));
|
|
7934
8628
|
__publicField(this, "emailDomains", new EmailDomainsService(this));
|
|
7935
8629
|
__publicField(this, "licenses", new LicenseService(this));
|
|
7936
8630
|
__publicField(this, "documents", new DocumentService(this));
|
|
8631
|
+
__publicField(this, "documentAttachments", new DocumentAttachmentService(this));
|
|
7937
8632
|
this.API_URL = apiUrl;
|
|
7938
8633
|
this.store = store;
|
|
7939
8634
|
}
|
|
@@ -14039,7 +14734,7 @@ const initialFormValues = (fields, values) => {
|
|
|
14039
14734
|
};
|
|
14040
14735
|
const useAttachImagesToFormRevisionFields = (revision) => {
|
|
14041
14736
|
const { sdk } = useSDK();
|
|
14042
|
-
const attachments = useAppSelector(
|
|
14737
|
+
const attachments = useAppSelector(selectAttachmentsOfFormRevision((revision == null ? void 0 : revision.offline_id) ?? ""));
|
|
14043
14738
|
return useMemo(() => {
|
|
14044
14739
|
if (!revision || !attachments)
|
|
14045
14740
|
return revision;
|
|
@@ -14136,7 +14831,7 @@ const FormSubmissionViewer = memo(
|
|
|
14136
14831
|
return formRevisionToSchema(revisionWithImages, { readonly: true });
|
|
14137
14832
|
}, [revisionWithImages]);
|
|
14138
14833
|
const submissionValuesWithAttachments = useMemo(() => {
|
|
14139
|
-
const attachments =
|
|
14834
|
+
const attachments = selectAttachmentsOfFormSubmission(submission.offline_id)(sdk.store.getState()) ?? [];
|
|
14140
14835
|
const downloadedAttachments = {};
|
|
14141
14836
|
for (const attachment of attachments) {
|
|
14142
14837
|
const promise = sdk.files.fetchFileFromUrl(attachment.file, attachment.file_sha1, attachment.file_name);
|
|
@@ -14186,8 +14881,8 @@ const FormBrowser = memo(
|
|
|
14186
14881
|
}
|
|
14187
14882
|
return ret;
|
|
14188
14883
|
}, [filter, maxResults, ownerFilter]);
|
|
14189
|
-
const userForms = useAppSelector(
|
|
14190
|
-
const userFormMapping = useAppSelector(
|
|
14884
|
+
const userForms = useAppSelector(selectFilteredForms(ownerFilterOptions)) ?? [];
|
|
14885
|
+
const userFormMapping = useAppSelector(selectFormMapping);
|
|
14191
14886
|
const attachableUserForms = userForms.filter((form) => !form.component_type);
|
|
14192
14887
|
const attachableUserFormMapping = Object.values(userFormMapping).filter(
|
|
14193
14888
|
(form) => !form.component_type
|
|
@@ -14220,7 +14915,7 @@ const FormBrowser = memo(
|
|
|
14220
14915
|
const handleChange = useCallback((e) => {
|
|
14221
14916
|
setFilter(e.currentTarget.value);
|
|
14222
14917
|
}, []);
|
|
14223
|
-
const numberOfForms = useAppSelector(
|
|
14918
|
+
const numberOfForms = useAppSelector(selectGeneralFormCount) || 0;
|
|
14224
14919
|
const numberOfHiddenForms = numberOfForms - attachableUserForms.length;
|
|
14225
14920
|
const overflowMessage = attachableUserForms.length == maxResults && numberOfHiddenForms > 0 ? `Only the first ${maxResults} results are shown (${numberOfHiddenForms} hidden)` : numberOfHiddenForms > 0 && `${numberOfHiddenForms} hidden forms`;
|
|
14226
14921
|
return /* @__PURE__ */ jsxs(Flex$1, { ref, direction: "column", gap: "2", children: [
|
|
@@ -14314,16 +15009,13 @@ const FormSubmissionBrowserEntry = memo((props) => {
|
|
|
14314
15009
|
const { submission, onSubmissionClick, compact, labelType, rowDecorator } = props;
|
|
14315
15010
|
const currentUser = useAppSelector(selectCurrentUser);
|
|
14316
15011
|
const createdBy = useAppSelector(selectUser("created_by" in submission ? submission.created_by : currentUser.id));
|
|
14317
|
-
const dateToUse =
|
|
14318
|
-
const formattedDateTime =
|
|
14319
|
-
hour: "2-digit",
|
|
14320
|
-
minute: "2-digit"
|
|
14321
|
-
}) : getLocalDateString(dateToUse);
|
|
15012
|
+
const dateToUse = submission.submitted_at;
|
|
15013
|
+
const formattedDateTime = getLocalDateString(dateToUse);
|
|
14322
15014
|
const revision = useAppSelector(selectFormRevision(submission.form_revision));
|
|
14323
15015
|
if (!revision) {
|
|
14324
15016
|
throw new Error(`Could not find revision ${submission.form_revision} for submission ${submission.offline_id}.`);
|
|
14325
15017
|
}
|
|
14326
|
-
const latestRevisionNumber = (_a2 = useAppSelector(
|
|
15018
|
+
const latestRevisionNumber = (_a2 = useAppSelector(selectLatestFormRevisionOfForm(revision.form))) == null ? void 0 : _a2.revision;
|
|
14327
15019
|
const creatorProfileSrc = useFileSrc({
|
|
14328
15020
|
file: (createdBy == null ? void 0 : createdBy.profile.file) ?? null,
|
|
14329
15021
|
fileSha1: (createdBy == null ? void 0 : createdBy.profile.file_sha1) ?? null
|
|
@@ -14354,10 +15046,6 @@ const FormSubmissionBrowserEntry = memo((props) => {
|
|
|
14354
15046
|
return row;
|
|
14355
15047
|
});
|
|
14356
15048
|
FormSubmissionBrowserEntry.displayName = "FormSubmissionBrowserEntry";
|
|
14357
|
-
const getCreatedAtOrSubmittedAtDate = (submission) => {
|
|
14358
|
-
const date = "created_at" in submission ? submission.created_at : submission.submitted_at;
|
|
14359
|
-
return new Date(date);
|
|
14360
|
-
};
|
|
14361
15049
|
const FormSubmissionBrowser = memo((props) => {
|
|
14362
15050
|
const {
|
|
14363
15051
|
formId: formId2,
|
|
@@ -14371,10 +15059,10 @@ const FormSubmissionBrowser = memo((props) => {
|
|
|
14371
15059
|
if (!!formId2 === !!propSubmissions) {
|
|
14372
15060
|
throw new Error("Either formId or submissions must be provided, but not both.");
|
|
14373
15061
|
}
|
|
14374
|
-
const submissions = useAppSelector(propSubmissions ? () => propSubmissions :
|
|
15062
|
+
const submissions = useAppSelector(propSubmissions ? () => propSubmissions : selectFormSubmissionsOfForm(formId2));
|
|
14375
15063
|
const sortedSubmissions = useMemo(
|
|
14376
15064
|
() => submissions == null ? void 0 : submissions.sort((a, b) => {
|
|
14377
|
-
return
|
|
15065
|
+
return a.submitted_at.localeCompare(b.submitted_at);
|
|
14378
15066
|
}),
|
|
14379
15067
|
[submissions]
|
|
14380
15068
|
);
|
|
@@ -15598,6 +16286,7 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
|
|
|
15598
16286
|
export {
|
|
15599
16287
|
APIError,
|
|
15600
16288
|
AgentService,
|
|
16289
|
+
AttachmentModel,
|
|
15601
16290
|
AttachmentService,
|
|
15602
16291
|
AuthService,
|
|
15603
16292
|
BaseApiService,
|
|
@@ -15609,15 +16298,18 @@ export {
|
|
|
15609
16298
|
ColorPicker,
|
|
15610
16299
|
Colors,
|
|
15611
16300
|
ColorsToString,
|
|
16301
|
+
ComponentAttachmentService,
|
|
15612
16302
|
ComponentService,
|
|
15613
16303
|
ComponentStageColors,
|
|
15614
16304
|
ComponentStageCompletionService,
|
|
15615
16305
|
ComponentStageService,
|
|
16306
|
+
ComponentTypeAttachmentService,
|
|
15616
16307
|
ComponentTypeService,
|
|
15617
16308
|
DEFAULT_ISSUE_PRIORITY,
|
|
15618
16309
|
DEFAULT_ISSUE_STATUS,
|
|
15619
16310
|
DateField,
|
|
15620
16311
|
DateInput,
|
|
16312
|
+
DocumentAttachmentService,
|
|
15621
16313
|
DocumentService,
|
|
15622
16314
|
EmailDomainsService,
|
|
15623
16315
|
EmailVerificationService,
|
|
@@ -15641,6 +16333,7 @@ export {
|
|
|
15641
16333
|
InputWithHelpText,
|
|
15642
16334
|
InputWithLabel,
|
|
15643
16335
|
InputWithLabelAndHelpText,
|
|
16336
|
+
IssueAttachmentService,
|
|
15644
16337
|
IssueCommentService,
|
|
15645
16338
|
IssuePriority,
|
|
15646
16339
|
IssueService,
|
|
@@ -15672,6 +16365,7 @@ export {
|
|
|
15672
16365
|
PatchFormProvider,
|
|
15673
16366
|
ProjectAccessLevel,
|
|
15674
16367
|
ProjectAccessService,
|
|
16368
|
+
ProjectAttachmentService,
|
|
15675
16369
|
ProjectFileService,
|
|
15676
16370
|
ProjectService,
|
|
15677
16371
|
ProjectType,
|
|
@@ -15692,6 +16386,7 @@ export {
|
|
|
15692
16386
|
VerificationCodeType,
|
|
15693
16387
|
WorkspaceService,
|
|
15694
16388
|
YELLOW,
|
|
16389
|
+
_selectLatestFormRevision,
|
|
15695
16390
|
_setLatestRetryTime,
|
|
15696
16391
|
acceptProjectInvite,
|
|
15697
16392
|
addActiveProjectFormSubmissionsCount,
|
|
@@ -15709,6 +16404,16 @@ export {
|
|
|
15709
16404
|
addDocuments,
|
|
15710
16405
|
addEmailDomain,
|
|
15711
16406
|
addFavouriteProjectId,
|
|
16407
|
+
addForm,
|
|
16408
|
+
addFormRevision,
|
|
16409
|
+
addFormRevisionAttachment,
|
|
16410
|
+
addFormRevisionAttachments,
|
|
16411
|
+
addFormRevisions,
|
|
16412
|
+
addFormSubmission,
|
|
16413
|
+
addFormSubmissionAttachment,
|
|
16414
|
+
addFormSubmissionAttachments,
|
|
16415
|
+
addFormSubmissions,
|
|
16416
|
+
addForms,
|
|
15712
16417
|
addIssue,
|
|
15713
16418
|
addIssueAttachment,
|
|
15714
16419
|
addIssueAttachments,
|
|
@@ -15729,13 +16434,6 @@ export {
|
|
|
15729
16434
|
addStageCompletions,
|
|
15730
16435
|
addStages,
|
|
15731
16436
|
addToRecentIssues,
|
|
15732
|
-
addUserForm,
|
|
15733
|
-
addUserFormRevision,
|
|
15734
|
-
addUserFormRevisionAttachment,
|
|
15735
|
-
addUserFormRevisions,
|
|
15736
|
-
addUserFormSubmissionAttachment,
|
|
15737
|
-
addUserFormSubmissions,
|
|
15738
|
-
addUserForms,
|
|
15739
16437
|
addUsers,
|
|
15740
16438
|
addWorkspace,
|
|
15741
16439
|
areArraysEqual,
|
|
@@ -15756,6 +16454,7 @@ export {
|
|
|
15756
16454
|
componentStageSlice,
|
|
15757
16455
|
componentTypeReducer,
|
|
15758
16456
|
componentTypeSlice,
|
|
16457
|
+
constructUploadedFilePayloads,
|
|
15759
16458
|
coordinatesAreEqual,
|
|
15760
16459
|
coordinatesToLiteral,
|
|
15761
16460
|
coordinatesToPointGeometry,
|
|
@@ -15766,12 +16465,16 @@ export {
|
|
|
15766
16465
|
defaultBadgeColor,
|
|
15767
16466
|
defaultStore,
|
|
15768
16467
|
deleteComponentType,
|
|
16468
|
+
deleteForm,
|
|
16469
|
+
deleteFormRevision,
|
|
16470
|
+
deleteFormRevisionAttachment,
|
|
16471
|
+
deleteFormRevisionAttachments,
|
|
16472
|
+
deleteFormRevisions,
|
|
16473
|
+
deleteFormSubmission,
|
|
16474
|
+
deleteFormSubmissionAttachment,
|
|
16475
|
+
deleteFormSubmissionAttachments,
|
|
16476
|
+
deleteFormSubmissions,
|
|
15769
16477
|
deleteProject,
|
|
15770
|
-
deleteUserForm,
|
|
15771
|
-
deleteUserFormRevision,
|
|
15772
|
-
deleteUserFormRevisions,
|
|
15773
|
-
deleteUserFormSubmission,
|
|
15774
|
-
deleteUserFormSubmissions,
|
|
15775
16478
|
dequeue,
|
|
15776
16479
|
deserialize,
|
|
15777
16480
|
deserializeField,
|
|
@@ -15800,7 +16503,13 @@ export {
|
|
|
15800
16503
|
fileSlice,
|
|
15801
16504
|
fileToBlob,
|
|
15802
16505
|
flipCoordinates,
|
|
16506
|
+
formReducer,
|
|
16507
|
+
formRevisionReducer,
|
|
15803
16508
|
formRevisionToSchema,
|
|
16509
|
+
formRevisionsSlice,
|
|
16510
|
+
formSlice,
|
|
16511
|
+
formSubmissionReducer,
|
|
16512
|
+
formSubmissionSlice,
|
|
15804
16513
|
index as forms,
|
|
15805
16514
|
fullComponentMarkerSize,
|
|
15806
16515
|
generateBadgeColors,
|
|
@@ -15876,6 +16585,7 @@ export {
|
|
|
15876
16585
|
removeFavouriteProjectId,
|
|
15877
16586
|
removeIssue,
|
|
15878
16587
|
removeIssueAttachment,
|
|
16588
|
+
removeIssueAttachments,
|
|
15879
16589
|
removeIssueComment,
|
|
15880
16590
|
removeIssueComments,
|
|
15881
16591
|
removeIssueUpdate,
|
|
@@ -15928,6 +16638,8 @@ export {
|
|
|
15928
16638
|
selectAttachmentsOfComponentTypeByType,
|
|
15929
16639
|
selectAttachmentsOfDocument,
|
|
15930
16640
|
selectAttachmentsOfDocumentByType,
|
|
16641
|
+
selectAttachmentsOfFormRevision,
|
|
16642
|
+
selectAttachmentsOfFormSubmission,
|
|
15931
16643
|
selectAttachmentsOfIssue,
|
|
15932
16644
|
selectAttachmentsOfIssueByType,
|
|
15933
16645
|
selectAttachmentsOfProject,
|
|
@@ -15945,11 +16657,9 @@ export {
|
|
|
15945
16657
|
selectComponent,
|
|
15946
16658
|
selectComponentAttachment,
|
|
15947
16659
|
selectComponentAttachmentMapping,
|
|
15948
|
-
selectComponentSubmissionMapping,
|
|
15949
16660
|
selectComponentType,
|
|
15950
16661
|
selectComponentTypeAttachment,
|
|
15951
16662
|
selectComponentTypeAttachmentMapping,
|
|
15952
|
-
selectComponentTypeForm,
|
|
15953
16663
|
selectComponentTypeFromComponent,
|
|
15954
16664
|
selectComponentTypeFromComponents,
|
|
15955
16665
|
selectComponentTypeStagesMapping,
|
|
@@ -15979,8 +16689,24 @@ export {
|
|
|
15979
16689
|
selectExpandedSections,
|
|
15980
16690
|
selectFavouriteProjects,
|
|
15981
16691
|
selectFileAttachmentsOfIssue,
|
|
15982
|
-
|
|
16692
|
+
selectFilteredForms,
|
|
16693
|
+
selectForm,
|
|
16694
|
+
selectFormMapping,
|
|
16695
|
+
selectFormOfComponentType,
|
|
15983
16696
|
selectFormRevision,
|
|
16697
|
+
selectFormRevisionMapping,
|
|
16698
|
+
selectFormRevisions,
|
|
16699
|
+
selectFormRevisionsOfForm,
|
|
16700
|
+
selectFormSubmission,
|
|
16701
|
+
selectFormSubmissionAttachmentsMapping,
|
|
16702
|
+
selectFormSubmissions,
|
|
16703
|
+
selectFormSubmissionsByComponents,
|
|
16704
|
+
selectFormSubmissionsMapping,
|
|
16705
|
+
selectFormSubmissionsOfComponent,
|
|
16706
|
+
selectFormSubmissionsOfForm,
|
|
16707
|
+
selectFormSubmissionsOfIssue,
|
|
16708
|
+
selectFormsCount,
|
|
16709
|
+
selectGeneralFormCount,
|
|
15984
16710
|
selectHiddenCategoryCount,
|
|
15985
16711
|
selectHiddenComponentTypeIds,
|
|
15986
16712
|
selectIsFetchingInitialData,
|
|
@@ -15995,10 +16721,10 @@ export {
|
|
|
15995
16721
|
selectIssueUpdateMapping,
|
|
15996
16722
|
selectIssueUpdatesOfIssue,
|
|
15997
16723
|
selectIssues,
|
|
15998
|
-
|
|
16724
|
+
selectLatestFormRevisionByForm,
|
|
16725
|
+
selectLatestFormRevisionOfForm,
|
|
16726
|
+
selectLatestFormRevisionsOfComponentTypes,
|
|
15999
16727
|
selectLatestRetryTime,
|
|
16000
|
-
selectLatestRevisionByFormId,
|
|
16001
|
-
selectLatestRevisionsFromComponentTypeIds,
|
|
16002
16728
|
selectLicense,
|
|
16003
16729
|
selectLicenseForProject,
|
|
16004
16730
|
selectLicenses,
|
|
@@ -16007,8 +16733,6 @@ export {
|
|
|
16007
16733
|
selectMapStyle,
|
|
16008
16734
|
selectNumberOfComponentTypesMatchingCaseInsensitiveName,
|
|
16009
16735
|
selectNumberOfComponentsOfComponentType,
|
|
16010
|
-
selectNumberOfGeneralUserForms,
|
|
16011
|
-
selectNumberOfUserForms,
|
|
16012
16736
|
selectOrganization,
|
|
16013
16737
|
selectOrganizationAccess,
|
|
16014
16738
|
selectOrganizationAccessForUser,
|
|
@@ -16025,6 +16749,7 @@ export {
|
|
|
16025
16749
|
selectProjectAccessForUser,
|
|
16026
16750
|
selectProjectAccessUserMapping,
|
|
16027
16751
|
selectProjectAccesses,
|
|
16752
|
+
selectProjectAttachment,
|
|
16028
16753
|
selectProjectAttachmentMapping,
|
|
16029
16754
|
selectProjectFileVisibility,
|
|
16030
16755
|
selectProjectFiles,
|
|
@@ -16036,8 +16761,6 @@ export {
|
|
|
16036
16761
|
selectRecentIssuesAsSearchResults,
|
|
16037
16762
|
selectRecentProjects,
|
|
16038
16763
|
selectRehydrated,
|
|
16039
|
-
selectRevisionAttachments,
|
|
16040
|
-
selectRevisionsForForm,
|
|
16041
16764
|
selectRootDocuments,
|
|
16042
16765
|
selectShowTooltips,
|
|
16043
16766
|
selectSortedEmailDomains,
|
|
@@ -16052,16 +16775,10 @@ export {
|
|
|
16052
16775
|
selectStagesFromComponentType,
|
|
16053
16776
|
selectStagesFromComponentTypeIds,
|
|
16054
16777
|
selectStagesFromStageIds,
|
|
16055
|
-
selectSubmissionAttachments,
|
|
16056
|
-
selectSubmissionsForComponent,
|
|
16057
|
-
selectSubmissionsForForm,
|
|
16058
|
-
selectSubmissionsForIssue,
|
|
16059
16778
|
selectUploadUrl,
|
|
16060
16779
|
selectUsedColors,
|
|
16061
16780
|
selectUser,
|
|
16062
|
-
|
|
16063
|
-
selectUserFormMapping,
|
|
16064
|
-
selectUserFormSubmission,
|
|
16781
|
+
selectUserFormRevisionAttachmentsMapping,
|
|
16065
16782
|
selectUsersAsMapping,
|
|
16066
16783
|
selectVisibleStatuses,
|
|
16067
16784
|
selectVisibleUserIds,
|
|
@@ -16076,21 +16793,32 @@ export {
|
|
|
16076
16793
|
setAppearance,
|
|
16077
16794
|
setCategories,
|
|
16078
16795
|
setCenterMapToProject,
|
|
16796
|
+
setComponentAttachment,
|
|
16079
16797
|
setComponentAttachments,
|
|
16798
|
+
setComponentTypeAttachment,
|
|
16080
16799
|
setComponentTypeAttachments,
|
|
16081
16800
|
setComponentTypes,
|
|
16082
16801
|
setComponents,
|
|
16083
16802
|
setCreateProjectType,
|
|
16084
16803
|
setCurrentUser,
|
|
16804
|
+
setDocumentAttachment,
|
|
16085
16805
|
setDocumentAttachments,
|
|
16086
16806
|
setDocuments,
|
|
16087
16807
|
setEmailDomains,
|
|
16088
16808
|
setEnableClustering,
|
|
16089
16809
|
setEnableDuplicateIssues,
|
|
16090
16810
|
setEnablePlacementMode,
|
|
16811
|
+
setFormRevision,
|
|
16812
|
+
setFormRevisionAttachments,
|
|
16813
|
+
setFormRevisions,
|
|
16814
|
+
setFormSubmission,
|
|
16815
|
+
setFormSubmissionAttachments,
|
|
16816
|
+
setFormSubmissions,
|
|
16817
|
+
setForms,
|
|
16091
16818
|
setIsFetchingInitialData,
|
|
16092
16819
|
setIsImportingProjectFile,
|
|
16093
16820
|
setIsLoading,
|
|
16821
|
+
setIssueAttachment,
|
|
16094
16822
|
setIssueAttachments,
|
|
16095
16823
|
setIssueComment,
|
|
16096
16824
|
setIssueComments,
|
|
@@ -16103,6 +16831,7 @@ export {
|
|
|
16103
16831
|
setOrganizations,
|
|
16104
16832
|
setProfilePicture,
|
|
16105
16833
|
setProjectAccesses,
|
|
16834
|
+
setProjectAttachment,
|
|
16106
16835
|
setProjectAttachments,
|
|
16107
16836
|
setProjectFileVisible,
|
|
16108
16837
|
setProjects,
|
|
@@ -16112,9 +16841,6 @@ export {
|
|
|
16112
16841
|
setTokens,
|
|
16113
16842
|
setTourStep,
|
|
16114
16843
|
setUploadUrl,
|
|
16115
|
-
setUserFormRevisionAttachments,
|
|
16116
|
-
setUserFormSubmissionAttachments,
|
|
16117
|
-
setUserFormSubmissions,
|
|
16118
16844
|
setUsers,
|
|
16119
16845
|
setVisibleStatuses,
|
|
16120
16846
|
setVisibleUserIds,
|
|
@@ -16136,17 +16862,24 @@ export {
|
|
|
16136
16862
|
updateActiveOrganization,
|
|
16137
16863
|
updateComponent,
|
|
16138
16864
|
updateComponentAttachment,
|
|
16865
|
+
updateComponentAttachments,
|
|
16139
16866
|
updateComponentTypeAttachment,
|
|
16867
|
+
updateComponentTypeAttachments,
|
|
16140
16868
|
updateDocumentAttachment,
|
|
16869
|
+
updateDocumentAttachments,
|
|
16141
16870
|
updateDocuments,
|
|
16871
|
+
updateFormSubmission,
|
|
16872
|
+
updateFormSubmissionAttachments,
|
|
16873
|
+
updateFormSubmissions,
|
|
16142
16874
|
updateIssue,
|
|
16143
16875
|
updateIssueAttachment,
|
|
16876
|
+
updateIssueAttachments,
|
|
16144
16877
|
updateLicense,
|
|
16145
16878
|
updateOrCreateProject,
|
|
16146
|
-
updateOrCreateUserFormSubmission,
|
|
16147
16879
|
updateOrganizationAccess,
|
|
16148
16880
|
updateProjectAccess,
|
|
16149
16881
|
updateProjectAttachment,
|
|
16882
|
+
updateProjectAttachments,
|
|
16150
16883
|
updateStages,
|
|
16151
16884
|
useAppDispatch,
|
|
16152
16885
|
useAppSelector,
|
|
@@ -16157,8 +16890,6 @@ export {
|
|
|
16157
16890
|
useFormikInput,
|
|
16158
16891
|
useMemoCompare,
|
|
16159
16892
|
useSDK,
|
|
16160
|
-
userFormReducer,
|
|
16161
|
-
userFormSlice,
|
|
16162
16893
|
userReducer,
|
|
16163
16894
|
userSlice,
|
|
16164
16895
|
valueIsFile,
|