@galadrim/galadmin 0.1.209 → 0.1.210

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,7 @@ import RichTextInput from "./inputs/RichTextInput";
3
3
  import BetterRichTextInput from "./inputs/BetterRichTextInput";
4
4
  import DatetimeInput from "./inputs/DatetimeInput";
5
5
  import AddressInput from "./inputs/AddressInput";
6
+ import CompanyInput from "./inputs/CompanyInput";
6
7
  import FileInput from "./inputs/FileInput";
7
8
  import ForeignSelectInput from "./inputs/ForeignSelectInput";
8
9
  import ForeignDatalistInput from "./inputs/ForeignDatalistInput";
@@ -91,6 +92,14 @@ export default ({ column, onChange, initialData }) => {
91
92
  initialData={initialData}
92
93
  />
93
94
  );
95
+ } else if (dataType === "company") {
96
+ return (
97
+ <CompanyInput
98
+ column={column}
99
+ onChange={onChange}
100
+ initialData={initialData}
101
+ />
102
+ );
94
103
  } else if (dataType === "color") {
95
104
  return (
96
105
  <ColorInput
@@ -0,0 +1,187 @@
1
+ import React, { useState, useEffect, useCallback, useRef } from 'react';
2
+ import debounce from 'lodash.debounce';
3
+ import axios from "axios";
4
+
5
+ export default ({ column, onChange, initialData }) => {
6
+ const [inputValue, setInputValue] = useState(initialData?.[column.companyNameField]);
7
+ const [suggestions, setSuggestions] = useState([]);
8
+ const [isLoading, setIsLoading] = useState(false);
9
+ const [isListVisible, setIsListVisible] = useState(false);
10
+ const latestQueryRef = useRef(inputValue);
11
+ const minSearchLength = 3;
12
+
13
+ const fetchSuggestions = async (query) => {
14
+ if (query.length < minSearchLength) {
15
+ setSuggestions([]);
16
+ setIsListVisible(false);
17
+ return;
18
+ }
19
+
20
+ setIsLoading(true);
21
+ setSuggestions([]);
22
+ latestQueryRef.current = query
23
+
24
+ try {
25
+ const response = await axios.get(`/searchCompanies`, {
26
+ params: {
27
+ query: query
28
+ }
29
+ });
30
+ const data = response.data;
31
+ if (query === latestQueryRef.current) {
32
+ setSuggestions(data);
33
+ setIsListVisible(data.length > 0);
34
+ }
35
+
36
+ } catch (err) {
37
+ console.error(err)
38
+ } finally {
39
+ if (query === latestQueryRef.current) {
40
+ setIsLoading(false);
41
+ }
42
+ }
43
+ };
44
+
45
+ // eslint-disable-next-line react-hooks/exhaustive-deps
46
+ const debouncedFetchSuggestions = useCallback(
47
+ debounce(fetchSuggestions, 300),
48
+ [inputValue]
49
+ );
50
+
51
+ const handleInputChange = (event) => {
52
+ const value = event.target.value;
53
+ setInputValue(value);
54
+
55
+ if (value.length === 0) {
56
+ setSuggestions([]);
57
+ setIsListVisible(false);
58
+ setIsLoading(false);
59
+ debouncedFetchSuggestions.cancel();
60
+ latestQueryRef.current = '';
61
+ } else if (value.length >= minSearchLength) {
62
+ setIsLoading(true);
63
+ debouncedFetchSuggestions(value);
64
+ } else {
65
+ setSuggestions([]);
66
+ setIsListVisible(false);
67
+ setIsLoading(false);
68
+ debouncedFetchSuggestions.cancel();
69
+ latestQueryRef.current = value;
70
+ }
71
+ };
72
+
73
+ const handleSelectCompany = (company) => {
74
+ setInputValue(company.companyName);
75
+ setSuggestions([]);
76
+ setIsListVisible(false);
77
+ const fieldValues = {
78
+ companyNameField: company.companyName,
79
+ sirenField: company.siren,
80
+ siretField: company.siret,
81
+ addressField: company.address,
82
+ cityField: company.city,
83
+ zipCodeField: company.zipCode,
84
+ activityNumberField: company.activityNumber,
85
+ }
86
+ const data = {}
87
+ for (const key in fieldValues) {
88
+ if (column[key]) {
89
+ data[column[key]] = fieldValues[key]
90
+ }
91
+ }
92
+ onChange(data);
93
+ };
94
+
95
+ useEffect(() => {
96
+ const handleClickOutside = (event) => {
97
+ if (!event.target.closest('.company-input-container')) {
98
+ setIsListVisible(false);
99
+ }
100
+ };
101
+
102
+ document.addEventListener('mousedown', handleClickOutside);
103
+ return () => {
104
+ document.removeEventListener('mousedown', handleClickOutside);
105
+ };
106
+ }, []);
107
+
108
+ return (
109
+ <div
110
+ className={`company-input-container`}
111
+ style={{ position: 'relative' }}
112
+ >
113
+ <input
114
+ type="text"
115
+ value={inputValue}
116
+ onChange={handleInputChange}
117
+ onFocus={() => {
118
+ if (suggestions.length > 0 && inputValue.length >= minSearchLength) {
119
+ setIsListVisible(true);
120
+ }
121
+ }}
122
+ placeholder={"Rechercher une entreprise..."}
123
+ aria-autocomplete="list"
124
+ aria-expanded={isListVisible}
125
+ style={{ width: '100%', boxSizing: 'border-box' }}
126
+ />
127
+
128
+ {isLoading && <div style={styles.loader}>Chargement...</div>}
129
+
130
+ {isListVisible && suggestions.length > 0 && (
131
+ <ul style={styles.suggestionList}>
132
+ {suggestions.map((company) => (
133
+ <li
134
+ key={company.id}
135
+ style={styles.suggestionItem}
136
+ onClick={() => handleSelectCompany(company)}
137
+ onMouseDown={(e) => e.preventDefault()}
138
+ role="option"
139
+ aria-selected="false"
140
+ >
141
+ <div style={styles.companyName}>{company.companyName}</div>
142
+ <div style={styles.companyAddress}>{company.siren} - {company.address}</div>
143
+ </li>
144
+ ))}
145
+ </ul>
146
+ )}
147
+ </div>
148
+ );
149
+ };
150
+
151
+ const styles = {
152
+ loader: {
153
+ position: 'absolute',
154
+ right: '10px',
155
+ top: '50%',
156
+ transform: 'translateY(-50%)',
157
+ fontSize: '0.8em',
158
+ color: '#888',
159
+ },
160
+ suggestionList: {
161
+ listStyleType: 'none',
162
+ padding: 0,
163
+ margin: 0,
164
+ position: 'absolute',
165
+ top: '100%',
166
+ left: 0,
167
+ right: 0,
168
+ border: '1px solid #ccc',
169
+ backgroundColor: 'white',
170
+ maxHeight: '200px',
171
+ overflowY: 'auto',
172
+ zIndex: 1000,
173
+ boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
174
+ },
175
+ suggestionItem: {
176
+ padding: '8px 12px',
177
+ cursor: 'pointer',
178
+ borderBottom: '1px solid #eee',
179
+ },
180
+ companyName: {
181
+ fontWeight: 'bold',
182
+ },
183
+ companyAddress: {
184
+ fontSize: '0.9em',
185
+ color: '#555',
186
+ },
187
+ };
@@ -39,7 +39,7 @@ export default ({ column, onChange, initialData, withTime }) => {
39
39
  <div>
40
40
  <input
41
41
  type="text"
42
- autocomplete="one-time-code"
42
+ autoComplete="one-time-code"
43
43
  ref={datepicker}
44
44
  data-timepicker={withTime ? "true" : "false"}
45
45
  />
@@ -24,13 +24,6 @@ export default () => {
24
24
  )
25
25
  const [isUpdating, setIsUpdating] = useState(false)
26
26
 
27
- for (let column of view.columns) {
28
- if (column.displayCondition) {
29
- console.log({ ...record, ...dataToUpdate })
30
- console.log(column.displayCondition({ ...record, ...dataToUpdate }))
31
- }
32
- }
33
-
34
27
  useEffect(() => {
35
28
  axios.get("/record", {
36
29
  params: {
@@ -97,6 +97,8 @@ export default (column, record, config, onTable) => {
97
97
  return <div>{record[column.name]?.join(", ")}</div>;
98
98
  } else if (column.dataType === "datetimeUTC") {
99
99
  return <div>{new Date(record[column.name] + "Z").toLocaleString()}</div>;
100
+ } else if (column.dataType === "company") {
101
+ return <div>{record[column.companyNameField]}</div>;
100
102
  } else {
101
103
  return <div>{record[column.name]}</div>;
102
104
  }
@@ -51,6 +51,17 @@ export type AddressColumn = {
51
51
  postalCodeField?: string;
52
52
  };
53
53
 
54
+ export type CompanyColumn = {
55
+ dataType: "company";
56
+ sirenField?: string;
57
+ siretField?: string;
58
+ companyNameField?: string;
59
+ addressField?: string;
60
+ zipCodeField?: string;
61
+ cityField?: string;
62
+ activityNumberField?: string;
63
+ };
64
+
54
65
  export type DateColumn = {
55
66
  dataType: "date";
56
67
  name: string;
@@ -450,6 +461,9 @@ export type Config = {
450
461
  /** Clé API Google Maps pour les champs adresses et l'affichage de cartes */
451
462
  googleMapsKey?: string;
452
463
 
464
+ /** Clé API INSEE pour la recherche de sociétés */
465
+ inseeKey?: string;
466
+
453
467
  /** Désactiver la sélection multiple dans les vues de type table */
454
468
  hideMultiselect?: boolean;
455
469
 
@@ -1,12 +0,0 @@
1
- #!/bin/sh
2
- basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
-
4
- case `uname` in
5
- *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
6
- esac
7
-
8
- if [ -x "$basedir/node" ]; then
9
- exec "$basedir/node" "$basedir/../semver/bin/semver.js" "$@"
10
- else
11
- exec node "$basedir/../semver/bin/semver.js" "$@"
12
- fi
@@ -1,17 +0,0 @@
1
- @ECHO off
2
- GOTO start
3
- :find_dp0
4
- SET dp0=%~dp0
5
- EXIT /b
6
- :start
7
- SETLOCAL
8
- CALL :find_dp0
9
-
10
- IF EXIST "%dp0%\node.exe" (
11
- SET "_prog=%dp0%\node.exe"
12
- ) ELSE (
13
- SET "_prog=node"
14
- SET PATHEXT=%PATHEXT:;.JS;=;%
15
- )
16
-
17
- endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\semver\bin\semver.js" %*
@@ -1,28 +0,0 @@
1
- #!/usr/bin/env pwsh
2
- $basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
3
-
4
- $exe=""
5
- if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
6
- # Fix case when both the Windows and Linux builds of Node
7
- # are installed in the same directory
8
- $exe=".exe"
9
- }
10
- $ret=0
11
- if (Test-Path "$basedir/node$exe") {
12
- # Support pipeline input
13
- if ($MyInvocation.ExpectingInput) {
14
- $input | & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args
15
- } else {
16
- & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args
17
- }
18
- $ret=$LASTEXITCODE
19
- } else {
20
- # Support pipeline input
21
- if ($MyInvocation.ExpectingInput) {
22
- $input | & "node$exe" "$basedir/../semver/bin/semver.js" $args
23
- } else {
24
- & "node$exe" "$basedir/../semver/bin/semver.js" $args
25
- }
26
- $ret=$LASTEXITCODE
27
- }
28
- exit $ret