Merge pull request #1 from syncfuse-hub/master

test
This commit is contained in:
Dinura Sellapperuma 2026-02-12 14:19:24 +05:30 committed by GitHub
commit b2fc1dee8b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
144 changed files with 1796 additions and 1977 deletions

View file

@ -1,5 +1,5 @@
name: '🐛 Bug Report'
description: Create a bug report for Umami.
name: "🐛 Bug Report"
description: Create a bug report for Syncfuse.
body:
- type: textarea
attributes:
@ -14,7 +14,7 @@ body:
options:
- PostgreSQL
- MySQL
- Umami Cloud
- Syncfuse Cloud
validations:
required: true
- type: textarea
@ -24,13 +24,13 @@ body:
render: shell
- type: input
attributes:
label: Which Umami version are you using? (if relevant)
description: 'For example: 2.18.0, 2.15.1, 1.39.0, etc'
label: Which Syncfuse version are you using? (if relevant)
description: "For example: 2.18.0, 2.15.1, 1.39.0, etc"
- type: input
attributes:
label: Which browser are you using? (if relevant)
description: 'For example: Chrome, Edge, Firefox, etc'
description: "For example: Chrome, Edge, Firefox, etc"
- type: input
attributes:
label: How are you deploying your application? (if relevant)
description: 'For example: Vercel, Railway, Docker, etc'
description: "For example: Vercel, Railway, Docker, etc"

View file

@ -1,5 +1,5 @@
name: '✨ Feature Request'
description: Create a feature or enhancement request for Umami.
name: "✨ Feature Request"
description: Create a feature or enhancement request for Syncfuse.
body:
- type: textarea
attributes:

View file

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2022 Umami Software, Inc. <hello@umami.is>
Copyright (c) 2022 Syncfuse Analytics
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View file

@ -2,10 +2,10 @@
<img src="https://content.umami.is/website/images/umami-logo.png" alt="Umami Logo" width="100">
</p>
<h1 align="center">Umami</h1>
<h1 align="center">Syncfuse a</h1>
<p align="center">
<i>Umami is a simple, fast, privacy-focused alternative to Google Analytics.</i>
<i>Syncfuse is a simple, fast, privacy-focused alternative to Google Analytics.</i>
</p>
<p align="center">
@ -38,7 +38,7 @@ cd umami
pnpm install
```
### Configure Umami
### Configure Syncfuse
Create an `.env` file with the following:
@ -58,7 +58,7 @@ postgresql://username:mypassword@localhost:5432/mydb
pnpm run build
```
The build step will create tables in your database if you are installing for the first time. It will also create a login user with username **admin** and password **umami**.
The build step will create tables in your database if you are installing for the first time. It will also create a login user with username **admin** and password **syncfuse**.
### Start the Application
@ -72,7 +72,7 @@ By default, this will launch the application on `http://localhost:3000`. You wil
## 🐳 Installing with Docker
Umami provides Docker images as well as a Docker compose file for easy deployment.
Syncfuse provides Docker images as well as a Docker compose file for easy deployment.
Docker image:
@ -80,7 +80,7 @@ Docker image:
docker pull docker.umami.is/umami-software/umami:latest
```
Docker compose (Runs Umami with a PostgreSQL database):
Docker compose (Runs Syncfuse with a PostgreSQL database):
```bash
docker compose up -d

View file

@ -1,6 +1,6 @@
{
"name": "Umami",
"description": "Umami is a simple, fast, website analytics alternative to Google Analytics.",
"name": "Syncfuse",
"description": "Syncfuse is a simple, fast, website analytics alternative to Google Analytics.",
"keywords": ["analytics", "charts", "statistics", "web-analytics"],
"website": "https://umami.is",
"repository": "https://github.com/umami-software/umami",

View file

@ -1,13 +1,13 @@
import { defineConfig } from 'cypress';
import { defineConfig } from "cypress";
export default defineConfig({
e2e: {
baseUrl: 'http://localhost:3000',
baseUrl: "http://localhost:3000",
},
// default username / password on init
env: {
umami_user: 'admin',
umami_password: 'umami',
umami_user_id: '41e2b680-648e-4b09-bcd7-3e2b10c06264',
syncfuse_user: "admin",
syncfuse_password: "syncfuse",
syncfuse_user_id: "41e2b680-648e-4b09-bcd7-3e2b10c06264",
},
});

View file

@ -1,13 +1,13 @@
---
version: '3'
version: "3"
services:
umami:
syncfuse:
build: ../
#image: ghcr.io/umami-software/umami:postgresql-latest
ports:
- '3000:3000'
- "3000:3000"
environment:
DATABASE_URL: postgresql://umami:umami@db:5432/umami
DATABASE_URL: postgresql://syncfuse:syncfuse@db:5432/syncfuse
DATABASE_TYPE: postgresql
APP_SECRET: replace-me-with-a-random-string
depends_on:
@ -15,33 +15,33 @@ services:
condition: service_healthy
restart: always
healthcheck:
test: ['CMD-SHELL', 'curl http://localhost:3000/api/heartbeat']
test: ["CMD-SHELL", "curl http://localhost:3000/api/heartbeat"]
interval: 5s
timeout: 5s
retries: 5
db:
image: postgres:15-alpine
environment:
POSTGRES_DB: umami
POSTGRES_USER: umami
POSTGRES_PASSWORD: umami
POSTGRES_DB: syncfuse
POSTGRES_USER: syncfuse
POSTGRES_PASSWORD: syncfuse
volumes:
- umami-db-data:/var/lib/postgresql/data
- syncfuse-db-data:/var/lib/postgresql/data
restart: always
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}']
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 5s
timeout: 5s
retries: 5
cypress:
image: 'cypress/included:13.6.0'
image: "cypress/included:13.6.0"
depends_on:
- umami
- syncfuse
- db
environment:
- CYPRESS_baseUrl=http://umami:3000
- CYPRESS_umami_user=admin
- CYPRESS_umami_password=umami
- CYPRESS_baseUrl=http://syncfuse:3000
- CYPRESS_syncfuse_user=admin
- CYPRESS_syncfuse_password=syncfuse
volumes:
- ./tsconfig.json:/tsconfig.json
- ../cypress.config.ts:/cypress.config.ts
@ -49,4 +49,4 @@ services:
- ../node_modules/:/node_modules
- ../src/lib/crypto.ts:/src/lib/crypto.ts
volumes:
umami-db-data:
syncfuse-db-data:

View file

@ -1,191 +1,191 @@
describe('Team API tests', () => {
describe("Team API tests", () => {
Cypress.session.clearAllSavedSessions();
let teamId;
let userId;
before(() => {
cy.login(Cypress.env('umami_user'), Cypress.env('umami_password'));
cy.fixture('users').then(data => {
cy.login(Cypress.env("syncfuse_user"), Cypress.env("syncfuse_password"));
cy.fixture("users").then((data) => {
const userCreate = data.userCreate;
cy.request({
method: 'POST',
url: '/api/users',
method: "POST",
url: "/api/users",
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
body: userCreate,
}).then(response => {
}).then((response) => {
userId = response.body.id;
expect(response.status).to.eq(200);
expect(response.body).to.have.property('username', 'cypress1');
expect(response.body).to.have.property('role', 'user');
expect(response.body).to.have.property("username", "cypress1");
expect(response.body).to.have.property("role", "user");
});
});
});
it('Creates a team.', () => {
cy.fixture('teams').then(data => {
it("Creates a team.", () => {
cy.fixture("teams").then((data) => {
const teamCreate = data.teamCreate;
cy.request({
method: 'POST',
url: '/api/teams',
method: "POST",
url: "/api/teams",
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
body: teamCreate,
}).then(response => {
}).then((response) => {
teamId = response.body[0].id;
expect(response.status).to.eq(200);
expect(response.body[0]).to.have.property('name', 'cypress');
expect(response.body[1]).to.have.property('role', 'team-owner');
expect(response.body[0]).to.have.property("name", "cypress");
expect(response.body[1]).to.have.property("role", "team-owner");
});
});
});
it('Gets a teams by ID.', () => {
it("Gets a teams by ID.", () => {
cy.request({
method: 'GET',
method: "GET",
url: `/api/teams/${teamId}`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.property('id', teamId);
expect(response.body).to.have.property("id", teamId);
});
});
it('Updates a team.', () => {
cy.fixture('teams').then(data => {
it("Updates a team.", () => {
cy.fixture("teams").then((data) => {
const teamUpdate = data.teamUpdate;
cy.request({
method: 'POST',
method: "POST",
url: `/api/teams/${teamId}`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
body: teamUpdate,
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.property('id', teamId);
expect(response.body).to.have.property('name', 'cypressUpdate');
expect(response.body).to.have.property("id", teamId);
expect(response.body).to.have.property("name", "cypressUpdate");
});
});
});
it('Get all users that belong to a team.', () => {
it("Get all users that belong to a team.", () => {
cy.request({
method: 'GET',
method: "GET",
url: `/api/teams/${teamId}/users`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body.data[0]).to.have.property('id');
expect(response.body.data[0]).to.have.property('teamId');
expect(response.body.data[0]).to.have.property('userId');
expect(response.body.data[0]).to.have.property('user');
expect(response.body.data[0]).to.have.property("id");
expect(response.body.data[0]).to.have.property("teamId");
expect(response.body.data[0]).to.have.property("userId");
expect(response.body.data[0]).to.have.property("user");
});
});
it('Get a user belonging to a team.', () => {
it("Get a user belonging to a team.", () => {
cy.request({
method: 'GET',
url: `/api/teams/${teamId}/users/${Cypress.env('umami_user_id')}`,
method: "GET",
url: `/api/teams/${teamId}/users/${Cypress.env("syncfuse_user_id")}`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.property('teamId');
expect(response.body).to.have.property('userId');
expect(response.body).to.have.property('role');
expect(response.body).to.have.property("teamId");
expect(response.body).to.have.property("userId");
expect(response.body).to.have.property("role");
});
});
it('Get all websites belonging to a team.', () => {
it("Get all websites belonging to a team.", () => {
cy.request({
method: 'GET',
method: "GET",
url: `/api/teams/${teamId}/websites`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.property('data');
expect(response.body).to.have.property("data");
});
});
it('Add a user to a team.', () => {
it("Add a user to a team.", () => {
cy.request({
method: 'POST',
method: "POST",
url: `/api/teams/${teamId}/users`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
body: {
userId,
role: 'team-member',
role: "team-member",
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.property('userId', userId);
expect(response.body).to.have.property('role', 'team-member');
expect(response.body).to.have.property("userId", userId);
expect(response.body).to.have.property("role", "team-member");
});
});
it(`Update a user's role on a team.`, () => {
cy.request({
method: 'POST',
method: "POST",
url: `/api/teams/${teamId}/users/${userId}`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
body: {
role: 'team-view-only',
role: "team-view-only",
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.property('userId', userId);
expect(response.body).to.have.property('role', 'team-view-only');
expect(response.body).to.have.property("userId", userId);
expect(response.body).to.have.property("role", "team-view-only");
});
});
it(`Remove a user from a team.`, () => {
cy.request({
method: 'DELETE',
method: "DELETE",
url: `/api/teams/${teamId}/users/${userId}`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
});
});
it('Deletes a team.', () => {
it("Deletes a team.", () => {
cy.request({
method: 'DELETE',
method: "DELETE",
url: `/api/teams/${teamId}`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.property('ok', true);
expect(response.body).to.have.property("ok", true);
});
});

View file

@ -1,125 +1,125 @@
describe('User API tests', () => {
describe("User API tests", () => {
Cypress.session.clearAllSavedSessions();
before(() => {
cy.login(Cypress.env('umami_user'), Cypress.env('umami_password'));
cy.login(Cypress.env("syncfuse_user"), Cypress.env("syncfuse_password"));
});
let userId;
it('Creates a user.', () => {
cy.fixture('users').then(data => {
it("Creates a user.", () => {
cy.fixture("users").then((data) => {
const userCreate = data.userCreate;
cy.request({
method: 'POST',
url: '/api/users',
method: "POST",
url: "/api/users",
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
body: userCreate,
}).then(response => {
}).then((response) => {
userId = response.body.id;
expect(response.status).to.eq(200);
expect(response.body).to.have.property('username', 'cypress1');
expect(response.body).to.have.property('role', 'user');
expect(response.body).to.have.property("username", "cypress1");
expect(response.body).to.have.property("role", "user");
});
});
});
it('Returns all users. Admin access is required.', () => {
it("Returns all users. Admin access is required.", () => {
cy.request({
method: 'GET',
url: '/api/admin/users',
method: "GET",
url: "/api/admin/users",
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body.data[0]).to.have.property('id');
expect(response.body.data[0]).to.have.property('username');
expect(response.body.data[0]).to.have.property('password');
expect(response.body.data[0]).to.have.property('role');
expect(response.body.data[0]).to.have.property("id");
expect(response.body.data[0]).to.have.property("username");
expect(response.body.data[0]).to.have.property("password");
expect(response.body.data[0]).to.have.property("role");
});
});
it('Updates a user.', () => {
cy.fixture('users').then(data => {
it("Updates a user.", () => {
cy.fixture("users").then((data) => {
const userUpdate = data.userUpdate;
cy.request({
method: 'POST',
method: "POST",
url: `/api/users/${userId}`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
body: userUpdate,
}).then(response => {
}).then((response) => {
userId = response.body.id;
expect(response.status).to.eq(200);
expect(response.body).to.have.property('id', userId);
expect(response.body).to.have.property('username', 'cypress1');
expect(response.body).to.have.property('role', 'view-only');
expect(response.body).to.have.property("id", userId);
expect(response.body).to.have.property("username", "cypress1");
expect(response.body).to.have.property("role", "view-only");
});
});
});
it('Gets a user by ID.', () => {
it("Gets a user by ID.", () => {
cy.request({
method: 'GET',
method: "GET",
url: `/api/users/${userId}`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.property('id', userId);
expect(response.body).to.have.property('username', 'cypress1');
expect(response.body).to.have.property('role', 'view-only');
expect(response.body).to.have.property("id", userId);
expect(response.body).to.have.property("username", "cypress1");
expect(response.body).to.have.property("role", "view-only");
});
});
it('Deletes a user.', () => {
it("Deletes a user.", () => {
cy.request({
method: 'DELETE',
method: "DELETE",
url: `/api/users/${userId}`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.property('ok', true);
expect(response.body).to.have.property("ok", true);
});
});
it('Gets all websites that belong to a user.', () => {
it("Gets all websites that belong to a user.", () => {
cy.request({
method: 'GET',
method: "GET",
url: `/api/users/${userId}/websites`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.property('data');
expect(response.body).to.have.property("data");
});
});
it('Gets all teams that belong to a user.', () => {
it("Gets all teams that belong to a user.", () => {
cy.request({
method: 'GET',
method: "GET",
url: `/api/users/${userId}/teams`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.property('data');
expect(response.body).to.have.property("data");
});
});
});

View file

@ -1,194 +1,194 @@
import { uuid } from '../../src/lib/crypto';
import { uuid } from "../../src/lib/crypto";
describe('Website API tests', () => {
describe("Website API tests", () => {
Cypress.session.clearAllSavedSessions();
let websiteId;
let teamId;
before(() => {
cy.login(Cypress.env('umami_user'), Cypress.env('umami_password'));
cy.fixture('teams').then(data => {
cy.login(Cypress.env("syncfuse_user"), Cypress.env("syncfuse_password"));
cy.fixture("teams").then((data) => {
const teamCreate = data.teamCreate;
cy.request({
method: 'POST',
url: '/api/teams',
method: "POST",
url: "/api/teams",
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
body: teamCreate,
}).then(response => {
}).then((response) => {
teamId = response.body[0].id;
expect(response.status).to.eq(200);
expect(response.body[0]).to.have.property('name', 'cypress');
expect(response.body[1]).to.have.property('role', 'team-owner');
expect(response.body[0]).to.have.property("name", "cypress");
expect(response.body[1]).to.have.property("role", "team-owner");
});
});
});
it('Creates a website for user.', () => {
cy.fixture('websites').then(data => {
it("Creates a website for user.", () => {
cy.fixture("websites").then((data) => {
const websiteCreate = data.websiteCreate;
cy.request({
method: 'POST',
url: '/api/websites',
method: "POST",
url: "/api/websites",
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
body: websiteCreate,
}).then(response => {
}).then((response) => {
websiteId = response.body.id;
expect(response.status).to.eq(200);
expect(response.body).to.have.property('name', 'Cypress Website');
expect(response.body).to.have.property('domain', 'cypress.com');
expect(response.body).to.have.property("name", "Cypress Website");
expect(response.body).to.have.property("domain", "cypress.com");
});
});
});
it('Creates a website for team.', () => {
it("Creates a website for team.", () => {
cy.request({
method: 'POST',
url: '/api/websites',
method: "POST",
url: "/api/websites",
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
body: {
name: 'Team Website',
domain: 'teamwebsite.com',
name: "Team Website",
domain: "teamwebsite.com",
teamId: teamId,
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.property('name', 'Team Website');
expect(response.body).to.have.property('domain', 'teamwebsite.com');
expect(response.body).to.have.property("name", "Team Website");
expect(response.body).to.have.property("domain", "teamwebsite.com");
});
});
it('Creates a website with a fixed ID.', () => {
cy.fixture('websites').then(data => {
it("Creates a website with a fixed ID.", () => {
cy.fixture("websites").then((data) => {
const websiteCreate = data.websiteCreate;
const fixedId = uuid();
cy.request({
method: 'POST',
url: '/api/websites',
method: "POST",
url: "/api/websites",
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
body: { ...websiteCreate, id: fixedId },
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.property('id', fixedId);
expect(response.body).to.have.property('name', 'Cypress Website');
expect(response.body).to.have.property('domain', 'cypress.com');
expect(response.body).to.have.property("id", fixedId);
expect(response.body).to.have.property("name", "Cypress Website");
expect(response.body).to.have.property("domain", "cypress.com");
// cleanup
cy.request({
method: 'DELETE',
method: "DELETE",
url: `/api/websites/${fixedId}`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
});
});
});
});
it('Returns all tracked websites.', () => {
it("Returns all tracked websites.", () => {
cy.request({
method: 'GET',
url: '/api/websites',
method: "GET",
url: "/api/websites",
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body.data[0]).to.have.property('id');
expect(response.body.data[0]).to.have.property('name');
expect(response.body.data[0]).to.have.property('domain');
expect(response.body.data[0]).to.have.property("id");
expect(response.body.data[0]).to.have.property("name");
expect(response.body.data[0]).to.have.property("domain");
});
});
it('Gets a website by ID.', () => {
it("Gets a website by ID.", () => {
cy.request({
method: 'GET',
method: "GET",
url: `/api/websites/${websiteId}`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.property('name', 'Cypress Website');
expect(response.body).to.have.property('domain', 'cypress.com');
expect(response.body).to.have.property("name", "Cypress Website");
expect(response.body).to.have.property("domain", "cypress.com");
});
});
it('Updates a website.', () => {
cy.fixture('websites').then(data => {
it("Updates a website.", () => {
cy.fixture("websites").then((data) => {
const websiteUpdate = data.websiteUpdate;
cy.request({
method: 'POST',
method: "POST",
url: `/api/websites/${websiteId}`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
body: websiteUpdate,
}).then(response => {
}).then((response) => {
websiteId = response.body.id;
expect(response.status).to.eq(200);
expect(response.body).to.have.property('name', 'Cypress Website Updated');
expect(response.body).to.have.property('domain', 'cypressupdated.com');
expect(response.body).to.have.property("name", "Cypress Website Updated");
expect(response.body).to.have.property("domain", "cypressupdated.com");
});
});
});
it('Updates a website with only shareId.', () => {
it("Updates a website with only shareId.", () => {
cy.request({
method: 'POST',
method: "POST",
url: `/api/websites/${websiteId}`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
body: { shareId: 'ABCDEF' },
}).then(response => {
body: { shareId: "ABCDEF" },
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.property('shareId', 'ABCDEF');
expect(response.body).to.have.property("shareId", "ABCDEF");
});
});
it('Resets a website by removing all data related to the website.', () => {
it("Resets a website by removing all data related to the website.", () => {
cy.request({
method: 'POST',
method: "POST",
url: `/api/websites/${websiteId}/reset`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.property('ok', true);
expect(response.body).to.have.property("ok", true);
});
});
it('Deletes a website.', () => {
it("Deletes a website.", () => {
cy.request({
method: 'DELETE',
method: "DELETE",
url: `/api/websites/${websiteId}`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.property('ok', true);
expect(response.body).to.have.property("ok", true);
});
});

View file

@ -1,36 +1,34 @@
describe('Login tests', () => {
describe("Login tests", () => {
beforeEach(() => {
cy.visit('/login');
cy.visit("/login");
});
it(
'logs user in with correct credentials and logs user out',
"logs user in with correct credentials and logs user out",
{
defaultCommandTimeout: 10000,
},
() => {
cy.getDataTest('input-username').find('input').as('inputUsername').click();
cy.get('@inputUsername').type(Cypress.env('umami_user'), { delay: 0 });
cy.get('@inputUsername').click();
cy.getDataTest('input-password')
.find('input')
.type(Cypress.env('umami_password'), { delay: 0 });
cy.getDataTest('button-submit').click();
cy.url().should('eq', Cypress.config().baseUrl + '/dashboard');
cy.getDataTest("input-username").find("input").as("inputUsername").click();
cy.get("@inputUsername").type(Cypress.env("syncfuse_user"), { delay: 0 });
cy.get("@inputUsername").click();
cy.getDataTest("input-password").find("input").type(Cypress.env("syncfuse_password"), { delay: 0 });
cy.getDataTest("button-submit").click();
cy.url().should("eq", Cypress.config().baseUrl + "/dashboard");
cy.logout();
},
);
it('login with blank inputs or incorrect credentials', () => {
cy.getDataTest('button-submit').click();
cy.contains(/Required/i).should('be.visible');
it("login with blank inputs or incorrect credentials", () => {
cy.getDataTest("button-submit").click();
cy.contains(/Required/i).should("be.visible");
cy.getDataTest('input-username').find('input').as('inputUsername');
cy.get('@inputUsername').click();
cy.get('@inputUsername').type(Cypress.env('umami_user'), { delay: 0 });
cy.get('@inputUsername').click();
cy.getDataTest('input-password').find('input').type('wrongpassword', { delay: 0 });
cy.getDataTest('button-submit').click();
cy.contains(/Incorrect username and\/or password./i).should('be.visible');
cy.getDataTest("input-username").find("input").as("inputUsername");
cy.get("@inputUsername").click();
cy.get("@inputUsername").type(Cypress.env("syncfuse_user"), { delay: 0 });
cy.get("@inputUsername").click();
cy.getDataTest("input-password").find("input").type("wrongpassword", { delay: 0 });
cy.getDataTest("button-submit").click();
cy.contains(/Incorrect username and\/or password./i).should("be.visible");
});
});

View file

@ -1,65 +1,65 @@
describe('User tests', () => {
describe("User tests", () => {
Cypress.session.clearAllSavedSessions();
beforeEach(() => {
cy.login(Cypress.env('umami_user'), Cypress.env('umami_password'));
cy.visit('/settings/users');
cy.login(Cypress.env("syncfuse_user"), Cypress.env("syncfuse_password"));
cy.visit("/settings/users");
});
it('Add a User', () => {
it("Add a User", () => {
// add user
cy.contains(/Create user/i).should('be.visible');
cy.getDataTest('button-create-user').click();
cy.getDataTest('input-username').find('input').as('inputName').click();
cy.get('@inputName').type('Test-user', { delay: 0 });
cy.getDataTest('input-password').find('input').as('inputPassword').click();
cy.get('@inputPassword').type('testPasswordCypress', { delay: 0 });
cy.getDataTest('dropdown-role').click();
cy.getDataTest('dropdown-item-user').click();
cy.getDataTest('button-submit').click();
cy.get('td[label="Username"]').should('contain.text', 'Test-user');
cy.get('td[label="Role"]').should('contain.text', 'User');
cy.contains(/Create user/i).should("be.visible");
cy.getDataTest("button-create-user").click();
cy.getDataTest("input-username").find("input").as("inputName").click();
cy.get("@inputName").type("Test-user", { delay: 0 });
cy.getDataTest("input-password").find("input").as("inputPassword").click();
cy.get("@inputPassword").type("testPasswordCypress", { delay: 0 });
cy.getDataTest("dropdown-role").click();
cy.getDataTest("dropdown-item-user").click();
cy.getDataTest("button-submit").click();
cy.get('td[label="Username"]').should("contain.text", "Test-user");
cy.get('td[label="Role"]').should("contain.text", "User");
});
it('Edit a User role and password', () => {
it("Edit a User role and password", () => {
// edit user
cy.get('table tbody tr')
.contains('td', /Test-user/i)
cy.get("table tbody tr")
.contains("td", /Test-user/i)
.parent()
.within(() => {
cy.getDataTest('link-button-edit').click(); // Clicks the button inside the row
cy.getDataTest("link-button-edit").click(); // Clicks the button inside the row
});
cy.getDataTest('input-password').find('input').as('inputPassword').click();
cy.get('@inputPassword').type('newPassword', { delay: 0 });
cy.getDataTest('dropdown-role').click();
cy.getDataTest('dropdown-item-viewOnly').click();
cy.getDataTest('button-submit').click();
cy.getDataTest("input-password").find("input").as("inputPassword").click();
cy.get("@inputPassword").type("newPassword", { delay: 0 });
cy.getDataTest("dropdown-role").click();
cy.getDataTest("dropdown-item-viewOnly").click();
cy.getDataTest("button-submit").click();
cy.visit('/settings/users');
cy.get('table tbody tr')
.contains('td', /Test-user/i)
cy.visit("/settings/users");
cy.get("table tbody tr")
.contains("td", /Test-user/i)
.parent()
.should('contain.text', 'View only');
.should("contain.text", "View only");
cy.logout();
cy.url().should('eq', Cypress.config().baseUrl + '/login');
cy.getDataTest('input-username').find('input').as('inputUsername').click();
cy.get('@inputUsername').type('Test-user', { delay: 0 });
cy.get('@inputUsername').click();
cy.getDataTest('input-password').find('input').type('newPassword', { delay: 0 });
cy.getDataTest('button-submit').click();
cy.url().should('eq', Cypress.config().baseUrl + '/dashboard');
cy.url().should("eq", Cypress.config().baseUrl + "/login");
cy.getDataTest("input-username").find("input").as("inputUsername").click();
cy.get("@inputUsername").type("Test-user", { delay: 0 });
cy.get("@inputUsername").click();
cy.getDataTest("input-password").find("input").type("newPassword", { delay: 0 });
cy.getDataTest("button-submit").click();
cy.url().should("eq", Cypress.config().baseUrl + "/dashboard");
});
it('Delete a user', () => {
it("Delete a user", () => {
// delete user
cy.get('table tbody tr')
.contains('td', /Test-user/i)
cy.get("table tbody tr")
.contains("td", /Test-user/i)
.parent()
.within(() => {
cy.getDataTest('button-delete').click(); // Clicks the button inside the row
cy.getDataTest("button-delete").click(); // Clicks the button inside the row
});
cy.contains(/Are you sure you want to delete Test-user?/i).should('be.visible');
cy.getDataTest('button-confirm').click();
cy.contains(/Are you sure you want to delete Test-user?/i).should("be.visible");
cy.getDataTest("button-confirm").click();
});
});

View file

@ -1,89 +1,89 @@
describe('Website tests', () => {
describe("Website tests", () => {
Cypress.session.clearAllSavedSessions();
beforeEach(() => {
cy.login(Cypress.env('umami_user'), Cypress.env('umami_password'));
cy.login(Cypress.env("syncfuse_user"), Cypress.env("syncfuse_password"));
});
it('Add a website', () => {
it("Add a website", () => {
// add website
cy.visit('/settings/websites');
cy.getDataTest('button-website-add').click();
cy.contains(/Add website/i).should('be.visible');
cy.getDataTest('input-name').find('input').as('inputUsername').click();
cy.getDataTest('input-name').find('input').type('Add test', { delay: 0 });
cy.getDataTest('input-domain').find('input').click();
cy.getDataTest('input-domain').find('input').type('addtest.com', { delay: 0 });
cy.getDataTest('button-submit').click();
cy.get('td[label="Name"]').should('contain.text', 'Add test');
cy.get('td[label="Domain"]').should('contain.text', 'addtest.com');
cy.visit("/settings/websites");
cy.getDataTest("button-website-add").click();
cy.contains(/Add website/i).should("be.visible");
cy.getDataTest("input-name").find("input").as("inputUsername").click();
cy.getDataTest("input-name").find("input").type("Add test", { delay: 0 });
cy.getDataTest("input-domain").find("input").click();
cy.getDataTest("input-domain").find("input").type("addtest.com", { delay: 0 });
cy.getDataTest("button-submit").click();
cy.get('td[label="Name"]').should("contain.text", "Add test");
cy.get('td[label="Domain"]').should("contain.text", "addtest.com");
// clean-up data
cy.getDataTest('link-button-edit').first().click();
cy.contains(/Details/i).should('be.visible');
cy.getDataTest('text-field-websiteId')
.find('input')
.then($input => {
cy.getDataTest("link-button-edit").first().click();
cy.contains(/Details/i).should("be.visible");
cy.getDataTest("text-field-websiteId")
.find("input")
.then(($input) => {
const websiteId = $input[0].value;
cy.deleteWebsite(websiteId);
});
cy.visit('/settings/websites');
cy.contains(/Add test/i).should('not.exist');
cy.visit("/settings/websites");
cy.contains(/Add test/i).should("not.exist");
});
it('Edit a website', () => {
it("Edit a website", () => {
// prep data
cy.addWebsite('Update test', 'updatetest.com');
cy.visit('/settings/websites');
cy.addWebsite("Update test", "updatetest.com");
cy.visit("/settings/websites");
// edit website
cy.getDataTest('link-button-edit').first().click();
cy.contains(/Details/i).should('be.visible');
cy.getDataTest('input-name').find('input').click();
cy.getDataTest('input-name').find('input').clear();
cy.getDataTest('input-name').find('input').type('Updated website', { delay: 0 });
cy.getDataTest('input-domain').find('input').click();
cy.getDataTest('input-domain').find('input').clear();
cy.getDataTest('input-domain').find('input').type('updatedwebsite.com', { delay: 0 });
cy.getDataTest('button-submit').click({ force: true });
cy.getDataTest('input-name').find('input').should('have.value', 'Updated website');
cy.getDataTest('input-domain').find('input').should('have.value', 'updatedwebsite.com');
cy.getDataTest("link-button-edit").first().click();
cy.contains(/Details/i).should("be.visible");
cy.getDataTest("input-name").find("input").click();
cy.getDataTest("input-name").find("input").clear();
cy.getDataTest("input-name").find("input").type("Updated website", { delay: 0 });
cy.getDataTest("input-domain").find("input").click();
cy.getDataTest("input-domain").find("input").clear();
cy.getDataTest("input-domain").find("input").type("updatedwebsite.com", { delay: 0 });
cy.getDataTest("button-submit").click({ force: true });
cy.getDataTest("input-name").find("input").should("have.value", "Updated website");
cy.getDataTest("input-domain").find("input").should("have.value", "updatedwebsite.com");
// verify tracking script
cy.get('div')
cy.get("div")
.contains(/Tracking code/i)
.click();
cy.get('textarea').should('contain.text', Cypress.config().baseUrl + '/script.js');
cy.get("textarea").should("contain.text", Cypress.config().baseUrl + "/script.js");
// clean-up data
cy.get('div')
cy.get("div")
.contains(/Details/i)
.click();
cy.contains(/Details/i).should('be.visible');
cy.getDataTest('text-field-websiteId')
.find('input')
.then($input => {
cy.contains(/Details/i).should("be.visible");
cy.getDataTest("text-field-websiteId")
.find("input")
.then(($input) => {
const websiteId = $input[0].value;
cy.deleteWebsite(websiteId);
});
cy.visit('/settings/websites');
cy.contains(/Add test/i).should('not.exist');
cy.visit("/settings/websites");
cy.contains(/Add test/i).should("not.exist");
});
it('Delete a website', () => {
it("Delete a website", () => {
// prep data
cy.addWebsite('Delete test', 'deletetest.com');
cy.visit('/settings/websites');
cy.addWebsite("Delete test", "deletetest.com");
cy.visit("/settings/websites");
// delete website
cy.getDataTest('link-button-edit').first().click();
cy.contains(/Data/i).should('be.visible');
cy.get('div').contains(/Data/i).click();
cy.contains(/All website data will be deleted./i).should('be.visible');
cy.getDataTest('button-delete').click();
cy.contains(/Type DELETE in the box below to confirm./i).should('be.visible');
cy.get('input[name="confirm"').type('DELETE');
cy.getDataTest("link-button-edit").first().click();
cy.contains(/Data/i).should("be.visible");
cy.get("div").contains(/Data/i).click();
cy.contains(/All website data will be deleted./i).should("be.visible");
cy.getDataTest("button-delete").click();
cy.contains(/Type DELETE in the box below to confirm./i).should("be.visible");
cy.get('input[name="confirm"').type("DELETE");
cy.get('button[type="submit"]').click();
cy.contains(/Delete test/i).should('not.exist');
cy.contains(/Delete test/i).should("not.exist");
});
});

View file

@ -1,123 +1,123 @@
/// <reference types="cypress" />
import { uuid } from '../../src/lib/crypto';
import { uuid } from "../../src/lib/crypto";
Cypress.Commands.add('getDataTest', (value: string) => {
Cypress.Commands.add("getDataTest", (value: string) => {
return cy.get(`[data-test=${value}]`);
});
Cypress.Commands.add('logout', () => {
cy.getDataTest('button-profile').click();
cy.getDataTest('item-logout').click();
cy.url().should('eq', Cypress.config().baseUrl + '/login');
Cypress.Commands.add("logout", () => {
cy.getDataTest("button-profile").click();
cy.getDataTest("item-logout").click();
cy.url().should("eq", Cypress.config().baseUrl + "/login");
});
Cypress.Commands.add('login', (username: string, password: string) => {
Cypress.Commands.add("login", (username: string, password: string) => {
cy.session([username, password], () => {
cy.request({
method: 'POST',
url: '/api/auth/login',
method: "POST",
url: "/api/auth/login",
body: {
username,
password,
},
})
.then(response => {
Cypress.env('authorization', `bearer ${response.body.token}`);
window.localStorage.setItem('umami.auth', JSON.stringify(response.body.token));
.then((response) => {
Cypress.env("authorization", `bearer ${response.body.token}`);
window.localStorage.setItem("syncfuse.auth", JSON.stringify(response.body.token));
})
.its('status')
.should('eq', 200);
.its("status")
.should("eq", 200);
});
});
Cypress.Commands.add('addWebsite', (name: string, domain: string) => {
Cypress.Commands.add("addWebsite", (name: string, domain: string) => {
cy.request({
method: 'POST',
url: '/api/websites',
method: "POST",
url: "/api/websites",
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
body: {
id: uuid(),
createdBy: '41e2b680-648e-4b09-bcd7-3e2b10c06264',
createdBy: "41e2b680-648e-4b09-bcd7-3e2b10c06264",
name: name,
domain: domain,
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
});
});
Cypress.Commands.add('deleteWebsite', (websiteId: string) => {
Cypress.Commands.add("deleteWebsite", (websiteId: string) => {
cy.request({
method: 'DELETE',
method: "DELETE",
url: `/api/websites/${websiteId}`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
});
});
Cypress.Commands.add('addUser', (username: string, password: string, role: string) => {
Cypress.Commands.add("addUser", (username: string, password: string, role: string) => {
cy.request({
method: 'POST',
url: '/api/users',
method: "POST",
url: "/api/users",
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
body: {
username: username,
password: password,
role: role,
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
});
});
Cypress.Commands.add('deleteUser', (userId: string) => {
Cypress.Commands.add("deleteUser", (userId: string) => {
cy.request({
method: 'DELETE',
method: "DELETE",
url: `/api/users/${userId}`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
});
});
Cypress.Commands.add('addTeam', (name: string) => {
Cypress.Commands.add("addTeam", (name: string) => {
cy.request({
method: 'POST',
url: '/api/teams',
method: "POST",
url: "/api/teams",
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
body: {
name: name,
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
});
});
Cypress.Commands.add('deleteTeam', (teamId: string) => {
Cypress.Commands.add("deleteTeam", (teamId: string) => {
cy.request({
method: 'DELETE',
method: "DELETE",
url: `/api/teams/${teamId}`,
headers: {
'Content-Type': 'application/json',
Authorization: Cypress.env('authorization'),
"Content-Type": "application/json",
Authorization: Cypress.env("authorization"),
},
}).then(response => {
}).then((response) => {
expect(response.status).to.eq(200);
});
});

View file

@ -9,10 +9,10 @@ ALTER TABLE "website_event" ADD COLUMN "job_id" UUID AFTER "created_at";
ALTER TABLE "event_data" ADD COLUMN "job_id" UUID AFTER "created_at";
-- update event_data string
alter table umami.event_data
alter table syncfuse.event_data
update string_value = number_value
where data_type = 2
alter table umami.event_data
alter table syncfuse.event_data
update string_value = replaceOne(concat(CAST(toDateTime(date_value, 'UTC'), 'String'),'Z'), ' ', 'T')
where data_type = 4

View file

@ -1,4 +1,4 @@
CREATE TABLE umami.website_event_join
CREATE TABLE syncfuse.website_event_join
(
session_id UUID,
visit_id UUID,
@ -8,7 +8,7 @@ CREATE TABLE umami.website_event_join
ORDER BY (session_id, created_at)
SETTINGS index_granularity = 8192;
INSERT INTO umami.website_event_join
INSERT INTO syncfuse.website_event_join
SELECT DISTINCT
s.session_id,
generateUUIDv4() visit_id,
@ -18,7 +18,7 @@ FROM (SELECT DISTINCT session_id,
FROM website_event) s;
-- create new table
CREATE TABLE umami.website_event_new
CREATE TABLE syncfuse.website_event_new
(
website_id UUID,
session_id UUID,
@ -49,7 +49,7 @@ CREATE TABLE umami.website_event_new
ORDER BY (website_id, session_id, created_at)
SETTINGS index_granularity = 8192;
INSERT INTO umami.website_event_new
INSERT INTO syncfuse.website_event_new
SELECT we.website_id,
we.session_id,
j.visit_id,
@ -74,17 +74,17 @@ SELECT we.website_id,
we.event_name,
we.created_at,
we.job_id
FROM umami.website_event we
JOIN umami.website_event_join j
FROM syncfuse.website_event we
JOIN syncfuse.website_event_join j
ON we.session_id = j.session_id
and date_trunc('hour', we.created_at) = j.created_at
RENAME TABLE umami.website_event TO umami.website_event_old;
RENAME TABLE umami.website_event_new TO umami.website_event;
RENAME TABLE syncfuse.website_event TO syncfuse.website_event_old;
RENAME TABLE syncfuse.website_event_new TO syncfuse.website_event;
/*
DROP TABLE umami.website_event_old
DROP TABLE umami.website_event_join
DROP TABLE syncfuse.website_event_old
DROP TABLE syncfuse.website_event_join
*/

View file

@ -1,4 +1,4 @@
CREATE TABLE umami.event_data_new
CREATE TABLE syncfuse.event_data_new
(
website_id UUID,
session_id UUID,
@ -17,7 +17,7 @@ CREATE TABLE umami.event_data_new
ORDER BY (website_id, event_id, data_key, created_at)
SETTINGS index_granularity = 8192;
INSERT INTO umami.event_data_new
INSERT INTO syncfuse.event_data_new
SELECT website_id,
session_id,
event_id,
@ -30,9 +30,9 @@ SELECT website_id,
data_type,
created_at,
NULL
FROM umami.event_data;
FROM syncfuse.event_data;
CREATE TABLE umami.session_data
CREATE TABLE syncfuse.session_data
(
website_id UUID,
session_id UUID,
@ -48,10 +48,10 @@ CREATE TABLE umami.session_data
ORDER BY (website_id, session_id, data_key, created_at)
SETTINGS index_granularity = 8192;
RENAME TABLE umami.event_data TO umami.event_data_old;
RENAME TABLE umami.event_data_new TO umami.event_data;
RENAME TABLE syncfuse.event_data TO syncfuse.event_data_old;
RENAME TABLE syncfuse.event_data_new TO syncfuse.event_data;
/*
DROP TABLE umami.event_data_old
DROP TABLE syncfuse.event_data_old
*/

View file

@ -1,12 +1,12 @@
-- add tag column
ALTER TABLE umami.website_event ADD COLUMN "tag" String AFTER "event_name";
ALTER TABLE umami.website_event_stats_hourly ADD COLUMN "tag" SimpleAggregateFunction(groupArrayArray, Array(String)) AFTER "max_time";
ALTER TABLE syncfuse.website_event ADD COLUMN "tag" String AFTER "event_name";
ALTER TABLE syncfuse.website_event_stats_hourly ADD COLUMN "tag" SimpleAggregateFunction(groupArrayArray, Array(String)) AFTER "max_time";
-- update materialized view
DROP TABLE umami.website_event_stats_hourly_mv;
DROP TABLE syncfuse.website_event_stats_hourly_mv;
CREATE MATERIALIZED VIEW umami.website_event_stats_hourly_mv
TO umami.website_event_stats_hourly
CREATE MATERIALIZED VIEW syncfuse.website_event_stats_hourly_mv
TO syncfuse.website_event_stats_hourly
AS
SELECT
website_id,
@ -60,7 +60,7 @@ FROM (SELECT
max(created_at) max_time,
arrayFilter(x -> x != '', groupArray(tag)) tag,
toStartOfHour(created_at) timestamp
FROM umami.website_event
FROM syncfuse.website_event
GROUP BY website_id,
session_id,
visit_id,

View file

@ -1,5 +1,5 @@
-- Create Event
CREATE TABLE umami.website_event_new
CREATE TABLE syncfuse.website_event_new
(
website_id UUID,
session_id UUID,
@ -49,7 +49,7 @@ ENGINE = MergeTree
SETTINGS index_granularity = 8192;
-- stats hourly
CREATE TABLE umami.website_event_stats_hourly_new
CREATE TABLE syncfuse.website_event_stats_hourly_new
(
website_id UUID,
session_id UUID,
@ -99,8 +99,8 @@ ENGINE = AggregatingMergeTree
)
SAMPLE BY cityHash64(visit_id);
CREATE MATERIALIZED VIEW umami.website_event_stats_hourly_mv_new
TO umami.website_event_stats_hourly_new
CREATE MATERIALIZED VIEW syncfuse.website_event_stats_hourly_mv_new
TO syncfuse.website_event_stats_hourly_new
AS
SELECT
website_id,
@ -176,7 +176,7 @@ FROM (SELECT
max(created_at) max_time,
arrayFilter(x -> x != '', groupArray(tag)) tag,
toStartOfHour(created_at) timestamp
FROM umami.website_event_new
FROM syncfuse.website_event_new
GROUP BY website_id,
session_id,
visit_id,
@ -193,22 +193,22 @@ GROUP BY website_id,
timestamp);
-- projections
ALTER TABLE umami.website_event_new
ALTER TABLE syncfuse.website_event_new
ADD PROJECTION website_event_url_path_projection (
SELECT * ORDER BY toStartOfDay(created_at), website_id, url_path, created_at
);
ALTER TABLE umami.website_event_new MATERIALIZE PROJECTION website_event_url_path_projection;
ALTER TABLE syncfuse.website_event_new MATERIALIZE PROJECTION website_event_url_path_projection;
ALTER TABLE umami.website_event_new
ALTER TABLE syncfuse.website_event_new
ADD PROJECTION website_event_referrer_domain_projection (
SELECT * ORDER BY toStartOfDay(created_at), website_id, referrer_domain, created_at
);
ALTER TABLE umami.website_event_new MATERIALIZE PROJECTION website_event_referrer_domain_projection;
ALTER TABLE syncfuse.website_event_new MATERIALIZE PROJECTION website_event_referrer_domain_projection;
-- migration
INSERT INTO umami.website_event_new
INSERT INTO syncfuse.website_event_new
SELECT website_id, session_id, visit_id, event_id, hostname, browser, os, device, screen, language, country, subdivision1, subdivision2, city, url_path, url_query,
extract(url_query, 'utm_source=([^&]*)') AS utm_source,
extract(url_query, 'utm_medium=([^&]*)') AS utm_medium,
@ -223,23 +223,23 @@ SELECT website_id, session_id, visit_id, event_id, hostname, browser, os, device
extract(url_query, 'li_fat_id=([^&]*)') li_fat_id,
extract(url_query, 'twclid=([^&]*)') twclid,
event_type, event_name, tag, created_at, job_id
FROM umami.website_event
FROM syncfuse.website_event
-- rename tables
RENAME TABLE umami.website_event TO umami.website_event_old;
RENAME TABLE umami.website_event_new TO umami.website_event;
RENAME TABLE syncfuse.website_event TO syncfuse.website_event_old;
RENAME TABLE syncfuse.website_event_new TO syncfuse.website_event;
RENAME TABLE umami.website_event_stats_hourly TO umami.website_event_stats_hourly_old;
RENAME TABLE umami.website_event_stats_hourly_new TO umami.website_event_stats_hourly;
RENAME TABLE syncfuse.website_event_stats_hourly TO syncfuse.website_event_stats_hourly_old;
RENAME TABLE syncfuse.website_event_stats_hourly_new TO syncfuse.website_event_stats_hourly;
RENAME TABLE umami.website_event_stats_hourly_mv TO umami.website_event_stats_hourly_mv_old;
RENAME TABLE umami.website_event_stats_hourly_mv_new TO umami.website_event_stats_hourly_mv;
RENAME TABLE syncfuse.website_event_stats_hourly_mv TO syncfuse.website_event_stats_hourly_mv_old;
RENAME TABLE syncfuse.website_event_stats_hourly_mv_new TO syncfuse.website_event_stats_hourly_mv;
-- recreate view
DROP TABLE umami.website_event_stats_hourly_mv;
DROP TABLE syncfuse.website_event_stats_hourly_mv;
CREATE MATERIALIZED VIEW umami.website_event_stats_hourly_mv
TO umami.website_event_stats_hourly
CREATE MATERIALIZED VIEW syncfuse.website_event_stats_hourly_mv
TO syncfuse.website_event_stats_hourly
AS
SELECT
website_id,
@ -315,7 +315,7 @@ FROM (SELECT
max(created_at) max_time,
arrayFilter(x -> x != '', groupArray(tag)) tag,
toStartOfHour(created_at) timestamp
FROM umami.website_event
FROM syncfuse.website_event
GROUP BY website_id,
session_id,
visit_id,

View file

@ -1,35 +1,35 @@
-- drop projections
ALTER TABLE umami.website_event DROP PROJECTION website_event_url_path_projection;
ALTER TABLE umami.website_event DROP PROJECTION website_event_referrer_domain_projection;
ALTER TABLE syncfuse.website_event DROP PROJECTION website_event_url_path_projection;
ALTER TABLE syncfuse.website_event DROP PROJECTION website_event_referrer_domain_projection;
--drop view
DROP TABLE umami.website_event_stats_hourly_mv;
DROP TABLE syncfuse.website_event_stats_hourly_mv;
-- rename columns
ALTER TABLE umami.website_event RENAME COLUMN "subdivision1" TO "region";
ALTER TABLE umami.website_event_stats_hourly RENAME COLUMN "subdivision1" TO "region";
ALTER TABLE syncfuse.website_event RENAME COLUMN "subdivision1" TO "region";
ALTER TABLE syncfuse.website_event_stats_hourly RENAME COLUMN "subdivision1" TO "region";
-- drop columns
ALTER TABLE umami.website_event DROP COLUMN "subdivision2";
ALTER TABLE syncfuse.website_event DROP COLUMN "subdivision2";
-- recreate projections
ALTER TABLE umami.website_event
ALTER TABLE syncfuse.website_event
ADD PROJECTION website_event_url_path_projection (
SELECT * ORDER BY toStartOfDay(created_at), website_id, url_path, created_at
);
ALTER TABLE umami.website_event MATERIALIZE PROJECTION website_event_url_path_projection;
ALTER TABLE syncfuse.website_event MATERIALIZE PROJECTION website_event_url_path_projection;
ALTER TABLE umami.website_event
ALTER TABLE syncfuse.website_event
ADD PROJECTION website_event_referrer_domain_projection (
SELECT * ORDER BY toStartOfDay(created_at), website_id, referrer_domain, created_at
);
ALTER TABLE umami.website_event MATERIALIZE PROJECTION website_event_referrer_domain_projection;
ALTER TABLE syncfuse.website_event MATERIALIZE PROJECTION website_event_referrer_domain_projection;
-- recreate view
CREATE MATERIALIZED VIEW umami.website_event_stats_hourly_mv
TO umami.website_event_stats_hourly
CREATE MATERIALIZED VIEW syncfuse.website_event_stats_hourly_mv
TO syncfuse.website_event_stats_hourly
AS
SELECT
website_id,
@ -105,7 +105,7 @@ FROM (SELECT
max(created_at) max_time,
arrayFilter(x -> x != '', groupArray(tag)) tag,
toStartOfHour(created_at) timestamp
FROM umami.website_event
FROM syncfuse.website_event
GROUP BY website_id,
session_id,
visit_id,

View file

@ -1,13 +1,13 @@
-- add tag column
ALTER TABLE umami.website_event ADD COLUMN "distinct_id" String AFTER "tag";
ALTER TABLE umami.website_event_stats_hourly ADD COLUMN "distinct_id" String AFTER "tag";
ALTER TABLE umami.session_data ADD COLUMN "distinct_id" String AFTER "data_type";
ALTER TABLE syncfuse.website_event ADD COLUMN "distinct_id" String AFTER "tag";
ALTER TABLE syncfuse.website_event_stats_hourly ADD COLUMN "distinct_id" String AFTER "tag";
ALTER TABLE syncfuse.session_data ADD COLUMN "distinct_id" String AFTER "data_type";
-- update materialized view
DROP TABLE umami.website_event_stats_hourly_mv;
DROP TABLE syncfuse.website_event_stats_hourly_mv;
CREATE MATERIALIZED VIEW umami.website_event_stats_hourly_mv
TO umami.website_event_stats_hourly
CREATE MATERIALIZED VIEW syncfuse.website_event_stats_hourly_mv
TO syncfuse.website_event_stats_hourly
AS
SELECT
website_id,
@ -85,7 +85,7 @@ FROM (SELECT
arrayFilter(x -> x != '', groupArray(tag)) tag,
distinct_id,
toStartOfHour(created_at) timestamp
FROM umami.website_event
FROM syncfuse.website_event
GROUP BY website_id,
session_id,
visit_id,

View file

@ -1,5 +1,5 @@
-- create new hourly table
CREATE TABLE umami.website_event_stats_hourly_new
CREATE TABLE syncfuse.website_event_stats_hourly_new
(
website_id UUID,
session_id UUID,
@ -51,8 +51,8 @@ ENGINE = AggregatingMergeTree
SAMPLE BY cityHash64(visit_id);
-- create view
CREATE MATERIALIZED VIEW umami.website_event_stats_hourly_mv_new
TO umami.website_event_stats_hourly_new
CREATE MATERIALIZED VIEW syncfuse.website_event_stats_hourly_mv_new
TO syncfuse.website_event_stats_hourly_new
AS
SELECT
website_id,
@ -130,7 +130,7 @@ FROM (SELECT
arrayFilter(x -> x != '', groupArray(tag)) tag,
distinct_id,
toStartOfHour(created_at) timestamp
FROM umami.website_event
FROM syncfuse.website_event
GROUP BY website_id,
session_id,
visit_id,
@ -148,16 +148,16 @@ GROUP BY website_id,
timestamp);
-- rename tables
RENAME TABLE umami.website_event_stats_hourly TO umami.website_event_stats_hourly_old;
RENAME TABLE umami.website_event_stats_hourly_new TO umami.website_event_stats_hourly;
RENAME TABLE syncfuse.website_event_stats_hourly TO syncfuse.website_event_stats_hourly_old;
RENAME TABLE syncfuse.website_event_stats_hourly_new TO syncfuse.website_event_stats_hourly;
-- drop views
DROP TABLE umami.website_event_stats_hourly_mv;
DROP TABLE umami.website_event_stats_hourly_mv_new;
DROP TABLE syncfuse.website_event_stats_hourly_mv;
DROP TABLE syncfuse.website_event_stats_hourly_mv_new;
-- recreate view
CREATE MATERIALIZED VIEW umami.website_event_stats_hourly_mv
TO umami.website_event_stats_hourly
CREATE MATERIALIZED VIEW syncfuse.website_event_stats_hourly_mv
TO syncfuse.website_event_stats_hourly
AS
SELECT
website_id,
@ -235,7 +235,7 @@ FROM (SELECT
arrayFilter(x -> x != '', groupArray(tag)) tag,
distinct_id,
toStartOfHour(created_at) timestamp
FROM umami.website_event
FROM syncfuse.website_event
GROUP BY website_id,
session_id,
visit_id,

View file

@ -1,5 +1,5 @@
-- Create Event
CREATE TABLE umami.website_event
CREATE TABLE syncfuse.website_event
(
website_id UUID,
session_id UUID,
@ -48,7 +48,7 @@ ENGINE = MergeTree
PRIMARY KEY (toStartOfHour(created_at), website_id, session_id, visit_id)
SETTINGS index_granularity = 8192;
CREATE TABLE umami.event_data
CREATE TABLE syncfuse.event_data
(
website_id UUID,
session_id UUID,
@ -67,7 +67,7 @@ ENGINE = MergeTree
ORDER BY (website_id, event_id, data_key, created_at)
SETTINGS index_granularity = 8192;
CREATE TABLE umami.session_data
CREATE TABLE syncfuse.session_data
(
website_id UUID,
session_id UUID,
@ -85,7 +85,7 @@ ENGINE = ReplacingMergeTree
SETTINGS index_granularity = 8192;
-- stats hourly
CREATE TABLE umami.website_event_stats_hourly
CREATE TABLE syncfuse.website_event_stats_hourly
(
website_id UUID,
session_id UUID,
@ -136,8 +136,8 @@ ENGINE = AggregatingMergeTree
)
SAMPLE BY cityHash64(visit_id);
CREATE MATERIALIZED VIEW umami.website_event_stats_hourly_mv
TO umami.website_event_stats_hourly
CREATE MATERIALIZED VIEW syncfuse.website_event_stats_hourly_mv
TO syncfuse.website_event_stats_hourly
AS
SELECT
website_id,
@ -215,7 +215,7 @@ FROM (SELECT
arrayFilter(x -> x != '', groupArray(tag)) tag,
distinct_id,
toStartOfHour(created_at) timestamp
FROM umami.website_event
FROM syncfuse.website_event
GROUP BY website_id,
session_id,
visit_id,
@ -233,22 +233,22 @@ GROUP BY website_id,
timestamp);
-- projections
ALTER TABLE umami.website_event
ALTER TABLE syncfuse.website_event
ADD PROJECTION website_event_url_path_projection (
SELECT * ORDER BY toStartOfDay(created_at), website_id, url_path, created_at
);
ALTER TABLE umami.website_event MATERIALIZE PROJECTION website_event_url_path_projection;
ALTER TABLE syncfuse.website_event MATERIALIZE PROJECTION website_event_url_path_projection;
ALTER TABLE umami.website_event
ALTER TABLE syncfuse.website_event
ADD PROJECTION website_event_referrer_domain_projection (
SELECT * ORDER BY toStartOfDay(created_at), website_id, referrer_domain, created_at
);
ALTER TABLE umami.website_event MATERIALIZE PROJECTION website_event_referrer_domain_projection;
ALTER TABLE syncfuse.website_event MATERIALIZE PROJECTION website_event_referrer_domain_projection;
-- revenue
CREATE TABLE umami.website_revenue
CREATE TABLE syncfuse.website_revenue
(
website_id UUID,
session_id UUID,
@ -264,8 +264,8 @@ ENGINE = MergeTree
SETTINGS index_granularity = 8192;
CREATE MATERIALIZED VIEW umami.website_revenue_mv
TO umami.website_revenue
CREATE MATERIALIZED VIEW syncfuse.website_revenue_mv
TO syncfuse.website_revenue
AS
SELECT DISTINCT
ed.website_id,
@ -275,9 +275,9 @@ SELECT DISTINCT
c.currency,
coalesce(toDecimal64(ed.number_value, 2), toDecimal64(ed.string_value, 2)) revenue,
ed.created_at
FROM umami.event_data ed
FROM syncfuse.event_data ed
JOIN (SELECT event_id, string_value as currency
FROM umami.event_data
FROM syncfuse.event_data
WHERE positionCaseInsensitive(data_key, 'currency') > 0) c
ON c.event_id = ed.event_id
WHERE positionCaseInsensitive(data_key, 'revenue') > 0;

View file

@ -1,11 +1,11 @@
---
services:
umami:
syncfuse:
image: ghcr.io/umami-software/umami:latest
ports:
- "3000:3000"
environment:
DATABASE_URL: postgresql://umami:umami@db:5432/umami
DATABASE_URL: postgresql://syncfuse:syncfuse@db:5432/syncfuse
APP_SECRET: replace-me-with-a-random-string
depends_on:
db:
@ -20,11 +20,11 @@ services:
db:
image: postgres:15-alpine
environment:
POSTGRES_DB: umami
POSTGRES_USER: umami
POSTGRES_PASSWORD: umami
POSTGRES_DB: syncfuse
POSTGRES_USER: syncfuse
POSTGRES_PASSWORD: syncfuse
volumes:
- umami-db-data:/var/lib/postgresql/data
- syncfuse-db-data:/var/lib/postgresql/data
restart: always
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
@ -32,4 +32,4 @@ services:
timeout: 5s
retries: 5
volumes:
umami-db-data:
syncfuse-db-data:

View file

@ -1,7 +1,7 @@
{
"name": "@umami/components",
"name": "@syncfuse/components",
"version": "0.130.0",
"description": "Umami React components.",
"description": "Syncfuse React components.",
"author": "Mike Cao <mike@mikecao.com>",
"license": "MIT",
"type": "module",

View file

@ -1,8 +1,8 @@
{
"name": "umami",
"name": "syncfuse",
"version": "3.0.3",
"description": "A modern, privacy-focused alternative to Google Analytics.",
"author": "Umami Software, Inc. <hello@umami.is>",
"author": "Syncfuse Analytics",
"license": "MIT",
"homepage": "https://umami.is",
"repository": {

View file

@ -1,25 +1,22 @@
# How to deploy umami on podman
# How to deploy syncfuse on podman
## How to use
1. Rename `env.sample` to `.env`
2. Edit `.env` file. At the minimum set the passwords.
3. Start umami by running `podman-compose up -d`.
If you need to stop umami, you can do so by running `podman-compose down`.
3. Start syncfuse by running `podman-compose up -d`.
If you need to stop syncfuse, you can do so by running `podman-compose down`.
### Install systemd service (optional)
If you want to install a systemd service to run umami, you can use the provided
If you want to install a systemd service to run syncfuse, you can use the provided
systemd service.
Edit `umami.service` and change these two variables:
Edit `syncfuse.service` and change these two variables:
WorkingDirectory=/opt/apps/umami
EnvironmentFile=/opt/apps/umami/.env
WorkingDirectory=/opt/apps/syncfuse
EnvironmentFile=/opt/apps/syncfuse/.env
`WorkingDirectory` should be changed to the path in which `podman-compose.yml`
is located.
@ -30,17 +27,14 @@ located.
You can run the script `install-systemd-user-service` to install the systemd
service under the current user.
./install-systemd-user-service
Note: this script will enable the service and also start it. So it will assume
that umami is not currently running. If you started it previously, bring it
that syncfuse is not currently running. If you started it previously, bring it
down using:
podman-compose down
## Compatibility
These files should be compatible with podman 4.3+.

View file

@ -1,16 +1,16 @@
# Rename this file to .env and modify the values
#
# Connection string for Umamis database.
# Connection string for Syncfuse's database.
# If you use the bundled DB container, "db" is the hostname.
DATABASE_URL=postgresql://umami:replace-me-with-a-random-string@db:5432/umami
DATABASE_URL=postgresql://syncfuse:replace-me-with-a-random-string@db:5432/syncfuse
# Database type (e.g. postgresql)
DATABASE_TYPE=postgresql
# A secret string used by Umami (replace with a strong random string)
# A secret string used by Syncfuse (replace with a strong random string)
APP_SECRET=replace-me-with-a-random-string
# Postgres container defaults.
POSTGRES_DB=umami
POSTGRES_USER=umami
POSTGRES_DB=syncfuse
POSTGRES_USER=syncfuse
POSTGRES_PASSWORD=replace-me-with-a-random-string

View file

@ -1,6 +1,6 @@
#!/bin/bash
set -e
service_name="umami"
service_name="syncfuse"
mkdir -p ~/.config/systemd/user
cp $service_name.service ~/.config/systemd/user

View file

@ -1,8 +1,8 @@
version: "3.8"
services:
umami:
container_name: umami
syncfuse:
container_name: syncfuse
image: ghcr.io/umami-software/umami:postgresql-latest
ports:
- "127.0.0.1:3000:3000"
@ -22,14 +22,14 @@ services:
retries: 5
db:
container_name: umami-db
container_name: syncfuse-db
image: docker.io/library/postgres:15-alpine
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- umami-db-data:/var/lib/postgresql/data:Z
- syncfuse-db-data:/var/lib/postgresql/data:Z
restart: always
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]

14
podman/syncfuse.service Normal file
View file

@ -0,0 +1,14 @@
[Unit]
Description=Syncfuse Container Stack via Podman-Compose
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/apps/syncfuse
EnvironmentFile=/opt/apps/syncfuse/.env
ExecStart=/usr/bin/podman-compose -f podman-compose.yml up -d
ExecStop=/usr/bin/podman-compose -f podman-compose.yml down
RemainAfterExit=yes
[Install]
WantedBy=default.target

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1990,7 +1990,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "إصدار جديد من Umami "
"value": "إصدار جديد من Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Даступная новая версія Umami "
"value": "Даступная новая версія Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Има нова версия на Umami "
"value": "Има нова версия на Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -2004,7 +2004,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Nova verzija Umami "
"value": "Nova verzija Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Una nova versió d'Umami "
"value": "Una nova versió d'Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Es isch en neue Version vo Umami "
"value": "Es isch en neue Version vo Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Eine neue Version von Umami ist verfügbar: "
"value": "Eine neue Version von Syncfuse ist verfügbar: "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -2002,7 +2002,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Una nueva versión de Umami "
"value": "Una nueva versión de Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1288,7 +1288,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1984,7 +1984,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "نسخه‌ی جدیدی از Umami "
"value": "نسخه‌ی جدیدی از Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1988,7 +1988,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Une nouvelle version d'Umami "
"value": "Une nouvelle version d'Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -2004,7 +2004,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Unha nova versión de Umami "
"value": "Unha nova versión de Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1984,7 +1984,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -2000,7 +2000,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1960,7 +1960,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Versi baru dari Umami "
"value": "Versi baru dari Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -2000,7 +2000,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1980,7 +1980,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Umamiの新しいバージョン"
"value": "Syncfuseの新しいバージョン"
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1972,7 +1972,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Version ថ្មីនៃ Umami "
"value": "Version ថ្មីនៃ Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1936,7 +1936,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Umami의 새 버전 "
"value": "Syncfuse의 새 버전 "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -2121,7 +2121,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Išleista nauja 'Umami' "
"value": "Išleista nauja 'Syncfuse' "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -2004,7 +2004,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Umami-н шинэ хувилбар "
"value": "Syncfuse-н шинэ хувилбар "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1988,7 +1988,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -2000,7 +2000,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "En ny versjon av Umami "
"value": "En ny versjon av Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Een nieuwe versie van Umami "
"value": "Een nieuwe versie van Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Nowa wersja Umami "
"value": "Nowa wersja Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1984,7 +1984,7 @@
},
{
"type": 0,
"value": " do Umami está disponível!"
"value": " do Syncfuse está disponível!"
}
],
"message.no-data-available": [

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -2000,7 +2000,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "O nouă versiune de Umami "
"value": "O nouă versiune de Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1972,7 +1972,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Вышла новая версия Umami "
"value": "Вышла новая версия Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1988,7 +1988,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1870,7 +1870,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Na voljo je nova verzija programa Umami "
"value": "Na voljo je nova verzija programa Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -2000,7 +2000,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "En ny version av Umami "
"value": "En ny version av Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1992,7 +1992,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1956,7 +1956,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Yeni versiyon Umami "
"value": "Yeni versiyon Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1972,7 +1972,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Вийшла нова версія Umami "
"value": "Вийшла нова версія Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1996,7 +1996,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "A new version of Umami "
"value": "A new version of Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1644,7 +1644,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Umami'ning yangi **"
"value": "Syncfuse'ning yangi **"
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1652,7 +1652,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Có phiên bản mới của Umami "
"value": "Có phiên bản mới của Syncfuse "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1984,7 +1984,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Umami 新版本 "
"value": "Syncfuse 新版本 "
},
{
"type": 1,

View file

@ -1,4 +1,4 @@
{
{
"label.access-code": [
{
"type": 0,
@ -1964,7 +1964,7 @@
"message.new-version-available": [
{
"type": 0,
"value": "Umami "
"value": "Syncfuse "
},
{
"type": 1,

View file

@ -1,518 +1,516 @@
import { defineMessages } from 'react-intl';
import { defineMessages } from "react-intl";
export const labels = defineMessages({
ok: { id: 'label.ok', defaultMessage: 'OK' },
unknown: { id: 'label.unknown', defaultMessage: 'Unknown' },
required: { id: 'label.required', defaultMessage: 'Required' },
save: { id: 'label.save', defaultMessage: 'Save' },
cancel: { id: 'label.cancel', defaultMessage: 'Cancel' },
continue: { id: 'label.continue', defaultMessage: 'Continue' },
delete: { id: 'label.delete', defaultMessage: 'Delete' },
leave: { id: 'label.leave', defaultMessage: 'Leave' },
users: { id: 'label.users', defaultMessage: 'Users' },
createUser: { id: 'label.create-user', defaultMessage: 'Create user' },
deleteUser: { id: 'label.delete-user', defaultMessage: 'Delete user' },
username: { id: 'label.username', defaultMessage: 'Username' },
password: { id: 'label.password', defaultMessage: 'Password' },
role: { id: 'label.role', defaultMessage: 'Role' },
user: { id: 'label.user', defaultMessage: 'User' },
viewOnly: { id: 'label.view-only', defaultMessage: 'View only' },
manage: { id: 'label.manage', defaultMessage: 'Manage' },
admin: { id: 'label.admin', defaultMessage: 'Admin' },
confirm: { id: 'label.confirm', defaultMessage: 'Confirm' },
details: { id: 'label.details', defaultMessage: 'Details' },
website: { id: 'label.website', defaultMessage: 'Website' },
websites: { id: 'label.websites', defaultMessage: 'Websites' },
myWebsites: { id: 'label.my-websites', defaultMessage: 'My websites' },
teamWebsites: { id: 'label.team-websites', defaultMessage: 'Team websites' },
created: { id: 'label.created', defaultMessage: 'Created' },
createdBy: { id: 'label.created-by', defaultMessage: 'Created By' },
edit: { id: 'label.edit', defaultMessage: 'Edit' },
name: { id: 'label.name', defaultMessage: 'Name' },
manager: { id: 'label.manager', defaultMessage: 'Manager' },
member: { id: 'label.member', defaultMessage: 'Member' },
members: { id: 'label.members', defaultMessage: 'Members' },
accessCode: { id: 'label.access-code', defaultMessage: 'Access code' },
teamId: { id: 'label.team-id', defaultMessage: 'Team ID' },
team: { id: 'label.team', defaultMessage: 'Team' },
teamName: { id: 'label.team-name', defaultMessage: 'Team name' },
regenerate: { id: 'label.regenerate', defaultMessage: 'Regenerate' },
remove: { id: 'label.remove', defaultMessage: 'Remove' },
join: { id: 'label.join', defaultMessage: 'Join' },
createTeam: { id: 'label.create-team', defaultMessage: 'Create team' },
joinTeam: { id: 'label.join-team', defaultMessage: 'Join team' },
settings: { id: 'label.settings', defaultMessage: 'Settings' },
owner: { id: 'label.owner', defaultMessage: 'Owner' },
teamOwner: { id: 'label.team-owner', defaultMessage: 'Team owner' },
teamManager: { id: 'label.team-manager', defaultMessage: 'Team manager' },
teamMember: { id: 'label.team-member', defaultMessage: 'Team member' },
teamViewOnly: { id: 'label.team-view-only', defaultMessage: 'Team view only' },
enableShareUrl: { id: 'label.enable-share-url', defaultMessage: 'Enable share URL' },
data: { id: 'label.data', defaultMessage: 'Data' },
trackingCode: { id: 'label.tracking-code', defaultMessage: 'Tracking code' },
shareUrl: { id: 'label.share-url', defaultMessage: 'Share URL' },
action: { id: 'label.action', defaultMessage: 'Action' },
actions: { id: 'label.actions', defaultMessage: 'Actions' },
domain: { id: 'label.domain', defaultMessage: 'Domain' },
websiteId: { id: 'label.website-id', defaultMessage: 'Website ID' },
resetWebsite: { id: 'label.reset-website', defaultMessage: 'Reset website' },
deleteWebsite: { id: 'label.delete-website', defaultMessage: 'Delete website' },
transferWebsite: { id: 'label.transfer-website', defaultMessage: 'Transfer website' },
deleteReport: { id: 'label.delete-report', defaultMessage: 'Delete report' },
reset: { id: 'label.reset', defaultMessage: 'Reset' },
addWebsite: { id: 'label.add-website', defaultMessage: 'Add website' },
addMember: { id: 'label.add-member', defaultMessage: 'Add member' },
editMember: { id: 'label.edit-member', defaultMessage: 'Edit member' },
removeMember: { id: 'label.remove-member', defaultMessage: 'Remove member' },
addDescription: { id: 'label.add-description', defaultMessage: 'Add description' },
changePassword: { id: 'label.change-password', defaultMessage: 'Change password' },
currentPassword: { id: 'label.current-password', defaultMessage: 'Current password' },
newPassword: { id: 'label.new-password', defaultMessage: 'New password' },
confirmPassword: { id: 'label.confirm-password', defaultMessage: 'Confirm password' },
timezone: { id: 'label.timezone', defaultMessage: 'Timezone' },
defaultDateRange: { id: 'label.default-date-range', defaultMessage: 'Default date range' },
language: { id: 'label.language', defaultMessage: 'Language' },
theme: { id: 'label.theme', defaultMessage: 'Theme' },
profile: { id: 'label.profile', defaultMessage: 'Profile' },
profiles: { id: 'label.profiles', defaultMessage: 'Profiles' },
dashboard: { id: 'label.dashboard', defaultMessage: 'Dashboard' },
more: { id: 'label.more', defaultMessage: 'More' },
realtime: { id: 'label.realtime', defaultMessage: 'Realtime' },
queries: { id: 'label.queries', defaultMessage: 'Queries' },
teams: { id: 'label.teams', defaultMessage: 'Teams' },
teamSettings: { id: 'label.team-settings', defaultMessage: 'Team settings' },
analytics: { id: 'label.analytics', defaultMessage: 'Analytics' },
login: { id: 'label.login', defaultMessage: 'Login' },
logout: { id: 'label.logout', defaultMessage: 'Logout' },
singleDay: { id: 'label.single-day', defaultMessage: 'Single day' },
dateRange: { id: 'label.date-range', defaultMessage: 'Date range' },
viewDetails: { id: 'label.view-details', defaultMessage: 'View details' },
deleteTeam: { id: 'label.delete-team', defaultMessage: 'Delete team' },
leaveTeam: { id: 'label.leave-team', defaultMessage: 'Leave team' },
refresh: { id: 'label.refresh', defaultMessage: 'Refresh' },
page: { id: 'label.page', defaultMessage: 'Page' },
pages: { id: 'label.pages', defaultMessage: 'Pages' },
entry: { id: 'label.entry', defaultMessage: 'Entry' },
exit: { id: 'label.exit', defaultMessage: 'Exit' },
referrers: { id: 'label.referrers', defaultMessage: 'Referrers' },
screen: { id: 'label.screen', defaultMessage: 'Screen' },
screens: { id: 'label.screens', defaultMessage: 'Screens' },
browsers: { id: 'label.browsers', defaultMessage: 'Browsers' },
os: { id: 'label.os', defaultMessage: 'OS' },
devices: { id: 'label.devices', defaultMessage: 'Devices' },
countries: { id: 'label.countries', defaultMessage: 'Countries' },
languages: { id: 'label.languages', defaultMessage: 'Languages' },
tags: { id: 'label.tags', defaultMessage: 'Tags' },
segments: { id: 'label.segments', defaultMessage: 'Segments' },
cohorts: { id: 'label.cohorts', defaultMessage: 'Cohorts' },
count: { id: 'label.count', defaultMessage: 'Count' },
average: { id: 'label.average', defaultMessage: 'Average' },
sum: { id: 'label.sum', defaultMessage: 'Sum' },
event: { id: 'label.event', defaultMessage: 'Event' },
events: { id: 'label.events', defaultMessage: 'Events' },
eventName: { id: 'label.event-name', defaultMessage: 'Event name' },
query: { id: 'label.query', defaultMessage: 'Query' },
queryParameters: { id: 'label.query-parameters', defaultMessage: 'Query parameters' },
back: { id: 'label.back', defaultMessage: 'Back' },
visitors: { id: 'label.visitors', defaultMessage: 'Visitors' },
visits: { id: 'label.visits', defaultMessage: 'Visits' },
filterCombined: { id: 'label.filter-combined', defaultMessage: 'Combined' },
filterRaw: { id: 'label.filter-raw', defaultMessage: 'Raw' },
views: { id: 'label.views', defaultMessage: 'Views' },
none: { id: 'label.none', defaultMessage: 'None' },
clearAll: { id: 'label.clear-all', defaultMessage: 'Clear all' },
property: { id: 'label.property', defaultMessage: 'Property' },
today: { id: 'label.today', defaultMessage: 'Today' },
lastHours: { id: 'label.last-hours', defaultMessage: 'Last {x} hours' },
yesterday: { id: 'label.yesterday', defaultMessage: 'Yesterday' },
thisWeek: { id: 'label.this-week', defaultMessage: 'This week' },
lastDays: { id: 'label.last-days', defaultMessage: 'Last {x} days' },
lastMonths: { id: 'label.last-months', defaultMessage: 'Last {x} months' },
thisMonth: { id: 'label.this-month', defaultMessage: 'This month' },
thisYear: { id: 'label.this-year', defaultMessage: 'This year' },
allTime: { id: 'label.all-time', defaultMessage: 'All time' },
customRange: { id: 'label.custom-range', defaultMessage: 'Custom range' },
selectWebsite: { id: 'label.select-website', defaultMessage: 'Select website' },
selectRole: { id: 'label.select-role', defaultMessage: 'Select role' },
selectDate: { id: 'label.select-date', defaultMessage: 'Select date' },
selectFilter: { id: 'label.select-filter', defaultMessage: 'Select filter' },
all: { id: 'label.all', defaultMessage: 'All' },
session: { id: 'label.session', defaultMessage: 'Session' },
sessions: { id: 'label.sessions', defaultMessage: 'Sessions' },
distinctId: { id: 'label.distinct-id', defaultMessage: 'Distinct ID' },
pageNotFound: { id: 'message.page-not-found', defaultMessage: 'Page not found' },
activity: { id: 'label.activity', defaultMessage: 'Activity' },
dismiss: { id: 'label.dismiss', defaultMessage: 'Dismiss' },
poweredBy: { id: 'label.powered-by', defaultMessage: 'Powered by {name}' },
pageViews: { id: 'label.page-views', defaultMessage: 'Page views' },
uniqueVisitors: { id: 'label.unique-visitors', defaultMessage: 'Unique visitors' },
bounceRate: { id: 'label.bounce-rate', defaultMessage: 'Bounce rate' },
viewsPerVisit: { id: 'label.views-per-visit', defaultMessage: 'Views per visit' },
visitDuration: { id: 'label.visit-duration', defaultMessage: 'Visit duration' },
desktop: { id: 'label.desktop', defaultMessage: 'Desktop' },
laptop: { id: 'label.laptop', defaultMessage: 'Laptop' },
tablet: { id: 'label.tablet', defaultMessage: 'Tablet' },
mobile: { id: 'label.mobile', defaultMessage: 'Mobile' },
toggleCharts: { id: 'label.toggle-charts', defaultMessage: 'Toggle charts' },
editDashboard: { id: 'label.edit-dashboard', defaultMessage: 'Edit dashboard' },
title: { id: 'label.title', defaultMessage: 'Title' },
view: { id: 'label.view', defaultMessage: 'View' },
cities: { id: 'label.cities', defaultMessage: 'Cities' },
regions: { id: 'label.regions', defaultMessage: 'Regions' },
reports: { id: 'label.reports', defaultMessage: 'Reports' },
eventData: { id: 'label.event-data', defaultMessage: 'Event data' },
sessionData: { id: 'label.session-data', defaultMessage: 'Session data' },
funnel: { id: 'label.funnel', defaultMessage: 'Funnel' },
funnels: { id: 'label.funnels', defaultMessage: 'Funnels' },
ok: { id: "label.ok", defaultMessage: "OK" },
unknown: { id: "label.unknown", defaultMessage: "Unknown" },
required: { id: "label.required", defaultMessage: "Required" },
save: { id: "label.save", defaultMessage: "Save" },
cancel: { id: "label.cancel", defaultMessage: "Cancel" },
continue: { id: "label.continue", defaultMessage: "Continue" },
delete: { id: "label.delete", defaultMessage: "Delete" },
leave: { id: "label.leave", defaultMessage: "Leave" },
users: { id: "label.users", defaultMessage: "Users" },
createUser: { id: "label.create-user", defaultMessage: "Create user" },
deleteUser: { id: "label.delete-user", defaultMessage: "Delete user" },
username: { id: "label.username", defaultMessage: "Username" },
password: { id: "label.password", defaultMessage: "Password" },
role: { id: "label.role", defaultMessage: "Role" },
user: { id: "label.user", defaultMessage: "User" },
viewOnly: { id: "label.view-only", defaultMessage: "View only" },
manage: { id: "label.manage", defaultMessage: "Manage" },
admin: { id: "label.admin", defaultMessage: "Admin" },
confirm: { id: "label.confirm", defaultMessage: "Confirm" },
details: { id: "label.details", defaultMessage: "Details" },
website: { id: "label.website", defaultMessage: "Website" },
websites: { id: "label.websites", defaultMessage: "Websites" },
myWebsites: { id: "label.my-websites", defaultMessage: "My websites" },
teamWebsites: { id: "label.team-websites", defaultMessage: "Team websites" },
created: { id: "label.created", defaultMessage: "Created" },
createdBy: { id: "label.created-by", defaultMessage: "Created By" },
edit: { id: "label.edit", defaultMessage: "Edit" },
name: { id: "label.name", defaultMessage: "Name" },
manager: { id: "label.manager", defaultMessage: "Manager" },
member: { id: "label.member", defaultMessage: "Member" },
members: { id: "label.members", defaultMessage: "Members" },
accessCode: { id: "label.access-code", defaultMessage: "Access code" },
teamId: { id: "label.team-id", defaultMessage: "Team ID" },
team: { id: "label.team", defaultMessage: "Team" },
teamName: { id: "label.team-name", defaultMessage: "Team name" },
regenerate: { id: "label.regenerate", defaultMessage: "Regenerate" },
remove: { id: "label.remove", defaultMessage: "Remove" },
join: { id: "label.join", defaultMessage: "Join" },
createTeam: { id: "label.create-team", defaultMessage: "Create team" },
joinTeam: { id: "label.join-team", defaultMessage: "Join team" },
settings: { id: "label.settings", defaultMessage: "Settings" },
owner: { id: "label.owner", defaultMessage: "Owner" },
teamOwner: { id: "label.team-owner", defaultMessage: "Team owner" },
teamManager: { id: "label.team-manager", defaultMessage: "Team manager" },
teamMember: { id: "label.team-member", defaultMessage: "Team member" },
teamViewOnly: { id: "label.team-view-only", defaultMessage: "Team view only" },
enableShareUrl: { id: "label.enable-share-url", defaultMessage: "Enable share URL" },
data: { id: "label.data", defaultMessage: "Data" },
trackingCode: { id: "label.tracking-code", defaultMessage: "Tracking code" },
shareUrl: { id: "label.share-url", defaultMessage: "Share URL" },
action: { id: "label.action", defaultMessage: "Action" },
actions: { id: "label.actions", defaultMessage: "Actions" },
domain: { id: "label.domain", defaultMessage: "Domain" },
websiteId: { id: "label.website-id", defaultMessage: "Website ID" },
resetWebsite: { id: "label.reset-website", defaultMessage: "Reset website" },
deleteWebsite: { id: "label.delete-website", defaultMessage: "Delete website" },
transferWebsite: { id: "label.transfer-website", defaultMessage: "Transfer website" },
deleteReport: { id: "label.delete-report", defaultMessage: "Delete report" },
reset: { id: "label.reset", defaultMessage: "Reset" },
addWebsite: { id: "label.add-website", defaultMessage: "Add website" },
addMember: { id: "label.add-member", defaultMessage: "Add member" },
editMember: { id: "label.edit-member", defaultMessage: "Edit member" },
removeMember: { id: "label.remove-member", defaultMessage: "Remove member" },
addDescription: { id: "label.add-description", defaultMessage: "Add description" },
changePassword: { id: "label.change-password", defaultMessage: "Change password" },
currentPassword: { id: "label.current-password", defaultMessage: "Current password" },
newPassword: { id: "label.new-password", defaultMessage: "New password" },
confirmPassword: { id: "label.confirm-password", defaultMessage: "Confirm password" },
timezone: { id: "label.timezone", defaultMessage: "Timezone" },
defaultDateRange: { id: "label.default-date-range", defaultMessage: "Default date range" },
language: { id: "label.language", defaultMessage: "Language" },
theme: { id: "label.theme", defaultMessage: "Theme" },
profile: { id: "label.profile", defaultMessage: "Profile" },
profiles: { id: "label.profiles", defaultMessage: "Profiles" },
dashboard: { id: "label.dashboard", defaultMessage: "Dashboard" },
more: { id: "label.more", defaultMessage: "More" },
realtime: { id: "label.realtime", defaultMessage: "Realtime" },
queries: { id: "label.queries", defaultMessage: "Queries" },
teams: { id: "label.teams", defaultMessage: "Teams" },
teamSettings: { id: "label.team-settings", defaultMessage: "Team settings" },
analytics: { id: "label.analytics", defaultMessage: "Analytics" },
login: { id: "label.login", defaultMessage: "Login" },
logout: { id: "label.logout", defaultMessage: "Logout" },
singleDay: { id: "label.single-day", defaultMessage: "Single day" },
dateRange: { id: "label.date-range", defaultMessage: "Date range" },
viewDetails: { id: "label.view-details", defaultMessage: "View details" },
deleteTeam: { id: "label.delete-team", defaultMessage: "Delete team" },
leaveTeam: { id: "label.leave-team", defaultMessage: "Leave team" },
refresh: { id: "label.refresh", defaultMessage: "Refresh" },
page: { id: "label.page", defaultMessage: "Page" },
pages: { id: "label.pages", defaultMessage: "Pages" },
entry: { id: "label.entry", defaultMessage: "Entry" },
exit: { id: "label.exit", defaultMessage: "Exit" },
referrers: { id: "label.referrers", defaultMessage: "Referrers" },
screen: { id: "label.screen", defaultMessage: "Screen" },
screens: { id: "label.screens", defaultMessage: "Screens" },
browsers: { id: "label.browsers", defaultMessage: "Browsers" },
os: { id: "label.os", defaultMessage: "OS" },
devices: { id: "label.devices", defaultMessage: "Devices" },
countries: { id: "label.countries", defaultMessage: "Countries" },
languages: { id: "label.languages", defaultMessage: "Languages" },
tags: { id: "label.tags", defaultMessage: "Tags" },
segments: { id: "label.segments", defaultMessage: "Segments" },
cohorts: { id: "label.cohorts", defaultMessage: "Cohorts" },
count: { id: "label.count", defaultMessage: "Count" },
average: { id: "label.average", defaultMessage: "Average" },
sum: { id: "label.sum", defaultMessage: "Sum" },
event: { id: "label.event", defaultMessage: "Event" },
events: { id: "label.events", defaultMessage: "Events" },
eventName: { id: "label.event-name", defaultMessage: "Event name" },
query: { id: "label.query", defaultMessage: "Query" },
queryParameters: { id: "label.query-parameters", defaultMessage: "Query parameters" },
back: { id: "label.back", defaultMessage: "Back" },
visitors: { id: "label.visitors", defaultMessage: "Visitors" },
visits: { id: "label.visits", defaultMessage: "Visits" },
filterCombined: { id: "label.filter-combined", defaultMessage: "Combined" },
filterRaw: { id: "label.filter-raw", defaultMessage: "Raw" },
views: { id: "label.views", defaultMessage: "Views" },
none: { id: "label.none", defaultMessage: "None" },
clearAll: { id: "label.clear-all", defaultMessage: "Clear all" },
property: { id: "label.property", defaultMessage: "Property" },
today: { id: "label.today", defaultMessage: "Today" },
lastHours: { id: "label.last-hours", defaultMessage: "Last {x} hours" },
yesterday: { id: "label.yesterday", defaultMessage: "Yesterday" },
thisWeek: { id: "label.this-week", defaultMessage: "This week" },
lastDays: { id: "label.last-days", defaultMessage: "Last {x} days" },
lastMonths: { id: "label.last-months", defaultMessage: "Last {x} months" },
thisMonth: { id: "label.this-month", defaultMessage: "This month" },
thisYear: { id: "label.this-year", defaultMessage: "This year" },
allTime: { id: "label.all-time", defaultMessage: "All time" },
customRange: { id: "label.custom-range", defaultMessage: "Custom range" },
selectWebsite: { id: "label.select-website", defaultMessage: "Select website" },
selectRole: { id: "label.select-role", defaultMessage: "Select role" },
selectDate: { id: "label.select-date", defaultMessage: "Select date" },
selectFilter: { id: "label.select-filter", defaultMessage: "Select filter" },
all: { id: "label.all", defaultMessage: "All" },
session: { id: "label.session", defaultMessage: "Session" },
sessions: { id: "label.sessions", defaultMessage: "Sessions" },
distinctId: { id: "label.distinct-id", defaultMessage: "Distinct ID" },
pageNotFound: { id: "message.page-not-found", defaultMessage: "Page not found" },
activity: { id: "label.activity", defaultMessage: "Activity" },
dismiss: { id: "label.dismiss", defaultMessage: "Dismiss" },
poweredBy: { id: "label.powered-by", defaultMessage: "Powered by {name}" },
pageViews: { id: "label.page-views", defaultMessage: "Page views" },
uniqueVisitors: { id: "label.unique-visitors", defaultMessage: "Unique visitors" },
bounceRate: { id: "label.bounce-rate", defaultMessage: "Bounce rate" },
viewsPerVisit: { id: "label.views-per-visit", defaultMessage: "Views per visit" },
visitDuration: { id: "label.visit-duration", defaultMessage: "Visit duration" },
desktop: { id: "label.desktop", defaultMessage: "Desktop" },
laptop: { id: "label.laptop", defaultMessage: "Laptop" },
tablet: { id: "label.tablet", defaultMessage: "Tablet" },
mobile: { id: "label.mobile", defaultMessage: "Mobile" },
toggleCharts: { id: "label.toggle-charts", defaultMessage: "Toggle charts" },
editDashboard: { id: "label.edit-dashboard", defaultMessage: "Edit dashboard" },
title: { id: "label.title", defaultMessage: "Title" },
view: { id: "label.view", defaultMessage: "View" },
cities: { id: "label.cities", defaultMessage: "Cities" },
regions: { id: "label.regions", defaultMessage: "Regions" },
reports: { id: "label.reports", defaultMessage: "Reports" },
eventData: { id: "label.event-data", defaultMessage: "Event data" },
sessionData: { id: "label.session-data", defaultMessage: "Session data" },
funnel: { id: "label.funnel", defaultMessage: "Funnel" },
funnels: { id: "label.funnels", defaultMessage: "Funnels" },
funnelDescription: {
id: 'label.funnel-description',
defaultMessage: 'Understand the conversion and drop-off rate of users.',
id: "label.funnel-description",
defaultMessage: "Understand the conversion and drop-off rate of users.",
},
revenue: { id: 'label.revenue', defaultMessage: 'Revenue' },
revenue: { id: "label.revenue", defaultMessage: "Revenue" },
revenueDescription: {
id: 'label.revenue-description',
defaultMessage: 'Look into your revenue data and how users are spending.',
id: "label.revenue-description",
defaultMessage: "Look into your revenue data and how users are spending.",
},
attribution: { id: 'label.attribution', defaultMessage: 'Attribution' },
attribution: { id: "label.attribution", defaultMessage: "Attribution" },
attributionDescription: {
id: 'label.attribution-description',
defaultMessage: 'See how users engage with your marketing and what drives conversions.',
id: "label.attribution-description",
defaultMessage: "See how users engage with your marketing and what drives conversions.",
},
currency: { id: 'label.currency', defaultMessage: 'Currency' },
model: { id: 'label.model', defaultMessage: 'Model' },
path: { id: 'label.path', defaultMessage: 'Path' },
paths: { id: 'label.paths', defaultMessage: 'Paths' },
add: { id: 'label.add', defaultMessage: 'Add' },
update: { id: 'label.update', defaultMessage: 'Update' },
window: { id: 'label.window', defaultMessage: 'Window' },
runQuery: { id: 'label.run-query', defaultMessage: 'Run query' },
field: { id: 'label.field', defaultMessage: 'Field' },
fields: { id: 'label.fields', defaultMessage: 'Fields' },
createReport: { id: 'label.create-report', defaultMessage: 'Create report' },
description: { id: 'label.description', defaultMessage: 'Description' },
untitled: { id: 'label.untitled', defaultMessage: 'Untitled' },
type: { id: 'label.type', defaultMessage: 'Type' },
filter: { id: 'label.filter', defaultMessage: 'Filter' },
filters: { id: 'label.filters', defaultMessage: 'Filters' },
breakdown: { id: 'label.breakdown', defaultMessage: 'Breakdown' },
true: { id: 'label.true', defaultMessage: 'True' },
false: { id: 'label.false', defaultMessage: 'False' },
is: { id: 'label.is', defaultMessage: 'Is' },
isNot: { id: 'label.is-not', defaultMessage: 'Is not' },
isSet: { id: 'label.is-set', defaultMessage: 'Is set' },
isNotSet: { id: 'label.is-not-set', defaultMessage: 'Is not set' },
greaterThan: { id: 'label.greater-than', defaultMessage: 'Greater than' },
lessThan: { id: 'label.less-than', defaultMessage: 'Less than' },
greaterThanEquals: { id: 'label.greater-than-equals', defaultMessage: 'Greater than or equals' },
lessThanEquals: { id: 'label.less-than-equals', defaultMessage: 'Less than or equals' },
contains: { id: 'label.contains', defaultMessage: 'Contains' },
doesNotContain: { id: 'label.does-not-contain', defaultMessage: 'Does not contain' },
includes: { id: 'label.includes', defaultMessage: 'Includes' },
doesNotInclude: { id: 'label.does-not-include', defaultMessage: 'Does not include' },
before: { id: 'label.before', defaultMessage: 'Before' },
after: { id: 'label.after', defaultMessage: 'After' },
isTrue: { id: 'label.is-true', defaultMessage: 'Is true' },
isFalse: { id: 'label.is-false', defaultMessage: 'Is false' },
exists: { id: 'label.exists', defaultMessage: 'Exists' },
doesNotExist: { id: 'label.doest-not-exist', defaultMessage: 'Does not exist' },
total: { id: 'label.total', defaultMessage: 'Total' },
min: { id: 'label.min', defaultMessage: 'Min' },
max: { id: 'label.max', defaultMessage: 'Max' },
unique: { id: 'label.unique', defaultMessage: 'Unique' },
value: { id: 'label.value', defaultMessage: 'Value' },
overview: { id: 'label.overview', defaultMessage: 'Overview' },
totalRecords: { id: 'label.total-records', defaultMessage: 'Total records' },
insight: { id: 'label.insight', defaultMessage: 'Insight' },
insights: { id: 'label.insights', defaultMessage: 'Insights' },
currency: { id: "label.currency", defaultMessage: "Currency" },
model: { id: "label.model", defaultMessage: "Model" },
path: { id: "label.path", defaultMessage: "Path" },
paths: { id: "label.paths", defaultMessage: "Paths" },
add: { id: "label.add", defaultMessage: "Add" },
update: { id: "label.update", defaultMessage: "Update" },
window: { id: "label.window", defaultMessage: "Window" },
runQuery: { id: "label.run-query", defaultMessage: "Run query" },
field: { id: "label.field", defaultMessage: "Field" },
fields: { id: "label.fields", defaultMessage: "Fields" },
createReport: { id: "label.create-report", defaultMessage: "Create report" },
description: { id: "label.description", defaultMessage: "Description" },
untitled: { id: "label.untitled", defaultMessage: "Untitled" },
type: { id: "label.type", defaultMessage: "Type" },
filter: { id: "label.filter", defaultMessage: "Filter" },
filters: { id: "label.filters", defaultMessage: "Filters" },
breakdown: { id: "label.breakdown", defaultMessage: "Breakdown" },
true: { id: "label.true", defaultMessage: "True" },
false: { id: "label.false", defaultMessage: "False" },
is: { id: "label.is", defaultMessage: "Is" },
isNot: { id: "label.is-not", defaultMessage: "Is not" },
isSet: { id: "label.is-set", defaultMessage: "Is set" },
isNotSet: { id: "label.is-not-set", defaultMessage: "Is not set" },
greaterThan: { id: "label.greater-than", defaultMessage: "Greater than" },
lessThan: { id: "label.less-than", defaultMessage: "Less than" },
greaterThanEquals: { id: "label.greater-than-equals", defaultMessage: "Greater than or equals" },
lessThanEquals: { id: "label.less-than-equals", defaultMessage: "Less than or equals" },
contains: { id: "label.contains", defaultMessage: "Contains" },
doesNotContain: { id: "label.does-not-contain", defaultMessage: "Does not contain" },
includes: { id: "label.includes", defaultMessage: "Includes" },
doesNotInclude: { id: "label.does-not-include", defaultMessage: "Does not include" },
before: { id: "label.before", defaultMessage: "Before" },
after: { id: "label.after", defaultMessage: "After" },
isTrue: { id: "label.is-true", defaultMessage: "Is true" },
isFalse: { id: "label.is-false", defaultMessage: "Is false" },
exists: { id: "label.exists", defaultMessage: "Exists" },
doesNotExist: { id: "label.doest-not-exist", defaultMessage: "Does not exist" },
total: { id: "label.total", defaultMessage: "Total" },
min: { id: "label.min", defaultMessage: "Min" },
max: { id: "label.max", defaultMessage: "Max" },
unique: { id: "label.unique", defaultMessage: "Unique" },
value: { id: "label.value", defaultMessage: "Value" },
overview: { id: "label.overview", defaultMessage: "Overview" },
totalRecords: { id: "label.total-records", defaultMessage: "Total records" },
insight: { id: "label.insight", defaultMessage: "Insight" },
insights: { id: "label.insights", defaultMessage: "Insights" },
insightsDescription: {
id: 'label.insights-description',
defaultMessage: 'Dive deeper into your data by using segments and filters.',
id: "label.insights-description",
defaultMessage: "Dive deeper into your data by using segments and filters.",
},
retention: { id: 'label.retention', defaultMessage: 'Retention' },
retention: { id: "label.retention", defaultMessage: "Retention" },
retentionDescription: {
id: 'label.retention-description',
defaultMessage: 'Measure your website stickiness by tracking how often users return.',
id: "label.retention-description",
defaultMessage: "Measure your website stickiness by tracking how often users return.",
},
dropoff: { id: 'label.dropoff', defaultMessage: 'Dropoff' },
referrer: { id: 'label.referrer', defaultMessage: 'Referrer' },
hostname: { id: 'label.hostname', defaultMessage: 'Hostname' },
country: { id: 'label.country', defaultMessage: 'Country' },
region: { id: 'label.region', defaultMessage: 'Region' },
city: { id: 'label.city', defaultMessage: 'City' },
browser: { id: 'label.browser', defaultMessage: 'Browser' },
device: { id: 'label.device', defaultMessage: 'Device' },
pageTitle: { id: 'label.pageTitle', defaultMessage: 'Page title' },
tag: { id: 'label.tag', defaultMessage: 'Tag' },
segment: { id: 'label.segment', defaultMessage: 'Segment' },
cohort: { id: 'label.cohort', defaultMessage: 'Cohort' },
day: { id: 'label.day', defaultMessage: 'Day' },
date: { id: 'label.date', defaultMessage: 'Date' },
pageOf: { id: 'label.page-of', defaultMessage: 'Page {current} of {total}' },
create: { id: 'label.create', defaultMessage: 'Create' },
search: { id: 'label.search', defaultMessage: 'Search' },
dropoff: { id: "label.dropoff", defaultMessage: "Dropoff" },
referrer: { id: "label.referrer", defaultMessage: "Referrer" },
hostname: { id: "label.hostname", defaultMessage: "Hostname" },
country: { id: "label.country", defaultMessage: "Country" },
region: { id: "label.region", defaultMessage: "Region" },
city: { id: "label.city", defaultMessage: "City" },
browser: { id: "label.browser", defaultMessage: "Browser" },
device: { id: "label.device", defaultMessage: "Device" },
pageTitle: { id: "label.pageTitle", defaultMessage: "Page title" },
tag: { id: "label.tag", defaultMessage: "Tag" },
segment: { id: "label.segment", defaultMessage: "Segment" },
cohort: { id: "label.cohort", defaultMessage: "Cohort" },
day: { id: "label.day", defaultMessage: "Day" },
date: { id: "label.date", defaultMessage: "Date" },
pageOf: { id: "label.page-of", defaultMessage: "Page {current} of {total}" },
create: { id: "label.create", defaultMessage: "Create" },
search: { id: "label.search", defaultMessage: "Search" },
numberOfRecords: {
id: 'label.number-of-records',
defaultMessage: '{x} {x, plural, one {record} other {records}}',
id: "label.number-of-records",
defaultMessage: "{x} {x, plural, one {record} other {records}}",
},
select: { id: 'label.select', defaultMessage: 'Select' },
myAccount: { id: 'label.my-account', defaultMessage: 'My account' },
transfer: { id: 'label.transfer', defaultMessage: 'Transfer' },
transactions: { id: 'label.transactions', defaultMessage: 'Transactions' },
uniqueCustomers: { id: 'label.uniqueCustomers', defaultMessage: 'Unique Customers' },
select: { id: "label.select", defaultMessage: "Select" },
myAccount: { id: "label.my-account", defaultMessage: "My account" },
transfer: { id: "label.transfer", defaultMessage: "Transfer" },
transactions: { id: "label.transactions", defaultMessage: "Transactions" },
uniqueCustomers: { id: "label.uniqueCustomers", defaultMessage: "Unique Customers" },
viewedPage: {
id: 'message.viewed-page',
defaultMessage: 'Viewed page',
id: "message.viewed-page",
defaultMessage: "Viewed page",
},
collectedData: {
id: 'message.collected-data',
defaultMessage: 'Collected data',
id: "message.collected-data",
defaultMessage: "Collected data",
},
triggeredEvent: {
id: 'message.triggered-event',
defaultMessage: 'Triggered event',
id: "message.triggered-event",
defaultMessage: "Triggered event",
},
utm: { id: 'label.utm', defaultMessage: 'UTM' },
utm: { id: "label.utm", defaultMessage: "UTM" },
utmDescription: {
id: 'label.utm-description',
defaultMessage: 'Track your campaigns through UTM parameters.',
id: "label.utm-description",
defaultMessage: "Track your campaigns through UTM parameters.",
},
conversionStep: { id: 'label.conversion-step', defaultMessage: 'Conversion step' },
conversionRate: { id: 'label.conversion-rate', defaultMessage: 'Conversion rate' },
steps: { id: 'label.steps', defaultMessage: 'Steps' },
startStep: { id: 'label.start-step', defaultMessage: 'Start Step' },
endStep: { id: 'label.end-step', defaultMessage: 'End Step' },
addStep: { id: 'label.add-step', defaultMessage: 'Add step' },
goal: { id: 'label.goal', defaultMessage: 'Goal' },
goals: { id: 'label.goals', defaultMessage: 'Goals' },
conversionStep: { id: "label.conversion-step", defaultMessage: "Conversion step" },
conversionRate: { id: "label.conversion-rate", defaultMessage: "Conversion rate" },
steps: { id: "label.steps", defaultMessage: "Steps" },
startStep: { id: "label.start-step", defaultMessage: "Start Step" },
endStep: { id: "label.end-step", defaultMessage: "End Step" },
addStep: { id: "label.add-step", defaultMessage: "Add step" },
goal: { id: "label.goal", defaultMessage: "Goal" },
goals: { id: "label.goals", defaultMessage: "Goals" },
goalsDescription: {
id: 'label.goals-description',
defaultMessage: 'Track your goals for pageviews and events.',
id: "label.goals-description",
defaultMessage: "Track your goals for pageviews and events.",
},
journey: { id: 'label.journey', defaultMessage: 'Journey' },
journeys: { id: 'label.journeys', defaultMessage: 'Journeys' },
journey: { id: "label.journey", defaultMessage: "Journey" },
journeys: { id: "label.journeys", defaultMessage: "Journeys" },
journeyDescription: {
id: 'label.journey-description',
defaultMessage: 'Understand how users navigate through your website.',
id: "label.journey-description",
defaultMessage: "Understand how users navigate through your website.",
},
compareDates: { id: 'label.compare-dates', defaultMessage: 'Compare dates' },
compare: { id: 'label.compare', defaultMessage: 'Compare' },
current: { id: 'label.current', defaultMessage: 'Current' },
previous: { id: 'label.previous', defaultMessage: 'Previous' },
previousPeriod: { id: 'label.previous-period', defaultMessage: 'Previous period' },
previousYear: { id: 'label.previous-year', defaultMessage: 'Previous year' },
lastSeen: { id: 'label.last-seen', defaultMessage: 'Last seen' },
firstSeen: { id: 'label.first-seen', defaultMessage: 'First seen' },
properties: { id: 'label.properties', defaultMessage: 'Properties' },
channel: { id: 'label.channel', defaultMessage: 'Channel' },
channels: { id: 'label.channels', defaultMessage: 'Channels' },
sources: { id: 'label.sources', defaultMessage: 'Sources' },
medium: { id: 'label.medium', defaultMessage: 'Medium' },
campaigns: { id: 'label.campaigns', defaultMessage: 'Campaigns' },
content: { id: 'label.content', defaultMessage: 'Content' },
terms: { id: 'label.terms', defaultMessage: 'Terms' },
direct: { id: 'label.direct', defaultMessage: 'Direct' },
referral: { id: 'label.referral', defaultMessage: 'Referral' },
affiliate: { id: 'label.affiliate', defaultMessage: 'Affiliate' },
email: { id: 'label.email', defaultMessage: 'Email' },
sms: { id: 'label.sms', defaultMessage: 'SMS' },
organicSearch: { id: 'label.organic-search', defaultMessage: 'Organic search' },
organicSocial: { id: 'label.organic-social', defaultMessage: 'Organic social' },
organicShopping: { id: 'label.organic-shopping', defaultMessage: 'Organic shopping' },
organicVideo: { id: 'label.organic-video', defaultMessage: 'Organic video' },
paidAds: { id: 'label.paid-ads', defaultMessage: 'Paid ads' },
paidSearch: { id: 'label.paid-search', defaultMessage: 'Paid search' },
paidSocial: { id: 'label.paid-social', defaultMessage: 'Paid social' },
paidShopping: { id: 'label.paid-shopping', defaultMessage: 'Paid shopping' },
paidVideo: { id: 'label.paid-video', defaultMessage: 'Paid video' },
grouped: { id: 'label.grouped', defaultMessage: 'Grouped' },
other: { id: 'label.other', defaultMessage: 'Other' },
boards: { id: 'label.boards', defaultMessage: 'Boards' },
apply: { id: 'label.apply', defaultMessage: 'Apply' },
link: { id: 'label.link', defaultMessage: 'Link' },
links: { id: 'label.links', defaultMessage: 'Links' },
pixel: { id: 'label.pixel', defaultMessage: 'Pixel' },
pixels: { id: 'label.pixels', defaultMessage: 'Pixels' },
addBoard: { id: 'label.add-board', defaultMessage: 'Add board' },
addLink: { id: 'label.add-link', defaultMessage: 'Add link' },
addPixel: { id: 'label.add-pixel', defaultMessage: 'Add pixel' },
maximize: { id: 'label.maximize', defaultMessage: 'Maximize' },
remaining: { id: 'label.remaining', defaultMessage: 'Remaining' },
conversion: { id: 'label.conversion', defaultMessage: 'Conversion' },
firstClick: { id: 'label.first-click', defaultMessage: 'First click' },
lastClick: { id: 'label.last-click', defaultMessage: 'Last click' },
online: { id: 'label.online', defaultMessage: 'Online' },
preferences: { id: 'label.preferences', defaultMessage: 'Preferences' },
location: { id: 'label.location', defaultMessage: 'Location' },
chart: { id: 'label.chart', defaultMessage: 'Chart' },
table: { id: 'label.table', defaultMessage: 'Table' },
download: { id: 'label.download', defaultMessage: 'Download' },
traffic: { id: 'label.traffic', defaultMessage: 'Traffic' },
behavior: { id: 'label.behavior', defaultMessage: 'Behavior' },
growth: { id: 'label.growth', defaultMessage: 'Growth' },
account: { id: 'label.account', defaultMessage: 'Account' },
application: { id: 'label.application', defaultMessage: 'Application' },
saveSegment: { id: 'label.save-segment', defaultMessage: 'Save as segment' },
saveCohort: { id: 'label.save-cohort', defaultMessage: 'Save as cohort' },
analysis: { id: 'label.analysis', defaultMessage: 'Analysis' },
destinationUrl: { id: 'label.destination-url', defaultMessage: 'Destination URL' },
audience: { id: 'label.audience', defaultMessage: 'Audience' },
invalidUrl: { id: 'label.invalid-url', defaultMessage: 'Invalid URL' },
environment: { id: 'label.environment', defaultMessage: 'Environment' },
criteria: { id: 'label.criteria', defaultMessage: 'Criteria' },
share: { id: 'label.share', defaultMessage: 'Share' },
support: { id: 'label.support', defaultMessage: 'Support' },
documentation: { id: 'label.documentation', defaultMessage: 'Documentation' },
switchAccount: { id: 'label.switch-account', defaultMessage: 'Switch account' },
compareDates: { id: "label.compare-dates", defaultMessage: "Compare dates" },
compare: { id: "label.compare", defaultMessage: "Compare" },
current: { id: "label.current", defaultMessage: "Current" },
previous: { id: "label.previous", defaultMessage: "Previous" },
previousPeriod: { id: "label.previous-period", defaultMessage: "Previous period" },
previousYear: { id: "label.previous-year", defaultMessage: "Previous year" },
lastSeen: { id: "label.last-seen", defaultMessage: "Last seen" },
firstSeen: { id: "label.first-seen", defaultMessage: "First seen" },
properties: { id: "label.properties", defaultMessage: "Properties" },
channel: { id: "label.channel", defaultMessage: "Channel" },
channels: { id: "label.channels", defaultMessage: "Channels" },
sources: { id: "label.sources", defaultMessage: "Sources" },
medium: { id: "label.medium", defaultMessage: "Medium" },
campaigns: { id: "label.campaigns", defaultMessage: "Campaigns" },
content: { id: "label.content", defaultMessage: "Content" },
terms: { id: "label.terms", defaultMessage: "Terms" },
direct: { id: "label.direct", defaultMessage: "Direct" },
referral: { id: "label.referral", defaultMessage: "Referral" },
affiliate: { id: "label.affiliate", defaultMessage: "Affiliate" },
email: { id: "label.email", defaultMessage: "Email" },
sms: { id: "label.sms", defaultMessage: "SMS" },
organicSearch: { id: "label.organic-search", defaultMessage: "Organic search" },
organicSocial: { id: "label.organic-social", defaultMessage: "Organic social" },
organicShopping: { id: "label.organic-shopping", defaultMessage: "Organic shopping" },
organicVideo: { id: "label.organic-video", defaultMessage: "Organic video" },
paidAds: { id: "label.paid-ads", defaultMessage: "Paid ads" },
paidSearch: { id: "label.paid-search", defaultMessage: "Paid search" },
paidSocial: { id: "label.paid-social", defaultMessage: "Paid social" },
paidShopping: { id: "label.paid-shopping", defaultMessage: "Paid shopping" },
paidVideo: { id: "label.paid-video", defaultMessage: "Paid video" },
grouped: { id: "label.grouped", defaultMessage: "Grouped" },
other: { id: "label.other", defaultMessage: "Other" },
boards: { id: "label.boards", defaultMessage: "Boards" },
apply: { id: "label.apply", defaultMessage: "Apply" },
link: { id: "label.link", defaultMessage: "Link" },
links: { id: "label.links", defaultMessage: "Links" },
pixel: { id: "label.pixel", defaultMessage: "Pixel" },
pixels: { id: "label.pixels", defaultMessage: "Pixels" },
addBoard: { id: "label.add-board", defaultMessage: "Add board" },
addLink: { id: "label.add-link", defaultMessage: "Add link" },
addPixel: { id: "label.add-pixel", defaultMessage: "Add pixel" },
maximize: { id: "label.maximize", defaultMessage: "Maximize" },
remaining: { id: "label.remaining", defaultMessage: "Remaining" },
conversion: { id: "label.conversion", defaultMessage: "Conversion" },
firstClick: { id: "label.first-click", defaultMessage: "First click" },
lastClick: { id: "label.last-click", defaultMessage: "Last click" },
online: { id: "label.online", defaultMessage: "Online" },
preferences: { id: "label.preferences", defaultMessage: "Preferences" },
location: { id: "label.location", defaultMessage: "Location" },
chart: { id: "label.chart", defaultMessage: "Chart" },
table: { id: "label.table", defaultMessage: "Table" },
download: { id: "label.download", defaultMessage: "Download" },
traffic: { id: "label.traffic", defaultMessage: "Traffic" },
behavior: { id: "label.behavior", defaultMessage: "Behavior" },
growth: { id: "label.growth", defaultMessage: "Growth" },
account: { id: "label.account", defaultMessage: "Account" },
application: { id: "label.application", defaultMessage: "Application" },
saveSegment: { id: "label.save-segment", defaultMessage: "Save as segment" },
saveCohort: { id: "label.save-cohort", defaultMessage: "Save as cohort" },
analysis: { id: "label.analysis", defaultMessage: "Analysis" },
destinationUrl: { id: "label.destination-url", defaultMessage: "Destination URL" },
audience: { id: "label.audience", defaultMessage: "Audience" },
invalidUrl: { id: "label.invalid-url", defaultMessage: "Invalid URL" },
environment: { id: "label.environment", defaultMessage: "Environment" },
criteria: { id: "label.criteria", defaultMessage: "Criteria" },
share: { id: "label.share", defaultMessage: "Share" },
support: { id: "label.support", defaultMessage: "Support" },
documentation: { id: "label.documentation", defaultMessage: "Documentation" },
switchAccount: { id: "label.switch-account", defaultMessage: "Switch account" },
});
export const messages = defineMessages({
error: { id: 'message.error', defaultMessage: 'Something went wrong.' },
saved: { id: 'message.saved', defaultMessage: 'Saved successfully.' },
noUsers: { id: 'message.no-users', defaultMessage: 'There are no users.' },
userDeleted: { id: 'message.user-deleted', defaultMessage: 'User deleted.' },
noDataAvailable: { id: 'message.no-data-available', defaultMessage: 'No data available.' },
nothingSelected: { id: 'message.nothing-selected', defaultMessage: 'Nothing selected.' },
error: { id: "message.error", defaultMessage: "Something went wrong." },
saved: { id: "message.saved", defaultMessage: "Saved successfully." },
noUsers: { id: "message.no-users", defaultMessage: "There are no users." },
userDeleted: { id: "message.user-deleted", defaultMessage: "User deleted." },
noDataAvailable: { id: "message.no-data-available", defaultMessage: "No data available." },
nothingSelected: { id: "message.nothing-selected", defaultMessage: "Nothing selected." },
confirmReset: {
id: 'message.confirm-reset',
defaultMessage: 'Are you sure you want to reset {target}?',
id: "message.confirm-reset",
defaultMessage: "Are you sure you want to reset {target}?",
},
confirmDelete: {
id: 'message.confirm-delete',
defaultMessage: 'Are you sure you want to delete {target}?',
id: "message.confirm-delete",
defaultMessage: "Are you sure you want to delete {target}?",
},
confirmRemove: {
id: 'message.confirm-remove',
defaultMessage: 'Are you sure you want to remove {target}?',
id: "message.confirm-remove",
defaultMessage: "Are you sure you want to remove {target}?",
},
confirmLeave: {
id: 'message.confirm-leave',
defaultMessage: 'Are you sure you want to leave {target}?',
id: "message.confirm-leave",
defaultMessage: "Are you sure you want to leave {target}?",
},
minPasswordLength: {
id: 'message.min-password-length',
defaultMessage: 'Minimum length of {n} characters',
id: "message.min-password-length",
defaultMessage: "Minimum length of {n} characters",
},
noTeams: {
id: 'message.no-teams',
defaultMessage: 'You have not created any teams.',
id: "message.no-teams",
defaultMessage: "You have not created any teams.",
},
shareUrl: {
id: 'message.share-url',
defaultMessage: 'Your website stats are publicly available at the following URL:',
id: "message.share-url",
defaultMessage: "Your website stats are publicly available at the following URL:",
},
trackingCode: {
id: 'message.tracking-code',
defaultMessage:
'To track stats for this website, place the following code in the <head>...</head> section of your HTML.',
id: "message.tracking-code",
defaultMessage: "To track stats for this website, place the following code in the <head>...</head> section of your HTML.",
},
joinTeamWarning: {
id: 'message.team-already-member',
defaultMessage: 'You are already a member of the team.',
id: "message.team-already-member",
defaultMessage: "You are already a member of the team.",
},
actionConfirmation: {
id: 'message.action-confirmation',
defaultMessage: 'Type {confirmation} in the box below to confirm.',
id: "message.action-confirmation",
defaultMessage: "Type {confirmation} in the box below to confirm.",
},
resetWebsite: {
id: 'message.reset-website',
defaultMessage: 'To reset this website, type {confirmation} in the box below to confirm.',
id: "message.reset-website",
defaultMessage: "To reset this website, type {confirmation} in the box below to confirm.",
},
invalidDomain: {
id: 'message.invalid-domain',
defaultMessage: 'Invalid domain. Do not include http/https.',
id: "message.invalid-domain",
defaultMessage: "Invalid domain. Do not include http/https.",
},
resetWebsiteWarning: {
id: 'message.reset-website-warning',
defaultMessage:
'All statistics for this website will be deleted, but your settings will remain intact.',
id: "message.reset-website-warning",
defaultMessage: "All statistics for this website will be deleted, but your settings will remain intact.",
},
deleteWebsiteWarning: {
id: 'message.delete-website-warning',
defaultMessage: 'All website data will be deleted.',
id: "message.delete-website-warning",
defaultMessage: "All website data will be deleted.",
},
deleteTeamWarning: {
id: 'message.delete-team-warning',
defaultMessage: 'Deleting a team will also delete all team websites.',
id: "message.delete-team-warning",
defaultMessage: "Deleting a team will also delete all team websites.",
},
noResultsFound: {
id: 'message.no-results-found',
defaultMessage: 'No results found.',
id: "message.no-results-found",
defaultMessage: "No results found.",
},
noWebsitesConfigured: {
id: 'message.no-websites-configured',
defaultMessage: 'You do not have any websites configured.',
id: "message.no-websites-configured",
defaultMessage: "You do not have any websites configured.",
},
noTeamWebsites: {
id: 'message.no-team-websites',
defaultMessage: 'This team does not have any websites.',
id: "message.no-team-websites",
defaultMessage: "This team does not have any websites.",
},
teamWebsitesInfo: {
id: 'message.team-websites-info',
defaultMessage: 'Websites can be viewed by anyone on the team.',
id: "message.team-websites-info",
defaultMessage: "Websites can be viewed by anyone on the team.",
},
noMatchPassword: { id: 'message.no-match-password', defaultMessage: 'Passwords do not match.' },
noMatchPassword: { id: "message.no-match-password", defaultMessage: "Passwords do not match." },
goToSettings: {
id: 'message.go-to-settings',
defaultMessage: 'Go to settings',
id: "message.go-to-settings",
defaultMessage: "Go to settings",
},
activeUsers: {
id: 'message.active-users',
defaultMessage: '{x} current {x, plural, one {visitor} other {visitors}}',
id: "message.active-users",
defaultMessage: "{x} current {x, plural, one {visitor} other {visitors}}",
},
teamNotFound: {
id: 'message.team-not-found',
defaultMessage: 'Team not found.',
id: "message.team-not-found",
defaultMessage: "Team not found.",
},
visitorLog: {
id: 'message.visitor-log',
defaultMessage: 'Visitor from {country} using {browser} on {os} {device}',
id: "message.visitor-log",
defaultMessage: "Visitor from {country} using {browser} on {os} {device}",
},
eventLog: {
id: 'message.event-log',
defaultMessage: '{event} on {url}',
id: "message.event-log",
defaultMessage: "{event} on {url}",
},
incorrectUsernamePassword: {
id: 'message.incorrect-username-password',
defaultMessage: 'Incorrect username and/or password.',
id: "message.incorrect-username-password",
defaultMessage: "Incorrect username and/or password.",
},
noEventData: {
id: 'message.no-event-data',
defaultMessage: 'No event data is available.',
id: "message.no-event-data",
defaultMessage: "No event data is available.",
},
newVersionAvailable: {
id: 'message.new-version-available',
defaultMessage: 'A new version of Umami {version} is available!',
id: "message.new-version-available",
defaultMessage: "A new version of Syncfuse {version} is available!",
},
transferWebsite: {
id: 'message.transfer-website',
defaultMessage: 'Transfer website ownership to your account or another team.',
id: "message.transfer-website",
defaultMessage: "Transfer website ownership to your account or another team.",
},
transferTeamWebsiteToUser: {
id: 'message.transfer-team-website-to-user',
defaultMessage: 'Transfer this website to your account?',
id: "message.transfer-team-website-to-user",
defaultMessage: "Transfer this website to your account?",
},
transferUserWebsiteToTeam: {
id: 'message.transfer-user-website-to-team',
defaultMessage: 'Select the team to transfer this website to.',
id: "message.transfer-user-website-to-team",
defaultMessage: "Select the team to transfer this website to.",
},
unauthorized: {
id: 'message.unauthorized',
defaultMessage: 'Unauthorized',
id: "message.unauthorized",
defaultMessage: "Unauthorized",
},
badRequest: {
id: 'message.bad-request',
defaultMessage: 'Bad request',
id: "message.bad-request",
defaultMessage: "Bad request",
},
forbidden: {
id: 'message.forbidden',
defaultMessage: 'Forbidden',
id: "message.forbidden",
defaultMessage: "Forbidden",
},
notFound: {
id: 'message.not-found',
defaultMessage: 'Not found',
id: "message.not-found",
defaultMessage: "Not found",
},
serverError: {
id: 'message.sever-error',
defaultMessage: 'Server error',
id: "message.sever-error",
defaultMessage: "Server error",
},
});

40
src/declaration.d.ts vendored
View file

@ -1,23 +1,23 @@
declare module '*.css';
declare module '*.svg';
declare module '*.json';
declare module 'bcryptjs';
declare module 'chartjs-adapter-date-fns';
declare module 'cors';
declare module 'date-fns-tz';
declare module 'debug';
declare module 'fs-extra';
declare module 'jsonwebtoken';
declare module 'md5';
declare module 'papaparse';
declare module 'prettier';
declare module 'react-simple-maps';
declare module 'semver';
declare module 'tsup';
declare module 'uuid';
declare module '@umami/esbuild-plugin-css-modules';
declare module "*.css";
declare module "*.svg";
declare module "*.json";
declare module "bcryptjs";
declare module "chartjs-adapter-date-fns";
declare module "cors";
declare module "date-fns-tz";
declare module "debug";
declare module "fs-extra";
declare module "jsonwebtoken";
declare module "md5";
declare module "papaparse";
declare module "prettier";
declare module "react-simple-maps";
declare module "semver";
declare module "tsup";
declare module "uuid";
declare module "@umami/esbuild-plugin-css-modules";
interface UmamiTracker {
interface SyncfuseTracker {
track: {
(): Promise<string>;
(eventName: string): Promise<string>;
@ -29,5 +29,5 @@ interface UmamiTracker {
}
interface Window {
umami: UmamiTracker;
syncfuse: SyncfuseTracker;
}

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "اسم المستخدم او كلمة المرور غير صحيحة.",
"message.invalid-domain": "النطاق غير صحيح",
"message.min-password-length": "اقل عدد مسموح به {n} حرف/أحرف",
"message.new-version-available": "إصدار جديد من Umami {version} متاح!",
"message.new-version-available": "إصدار جديد من Syncfuse {version} متاح!",
"message.no-data-available": "لا توجد بيانات متاحة.",
"message.no-event-data": "لا توجد بيانات الحدث متاحة.",
"message.no-match-password": "كلمة المرور غير متطابقة",

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "Некарэктнае імя карыстальніка/пароль.",
"message.invalid-domain": "Некарэктны дамен",
"message.min-password-length": "Мінімальная даўжыня {n} знакаў",
"message.new-version-available": "Даступная новая версія Umami {version}!",
"message.new-version-available": "Даступная новая версія Syncfuse {version}!",
"message.no-data-available": "Няма дадзеных.",
"message.no-event-data": "Дадзеныя падзеі недаступныя.",
"message.no-match-password": "Паролі не супадаюць",

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "Неправилно потребителско име и/или парола.",
"message.invalid-domain": "Невалиден домейн. Не включвайте http/https.",
"message.min-password-length": "Минимална дължина от {n} символа",
"message.new-version-available": "Има нова версия на Umami {version}!",
"message.new-version-available": "Има нова версия на Syncfuse {version}!",
"message.no-data-available": "Няма налични данни.",
"message.no-event-data": "Няма налични данни за събитие.",
"message.no-match-password": "Паролите не съвпадат.",

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "ভুল ব্যবহারকারীর নাম/পাসওয়ার্ড।",
"message.invalid-domain": "ভুল ডোমেন",
"message.min-password-length": "Minimum length of {n} characters",
"message.new-version-available": "A new version of Umami {version} is available!",
"message.new-version-available": "A new version of Syncfuse {version} is available!",
"message.no-data-available": "কোন তথ্য নেই।",
"message.no-event-data": "No event data is available.",
"message.no-match-password": "পাসওয়ার্ড মেলে না",

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "Pogrešno korisničko ime i/ili šifra.",
"message.invalid-domain": "Nevalidna domena. Ne uključujte http/https.",
"message.min-password-length": "Minimalna dužina od {n} karaktera",
"message.new-version-available": "Nova verzija Umami {version} je dostupna!",
"message.new-version-available": "Nova verzija Syncfuse {version} je dostupna!",
"message.no-data-available": "Nema dostupnih podataka.",
"message.no-event-data": "Nema dostupnih podataka o događajima.",
"message.no-match-password": "Šifre se ne poklapaju.",

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "Nom d'usuari o contrasenya incorrectes.",
"message.invalid-domain": "Domini invàlid",
"message.min-password-length": "Longitud mínima de {n} caràcters",
"message.new-version-available": "Una nova versió d'Umami {version} està disponible!",
"message.new-version-available": "Una nova versió d'Syncfuse {version} està disponible!",
"message.no-data-available": "No hi ha dades disponibles.",
"message.no-event-data": "No hi ha dades d'esdeveniments disponibles.",
"message.no-match-password": "Les contrasenyes no coincideixen",

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "Nesprávné jméno/heslo.",
"message.invalid-domain": "Neplatná doména",
"message.min-password-length": "Minimum length of {n} characters",
"message.new-version-available": "A new version of Umami {version} is available!",
"message.new-version-available": "A new version of Syncfuse {version} is available!",
"message.no-data-available": "Žádná data.",
"message.no-event-data": "No event data is available.",
"message.no-match-password": "Hesla se neschodují",

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "Ugyldigt brugernavn/adgangskode.",
"message.invalid-domain": "Ugyldigt domæne",
"message.min-password-length": "Minimum length of {n} characters",
"message.new-version-available": "A new version of Umami {version} is available!",
"message.new-version-available": "A new version of Syncfuse {version} is available!",
"message.no-data-available": "Ingen data tilgængelig.",
"message.no-event-data": "No event data is available.",
"message.no-match-password": "Adgangskoderne matcher ikke",

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "Falsches Passwort oder Benutzername.",
"message.invalid-domain": "Ungültigi Domain",
"message.min-password-length": "Miminamli längi vo {n} Zeiche",
"message.new-version-available": "Es isch en neue Version vo Umami {version} verfügbar!",
"message.new-version-available": "Es isch en neue Version vo Syncfuse {version} verfügbar!",
"message.no-data-available": "Kei Date vorhande.",
"message.no-event-data": "Es sind kei Event Date verfügbar.",
"message.no-match-password": "Passwörter stimmed ned überi",

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "Falsches Passwort oder Benutzername.",
"message.invalid-domain": "Ungültige Domain",
"message.min-password-length": "Minimale Länge von {n} Zeichen",
"message.new-version-available": "Eine neue Version von Umami ist verfügbar: {version}",
"message.new-version-available": "Eine neue Version von Syncfuse ist verfügbar: {version}",
"message.no-data-available": "Keine Daten vorhanden.",
"message.no-event-data": "Es sind keine Ereignisdaten verfügbar.",
"message.no-match-password": "Passwörter stimmen nicht überein",

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "Εσφαλμένο όνομα χρήστη / κωδικός πρόσβασης.",
"message.invalid-domain": "Μη έγκυρος τομέας",
"message.min-password-length": "Minimum length of {n} characters",
"message.new-version-available": "A new version of Umami {version} is available!",
"message.new-version-available": "A new version of Syncfuse {version} is available!",
"message.no-data-available": "Δεν υπάρχουν διαθέσιμα δεδομένα.",
"message.no-event-data": "No event data is available.",
"message.no-match-password": "Οι κωδικοί πρόσβασης δεν ταιριάζουν",

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "Incorrect username/password.",
"message.invalid-domain": "Invalid domain",
"message.min-password-length": "Minimum length of {n} characters",
"message.new-version-available": "A new version of Umami {version} is available!",
"message.new-version-available": "A new version of Syncfuse {version} is available!",
"message.no-data-available": "No data available.",
"message.no-event-data": "No event data is available.",
"message.no-match-password": "Passwords don't match",

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "Incorrect username and/or password.",
"message.invalid-domain": "Invalid domain. Do not include http/https.",
"message.min-password-length": "Minimum length of {n} characters",
"message.new-version-available": "A new version of Umami {version} is available!",
"message.new-version-available": "A new version of Syncfuse {version} is available!",
"message.no-data-available": "No data available.",
"message.no-event-data": "No event data is available.",
"message.no-match-password": "Passwords do not match.",

Some files were not shown because too many files have changed in this diff Show more