|
1 | 1 | 'use strict'; |
2 | 2 | /** |
3 | 3 | * Bulk Edit Operations for Modular List |
4 | | - * Handles bulk edit, bulk delete, bulk messaging functionality |
| 4 | + * Handles bulk edit, bulk delete, bulk messaging functionality. |
| 5 | + * |
| 6 | + * This module is the primary home for bulk behavior on modular lists. |
| 7 | + * New bulk-related features (edit, delete, share/follow, messaging, app actions) |
| 8 | + * should be implemented here rather than in modular-list.js. |
5 | 9 | * |
6 | 10 | * Organized into three main sections: |
7 | 11 | * 1. Bulk Operations & List Controls - Checkbox handling, record counting, shared queue processing |
|
878 | 882 | * Field Value Collection |
879 | 883 | */ |
880 | 884 |
|
| 885 | + function normalizeShareComponentItems(rawValue) { |
| 886 | + if (rawValue === null || rawValue === undefined) { |
| 887 | + return []; |
| 888 | + } |
| 889 | + |
| 890 | + let value = rawValue; |
| 891 | + |
| 892 | + if (typeof rawValue === 'string') { |
| 893 | + const trimmed = rawValue.trim(); |
| 894 | + if (!trimmed || trimmed === 'null' || trimmed === '[]') { |
| 895 | + return []; |
| 896 | + } |
| 897 | + try { |
| 898 | + value = JSON.parse(trimmed); |
| 899 | + } catch (e) { |
| 900 | + console.error( |
| 901 | + 'Error parsing share component string value as JSON:', |
| 902 | + e, |
| 903 | + 'Value was:', |
| 904 | + rawValue, |
| 905 | + ); |
| 906 | + return []; |
| 907 | + } |
| 908 | + } else if (Array.isArray(rawValue)) { |
| 909 | + value = rawValue; |
| 910 | + } else if (typeof rawValue === 'object') { |
| 911 | + value = Array.isArray(rawValue.value) ? rawValue.value : [rawValue]; |
| 912 | + } else { |
| 913 | + // Unexpected primitive type (number, boolean, etc.) |
| 914 | + return []; |
| 915 | + } |
| 916 | + |
| 917 | + return Array.isArray(value) ? value : []; |
| 918 | + } |
| 919 | + |
881 | 920 | function collectFieldValue(fieldKey, fieldType, fieldWrapper) { |
882 | 921 | // Special case: comment field (not a real post field type) |
883 | 922 | if (fieldType === 'comment') { |
|
922 | 961 | } |
923 | 962 |
|
924 | 963 | // Fallback: check component value directly |
925 | | - // dt-users-connection provides user IDs directly, so extract them |
| 964 | + // dt-users-connection should expose an array (or JSON string) of items |
926 | 965 | if (shareComponent && shareComponent.value) { |
927 | | - try { |
928 | | - let value; |
929 | | - if (typeof shareComponent.value === 'string') { |
930 | | - const trimmed = shareComponent.value.trim(); |
931 | | - if (trimmed === '' || trimmed === '[]' || trimmed === 'null') { |
932 | | - return null; |
933 | | - } |
934 | | - value = JSON.parse(shareComponent.value); |
935 | | - } else if (Array.isArray(shareComponent.value)) { |
936 | | - value = shareComponent.value; |
937 | | - } else { |
938 | | - return null; |
939 | | - } |
| 966 | + const items = normalizeShareComponentItems(shareComponent.value); |
| 967 | + if (items.length === 0) { |
| 968 | + return null; |
| 969 | + } |
940 | 970 |
|
941 | | - if (Array.isArray(value) && value.length > 0) { |
942 | | - // Extract user IDs directly from dt-users-connection format |
943 | | - const userIds = value |
944 | | - .map((item) => { |
945 | | - const userId = item.id || item.user_id || null; |
946 | | - return userId ? parseInt(userId, 10) : null; |
947 | | - }) |
948 | | - .filter((id) => id !== null); |
949 | | - |
950 | | - if (userIds.length > 0) { |
951 | | - // Cache in fieldData for future use |
952 | | - if (fieldData) { |
953 | | - fieldData.shareUserIds = userIds; |
954 | | - fieldData.shareUserId = userIds[0]; |
955 | | - // Store labels if available |
956 | | - fieldData.shareUserLabels = {}; |
957 | | - value.forEach((item) => { |
958 | | - const userId = item.id || item.user_id; |
959 | | - if (userId) { |
960 | | - fieldData.shareUserLabels[userId] = item.label || ''; |
961 | | - } |
962 | | - }); |
963 | | - } |
964 | | - return userIds; |
| 971 | + const userIds = items |
| 972 | + .map((item) => { |
| 973 | + const userId = item.id || item.user_id || null; |
| 974 | + return userId ? parseInt(userId, 10) : null; |
| 975 | + }) |
| 976 | + .filter((id) => id !== null); |
| 977 | + |
| 978 | + if (userIds.length === 0) { |
| 979 | + return null; |
| 980 | + } |
| 981 | + |
| 982 | + if (fieldData) { |
| 983 | + fieldData.shareUserIds = userIds; |
| 984 | + fieldData.shareUserId = userIds[0]; |
| 985 | + fieldData.shareUserLabels = {}; |
| 986 | + items.forEach((item) => { |
| 987 | + const userId = item.id || item.user_id; |
| 988 | + if (userId) { |
| 989 | + fieldData.shareUserLabels[userId] = item.label || ''; |
965 | 990 | } |
966 | | - } |
967 | | - } catch (e) { |
968 | | - console.error( |
969 | | - 'Error parsing share component value in collectFieldValue:', |
970 | | - e, |
971 | | - ); |
| 991 | + }); |
972 | 992 | } |
| 993 | + |
| 994 | + return userIds; |
973 | 995 | } |
974 | 996 |
|
975 | 997 | return null; |
|
1960 | 1982 | } |
1961 | 1983 |
|
1962 | 1984 | // Function to process component value and update fieldData |
1963 | | - // dt-users-connection provides user IDs directly, so no conversion needed |
| 1985 | + // dt-users-connection provides user IDs directly |
1964 | 1986 | const processShareComponentValue = async function (componentValue) { |
1965 | 1987 | const currentFieldData = bulkEditSelectedFields.find( |
1966 | 1988 | (f) => f.fieldKey === fieldKey, |
|
1969 | 1991 | return; |
1970 | 1992 | } |
1971 | 1993 |
|
1972 | | - // Handle empty or invalid values |
1973 | | - // componentValue might be a string, array, or object |
1974 | | - if ( |
1975 | | - !componentValue || |
1976 | | - componentValue === null || |
1977 | | - componentValue === undefined |
1978 | | - ) { |
1979 | | - // Value is null/undefined |
1980 | | - currentFieldData.shareUserIds = []; |
1981 | | - currentFieldData.shareUserLabels = {}; |
1982 | | - currentFieldData.shareUserId = null; |
1983 | | - currentFieldData.shareUserLabel = null; |
1984 | | - return; |
1985 | | - } |
1986 | | - |
1987 | | - // Handle if componentValue is already an array or object |
1988 | | - let value; |
1989 | | - if (Array.isArray(componentValue)) { |
1990 | | - value = componentValue; |
1991 | | - } else if (typeof componentValue === 'object') { |
1992 | | - // If it's an object, try to convert to array format |
1993 | | - value = Array.isArray(componentValue.value) |
1994 | | - ? componentValue.value |
1995 | | - : [componentValue]; |
1996 | | - } else if (typeof componentValue === 'string') { |
1997 | | - // Handle string values |
1998 | | - const trimmed = componentValue.trim(); |
1999 | | - if ( |
2000 | | - trimmed === '' || |
2001 | | - trimmed === 'null' || |
2002 | | - trimmed === '[]' || |
2003 | | - trimmed === 'undefined' |
2004 | | - ) { |
2005 | | - // Value is empty/null/empty array string |
2006 | | - currentFieldData.shareUserIds = []; |
2007 | | - currentFieldData.shareUserLabels = {}; |
2008 | | - currentFieldData.shareUserId = null; |
2009 | | - currentFieldData.shareUserLabel = null; |
2010 | | - return; |
2011 | | - } |
2012 | | - // Try to parse as JSON |
2013 | | - try { |
2014 | | - value = JSON.parse(componentValue); |
2015 | | - } catch (e) { |
2016 | | - console.error( |
2017 | | - 'Error parsing share component value as JSON:', |
2018 | | - e, |
2019 | | - 'Value was:', |
2020 | | - componentValue, |
2021 | | - ); |
2022 | | - // Clear field data on parse error |
2023 | | - currentFieldData.shareUserIds = []; |
2024 | | - currentFieldData.shareUserLabels = {}; |
2025 | | - currentFieldData.shareUserId = null; |
2026 | | - currentFieldData.shareUserLabel = null; |
2027 | | - return; |
2028 | | - } |
2029 | | - } else { |
2030 | | - // Unknown type |
2031 | | - console.error( |
2032 | | - 'Share component value has unexpected type:', |
2033 | | - typeof componentValue, |
2034 | | - componentValue, |
2035 | | - ); |
2036 | | - return; |
2037 | | - } |
| 1994 | + const items = normalizeShareComponentItems(componentValue); |
2038 | 1995 |
|
2039 | | - // Now process the value (should be an array at this point) |
2040 | 1996 | try { |
2041 | | - if (Array.isArray(value) && value.length > 0) { |
| 1997 | + if (items.length > 0) { |
2042 | 1998 | // dt-users-connection format: [{id: <userId>, type: 'user', label: <displayName>}] |
2043 | 1999 | // Extract user IDs directly - no conversion needed! |
2044 | | - const userIds = value |
| 2000 | + const userIds = items |
2045 | 2001 | .map((item) => { |
2046 | 2002 | // item.id is the user ID directly |
2047 | 2003 | const userId = item.id || item.user_id || null; |
|
2052 | 2008 | // Store user IDs and labels |
2053 | 2009 | currentFieldData.shareUserIds = userIds; |
2054 | 2010 | currentFieldData.shareUserLabels = {}; |
2055 | | - value.forEach((item) => { |
| 2011 | + items.forEach((item) => { |
2056 | 2012 | const userId = item.id || item.user_id; |
2057 | 2013 | if (userId) { |
2058 | 2014 | currentFieldData.shareUserLabels[userId] = item.label || ''; |
|
0 commit comments