iconograph-ui 1.7.19 → 2.0.0
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.
- package/example/src/routes/{+page.svelte → basic/+page.svelte} +3 -1
- package/example/src/routes/{user → basic/user}/+page.svelte +12 -2
- package/example/src/routes/parabole/+layout.svelte +111 -0
- package/example/src/routes/parabole/+page.svelte +112 -0
- package/example/static/css/testapp.css +8 -3
- package/example/static/icons/discord-logo-icon.svg +22 -0
- package/example/static/icons/icon-add-w.svg +38 -0
- package/example/static/icons/icon-archive-black.svg +1 -0
- package/example/static/icons/icon-archive-grey.svg +38 -0
- package/example/static/icons/icon-beneficiaire-small.svg +50 -0
- package/example/static/icons/icon-beneficiaire.svg +48 -0
- package/example/static/icons/icon-cardlist-black.svg +56 -0
- package/example/static/icons/icon-cardlist-grey.svg +56 -0
- package/example/static/icons/icon-client.png +0 -0
- package/example/static/icons/icon-dashboard.svg +40 -0
- package/example/static/icons/icon-doc.svg +39 -0
- package/example/static/icons/icon-done.svg +1 -0
- package/example/static/icons/icon-edit-g.svg +61 -0
- package/example/static/icons/icon-edit-w.svg +1 -0
- package/example/static/icons/icon-info-100.svg +54 -0
- package/example/static/icons/icon-info-w.svg +39 -0
- package/example/static/icons/icon-kanban-black.svg +65 -0
- package/example/static/icons/icon-kanban-grey.svg +65 -0
- package/example/static/icons/icon-link.svg +47 -0
- package/example/static/icons/icon-list-black.svg +76 -0
- package/example/static/icons/icon-list-grey.svg +76 -0
- package/example/static/icons/icon-member.png +0 -0
- package/example/static/icons/icon-next-w.svg +42 -0
- package/example/static/icons/icon-note.svg +44 -0
- package/example/static/icons/icon-order.svg +61 -0
- package/example/static/icons/icon-out.svg +38 -0
- package/example/static/icons/icon-project.svg +39 -0
- package/example/static/icons/icon-red-star.svg +53 -0
- package/example/static/icons/icon-save-b.png +0 -0
- package/example/static/icons/icon-save-w.png +0 -0
- package/example/static/icons/icon-task.svg +40 -0
- package/example/static/icons/icon-timeline-black.svg +68 -0
- package/example/static/icons/icon-timeline-grey.svg +68 -0
- package/example/static/icons/icon-user-add.svg +41 -0
- package/example/static/icons/icon-user.png +0 -0
- package/example/static/icons/icon-user.svg +39 -0
- package/example/static/icons/loader-ring-w.svg +1 -0
- package/lib/{display → components/display}/Portal.svelte +3 -3
- package/lib/{form → components/form}/ActionButton.svelte +53 -18
- package/lib/{layout → components/layout}/Card.svelte +2 -1
- package/lib/{navigation → components/navigation}/Button.svelte +10 -2
- package/lib/{navigation → components/navigation}/MainMenu.svelte +26 -33
- package/lib/{navigation → components/navigation}/MenuItem.svelte +8 -7
- package/lib/{navigation → components/navigation}/NavBar.svelte +8 -7
- package/lib/network/APIErrors.js +51 -0
- package/lib/network/action.js +21 -0
- package/lib/network/clientFetch.js +50 -0
- package/lib/network/index.js +1 -0
- package/lib/network/requestApi.js +127 -0
- package/lib/network/requestn8n.js +52 -0
- package/lib/utils/flattenType.js +8 -0
- package/lib/utils/transformers/entityTransformer.js +28 -0
- package/lib/utils/transformers/index.js +1 -0
- package/lib/utils/transformers/projectTransformer.js +17 -0
- package/lib/utils/transformers/userTransformer.js +36 -0
- package/package.json +11 -3
- /package/example/src/routes/{+layout.svelte → basic/+layout.svelte} +0 -0
- /package/example/src/routes/{example → basic/example}/+server.js +0 -0
- /package/example/src/routes/{user → basic/user}/+server.js +0 -0
- /package/lib/{display → components/display}/DateStr.svelte +0 -0
- /package/lib/{display → components/display}/Field.svelte +0 -0
- /package/lib/{display → components/display}/Link.svelte +0 -0
- /package/lib/{form → components/form}/Checkbox.svelte +0 -0
- /package/lib/{form → components/form}/FlexForm.svelte +0 -0
- /package/lib/{form → components/form}/Form.svelte +0 -0
- /package/lib/{form → components/form}/FormButton.svelte +0 -0
- /package/lib/{form → components/form}/Input.svelte +0 -0
- /package/lib/{form → components/form}/MultiSelect.svelte +0 -0
- /package/lib/{form → components/form}/SegmentedSwitchInput.svelte +0 -0
- /package/lib/{form → components/form}/SexeChoiceInput.svelte +0 -0
- /package/lib/{inputs → components/form/inputs}/Editor.svelte +0 -0
- /package/lib/{inputs → components/form/inputs}/PasswordInput.svelte +0 -0
- /package/lib/{inputs → components/form/inputs}/SearchSelect.svelte +0 -0
- /package/lib/{layout → components/layout}/BodySection.svelte +0 -0
- /package/lib/{layout → components/layout}/HeadSection.svelte +0 -0
- /package/lib/{layout → components/layout}/Modal.svelte +0 -0
- /package/lib/{layout → components/layout}/SectionContent.svelte +0 -0
- /package/lib/{notification → components/notification}/Notification.svelte +0 -0
- /package/lib/{notification → components/notification}/NotificationWrapper.svelte +0 -0
- /package/lib/{table → components/table}/CellLink.svelte +0 -0
- /package/lib/{table → components/table}/Table.svelte +0 -0
- /package/lib/{table → components/table}/TableColumnFilter.svelte +0 -0
- /package/lib/{table → components/table}/TableFilter.svelte +0 -0
- /package/lib/{table → components/table}/TablePagination.svelte +0 -0
- /package/lib/{table → components/table}/TableRow.svelte +0 -0
- /package/lib/{user → components/user}/SelectUserInput.svelte +0 -0
- /package/lib/{user → components/user}/UserPicture.svelte +0 -0
- /package/lib/utils/{clickOutside.js → ui/clickOutside.js} +0 -0
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
export let options = [];
|
|
9
9
|
export let style = "classic";
|
|
10
|
+
export let outline = false;
|
|
10
11
|
|
|
11
12
|
let open = false;
|
|
12
13
|
let dropdownEl;
|
|
@@ -26,7 +27,7 @@
|
|
|
26
27
|
|
|
27
28
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
28
29
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
29
|
-
<div class="dropdown {open ? 'open' : ''} {style == "icon" ? 'icon' : ''}"
|
|
30
|
+
<div class="dropdown {open ? 'open' : ''} {style == "icon" ? 'icon' : ''} {outline ? 'outline' : '' }"
|
|
30
31
|
bind:this={dropdownEl} use:clickOutside on:click_outside={() => {open = false}}
|
|
31
32
|
on:click|preventDefault|stopPropagation={openDropdown}>
|
|
32
33
|
{#if style == "icon"}
|
|
@@ -38,12 +39,16 @@
|
|
|
38
39
|
<!-- Liste déroulante -->
|
|
39
40
|
{#if open}
|
|
40
41
|
<Portal target="#main-container" position={"top: 0px; right: 0px"}>
|
|
41
|
-
<div class="list" style="position: absolute; top:{coords.top +
|
|
42
|
+
<div class="list" style="position: absolute; top:{coords.top + 6}px; right:{coords.right - 0}px; width: {coords.width}px;" >
|
|
42
43
|
<!-- Options -->
|
|
43
44
|
{#each options as opt}
|
|
44
|
-
|
|
45
|
+
{#if opt.separator }
|
|
46
|
+
<hr />
|
|
47
|
+
{:else}
|
|
48
|
+
<div class="option" on:click={opt.action} style:background-image={`url("${opt.icon}")`} >
|
|
45
49
|
<span>{opt.label}</span>
|
|
46
50
|
</div>
|
|
51
|
+
{/if}
|
|
47
52
|
{/each}
|
|
48
53
|
</div>
|
|
49
54
|
</Portal>
|
|
@@ -67,27 +72,34 @@
|
|
|
67
72
|
}
|
|
68
73
|
.dropdown > div:first-of-type {
|
|
69
74
|
background-color: var(--theme-input-bg-highlight);
|
|
75
|
+
box-shadow: var(--button-box-shadow);
|
|
70
76
|
height: 32px;
|
|
71
77
|
border: none;
|
|
72
|
-
border-radius:
|
|
78
|
+
border-radius: 7px;
|
|
73
79
|
cursor: pointer;
|
|
74
80
|
padding: 0px 8px;
|
|
75
81
|
font-size: 14px;
|
|
76
|
-
line-height:
|
|
77
|
-
font-weight:
|
|
82
|
+
line-height: 32px;
|
|
83
|
+
font-weight: 500;
|
|
78
84
|
font-family: var(--theme-text-font);
|
|
79
|
-
color: #
|
|
85
|
+
color: #121212;
|
|
80
86
|
flex: 1;
|
|
81
|
-
min-width: 76px;
|
|
82
87
|
background-size: 14px auto;
|
|
83
88
|
background-repeat: no-repeat;
|
|
84
|
-
background-position: center right
|
|
85
|
-
padding-left:
|
|
86
|
-
|
|
89
|
+
background-position: center right 12px;
|
|
90
|
+
padding-left: 18px;
|
|
91
|
+
padding-right: 32px;
|
|
87
92
|
transition: all ease-in-out 0.17s;
|
|
88
93
|
}
|
|
94
|
+
.dropdown.outline > div:first-of-type {
|
|
95
|
+
height: 30px;
|
|
96
|
+
line-height: 30px;
|
|
97
|
+
border: 1px solid var(--button-border-color);
|
|
98
|
+
background-color: var(--main-bg-color);
|
|
99
|
+
}
|
|
89
100
|
.dropdown > div:first-of-type:hover {
|
|
90
101
|
background-color: var(--theme-input-bg-hover);
|
|
102
|
+
box-shadow: var(--button-hover-box-shadow);
|
|
91
103
|
}
|
|
92
104
|
.dropdown > div:first-of-type.icon {
|
|
93
105
|
min-width: 1px;
|
|
@@ -99,30 +111,45 @@
|
|
|
99
111
|
padding: 0px;
|
|
100
112
|
height: 32px;
|
|
101
113
|
}
|
|
114
|
+
.dropdown.outline > div:first-of-type.icon {
|
|
115
|
+
height: 30px;
|
|
116
|
+
line-height: 30px;
|
|
117
|
+
max-width: 30px;
|
|
118
|
+
border: 1px solid var(--button-border-color);
|
|
119
|
+
background-color: var(--main-bg-color);
|
|
120
|
+
}
|
|
121
|
+
.dropdown.outline > div:first-of-type:hover {
|
|
122
|
+
background-color: var(--theme-input-bg-highlight);
|
|
123
|
+
}
|
|
102
124
|
.list {
|
|
103
125
|
position: absolute;
|
|
104
126
|
top: 100%;
|
|
105
127
|
right: 0px;
|
|
106
128
|
background: #ffffff; /*var(--theme-input-bg-highlight, #ebebed);*/
|
|
107
|
-
border-radius:
|
|
129
|
+
border-radius: 7px;
|
|
108
130
|
padding: 8px 0px;
|
|
109
131
|
max-height: 220px;
|
|
110
132
|
overflow-y: auto;
|
|
111
133
|
z-index: 9999;
|
|
112
|
-
min-width:
|
|
113
|
-
border: 1px solid
|
|
114
|
-
box-shadow: #
|
|
134
|
+
min-width: 260px;
|
|
135
|
+
border: 1px solid var(--button-border-color);
|
|
136
|
+
box-shadow: #77777715 0 3px 10px;
|
|
115
137
|
}
|
|
116
138
|
.option {
|
|
117
139
|
display: flex;
|
|
118
140
|
align-items: center;
|
|
119
|
-
padding: 8px
|
|
141
|
+
padding: 8px 12px 8px 36px;
|
|
142
|
+
margin: 0px 8px;
|
|
120
143
|
gap: 8px;
|
|
121
144
|
cursor: pointer;
|
|
145
|
+
border-radius: 5px;
|
|
146
|
+
background-size: 20px auto;
|
|
147
|
+
background-repeat: no-repeat;
|
|
148
|
+
background-position: center left 8px;
|
|
122
149
|
}
|
|
123
150
|
.option > span {
|
|
124
151
|
font-size: 14px;
|
|
125
|
-
line-height:
|
|
152
|
+
line-height: 20px;
|
|
126
153
|
font-weight: 400;
|
|
127
154
|
font-family: var(--theme-text-font);
|
|
128
155
|
color: var(--theme-input-text-color);
|
|
@@ -131,6 +158,14 @@
|
|
|
131
158
|
text-overflow: ellipsis;
|
|
132
159
|
}
|
|
133
160
|
.option:hover {
|
|
134
|
-
background: var(--theme-input-bg-
|
|
161
|
+
background-color: var(--theme-input-bg-color);
|
|
162
|
+
}
|
|
163
|
+
hr {
|
|
164
|
+
color: var(--button-border-color);
|
|
165
|
+
height: 0;
|
|
166
|
+
line-height: 0;
|
|
167
|
+
margin: 7px 12px;
|
|
168
|
+
border-top: 1px solid var(--button-border-color);
|
|
169
|
+
border-bottom: 0px solid var(--button-border-color);
|
|
135
170
|
}
|
|
136
171
|
</style>
|
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
width: 100%;
|
|
13
13
|
background-color: var(--main-bg-color);
|
|
14
14
|
box-sizing: border-box;
|
|
15
|
-
border: 1px solid var(--main-border-color);
|
|
15
|
+
border: var(--main-border, 1px solid var(--main-border-color));
|
|
16
16
|
border-radius: 8px;
|
|
17
17
|
overflow: hidden;
|
|
18
|
+
box-shadow: var(--main-shadow);
|
|
18
19
|
}
|
|
19
20
|
</style>
|
|
@@ -34,9 +34,9 @@ a, button {
|
|
|
34
34
|
display: inline-block;
|
|
35
35
|
background-color: var(--theme-main-color);
|
|
36
36
|
color: #ffffff !important;
|
|
37
|
-
|
|
37
|
+
box-shadow: var(--button-box-shadow);
|
|
38
38
|
border: 1px solid var(--theme-main-color);
|
|
39
|
-
border-radius:
|
|
39
|
+
border-radius: 7px;
|
|
40
40
|
height: 30px;
|
|
41
41
|
line-height: 30px !important;
|
|
42
42
|
font-size: 13px;
|
|
@@ -86,6 +86,14 @@ a:disabled {
|
|
|
86
86
|
background-size: 18px;
|
|
87
87
|
padding-left: 36px;
|
|
88
88
|
}
|
|
89
|
+
.min {
|
|
90
|
+
min-width: 30px;
|
|
91
|
+
border: 1px solid var(--theme-main-color);
|
|
92
|
+
padding: 0px 0px;
|
|
93
|
+
background-position: center center;
|
|
94
|
+
background-size: 18px;
|
|
95
|
+
padding-left: 0px;
|
|
96
|
+
}
|
|
89
97
|
.disabled {
|
|
90
98
|
background-color: #eee;
|
|
91
99
|
color: #888 !important;
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
afterUpdate(() => {
|
|
14
14
|
current_url = $page.url.pathname.split('/');
|
|
15
15
|
current_url = '/' + current_url[1];
|
|
16
|
+
|
|
17
|
+
console.log(current_url);
|
|
16
18
|
});
|
|
17
19
|
|
|
18
20
|
</script>
|
|
@@ -26,9 +28,12 @@
|
|
|
26
28
|
</div>
|
|
27
29
|
</header>
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
{#if menu.logo != null}
|
|
32
|
+
<div class="logo" >
|
|
33
|
+
</div>
|
|
34
|
+
{:else}
|
|
35
|
+
<div><h1>Bienvenue</h1></div>
|
|
36
|
+
{/if}
|
|
32
37
|
|
|
33
38
|
<div class="main">
|
|
34
39
|
<ul>
|
|
@@ -53,19 +58,21 @@
|
|
|
53
58
|
padding: 14px;
|
|
54
59
|
position: absolute;
|
|
55
60
|
top: 10px;
|
|
56
|
-
right: -11px
|
|
61
|
+
/*right: -11px;*/
|
|
62
|
+
left: 20px;
|
|
57
63
|
z-index: 300;
|
|
64
|
+
margin-bottom: 12px;
|
|
58
65
|
}
|
|
59
66
|
header > div {
|
|
60
67
|
position: absolute;
|
|
61
|
-
top:
|
|
68
|
+
top: 16px;
|
|
62
69
|
left: 0px;
|
|
63
70
|
width: 32px;
|
|
64
71
|
height: 32px;
|
|
65
72
|
border-radius: 30px;
|
|
66
73
|
cursor: pointer;
|
|
67
|
-
background-color: #
|
|
68
|
-
border: 1px solid var(--main-border-color)
|
|
74
|
+
/*background-color: var(--main-menu-bg-color, #ffffff);
|
|
75
|
+
border: 1px solid var(--main-border-color);*/
|
|
69
76
|
transition: all ease-in-out 0.3s;
|
|
70
77
|
align-self: flex-end;
|
|
71
78
|
}
|
|
@@ -77,22 +84,22 @@
|
|
|
77
84
|
height: 32px;
|
|
78
85
|
}
|
|
79
86
|
header > div.menu-open {
|
|
80
|
-
background-color: #
|
|
87
|
+
/*background-color: var(--main-menu-bg-color, #ffffff);*/
|
|
81
88
|
box-shadow: inset;
|
|
82
89
|
}
|
|
83
90
|
header > div > div > div{
|
|
84
91
|
display: inline-block;
|
|
85
92
|
position: absolute;
|
|
86
93
|
vertical-align: top;
|
|
87
|
-
background-color: #
|
|
94
|
+
background-color: #555;
|
|
88
95
|
border-radius: 0px;
|
|
89
|
-
height:
|
|
90
|
-
width:
|
|
96
|
+
height: 3px;
|
|
97
|
+
width: 25px;
|
|
91
98
|
transition: all 0.3s;
|
|
92
99
|
border-radius: 0px;
|
|
93
100
|
}
|
|
94
101
|
header > div > div > div:nth-of-type(1){
|
|
95
|
-
top:
|
|
102
|
+
top: 12px;
|
|
96
103
|
left: 10px;
|
|
97
104
|
}
|
|
98
105
|
header > div > div > div:nth-of-type(2){
|
|
@@ -100,7 +107,7 @@
|
|
|
100
107
|
left: 10px;
|
|
101
108
|
}
|
|
102
109
|
header > div > div > div:nth-of-type(3){
|
|
103
|
-
top:
|
|
110
|
+
top: 28px;
|
|
104
111
|
left: 10px;
|
|
105
112
|
}
|
|
106
113
|
header > div.menu-open > div > div:nth-of-type(1){
|
|
@@ -115,7 +122,7 @@
|
|
|
115
122
|
transform: rotate(-45deg);
|
|
116
123
|
}
|
|
117
124
|
nav {
|
|
118
|
-
background-color: var(--main-bg-color);
|
|
125
|
+
background-color: var(--main-menu-bg-color, #ffffff);
|
|
119
126
|
position: fixed;
|
|
120
127
|
top: 0px;
|
|
121
128
|
left: 0px;
|
|
@@ -124,7 +131,7 @@
|
|
|
124
131
|
max-height: 100vh;
|
|
125
132
|
box-sizing: border-box;
|
|
126
133
|
border-right: 1px solid var(--main-border-color);
|
|
127
|
-
padding-top:
|
|
134
|
+
padding-top: 80px;
|
|
128
135
|
padding-bottom: 10px;
|
|
129
136
|
transition: all ease-in-out 0.4s;
|
|
130
137
|
display: flex;
|
|
@@ -136,23 +143,6 @@
|
|
|
136
143
|
transform: translateX(0px);
|
|
137
144
|
width: 285px;
|
|
138
145
|
}
|
|
139
|
-
nav > .logo {
|
|
140
|
-
width: 48px;
|
|
141
|
-
height: 40px;
|
|
142
|
-
min-height: 40px;
|
|
143
|
-
background-image: var(--logo-large);
|
|
144
|
-
background-size: auto 32px;
|
|
145
|
-
background-repeat: no-repeat;
|
|
146
|
-
background-position: 0px center;
|
|
147
|
-
margin-bottom: 32px;
|
|
148
|
-
margin-left: 17px;
|
|
149
|
-
transition: all ease-in-out 0.4s;
|
|
150
|
-
}
|
|
151
|
-
nav.menu-open > .logo {
|
|
152
|
-
width: 248px;
|
|
153
|
-
background-size: auto 32px;
|
|
154
|
-
background-position: 0px center;
|
|
155
|
-
}
|
|
156
146
|
|
|
157
147
|
nav > .main {
|
|
158
148
|
flex: 1;
|
|
@@ -184,12 +174,15 @@
|
|
|
184
174
|
width: 285px;
|
|
185
175
|
}
|
|
186
176
|
header {
|
|
177
|
+
position: fixed;
|
|
187
178
|
top: 10px;
|
|
188
179
|
right: initial;
|
|
189
180
|
left: 105px;
|
|
181
|
+
transform: translateX(0px);
|
|
182
|
+
transition: all ease-in-out 0.4s;
|
|
190
183
|
}
|
|
191
184
|
nav.menu-open > header {
|
|
192
|
-
|
|
185
|
+
transform: translateX(-85px);
|
|
193
186
|
}
|
|
194
187
|
header > div {
|
|
195
188
|
border: none;
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
li {
|
|
25
25
|
list-style: none;
|
|
26
26
|
width: 100%;
|
|
27
|
-
margin-bottom:
|
|
27
|
+
margin-bottom: 2px;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
.menu-item {
|
|
@@ -68,8 +68,9 @@
|
|
|
68
68
|
line-height: 48px;
|
|
69
69
|
padding-left: 48px;
|
|
70
70
|
overflow: hidden;
|
|
71
|
-
font-weight: 600;
|
|
72
|
-
|
|
71
|
+
font-weight: var(--main-menu-font-weight, 600);
|
|
72
|
+
font-size: var(--main-menu-font-size);
|
|
73
|
+
color: var(--main-menu-fg-color, --theme-text-darkgrey);
|
|
73
74
|
font-family: var(--theme-title-font);
|
|
74
75
|
}
|
|
75
76
|
.menu-item > div.menu-open > div:nth-of-type(2) {
|
|
@@ -78,13 +79,13 @@
|
|
|
78
79
|
display: flex;
|
|
79
80
|
}
|
|
80
81
|
.menu-item.selected > div > div:nth-of-type(1) {
|
|
81
|
-
background-color: var(--theme-main-color);
|
|
82
|
+
background-color: var(--main-menu-fg-color, --theme-main-color);
|
|
82
83
|
}
|
|
83
84
|
.menu-item.selected > div > div:nth-of-type(2) {
|
|
84
|
-
color: var(--theme-main-color);
|
|
85
|
+
color: var(--main-menu-fg-color, --theme-main-color);
|
|
85
86
|
}
|
|
86
87
|
.menu-item:hover > div > div:nth-of-type(2) {
|
|
87
|
-
background-color: var(--theme-bg-color-light);
|
|
88
|
-
color: var(--theme-main-color);
|
|
88
|
+
background-color: var(--main-menu-bg-hover-color, --theme-bg-color-light);
|
|
89
|
+
color: var(--main-menu-fg-color, --theme-main-color);
|
|
89
90
|
}
|
|
90
91
|
</style>
|
|
@@ -4,16 +4,17 @@
|
|
|
4
4
|
export let tabs;
|
|
5
5
|
export let currentTab;
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
history.replaceState(null, '', `#${currentTab}`);
|
|
9
|
-
}*/
|
|
10
|
-
|
|
11
|
-
/*onMount(() => {
|
|
7
|
+
onMount(() => {
|
|
12
8
|
const hash = window.location.hash.replace('#', '');
|
|
13
9
|
|
|
14
10
|
if (hash && Object.keys(tabs).includes(hash))
|
|
15
11
|
currentTab = hash;
|
|
16
|
-
})
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
function onChangeTab(key) {
|
|
15
|
+
currentTab = key;
|
|
16
|
+
history.replaceState({}, "", `#${key}`);
|
|
17
|
+
}
|
|
17
18
|
|
|
18
19
|
</script>
|
|
19
20
|
|
|
@@ -21,7 +22,7 @@
|
|
|
21
22
|
{#each Object.keys(tabs) as key}
|
|
22
23
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
23
24
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
24
|
-
<div on:click={() => {
|
|
25
|
+
<div on:click={() => {onChangeTab(key)}} class="{currentTab == key ? 'selected' : ''}">
|
|
25
26
|
{tabs[key]}
|
|
26
27
|
</div>
|
|
27
28
|
{/each}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
|
|
3
|
+
export class APIError extends Error {
|
|
4
|
+
constructor(message, statusCode, endpoint, user = null) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = 'APIError';
|
|
7
|
+
this.statusCode = statusCode;
|
|
8
|
+
this.endpoint = endpoint;
|
|
9
|
+
this.user = user ? user : { id: null, email: null };
|
|
10
|
+
this.timestamp = new Date();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async logError() {
|
|
14
|
+
this.user = this.user.id ? await JSON.parse(this.user) : {};
|
|
15
|
+
console.error(`[${this.timestamp.toISOString()}] ${this.name}: ${this.message} (${this.statusCode}) at ${this.endpoint} - ${this.user.id}`);
|
|
16
|
+
console.trace(`${this.message} (${this.statusCode}) at ${this.endpoint}`);
|
|
17
|
+
|
|
18
|
+
if (this.statusCode != 401) {
|
|
19
|
+
const webhookUrl = "https://discord.com/api/webhooks/1422717261738676244/qZ5jx0uGTmcL2DEH8Kdb0IoerCh6VG27xIyKKJU55XYqwADhXXqM-qlh3E5WZzVH5nuV";
|
|
20
|
+
|
|
21
|
+
let stackTrace = this.stack || "No stack trace available.";
|
|
22
|
+
if (stackTrace.length > 1020)
|
|
23
|
+
stackTrace = stackTrace.slice(0, 1017) + "...";
|
|
24
|
+
|
|
25
|
+
const embed = {
|
|
26
|
+
title: process.env.NODE_ENV == 'development' ? "[DEV] erreur" : "⚠️ Nouvelle erreur détectée",
|
|
27
|
+
color: process.env.NODE_ENV == 'development' ? 0x0000ff : 0xff0000,
|
|
28
|
+
fields: [
|
|
29
|
+
{ name: "Message", value: String(this.statusCode) + ' ' + this.message },
|
|
30
|
+
{ name: "Endpoint", value: this.endpoint },
|
|
31
|
+
{ name: "User", value: this.user.email },
|
|
32
|
+
{ name: "Timestamp", value: this.timestamp.toISOString() },
|
|
33
|
+
{ name: "Stack Trace", value: "```" + stackTrace + "```" }
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
await fetch(webhookUrl, {
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers: { "Content-Type": "application/json" },
|
|
41
|
+
body: JSON.stringify({
|
|
42
|
+
username: "Error Logger",
|
|
43
|
+
embeds: [embed],
|
|
44
|
+
}),
|
|
45
|
+
});
|
|
46
|
+
} catch (err) {
|
|
47
|
+
console.error("Erreur lors de l'envoi au webhook Discord:", err);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { json } from '@sveltejs/kit';
|
|
3
|
+
import { requestApi } from './requestApi.js';
|
|
4
|
+
|
|
5
|
+
export async function addActivity(objectId, objectType, type, content, cookies) {
|
|
6
|
+
|
|
7
|
+
const response = await requestApi('POST', '/graphql', {
|
|
8
|
+
query: `mutation {
|
|
9
|
+
createAction (
|
|
10
|
+
objectId: "${objectId}",
|
|
11
|
+
objectType: "${objectType}",
|
|
12
|
+
type: "${type}",
|
|
13
|
+
content: "${encodeURI(content)}"
|
|
14
|
+
) {
|
|
15
|
+
id
|
|
16
|
+
}
|
|
17
|
+
}`
|
|
18
|
+
}, cookies);
|
|
19
|
+
|
|
20
|
+
return response.data.createAction;
|
|
21
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { addNotification } from "iconograph-ui";
|
|
3
|
+
import { APIError } from "./APIErrors";
|
|
4
|
+
import { json } from "@sveltejs/kit";
|
|
5
|
+
|
|
6
|
+
export const Notifications = {
|
|
7
|
+
All: 'ALL',
|
|
8
|
+
ErrorsOnly: 'ERROR_ONLY',
|
|
9
|
+
None: 'NONE'
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function clientFetch(method, uri, body, n = Notifications.All) {
|
|
13
|
+
let response;
|
|
14
|
+
|
|
15
|
+
if (method == 'GET' || !body) {
|
|
16
|
+
response = await fetch(uri, {
|
|
17
|
+
method: method,
|
|
18
|
+
headers: { 'Content-Type': 'application/json' }
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
response = await fetch(uri, {
|
|
23
|
+
method: method,
|
|
24
|
+
body: JSON.stringify(body),
|
|
25
|
+
headers: { 'Content-Type': 'application/json' }
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!response.ok && response.status == 401) {
|
|
30
|
+
if (n != Notifications.None)
|
|
31
|
+
addNotification({ 'status': 'failure', 'message': 'Votre session a expiré, veuillez vous reconnecter' });
|
|
32
|
+
return window.location = '/auth/signout?reason=Expired'
|
|
33
|
+
}
|
|
34
|
+
if (!response.ok && response.status == 404 && n != Notifications.None) {
|
|
35
|
+
(new APIError(JSON.stringify(response, null, 4) , response.status, uri, null)).logError();
|
|
36
|
+
return addNotification({ 'status': 'failure', 'message': 'Erreur ' + response.status });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const data = await response.json();
|
|
40
|
+
|
|
41
|
+
if (!response.ok && (n === Notifications.ErrorsOnly || n === Notifications.All)) {
|
|
42
|
+
(new APIError(JSON.stringify(data.message, null, 4) , response.status, uri, null)).logError();
|
|
43
|
+
addNotification({ 'status': 'failure', 'message': response.status + ': ' + data.message });
|
|
44
|
+
data.__errors == true;
|
|
45
|
+
}
|
|
46
|
+
else if (method != 'GET' && n == Notifications.All)
|
|
47
|
+
addNotification({ 'status': 'success', 'message': data.message });
|
|
48
|
+
|
|
49
|
+
return data;
|
|
50
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * as network from "./"
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { error, redirect } from '@sveltejs/kit';
|
|
3
|
+
import { env } from '$env/dynamic/private';
|
|
4
|
+
import { APIError } from './APIErrors';
|
|
5
|
+
|
|
6
|
+
let API_DATA_HOST = process.env.API_DATA_HOST || 'srvc-data';
|
|
7
|
+
let API_DATA_PORT = process.env.API_DATA_PORT || '3030';
|
|
8
|
+
|
|
9
|
+
let API_OIDC_HOST = env.API_OIDC_HOST || 'localhost';
|
|
10
|
+
let API_OIDC_PORT = env.API_OIDC_PORT || '3030';
|
|
11
|
+
|
|
12
|
+
const dev = (!env.NODE_ENV) || env.NODE_ENV === 'development';
|
|
13
|
+
|
|
14
|
+
async function fetchInterceptor(resource, config, cookies, cookieName) {
|
|
15
|
+
try {
|
|
16
|
+
const raw = await fetch(resource, config);
|
|
17
|
+
const text = await raw.text();
|
|
18
|
+
let json;
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
json = JSON.parse(text);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
throw new APIError("Invalid JSON received from API", 502, resource);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/*if (response.errors) {
|
|
28
|
+
if (response.errors[0].message == 'Not authenticated') {
|
|
29
|
+
|
|
30
|
+
/*const refreshToken = cookies.get('refreshToken');
|
|
31
|
+
response = await fetch('http://' + API_OIDC_HOST + ':' + API_OIDC_PORT + '/jwks/sign/' + tokenNames[cookieName], {
|
|
32
|
+
method: 'POST',
|
|
33
|
+
body: JSON.stringify({refreshToken: refreshToken}),
|
|
34
|
+
headers: headers,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
if (!response.ok)
|
|
38
|
+
return response;
|
|
39
|
+
|
|
40
|
+
const data = await response.json();
|
|
41
|
+
cookies.set(cookieName, data.token, {
|
|
42
|
+
path: '/',
|
|
43
|
+
httpOnly: true,
|
|
44
|
+
sameSite: 'lax',
|
|
45
|
+
secure: !dev,
|
|
46
|
+
maxAge: 60 * 100
|
|
47
|
+
});*/
|
|
48
|
+
|
|
49
|
+
// config.headers['Authorization'] = data.token;
|
|
50
|
+
// response = await fetch(resource, config);
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
return { raw, json };
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
if (e.message === 'fetch failed') {
|
|
57
|
+
error(501, { message: "Le serveur de données n'est pas disponible (__SRVC_DATACORE_DOWN__)"});
|
|
58
|
+
}
|
|
59
|
+
throw e;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export async function request(method, url, body, cookies, cookieName) {
|
|
64
|
+
|
|
65
|
+
const jwt = cookies.get(cookieName);
|
|
66
|
+
const headers = {
|
|
67
|
+
'Accept': 'application/json',
|
|
68
|
+
'Content-Type': 'application/json',
|
|
69
|
+
...(jwt ? { Authorization: 'Bearer ' + jwt } : {})
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
const { raw, json } = await fetchInterceptor(url, {
|
|
74
|
+
method: method,
|
|
75
|
+
body: (method == 'GET' || method == 'HEAD') ? undefined : JSON.stringify(body),
|
|
76
|
+
headers: headers,
|
|
77
|
+
}, cookies, cookieName);
|
|
78
|
+
|
|
79
|
+
if (json.errors?.length) {
|
|
80
|
+
const msg = json.errors[0].message;
|
|
81
|
+
|
|
82
|
+
switch (msg) {
|
|
83
|
+
case "Not authenticated":
|
|
84
|
+
throw new APIError(msg, 401, url);
|
|
85
|
+
case "Unauthorized":
|
|
86
|
+
throw new APIError(msg, 403, url);
|
|
87
|
+
case "Invalid credentials":
|
|
88
|
+
throw new APIError("Identifiants non valides", 401, url);
|
|
89
|
+
default:
|
|
90
|
+
throw new APIError(msg, 500, url);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return json;
|
|
95
|
+
}
|
|
96
|
+
catch (e) {
|
|
97
|
+
throw e;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export async function requestApi(method, uri, body, cookies) {
|
|
102
|
+
try {
|
|
103
|
+
return await request(method, 'http://' + API_DATA_HOST + ':' + API_DATA_PORT + uri, body, cookies, 'BibliapediaAccessToken');
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
if (e instanceof APIError)
|
|
107
|
+
e.logError();
|
|
108
|
+
else
|
|
109
|
+
console.error(e)
|
|
110
|
+
|
|
111
|
+
error(e.statusCode, { message: e.message })
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export async function loadApi(method, uri, body, cookies) {
|
|
116
|
+
try {
|
|
117
|
+
return await request(method, 'http://' + API_DATA_HOST + ':' + API_DATA_PORT + uri, body, cookies, 'BibliapediaAccessToken');
|
|
118
|
+
}
|
|
119
|
+
catch (e) {
|
|
120
|
+
e.logError();
|
|
121
|
+
|
|
122
|
+
if (e.statusCode == 401)
|
|
123
|
+
return redirect(307, "/auth/signout?reason=Expired");
|
|
124
|
+
else
|
|
125
|
+
error(e.statusCode, { message: e.message })
|
|
126
|
+
}
|
|
127
|
+
}
|