From 69983ff83a712c5e2b6d5f939fc12174dc40bcd6 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 17 Feb 2024 11:00:55 -0600 Subject: [PATCH] feat: enhance search (#7127) * feat: hybrid search * fixing normal search * building out the query * okla * filters * date * order by date * Remove hybrid search endpoint * remove search hybrid endpoint * faces query * search for person * search and pagination * with exif * with exif * justify gallery viewer * memory view * Fixed userId is null * openapi and styling * searchdto * lint and format * remove term * generate sql * fix test * chips * not showing true * pr feedback * pr feedback * nit name * linting * pr feedback * styling * linting --- mobile/openapi/.openapi-generator/FILES | 6 + mobile/openapi/README.md | Bin 24416 -> 24512 bytes mobile/openapi/doc/AssetApi.md | Bin 57625 -> 57883 bytes mobile/openapi/doc/MetadataSearchDto.md | Bin 0 -> 2462 bytes mobile/openapi/doc/SearchApi.md | Bin 21245 -> 13525 bytes mobile/openapi/doc/SmartSearchDto.md | Bin 0 -> 1859 bytes mobile/openapi/lib/api.dart | Bin 8306 -> 8381 bytes mobile/openapi/lib/api/asset_api.dart | Bin 59421 -> 59931 bytes mobile/openapi/lib/api/search_api.dart | Bin 29053 -> 12967 bytes mobile/openapi/lib/api_client.dart | Bin 23526 -> 23692 bytes .../lib/model/metadata_search_dto.dart | Bin 0 -> 32394 bytes .../openapi/lib/model/smart_search_dto.dart | Bin 0 -> 23646 bytes mobile/openapi/test/asset_api_test.dart | Bin 5729 -> 5772 bytes .../test/metadata_search_dto_test.dart | Bin 0 -> 4948 bytes mobile/openapi/test/search_api_test.dart | Bin 2714 -> 1490 bytes .../openapi/test/smart_search_dto_test.dart | Bin 0 -> 3635 bytes open-api/immich-openapi-specs.json | 897 ++++------ open-api/typescript-sdk/axios-client/api.ts | 1504 ++++++----------- open-api/typescript-sdk/fetch-client.ts | Bin 75448 -> 73711 bytes .../domain/repositories/search.repository.ts | 19 +- server/src/domain/search/dto/search.dto.ts | 6 + server/src/domain/search/search.service.ts | 3 +- .../immich/controllers/search.controller.ts | 10 +- server/src/infra/infra.utils.ts | 35 +- .../infra/repositories/search.repository.ts | 2 +- server/src/infra/sql/search.repository.sql | 4 +- web/.eslintrc.cjs | 1 + .../memory-page/memory-viewer.svelte | 13 +- .../photos-page/asset-date-group.svelte | 24 +- .../individual-shared-viewer.svelte | 6 +- .../shared-components/control-app-bar.svelte | 2 +- .../gallery-viewer/gallery-viewer.svelte | 45 +- .../search-bar/search-bar.svelte | 62 +- .../search-bar/search-filter-box.svelte | 161 +- .../search-bar/search-history-box.svelte | 9 - web/src/lib/constants.ts | 1 + web/src/lib/stores/search.store.ts | 2 + web/src/lib/utils/timeline-util.ts | 17 + web/src/routes/(user)/search/+page.svelte | 189 ++- web/src/routes/(user)/search/+page.ts | 32 +- 40 files changed, 1298 insertions(+), 1752 deletions(-) create mode 100644 mobile/openapi/doc/MetadataSearchDto.md create mode 100644 mobile/openapi/doc/SmartSearchDto.md create mode 100644 mobile/openapi/lib/model/metadata_search_dto.dart create mode 100644 mobile/openapi/lib/model/smart_search_dto.dart create mode 100644 mobile/openapi/test/metadata_search_dto_test.dart create mode 100644 mobile/openapi/test/smart_search_dto_test.dart diff --git a/mobile/openapi/.openapi-generator/FILES b/mobile/openapi/.openapi-generator/FILES index aeb3d49cb4..f42a9c82ca 100644 --- a/mobile/openapi/.openapi-generator/FILES +++ b/mobile/openapi/.openapi-generator/FILES @@ -90,6 +90,7 @@ doc/MapMarkerResponseDto.md doc/MapTheme.md doc/MemoryLaneResponseDto.md doc/MergePersonDto.md +doc/MetadataSearchDto.md doc/ModelType.md doc/OAuthApi.md doc/OAuthAuthorizeResponseDto.md @@ -137,6 +138,7 @@ doc/SharedLinkResponseDto.md doc/SharedLinkType.md doc/SignUpDto.md doc/SmartInfoResponseDto.md +doc/SmartSearchDto.md doc/SystemConfigApi.md doc/SystemConfigDto.md doc/SystemConfigFFmpegDto.md @@ -288,6 +290,7 @@ lib/model/map_marker_response_dto.dart lib/model/map_theme.dart lib/model/memory_lane_response_dto.dart lib/model/merge_person_dto.dart +lib/model/metadata_search_dto.dart lib/model/model_type.dart lib/model/o_auth_authorize_response_dto.dart lib/model/o_auth_callback_dto.dart @@ -329,6 +332,7 @@ lib/model/shared_link_response_dto.dart lib/model/shared_link_type.dart lib/model/sign_up_dto.dart lib/model/smart_info_response_dto.dart +lib/model/smart_search_dto.dart lib/model/system_config_dto.dart lib/model/system_config_f_fmpeg_dto.dart lib/model/system_config_job_dto.dart @@ -457,6 +461,7 @@ test/map_marker_response_dto_test.dart test/map_theme_test.dart test/memory_lane_response_dto_test.dart test/merge_person_dto_test.dart +test/metadata_search_dto_test.dart test/model_type_test.dart test/o_auth_api_test.dart test/o_auth_authorize_response_dto_test.dart @@ -504,6 +509,7 @@ test/shared_link_response_dto_test.dart test/shared_link_type_test.dart test/sign_up_dto_test.dart test/smart_info_response_dto_test.dart +test/smart_search_dto_test.dart test/system_config_api_test.dart test/system_config_dto_test.dart test/system_config_f_fmpeg_dto_test.dart diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index 12d20ea13d1244f3711942071cb154f0753e93fb..9e241b0a44e30227c1b0f28910d87e6afd74bc4b 100644 GIT binary patch delta 108 zcmaE`kMY2M#to7>%mMzvlcjZbfauLvbs`m1Q%e$45=#<;Qxl7lGh9mYV>MFpllAp| fQN%YZ`o?m|<|Y=EpsNdp2~NHkCbhXU^g1U1hh`{< delta 35 tcmV+;0Nnq;zX9OB0k9b?llv+TlPD~#0!Kx&*DP5evtmt92(#W*;t3B=4z>UQ diff --git a/mobile/openapi/doc/AssetApi.md b/mobile/openapi/doc/AssetApi.md index 963e2e66c51b6d52b5f5b7999f8e1c03d90306f3..5691965bc71c730a54aaa2bbee3afcdc0823d2d2 100644 GIT binary patch delta 244 zcmbPvh^;k$vmmvoI6u!brFipTAMggQEzn~;DKQA#SRv|hiH7&6; Xr$nJ7Um-a^ueb#0zSzxz>o|-7?Ui30 delta 82 zcmbPzgn8y6<_%i2CMR4`oE*2pfAi*9)$Ehk-^$#)cTpYV=9DF;nPF0sH_zHRxwF@Q k^MRE=nI>!9uiKomHlC5KD784VDs}R^4eFa+)?YUQ0Kda2djJ3c diff --git a/mobile/openapi/doc/MetadataSearchDto.md b/mobile/openapi/doc/MetadataSearchDto.md new file mode 100644 index 0000000000000000000000000000000000000000..bfbf81749e94d0b23eb636ed0d188e8efd4c6217 GIT binary patch literal 2462 zcmbtW!A|2a5WVLsEcF15)N-EH?l}gYCL+l$ZFCEr|*6`@c5+eq$ zemwbVG#DHkXL(+3pnUY(D$g05=L>RZ9^!zU%=5PlG@XA^p$=_`c`bkqno4XVF%snu&VaoF^=!M)_htzC%H*{u$ zR1?y(l&5B-SATWbRlxOntz z9}mg9&S3PGgw)olmopUwe%;Izr!S+A&K0-!0a*+es390oQobf6QR+22W6NsVp1+eX zTcEdQs(cH)L{C4Oz4;lZ-bO4HtmRgdAS+61Jc(sduxmN+_zM#23eaP9d18xdL0zpP z?x^{+x5ensI~zIaH(#*UHvS6*@QoEWi7h!QE?i-g*z8tlxOY8e%WVaQPX&AZfUn{~G%4Q~FVUm`;Ya&PO!` literal 21245 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 GhXVj%lND6} delta 21 dcmdn%_{m{|uHfbn!E(0A3evor|A-&t003V`2p#|c diff --git a/mobile/openapi/lib/api/asset_api.dart b/mobile/openapi/lib/api/asset_api.dart index 97c9e7cbec0c1edbf0658049b1f7c447df11ceb4..bdcb874092378527d0ccb73ea9673e4c99e60141 100644 GIT binary patch delta 376 zcmbPxfqC{7<_(4uxcu@;>i;j#e6c0OKgHmiZb)k?P3)Q zQj3c7^E^`~Hy)ANJbPj|GqN`84adcimD|IW7jN1a$hi66v~6t2>JM62N+N7k*HOqU zMsO!z%omv~bw_g2T=mUg=8Ca!!mKWye9*#JF1IwNBonAb9WD&yz}cIBEbQb&wu(p} myr!8&WWZgiW#bSAJb&!=gyN~Z=Jt+!M18+0A|cEt^fc4 diff --git a/mobile/openapi/lib/api/search_api.dart b/mobile/openapi/lib/api/search_api.dart index 16d2b3003e2c7f26e05ccb909b3ceee59b3eebb9..062ca4a50b7ca7ab6ecb8f1ccfa65f4d2d63ea3b 100644 GIT binary patch delta 574 zcmezSh;e!9hG0470RQ00p>omszNsaNDTyVC!KsNw$r&ys`LPPQ=t2q_MX80QnMJ87 znv)lLN>A2P5mmv^hpA0x@<&g<$qUt;MHFl?WhWot?3irJEGML%SWu9YnVeXXnV+Yh zRh*xvK3Rar0_?zv5}QbNpud!=F3fQnFb3RrnC{S-{9j6Y@^vRsAq;=(Y;JVp=K{NA zQb43eZemdh+@M&6ViZ1l81aV+%c3ekRSyZA4dD)gz`#M3A~Iw&gHg=K=OAF1sDM># Zpz1-h7!nl8IYRuX4g!Tk2@_K-7XTUI(;WZ+ literal 29053 zcmeHQ-E-SE5`Xt!f%c)cZ*+Dq(}x>1iO*@A#xqTvOWbB|G9H(fAe$GNlu0U%FO&cM zcCotvNPtofa?*>dhnV=<{ShC#*j<3i?(W9!uG;_g_~@@cA3Q&Jxqp1{SUoxX>2-EfpU&pZX{E2`c?IM}b_suHSq0BVS2ZxN>NxqREb1mJn$vs? zfcYfXl_9UAVAH(N_35-M&Y@Xzkrk(Z|NeAzkyZ7^2Ea9{oTzf9i)@zfz`q|iHa14n ztgh87omHcY{aLO)Y$%u8dILp2O>=g{j?zp?;w&80O1bWrccreEdRf{(Nw(c5CxuyZZfX3Nx{ZZ(n6iUKY@9tSa5i ztD;uTg;sA~>UsvFrB8MM@W~u%^nEFNsLpkBKujKIP4+r(E}k~c?68=WTiYtDZ;FxW zx>9!9hiX>o2@Ir}gVV8wp(5-W0HjZ|ths<8s5ZN=YI+u9XT}01X_QTg(b3tz^#}%d zR@Tj-&xapA`i*g< z7dADFO}`cVZD9V7Z)V!O0W(B&oLR+_;HGpZFW!}J_5O>)EmN-)j?sYAIIWwK@j53( zG6<6Q`z2-W^`*pr$(_7DxSTaNYEKpO=@iy#tJcUG(QV_He8gVxa``2%oBJdSyjWxb zJ#NZ}d)-ykSvfRe6)!`Si|Z_J7Op&+lzgJLglq@Iy_wfPm1C_QK2W$wUzw7fvuykl zG>ER7ZC=U;6eQsFg$4(_}l5U;DqRY;3Kb(LL)3A69Gg>{Qla1(E@mj9n>-qUPtZZ1o z^`|R&!`AMiLwE@&p}*=c>J16I3WgJ$ZFe{(B1F)yv__xvY7cf%r^^YlvGBCgg(iCO?xfLjSJWSE zSw`)$jn&n1^;Wm!v+2F|rfoNDa38v_&{oX22nR}p8*NUreUMBJSpyp>f($8Ov+#$s z{s)Rpu$Co)E!MW++7>i!u1d58Nw5}Je$?QL*m<{R+ntr=6l}CBJ6Mhr?Ny^WQ)&`HHkwaZz2ZflnA+_d?oTmQs9h_2wzk@sf>{p zIpZ^AjdGvJ8A*XLK0>~}4oT$ivj7}F>+sfYL@SCy`^|c%?d-JV4S3;Uhz`@9yY>IN z&-S=B5lev#D>f9^k^-*Rdxta! z$@!3@SH3I`TavkUjqY}soCC&71Krf1KXML1wm>L12PWVhlv9-5X!=#6)^L2Ajo~=) z*4!F#HAWYD^tPT~2G+lAkT?CIX^uSv#BlPdkKy129H&Y{db~e@dRw z0dHIX9!3Pts(Twe$=;Q4W)+TxaCjDXJf-?*GQm^&Uj8rP9QUZ0hLbA{e#`3|&tCeR z#;GpqXBc4WZ;_u>S#`5uDlm@ROHM(oF1(rkqYBQTPgIGIUV0e5bG#1l1a4G3hZ_(} z8%7tyaz`G{>|oF7C&t=dY>LfwJLv?dfe|W}iH~X2BRn3fDyuJ+%VI;#df1uaKL)$` zzzhsp&_UlE%6!GU~J&+=f*ZOQ09c5avt&P1qpsvYdxKjffDR^nu;^2KgSy25# zm$QgiIQmyjHhQ}-TJnt5`D_1nhO3pdr-a=~=jP#QN8k)5tmw zElt`jJ{-G}uC8=7Ikdt)?jE-rz0HOx6QD4kUPK#IKK5#dYfE0r}-BX>$g06b-wisG?AC@0Z#F03nvH}!yU@Xo#Fo?C{ebn`JX!xE9zXst; zbrM(!LdmuPL`V87DYy~TOVnTSRd zPf#x_!}==yEyT^}ZGpZ*e)=$lZ>o6+VSv};A_>HD#u zjf3<}kLAsJAZ5YHW*;zer&>!+ym1TXO?3ei+z%I2(>AuC0q;H7f-fQmH!ke;C^=+< zYf{urI1O7LteNvVR$y}OlGmcKTnVcvcj{wxl2;^3$Q7a1@p7nU2FmG`^}!n4irEvl zfrQcxmq?+^f^Qc4Wh`fY5ek-{CrR>4SagDewS|}UM224b2h~=L;Nv4JPdH8D& zX1s5c{PPniuH2;{d$z(FN-AY+T89$D_8Em7S-=GouE3+~Zlr%0lwh=e2><+;I^=D9 z9m_cej>VibrD9rOF{iQIS`=Oy%h`~yDJ&D~!6mU&BoF~5jpbr0xTF`#9J;8c7kPwI zCz!?zh<+7DmuKXpyL-Ytgo<_;4I_C}f{Vg9Jq_6*O$|rtMj{^(gBz#C532&UZ5ndr$MN`DVD#{3k`3atNtcos2`mw4N zq{)0#Pa-6O#lK-h-+NHi*8eI|3(eAq#FD6*J&^_8ORvA|xZ7WLv=_^l`~jqJ;rD<4 z9=81=pTh5&Z=r5|12!LFE!u%4wq!iR?tN@q`A3AgBOfG4?089(%Q}NSF)HU3_BODt zVs}X775=2b=l<_3OpWm!yF(_cs5Z`Ix7NiopL`J(G z)sYe#(6I$Jlp`e~rH&1WrOSWe7%B*X{BDLxqCB|Bp%DOo)ZB^>N@;7! zlM#rAL!^8NN#X0yduiUOxWqm=2GAjw343GBpJX6by#|NVQ5aUp={U@QfH)IF5=Ebk zBn%9aWMW9Pfh6M)xj~_141+hNWDuq|D4dSL$N@z%jxaDll8GVl@kcTc(;FO4hcNbN zGZDtp1B^{aVB}OL6-MY0M$#b+p7 z&&KiCKVAWjIWQXM;$Z0itbl~%41-CB0WpsCQ3wTk{G*U{Tr>WAHf%!&u`KlGPrz#s z)3>()S*^X*Y;N|}iq6#(2DsMh*Qpd-Yn^;r=RkqMk X0-0;*p+EVlsrY0$7oN@K&iN7m^yDNL delta 19 bcmeC#$@pwLH^k+=m8MzD}qT(6q7w3W1ReX0NV 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 literal 0 HcmV?d00001 diff --git a/mobile/openapi/lib/model/smart_search_dto.dart b/mobile/openapi/lib/model/smart_search_dto.dart new file mode 100644 index 0000000000000000000000000000000000000000..b82a3345fbec819f297de08e7ef1e438f05db056 GIT binary patch literal 23646 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 literal 0 HcmV?d00001 diff --git a/mobile/openapi/test/search_api_test.dart b/mobile/openapi/test/search_api_test.dart index d89c47e748199a7309c3ecbcdbe9dbde82783b55..14169e461d283d630fe94bd66cc15a1bc40069be 100644 GIT binary patch delta 88 zcmbOwdWn035sR{KYDr>BVo73fYGP4xhD%AlLN2<<%l_1m=qj15B HGPsNYyi*|t literal 2714 zcmdT`OHbQC5WeSEY)=VNN?J}8FEv$?76~vSDN;|?#-2DM>|L|F4y1_x-q~Hhl!qu1 z7Y-Qj>^#1CeB%rToxy+&f6s!?KgZYO+u>|HVv~!@ai5I>b{)*vRWQ1k{P{#`R`Ywz zl{q^){Cd=}M@)oN5H6$&7ns5^D@36o4k3jMgy~mj%yOyBP79ts^0f~0!h{MQ3RGk+ zct+2hEBbFhX>zXgZu3YAZMZNY#uN}22+Eo3oxxHRpu<#(gw)KEi}2f*Fj{h@I~|Xa zb#orw^8}7%4ua=6pua<#b@yaT#eg;g`=}IbQ3lLPG^3)hDR31nhdFju5@VKe6ukrX z++mE=7ASbi(BY4Ooi*CMgOd*FBuW-}ue-xtx6evH*3+agg@V&d)aKMj96#kLHRcv{ zPW6G2k>}?u0aMCH+;FnzdMzS~!yIBCXhX{fa*7VNRVL`OU=%pR7msucg;6LHAJZe6 z7D+;7L4woUl+4ySFhh?%duCH-$|6|^qt^ZEobh|QE-y0~Lt3Ax{|4C0{(Ls$>9=R) zU9{`TwCio}na!n4S(IYl_ph0>Y4({YGM3XM)j%Jbw*qW#&Qd|-sAAPM{v~xM))~!Q zZQ!fpE*{Y=hcs2Vf_QJ%9^53M57Sj5&7i}H_KWR$;ed;bycfcF!n~x z`H2t_6>GtSucSg#bprKO+0oKtuvpkdQtRIWj{}ib4Mly28s}+~O$vg1v}ZQOx#DWw zN@dr8yZi$cgJRM?>+}d-Vzv#h)w{5DOObspnS7}vo;qCNtEBc1MXi~Iy$$7a<{7tV+(tZW)My%2O!k9jC zuW;V`cssPc8*XYBQHANjFRo?@ygTPDB}$%sVCFW=Yu5S)qFFt18!gz+s#m7c4bguN KrTtCu()kB6q@9`o diff --git a/mobile/openapi/test/smart_search_dto_test.dart b/mobile/openapi/test/smart_search_dto_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..858c7769c81578dff06ccbffb127af5c63f41793 GIT binary patch literal 3635 zcmbuCQBT`25P;wFE4-(I)X|Nn352vx2~(w&NVJ=@r(lvxdm^!e?G(C+|IRr{OUIDn zn1{BB^xb_v`x3j8NidnP>Ca{S@q2U?T~C)$$S!9;qA?3&b`>w#JPv1|4HqWCjD(mYs3u&$DJxKbP6{bjgqbxL$(K(_y5>p;K|4k^ zs(59%ifhCr}QU!FG zO>+Xts1!cT6&PMTb~Rzn8GaUHSNGbl3OXMrSz1#4mZ#*c|m>lDm;>0ewl;%nb%*pI;Z$od%WVabZ9PL5 zz0Zt=208X~SXY_*QS1R3Nf T^oY5W#e!}MO4s}ucnY2YtN|?P literal 0 HcmV?d00001 diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index 66a65fcb3d..5dd394108e 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -2256,6 +2256,14 @@ "type": "boolean" } }, + { + "name": "isNotInAlbum", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + }, { "name": "isOffline", "required": false, @@ -2345,6 +2353,17 @@ "type": "number" } }, + { + "name": "personIds", + "required": false, + "in": "query", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, { "name": "resizePath", "required": false, @@ -4526,350 +4545,21 @@ } }, "/search/metadata": { - "get": { + "post": { "operationId": "searchMetadata", - "parameters": [ - { - "name": "checksum", - "required": false, - "in": "query", - "schema": { - "type": "string" + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MetadataSearchDto" + } } }, - { - "name": "city", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "country", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "createdAfter", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "createdBefore", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "deviceAssetId", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "deviceId", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "encodedVideoPath", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "id", - "required": false, - "in": "query", - "schema": { - "format": "uuid", - "type": "string" - } - }, - { - "name": "isArchived", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isEncoded", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isExternal", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isFavorite", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isMotion", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isOffline", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isReadOnly", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isVisible", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "lensModel", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "libraryId", - "required": false, - "in": "query", - "schema": { - "format": "uuid", - "type": "string" - } - }, - { - "name": "make", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "model", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "order", - "required": false, - "in": "query", - "schema": { - "$ref": "#/components/schemas/AssetOrder" - } - }, - { - "name": "originalFileName", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "originalPath", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "page", - "required": false, - "in": "query", - "schema": { - "type": "number" - } - }, - { - "name": "resizePath", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "size", - "required": false, - "in": "query", - "schema": { - "type": "number" - } - }, - { - "name": "state", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "takenAfter", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "takenBefore", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "trashedAfter", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "trashedBefore", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "type", - "required": false, - "in": "query", - "schema": { - "$ref": "#/components/schemas/AssetTypeEnum" - } - }, - { - "name": "updatedAfter", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "updatedBefore", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "webpPath", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "withArchived", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "withDeleted", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "withExif", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "withPeople", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "withStacked", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - } - ], + "required": true + }, "responses": { - "200": { + "201": { "content": { "application/json": { "schema": { @@ -4949,269 +4639,21 @@ } }, "/search/smart": { - "get": { + "post": { "operationId": "searchSmart", - "parameters": [ - { - "name": "city", - "required": false, - "in": "query", - "schema": { - "type": "string" + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SmartSearchDto" + } } }, - { - "name": "country", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "createdAfter", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "createdBefore", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "deviceId", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "isArchived", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isEncoded", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isExternal", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isFavorite", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isMotion", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isOffline", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isReadOnly", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "isVisible", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "lensModel", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "libraryId", - "required": false, - "in": "query", - "schema": { - "format": "uuid", - "type": "string" - } - }, - { - "name": "make", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "model", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "page", - "required": false, - "in": "query", - "schema": { - "type": "number" - } - }, - { - "name": "query", - "required": true, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "size", - "required": false, - "in": "query", - "schema": { - "type": "number" - } - }, - { - "name": "state", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "takenAfter", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "takenBefore", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "trashedAfter", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "trashedBefore", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "type", - "required": false, - "in": "query", - "schema": { - "$ref": "#/components/schemas/AssetTypeEnum" - } - }, - { - "name": "updatedAfter", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "updatedBefore", - "required": false, - "in": "query", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "withArchived", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "withDeleted", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "withExif", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - } - ], + "required": true + }, "responses": { - "200": { + "201": { "content": { "application/json": { "schema": { @@ -8805,6 +8247,153 @@ ], "type": "object" }, + "MetadataSearchDto": { + "properties": { + "checksum": { + "type": "string" + }, + "city": { + "type": "string" + }, + "country": { + "type": "string" + }, + "createdAfter": { + "format": "date-time", + "type": "string" + }, + "createdBefore": { + "format": "date-time", + "type": "string" + }, + "deviceAssetId": { + "type": "string" + }, + "deviceId": { + "type": "string" + }, + "encodedVideoPath": { + "type": "string" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "isArchived": { + "type": "boolean" + }, + "isEncoded": { + "type": "boolean" + }, + "isExternal": { + "type": "boolean" + }, + "isFavorite": { + "type": "boolean" + }, + "isMotion": { + "type": "boolean" + }, + "isNotInAlbum": { + "type": "boolean" + }, + "isOffline": { + "type": "boolean" + }, + "isReadOnly": { + "type": "boolean" + }, + "isVisible": { + "type": "boolean" + }, + "lensModel": { + "type": "string" + }, + "libraryId": { + "format": "uuid", + "type": "string" + }, + "make": { + "type": "string" + }, + "model": { + "type": "string" + }, + "order": { + "$ref": "#/components/schemas/AssetOrder" + }, + "originalFileName": { + "type": "string" + }, + "originalPath": { + "type": "string" + }, + "page": { + "type": "number" + }, + "personIds": { + "items": { + "type": "string" + }, + "type": "array" + }, + "resizePath": { + "type": "string" + }, + "size": { + "type": "number" + }, + "state": { + "type": "string" + }, + "takenAfter": { + "format": "date-time", + "type": "string" + }, + "takenBefore": { + "format": "date-time", + "type": "string" + }, + "trashedAfter": { + "format": "date-time", + "type": "string" + }, + "trashedBefore": { + "format": "date-time", + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/AssetTypeEnum" + }, + "updatedAfter": { + "format": "date-time", + "type": "string" + }, + "updatedBefore": { + "format": "date-time", + "type": "string" + }, + "webpPath": { + "type": "string" + }, + "withArchived": { + "type": "boolean" + }, + "withDeleted": { + "type": "boolean" + }, + "withExif": { + "type": "boolean" + }, + "withPeople": { + "type": "boolean" + }, + "withStacked": { + "type": "boolean" + } + }, + "type": "object" + }, "ModelType": { "enum": [ "facial-recognition", @@ -9760,6 +9349,116 @@ }, "type": "object" }, + "SmartSearchDto": { + "properties": { + "city": { + "type": "string" + }, + "country": { + "type": "string" + }, + "createdAfter": { + "format": "date-time", + "type": "string" + }, + "createdBefore": { + "format": "date-time", + "type": "string" + }, + "deviceId": { + "type": "string" + }, + "isArchived": { + "type": "boolean" + }, + "isEncoded": { + "type": "boolean" + }, + "isExternal": { + "type": "boolean" + }, + "isFavorite": { + "type": "boolean" + }, + "isMotion": { + "type": "boolean" + }, + "isOffline": { + "type": "boolean" + }, + "isReadOnly": { + "type": "boolean" + }, + "isVisible": { + "type": "boolean" + }, + "lensModel": { + "type": "string" + }, + "libraryId": { + "format": "uuid", + "type": "string" + }, + "make": { + "type": "string" + }, + "model": { + "type": "string" + }, + "page": { + "type": "number" + }, + "query": { + "type": "string" + }, + "size": { + "type": "number" + }, + "state": { + "type": "string" + }, + "takenAfter": { + "format": "date-time", + "type": "string" + }, + "takenBefore": { + "format": "date-time", + "type": "string" + }, + "trashedAfter": { + "format": "date-time", + "type": "string" + }, + "trashedBefore": { + "format": "date-time", + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/AssetTypeEnum" + }, + "updatedAfter": { + "format": "date-time", + "type": "string" + }, + "updatedBefore": { + "format": "date-time", + "type": "string" + }, + "withArchived": { + "type": "boolean" + }, + "withDeleted": { + "type": "boolean" + }, + "withExif": { + "type": "boolean" + } + }, + "required": [ + "query" + ], + "type": "object" + }, "SystemConfigDto": { "properties": { "ffmpeg": { diff --git a/open-api/typescript-sdk/axios-client/api.ts b/open-api/typescript-sdk/axios-client/api.ts index 16fcd79cd7..5d37706904 100644 --- a/open-api/typescript-sdk/axios-client/api.ts +++ b/open-api/typescript-sdk/axios-client/api.ts @@ -2330,6 +2330,273 @@ export interface MergePersonDto { */ 'ids': Array; } +/** + * + * @export + * @interface MetadataSearchDto + */ +export interface MetadataSearchDto { + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'checksum'?: string; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'city'?: string; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'country'?: string; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'createdAfter'?: string; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'createdBefore'?: string; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'deviceAssetId'?: string; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'deviceId'?: string; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'encodedVideoPath'?: string; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'id'?: string; + /** + * + * @type {boolean} + * @memberof MetadataSearchDto + */ + 'isArchived'?: boolean; + /** + * + * @type {boolean} + * @memberof MetadataSearchDto + */ + 'isEncoded'?: boolean; + /** + * + * @type {boolean} + * @memberof MetadataSearchDto + */ + 'isExternal'?: boolean; + /** + * + * @type {boolean} + * @memberof MetadataSearchDto + */ + 'isFavorite'?: boolean; + /** + * + * @type {boolean} + * @memberof MetadataSearchDto + */ + 'isMotion'?: boolean; + /** + * + * @type {boolean} + * @memberof MetadataSearchDto + */ + 'isNotInAlbum'?: boolean; + /** + * + * @type {boolean} + * @memberof MetadataSearchDto + */ + 'isOffline'?: boolean; + /** + * + * @type {boolean} + * @memberof MetadataSearchDto + */ + 'isReadOnly'?: boolean; + /** + * + * @type {boolean} + * @memberof MetadataSearchDto + */ + 'isVisible'?: boolean; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'lensModel'?: string; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'libraryId'?: string; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'make'?: string; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'model'?: string; + /** + * + * @type {AssetOrder} + * @memberof MetadataSearchDto + */ + 'order'?: AssetOrder; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'originalFileName'?: string; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'originalPath'?: string; + /** + * + * @type {number} + * @memberof MetadataSearchDto + */ + 'page'?: number; + /** + * + * @type {Array} + * @memberof MetadataSearchDto + */ + 'personIds'?: Array; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'resizePath'?: string; + /** + * + * @type {number} + * @memberof MetadataSearchDto + */ + 'size'?: number; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'state'?: string; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'takenAfter'?: string; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'takenBefore'?: string; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'trashedAfter'?: string; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'trashedBefore'?: string; + /** + * + * @type {AssetTypeEnum} + * @memberof MetadataSearchDto + */ + 'type'?: AssetTypeEnum; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'updatedAfter'?: string; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'updatedBefore'?: string; + /** + * + * @type {string} + * @memberof MetadataSearchDto + */ + 'webpPath'?: string; + /** + * + * @type {boolean} + * @memberof MetadataSearchDto + */ + 'withArchived'?: boolean; + /** + * + * @type {boolean} + * @memberof MetadataSearchDto + */ + 'withDeleted'?: boolean; + /** + * + * @type {boolean} + * @memberof MetadataSearchDto + */ + 'withExif'?: boolean; + /** + * + * @type {boolean} + * @memberof MetadataSearchDto + */ + 'withPeople'?: boolean; + /** + * + * @type {boolean} + * @memberof MetadataSearchDto + */ + 'withStacked'?: boolean; +} + + /** * * @export @@ -3547,6 +3814,201 @@ export interface SmartInfoResponseDto { */ 'tags'?: Array | null; } +/** + * + * @export + * @interface SmartSearchDto + */ +export interface SmartSearchDto { + /** + * + * @type {string} + * @memberof SmartSearchDto + */ + 'city'?: string; + /** + * + * @type {string} + * @memberof SmartSearchDto + */ + 'country'?: string; + /** + * + * @type {string} + * @memberof SmartSearchDto + */ + 'createdAfter'?: string; + /** + * + * @type {string} + * @memberof SmartSearchDto + */ + 'createdBefore'?: string; + /** + * + * @type {string} + * @memberof SmartSearchDto + */ + 'deviceId'?: string; + /** + * + * @type {boolean} + * @memberof SmartSearchDto + */ + 'isArchived'?: boolean; + /** + * + * @type {boolean} + * @memberof SmartSearchDto + */ + 'isEncoded'?: boolean; + /** + * + * @type {boolean} + * @memberof SmartSearchDto + */ + 'isExternal'?: boolean; + /** + * + * @type {boolean} + * @memberof SmartSearchDto + */ + 'isFavorite'?: boolean; + /** + * + * @type {boolean} + * @memberof SmartSearchDto + */ + 'isMotion'?: boolean; + /** + * + * @type {boolean} + * @memberof SmartSearchDto + */ + 'isOffline'?: boolean; + /** + * + * @type {boolean} + * @memberof SmartSearchDto + */ + 'isReadOnly'?: boolean; + /** + * + * @type {boolean} + * @memberof SmartSearchDto + */ + 'isVisible'?: boolean; + /** + * + * @type {string} + * @memberof SmartSearchDto + */ + 'lensModel'?: string; + /** + * + * @type {string} + * @memberof SmartSearchDto + */ + 'libraryId'?: string; + /** + * + * @type {string} + * @memberof SmartSearchDto + */ + 'make'?: string; + /** + * + * @type {string} + * @memberof SmartSearchDto + */ + 'model'?: string; + /** + * + * @type {number} + * @memberof SmartSearchDto + */ + 'page'?: number; + /** + * + * @type {string} + * @memberof SmartSearchDto + */ + 'query': string; + /** + * + * @type {number} + * @memberof SmartSearchDto + */ + 'size'?: number; + /** + * + * @type {string} + * @memberof SmartSearchDto + */ + 'state'?: string; + /** + * + * @type {string} + * @memberof SmartSearchDto + */ + 'takenAfter'?: string; + /** + * + * @type {string} + * @memberof SmartSearchDto + */ + 'takenBefore'?: string; + /** + * + * @type {string} + * @memberof SmartSearchDto + */ + 'trashedAfter'?: string; + /** + * + * @type {string} + * @memberof SmartSearchDto + */ + 'trashedBefore'?: string; + /** + * + * @type {AssetTypeEnum} + * @memberof SmartSearchDto + */ + 'type'?: AssetTypeEnum; + /** + * + * @type {string} + * @memberof SmartSearchDto + */ + 'updatedAfter'?: string; + /** + * + * @type {string} + * @memberof SmartSearchDto + */ + 'updatedBefore'?: string; + /** + * + * @type {boolean} + * @memberof SmartSearchDto + */ + 'withArchived'?: boolean; + /** + * + * @type {boolean} + * @memberof SmartSearchDto + */ + 'withDeleted'?: boolean; + /** + * + * @type {boolean} + * @memberof SmartSearchDto + */ + 'withExif'?: boolean; +} + + /** * * @export @@ -7766,6 +8228,7 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration * @param {boolean} [isExternal] * @param {boolean} [isFavorite] * @param {boolean} [isMotion] + * @param {boolean} [isNotInAlbum] * @param {boolean} [isOffline] * @param {boolean} [isReadOnly] * @param {boolean} [isVisible] @@ -7777,6 +8240,7 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration * @param {string} [originalFileName] * @param {string} [originalPath] * @param {number} [page] + * @param {Array} [personIds] * @param {string} [resizePath] * @param {number} [size] * @param {string} [state] @@ -7797,7 +8261,7 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration * @deprecated * @throws {RequiredError} */ - searchAssets: async (checksum?: string, city?: string, country?: string, createdAfter?: string, createdBefore?: string, deviceAssetId?: string, deviceId?: string, encodedVideoPath?: string, id?: string, isArchived?: boolean, isEncoded?: boolean, isExternal?: boolean, isFavorite?: boolean, isMotion?: boolean, isOffline?: boolean, isReadOnly?: boolean, isVisible?: boolean, lensModel?: string, libraryId?: string, make?: string, model?: string, order?: AssetOrder, originalFileName?: string, originalPath?: string, page?: number, resizePath?: string, size?: number, state?: string, takenAfter?: string, takenBefore?: string, trashedAfter?: string, trashedBefore?: string, type?: AssetTypeEnum, updatedAfter?: string, updatedBefore?: string, webpPath?: string, withArchived?: boolean, withDeleted?: boolean, withExif?: boolean, withPeople?: boolean, withStacked?: boolean, options: RawAxiosRequestConfig = {}): Promise => { + searchAssets: async (checksum?: string, city?: string, country?: string, createdAfter?: string, createdBefore?: string, deviceAssetId?: string, deviceId?: string, encodedVideoPath?: string, id?: string, isArchived?: boolean, isEncoded?: boolean, isExternal?: boolean, isFavorite?: boolean, isMotion?: boolean, isNotInAlbum?: boolean, isOffline?: boolean, isReadOnly?: boolean, isVisible?: boolean, lensModel?: string, libraryId?: string, make?: string, model?: string, order?: AssetOrder, originalFileName?: string, originalPath?: string, page?: number, personIds?: Array, resizePath?: string, size?: number, state?: string, takenAfter?: string, takenBefore?: string, trashedAfter?: string, trashedBefore?: string, type?: AssetTypeEnum, updatedAfter?: string, updatedBefore?: string, webpPath?: string, withArchived?: boolean, withDeleted?: boolean, withExif?: boolean, withPeople?: boolean, withStacked?: boolean, options: RawAxiosRequestConfig = {}): Promise => { const localVarPath = `/assets`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -7879,6 +8343,10 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration localVarQueryParameter['isMotion'] = isMotion; } + if (isNotInAlbum !== undefined) { + localVarQueryParameter['isNotInAlbum'] = isNotInAlbum; + } + if (isOffline !== undefined) { localVarQueryParameter['isOffline'] = isOffline; } @@ -7923,6 +8391,10 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration localVarQueryParameter['page'] = page; } + if (personIds) { + localVarQueryParameter['personIds'] = personIds; + } + if (resizePath !== undefined) { localVarQueryParameter['resizePath'] = resizePath; } @@ -8598,6 +9070,7 @@ export const AssetApiFp = function(configuration?: Configuration) { * @param {boolean} [isExternal] * @param {boolean} [isFavorite] * @param {boolean} [isMotion] + * @param {boolean} [isNotInAlbum] * @param {boolean} [isOffline] * @param {boolean} [isReadOnly] * @param {boolean} [isVisible] @@ -8609,6 +9082,7 @@ export const AssetApiFp = function(configuration?: Configuration) { * @param {string} [originalFileName] * @param {string} [originalPath] * @param {number} [page] + * @param {Array} [personIds] * @param {string} [resizePath] * @param {number} [size] * @param {string} [state] @@ -8629,8 +9103,8 @@ export const AssetApiFp = function(configuration?: Configuration) { * @deprecated * @throws {RequiredError} */ - async searchAssets(checksum?: string, city?: string, country?: string, createdAfter?: string, createdBefore?: string, deviceAssetId?: string, deviceId?: string, encodedVideoPath?: string, id?: string, isArchived?: boolean, isEncoded?: boolean, isExternal?: boolean, isFavorite?: boolean, isMotion?: boolean, isOffline?: boolean, isReadOnly?: boolean, isVisible?: boolean, lensModel?: string, libraryId?: string, make?: string, model?: string, order?: AssetOrder, originalFileName?: string, originalPath?: string, page?: number, resizePath?: string, size?: number, state?: string, takenAfter?: string, takenBefore?: string, trashedAfter?: string, trashedBefore?: string, type?: AssetTypeEnum, updatedAfter?: string, updatedBefore?: string, webpPath?: string, withArchived?: boolean, withDeleted?: boolean, withExif?: boolean, withPeople?: boolean, withStacked?: boolean, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { - const localVarAxiosArgs = await localVarAxiosParamCreator.searchAssets(checksum, city, country, createdAfter, createdBefore, deviceAssetId, deviceId, encodedVideoPath, id, isArchived, isEncoded, isExternal, isFavorite, isMotion, isOffline, isReadOnly, isVisible, lensModel, libraryId, make, model, order, originalFileName, originalPath, page, resizePath, size, state, takenAfter, takenBefore, trashedAfter, trashedBefore, type, updatedAfter, updatedBefore, webpPath, withArchived, withDeleted, withExif, withPeople, withStacked, options); + async searchAssets(checksum?: string, city?: string, country?: string, createdAfter?: string, createdBefore?: string, deviceAssetId?: string, deviceId?: string, encodedVideoPath?: string, id?: string, isArchived?: boolean, isEncoded?: boolean, isExternal?: boolean, isFavorite?: boolean, isMotion?: boolean, isNotInAlbum?: boolean, isOffline?: boolean, isReadOnly?: boolean, isVisible?: boolean, lensModel?: string, libraryId?: string, make?: string, model?: string, order?: AssetOrder, originalFileName?: string, originalPath?: string, page?: number, personIds?: Array, resizePath?: string, size?: number, state?: string, takenAfter?: string, takenBefore?: string, trashedAfter?: string, trashedBefore?: string, type?: AssetTypeEnum, updatedAfter?: string, updatedBefore?: string, webpPath?: string, withArchived?: boolean, withDeleted?: boolean, withExif?: boolean, withPeople?: boolean, withStacked?: boolean, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { + const localVarAxiosArgs = await localVarAxiosParamCreator.searchAssets(checksum, city, country, createdAfter, createdBefore, deviceAssetId, deviceId, encodedVideoPath, id, isArchived, isEncoded, isExternal, isFavorite, isMotion, isNotInAlbum, isOffline, isReadOnly, isVisible, lensModel, libraryId, make, model, order, originalFileName, originalPath, page, personIds, resizePath, size, state, takenAfter, takenBefore, trashedAfter, trashedBefore, type, updatedAfter, updatedBefore, webpPath, withArchived, withDeleted, withExif, withPeople, withStacked, options); const index = configuration?.serverIndex ?? 0; const operationBasePath = operationServerMap['AssetApi.searchAssets']?.[index]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); @@ -8882,7 +9356,7 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath * @throws {RequiredError} */ searchAssets(requestParameters: AssetApiSearchAssetsRequest = {}, options?: RawAxiosRequestConfig): AxiosPromise> { - return localVarFp.searchAssets(requestParameters.checksum, requestParameters.city, requestParameters.country, requestParameters.createdAfter, requestParameters.createdBefore, requestParameters.deviceAssetId, requestParameters.deviceId, requestParameters.encodedVideoPath, requestParameters.id, requestParameters.isArchived, requestParameters.isEncoded, requestParameters.isExternal, requestParameters.isFavorite, requestParameters.isMotion, requestParameters.isOffline, requestParameters.isReadOnly, requestParameters.isVisible, requestParameters.lensModel, requestParameters.libraryId, requestParameters.make, requestParameters.model, requestParameters.order, requestParameters.originalFileName, requestParameters.originalPath, requestParameters.page, requestParameters.resizePath, requestParameters.size, requestParameters.state, requestParameters.takenAfter, requestParameters.takenBefore, requestParameters.trashedAfter, requestParameters.trashedBefore, requestParameters.type, requestParameters.updatedAfter, requestParameters.updatedBefore, requestParameters.webpPath, requestParameters.withArchived, requestParameters.withDeleted, requestParameters.withExif, requestParameters.withPeople, requestParameters.withStacked, options).then((request) => request(axios, basePath)); + return localVarFp.searchAssets(requestParameters.checksum, requestParameters.city, requestParameters.country, requestParameters.createdAfter, requestParameters.createdBefore, requestParameters.deviceAssetId, requestParameters.deviceId, requestParameters.encodedVideoPath, requestParameters.id, requestParameters.isArchived, requestParameters.isEncoded, requestParameters.isExternal, requestParameters.isFavorite, requestParameters.isMotion, requestParameters.isNotInAlbum, requestParameters.isOffline, requestParameters.isReadOnly, requestParameters.isVisible, requestParameters.lensModel, requestParameters.libraryId, requestParameters.make, requestParameters.model, requestParameters.order, requestParameters.originalFileName, requestParameters.originalPath, requestParameters.page, requestParameters.personIds, requestParameters.resizePath, requestParameters.size, requestParameters.state, requestParameters.takenAfter, requestParameters.takenBefore, requestParameters.trashedAfter, requestParameters.trashedBefore, requestParameters.type, requestParameters.updatedAfter, requestParameters.updatedBefore, requestParameters.webpPath, requestParameters.withArchived, requestParameters.withDeleted, requestParameters.withExif, requestParameters.withPeople, requestParameters.withStacked, options).then((request) => request(axios, basePath)); }, /** * @@ -9484,6 +9958,13 @@ export interface AssetApiSearchAssetsRequest { */ readonly isMotion?: boolean + /** + * + * @type {boolean} + * @memberof AssetApiSearchAssets + */ + readonly isNotInAlbum?: boolean + /** * * @type {boolean} @@ -9561,6 +10042,13 @@ export interface AssetApiSearchAssetsRequest { */ readonly page?: number + /** + * + * @type {Array} + * @memberof AssetApiSearchAssets + */ + readonly personIds?: Array + /** * * @type {string} @@ -10077,7 +10565,7 @@ export class AssetApi extends BaseAPI { * @memberof AssetApi */ public searchAssets(requestParameters: AssetApiSearchAssetsRequest = {}, options?: RawAxiosRequestConfig) { - return AssetApiFp(this.configuration).searchAssets(requestParameters.checksum, requestParameters.city, requestParameters.country, requestParameters.createdAfter, requestParameters.createdBefore, requestParameters.deviceAssetId, requestParameters.deviceId, requestParameters.encodedVideoPath, requestParameters.id, requestParameters.isArchived, requestParameters.isEncoded, requestParameters.isExternal, requestParameters.isFavorite, requestParameters.isMotion, requestParameters.isOffline, requestParameters.isReadOnly, requestParameters.isVisible, requestParameters.lensModel, requestParameters.libraryId, requestParameters.make, requestParameters.model, requestParameters.order, requestParameters.originalFileName, requestParameters.originalPath, requestParameters.page, requestParameters.resizePath, requestParameters.size, requestParameters.state, requestParameters.takenAfter, requestParameters.takenBefore, requestParameters.trashedAfter, requestParameters.trashedBefore, requestParameters.type, requestParameters.updatedAfter, requestParameters.updatedBefore, requestParameters.webpPath, requestParameters.withArchived, requestParameters.withDeleted, requestParameters.withExif, requestParameters.withPeople, requestParameters.withStacked, options).then((request) => request(this.axios, this.basePath)); + return AssetApiFp(this.configuration).searchAssets(requestParameters.checksum, requestParameters.city, requestParameters.country, requestParameters.createdAfter, requestParameters.createdBefore, requestParameters.deviceAssetId, requestParameters.deviceId, requestParameters.encodedVideoPath, requestParameters.id, requestParameters.isArchived, requestParameters.isEncoded, requestParameters.isExternal, requestParameters.isFavorite, requestParameters.isMotion, requestParameters.isNotInAlbum, requestParameters.isOffline, requestParameters.isReadOnly, requestParameters.isVisible, requestParameters.lensModel, requestParameters.libraryId, requestParameters.make, requestParameters.model, requestParameters.order, requestParameters.originalFileName, requestParameters.originalPath, requestParameters.page, requestParameters.personIds, requestParameters.resizePath, requestParameters.size, requestParameters.state, requestParameters.takenAfter, requestParameters.takenBefore, requestParameters.trashedAfter, requestParameters.trashedBefore, requestParameters.type, requestParameters.updatedAfter, requestParameters.updatedBefore, requestParameters.webpPath, requestParameters.withArchived, requestParameters.withDeleted, requestParameters.withExif, requestParameters.withPeople, requestParameters.withStacked, options).then((request) => request(this.axios, this.basePath)); } /** @@ -14705,51 +15193,13 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio }, /** * - * @param {string} [checksum] - * @param {string} [city] - * @param {string} [country] - * @param {string} [createdAfter] - * @param {string} [createdBefore] - * @param {string} [deviceAssetId] - * @param {string} [deviceId] - * @param {string} [encodedVideoPath] - * @param {string} [id] - * @param {boolean} [isArchived] - * @param {boolean} [isEncoded] - * @param {boolean} [isExternal] - * @param {boolean} [isFavorite] - * @param {boolean} [isMotion] - * @param {boolean} [isOffline] - * @param {boolean} [isReadOnly] - * @param {boolean} [isVisible] - * @param {string} [lensModel] - * @param {string} [libraryId] - * @param {string} [make] - * @param {string} [model] - * @param {AssetOrder} [order] - * @param {string} [originalFileName] - * @param {string} [originalPath] - * @param {number} [page] - * @param {string} [resizePath] - * @param {number} [size] - * @param {string} [state] - * @param {string} [takenAfter] - * @param {string} [takenBefore] - * @param {string} [trashedAfter] - * @param {string} [trashedBefore] - * @param {AssetTypeEnum} [type] - * @param {string} [updatedAfter] - * @param {string} [updatedBefore] - * @param {string} [webpPath] - * @param {boolean} [withArchived] - * @param {boolean} [withDeleted] - * @param {boolean} [withExif] - * @param {boolean} [withPeople] - * @param {boolean} [withStacked] + * @param {MetadataSearchDto} metadataSearchDto * @param {*} [options] Override http request option. * @throws {RequiredError} */ - searchMetadata: async (checksum?: string, city?: string, country?: string, createdAfter?: string, createdBefore?: string, deviceAssetId?: string, deviceId?: string, encodedVideoPath?: string, id?: string, isArchived?: boolean, isEncoded?: boolean, isExternal?: boolean, isFavorite?: boolean, isMotion?: boolean, isOffline?: boolean, isReadOnly?: boolean, isVisible?: boolean, lensModel?: string, libraryId?: string, make?: string, model?: string, order?: AssetOrder, originalFileName?: string, originalPath?: string, page?: number, resizePath?: string, size?: number, state?: string, takenAfter?: string, takenBefore?: string, trashedAfter?: string, trashedBefore?: string, type?: AssetTypeEnum, updatedAfter?: string, updatedBefore?: string, webpPath?: string, withArchived?: boolean, withDeleted?: boolean, withExif?: boolean, withPeople?: boolean, withStacked?: boolean, options: RawAxiosRequestConfig = {}): Promise => { + searchMetadata: async (metadataSearchDto: MetadataSearchDto, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'metadataSearchDto' is not null or undefined + assertParamExists('searchMetadata', 'metadataSearchDto', metadataSearchDto) const localVarPath = `/search/metadata`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -14758,7 +15208,7 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio baseOptions = configuration.baseOptions; } - const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; @@ -14771,191 +15221,14 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio // http bearer authentication required await setBearerAuthToObject(localVarHeaderParameter, configuration) - if (checksum !== undefined) { - localVarQueryParameter['checksum'] = checksum; - } - - if (city !== undefined) { - localVarQueryParameter['city'] = city; - } - - if (country !== undefined) { - localVarQueryParameter['country'] = country; - } - - if (createdAfter !== undefined) { - localVarQueryParameter['createdAfter'] = (createdAfter as any instanceof Date) ? - (createdAfter as any).toISOString() : - createdAfter; - } - - if (createdBefore !== undefined) { - localVarQueryParameter['createdBefore'] = (createdBefore as any instanceof Date) ? - (createdBefore as any).toISOString() : - createdBefore; - } - - if (deviceAssetId !== undefined) { - localVarQueryParameter['deviceAssetId'] = deviceAssetId; - } - - if (deviceId !== undefined) { - localVarQueryParameter['deviceId'] = deviceId; - } - - if (encodedVideoPath !== undefined) { - localVarQueryParameter['encodedVideoPath'] = encodedVideoPath; - } - - if (id !== undefined) { - localVarQueryParameter['id'] = id; - } - - if (isArchived !== undefined) { - localVarQueryParameter['isArchived'] = isArchived; - } - - if (isEncoded !== undefined) { - localVarQueryParameter['isEncoded'] = isEncoded; - } - - if (isExternal !== undefined) { - localVarQueryParameter['isExternal'] = isExternal; - } - - if (isFavorite !== undefined) { - localVarQueryParameter['isFavorite'] = isFavorite; - } - - if (isMotion !== undefined) { - localVarQueryParameter['isMotion'] = isMotion; - } - - if (isOffline !== undefined) { - localVarQueryParameter['isOffline'] = isOffline; - } - - if (isReadOnly !== undefined) { - localVarQueryParameter['isReadOnly'] = isReadOnly; - } - - if (isVisible !== undefined) { - localVarQueryParameter['isVisible'] = isVisible; - } - - if (lensModel !== undefined) { - localVarQueryParameter['lensModel'] = lensModel; - } - - if (libraryId !== undefined) { - localVarQueryParameter['libraryId'] = libraryId; - } - - if (make !== undefined) { - localVarQueryParameter['make'] = make; - } - - if (model !== undefined) { - localVarQueryParameter['model'] = model; - } - - if (order !== undefined) { - localVarQueryParameter['order'] = order; - } - - if (originalFileName !== undefined) { - localVarQueryParameter['originalFileName'] = originalFileName; - } - - if (originalPath !== undefined) { - localVarQueryParameter['originalPath'] = originalPath; - } - - if (page !== undefined) { - localVarQueryParameter['page'] = page; - } - - if (resizePath !== undefined) { - localVarQueryParameter['resizePath'] = resizePath; - } - - if (size !== undefined) { - localVarQueryParameter['size'] = size; - } - - if (state !== undefined) { - localVarQueryParameter['state'] = state; - } - - if (takenAfter !== undefined) { - localVarQueryParameter['takenAfter'] = (takenAfter as any instanceof Date) ? - (takenAfter as any).toISOString() : - takenAfter; - } - - if (takenBefore !== undefined) { - localVarQueryParameter['takenBefore'] = (takenBefore as any instanceof Date) ? - (takenBefore as any).toISOString() : - takenBefore; - } - - if (trashedAfter !== undefined) { - localVarQueryParameter['trashedAfter'] = (trashedAfter as any instanceof Date) ? - (trashedAfter as any).toISOString() : - trashedAfter; - } - - if (trashedBefore !== undefined) { - localVarQueryParameter['trashedBefore'] = (trashedBefore as any instanceof Date) ? - (trashedBefore as any).toISOString() : - trashedBefore; - } - - if (type !== undefined) { - localVarQueryParameter['type'] = type; - } - - if (updatedAfter !== undefined) { - localVarQueryParameter['updatedAfter'] = (updatedAfter as any instanceof Date) ? - (updatedAfter as any).toISOString() : - updatedAfter; - } - - if (updatedBefore !== undefined) { - localVarQueryParameter['updatedBefore'] = (updatedBefore as any instanceof Date) ? - (updatedBefore as any).toISOString() : - updatedBefore; - } - - if (webpPath !== undefined) { - localVarQueryParameter['webpPath'] = webpPath; - } - - if (withArchived !== undefined) { - localVarQueryParameter['withArchived'] = withArchived; - } - - if (withDeleted !== undefined) { - localVarQueryParameter['withDeleted'] = withDeleted; - } - - if (withExif !== undefined) { - localVarQueryParameter['withExif'] = withExif; - } - - if (withPeople !== undefined) { - localVarQueryParameter['withPeople'] = withPeople; - } - - if (withStacked !== undefined) { - localVarQueryParameter['withStacked'] = withStacked; - } - + localVarHeaderParameter['Content-Type'] = 'application/json'; + setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(metadataSearchDto, localVarRequestOptions, configuration) return { url: toPathString(localVarUrlObj), @@ -15014,43 +15287,13 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio }, /** * - * @param {string} query - * @param {string} [city] - * @param {string} [country] - * @param {string} [createdAfter] - * @param {string} [createdBefore] - * @param {string} [deviceId] - * @param {boolean} [isArchived] - * @param {boolean} [isEncoded] - * @param {boolean} [isExternal] - * @param {boolean} [isFavorite] - * @param {boolean} [isMotion] - * @param {boolean} [isOffline] - * @param {boolean} [isReadOnly] - * @param {boolean} [isVisible] - * @param {string} [lensModel] - * @param {string} [libraryId] - * @param {string} [make] - * @param {string} [model] - * @param {number} [page] - * @param {number} [size] - * @param {string} [state] - * @param {string} [takenAfter] - * @param {string} [takenBefore] - * @param {string} [trashedAfter] - * @param {string} [trashedBefore] - * @param {AssetTypeEnum} [type] - * @param {string} [updatedAfter] - * @param {string} [updatedBefore] - * @param {boolean} [withArchived] - * @param {boolean} [withDeleted] - * @param {boolean} [withExif] + * @param {SmartSearchDto} smartSearchDto * @param {*} [options] Override http request option. * @throws {RequiredError} */ - searchSmart: async (query: string, city?: string, country?: string, createdAfter?: string, createdBefore?: string, deviceId?: string, isArchived?: boolean, isEncoded?: boolean, isExternal?: boolean, isFavorite?: boolean, isMotion?: boolean, isOffline?: boolean, isReadOnly?: boolean, isVisible?: boolean, lensModel?: string, libraryId?: string, make?: string, model?: string, page?: number, size?: number, state?: string, takenAfter?: string, takenBefore?: string, trashedAfter?: string, trashedBefore?: string, type?: AssetTypeEnum, updatedAfter?: string, updatedBefore?: string, withArchived?: boolean, withDeleted?: boolean, withExif?: boolean, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'query' is not null or undefined - assertParamExists('searchSmart', 'query', query) + searchSmart: async (smartSearchDto: SmartSearchDto, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'smartSearchDto' is not null or undefined + assertParamExists('searchSmart', 'smartSearchDto', smartSearchDto) const localVarPath = `/search/smart`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -15059,7 +15302,7 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio baseOptions = configuration.baseOptions; } - const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; @@ -15072,151 +15315,14 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio // http bearer authentication required await setBearerAuthToObject(localVarHeaderParameter, configuration) - if (city !== undefined) { - localVarQueryParameter['city'] = city; - } - - if (country !== undefined) { - localVarQueryParameter['country'] = country; - } - - if (createdAfter !== undefined) { - localVarQueryParameter['createdAfter'] = (createdAfter as any instanceof Date) ? - (createdAfter as any).toISOString() : - createdAfter; - } - - if (createdBefore !== undefined) { - localVarQueryParameter['createdBefore'] = (createdBefore as any instanceof Date) ? - (createdBefore as any).toISOString() : - createdBefore; - } - - if (deviceId !== undefined) { - localVarQueryParameter['deviceId'] = deviceId; - } - - if (isArchived !== undefined) { - localVarQueryParameter['isArchived'] = isArchived; - } - - if (isEncoded !== undefined) { - localVarQueryParameter['isEncoded'] = isEncoded; - } - - if (isExternal !== undefined) { - localVarQueryParameter['isExternal'] = isExternal; - } - - if (isFavorite !== undefined) { - localVarQueryParameter['isFavorite'] = isFavorite; - } - - if (isMotion !== undefined) { - localVarQueryParameter['isMotion'] = isMotion; - } - - if (isOffline !== undefined) { - localVarQueryParameter['isOffline'] = isOffline; - } - - if (isReadOnly !== undefined) { - localVarQueryParameter['isReadOnly'] = isReadOnly; - } - - if (isVisible !== undefined) { - localVarQueryParameter['isVisible'] = isVisible; - } - - if (lensModel !== undefined) { - localVarQueryParameter['lensModel'] = lensModel; - } - - if (libraryId !== undefined) { - localVarQueryParameter['libraryId'] = libraryId; - } - - if (make !== undefined) { - localVarQueryParameter['make'] = make; - } - - if (model !== undefined) { - localVarQueryParameter['model'] = model; - } - - if (page !== undefined) { - localVarQueryParameter['page'] = page; - } - - if (query !== undefined) { - localVarQueryParameter['query'] = query; - } - - if (size !== undefined) { - localVarQueryParameter['size'] = size; - } - - if (state !== undefined) { - localVarQueryParameter['state'] = state; - } - - if (takenAfter !== undefined) { - localVarQueryParameter['takenAfter'] = (takenAfter as any instanceof Date) ? - (takenAfter as any).toISOString() : - takenAfter; - } - - if (takenBefore !== undefined) { - localVarQueryParameter['takenBefore'] = (takenBefore as any instanceof Date) ? - (takenBefore as any).toISOString() : - takenBefore; - } - - if (trashedAfter !== undefined) { - localVarQueryParameter['trashedAfter'] = (trashedAfter as any instanceof Date) ? - (trashedAfter as any).toISOString() : - trashedAfter; - } - - if (trashedBefore !== undefined) { - localVarQueryParameter['trashedBefore'] = (trashedBefore as any instanceof Date) ? - (trashedBefore as any).toISOString() : - trashedBefore; - } - - if (type !== undefined) { - localVarQueryParameter['type'] = type; - } - - if (updatedAfter !== undefined) { - localVarQueryParameter['updatedAfter'] = (updatedAfter as any instanceof Date) ? - (updatedAfter as any).toISOString() : - updatedAfter; - } - - if (updatedBefore !== undefined) { - localVarQueryParameter['updatedBefore'] = (updatedBefore as any instanceof Date) ? - (updatedBefore as any).toISOString() : - updatedBefore; - } - - if (withArchived !== undefined) { - localVarQueryParameter['withArchived'] = withArchived; - } - - if (withDeleted !== undefined) { - localVarQueryParameter['withDeleted'] = withDeleted; - } - - if (withExif !== undefined) { - localVarQueryParameter['withExif'] = withExif; - } - + localVarHeaderParameter['Content-Type'] = 'application/json'; + setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(smartSearchDto, localVarRequestOptions, configuration) return { url: toPathString(localVarUrlObj), @@ -15284,52 +15390,12 @@ export const SearchApiFp = function(configuration?: Configuration) { }, /** * - * @param {string} [checksum] - * @param {string} [city] - * @param {string} [country] - * @param {string} [createdAfter] - * @param {string} [createdBefore] - * @param {string} [deviceAssetId] - * @param {string} [deviceId] - * @param {string} [encodedVideoPath] - * @param {string} [id] - * @param {boolean} [isArchived] - * @param {boolean} [isEncoded] - * @param {boolean} [isExternal] - * @param {boolean} [isFavorite] - * @param {boolean} [isMotion] - * @param {boolean} [isOffline] - * @param {boolean} [isReadOnly] - * @param {boolean} [isVisible] - * @param {string} [lensModel] - * @param {string} [libraryId] - * @param {string} [make] - * @param {string} [model] - * @param {AssetOrder} [order] - * @param {string} [originalFileName] - * @param {string} [originalPath] - * @param {number} [page] - * @param {string} [resizePath] - * @param {number} [size] - * @param {string} [state] - * @param {string} [takenAfter] - * @param {string} [takenBefore] - * @param {string} [trashedAfter] - * @param {string} [trashedBefore] - * @param {AssetTypeEnum} [type] - * @param {string} [updatedAfter] - * @param {string} [updatedBefore] - * @param {string} [webpPath] - * @param {boolean} [withArchived] - * @param {boolean} [withDeleted] - * @param {boolean} [withExif] - * @param {boolean} [withPeople] - * @param {boolean} [withStacked] + * @param {MetadataSearchDto} metadataSearchDto * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async searchMetadata(checksum?: string, city?: string, country?: string, createdAfter?: string, createdBefore?: string, deviceAssetId?: string, deviceId?: string, encodedVideoPath?: string, id?: string, isArchived?: boolean, isEncoded?: boolean, isExternal?: boolean, isFavorite?: boolean, isMotion?: boolean, isOffline?: boolean, isReadOnly?: boolean, isVisible?: boolean, lensModel?: string, libraryId?: string, make?: string, model?: string, order?: AssetOrder, originalFileName?: string, originalPath?: string, page?: number, resizePath?: string, size?: number, state?: string, takenAfter?: string, takenBefore?: string, trashedAfter?: string, trashedBefore?: string, type?: AssetTypeEnum, updatedAfter?: string, updatedBefore?: string, webpPath?: string, withArchived?: boolean, withDeleted?: boolean, withExif?: boolean, withPeople?: boolean, withStacked?: boolean, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.searchMetadata(checksum, city, country, createdAfter, createdBefore, deviceAssetId, deviceId, encodedVideoPath, id, isArchived, isEncoded, isExternal, isFavorite, isMotion, isOffline, isReadOnly, isVisible, lensModel, libraryId, make, model, order, originalFileName, originalPath, page, resizePath, size, state, takenAfter, takenBefore, trashedAfter, trashedBefore, type, updatedAfter, updatedBefore, webpPath, withArchived, withDeleted, withExif, withPeople, withStacked, options); + async searchMetadata(metadataSearchDto: MetadataSearchDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.searchMetadata(metadataSearchDto, options); const index = configuration?.serverIndex ?? 0; const operationBasePath = operationServerMap['SearchApi.searchMetadata']?.[index]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); @@ -15349,42 +15415,12 @@ export const SearchApiFp = function(configuration?: Configuration) { }, /** * - * @param {string} query - * @param {string} [city] - * @param {string} [country] - * @param {string} [createdAfter] - * @param {string} [createdBefore] - * @param {string} [deviceId] - * @param {boolean} [isArchived] - * @param {boolean} [isEncoded] - * @param {boolean} [isExternal] - * @param {boolean} [isFavorite] - * @param {boolean} [isMotion] - * @param {boolean} [isOffline] - * @param {boolean} [isReadOnly] - * @param {boolean} [isVisible] - * @param {string} [lensModel] - * @param {string} [libraryId] - * @param {string} [make] - * @param {string} [model] - * @param {number} [page] - * @param {number} [size] - * @param {string} [state] - * @param {string} [takenAfter] - * @param {string} [takenBefore] - * @param {string} [trashedAfter] - * @param {string} [trashedBefore] - * @param {AssetTypeEnum} [type] - * @param {string} [updatedAfter] - * @param {string} [updatedBefore] - * @param {boolean} [withArchived] - * @param {boolean} [withDeleted] - * @param {boolean} [withExif] + * @param {SmartSearchDto} smartSearchDto * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async searchSmart(query: string, city?: string, country?: string, createdAfter?: string, createdBefore?: string, deviceId?: string, isArchived?: boolean, isEncoded?: boolean, isExternal?: boolean, isFavorite?: boolean, isMotion?: boolean, isOffline?: boolean, isReadOnly?: boolean, isVisible?: boolean, lensModel?: string, libraryId?: string, make?: string, model?: string, page?: number, size?: number, state?: string, takenAfter?: string, takenBefore?: string, trashedAfter?: string, trashedBefore?: string, type?: AssetTypeEnum, updatedAfter?: string, updatedBefore?: string, withArchived?: boolean, withDeleted?: boolean, withExif?: boolean, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.searchSmart(query, city, country, createdAfter, createdBefore, deviceId, isArchived, isEncoded, isExternal, isFavorite, isMotion, isOffline, isReadOnly, isVisible, lensModel, libraryId, make, model, page, size, state, takenAfter, takenBefore, trashedAfter, trashedBefore, type, updatedAfter, updatedBefore, withArchived, withDeleted, withExif, options); + async searchSmart(smartSearchDto: SmartSearchDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.searchSmart(smartSearchDto, options); const index = configuration?.serverIndex ?? 0; const operationBasePath = operationServerMap['SearchApi.searchSmart']?.[index]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath); @@ -15432,8 +15468,8 @@ export const SearchApiFactory = function (configuration?: Configuration, basePat * @param {*} [options] Override http request option. * @throws {RequiredError} */ - searchMetadata(requestParameters: SearchApiSearchMetadataRequest = {}, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.searchMetadata(requestParameters.checksum, requestParameters.city, requestParameters.country, requestParameters.createdAfter, requestParameters.createdBefore, requestParameters.deviceAssetId, requestParameters.deviceId, requestParameters.encodedVideoPath, requestParameters.id, requestParameters.isArchived, requestParameters.isEncoded, requestParameters.isExternal, requestParameters.isFavorite, requestParameters.isMotion, requestParameters.isOffline, requestParameters.isReadOnly, requestParameters.isVisible, requestParameters.lensModel, requestParameters.libraryId, requestParameters.make, requestParameters.model, requestParameters.order, requestParameters.originalFileName, requestParameters.originalPath, requestParameters.page, requestParameters.resizePath, requestParameters.size, requestParameters.state, requestParameters.takenAfter, requestParameters.takenBefore, requestParameters.trashedAfter, requestParameters.trashedBefore, requestParameters.type, requestParameters.updatedAfter, requestParameters.updatedBefore, requestParameters.webpPath, requestParameters.withArchived, requestParameters.withDeleted, requestParameters.withExif, requestParameters.withPeople, requestParameters.withStacked, options).then((request) => request(axios, basePath)); + searchMetadata(requestParameters: SearchApiSearchMetadataRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.searchMetadata(requestParameters.metadataSearchDto, options).then((request) => request(axios, basePath)); }, /** * @@ -15451,7 +15487,7 @@ export const SearchApiFactory = function (configuration?: Configuration, basePat * @throws {RequiredError} */ searchSmart(requestParameters: SearchApiSearchSmartRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.searchSmart(requestParameters.query, requestParameters.city, requestParameters.country, requestParameters.createdAfter, requestParameters.createdBefore, requestParameters.deviceId, requestParameters.isArchived, requestParameters.isEncoded, requestParameters.isExternal, requestParameters.isFavorite, requestParameters.isMotion, requestParameters.isOffline, requestParameters.isReadOnly, requestParameters.isVisible, requestParameters.lensModel, requestParameters.libraryId, requestParameters.make, requestParameters.model, requestParameters.page, requestParameters.size, requestParameters.state, requestParameters.takenAfter, requestParameters.takenBefore, requestParameters.trashedAfter, requestParameters.trashedBefore, requestParameters.type, requestParameters.updatedAfter, requestParameters.updatedBefore, requestParameters.withArchived, requestParameters.withDeleted, requestParameters.withExif, options).then((request) => request(axios, basePath)); + return localVarFp.searchSmart(requestParameters.smartSearchDto, options).then((request) => request(axios, basePath)); }, }; }; @@ -15583,290 +15619,10 @@ export interface SearchApiSearchRequest { export interface SearchApiSearchMetadataRequest { /** * - * @type {string} + * @type {MetadataSearchDto} * @memberof SearchApiSearchMetadata */ - readonly checksum?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly city?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly country?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly createdAfter?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly createdBefore?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly deviceAssetId?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly deviceId?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly encodedVideoPath?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly id?: string - - /** - * - * @type {boolean} - * @memberof SearchApiSearchMetadata - */ - readonly isArchived?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchMetadata - */ - readonly isEncoded?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchMetadata - */ - readonly isExternal?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchMetadata - */ - readonly isFavorite?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchMetadata - */ - readonly isMotion?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchMetadata - */ - readonly isOffline?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchMetadata - */ - readonly isReadOnly?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchMetadata - */ - readonly isVisible?: boolean - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly lensModel?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly libraryId?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly make?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly model?: string - - /** - * - * @type {AssetOrder} - * @memberof SearchApiSearchMetadata - */ - readonly order?: AssetOrder - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly originalFileName?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly originalPath?: string - - /** - * - * @type {number} - * @memberof SearchApiSearchMetadata - */ - readonly page?: number - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly resizePath?: string - - /** - * - * @type {number} - * @memberof SearchApiSearchMetadata - */ - readonly size?: number - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly state?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly takenAfter?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly takenBefore?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly trashedAfter?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly trashedBefore?: string - - /** - * - * @type {AssetTypeEnum} - * @memberof SearchApiSearchMetadata - */ - readonly type?: AssetTypeEnum - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly updatedAfter?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly updatedBefore?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchMetadata - */ - readonly webpPath?: string - - /** - * - * @type {boolean} - * @memberof SearchApiSearchMetadata - */ - readonly withArchived?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchMetadata - */ - readonly withDeleted?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchMetadata - */ - readonly withExif?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchMetadata - */ - readonly withPeople?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchMetadata - */ - readonly withStacked?: boolean + readonly metadataSearchDto: MetadataSearchDto } /** @@ -15898,220 +15654,10 @@ export interface SearchApiSearchPersonRequest { export interface SearchApiSearchSmartRequest { /** * - * @type {string} + * @type {SmartSearchDto} * @memberof SearchApiSearchSmart */ - readonly query: string - - /** - * - * @type {string} - * @memberof SearchApiSearchSmart - */ - readonly city?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchSmart - */ - readonly country?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchSmart - */ - readonly createdAfter?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchSmart - */ - readonly createdBefore?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchSmart - */ - readonly deviceId?: string - - /** - * - * @type {boolean} - * @memberof SearchApiSearchSmart - */ - readonly isArchived?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchSmart - */ - readonly isEncoded?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchSmart - */ - readonly isExternal?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchSmart - */ - readonly isFavorite?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchSmart - */ - readonly isMotion?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchSmart - */ - readonly isOffline?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchSmart - */ - readonly isReadOnly?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchSmart - */ - readonly isVisible?: boolean - - /** - * - * @type {string} - * @memberof SearchApiSearchSmart - */ - readonly lensModel?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchSmart - */ - readonly libraryId?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchSmart - */ - readonly make?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchSmart - */ - readonly model?: string - - /** - * - * @type {number} - * @memberof SearchApiSearchSmart - */ - readonly page?: number - - /** - * - * @type {number} - * @memberof SearchApiSearchSmart - */ - readonly size?: number - - /** - * - * @type {string} - * @memberof SearchApiSearchSmart - */ - readonly state?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchSmart - */ - readonly takenAfter?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchSmart - */ - readonly takenBefore?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchSmart - */ - readonly trashedAfter?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchSmart - */ - readonly trashedBefore?: string - - /** - * - * @type {AssetTypeEnum} - * @memberof SearchApiSearchSmart - */ - readonly type?: AssetTypeEnum - - /** - * - * @type {string} - * @memberof SearchApiSearchSmart - */ - readonly updatedAfter?: string - - /** - * - * @type {string} - * @memberof SearchApiSearchSmart - */ - readonly updatedBefore?: string - - /** - * - * @type {boolean} - * @memberof SearchApiSearchSmart - */ - readonly withArchived?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchSmart - */ - readonly withDeleted?: boolean - - /** - * - * @type {boolean} - * @memberof SearchApiSearchSmart - */ - readonly withExif?: boolean + readonly smartSearchDto: SmartSearchDto } /** @@ -16161,8 +15707,8 @@ export class SearchApi extends BaseAPI { * @throws {RequiredError} * @memberof SearchApi */ - public searchMetadata(requestParameters: SearchApiSearchMetadataRequest = {}, options?: RawAxiosRequestConfig) { - return SearchApiFp(this.configuration).searchMetadata(requestParameters.checksum, requestParameters.city, requestParameters.country, requestParameters.createdAfter, requestParameters.createdBefore, requestParameters.deviceAssetId, requestParameters.deviceId, requestParameters.encodedVideoPath, requestParameters.id, requestParameters.isArchived, requestParameters.isEncoded, requestParameters.isExternal, requestParameters.isFavorite, requestParameters.isMotion, requestParameters.isOffline, requestParameters.isReadOnly, requestParameters.isVisible, requestParameters.lensModel, requestParameters.libraryId, requestParameters.make, requestParameters.model, requestParameters.order, requestParameters.originalFileName, requestParameters.originalPath, requestParameters.page, requestParameters.resizePath, requestParameters.size, requestParameters.state, requestParameters.takenAfter, requestParameters.takenBefore, requestParameters.trashedAfter, requestParameters.trashedBefore, requestParameters.type, requestParameters.updatedAfter, requestParameters.updatedBefore, requestParameters.webpPath, requestParameters.withArchived, requestParameters.withDeleted, requestParameters.withExif, requestParameters.withPeople, requestParameters.withStacked, options).then((request) => request(this.axios, this.basePath)); + public searchMetadata(requestParameters: SearchApiSearchMetadataRequest, options?: RawAxiosRequestConfig) { + return SearchApiFp(this.configuration).searchMetadata(requestParameters.metadataSearchDto, options).then((request) => request(this.axios, this.basePath)); } /** @@ -16184,7 +15730,7 @@ export class SearchApi extends BaseAPI { * @memberof SearchApi */ public searchSmart(requestParameters: SearchApiSearchSmartRequest, options?: RawAxiosRequestConfig) { - return SearchApiFp(this.configuration).searchSmart(requestParameters.query, requestParameters.city, requestParameters.country, requestParameters.createdAfter, requestParameters.createdBefore, requestParameters.deviceId, requestParameters.isArchived, requestParameters.isEncoded, requestParameters.isExternal, requestParameters.isFavorite, requestParameters.isMotion, requestParameters.isOffline, requestParameters.isReadOnly, requestParameters.isVisible, requestParameters.lensModel, requestParameters.libraryId, requestParameters.make, requestParameters.model, requestParameters.page, requestParameters.size, requestParameters.state, requestParameters.takenAfter, requestParameters.takenBefore, requestParameters.trashedAfter, requestParameters.trashedBefore, requestParameters.type, requestParameters.updatedAfter, requestParameters.updatedBefore, requestParameters.withArchived, requestParameters.withDeleted, requestParameters.withExif, options).then((request) => request(this.axios, this.basePath)); + return SearchApiFp(this.configuration).searchSmart(requestParameters.smartSearchDto, options).then((request) => request(this.axios, this.basePath)); } } diff --git a/open-api/typescript-sdk/fetch-client.ts b/open-api/typescript-sdk/fetch-client.ts index 8eef9b3a5c66851ec7682bb0365402bc60242601..0f42ff9178126c1734df637cd23ece577a0b3ce4 100644 GIT binary patch delta 456 zcmdmSmgW6^mJLbfe7>nAi7AOCiNUFfMadbH1?7}CFPr4T$mN$`;+f}|lT?~J`S-)k zle?#+vK6Ej73b$oE>sqo{9($f$qL$Rljl!;I{CjKA9rwWVo?dyh;z)6lk2WUZmxd# ziV>>FZ}Rz@UX#1M1t!~Dv2M;V{}PF8zU~9}$@3@bazf1aOex-cYN7%YvIK>hA8PhoS&y&Oj4Vnl$T*oP`^rGOl8f)Jbd;5LC3gRJ33 T(l!}r$7F|hteb6~*VqF9hdsGH delta 247 zcmaFApJm5cmJLbflM5W!Heay&5;^(OjDpR+Gv$~zx6fu{+`N2FIP+wY1t&JYUr=E^ zS!Koo40#r&$&z=aCfDEM;MC7eElEsCEJ>Waaf-s`ck=`op<0U=H}AQd!#G)Qh7qIZ z; @@ -156,7 +164,8 @@ export type SmartSearchOptions = SearchDateOptions & SearchExifOptions & SearchOneToOneRelationOptions & SearchStatusOptions & - SearchUserIDOptions; + SearchUserIdOptions & + SearchPeopleOptions; export interface FaceEmbeddingSearch extends SearchEmbeddingOptions { hasPerson?: boolean; diff --git a/server/src/domain/search/dto/search.dto.ts b/server/src/domain/search/dto/search.dto.ts index a4e0396688..5aa73433d9 100644 --- a/server/src/domain/search/dto/search.dto.ts +++ b/server/src/domain/search/dto/search.dto.ts @@ -169,6 +169,12 @@ export class MetadataSearchDto extends BaseSearchDto { @Optional() @ApiProperty({ enumName: 'AssetOrder', enum: AssetOrder }) order?: AssetOrder; + + @QueryBoolean({ optional: true }) + isNotInAlbum?: boolean; + + @Optional() + personIds?: string[]; } export class SmartSearchDto extends BaseSearchDto { diff --git a/server/src/domain/search/search.service.ts b/server/src/domain/search/search.service.ts index 49cca2ab48..452c556f41 100644 --- a/server/src/domain/search/search.service.ts +++ b/server/src/domain/search/search.service.ts @@ -60,6 +60,7 @@ export class SearchService { async searchMetadata(auth: AuthDto, dto: MetadataSearchDto): Promise { let checksum: Buffer | undefined; + const userIds = await this.getUserIdsToSearch(auth); if (dto.checksum) { const encoding = dto.checksum.length === 28 ? 'base64' : 'hex'; @@ -74,7 +75,7 @@ export class SearchService { { ...dto, checksum, - ownerId: auth.user.id, + userIds, orderDirection: dto.order ? enumToOrder[dto.order] : 'DESC', }, ); diff --git a/server/src/immich/controllers/search.controller.ts b/server/src/immich/controllers/search.controller.ts index f8438b2e35..4e57cfaa62 100644 --- a/server/src/immich/controllers/search.controller.ts +++ b/server/src/immich/controllers/search.controller.ts @@ -10,7 +10,7 @@ import { SmartSearchDto, } from '@app/domain'; import { SearchSuggestionRequestDto } from '@app/domain/search/dto/search-suggestion.dto'; -import { Controller, Get, Query } from '@nestjs/common'; +import { Body, Controller, Get, Post, Query } from '@nestjs/common'; import { ApiOperation, ApiTags } from '@nestjs/swagger'; import { Auth, Authenticated } from '../app.guard'; import { UseValidation } from '../app.utils'; @@ -22,13 +22,13 @@ import { UseValidation } from '../app.utils'; export class SearchController { constructor(private service: SearchService) {} - @Get('metadata') - searchMetadata(@Auth() auth: AuthDto, @Query() dto: MetadataSearchDto): Promise { + @Post('metadata') + searchMetadata(@Auth() auth: AuthDto, @Body() dto: MetadataSearchDto): Promise { return this.service.searchMetadata(auth, dto); } - @Get('smart') - searchSmart(@Auth() auth: AuthDto, @Query() dto: SmartSearchDto): Promise { + @Post('smart') + searchSmart(@Auth() auth: AuthDto, @Body() dto: SmartSearchDto): Promise { return this.service.searchSmart(auth, dto); } diff --git a/server/src/infra/infra.utils.ts b/server/src/infra/infra.utils.ts index 89bd319662..2b274cb12a 100644 --- a/server/src/infra/infra.utils.ts +++ b/server/src/infra/infra.utils.ts @@ -139,14 +139,27 @@ export function searchAssetBuilder( ); const exifInfo = _.omitBy(_.pick(options, ['city', 'country', 'lensModel', 'make', 'model', 'state']), _.isUndefined); - if (Object.keys(exifInfo).length > 0) { - builder.leftJoin(`${builder.alias}.exifInfo`, 'exifInfo'); + const hasExifQuery = Object.keys(exifInfo).length > 0; + + if (options.withExif && !hasExifQuery) { + builder.leftJoinAndSelect(`${builder.alias}.exifInfo`, 'exifInfo'); + } + + if (hasExifQuery) { + options.withExif + ? builder.leftJoinAndSelect(`${builder.alias}.exifInfo`, 'exifInfo') + : builder.leftJoin(`${builder.alias}.exifInfo`, 'exifInfo'); + builder.andWhere({ exifInfo }); } - const id = _.pick(options, ['checksum', 'deviceAssetId', 'deviceId', 'id', 'libraryId', 'ownerId']); + const id = _.pick(options, ['checksum', 'deviceAssetId', 'deviceId', 'id', 'libraryId']); builder.andWhere(_.omitBy(id, _.isUndefined)); + if (options.userIds) { + builder.andWhere(`${builder.alias}.ownerId IN (:...userIds)`, { userIds: options.userIds }); + } + const path = _.pick(options, ['encodedVideoPath', 'originalFileName', 'originalPath', 'resizePath', 'webpPath']); builder.andWhere(_.omitBy(path, _.isUndefined)); @@ -164,8 +177,8 @@ export function searchAssetBuilder( ), ); - if (options.withExif) { - builder.leftJoinAndSelect(`${builder.alias}.exifInfo`, 'exifInfo'); + if (options.isNotInAlbum) { + builder.leftJoin(`${builder.alias}.albums`, 'albums').andWhere('albums.id IS NULL'); } if (options.withFaces || options.withPeople) { @@ -180,6 +193,18 @@ export function searchAssetBuilder( builder.leftJoinAndSelect(`${builder.alias}.smartInfo`, 'smartInfo'); } + if (options.personIds && options.personIds.length > 0) { + builder + .leftJoin(`${builder.alias}.faces`, 'faces') + .andWhere('faces.personId IN (:...personIds)', { personIds: options.personIds }) + .addGroupBy(`${builder.alias}.id`) + .having('COUNT(faces.id) = :personCount', { personCount: options.personIds.length }); + + if (options.withExif) { + builder.addGroupBy('exifInfo.assetId'); + } + } + if (options.withStacked) { builder .leftJoinAndSelect(`${builder.alias}.stack`, 'stack') diff --git a/server/src/infra/repositories/search.repository.ts b/server/src/infra/repositories/search.repository.ts index 7d0421b05d..a30c96b10d 100644 --- a/server/src/infra/repositories/search.repository.ts +++ b/server/src/infra/repositories/search.repository.ts @@ -58,6 +58,7 @@ export class SearchRepository implements ISearchRepository { ownerId: DummyValue.UUID, withStacked: true, isFavorite: true, + ownerIds: [DummyValue.UUID], }, ], }) @@ -66,7 +67,6 @@ export class SearchRepository implements ISearchRepository { builder = searchAssetBuilder(builder, options); builder.orderBy('asset.fileCreatedAt', options.orderDirection ?? 'DESC'); - return paginatedBuilder(builder, { mode: PaginationMode.SKIP_TAKE, skip: (pagination.page - 1) * pagination.size, diff --git a/server/src/infra/sql/search.repository.sql b/server/src/infra/sql/search.repository.sql index 538a854094..ebae46f65b 100644 --- a/server/src/infra/sql/search.repository.sql +++ b/server/src/infra/sql/search.repository.sql @@ -77,9 +77,9 @@ FROM ( "asset"."fileCreatedAt" >= $1 AND "exifInfo"."lensModel" = $2 - AND "asset"."ownerId" = $3 AND 1 = 1 - AND "asset"."isFavorite" = $4 + AND 1 = 1 + AND "asset"."isFavorite" = $3 AND ( "stack"."primaryAssetId" = "asset"."id" OR "asset"."stackId" IS NULL diff --git a/web/.eslintrc.cjs b/web/.eslintrc.cjs index de62060e0f..ef17242c8e 100644 --- a/web/.eslintrc.cjs +++ b/web/.eslintrc.cjs @@ -38,6 +38,7 @@ module.exports = { 'unicorn/prevent-abbreviations': 'off', 'unicorn/no-nested-ternary': 'off', 'unicorn/consistent-function-scoping': 'off', + 'unicorn/prefer-top-level-await': 'off', '@typescript-eslint/no-unused-vars': [ 'warn', { diff --git a/web/src/lib/components/memory-page/memory-viewer.svelte b/web/src/lib/components/memory-page/memory-viewer.svelte index af26a7bffa..397c167d16 100644 --- a/web/src/lib/components/memory-page/memory-viewer.svelte +++ b/web/src/lib/components/memory-page/memory-viewer.svelte @@ -7,6 +7,7 @@ import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte'; import GalleryViewer from '$lib/components/shared-components/gallery-viewer/gallery-viewer.svelte'; import { AppRoute, QueryParameter } from '$lib/constants'; + import type { Viewport } from '$lib/stores/assets.store'; import { memoryStore } from '$lib/stores/memory.store'; import { getAssetThumbnailUrl } from '$lib/utils'; import { fromLocalDateTime } from '$lib/utils/timeline-util'; @@ -34,6 +35,7 @@ $: canGoForward = !!(nextMemory || nextAsset); $: canGoBack = !!(previousMemory || previousAsset); + const viewport: Viewport = { width: 0, height: 0 }; const toNextMemory = () => goto(`?${QueryParameter.MEMORY_INDEX}=${memoryIndex + 1}`); const toPreviousMemory = () => goto(`?${QueryParameter.MEMORY_INDEX}=${memoryIndex - 1}`); @@ -251,7 +253,7 @@ -
+
(galleryInView = false)} bottom={-200} > -
diff --git a/web/src/lib/components/photos-page/asset-date-group.svelte b/web/src/lib/components/photos-page/asset-date-group.svelte index a38708e881..04fb872116 100644 --- a/web/src/lib/components/photos-page/asset-date-group.svelte +++ b/web/src/lib/components/photos-page/asset-date-group.svelte @@ -5,7 +5,12 @@ import type { AssetStore, Viewport } from '$lib/stores/assets.store'; import { locale } from '$lib/stores/preferences.store'; import { getAssetRatio } from '$lib/utils/asset-utils'; - import { formatGroupTitle, fromLocalDateTime, splitBucketIntoDateGroups } from '$lib/utils/timeline-util'; + import { + calculateWidth, + formatGroupTitle, + fromLocalDateTime, + splitBucketIntoDateGroups, + } from '$lib/utils/timeline-util'; import type { AssetResponseDto } from '@immich/sdk'; import { mdiCheckCircle, mdiCircleOutline } from '@mdi/js'; import justifiedLayout from 'justified-layout'; @@ -36,12 +41,6 @@ let actualBucketHeight: number; let hoveredDateGroup = ''; - interface LayoutBox { - top: number; - left: number; - width: number; - } - $: assetsGroupByDate = splitBucketIntoDateGroups(assets, $locale); $: geometry = (() => { @@ -80,17 +79,6 @@ }); } - const calculateWidth = (boxes: LayoutBox[]): number => { - let width = 0; - for (const box of boxes) { - if (box.top < 100) { - width = box.left + box.width; - } - } - - return width; - }; - const assetClickHandler = (asset: AssetResponseDto, assetsInDateGroup: AssetResponseDto[], groupTitle: string) => { if (isSelectionMode || $isMultiSelectState) { assetSelectHandler(asset, assetsInDateGroup, groupTitle); diff --git a/web/src/lib/components/share-page/individual-shared-viewer.svelte b/web/src/lib/components/share-page/individual-shared-viewer.svelte index 37b2983ae1..0036331378 100644 --- a/web/src/lib/components/share-page/individual-shared-viewer.svelte +++ b/web/src/lib/components/share-page/individual-shared-viewer.svelte @@ -16,10 +16,12 @@ import GalleryViewer from '../shared-components/gallery-viewer/gallery-viewer.svelte'; import ImmichLogo from '../shared-components/immich-logo.svelte'; import { NotificationType, notificationController } from '../shared-components/notification/notification'; + import type { Viewport } from '$lib/stores/assets.store'; export let sharedLink: SharedLinkResponseDto; export let isOwned: boolean; + const viewport: Viewport = { width: 0, height: 0 }; let selectedAssets: Set = new Set(); $: assets = sharedLink.assets; @@ -97,7 +99,7 @@ {/if} -
- +
+
diff --git a/web/src/lib/components/shared-components/control-app-bar.svelte b/web/src/lib/components/shared-components/control-app-bar.svelte index e8d56b742c..bdb2aed709 100644 --- a/web/src/lib/components/shared-components/control-app-bar.svelte +++ b/web/src/lib/components/shared-components/control-app-bar.svelte @@ -51,7 +51,7 @@
diff --git a/web/src/lib/components/shared-components/gallery-viewer/gallery-viewer.svelte b/web/src/lib/components/shared-components/gallery-viewer/gallery-viewer.svelte index fa1d7d6732..2fb4feb67a 100644 --- a/web/src/lib/components/shared-components/gallery-viewer/gallery-viewer.svelte +++ b/web/src/lib/components/shared-components/gallery-viewer/gallery-viewer.svelte @@ -2,13 +2,14 @@ import { page } from '$app/stores'; import Thumbnail from '$lib/components/assets/thumbnail/thumbnail.svelte'; import { assetViewingStore } from '$lib/stores/asset-viewing.store'; - import type { BucketPosition } from '$lib/stores/assets.store'; + import type { BucketPosition, Viewport } from '$lib/stores/assets.store'; import { handleError } from '$lib/utils/handle-error'; - import { getThumbnailSize } from '$lib/utils/thumbnail-util'; - import { ThumbnailFormat, type AssetResponseDto } from '@immich/sdk'; + import { type AssetResponseDto } from '@immich/sdk'; import { createEventDispatcher, onDestroy } from 'svelte'; - import { flip } from 'svelte/animate'; import AssetViewer from '../../asset-viewer/asset-viewer.svelte'; + import justifiedLayout from 'justified-layout'; + import { getAssetRatio } from '$lib/utils/asset-utils'; + import { calculateWidth } from '$lib/utils/timeline-util'; const dispatch = createEventDispatcher<{ intersected: { container: HTMLDivElement; position: BucketPosition } }>(); @@ -16,14 +17,12 @@ export let selectedAssets: Set = new Set(); export let disableAssetSelect = false; export let showArchiveIcon = false; + export let viewport: Viewport; let { isViewing: showAssetViewer } = assetViewingStore; let selectedAsset: AssetResponseDto; let currentViewAssetIndex = 0; - let viewWidth: number; - $: thumbnailSize = getThumbnailSize(assets.length, viewWidth); - $: isMultiSelectionMode = selectedAssets.size > 0; const viewAssetHandler = (event: CustomEvent) => { @@ -86,23 +85,45 @@ onDestroy(() => { $showAssetViewer = false; }); + + $: geometry = (() => { + const justifiedLayoutResult = justifiedLayout( + assets.map((asset) => getAssetRatio(asset)), + { + boxSpacing: 2, + containerWidth: Math.floor(viewport.width), + containerPadding: 0, + targetRowHeightTolerance: 0.15, + targetRowHeight: 235, + }, + ); + + return { + ...justifiedLayoutResult, + containerWidth: calculateWidth(justifiedLayoutResult.boxes), + }; + })(); {#if assets.length > 0} -
- {#each assets as asset, i (asset.id)} -
+
+ {#each assets as asset, i (i)} +
(isMultiSelectionMode ? selectAssetHandler(e) : viewAssetHandler(e))} on:select={selectAssetHandler} on:intersected={(event) => i === Math.max(1, assets.length - 7) ? dispatch('intersected', event.detail) : undefined} selected={selectedAssets.has(asset)} {showArchiveIcon} + thumbnailWidth={geometry.boxes[i].width} + thumbnailHeight={geometry.boxes[i].height} />
{/each} diff --git a/web/src/lib/components/shared-components/search-bar/search-bar.svelte b/web/src/lib/components/shared-components/search-bar/search-bar.svelte index 8dfba184ad..62e950566d 100644 --- a/web/src/lib/components/shared-components/search-bar/search-bar.svelte +++ b/web/src/lib/components/shared-components/search-bar/search-bar.svelte @@ -2,12 +2,18 @@ import { AppRoute } from '$lib/constants'; import Icon from '$lib/components/elements/icon.svelte'; import { goto } from '$app/navigation'; - import { isSearchEnabled, preventRaceConditionSearchBar, savedSearchTerms } from '$lib/stores/search.store'; + import { + isSearchEnabled, + preventRaceConditionSearchBar, + savedSearchTerms, + searchQuery, + } from '$lib/stores/search.store'; import { clickOutside } from '$lib/utils/click-outside'; import { mdiClose, mdiMagnify, mdiTune } from '@mdi/js'; import IconButton from '$lib/components/elements/buttons/icon-button.svelte'; import SearchHistoryBox from './search-history-box.svelte'; import SearchFilterBox from './search-filter-box.svelte'; + import type { MetadataSearchDto, SmartSearchDto } from '@immich/sdk'; export let value = ''; export let grayTheme: boolean; @@ -17,28 +23,17 @@ let showFilter = false; $: showClearIcon = value.length > 0; - function onSearch() { - let smartSearch = 'true'; - let searchValue = value; - - if (value.slice(0, 2) == 'm:') { - smartSearch = 'false'; - searchValue = value.slice(2); - } - - $savedSearchTerms = $savedSearchTerms.filter((item) => item !== value); - saveSearchTerm(value); - + const onSearch = (payload: SmartSearchDto | MetadataSearchDto) => { const parameters = new URLSearchParams({ - q: searchValue, - smart: smartSearch, - take: '100', + query: JSON.stringify(payload), }); showHistory = false; + showFilter = false; $isSearchEnabled = false; + $searchQuery = payload; goto(`${AppRoute.SEARCH}?${parameters}`, { invalidateAll: true }); - } + }; const clearSearchTerm = (searchTerm: string) => { input.focus(); @@ -70,6 +65,26 @@ showHistory = false; $isSearchEnabled = false; + showFilter = false; + }; + + const onHistoryTermClick = (searchTerm: string) => { + const searchPayload = { query: searchTerm }; + onSearch(searchPayload); + }; + + const onFilterClick = () => { + showFilter = !showFilter; + value = ''; + + if (showFilter) { + showHistory = false; + } + }; + + const onSubmit = () => { + onSearch({ query: value }); + saveSearchTerm(value); }; @@ -80,7 +95,7 @@ class="relative select-text text-sm" action={AppRoute.SEARCH} on:reset={() => (value = '')} - on:submit|preventDefault={() => onSearch()} + on:submit|preventDefault={onSubmit} >
-
+{#if terms} +
+ {#each Object.keys(terms) as key, index (index)} +
+
+ {getHumanReadableSearchKey(key)} +
+ + {#if terms[key] !== true} +
+ {#if key === 'takenAfter' || key === 'takenBefore'} + {getHumanReadableDate(terms[key])} + {:else if key === 'personIds'} + {#await getPersonName(terms[key]) then personName} + {personName} + {/await} + {:else} + {terms[key]} + {/if} +
+ {/if} +
+ {/each} +
+{/if} + +
{#if albums && albums.length > 0}
@@ -193,14 +317,13 @@ {/if}
{#if searchResultAssets && searchResultAssets.length > 0} -
- -
+ {:else}
diff --git a/web/src/routes/(user)/search/+page.ts b/web/src/routes/(user)/search/+page.ts index e3c99b007b..b2997e70b0 100644 --- a/web/src/routes/(user)/search/+page.ts +++ b/web/src/routes/(user)/search/+page.ts @@ -1,6 +1,13 @@ import { QueryParameter } from '$lib/constants'; +import { searchQuery } from '$lib/stores/search.store'; import { authenticate } from '$lib/utils/auth'; -import { search, type AssetResponseDto, type SearchResponseDto } from '@immich/sdk'; +import { + searchMetadata, + searchSmart, + type MetadataSearchDto, + type SearchResponseDto, + type SmartSearchDto, +} from '@immich/sdk'; import type { PageLoad } from './$types'; export const load = (async (data) => { @@ -10,22 +17,13 @@ export const load = (async (data) => { url.searchParams.get(QueryParameter.SEARCH_TERM) || url.searchParams.get(QueryParameter.QUERY) || undefined; let results: SearchResponseDto | null = null; if (term) { - let params = {}; - for (const [key, value] of data.url.searchParams) { - params = { ...params, [key]: value }; - } - const response = await search({ ...params }); - let items: AssetResponseDto[] = (data as unknown as { results: SearchResponseDto }).results?.assets.items; - if (items) { - items.push(...response.assets.items); - } else { - items = response.assets.items; - } - const assets = { ...response.assets, items }; - results = { - assets, - albums: response.albums, - }; + const payload = JSON.parse(term) as SmartSearchDto | MetadataSearchDto; + searchQuery.set(payload); + + results = + payload && 'query' in payload + ? await searchSmart({ smartSearchDto: { ...payload, withExif: true } }) + : await searchMetadata({ metadataSearchDto: { ...payload, withExif: true } }); } return {