Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
digibib
deichman
Commits
88a5ab5c
Commit
88a5ab5c
authored
Mar 01, 2021
by
David Björkheim
Browse files
DEICH-5558
Deichman.no: Data fetching for other publications
parent
b3dd3f09
Changes
5
Hide whitespace changes
Inline
Side-by-side
deichman.no/components/PublicationList/PublicationAccordionContainer.js
deleted
100644 → 0
View file @
b3dd3f09
import
React
from
"
react
"
;
import
{
Accordion
,
Block
}
from
"
@digibib/deichman-ui
"
;
export
default
function
PublicationAccordionContainer
({
publicationId
})
{
return
(
<
Block
top
=
{
8
}
>
<
Accordion
text
=
"
Andre utgaver
"
openByDefault
large
showDividers
>
<
div
>
TODO
IMPLEMENT
ME
<
/div
>
{
/* <Block top={5}>
<ActiveFilters type="publication" />
</Block>
<PublicationList
query={query}
items={workData.publications}
favourites={favourites}
parent={workData}
onReserve={this.handleReserve}
onFavourite={this.handleFavourite}
onShowDetails={this.handleShowDetails}
userCategory={userCategory}
tjenesteKatalogUrl={tjenesteKatalogUrl}
publicationId={publicationId}
/> */
}
<
/Accordion
>
<
/Block
>
);
}
deichman.no/components/PublicationList/PublicationList.js
View file @
88a5ab5c
import
React
,
{
Component
}
from
"
react
"
;
import
autoBind
from
"
auto-bind
"
;
import
React
from
"
react
"
;
import
PropTypes
from
"
prop-types
"
;
import
{
...
...
@@ -10,142 +9,43 @@ import MT_WEIGHTS from "../../constants/mediaTypeWeights";
import
LNG_WEIGHTS
from
"
../../constants/languageWeights
"
;
import
PublicationCard
from
"
../PublicationCard
"
;
import
{
Block
,
ShowMore
}
from
"
@digibib/deichman-ui
"
;
import
{
translations
as
TRANSLATIONS
}
from
"
../../constants/translations
"
;
import
"
./styles.css
"
;
function
ensureArray
(
obj
)
{
if
(
!
obj
||
obj
===
null
)
{
return
[];
}
if
(
Array
.
isArray
(
obj
))
{
return
obj
;
}
return
[
obj
];
}
class
PublicationList
extends
Component
{
constructor
(
props
)
{
super
(
props
);
autoBind
(
this
);
this
.
state
=
{
expanded
:
false
};
}
handleExpand
()
{
this
.
setState
({
expanded
:
true
});
}
filterAndSortItems
()
{
const
{
expanded
}
=
this
.
state
;
const
{
query
,
items
,
limited
,
publicationId
}
=
this
.
props
;
const
showPreview
=
limited
&&
!
expanded
;
const
activeFilters
=
[
...
getActiveFiltersFromUrlLegacy
(
query
),
...
getActiveCustomSearchFilters
(
query
)
];
const
filterValuesByType
=
activeFilters
.
reduce
((
acc
,
f
)
=>
{
if
(
!
acc
[
f
.
type
])
{
acc
[
f
.
type
]
=
[];
}
acc
[
f
.
type
].
push
(
f
.
paramValue
||
f
.
value
);
return
acc
;
},
{});
const
processed
=
items
.
filter
(
pub
=>
{
// Check if publication matches at least one value for every filter type
const
isMatch
=
Object
.
keys
(
filterValuesByType
).
every
(
type
=>
{
switch
(
type
)
{
case
"
language
"
:
return
ensureArray
(
pub
.
languages
).
some
(
l
=>
filterValuesByType
[
type
].
includes
(
TRANSLATIONS
[
l
])
);
case
"
branch
"
:
return
ensureArray
(
pub
.
items
).
some
(
i
=>
filterValuesByType
[
type
].
includes
(
i
.
branchcode
)
);
case
"
excludeUnavailable
"
:
return
ensureArray
(
pub
.
items
).
some
(
i
=>
i
.
available
>
0
);
case
"
mediatype
"
:
return
[
pub
.
mediaType
].
some
(
m
=>
filterValuesByType
[
type
].
includes
(
TRANSLATIONS
[
m
])
);
case
"
format
"
:
return
ensureArray
(
pub
.
formats
).
some
(
f
=>
filterValuesByType
[
type
].
includes
(
TRANSLATIONS
[
f
])
);
case
"
yearFrom
"
:
return
pub
.
publicationYear
>=
filterValuesByType
[
type
];
case
"
yearTo
"
:
return
pub
.
publicationYear
<=
filterValuesByType
[
type
];
default
:
return
true
;
}
});
return
isMatch
;
});
// Group and sort by MediaType, then by language,
// but always sort selected publication first
const
sorted
=
processed
.
sort
(
(
a
,
b
)
=>
(
a
.
id
===
publicationId
||
1000
)
-
(
b
.
id
===
publicationId
||
1000
)
||
MT_WEIGHTS
[
a
.
mediaType
]
-
MT_WEIGHTS
[
b
.
mediaType
]
||
((
a
.
languages
&&
LNG_WEIGHTS
[
a
.
languages
[
0
]])
||
100
)
-
((
b
.
languages
&&
LNG_WEIGHTS
[
b
.
languages
[
0
]])
||
100
)
||
b
.
publicationYear
-
a
.
publicationYear
);
return
showPreview
?
sorted
.
slice
(
0
,
6
)
:
sorted
;
}
render
()
{
const
{
parent
,
limited
,
onFavourite
,
favourites
,
onReserve
,
tjenesteKatalogUrl
,
userCategory
}
=
this
.
props
;
const
{
expanded
}
=
this
.
state
;
const
items
=
this
.
filterAndSortItems
();
return
(
<
section
className
=
"
publication-list
"
>
<
ul
className
=
"
publication-list__items
"
>
{
items
.
map
(
item
=>
(
<
li
className
=
"
publication-list__item
"
key
=
{
item
.
id
}
>
<
PublicationCard
data
=
{
item
}
parent
=
{
parent
}
flags
=
{
item
.
flags
}
isFavourited
=
{
favourites
.
includes
(
item
.
recordId
)}
onFavourite
=
{()
=>
onFavourite
(
item
.
recordId
)}
onReserve
=
{()
=>
onReserve
(
item
.
recordId
)}
tjenesteKatalogUrl
=
{
tjenesteKatalogUrl
}
userCategory
=
{
userCategory
}
/
>
<
/li
>
))}
<
/ul
>
{
limited
&&
!
expanded
&&
(
<
Block
top
=
{
6
}
>
<
ShowMore
text
=
"
Se flere
"
onClick
=
{
this
.
handleExpand
}
/
>
<
/Block
>
)}
<
/section
>
);
}
export
default
function
PublicationList
({
parent
,
onFavourite
,
favourites
,
onReserve
,
tjenesteKatalogUrl
,
userCategory
,
query
,
publications
,
publicationId
})
{
const
dispItems
=
filterAndSortItems
({
query
,
publications
,
publicationId
});
return
(
<
section
className
=
"
publication-list
"
>
<
ul
className
=
"
publication-list__items
"
>
{
dispItems
.
map
(
item
=>
(
<
li
className
=
"
publication-list__item
"
key
=
{
item
.
id
}
>
<
PublicationCard
data
=
{
item
}
parent
=
{
parent
}
flags
=
{
item
.
flags
}
isFavourited
=
{
favourites
.
includes
(
item
.
recordId
)}
onFavourite
=
{()
=>
onFavourite
(
item
.
recordId
)}
onReserve
=
{()
=>
onReserve
(
item
.
recordId
)}
tjenesteKatalogUrl
=
{
tjenesteKatalogUrl
}
userCategory
=
{
userCategory
}
/
>
<
/li
>
))}
<
/ul
>
<
/section
>
);
}
PublicationList
.
defaultProps
=
{
...
...
@@ -158,10 +58,9 @@ PublicationList.defaultProps = {
};
PublicationList
.
propTypes
=
{
item
s
:
PropTypes
.
arrayOf
(
PropTypes
.
object
),
publication
s
:
PropTypes
.
arrayOf
(
PropTypes
.
object
),
query
:
PropTypes
.
object
,
parent
:
PropTypes
.
object
,
limited
:
PropTypes
.
bool
,
favourites
:
PropTypes
.
array
,
onFavourite
:
PropTypes
.
func
.
isRequired
,
onReserve
:
PropTypes
.
func
.
isRequired
,
...
...
@@ -170,4 +69,76 @@ PublicationList.propTypes = {
publicationId
:
PropTypes
.
string
.
isRequired
};
export
default
PublicationList
;
// --------- Utils below ------------------
function
ensureArray
(
obj
)
{
if
(
!
obj
||
obj
===
null
)
{
return
[];
}
if
(
Array
.
isArray
(
obj
))
{
return
obj
;
}
return
[
obj
];
}
function
filterAndSortItems
({
query
,
publications
,
publicationId
})
{
const
activeFilters
=
[
...
getActiveFiltersFromUrlLegacy
(
query
),
...
getActiveCustomSearchFilters
(
query
)
];
const
filterValuesByType
=
activeFilters
.
reduce
((
acc
,
f
)
=>
{
if
(
!
acc
[
f
.
type
])
{
acc
[
f
.
type
]
=
[];
}
acc
[
f
.
type
].
push
(
f
.
paramValue
||
f
.
value
);
return
acc
;
},
{});
const
processed
=
publications
.
filter
(
pub
=>
{
// Check if publication matches at least one value for every filter type
const
isMatch
=
Object
.
keys
(
filterValuesByType
).
every
(
type
=>
{
switch
(
type
)
{
case
"
language
"
:
return
ensureArray
(
pub
.
languages
).
some
(
l
=>
filterValuesByType
[
type
].
includes
(
TRANSLATIONS
[
l
])
);
case
"
branch
"
:
return
ensureArray
(
pub
.
items
).
some
(
i
=>
filterValuesByType
[
type
].
includes
(
i
.
branchcode
)
);
case
"
excludeUnavailable
"
:
return
ensureArray
(
pub
.
items
).
some
(
i
=>
i
.
available
>
0
);
case
"
mediatype
"
:
return
[
pub
.
mediaType
].
some
(
m
=>
filterValuesByType
[
type
].
includes
(
TRANSLATIONS
[
m
])
);
case
"
format
"
:
return
ensureArray
(
pub
.
formats
).
some
(
f
=>
filterValuesByType
[
type
].
includes
(
TRANSLATIONS
[
f
])
);
case
"
yearFrom
"
:
return
pub
.
publicationYear
>=
filterValuesByType
[
type
];
case
"
yearTo
"
:
return
pub
.
publicationYear
<=
filterValuesByType
[
type
];
default
:
return
true
;
}
});
return
isMatch
;
});
// Group and sort by MediaType, then by language,
// but always sort selected publication first
const
sorted
=
processed
.
sort
(
(
a
,
b
)
=>
(
a
.
id
===
publicationId
||
1000
)
-
(
b
.
id
===
publicationId
||
1000
)
||
MT_WEIGHTS
[
a
.
mediaType
]
-
MT_WEIGHTS
[
b
.
mediaType
]
||
((
a
.
languages
&&
LNG_WEIGHTS
[
a
.
languages
[
0
]])
||
100
)
-
((
b
.
languages
&&
LNG_WEIGHTS
[
b
.
languages
[
0
]])
||
100
)
||
b
.
publicationYear
-
a
.
publicationYear
);
return
sorted
;
}
deichman.no/components/PublicationList/PublicationsAccordionContainer.js
0 → 100644
View file @
88a5ab5c
import
React
,
{
useEffect
,
useState
}
from
"
react
"
;
import
{
Accordion
,
Block
,
Loader
}
from
"
@digibib/deichman-ui
"
;
import
{
useDispatch
,
useSelector
}
from
"
react-redux
"
;
import
ActiveFilters
from
"
../ActiveFilters
"
;
import
PublicationList
from
"
./PublicationList
"
;
import
{
useRouter
}
from
"
next/router
"
;
export
default
function
PublicationsAccordionContainer
({
publication
})
{
const
[
isLoading
,
setLoading
]
=
useState
(
true
);
const
[
copies
,
setCopies
]
=
useState
({});
const
dispatch
=
useDispatch
();
const
favourites
=
useSelector
(
state
=>
state
.
favourites
.
biblioNumbers
);
const
onFavourite
=
recordId
=>
dispatch
(
toggleFavourites
({
recordId
}));
const
userCategory
=
useSelector
(
state
=>
state
.
auth
.
userData
.
category
);
const
tjenesteKatalogUrl
=
useSelector
(
state
=>
state
.
application
.
urls
.
tjenestekatalog
);
const
{
query
}
=
useRouter
();
const
getCopies
=
id
=>
{
return
(
copies
[
publication
.
id
]
&&
copies
[
publication
.
id
][
id
]
&&
copies
[
publication
.
id
][
id
].
items
);
};
const
decoratedPublications
=
publication
.
work
.
publications
.
map
(
p
=>
({
...
p
,
items
:
getCopies
(
p
.
recordId
)
}))
.
filter
(
p
=>
p
.
mediaType
===
publication
.
mediaType
&&
p
.
id
!==
publication
.
id
);
return
(
<
Block
top
=
{
8
}
>
<
Accordion
text
=
"
Andre utgivelser
"
closedByDefault
large
showDividers
>
<>
<
LoadDataTrigger
publication
=
{
publication
}
setLoading
=
{
setLoading
}
setCopies
=
{
setCopies
}
copies
=
{
copies
}
/
>
{
isLoading
&&
(
<
Block
top
=
{
6
}
responsive
>
<
Loader
/>
<
/Block
>
)}
{
!
isLoading
&&
decoratedPublications
.
length
>
0
&&
(
<
Block
top
=
{
5
}
>
<
ActiveFilters
type
=
"
publication
"
/>
<
PublicationList
query
=
{
query
}
publications
=
{
decoratedPublications
}
favourites
=
{
favourites
}
parent
=
{
publication
.
work
}
onReserve
=
{
Function
.
prototype
}
//TODO fix this post DEICH-5554 merge
onFavourite
=
{
onFavourite
}
onShowDetails
=
{
Function
.
prototype
}
//TODO fix this post DEICH-5554 merge
userCategory
=
{
userCategory
}
tjenesteKatalogUrl
=
{
tjenesteKatalogUrl
}
publicationId
=
{
publication
.
id
}
/
>
<
/Block
>
)}
{
!
isLoading
&&
decoratedPublications
.
length
===
0
&&
(
<
Block
top
=
{
5
}
>
Her
fantes
det
ingen
utgaver
å
vise
<
/Block
>
)}
<
/
>
<
/Accordion
>
<
/Block
>
);
}
function
LoadDataTrigger
(
props
)
{
const
id
=
props
?.
publication
?.
id
;
const
loadCopies
=
async
(
{
publication
,
setLoading
,
setCopies
,
copies
},
controls
)
=>
{
if
(
!
copies
[
publication
.
id
])
{
!
controls
.
canceled
&&
setLoading
(
true
);
try
{
const
res
=
await
fetch
(
`/api/resources/copies?id=
${
publication
.
work
.
publications
.
map
(
p
=>
p
.
recordId
)
.
join
(
"
,
"
)}
`
);
const
newCopies
=
await
res
.
json
();
!
controls
.
canceled
&&
setCopies
({
...
copies
,
[
publication
.
id
]:
newCopies
});
}
catch
(
err
)
{
console
.
error
(
err
);
}
!
controls
.
canceled
&&
setLoading
(
false
);
}
};
useEffect
(
()
=>
{
const
controls
=
{
canceled
:
false
};
loadCopies
(
props
,
controls
);
return
()
=>
(
controls
.
canceled
=
true
);
},
[
id
]
);
return
null
;
}
deichman.no/pages/utgivelse/[publicationId].js
View file @
88a5ab5c
...
...
@@ -14,8 +14,8 @@ import RecommendationAccordion from "../../components/RecommendationAccordion/Re
import
WorkDetailsAccordionContainer
from
"
../../components/WorkDetails/WorkDetailsAccordionContainer
"
;
import
PublicationPartsAccordion
from
"
../../components/PublicationParts
"
;
import
WorkHeroContainer
from
"
../../components/WorkHero/WorkHeroContainer
"
;
import
PublicationAccordionContainer
from
"
../../components/PublicationList/PublicationAccordionContainer
"
;
import
PublicationRelatedContent
from
"
../../components/PublicationRelatedContent/PublicationRelatedContent
"
;
import
PublicationsAccordionContainer
from
"
../../components/PublicationList/PublicationsAccordionContainer
"
;
import
{
useRouter
}
from
"
next/router
"
;
class
PublicationPage
extends
React
.
Component
{
...
...
@@ -107,7 +107,7 @@ class PublicationPage extends React.Component {
<
RecommendationAccordion
recommendations
=
{
recommendations
}
/
>
<
WorkDetailsAccordionContainer
publication
=
{
publication
}
/
>
<
PublicationPartsAccordion
publication
=
{
publication
}
/
>
<
PublicationAccordionContainer
/>
<
Publication
s
AccordionContainer
publication
=
{
publication
}
/
>
<
/Container
>
<
Container
>
<
PublicationRelatedContent
publication
=
{
publication
}
/
>
...
...
deichman.no/server/routes/resources.js
View file @
88a5ab5c
...
...
@@ -690,4 +690,18 @@ routes.get("/publication/:publicationId/biblio", async (req, res) => {
res
.
json
({});
});
routes
.
get
(
"
/copies/
"
,
async
(
req
,
res
)
=>
{
const
deichmanCallId
=
req
.
headers
[
CALL_ID_HEADER
];
const
{
id
:
idString
}
=
req
.
query
;
const
ids
=
`
${
idString
}
`
.
split
(
"
,
"
);
const
info
=
await
getWorkItemsByRecordIds
(
ids
,
req
.
query
.
categorycode
,
deichmanCallId
);
res
.
json
(
info
);
});
module
.
exports
=
routes
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment