Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Rex Dri
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Julien Jerphanion
Rex Dri
Commits
e9e8ecbe
Commit
e9e8ecbe
authored
Sep 01, 2018
by
Florent Chehab
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'better_api_integration' into 'master'
Better api integration See merge request chehabfl/outgoing_rex!24
parents
6ebf4368
86794957
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
199 additions
and
181 deletions
+199
-181
Makefile
Makefile
+3
-0
backend/generate/api_config.yml
backend/generate/api_config.yml
+90
-60
frontend/generate/generate_frontend_files.py
frontend/generate/generate_frontend_files.py
+17
-15
frontend/generate/templates/actions.tpl
frontend/generate/templates/actions.tpl
+10
-10
frontend/generate/templates/reducers.tpl
frontend/generate/templates/reducers.tpl
+6
-6
frontend/src/components/App.js
frontend/src/components/App.js
+8
-30
frontend/src/components/MyComponent.js
frontend/src/components/MyComponent.js
+45
-1
frontend/src/components/map/UnivMakers.js
frontend/src/components/map/UnivMakers.js
+8
-17
frontend/src/components/map/UnivMap.js
frontend/src/components/map/UnivMap.js
+10
-40
frontend/src/reducers/index.js
frontend/src/reducers/index.js
+2
-2
No files found.
Makefile
View file @
e9e8ecbe
...
...
@@ -7,6 +7,9 @@ install_backend:
generate_backend
:
python ./backend/generate/generate_all.py
generate_frontend
:
python ./frontend/generate/generate_frontend_files.py
test_backend
:
generate_backend
pytest
...
...
backend/generate/api_config.yml
View file @
e9e8ecbe
# THIS FILE IS USED TO GENERATE OTHER VERY IMPORTANT FILES
# BOTH IN THE FRONTEND AND IN THE BACKEND !
# TAKE CARE WHEN MODYFING IT ;)
# model : the model name (may be null)
# viewset : the viewset name for the api
# api_end_pont : the main part of the url for making request to the api
# This string will also be used for naming variables in JS !!
# So no weird characters there please...
# versionned: boolean to specify wether this model is versionned or not
# api_attr : to specify some attributes that may be captured
# and used in the viewset
# requires_testing: boolean to tell if this viewset is only availble in
# a testing environment.
-
model
:
Country
viewset
:
CountryViewSet
import_location
:
location
api_end_point
:
countr
y
api_end_point
:
countr
ies
-
model
:
City
viewset
:
CityViewSet
import_location
:
location
api_end_point
:
city
-
model
:
Tag
viewset
:
TagViewSet
import_location
:
tag
api_end_point
:
tag
api_end_point
:
cities
-
model
:
University
TaggedItem
viewset
:
University
TaggedItem
ViewSet
-
model
:
University
viewset
:
UniversityViewSet
import_location
:
university
api_end_point
:
university_more_tmp
versionned
:
true
api_end_point
:
universities
-
model
:
Campus
TaggedItem
viewset
:
Campus
TaggedItem
ViewSet
-
model
:
Campus
viewset
:
CampusViewSet
import_location
:
university
api_end_point
:
campus
_more_tmp
api_end_point
:
campus
es
versionned
:
true
-
model
:
CountryTaggedItem
viewset
:
CountryTaggedItemViewSet
import_location
:
location
api_end_point
:
country_more_tmp
versionned
:
true
-
model
:
CityTaggedItem
viewset
:
CityTaggedItemViewSet
import_location
:
location
api_end_point
:
city_more_tmp
versionned
:
true
-
model
:
UserData
viewset
:
UserDataViewSet
import_location
:
user
api_end_point
:
userData
api_name
:
user-data-detail
-
model
:
Tag
viewset
:
TagViewSet
import_location
:
tag
api_end_point
:
tags
-
model
:
Currency
viewset
:
CurrencyViewSet
import_location
:
location
api_end_point
:
currenc
y
api_end_point
:
currenc
ies
-
model
:
Department
viewset
:
DepartmentViewSet
import_location
:
other_core
api_end_point
:
other/department
api_end_point
:
departments
-
model
:
Specialty
viewset
:
SpecialtyViewSet
import_location
:
other_core
api_end_point
:
other/specialty
api_end_point
:
specialties
-
model
:
Semester
viewset
:
SemesterViewSet
import_location
:
other_core
api_end_point
:
other/semester
api_end_point
:
semesters
-
model
:
Offer
viewset
:
OfferViewSet
import_location
:
other_core
api_end_point
:
other/offer
api_end_point
:
offers
-
model
:
CountryTaggedItem
viewset
:
CountryTaggedItemViewSet
import_location
:
location
api_end_point
:
countriesTaggedItems
versionned
:
true
-
model
:
CountryScholarship
viewset
:
CountryScholarshipViewSet
import_location
:
location
api_end_point
:
countr
y_more/scholarship
api_end_point
:
countr
iesScholarships
versionned
:
true
-
model
:
CountryDri
viewset
:
CountryDriViewSet
import_location
:
location
api_end_point
:
countr
y_more/d
ri
api_end_point
:
countr
iesD
ri
versionned
:
true
-
model
:
University
viewset
:
UniversityViewSet
import_location
:
university
api_end_point
:
university
-
model
:
Campus
viewset
:
CampusViewSet
import_location
:
university
api_end_point
:
campus
-
model
:
CityTaggedItem
viewset
:
CityTaggedItemViewSet
import_location
:
location
api_end_point
:
citiesTaggedItems
versionned
:
true
-
model
:
null
viewset
:
MainCampusViewSet
-
model
:
UniversityTaggedItem
viewset
:
UniversityTaggedItemViewSet
import_location
:
university
api_end_point
:
main_campu
s
read_only
:
true
api_end_point
:
universitiesTaggedItem
s
versionned
:
true
-
model
:
UniversityScholarship
viewset
:
UniversityScholarshipViewSet
import_location
:
university
api_end_point
:
universit
y_more/scholarship
api_end_point
:
universit
iesScholarships
versionned
:
true
-
model
:
UniversityInfo
viewset
:
UniversityInfoViewSet
import_location
:
university
api_end_point
:
universit
y_more/i
nfo
api_end_point
:
universit
iesI
nfo
versionned
:
true
-
model
:
UniversitySemestersDates
viewset
:
UniversitySemestersDatesViewSet
import_location
:
university
api_end_point
:
universit
y_more/semesters_d
ates
api_end_point
:
universit
iesSemestersD
ates
versionned
:
true
-
model
:
UniversityDri
viewset
:
UniversityDriViewSet
import_location
:
university
api_end_point
:
universit
y_more/d
ri
api_end_point
:
universit
iesD
ri
versionned
:
true
-
model
:
null
viewset
:
UniversityModulesViewSet
import_location
:
university
api_end_point
:
universit
y_more/a
ll
api_end_point
:
universit
iesA
ll
api_attr
:
(?P<univ_id>[0-9]+)
api_name
:
university_details
-
model
:
CampusTaggedItem
viewset
:
CampusTaggedItemViewSet
import_location
:
university
api_end_point
:
campusesTaggedItems
versionned
:
true
-
model
:
null
viewset
:
MainCampusViewSet
import_location
:
university
api_end_point
:
mainCampuses
read_only
:
true
-
model
:
Recommendation
viewset
:
RecommendationViewSet
import_location
:
user
api_end_point
:
user
/recommendation
api_end_point
:
user
Recommendations
-
model
:
RecommendationList
viewset
:
RecommendationListViewSet
import_location
:
user
api_end_point
:
user
/recommendations_list
api_end_point
:
user
RecommendationLists
-
model
:
PreviousDeparture
viewset
:
PreviousDepartureViewSet
import_location
:
user
api_end_point
:
universit
y_more/previous_departure
api_end_point
:
universit
iesPreviousDepartures
-
model
:
PreviousDepartureFeedback
viewset
:
PreviousDepartureFeedbackViewSet
import_location
:
user
api_end_point
:
university_more/previous_departure_feedback
api_end_point
:
universitiesPreviousDepartureFeedback
-
model
:
UserData
viewset
:
UserDataViewSet
import_location
:
user
api_end_point
:
user/data
api_name
:
user-data-detail
-
model
:
PendingModeration
viewset
:
PendingModerationViewSet
import_location
:
my_model
api_end_point
:
pending
_m
oderation
api_end_point
:
pending
M
oderation
-
model
:
Version
viewset
:
VersionViewSet
import_location
:
my_model
api_end_point
:
version
api_end_point
:
version
s
api_attr
:
(?P<content_type_id>[0-9]+)/(?P<object_pk>[0-9A-Za-z]+)
api_name
:
versions
-l
ist
api_name
:
versions
L
ist
ignore_in_admin
:
true
-
model
:
ForTestingModeration
...
...
frontend/generate/generate_frontend_files.py
View file @
e9e8ecbe
#####
# This python file is used to generate js files for redux
import
os
from
os.path
import
join
from
django
import
template
import
re
import
yaml
############
# Need to do this first so that Django template engine is working
...
...
@@ -35,21 +37,21 @@ templates = [
'combinedReducers'
]
API_BASE
=
"
http://127.0.0.1:8000
/api/"
contexts
=
[
{
'name'
:
'universities'
,
'api_url'
:
API_BASE
+
"university/"
,
},
{
'name'
:
'countries'
,
'api_url'
:
API_BASE
+
"country/"
},
{
'name'
:
'mainCampus'
,
'api_url'
:
API_BASE
+
"main_campus/"
,
'read_only'
:
True
}
]
API_BASE
=
"/api/"
with
open
(
join
(
current_dir
,
'../../backend/generate/api_config.yml'
),
'r'
)
as
f
:
data
=
f
.
read
()
api_config
=
yaml
.
load
(
data
)
contexts
=
[]
for
api
in
api_config
:
if
"requires_testing"
in
api
and
api
[
"requires_testing"
]:
continue
name
=
api
[
'viewset'
].
split
(
'ViewSet'
)[
0
]
name
=
name
[
0
].
lower
()
+
name
[
1
:]
contexts
.
append
({
"name"
:
api
[
"api_end_point"
],
"api_end_point"
:
API_BASE
+
api
[
"api_end_point"
]
+
'/'
,
})
def
read_file
(
file
):
...
...
frontend/generate/templates/actions.tpl
View file @
e9e8ecbe
...
...
@@ -29,25 +29,25 @@ import {
//////////////////////////////////
// generic function definitions
function _FetchData(pk, api_
url
, _IsLoading, _FetchDataSuccess, _Invalidated, _HasError, pk_required=false) {
function _FetchData(pk, api_
end_point
, _IsLoading, _FetchDataSuccess, _Invalidated, _HasError, pk_required=false) {
if (pk_required
&&
pk == ""){
throw "pk shouldn't be empty when requesting a specific element";
}
return (dispatch) => {
dispatch(_IsLoading(true));
fetch(api_
url
)
let token = Cookies.get('csrftoken');
fetch(api_
end_point,
{
credentials
:
'same-origin'
,
headers
:
{
'X-CSRFToken'
:
token
}}
)
.then((response) => {
if (!response.ok) {
throw Error(response.statusText);
}
dispatch(_IsLoading(false));
return response;
})
.then((response) => response.json())
.then((obj) => {
dispatch(_Invalidated(false));
dispatch(_FetchDataSuccess(obj));
dispatch(_IsLoading(false));
})
.catch(() => dispatch(_HasError(true)));
};
...
...
@@ -55,7 +55,7 @@ function _FetchData(pk, api_url, _IsLoading, _FetchDataSuccess, _Invalidated, _H
function _ElSaveData(data, api_
url
, _IsLoading, _FetchDataSuccess, _Invalidated, _HasError) {
function _ElSaveData(data, api_
end_point
, _IsLoading, _FetchDataSuccess, _Invalidated, _HasError) {
return (dispatch) => {
let method = "POST";
let pk = "";
...
...
@@ -66,7 +66,7 @@ function _ElSaveData(data, api_url, _IsLoading, _FetchDataSuccess, _Invalidated,
dispatch(_ElIsSaving(true));
let token = Cookies.get('csrftoken');
fetch(api_
url
+pk, {
fetch(api_
end_point
+pk, {
method: method,
credentials: 'same-origin',
headers: {
...
...
@@ -81,13 +81,13 @@ function _ElSaveData(data, api_url, _IsLoading, _FetchDataSuccess, _Invalidated,
throw Error(response.statusText);
}
dispatch(_ElIsSaving(false));
return response;
})
.then((response) => response.json())
.then((_El) => {
dispatch(_ElInvalidated(false));
dispatch(_ElSaveDataSuccess(_El));
dispatch(_ElIsSaving(false));
})
.catch(() => dispatch(_ElHasError(true)));
};
...
...
@@ -131,7 +131,7 @@ export function {{obj.name}}FetchDataSuccess({{obj.name}}) {
export function {
{
obj
.
name
}
}FetchData() {
return _FetchData(
"",
"{
{
obj
.
api_
url
}
}",
"{
{
obj
.
api_
end_point
}
}",
{
{
obj
.
name
}
}IsLoading,
{
{
obj
.
name
}
}FetchDataSuccess,
{
{
obj
.
name
}
}Invalidated,
...
...
@@ -176,7 +176,7 @@ export function {{obj.name}}ElFetchDataSuccess({{obj.name}}El) {
export function {
{
obj
.
name
}
}ElFetchData(pk) {
return _FetchData(
pk,
"{
{
obj
.
api_
url
}
}",
"{
{
obj
.
api_
end_point
}
}",
{
{
obj
.
name
}
}ElIsLoading,
{
{
obj
.
name
}
}ElFetchDataSuccess,
{
{
obj
.
name
}
}ElInvalidated,
...
...
@@ -207,7 +207,7 @@ export function {{obj.name}}ElSaveDataSuccess({{obj.name}}El) {
}
export function {
{
obj
.
name
}
}ElSaveData(data) {
return _ElSaveData(data, "{
{
obj
.
api_
url
}
}", {
{
obj
.
name
}
}ElIsLoading, {
{
obj
.
name
}
}ElFetchDataSuccess, {
{
obj
.
name
}
}ElInvalidated, {
{
obj
.
name
}
}ElHasError)
return _ElSaveData(data, "{
{
obj
.
api_
end_point
}
}", {
{
obj
.
name
}
}ElIsLoading, {
{
obj
.
name
}
}ElFetchDataSuccess, {
{
obj
.
name
}
}ElInvalidated, {
{
obj
.
name
}
}ElHasError)
}
{% endif %}
...
...
frontend/generate/templates/reducers.tpl
View file @
e9e8ecbe
...
...
@@ -65,11 +65,11 @@ export function {{obj.name}}ElIsLoading(state = false, action) {
}
}
export function {
{
obj
.
name
}
}Fetched(state = {
{
{
obj
.
name
}
}: [], {
{
obj
.
name
}
}F
etchedAt: null }, action) {
export function {
{
obj
.
name
}
}Fetched(state = {
data: Object(), f
etchedAt: null }, action) {
switch (action.type) {
case {
{
obj
.
NAME
}
}_FETCH_DATA_SUCCESS:
return {
{
{
obj
.
name
}
}
: action.{
{
obj
.
name
}
},
data
: action.{
{
obj
.
name
}
},
fetchedAt: action.{
{
obj
.
name
}
}FetchedAt
}
...
...
@@ -100,11 +100,11 @@ export function {{obj.name}}ElInvalidated(state = false, action) {
}
}
export function {
{
obj
.
name
}
}ElFetched(state = {
{
{
obj
.
name
}
}El: [], {
{
obj
.
name
}
}ElF
etchedAt: null }, action) {
export function {
{
obj
.
name
}
}ElFetched(state = {
data: Object(), f
etchedAt: null }, action) {
switch (action.type) {
case {
{
obj
.
NAME
}
}_EL_FETCH_DATA_SUCCESS:
return {
{
{
obj
.
name
}
}El
: action.{
{
obj
.
name
}
}El,
data
: action.{
{
obj
.
name
}
}El,
fetchedAt: action.{
{
obj
.
name
}
}ElFetchedAt
}
...
...
@@ -128,11 +128,11 @@ export function {{obj.name}}ElIsSaving(state = false, action) {
}
}
export function {
{
obj
.
name
}
}ElSaved(state = {
{
{
obj
.
name
}
}El: [], {
{
obj
.
name
}
}ElS
avedAt: null }, action) {
export function {
{
obj
.
name
}
}ElSaved(state = {
data: Object(), s
avedAt: null }, action) {
switch (action.type) {
case {
{
obj
.
NAME
}
}_EL_SAVING_DATA_SUCCESS:
return {
{
{
obj
.
name
}
}El
: action.{
{
obj
.
name
}
}El,
data
: action.{
{
obj
.
name
}
}El,
fetchedAt: action.{
{
obj
.
name
}
}ElSavedAt
}
...
...
frontend/src/components/App.js
View file @
e9e8ecbe
...
...
@@ -17,7 +17,7 @@ import SchoolIcon from '@material-ui/icons/School';
import
{
mainListItems
,
secondaryListItems
}
from
'
./template/listItems
'
;
import
{
connect
}
from
"
react-redux
"
;
import
Loading
from
'
./other/Loading
'
;
import
MyComponent
from
'
./MyComponent
'
// import route Components here
...
...
@@ -97,10 +97,10 @@ const styles = theme => ({
myPaper
:
{
padding
:
16
},
null
:{}
null
:
{}
});
class
App
extends
React
.
Component
{
class
App
extends
My
Component
{
state
=
{
open
:
true
,
};
...
...
@@ -113,32 +113,8 @@ class App extends React.Component {
this
.
setState
({
open
:
false
});
};
componentDidMount
()
{
if
(
this
.
props
.
countries
.
fetched
.
countries
.
length
==
0
||
this
.
props
.
invalidated
)
{
this
.
props
.
fetchData
();
}
}
componentDidUpdate
()
{
// TODO ajouter expire date
if
(
this
.
props
.
countries
.
invalidated
)
{
this
.
props
.
countries
.
fetchData
();
}
}
componentWillUnmount
()
{
}
render
()
{
if
(
this
.
props
.
countries
.
hasError
)
{
return
<
p
>
Sorry
!
There
was
an
error
loading
the
items
<
/p>
;
}
if
(
this
.
props
.
countries
.
isLoading
||
this
.
props
.
countries
.
invalidated
)
{
return
<
Loading
/>
;
}
myRender
()
{
const
{
classes
}
=
this
.
props
;
return
(
...
...
@@ -204,7 +180,9 @@ const mapStateToProps = (state) => {
const
mapDispatchToProps
=
(
dispatch
)
=>
{
return
{
fetchData
:
()
=>
dispatch
(
countriesFetchData
()),
fetchData
:
{
countries
:
()
=>
dispatch
(
countriesFetchData
())
}
};
};
...
...
frontend/src/components/MyComponent.js
View file @
e9e8ecbe
import
React
,
{
Component
}
from
'
react
'
;
import
Loading
from
'
./other/Loading
'
;
class
MyComponent
extends
Component
{
checkProps
(
val
)
{
for
(
let
el
in
this
.
props
)
{
let
prop
=
this
.
props
[
el
];
if
(
val
in
prop
&&
prop
[
val
])
{
if
(
prop
&&
val
in
prop
&&
prop
[
val
])
{
return
true
;
}
}
return
false
;
}
checkPropsHasError
()
{
return
this
.
checkProps
(
'
hasError
'
);
}
...
...
@@ -18,6 +20,48 @@ class MyComponent extends Component {
checkPropsIsLoading
()
{
return
this
.
checkProps
(
'
isLoading
'
);
}
checkPropsInvalidated
()
{
return
this
.
checkProps
(
'
invalidated
'
);
}
loadPropsIfNeeded
(){
for
(
let
prop_key
in
this
.
props
)
{
let
prop
=
this
.
props
[
prop_key
];
if
(
prop
&&
'
fetched
'
in
prop
){
if
(
(
!
prop
.
fetched
.
fetchedAt
)
||
prop
.
invalidated
){
if
(
!
prop
.
isLoading
){
this
.
props
.
fetchData
[
prop_key
]();
}
}
}
}
}
componentDidMount
()
{
this
.
loadPropsIfNeeded
();
this
.
myComponentDidMount
();
}
myComponentDidMount
(){};
componentDidUpdate
()
{
// TODO ajouter expire date
this
.
loadPropsIfNeeded
();
this
.
myComponentDidMount
();
}
myComponentDidMount
(){};
render
()
{
if
(
this
.
checkPropsHasError
())
{
return
<
p
>
Sorry
!
There
was
an
error
loading
the
items
<
/p>
;
}
if
(
this
.
checkPropsIsLoading
()
||
this
.
checkPropsInvalidated
())
{
return
<
Loading
/>
;
}
return
this
.
myRender
();
}
}
...
...
frontend/src/components/map/UnivMakers.js
View file @
e9e8ecbe
...
...
@@ -7,8 +7,8 @@ import { Map, TileLayer, Marker, Popup, LayersControl, FeatureGroup, Circle, Lay
import
{
universitiesFetchData
,
universitiesInvalidated
,
mainCampusFetchData
,
mainCampusInvalidated
mainCampus
es
FetchData
,
mainCampus
es
Invalidated
}
from
'
../../generated/actions
'
;
...
...
@@ -17,12 +17,12 @@ class UnivMarkers extends Component {
render
()
{
let
universities
=
this
.
props
.
universities
;
let
mainCampus
=
this
.
props
.
mainCampus
;
let
universities
=
this
.
props
.
universities
.
fetched
.
data
;
let
mainCampus
es
=
this
.
props
.
mainCampuses
.
fetched
.
data
;
let
selected_main_campus
=
[];
for
(
let
main_campus_pk
in
mainCampus
)
{
let
campus
=
mainCampus
[
main_campus_pk
]
for
(
let
main_campus_pk
in
mainCampus
es
)
{
let
campus
=
mainCampus
es
[
main_campus_pk
]
let
univ
=
universities
[
campus
.
university
]
if
(
univ
&&
campus
)
{
selected_main_campus
.
push
({
...
...
@@ -50,17 +50,8 @@ class UnivMarkers extends Component {
const
mapStateToProps
=
(
state
)
=>
{
return
{
universities
:
state
.
universities
.
fetched
.
universities
,
universitiesFetchedAt
:
state
.
universities
.
fetched
.
fetchedAt
,
universitiesHasError
:
state
.
universities
.
hasError
,
universitiesIsLoading
:
state
.
universities
.
isLoading
,
universitiesInvalidated
:
state
.
universities
.
invalidated
,
mainCampus
:
state
.
mainCampus
.
fetched
.
mainCampus
,
mainCampusFetchedAt
:
state
.
mainCampus
.
fetched
.
fetchedAt
,
mainCampusHasError
:
state
.
mainCampus
.
hasError
,
mainCampusIsLoading
:
state
.
mainCampus
.
isLoading
,
mainCampusInvalidated
:
state
.
mainCampus
.
invalidated
,
universities
:
state
.
universities
,
mainCampuses
:
state
.
mainCampuses
};
};
...
...
frontend/src/components/map/UnivMap.js
View file @
e9e8ecbe
import
React
from
'
react
'
;
import
MyComponent
from
'
../MyComponent
'
import
{
connect
}
from
"
react-redux
"
;
import
Loading
from
'
../other/Loading
'
;
import
{
Map
,
TileLayer
,
Marker
,
Popup
,
LayersControl
,
FeatureGroup
,
Circle
,
LayerGroup
}
from
'
react-leaflet
'
;
// import MarkerClusterGroup from 'react-leaflet-markercluster';
import
{
Map
,
TileLayer
,
LayersControl
,
LayerGroup
}
from
'
react-leaflet
'
;
import
{
universitiesFetchData
,
mainCampusFetchData
,
mainCampus
es
FetchData
,
}
from
'
../../generated/actions
'
;
import
UnivMarkers
from
'
./UnivMakers
'
;
...
...
@@ -20,30 +19,6 @@ class UnivMap extends MyComponent {
};
}
componentDidMount
()
{