Mirror of https://github.com/roostorg/coop github.com/roostorg/coop
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add matched banks info on NCMEC view (#48)

authored by

Juan Mrad and committed by
GitHub
4fb2c5fb 667c6c10

+77 -28
+44 -28
client/src/webpages/dashboard/mrt/manual_review_job/v2/ncmec/NCMECInspectedMedia.tsx
··· 26 26 import NCMECLabelSelector from './NCMECLabelSelector'; 27 27 import NCMECMediaViewer from './NCMECMediaViewer'; 28 28 import { 29 + getMatchedBanksForMediaUrl, 29 30 NCMECCategory, 30 31 NCMECMediaIdentifier, 31 32 NCMECMediaQueryResult, ··· 166 167 const navigationButtons = ( 167 168 <div className="flex items-center justify-between w-full mb-3"> 168 169 <div 169 - className={`cursor-pointer py-1 px-3 rounded border border-solid ${ 170 - index === 0 170 + className={`cursor-pointer py-1 px-3 rounded border border-solid ${index === 0 171 171 ? 'text-slate-300 border-slate-100' 172 172 : 'text-coop-blue border-coop-blue hover:border-coop-blue hover:bg-coop-lightblue' 173 - }`} 173 + }`} 174 174 onClick={goToPreviousMedia} 175 175 > 176 176 <ArrowLeftOutlined className="pr-1 text-xs" /> Previous 177 177 </div> 178 - <div className="text-sm text-slate-500">{`${ 179 - index + 1 180 - } / ${totalLength}`}</div> 178 + <div className="text-sm text-slate-500">{`${index + 1 179 + } / ${totalLength}`}</div> 181 180 <div 182 - className={`cursor-pointer py-1 px-3 rounded border border-solid ${ 183 - index === totalLength - 1 181 + className={`cursor-pointer py-1 px-3 rounded border border-solid ${index === totalLength - 1 184 182 ? 'text-slate-300 border-slate-100' 185 183 : 'text-coop-blue border-coop-blue hover:border-coop-blue hover:bg-coop-lightblue' 186 - }`} 184 + }`} 187 185 onClick={goToNextMedia} 188 186 > 189 187 Next <ArrowRightOutlined className="pl-1 text-xs" /> ··· 192 190 ); 193 191 const threadInfoFields = threadInfo 194 192 ? threadInfo.type.baseFields 195 - .map( 196 - (itemTypeField) => 197 - ({ 198 - ...itemTypeField, 199 - value: threadInfo.data[itemTypeField.name], 200 - }) as ItemTypeFieldFieldData, 201 - ) 202 - .filter((field) => { 203 - return isContainerType(field.type) 204 - ? !isMediaType(field.container!.valueScalarType) && 205 - field.container!.valueScalarType !== ScalarTypes.RELATED_ITEM && 206 - threadInfo.data[field.name] !== undefined 207 - : !isMediaType(field.type) && 208 - field.type !== ScalarTypes.RELATED_ITEM && 209 - threadInfo.data[field.name] !== undefined; 210 - }) 193 + .map( 194 + (itemTypeField) => 195 + ({ 196 + ...itemTypeField, 197 + value: threadInfo.data[itemTypeField.name], 198 + }) as ItemTypeFieldFieldData, 199 + ) 200 + .filter((field) => { 201 + return isContainerType(field.type) 202 + ? !isMediaType(field.container!.valueScalarType) && 203 + field.container!.valueScalarType !== ScalarTypes.RELATED_ITEM && 204 + threadInfo.data[field.name] !== undefined 205 + : !isMediaType(field.type) && 206 + field.type !== ScalarTypes.RELATED_ITEM && 207 + threadInfo.data[field.name] !== undefined; 208 + }) 211 209 : []; 212 210 const threadComponent = (() => { 213 211 if (threadLoading) { ··· 295 293 setIsOpen={setIsLabelSelectorInInspectedMediaVisible} 296 294 /> 297 295 </div> 296 + {(() => { 297 + const matchedBanks = getMatchedBanksForMediaUrl( 298 + fullNcmecContentItem.contentItem, 299 + mediaId.urlInfo.url, 300 + ); 301 + if (matchedBanks.length === 0) return null; 302 + return ( 303 + <> 304 + {divider} 305 + <div className="flex flex-col w-full gap-2 text-start"> 306 + <div className="text-base font-bold pb-0.5">Matched</div> 307 + <div className="w-full px-3 py-2 text-sm border border-gray-200 border-solid rounded-md bg-white min-h-[32px] flex items-center"> 308 + [ {matchedBanks.join(', ')} ] 309 + </div> 310 + </div> 311 + </> 312 + ); 313 + })()} 298 314 </div> 299 315 {divider} 300 316 <div className="text-base font-bold pb-0.5">Media Info</div> ··· 303 319 fields={fieldData.filter((field) => { 304 320 return isContainerType(field.type) 305 321 ? !isMediaType(field.container!.valueScalarType) && 306 - field.container!.valueScalarType !== 307 - ScalarTypes.RELATED_ITEM 322 + field.container!.valueScalarType !== 323 + ScalarTypes.RELATED_ITEM 308 324 : !isMediaType(field.type) && 309 - field.type !== ScalarTypes.RELATED_ITEM; 325 + field.type !== ScalarTypes.RELATED_ITEM; 310 326 })} 311 327 itemTypeId={fullNcmecContentItem.contentItem.type.id} 312 328 />
+33
client/src/webpages/dashboard/mrt/manual_review_job/v2/ncmec/NCMECReviewUser.tsx
··· 143 143 ); 144 144 } 145 145 146 + /** Get matched bank names for a given media URL from the content item's field data. */ 147 + export function getMatchedBanksForMediaUrl( 148 + item: NCMECMediaQueryResult['contentItem'], 149 + mediaUrl: string, 150 + ): string[] { 151 + const mediaFields = item.type.baseFields.filter( 152 + (it) => 153 + it.type === 'IMAGE' || 154 + it.type === 'VIDEO' || 155 + it.container?.valueScalarType === 'IMAGE' || 156 + it.container?.valueScalarType === 'VIDEO', 157 + ); 158 + for (const field of mediaFields) { 159 + const valueOrValues = getFieldValueOrValues(item.data, field) as 160 + | { value: { url?: string; matchedBanks?: string[] }; type: string } 161 + | { value: { url?: string; matchedBanks?: string[] }; type: string }[] 162 + | undefined; 163 + if (valueOrValues === undefined) continue; 164 + const values = Array.isArray(valueOrValues) ? valueOrValues : [valueOrValues]; 165 + for (const tagged of values) { 166 + const v = tagged.value; 167 + if (v?.url === mediaUrl) { 168 + const matchedBanks = v?.matchedBanks; 169 + if (Array.isArray(matchedBanks) && matchedBanks.length > 0) { 170 + return matchedBanks; 171 + } 172 + return []; 173 + } 174 + } 175 + } 176 + return []; 177 + } 178 + 146 179 // Mapping from GraphQL enum values to display labels 147 180 const NCMEC_INCIDENT_TYPE_LABELS: Record<GQLNcmecIncidentType, string> = { 148 181 [GQLNcmecIncidentType.ChildPornography]: