Skip to content

Commit 64fe5ce

Browse files
committed
DynamicInputResolver, DynamicObjectSelect, ... supports now autoCompletionUrlParam. Cost-Search-Page supports now checkbox "showOnlyActives".
1 parent 78c2447 commit 64fe5ce

File tree

9 files changed

+58
-16
lines changed

9 files changed

+58
-16
lines changed

projectforge-rest/src/main/kotlin/org/projectforge/rest/fibu/kost/CostSearchPageRest.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class CostSearchPageRest : AbstractDynamicPageRest() {
4848
) : DisplayNameCapable
4949

5050
class SearchData {
51+
var onlyActiveEntries: Boolean? = true
5152
var cost1: CostObject? = null
5253
var cost2: CostObject? = null
5354
var cost1Number: Int? = null
@@ -67,14 +68,18 @@ class CostSearchPageRest : AbstractDynamicPageRest() {
6768
val layout = UILayout("menu.fibu.kostSearch")
6869

6970
layout.add(
71+
UICheckbox("onlyActiveEntries", label = "label.onlyActiveEntries")
72+
).add(
7073
UIRow().add(
7174
UICol(sm = 6).add(
7275
UIRow().add(
7376
UIInput(
7477
"cost1",
7578
label = "fibu.kost1",
7679
dataType = UIDataType.COST1,
77-
)
80+
).also {
81+
it.autoCompletionUrlParams = mapOf("onlyActiveEntries" to "onlyActiveEntries")
82+
}
7883
)
7984
).add(
8085
UIRow().add(
@@ -94,7 +99,9 @@ class CostSearchPageRest : AbstractDynamicPageRest() {
9499
"cost2",
95100
label = "fibu.kost2",
96101
dataType = UIDataType.COST2,
97-
)
102+
).also {
103+
it.autoCompletionUrlParams = mapOf("onlyActiveEntries" to "onlyActiveEntries")
104+
}
98105
)
99106
).add(
100107
UIRow().add(

projectforge-rest/src/main/kotlin/org/projectforge/rest/fibu/kost/Kost1PagesRest.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import org.springframework.web.bind.annotation.RequestMapping
3434
import org.springframework.web.bind.annotation.RestController
3535
import jakarta.servlet.http.HttpServletRequest
3636
import org.projectforge.business.fibu.KostFormatter
37+
import org.projectforge.business.fibu.kost.KostentraegerStatus
3738
import org.projectforge.business.user.ProjectForgeGroup
3839
import org.projectforge.framework.persistence.api.BaseSearchFilter
3940
import org.projectforge.framework.persistence.user.entities.PFUserDO
@@ -81,7 +82,11 @@ class Kost1PagesRest : AbstractDTOPagesRest<Kost1DO, Kost1, Kost1Dao>(Kost1Dao::
8182
}
8283

8384
override fun queryAutocompleteObjects(request: HttpServletRequest, filter: BaseSearchFilter): List<Kost1DO> {
84-
val list = super.queryAutocompleteObjects(request, filter)
85+
val onlyActiveEntries = request.getParameter("onlyActiveEntries")?.toBooleanStrictOrNull() ?: true
86+
var list = super.queryAutocompleteObjects(request, filter)
87+
if (onlyActiveEntries) {
88+
list = list.filter { it.kostentraegerStatus == null || it.kostentraegerStatus == KostentraegerStatus.ACTIVE }
89+
}
8590
list.forEach { it.displayName = kostFormatter.formatKost1(it, KostFormatter.FormatType.LONG) }
8691
return list
8792
}

projectforge-rest/src/main/kotlin/org/projectforge/rest/fibu/kost/Kost2PagesRest.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import jakarta.servlet.http.HttpServletRequest
2727
import org.projectforge.business.fibu.KostFormatter
2828
import org.projectforge.business.fibu.kost.Kost2DO
2929
import org.projectforge.business.fibu.kost.Kost2Dao
30+
import org.projectforge.business.fibu.kost.KostentraegerStatus
3031
import org.projectforge.framework.persistence.api.BaseSearchFilter
3132
import org.projectforge.framework.persistence.api.MagicFilter
3233
import org.projectforge.rest.config.Rest
@@ -116,7 +117,11 @@ class Kost2PagesRest : AbstractDTOPagesRest<Kost2DO, Kost2, Kost2Dao>(Kost2Dao::
116117
}
117118

118119
override fun queryAutocompleteObjects(request: HttpServletRequest, filter: BaseSearchFilter): List<Kost2DO> {
119-
val list = super.queryAutocompleteObjects(request, filter)
120+
val onlyActiveEntries = request.getParameter("onlyActiveEntries")?.toBooleanStrictOrNull() ?: true
121+
var list = super.queryAutocompleteObjects(request, filter)
122+
if (onlyActiveEntries) {
123+
list = list.filter { it.kostentraegerStatus == null || it.kostentraegerStatus == KostentraegerStatus.ACTIVE }
124+
}
120125
list.forEach { it.displayName = kostFormatter.formatKost2(it, KostFormatter.FormatType.LONG) }
121126
return list.sortedBy { it.displayName }
122127
}

projectforge-rest/src/main/kotlin/org/projectforge/ui/UIInput.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ data class UIInput(
4949
*/
5050
val autoComplete: AutoCompleteType? = null,
5151
/**
52-
* Input modes for HTML Input fields (e. g. inputmode="numeric").
52+
* Input modes for HTML Input fields (e.g. inputmode="numeric").
5353
*/
5454
val inputMode: InputMode? = null,
5555
/**
56-
* Pattern for HTML Input fields (e. g. pattern="\d*").
56+
* Pattern for HTML Input fields (e.g. pattern="\d*").
5757
*/
5858
val pattern: String? = null,
5959
) : UIElement(UIElementType.INPUT), UILabelledElement, IUIId {

projectforge-webapp/src/components/base/dynamicLayout/components/input/DynamicInputResolver.jsx

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,7 @@ function DynamicInputResolver(
4646
case 'GROUP':
4747
case 'EMPLOYEE':
4848
case 'COST1':
49-
Tag = DynamicObjectSelect;
50-
additionalProps.type = dataType;
51-
break;
5249
case 'COST2':
53-
Tag = DynamicObjectSelect;
54-
additionalProps.type = dataType;
55-
break;
5650
case 'KONTO':
5751
Tag = DynamicObjectSelect;
5852
additionalProps.type = dataType;

projectforge-webapp/src/components/base/dynamicLayout/components/select/DynamicObjectSelect.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import DynamicValidationManager from '../input/DynamicValidationManager';
77
function DynamicObjectSelect(
88
{
99
id,
10+
urlparams,
1011
...props
1112
},
1213
) {
@@ -21,6 +22,7 @@ function DynamicObjectSelect(
2122
onSelect={handleSelect}
2223
translations={ui.translations}
2324
value={data[id] || {}}
25+
urlparams={urlparams}
2426
{...props}
2527
/>
2628
</DynamicValidationManager>
@@ -29,6 +31,7 @@ function DynamicObjectSelect(
2931

3032
DynamicObjectSelect.propTypes = {
3133
id: PropTypes.string.isRequired,
34+
urlparams: PropTypes.shape({}),
3235
};
3336

3437
export default DynamicObjectSelect;

projectforge-webapp/src/components/design/input/autoCompletion/ObjectAutoCompletion.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ function ObjectAutoCompletion(
1111
inputId,
1212
inputProps,
1313
onSelect,
14+
urlparams,
1415
value = {},
1516
...props
1617
},
@@ -66,6 +67,7 @@ function ObjectAutoCompletion(
6667
)}
6768
onSelect={onSelect}
6869
search={search}
70+
urlparams={urlparams}
6971
{...props}
7072
/>
7173
);
@@ -76,6 +78,7 @@ ObjectAutoCompletion.propTypes = {
7678
onSelect: PropTypes.func.isRequired,
7779
icon: PropTypes.shape({}),
7880
inputProps: PropTypes.shape({}),
81+
urlparams: PropTypes.shape({}),
7982
value: PropTypes.shape({
8083
displayName: PropTypes.string,
8184
}),

projectforge-webapp/src/components/design/input/autoCompletion/ObjectSelect.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ function ObjectSelect(
1616
translations,
1717
type,
1818
url,
19+
urlparams,
1920
user,
2021
value,
2122
...props
@@ -65,6 +66,7 @@ function ObjectSelect(
6566
inputProps={inputProps}
6667
onSelect={onSelect}
6768
url={url || `${type.toLowerCase()}/autosearch?search=:search`}
69+
urlparams={urlparams}
6870
value={value}
6971
{...props}
7072
/>
@@ -87,6 +89,7 @@ ObjectSelect.propTypes = {
8789
'tooltip.selectMe': PropTypes.string,
8890
}),
8991
url: PropTypes.string,
92+
urlparams: PropTypes.shape({}),
9093
user: PropTypes.shape({
9194
id: PropTypes.number.isRequired,
9295
displayName: PropTypes.string.isRequired,

projectforge-webapp/src/components/design/input/autoCompletion/index.jsx

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ import AwesomeDebouncePromise from 'awesome-debounce-promise';
22
import PropTypes from 'prop-types';
33
import React from 'react';
44
import { colorPropType } from '../../../../utilities/propTypes';
5-
import { debouncedWaitTime, getServiceURL, handleHTTPErrors } from '../../../../utilities/rest';
5+
import { debouncedWaitTime, getServiceURL, handleHTTPErrors, evalServiceURL } from '../../../../utilities/rest';
66
import AdvancedPopper from '../../popper/AdvancedPopper';
77
import styles from './AutoCompletion.module.scss';
88
import Completion from './Completion';
9+
import { DynamicLayoutContext } from '../../../base/dynamicLayout/context';
910

1011
const loadCompletionsBounced = (
1112
{
@@ -37,6 +38,7 @@ function AutoCompletion(
3738
color,
3839
input,
3940
url,
41+
urlparams,
4042
onSelect,
4143
required = false,
4244
search = '',
@@ -54,6 +56,25 @@ function AutoCompletion(
5456
() => AwesomeDebouncePromise(loadCompletionsBounced, debouncedWaitTime),
5557
);
5658

59+
// Try to get context data, but make it optional for backward compatibility
60+
const contextData = React.useContext(DynamicLayoutContext);
61+
const data = contextData?.data;
62+
63+
// Process URL params similar to DynamicAutoCompletion
64+
const processedUrl = React.useMemo(() => {
65+
if (!url) return url;
66+
67+
if (urlparams && data) {
68+
const autoCompletionData = {};
69+
Object.keys(urlparams).forEach((key) => {
70+
autoCompletionData[key] = Object.getByString(data, urlparams[key]);
71+
});
72+
return evalServiceURL(url, autoCompletionData);
73+
}
74+
75+
return url;
76+
}, [url, urlparams, data]);
77+
5778
const setIsOpen = (state) => {
5879
setIsOpenState(state);
5980

@@ -102,11 +123,11 @@ function AutoCompletion(
102123
};
103124

104125
React.useEffect(() => {
105-
if (url && wasOpen) {
126+
if (processedUrl && wasOpen) {
106127
const newAbortController = new AbortController();
107128

108129
loadCompletions({
109-
url,
130+
url: processedUrl,
110131
search,
111132
setCompletions,
112133
searchParameter,
@@ -118,7 +139,7 @@ function AutoCompletion(
118139
}
119140

120141
return undefined;
121-
}, [url, search, wasOpen]);
142+
}, [processedUrl, search, wasOpen]);
122143

123144
React.useEffect(() => {
124145
setSelected(Math.min(completions.length, selected));
@@ -169,6 +190,7 @@ AutoCompletion.propTypes = {
169190
additionalLabel: PropTypes.string,
170191
color: colorPropType,
171192
url: PropTypes.string,
193+
urlparams: PropTypes.shape({}),
172194
required: PropTypes.bool,
173195
search: PropTypes.string,
174196
searchParameter: PropTypes.string,

0 commit comments

Comments
 (0)