Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
4545b5c
WIP on change note user settings
lrosenstrom Oct 6, 2023
02516b1
Get change categories + labels from the data instead
lrosenstrom Oct 10, 2023
cae6e9a
Use flexbox instead of table
lrosenstrom Oct 11, 2023
f474a43
Simplify icon rotation css + make it work
lrosenstrom Oct 11, 2023
c16d9bc
*Naming things *Don't expand category list by default
lrosenstrom Oct 11, 2023
0dd1eb6
Sort list of sigels for changecategory view
lrosenstrom Oct 11, 2023
abcf5aa
Use sigel label instead of friendly name
lrosenstrom Oct 11, 2023
4a62eea
Cleanup
lrosenstrom Oct 11, 2023
830bacb
Write changenote notification email to user db
lrosenstrom Oct 12, 2023
e54dacb
Use library uri instead of library code in changesettings db
lrosenstrom Oct 16, 2023
e0bf139
Fix collection uri generation
lrosenstrom Oct 16, 2023
d036174
Fix sigelUri again
lrosenstrom Oct 16, 2023
fe76f94
Fix nullpointer on work extraction
lrosenstrom Oct 16, 2023
b23a37d
Cleanup
lrosenstrom Oct 16, 2023
9a2e23d
Let frontend facilitate a simple commit message in adminmetadata instead
lrosenstrom Oct 26, 2023
8db1bac
Alternative: overwrite changenote for each change.
lrosenstrom Oct 26, 2023
402a1cd
Label -> comment
lrosenstrom Oct 26, 2023
1c4fec4
Fix hightlight not being removed automatically
lrosenstrom Oct 26, 2023
2d8e587
Remove TODO
lrosenstrom Oct 26, 2023
0d8a1a1
Remove unused changenote code
lrosenstrom Oct 26, 2023
f6b6c83
WIP
lrosenstrom Oct 27, 2023
9a7484a
Avoid messing with the activeSearchType state when in the 'changes' view
lrosenstrom Oct 31, 2023
951d964
Make search tab menu look reasonable
lrosenstrom Oct 31, 2023
ab44db7
Restore file deleted by mistake
lrosenstrom Nov 1, 2023
da96898
Put change note search under directory care
lrosenstrom Nov 1, 2023
22d87de
Fix reverse relations spinner in change note search
lrosenstrom Nov 1, 2023
506d30d
Wrapper for change note view
lrosenstrom Nov 6, 2023
fd41d23
Search directly on change note view page load
lrosenstrom Nov 6, 2023
84e7d7a
Allow only one set of change categories for all library codes
lrosenstrom Nov 8, 2023
2ab0280
Aktivt sigel -> Aktiv sigel
lrosenstrom Nov 8, 2023
ee2bc16
WIP on facets
lrosenstrom Nov 9, 2023
77157eb
Checkboxes
lrosenstrom Nov 10, 2023
cf4d910
Checkboxes
lrosenstrom Nov 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion lxljs/string.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ export function isLibrisResourceUri(uri, settings) {
const baseUri = settings.dataPath;

let translatedUri = uri;
if (uri.startsWith('https://id.kb.se')) {
if (uri && uri.startsWith('https://id.kb.se')) {
translatedUri = uri.replace('https://id.kb.se', settings.idPath);
}

Expand Down Expand Up @@ -308,3 +308,20 @@ export function getFormattedEntries(list, vocab, language, context) {
remove(formatted, value => value === '' || value === null); // Remove empty strings
return formatted;
}

export function getSigelLabel(sigel, len) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is mostly a hygiene detail. Is it possible to use a bit more generic or less libris-centric names excluding the word sigel in some of these function or var/const names? Since the sigel is by our definition the code on something and not the actual entity it describes (contrary to how we use it in natural language, the hard part here being it plays different roles and is not always a library). Are we meaning userLocation? Not a stopper by any means and should it turn out to be too timeconsuming to figure out I wouldn't argue it easier to revisit later when the model and definitions around this is clearer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can change it to 'collection', because that's what it is called in the user store?

if (!sigel.friendly_name) {
return sigel.code;
}

const sigelPart = ` (${sigel.code})`;
const fName = sigel.friendly_name.length + sigelPart.length > len
? `${sigel.friendly_name.substr(0, len - sigelPart.length - 3)}...`
: sigel.friendly_name;

return `${fName}${sigelPart}`;
}

export function getLibraryUri(sigel) {
return `https://libris.kb.se/library/${sigel}`;
}
2 changes: 1 addition & 1 deletion vue-client/src/components/inspector/reverse-relations.vue
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ export default {
},
mounted() {
this.$nextTick(() => {
if (this.$route.name === 'Search' || this.forceLoad) {
if (this.$route.name === 'Search' || this.$route.params.tool === 'changes' || this.forceLoad) {
this.getRelationsInfo();
}
});
Expand Down
2 changes: 1 addition & 1 deletion vue-client/src/components/layout/search-bar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export default {
{{ versionInfo }}
</a>
</div>
<search-form class="SearchBar-searchForm col-sm-12 col-md-9" :search-perimeter="$route.params.perimeter" />
<search-form class="SearchBar-searchForm col-sm-12 col-md-9" :search-perimeter="$route.params.tool === 'changes' ? '' : $route.params.perimeter" :search-tool="$route.params.tool"/>
</div>
</div>
</div>
Expand Down
3 changes: 3 additions & 0 deletions vue-client/src/components/mixins/facet-mixin.vue
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ export default {
settings() {
return this.$store.getters.settings;
},
changeCategories() {
return this.$store.getters.userChangeCategories;
},
},

};
Expand Down
5 changes: 5 additions & 0 deletions vue-client/src/components/search/facet-controls.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ export default {
name: 'facet-controls',
props: {
result: {},
isChangeView: {
type: Boolean,
default: false,
},
},
data() {
return {
Expand Down Expand Up @@ -50,6 +54,7 @@ export default {
v-for="(dimensionValue, dimensionKey, index) in sortedFacets"
:key="dimensionKey"
:group="dimensionValue"
:is-change-view="isChangeView"
:expanded="index < numOfExpanded"/>
</div>
</template>
Expand Down
48 changes: 44 additions & 4 deletions vue-client/src/components/search/facet-group.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { mixin as clickaway } from 'vue-clickaway';
import * as DisplayUtil from 'lxljs/display';
import EncodingLevelIcon from '@/components/shared/encoding-level-icon';
import TypeIcon from '@/components/shared/type-icon';
import CheckBox from '@/components/shared/check-box';
import FacetMixin from '@/components/mixins/facet-mixin';
import Facet from './facet.vue';

Expand All @@ -18,6 +19,10 @@ export default {
expanded: {
type: Boolean,
},
isChangeView: {
type: Boolean,
default: false,
},
},
data() {
return {
Expand Down Expand Up @@ -47,7 +52,7 @@ export default {
this.$store.dispatch('setUser', userObj);
},
featuredComparison(facet) {
if (this.group.dimension === '@reverse.itemOf.heldBy.@id') {
if (this.isCollectionGroup(this.group.dimension)) {
// Featured code for '@reverse.itemOf.heldBy.@id'
const userSigels = this.user.collections.map(item => item.code);
if (facet.object.hasOwnProperty('sigel')) {
Expand All @@ -61,6 +66,20 @@ export default {
}
return false;
},
defaultChecked(facet) {
if (this.isChangeFacetGroup) {
const id = facet.object['@id'];
return this.checkedCategoriesAndSigels.includes(id);
}
return false;
},
checked(link, id) {
console.log('link', JSON.stringify(link));
console.log('id', JSON.stringify(id));
},
isCollectionGroup(dim) {
return dim === '@reverse.itemOf.heldBy.@id' || dim === '[email protected].@id';
},
},
computed: {
settings() {
Expand All @@ -76,6 +95,7 @@ export default {
const self = this;
const list = this.group.observation.map((o) => {
let label;
console.log('observation', JSON.stringify(o));
if (o.object.hasOwnProperty('@id')) {
label = DisplayUtil.getItemLabel(
o.object,
Expand All @@ -96,6 +116,7 @@ export default {
amount: o.totalItems,
link: o.view['@id'],
featured: self.featuredComparison(o),
isDefaultChecked: self.defaultChecked(o),
};
});
return list;
Expand Down Expand Up @@ -132,7 +153,7 @@ export default {
},
featuredFacets() {
let featured = this.facets.filter(o => o.featured === true);
if (this.group.dimension === '@reverse.itemOf.heldBy.@id') {
if (this.isCollectionGroup(this.group.dimension)) {
const activeSigel = this.user.settings.activeSigel;
featured = sortBy(featured, o => o.object.sigel !== activeSigel && o.label !== activeSigel && o.label !== `library/${activeSigel}`);
}
Expand Down Expand Up @@ -161,11 +182,18 @@ export default {
hasScroll() {
return !this.revealLevels[this.currentLevel] && this.isExpanded;
},
isChangeFacetGroup() {
return (this.group.dimension === 'category.@id' || this.group.dimension === '[email protected].@id') && this.isChangeView;
},
checkedCategoriesAndSigels() {
return [...this.changeCategories.map(c => c.heldBy), ...this.changeCategories.find(c => c.hasOwnProperty('triggers')).triggers];
},
},
components: {
Facet,
EncodingLevelIcon,
TypeIcon,
CheckBox,
},
};
</script>
Expand Down Expand Up @@ -209,7 +237,13 @@ export default {
:class="{'is-expanded' : isExpanded, 'has-scroll' : hasScroll}">
<facet v-for="facetItem in featuredFacets"
:facet="facetItem"
:key="'featured_'+facetItem.link">
:key="'featured_'+facetItem.link"
:is-link="!isChangeFacetGroup">
<check-box v-if="group.dimension === '[email protected].@id' && isChangeView"
slot="checkbox"
:checkedProperty="facetItem.object['@id']"
:isChosen="facetItem.isDefaultChecked"
@changed="checked(facetItem.link, facetItem.object['@id'])"></check-box>
<encoding-level-icon
slot="icon"
v-if="group.dimension === 'meta.encodingLevel'"
Expand All @@ -223,7 +257,13 @@ export default {
<hr v-show="featuredFacets.length > 0">
<facet v-for="facetItem in normalFacets"
:facet="facetItem"
:key="facetItem.link">
:key="facetItem.link"
:is-link="!isChangeFacetGroup">
<check-box v-if="group.dimension === 'category.@id' || group.dimension === '[email protected].@id' && isChangeView"
slot="checkbox"
:checkedProperty="facetItem.object['@id']"
:isChosen="facetItem.isDefaultChecked"
@changed="checked(facetItem.link, facetItem.object['@id'])"></check-box>
<encoding-level-icon
slot="icon"
v-if="group.dimension === 'meta.encodingLevel'"
Expand Down
5 changes: 5 additions & 0 deletions vue-client/src/components/search/facet.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export default {
type: Object,
default: null,
},
isLink: {
type: Boolean,
default: false,
},
},
data() {
return {
Expand Down Expand Up @@ -60,6 +64,7 @@ export default {
<template>
<li class="Facet">
<slot name="icon"></slot>
<slot name="checkbox"></slot>
<router-link class="Facet-link"
:to="facet.link | asAppPath"
:title="facet.label | capitalize">
Expand Down
1 change: 1 addition & 0 deletions vue-client/src/components/search/result-list-item.vue
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ export default {
<div class="ResultItem-tags" v-if="user.isLoggedIn && isImport === false">
<!-- <tag-switch :document="focusData" class="" :action-labels="{ on: 'Mark as', off: 'Unmark as' }" tag="Bookmark" /> -->
<tag-switch v-if="recordType === 'Instance'" :document="focusData" class="" :action-labels="{ on: 'Mark as', off: 'Unmark as' }" tag="Flagged" />
<tag-switch :document="focusData" class="" :action-labels="{ on: 'Mark as', off: 'Unmark as' }" tag="Handled" />
</div>
<div class="ResultItem-relationsContainer"
v-if="isImport === false">
Expand Down
41 changes: 35 additions & 6 deletions vue-client/src/components/search/search-form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export default {
default: 'libris',
type: String,
},
searchTool: {
default: '',
type: String,
},
},
data() {
return {
Expand Down Expand Up @@ -51,13 +55,18 @@ export default {
this.helpToggled = !this.helpToggled;
},
composeQuery() {
return buildQueryString(this.searchPerimeter === 'libris'
return buildQueryString(this.searchPerimeter === 'libris' || this.searchTool === 'changes'
? this.mergedParams
: { q: this.searchPhrase, databases: this.status.remoteDatabases.join() });
},
doSearch() {
this.helpToggled = false;
const path = `/search/${this.searchPerimeter}?${this.composeQuery()}`;
let path = '';
if (this.searchPerimeter === 'libris' || this.searchPerimeter === 'remote') {
path = `/search/${this.searchPerimeter}?${this.composeQuery()}`;
} else if (this.searchTool === 'changes') {
path = `${this.$route.path}?${this.composeQuery()}`;
}
this.$router.push({ path });
},
clearInputs() {
Expand Down Expand Up @@ -98,7 +107,7 @@ export default {
return PropertyMappings[0];
},
setType() {
if (this.$route.params.perimeter === 'remote') {
if (this.$route.params.perimeter === 'remote' || this.searchTool === 'changes') {
return this.activeSearchType; // Don't change while remote searching
}
const performedQuery = cloneDeep(this.$route.query);
Expand Down Expand Up @@ -183,7 +192,13 @@ export default {
return this.searchPhrase.length > 0;
},
inputPlaceholder() {
return this.searchPerimeter === 'remote' ? 'ISBN eller valfria sökord' : 'Search';
if (this.searchPerimeter === 'remote') {
return 'ISBN eller valfria sökord';
}
if (this.searchTool === 'changes') {
return 'Sök bland ändringar'; // TODO: i18n
}
return 'Search';
},
composedSearchParam() { // pair current search param with searchphrase
let composed = {};
Expand All @@ -197,7 +212,15 @@ export default {
return composed;
},
composedTypes() {
return this.activeSearchType && this.activeSearchType.length > 0 ? { '@type': this.activeSearchType } : { '@type': null };
let type = null;
if (this.activeSearchType && this.activeSearchType.length > 0) {
if (this.searchPerimeter === 'libris') {
type = this.activeSearchType;
} else if (this.searchTool === 'changes') {
type = 'AdministrativeNotice';
}
}
return { '@type': type };
},
prefSort() {
if (this.user && this.user.settings.sort) {
Expand Down Expand Up @@ -238,6 +261,12 @@ export default {
this.resetSearchParam();
}
},
searchTool(newVal, oldVal) {
if (newVal !== oldVal && newVal === 'changes') {
this.clearInputs();
this.doSearch();
}
},
searchPerimeter(newVal, oldVal) {
if (newVal !== oldVal) {
this.$nextTick(() => {
Expand Down Expand Up @@ -337,7 +366,7 @@ export default {
<span class="SearchForm-clear icon icon--md"
@focus="searchGroupFocus.clear = true"
@blur="searchGroupFocus.clear = false"
:class="{ 'in-remote': searchPerimeter === 'remote' }" tabindex="0" v-show="hasInput" @keyup.enter="clearInputs()" @click="clearInputs()">
:class="{ 'in-remote': searchPerimeter === 'remote' || searchTool === 'changes' }" tabindex="0" v-show="hasInput" @keyup.enter="clearInputs()" @click="clearInputs()">
<i class="fa fa-fw fa-close"></i>
</span>
<div class="SearchForm-selectWrapper SearchForm-paramSelectWrapper hidden-xs" v-if="searchPerimeter === 'libris'">
Expand Down
68 changes: 68 additions & 0 deletions vue-client/src/components/shared/check-box.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<script>
import { mapGetters } from 'vuex';

export default {
name: 'check-box',
props: {
checkedProperty: {
type: String,
default: '',
},
tooltipText: {
type: String,
default: '',
},
isChosen: {
type: Boolean,
default: false,
},
},
data() {
return {
};
},
methods: {
onChange(e) {
this.$emit('changed', e);
// emit on change and let the parent handle it.
},
},
computed: {
...mapGetters([
'resources',
]),
},
components: {
},
mounted() {
this.$nextTick(() => {});
},
};
</script>

<template>
<div class="TypeIcon">
<input id="test" class="customCheckbox-input" type="checkbox" @change="onChange" :checked="isChosen">
<div class="customCheckbox-icon"></div>
</div>
</template>

<style lang="less">
.TypeIcon {
background-color: @grey-lightest;
color: @brand-primary;
display: flex;
justify-content: center;
align-items: center;
min-width: 20px;
height: 20px;
border-radius: 0.25rem;
margin-right: 5px;
font-size: 12px;

&-label {
font-weight: 800;
}
}

</style>
1 change: 1 addition & 0 deletions vue-client/src/components/shared/entity-summary.vue
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ export default {
<div :title="topBarInformation" v-if="excludeComponents.indexOf('categorization') < 0" class="EntitySummary-type uppercaseHeading--light">
{{ topBarInformation }} {{ isLocal ? '{lokal entitet}' : '' }}
<span class="EntitySummary-sourceLabel" v-if="database">{{ database }}</span>
<span class="EntitySummary-sourceLabel" v-if="database">{{ database }}</span>
</div>
<div v-if="idAsFnurgel && excludeComponents.indexOf('id') < 0" class="EntitySummary-id" :class="{'recently-copied': recentlyCopiedId }" @mouseover="idHover = true" @mouseout="idHover = false">
<i v-tooltip.top="idTooltipText" class="fa fa-copy EntitySummary-idCopyIcon" :class="{'collapsedIcon': !idHover || recentlyCopiedId }" @click.stop="copyFnurgel">
Expand Down
Loading