diff --git a/server/application.py b/server/application.py
index d1eae870..6f5fea24 100644
--- a/server/application.py
+++ b/server/application.py
@@ -28,6 +28,7 @@
Configuration.SERVER_TYPE = "ce"
Configuration.USER_SELF_REGISTRATION = False
+
application = create_app(
[
"DOCS_URL",
@@ -37,6 +38,7 @@
"GLOBAL_ADMIN",
"GLOBAL_READ",
"GLOBAL_WRITE",
+ "ENABLE_SUPERADMIN_ASSIGNMENT",
]
)
register_stats(application)
diff --git a/server/mergin/auth/api.yaml b/server/mergin/auth/api.yaml
index 337dc862..f89e110d 100644
--- a/server/mergin/auth/api.yaml
+++ b/server/mergin/auth/api.yaml
@@ -171,7 +171,7 @@ paths:
count:
type: integer
example: 10
- users:
+ items:
type: array
items:
$ref: "#/components/schemas/User"
@@ -670,6 +670,11 @@ components:
type: string
format: date-time
example: 2023-07-30T08:47:58Z
+ registration_date:
+ nullable: true
+ type: string
+ format: date-time
+ example: 2023-07-30T08:47:58Z
profile:
$ref: "#/components/schemas/UserProfile"
PaginatedUsers:
@@ -839,4 +844,4 @@ components:
- editor
- reader
- guest
- example: reader
\ No newline at end of file
+ example: reader
diff --git a/server/mergin/auth/controller.py b/server/mergin/auth/controller.py
index 36932def..bccb98ba 100644
--- a/server/mergin/auth/controller.py
+++ b/server/mergin/auth/controller.py
@@ -6,7 +6,7 @@
import pytz
from datetime import datetime, timedelta
from connexion import NoContent
-from sqlalchemy import func, desc, asc
+from sqlalchemy import func, desc, asc, or_
from sqlalchemy.sql.operators import is_
from flask import request, current_app, jsonify, abort, render_template
from flask_login import login_user, logout_user, current_user
@@ -23,7 +23,7 @@
user_account_closed,
)
from .bearer import encode_token
-from .models import User, LoginHistory
+from .models import User, LoginHistory, UserProfile
from .schemas import UserSchema, UserSearchSchema, UserProfileSchema, UserInfoSchema
from .forms import (
LoginForm,
@@ -408,11 +408,17 @@ def update_user(username): # pylint: disable=W0613,W0612
form = UserForm.from_json(request.json)
if not form.validate_on_submit():
return jsonify(form.errors), 400
+ if request.json.get("is_admin") is not None and not current_app.config.get(
+ "ENABLE_SUPERADMIN_ASSIGNMENT"
+ ):
+ abort(400, "Unable to assign super admin role")
user = User.query.filter_by(username=username).first_or_404("User not found")
form.update_obj(user)
+
# remove inactive since flag for ban or re-activation
user.inactive_since = None
+
db.session.add(user)
db.session.commit()
return jsonify(UserSchema().dump(user))
@@ -449,13 +455,17 @@ def get_paginated_users(
:rtype: Dict[str: List[User], str: Integer]
"""
- users = User.query.filter(
+ users = User.query.join(UserProfile).filter(
is_(User.username.ilike("deleted_%"), False) | is_(User.active, True)
)
if like:
- attr = User.email if "@" in like else User.username
- users = users.filter(attr.ilike(f"%{like}%"))
+ users = users.filter(
+ User.username.ilike(f"%{like}%")
+ | User.email.ilike(f"%{like}%")
+ | UserProfile.first_name.ilike(f"%{like}%")
+ | UserProfile.last_name.ilike(f"%{like}%")
+ )
if descending and order_by:
users = users.order_by(desc(User.__table__.c[order_by]))
@@ -467,7 +477,7 @@ def get_paginated_users(
result_users = UserSchema(many=True).dump(result)
- data = {"users": result_users, "total": total}
+ data = {"items": result_users, "count": total}
return data, 200
diff --git a/server/mergin/auth/schemas.py b/server/mergin/auth/schemas.py
index bcebca5c..10475b2c 100644
--- a/server/mergin/auth/schemas.py
+++ b/server/mergin/auth/schemas.py
@@ -71,6 +71,7 @@ class Meta:
"verified_email",
"profile",
"scheduled_removal",
+ "registration_date",
)
load_instance = True
diff --git a/server/mergin/config.py b/server/mergin/config.py
index 177063b5..fdb8108b 100644
--- a/server/mergin/config.py
+++ b/server/mergin/config.py
@@ -95,6 +95,10 @@ class Configuration(object):
# build hash number
BUILD_HASH = config("BUILD_HASH", default="")
+ # Allow changing access to admin panel
+ ENABLE_SUPERADMIN_ASSIGNMENT = config(
+ "ENABLE_SUPERADMIN_ASSIGNMENT", default=True, cast=bool
+ )
# backend version
VERSION = config("VERSION", default=get_version())
SERVER_TYPE = config("SERVER_TYPE", default="ce")
diff --git a/server/mergin/sync/private_api.yaml b/server/mergin/sync/private_api.yaml
index 4ab4b9b2..4160ed07 100644
--- a/server/mergin/sync/private_api.yaml
+++ b/server/mergin/sync/private_api.yaml
@@ -183,20 +183,13 @@ paths:
- $ref: "#/components/parameters/Page"
- $ref: "#/components/parameters/PerPage"
- $ref: "#/components/parameters/OrderParams"
- - name: name
+ - name: like
in: query
- description: Filter projects by name with ilike pattern
+ description: Filter projects by name or workspace name with ilike pattern
required: false
schema:
type: string
example: survey
- - name: workspace
- in: query
- description: Filter projects by workspace with ilike pattern
- required: false
- schema:
- type: string
- example: my-workspace
responses:
"200":
description: List of projects
@@ -209,7 +202,7 @@ paths:
type: integer
description: Total number of all projects
example: 20
- projects:
+ items:
type: array
items:
$ref: "#/components/schemas/ProjectListItem"
@@ -292,7 +285,7 @@ paths:
id:
type: string
format: uuid
- example: 'd4ecda97-0595-40af-892c-e7522de70bd2'
+ example: "d4ecda97-0595-40af-892c-e7522de70bd2"
name:
type: string
example: survey
@@ -460,7 +453,7 @@ components:
- detail
UsersLimitHit:
allOf:
- - $ref: '#/components/schemas/CustomError'
+ - $ref: "#/components/schemas/CustomError"
type: object
properties:
rejected_emails:
@@ -473,7 +466,7 @@ components:
example:
code: UsersLimitHit
detail: Maximum number of people in this workspace is reached. Please upgrade your subscription to add more people (UsersLimitHit)
- rejected_emails: [ rejected@example.com ]
+ rejected_emails: [rejected@example.com]
users_quota: 6
ProjectAccessRequestList:
type: array
@@ -488,7 +481,7 @@ components:
project_id:
type: string
format: uuid
- example: 'd4ecda97-0595-40af-892c-e7522de70bd2'
+ example: "d4ecda97-0595-40af-892c-e7522de70bd2"
project_name:
type: string
example: survey
@@ -619,25 +612,25 @@ components:
nullable: false
items:
type: string
- example: [ john.doe ]
+ example: [john.doe]
writersnames:
type: array
nullable: false
items:
type: string
- example: [ john.doe ]
+ example: [john.doe]
editorsnames:
type: array
nullable: false
items:
type: string
- example: [ john.doe ]
+ example: [john.doe]
readersnames:
nullable: false
type: array
items:
type: string
- example: [ john.doe ]
+ example: [john.doe]
public:
type: boolean
example: true
diff --git a/server/mergin/sync/private_api_controller.py b/server/mergin/sync/private_api_controller.py
index c6122166..57da6492 100644
--- a/server/mergin/sync/private_api_controller.py
+++ b/server/mergin/sync/private_api_controller.py
@@ -185,10 +185,8 @@ def list_namespace_project_access_requests(
@auth_required(permissions=["admin"])
-def list_projects(
- page, per_page, order_params=None, name=None, workspace=None
-): # noqa: E501
- projects = current_app.ws_handler.projects_query(name, workspace)
+def list_projects(page, per_page, order_params=None, like=None): # noqa: E501
+ projects = current_app.ws_handler.projects_query(like)
# do not fetch from db what is not needed
projects = projects.options(
defer(Project.storage_params),
@@ -211,7 +209,7 @@ def list_projects(
result = projects.paginate(page, per_page).items
total = projects.paginate(page, per_page).total
data = AdminProjectSchema(many=True).dump(result)
- data = {"projects": data, "count": total}
+ data = {"items": data, "count": total}
return data, 200
diff --git a/server/mergin/sync/schemas.py b/server/mergin/sync/schemas.py
index 827391a9..081b2ab7 100644
--- a/server/mergin/sync/schemas.py
+++ b/server/mergin/sync/schemas.py
@@ -293,7 +293,8 @@ class Meta:
class AdminProjectSchema(ma.SQLAlchemyAutoSchema):
id = fields.UUID(attribute="Project.id")
name = fields.Str(attribute="Project.name")
- namespace = fields.Method("_workspace_name")
+ workspace = fields.Method("_workspace_name")
+ workspace_id = fields.Int(attribute="Project.workspace_id")
version = fields.Function(
lambda obj: ProjectVersion.to_v_name(obj.Project.latest_version)
)
diff --git a/server/mergin/sync/workspace.py b/server/mergin/sync/workspace.py
index 7781f7be..1397a85d 100644
--- a/server/mergin/sync/workspace.py
+++ b/server/mergin/sync/workspace.py
@@ -269,16 +269,17 @@ def monthly_contributors_count():
.count()
)
- def projects_query(self, name=None, workspace=None):
+ def projects_query(self, like: str = None):
ws = self.factory_method()
query = db.session.query(
- Project, literal(ws.name).label("workspace_name")
+ Project,
+ literal(ws.name).label("workspace_name"),
).filter(Project.storage_params.isnot(None))
- if name:
- query = query.filter(Project.name.ilike(f"%{name}%"))
- if workspace:
- query = query.filter(literal(ws.name).ilike(f"%{workspace}%"))
+ if like:
+ query = query.filter(
+ Project.name.ilike(f"%{like}%") | literal(ws.name).ilike(f"%{like}%")
+ )
return query
@staticmethod
diff --git a/server/mergin/tests/test_auth.py b/server/mergin/tests/test_auth.py
index c4a12103..43d61d7d 100644
--- a/server/mergin/tests/test_auth.py
+++ b/server/mergin/tests/test_auth.py
@@ -412,6 +412,25 @@ def test_api_user_profile(client):
def test_update_user(client):
login_as_admin(client)
user = User.query.filter_by(username="mergin").first()
+ data = {"active": True, "is_admin": True}
+ resp = client.patch(
+ url_for("/.mergin_auth_controller_update_user", username=user.username),
+ data=json.dumps(data),
+ headers=json_headers,
+ )
+ assert resp.status_code == 200
+ assert user.active
+ assert user.is_admin
+
+ client.application.config["ENABLE_SUPERADMIN_ASSIGNMENT"] = False
+ data = {"active": False, "is_admin": False}
+ resp = client.patch(
+ url_for("/.mergin_auth_controller_update_user", username=user.username),
+ data=json.dumps(data),
+ headers=json_headers,
+ )
+ assert resp.status_code == 400
+ assert user.active
data = {"active": False}
resp = client.patch(
url_for("/.mergin_auth_controller_update_user", username=user.username),
@@ -421,6 +440,7 @@ def test_update_user(client):
assert resp.status_code == 200
assert not user.active
+ client.application.config["ENABLE_SUPERADMIN_ASSIGNMENT"] = True
user.is_admin = False
db.session.add(user)
db.session.commit()
@@ -694,27 +714,27 @@ def test_paginate_users(client):
url = "/app/admin/users?page=1&per_page=10"
# get 5 users (default + 5 new added - 1 deleted & inactive)
resp = client.get(url)
- list_of_usernames = [user["username"] for user in resp.json["users"]]
- assert resp.json["total"] == 5
- assert resp.json["users"][0]["username"] == "mergin"
+ list_of_usernames = [user["username"] for user in resp.json["items"]]
+ assert resp.json["count"] == 5
+ assert resp.json["items"][0]["username"] == "mergin"
assert user_inactive.username in list_of_usernames
assert deleted_active.username in list_of_usernames
assert deleted_inactive.username not in list_of_usernames
# order by username
resp = client.get(url + "&order_by=username")
- assert resp.json["total"] == 5
- assert resp.json["users"][0]["username"] == "alice"
+ assert resp.json["count"] == 5
+ assert resp.json["items"][0]["username"] == "alice"
# exact match with username
resp = client.get(url + "&like=bob")
- assert resp.json["total"] == 1
- assert resp.json["users"][0]["username"] == "bob"
+ assert resp.json["count"] == 1
+ assert resp.json["items"][0]["username"] == "bob"
# ilike search with email
resp = client.get(url + "&like=@mergin.com")
- assert resp.json["total"] == 5
+ assert resp.json["count"] == 5
# exact search by email
resp = client.get(url + "&like=alice@mergin.com")
- assert resp.json["total"] == 1
- assert resp.json["users"][0]["username"] == "alice"
+ assert resp.json["count"] == 1
+ assert resp.json["items"][0]["username"] == "alice"
# invalid paging
assert client.get("/app/admin/users?page=2&per_page=10").status_code == 404
diff --git a/server/mergin/tests/test_private_project_api.py b/server/mergin/tests/test_private_project_api.py
index 9bd66b7b..361fe59e 100644
--- a/server/mergin/tests/test_private_project_api.py
+++ b/server/mergin/tests/test_private_project_api.py
@@ -412,7 +412,7 @@ def test_restore_project(client, diff_project):
# tests listing
resp = client.get("/app/admin/projects?page=1&per_page=10")
assert resp.json["count"] == 1
- assert resp.json["projects"][0]["removed_at"]
+ assert resp.json["items"][0]["removed_at"]
diff_project.workspace.active = True
db.session.commit()
@@ -432,7 +432,7 @@ def test_admin_project_list(client):
assert resp.status_code == 200
assert resp.json.get("count") == 1
# mark as inactive
- p = Project.query.get(resp.json["projects"][0]["id"])
+ p = Project.query.get(resp.json["items"][0]["id"])
p.removed_at = datetime.datetime.utcnow()
p.removed_by = user.id
db.session.commit()
@@ -445,7 +445,7 @@ def test_admin_project_list(client):
resp = client.get("/app/admin/projects?page=1&per_page=10&order_params=name ASC")
assert resp.status_code == 200
assert resp.json.get("count") == 15
- projects = resp.json.get("projects")
+ projects = resp.json.get("items")
assert len(projects) == 10
assert "foo5" in projects[9]["name"]
assert "v0" == projects[9]["version"]
@@ -454,30 +454,30 @@ def test_admin_project_list(client):
"/app/admin/projects?page=1&per_page=10&order_params=removed_at ASC"
)
assert resp.status_code == 200
- assert resp.json["projects"][0]["name"] == p.name
+ assert resp.json["items"][0]["name"] == p.name
resp = client.get(
"/app/admin/projects?page=1&per_page=15&order_params=created DESC"
)
- assert resp.json["projects"][0]["name"] == "foo13"
+ assert resp.json["items"][0]["name"] == "foo13"
- resp = client.get("/app/admin/projects?page=1&per_page=15&name=12")
- assert len(resp.json["projects"]) == 1
- assert resp.json["projects"][0]["name"] == "foo12"
+ resp = client.get("/app/admin/projects?page=1&per_page=15&like=12")
+ assert len(resp.json["items"]) == 1
+ assert resp.json["items"][0]["name"] == "foo12"
- resp = client.get("/app/admin/projects?page=1&per_page=15&name=foo")
- assert len(resp.json["projects"]) == 14
+ resp = client.get("/app/admin/projects?page=1&per_page=15&like=foo")
+ assert len(resp.json["items"]) == 14
- resp = client.get("/app/admin/projects?page=1&per_page=15&workspace=invalid")
- assert len(resp.json["projects"]) == 0
+ resp = client.get("/app/admin/projects?page=1&per_page=15&like=invalid")
+ assert len(resp.json["items"]) == 0
- resp = client.get("/app/admin/projects?page=1&per_page=15&workspace=mergin")
- assert len(resp.json["projects"]) == 15
+ resp = client.get("/app/admin/projects?page=1&per_page=15&like=mergin")
+ assert len(resp.json["items"]) == 15
# delete project permanently
p.delete()
- resp = client.get("/app/admin/projects?page=1&per_page=15&workspace=mergin")
- assert len(resp.json["projects"]) == 14
+ resp = client.get("/app/admin/projects?page=1&per_page=15&like=mergin")
+ assert len(resp.json["items"]) == 14
def test_get_project_access(client):
diff --git a/web-app/.eslintrc.cjs b/web-app/.eslintrc.cjs
index c3e9d504..9689d42e 100644
--- a/web-app/.eslintrc.cjs
+++ b/web-app/.eslintrc.cjs
@@ -1,15 +1,12 @@
module.exports = {
root: true,
env: {
- es2021: true,
- browser: true
+ es2022: true,
+ browser: true,
+ node: true
},
- extends: [
- 'plugin:vue/essential',
- '@vue/standard',
- 'plugin:prettier/recommended'
- ],
- plugins: ['@typescript-eslint'],
+ extends: ['plugin:vue/vue3-essential', 'plugin:prettier/recommended'],
+ plugins: ['@typescript-eslint', 'eslint-plugin-import'],
rules: {
'prettier/prettier': 'warn',
'@typescript-eslint/no-unused-vars': [
diff --git a/web-app/README.md b/web-app/README.md
index 053a0e40..76f3d62f 100644
--- a/web-app/README.md
+++ b/web-app/README.md
@@ -11,18 +11,17 @@ Monorepo for mergin frontend stuff:
* monorepo consists of root directory with own package.json and individual workspaces in `packages` directory
* root package.json defines common devDependencies and it cannot hold any non-development dependency
* individual workspace package.json defines dependencies used in that particular workspace package
-* frontend applications (e.g. app) is also a workspace package (@mergin/app) held in directory [./packages/app](./packages/app).
+* frontend application (e.g. app) is also a workspace package (@mergin/app) held in directory [./packages/app](./packages/app).
Application constist of several packages in `packages` directory:
- @mergin/lib - Shared library for common features
-- @mergin/lib-vue2 - Shared library for common features with vuetify and vue 2.7
- @mergin/admin-lib - Shared library for admin
- @mergin/app - Web appliacation"
- @mergin/admin-app - Web application for administration
Library packages with *-lib* name are containing shared code for *-app* applications.
-Web application *@mergin/app* is using shared library *@mergin/lib*. Web application for administration *admin-app* is using shared libraries with vue 2.7 *@mergin/admin-lib* and *@mergin/lib-vue2*.
+Web application *@mergin/app* is using shared library *@mergin/lib*. Web application for administration *admin-app* is using shared library *@mergin/admin-lib*.
For details about development follow instructions in [development guide](../development.md).
\ No newline at end of file
diff --git a/web-app/package.json b/web-app/package.json
index 50771c7c..869ef85b 100755
--- a/web-app/package.json
+++ b/web-app/package.json
@@ -6,7 +6,6 @@
"packages/admin-lib",
"packages/app",
"packages/admin-app",
- "packages/lib-vue2",
"packages/*"
],
"scripts": {
@@ -25,58 +24,50 @@
"build:dev": "yarn workspace @mergin/app build:dev",
"build:admin": "yarn workspace @mergin/admin-app build",
"build:admin:dev": "yarn workspace @mergin/admin-app build:dev",
- "clean:libs": "yarn workspace @mergin/lib clean && yarn workspace @mergin/admin-lib clean && yarn workspace @mergin/lib-vue2 clean",
+ "clean:libs": "yarn workspace @mergin/lib clean && yarn workspace @mergin/admin-lib clean",
"clean:libs:noadmin": "yarn workspace @mergin/lib clean",
- "i18n:report": "yarn workspace @mergin/app 18n:report",
- "link:dependencies": "yarn link:register && yarn link @mergin/lib && yarn link @mergin/admin-lib && yarn link @mergin/lib-vue2",
+ "link:dependencies": "yarn link:register && yarn link @mergin/lib && yarn link @mergin/admin-lib",
"link:register": "yarn workspaces run link:register",
"link:unregister": "yarn workspaces run link:unregister",
"types:libs": "yarn workspaces run build:types",
"types:lib": "yarn workspace @mergin/lib build:types",
- "types:lib-vue2": "yarn workspace @mergin/lib-vue2 build:types",
"types:admin-lib": "yarn workspace @mergin/admin-lib build:types",
"watch:lib": "yarn workspace @mergin/lib build:lib:watch",
- "watch:lib-vue2": "yarn workspace @mergin/lib-vue2 build:lib:watch",
"watch:lib:types": "yarn workspace @mergin/lib build:types:watch",
- "watch:lib-vue2:types": "yarn workspace @mergin/lib-vue2 build:types:watch",
"watch:admin-lib": "yarn workspace @mergin/admin-lib build:lib:watch",
"watch:admin-lib:types": "yarn workspace @mergin/admin-lib build:types:watch",
"lint:all": "yarn workspaces run lint",
"lint:no-legacy": "yarn workspace @mergin/lib lint && yarn workspace @mergin/app lint"
},
"devDependencies": {
- "@babel/core": "^7.17.9",
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
"@esbuild-plugins/node-modules-polyfill": "^0.2.2",
- "@typescript-eslint/eslint-plugin": "^5.61.0",
- "@typescript-eslint/parser": "^5.61.0",
- "@vitejs/plugin-vue": "^4.6.2",
- "@vitejs/plugin-vue2": "^2.2.0",
- "@vue/eslint-config-standard": "^8.0.1",
- "@vue/eslint-config-typescript": "^11.0.2",
+ "@typescript-eslint/eslint-plugin": "^8.11.0",
+ "@typescript-eslint/parser": "^8.11.0",
+ "@vitejs/plugin-vue": "^5.1.4",
+ "@vue/eslint-config-typescript": "^13.0.0",
"agent-base": "^6.0.2",
"autoprefixer": "^10.4.14",
"concurrently": "^8.0.1",
- "eslint": "^8.37.0",
+ "eslint": "^8.57.1",
"eslint-config-prettier": "^8.8.0",
- "eslint-plugin-import": "^2.27.5",
+ "eslint-plugin-import": "^2.31.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-promise": "^6.1.1",
- "eslint-plugin-vue": "^9.10.0",
+ "eslint-plugin-vue": "^9.29.1",
"npm-run-all": "^4.1.5",
- "postcss": "^8.4.21",
+ "postcss": "^8.4.47",
"prettier": "2.6.0",
"purgecss": "^5.0.0",
"rimraf": "^3.0.2",
- "rollup-plugin-copy": "^3.4.0",
+ "sass": "^1.69.5",
"tsc-alias": "^1.8.6",
- "typescript": "^5.0.4",
- "unplugin-vue-components": "^0.25.1",
- "vite": "^4.5.3",
- "vite-plugin-static-copy": "^0.17.0",
- "vite-plugin-vuetify": "^1.0.2",
- "vue-tsc": "^1.6.5"
+ "typescript": "^5.6.3",
+ "unplugin-vue-components": "^0.27.1",
+ "vite": "^5.4.10",
+ "vite-plugin-static-copy": "^2.0.0",
+ "vue-tsc": "^2.1.6"
},
"engines": {
"node": ">=18"
diff --git a/web-app/packages/admin-app/.eslintrc.cjs b/web-app/packages/admin-app/.eslintrc.cjs
index 51dfd9e4..9a294e26 100644
--- a/web-app/packages/admin-app/.eslintrc.cjs
+++ b/web-app/packages/admin-app/.eslintrc.cjs
@@ -1,11 +1,9 @@
module.exports = {
- env: {
- node: true
- },
extends: [
'plugin:vue/essential',
'eslint:recommended',
- '@vue/typescript/recommended'
+ '@vue/typescript/recommended',
+ '../../.eslintrc.cjs'
],
parser: 'vue-eslint-parser',
parserOptions: {
@@ -16,6 +14,9 @@ module.exports = {
plugins: ['@typescript-eslint'],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
- 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
+ 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
+ // Vue 3 opt https://v3-migration.vuejs.org/breaking-changes/key-attribute.html#with-template-v-for
+ 'vue/no-v-for-template-key-on-child': 'error',
+ 'vue/no-v-for-template-key': 'off',
}
}
diff --git a/web-app/packages/admin-app/components.d.ts b/web-app/packages/admin-app/components.d.ts
index 277cd1f0..6bcacfd1 100644
--- a/web-app/packages/admin-app/components.d.ts
+++ b/web-app/packages/admin-app/components.d.ts
@@ -1,12 +1,13 @@
/* eslint-disable */
-/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {}
+/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
+ PDivider: typeof import('primevue/divider')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
VApp: typeof import('vuetify/lib')['VApp']
diff --git a/web-app/packages/admin-app/index.html b/web-app/packages/admin-app/index.html
index e4efe3b2..afdb9b39 100644
--- a/web-app/packages/admin-app/index.html
+++ b/web-app/packages/admin-app/index.html
@@ -11,7 +11,7 @@
-
Mergin Maps
+ Mergin Maps Admin Panel