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' name: "🐛 Bug Report"
description: Create a bug report for Umami. description: Create a bug report for Syncfuse.
body: body:
- type: textarea - type: textarea
attributes: attributes:
@ -14,7 +14,7 @@ body:
options: options:
- PostgreSQL - PostgreSQL
- MySQL - MySQL
- Umami Cloud - Syncfuse Cloud
validations: validations:
required: true required: true
- type: textarea - type: textarea
@ -24,13 +24,13 @@ body:
render: shell render: shell
- type: input - type: input
attributes: attributes:
label: Which Umami version are you using? (if relevant) label: Which Syncfuse version are you using? (if relevant)
description: 'For example: 2.18.0, 2.15.1, 1.39.0, etc' description: "For example: 2.18.0, 2.15.1, 1.39.0, etc"
- type: input - type: input
attributes: attributes:
label: Which browser are you using? (if relevant) label: Which browser are you using? (if relevant)
description: 'For example: Chrome, Edge, Firefox, etc' description: "For example: Chrome, Edge, Firefox, etc"
- type: input - type: input
attributes: attributes:
label: How are you deploying your application? (if relevant) 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' name: "✨ Feature Request"
description: Create a feature or enhancement request for Umami. description: Create a feature or enhancement request for Syncfuse.
body: body:
- type: textarea - type: textarea
attributes: attributes:

View file

@ -1,6 +1,6 @@
MIT License 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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal 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"> <img src="https://content.umami.is/website/images/umami-logo.png" alt="Umami Logo" width="100">
</p> </p>
<h1 align="center">Umami</h1> <h1 align="center">Syncfuse a</h1>
<p align="center"> <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>
<p align="center"> <p align="center">
@ -38,7 +38,7 @@ cd umami
pnpm install pnpm install
``` ```
### Configure Umami ### Configure Syncfuse
Create an `.env` file with the following: Create an `.env` file with the following:
@ -58,7 +58,7 @@ postgresql://username:mypassword@localhost:5432/mydb
pnpm run build 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 ### Start the Application
@ -72,7 +72,7 @@ By default, this will launch the application on `http://localhost:3000`. You wil
## 🐳 Installing with Docker ## 🐳 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: Docker image:
@ -80,7 +80,7 @@ Docker image:
docker pull docker.umami.is/umami-software/umami:latest 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 ```bash
docker compose up -d docker compose up -d

View file

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

View file

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

View file

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

View file

@ -1,191 +1,191 @@
describe('Team API tests', () => { describe("Team API tests", () => {
Cypress.session.clearAllSavedSessions(); Cypress.session.clearAllSavedSessions();
let teamId; let teamId;
let userId; let userId;
before(() => { before(() => {
cy.login(Cypress.env('umami_user'), Cypress.env('umami_password')); cy.login(Cypress.env("syncfuse_user"), Cypress.env("syncfuse_password"));
cy.fixture('users').then(data => { cy.fixture("users").then((data) => {
const userCreate = data.userCreate; const userCreate = data.userCreate;
cy.request({ cy.request({
method: 'POST', method: "POST",
url: '/api/users', url: "/api/users",
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
body: userCreate, body: userCreate,
}).then(response => { }).then((response) => {
userId = response.body.id; userId = response.body.id;
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
expect(response.body).to.have.property('username', 'cypress1'); expect(response.body).to.have.property("username", "cypress1");
expect(response.body).to.have.property('role', 'user'); expect(response.body).to.have.property("role", "user");
}); });
}); });
}); });
it('Creates a team.', () => { it("Creates a team.", () => {
cy.fixture('teams').then(data => { cy.fixture("teams").then((data) => {
const teamCreate = data.teamCreate; const teamCreate = data.teamCreate;
cy.request({ cy.request({
method: 'POST', method: "POST",
url: '/api/teams', url: "/api/teams",
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
body: teamCreate, body: teamCreate,
}).then(response => { }).then((response) => {
teamId = response.body[0].id; teamId = response.body[0].id;
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
expect(response.body[0]).to.have.property('name', 'cypress'); expect(response.body[0]).to.have.property("name", "cypress");
expect(response.body[1]).to.have.property('role', 'team-owner'); expect(response.body[1]).to.have.property("role", "team-owner");
}); });
}); });
}); });
it('Gets a teams by ID.', () => { it("Gets a teams by ID.", () => {
cy.request({ cy.request({
method: 'GET', method: "GET",
url: `/api/teams/${teamId}`, url: `/api/teams/${teamId}`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); 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.', () => { it("Updates a team.", () => {
cy.fixture('teams').then(data => { cy.fixture("teams").then((data) => {
const teamUpdate = data.teamUpdate; const teamUpdate = data.teamUpdate;
cy.request({ cy.request({
method: 'POST', method: "POST",
url: `/api/teams/${teamId}`, url: `/api/teams/${teamId}`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
body: teamUpdate, body: teamUpdate,
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
expect(response.body).to.have.property('id', teamId); expect(response.body).to.have.property("id", teamId);
expect(response.body).to.have.property('name', 'cypressUpdate'); 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({ cy.request({
method: 'GET', method: "GET",
url: `/api/teams/${teamId}/users`, url: `/api/teams/${teamId}/users`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
expect(response.body.data[0]).to.have.property('id'); 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("teamId");
expect(response.body.data[0]).to.have.property('userId'); 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("user");
}); });
}); });
it('Get a user belonging to a team.', () => { it("Get a user belonging to a team.", () => {
cy.request({ cy.request({
method: 'GET', method: "GET",
url: `/api/teams/${teamId}/users/${Cypress.env('umami_user_id')}`, url: `/api/teams/${teamId}/users/${Cypress.env("syncfuse_user_id")}`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
expect(response.body).to.have.property('teamId'); expect(response.body).to.have.property("teamId");
expect(response.body).to.have.property('userId'); expect(response.body).to.have.property("userId");
expect(response.body).to.have.property('role'); 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({ cy.request({
method: 'GET', method: "GET",
url: `/api/teams/${teamId}/websites`, url: `/api/teams/${teamId}/websites`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); 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({ cy.request({
method: 'POST', method: "POST",
url: `/api/teams/${teamId}/users`, url: `/api/teams/${teamId}/users`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
body: { body: {
userId, userId,
role: 'team-member', role: "team-member",
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
expect(response.body).to.have.property('userId', userId); expect(response.body).to.have.property("userId", userId);
expect(response.body).to.have.property('role', 'team-member'); expect(response.body).to.have.property("role", "team-member");
}); });
}); });
it(`Update a user's role on a team.`, () => { it(`Update a user's role on a team.`, () => {
cy.request({ cy.request({
method: 'POST', method: "POST",
url: `/api/teams/${teamId}/users/${userId}`, url: `/api/teams/${teamId}/users/${userId}`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
body: { body: {
role: 'team-view-only', role: "team-view-only",
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
expect(response.body).to.have.property('userId', userId); expect(response.body).to.have.property("userId", userId);
expect(response.body).to.have.property('role', 'team-view-only'); expect(response.body).to.have.property("role", "team-view-only");
}); });
}); });
it(`Remove a user from a team.`, () => { it(`Remove a user from a team.`, () => {
cy.request({ cy.request({
method: 'DELETE', method: "DELETE",
url: `/api/teams/${teamId}/users/${userId}`, url: `/api/teams/${teamId}/users/${userId}`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
}); });
}); });
it('Deletes a team.', () => { it("Deletes a team.", () => {
cy.request({ cy.request({
method: 'DELETE', method: "DELETE",
url: `/api/teams/${teamId}`, url: `/api/teams/${teamId}`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); 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(); Cypress.session.clearAllSavedSessions();
before(() => { before(() => {
cy.login(Cypress.env('umami_user'), Cypress.env('umami_password')); cy.login(Cypress.env("syncfuse_user"), Cypress.env("syncfuse_password"));
}); });
let userId; let userId;
it('Creates a user.', () => { it("Creates a user.", () => {
cy.fixture('users').then(data => { cy.fixture("users").then((data) => {
const userCreate = data.userCreate; const userCreate = data.userCreate;
cy.request({ cy.request({
method: 'POST', method: "POST",
url: '/api/users', url: "/api/users",
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
body: userCreate, body: userCreate,
}).then(response => { }).then((response) => {
userId = response.body.id; userId = response.body.id;
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
expect(response.body).to.have.property('username', 'cypress1'); expect(response.body).to.have.property("username", "cypress1");
expect(response.body).to.have.property('role', 'user'); 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({ cy.request({
method: 'GET', method: "GET",
url: '/api/admin/users', url: "/api/admin/users",
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
expect(response.body.data[0]).to.have.property('id'); 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("username");
expect(response.body.data[0]).to.have.property('password'); 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("role");
}); });
}); });
it('Updates a user.', () => { it("Updates a user.", () => {
cy.fixture('users').then(data => { cy.fixture("users").then((data) => {
const userUpdate = data.userUpdate; const userUpdate = data.userUpdate;
cy.request({ cy.request({
method: 'POST', method: "POST",
url: `/api/users/${userId}`, url: `/api/users/${userId}`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
body: userUpdate, body: userUpdate,
}).then(response => { }).then((response) => {
userId = response.body.id; userId = response.body.id;
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
expect(response.body).to.have.property('id', userId); expect(response.body).to.have.property("id", userId);
expect(response.body).to.have.property('username', 'cypress1'); expect(response.body).to.have.property("username", "cypress1");
expect(response.body).to.have.property('role', 'view-only'); expect(response.body).to.have.property("role", "view-only");
}); });
}); });
}); });
it('Gets a user by ID.', () => { it("Gets a user by ID.", () => {
cy.request({ cy.request({
method: 'GET', method: "GET",
url: `/api/users/${userId}`, url: `/api/users/${userId}`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
expect(response.body).to.have.property('id', userId); expect(response.body).to.have.property("id", userId);
expect(response.body).to.have.property('username', 'cypress1'); expect(response.body).to.have.property("username", "cypress1");
expect(response.body).to.have.property('role', 'view-only'); expect(response.body).to.have.property("role", "view-only");
}); });
}); });
it('Deletes a user.', () => { it("Deletes a user.", () => {
cy.request({ cy.request({
method: 'DELETE', method: "DELETE",
url: `/api/users/${userId}`, url: `/api/users/${userId}`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); 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({ cy.request({
method: 'GET', method: "GET",
url: `/api/users/${userId}/websites`, url: `/api/users/${userId}/websites`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); 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({ cy.request({
method: 'GET', method: "GET",
url: `/api/users/${userId}/teams`, url: `/api/users/${userId}/teams`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); 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(); Cypress.session.clearAllSavedSessions();
let websiteId; let websiteId;
let teamId; let teamId;
before(() => { before(() => {
cy.login(Cypress.env('umami_user'), Cypress.env('umami_password')); cy.login(Cypress.env("syncfuse_user"), Cypress.env("syncfuse_password"));
cy.fixture('teams').then(data => { cy.fixture("teams").then((data) => {
const teamCreate = data.teamCreate; const teamCreate = data.teamCreate;
cy.request({ cy.request({
method: 'POST', method: "POST",
url: '/api/teams', url: "/api/teams",
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
body: teamCreate, body: teamCreate,
}).then(response => { }).then((response) => {
teamId = response.body[0].id; teamId = response.body[0].id;
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
expect(response.body[0]).to.have.property('name', 'cypress'); expect(response.body[0]).to.have.property("name", "cypress");
expect(response.body[1]).to.have.property('role', 'team-owner'); expect(response.body[1]).to.have.property("role", "team-owner");
}); });
}); });
}); });
it('Creates a website for user.', () => { it("Creates a website for user.", () => {
cy.fixture('websites').then(data => { cy.fixture("websites").then((data) => {
const websiteCreate = data.websiteCreate; const websiteCreate = data.websiteCreate;
cy.request({ cy.request({
method: 'POST', method: "POST",
url: '/api/websites', url: "/api/websites",
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
body: websiteCreate, body: websiteCreate,
}).then(response => { }).then((response) => {
websiteId = response.body.id; websiteId = response.body.id;
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
expect(response.body).to.have.property('name', 'Cypress Website'); expect(response.body).to.have.property("name", "Cypress Website");
expect(response.body).to.have.property('domain', 'cypress.com'); expect(response.body).to.have.property("domain", "cypress.com");
}); });
}); });
}); });
it('Creates a website for team.', () => { it("Creates a website for team.", () => {
cy.request({ cy.request({
method: 'POST', method: "POST",
url: '/api/websites', url: "/api/websites",
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
body: { body: {
name: 'Team Website', name: "Team Website",
domain: 'teamwebsite.com', domain: "teamwebsite.com",
teamId: teamId, teamId: teamId,
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
expect(response.body).to.have.property('name', 'Team Website'); expect(response.body).to.have.property("name", "Team Website");
expect(response.body).to.have.property('domain', 'teamwebsite.com'); expect(response.body).to.have.property("domain", "teamwebsite.com");
}); });
}); });
it('Creates a website with a fixed ID.', () => { it("Creates a website with a fixed ID.", () => {
cy.fixture('websites').then(data => { cy.fixture("websites").then((data) => {
const websiteCreate = data.websiteCreate; const websiteCreate = data.websiteCreate;
const fixedId = uuid(); const fixedId = uuid();
cy.request({ cy.request({
method: 'POST', method: "POST",
url: '/api/websites', url: "/api/websites",
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
body: { ...websiteCreate, id: fixedId }, body: { ...websiteCreate, id: fixedId },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
expect(response.body).to.have.property('id', fixedId); expect(response.body).to.have.property("id", fixedId);
expect(response.body).to.have.property('name', 'Cypress Website'); expect(response.body).to.have.property("name", "Cypress Website");
expect(response.body).to.have.property('domain', 'cypress.com'); expect(response.body).to.have.property("domain", "cypress.com");
// cleanup // cleanup
cy.request({ cy.request({
method: 'DELETE', method: "DELETE",
url: `/api/websites/${fixedId}`, url: `/api/websites/${fixedId}`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}); });
}); });
}); });
}); });
it('Returns all tracked websites.', () => { it("Returns all tracked websites.", () => {
cy.request({ cy.request({
method: 'GET', method: "GET",
url: '/api/websites', url: "/api/websites",
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
expect(response.body.data[0]).to.have.property('id'); 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("name");
expect(response.body.data[0]).to.have.property('domain'); expect(response.body.data[0]).to.have.property("domain");
}); });
}); });
it('Gets a website by ID.', () => { it("Gets a website by ID.", () => {
cy.request({ cy.request({
method: 'GET', method: "GET",
url: `/api/websites/${websiteId}`, url: `/api/websites/${websiteId}`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
expect(response.body).to.have.property('name', 'Cypress Website'); expect(response.body).to.have.property("name", "Cypress Website");
expect(response.body).to.have.property('domain', 'cypress.com'); expect(response.body).to.have.property("domain", "cypress.com");
}); });
}); });
it('Updates a website.', () => { it("Updates a website.", () => {
cy.fixture('websites').then(data => { cy.fixture("websites").then((data) => {
const websiteUpdate = data.websiteUpdate; const websiteUpdate = data.websiteUpdate;
cy.request({ cy.request({
method: 'POST', method: "POST",
url: `/api/websites/${websiteId}`, url: `/api/websites/${websiteId}`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
body: websiteUpdate, body: websiteUpdate,
}).then(response => { }).then((response) => {
websiteId = response.body.id; websiteId = response.body.id;
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
expect(response.body).to.have.property('name', 'Cypress Website Updated'); 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("domain", "cypressupdated.com");
}); });
}); });
}); });
it('Updates a website with only shareId.', () => { it("Updates a website with only shareId.", () => {
cy.request({ cy.request({
method: 'POST', method: "POST",
url: `/api/websites/${websiteId}`, url: `/api/websites/${websiteId}`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
body: { shareId: 'ABCDEF' }, body: { shareId: "ABCDEF" },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); 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({ cy.request({
method: 'POST', method: "POST",
url: `/api/websites/${websiteId}/reset`, url: `/api/websites/${websiteId}/reset`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); 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({ cy.request({
method: 'DELETE', method: "DELETE",
url: `/api/websites/${websiteId}`, url: `/api/websites/${websiteId}`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); 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(() => { beforeEach(() => {
cy.visit('/login'); cy.visit("/login");
}); });
it( it(
'logs user in with correct credentials and logs user out', "logs user in with correct credentials and logs user out",
{ {
defaultCommandTimeout: 10000, defaultCommandTimeout: 10000,
}, },
() => { () => {
cy.getDataTest('input-username').find('input').as('inputUsername').click(); cy.getDataTest("input-username").find("input").as("inputUsername").click();
cy.get('@inputUsername').type(Cypress.env('umami_user'), { delay: 0 }); cy.get("@inputUsername").type(Cypress.env("syncfuse_user"), { delay: 0 });
cy.get('@inputUsername').click(); cy.get("@inputUsername").click();
cy.getDataTest('input-password') cy.getDataTest("input-password").find("input").type(Cypress.env("syncfuse_password"), { delay: 0 });
.find('input') cy.getDataTest("button-submit").click();
.type(Cypress.env('umami_password'), { delay: 0 }); cy.url().should("eq", Cypress.config().baseUrl + "/dashboard");
cy.getDataTest('button-submit').click();
cy.url().should('eq', Cypress.config().baseUrl + '/dashboard');
cy.logout(); cy.logout();
}, },
); );
it('login with blank inputs or incorrect credentials', () => { it("login with blank inputs or incorrect credentials", () => {
cy.getDataTest('button-submit').click(); cy.getDataTest("button-submit").click();
cy.contains(/Required/i).should('be.visible'); cy.contains(/Required/i).should("be.visible");
cy.getDataTest('input-username').find('input').as('inputUsername'); cy.getDataTest("input-username").find("input").as("inputUsername");
cy.get('@inputUsername').click(); cy.get("@inputUsername").click();
cy.get('@inputUsername').type(Cypress.env('umami_user'), { delay: 0 }); cy.get("@inputUsername").type(Cypress.env("syncfuse_user"), { delay: 0 });
cy.get('@inputUsername').click(); cy.get("@inputUsername").click();
cy.getDataTest('input-password').find('input').type('wrongpassword', { delay: 0 }); cy.getDataTest("input-password").find("input").type("wrongpassword", { delay: 0 });
cy.getDataTest('button-submit').click(); cy.getDataTest("button-submit").click();
cy.contains(/Incorrect username and\/or password./i).should('be.visible'); 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(); Cypress.session.clearAllSavedSessions();
beforeEach(() => { beforeEach(() => {
cy.login(Cypress.env('umami_user'), Cypress.env('umami_password')); cy.login(Cypress.env("syncfuse_user"), Cypress.env("syncfuse_password"));
cy.visit('/settings/users'); cy.visit("/settings/users");
}); });
it('Add a User', () => { it("Add a User", () => {
// add user // add user
cy.contains(/Create user/i).should('be.visible'); cy.contains(/Create user/i).should("be.visible");
cy.getDataTest('button-create-user').click(); cy.getDataTest("button-create-user").click();
cy.getDataTest('input-username').find('input').as('inputName').click(); cy.getDataTest("input-username").find("input").as("inputName").click();
cy.get('@inputName').type('Test-user', { delay: 0 }); cy.get("@inputName").type("Test-user", { delay: 0 });
cy.getDataTest('input-password').find('input').as('inputPassword').click(); cy.getDataTest("input-password").find("input").as("inputPassword").click();
cy.get('@inputPassword').type('testPasswordCypress', { delay: 0 }); cy.get("@inputPassword").type("testPasswordCypress", { delay: 0 });
cy.getDataTest('dropdown-role').click(); cy.getDataTest("dropdown-role").click();
cy.getDataTest('dropdown-item-user').click(); cy.getDataTest("dropdown-item-user").click();
cy.getDataTest('button-submit').click(); cy.getDataTest("button-submit").click();
cy.get('td[label="Username"]').should('contain.text', 'Test-user'); cy.get('td[label="Username"]').should("contain.text", "Test-user");
cy.get('td[label="Role"]').should('contain.text', '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 // edit user
cy.get('table tbody tr') cy.get("table tbody tr")
.contains('td', /Test-user/i) .contains("td", /Test-user/i)
.parent() .parent()
.within(() => { .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.getDataTest("input-password").find("input").as("inputPassword").click();
cy.get('@inputPassword').type('newPassword', { delay: 0 }); cy.get("@inputPassword").type("newPassword", { delay: 0 });
cy.getDataTest('dropdown-role').click(); cy.getDataTest("dropdown-role").click();
cy.getDataTest('dropdown-item-viewOnly').click(); cy.getDataTest("dropdown-item-viewOnly").click();
cy.getDataTest('button-submit').click(); cy.getDataTest("button-submit").click();
cy.visit('/settings/users'); cy.visit("/settings/users");
cy.get('table tbody tr') cy.get("table tbody tr")
.contains('td', /Test-user/i) .contains("td", /Test-user/i)
.parent() .parent()
.should('contain.text', 'View only'); .should("contain.text", "View only");
cy.logout(); cy.logout();
cy.url().should('eq', Cypress.config().baseUrl + '/login'); cy.url().should("eq", Cypress.config().baseUrl + "/login");
cy.getDataTest('input-username').find('input').as('inputUsername').click(); cy.getDataTest("input-username").find("input").as("inputUsername").click();
cy.get('@inputUsername').type('Test-user', { delay: 0 }); cy.get("@inputUsername").type("Test-user", { delay: 0 });
cy.get('@inputUsername').click(); cy.get("@inputUsername").click();
cy.getDataTest('input-password').find('input').type('newPassword', { delay: 0 }); cy.getDataTest("input-password").find("input").type("newPassword", { delay: 0 });
cy.getDataTest('button-submit').click(); cy.getDataTest("button-submit").click();
cy.url().should('eq', Cypress.config().baseUrl + '/dashboard'); cy.url().should("eq", Cypress.config().baseUrl + "/dashboard");
}); });
it('Delete a user', () => { it("Delete a user", () => {
// delete user // delete user
cy.get('table tbody tr') cy.get("table tbody tr")
.contains('td', /Test-user/i) .contains("td", /Test-user/i)
.parent() .parent()
.within(() => { .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.contains(/Are you sure you want to delete Test-user?/i).should("be.visible");
cy.getDataTest('button-confirm').click(); cy.getDataTest("button-confirm").click();
}); });
}); });

View file

@ -1,89 +1,89 @@
describe('Website tests', () => { describe("Website tests", () => {
Cypress.session.clearAllSavedSessions(); Cypress.session.clearAllSavedSessions();
beforeEach(() => { 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 // add website
cy.visit('/settings/websites'); cy.visit("/settings/websites");
cy.getDataTest('button-website-add').click(); cy.getDataTest("button-website-add").click();
cy.contains(/Add website/i).should('be.visible'); cy.contains(/Add website/i).should("be.visible");
cy.getDataTest('input-name').find('input').as('inputUsername').click(); cy.getDataTest("input-name").find("input").as("inputUsername").click();
cy.getDataTest('input-name').find('input').type('Add test', { delay: 0 }); cy.getDataTest("input-name").find("input").type("Add test", { delay: 0 });
cy.getDataTest('input-domain').find('input').click(); cy.getDataTest("input-domain").find("input").click();
cy.getDataTest('input-domain').find('input').type('addtest.com', { delay: 0 }); cy.getDataTest("input-domain").find("input").type("addtest.com", { delay: 0 });
cy.getDataTest('button-submit').click(); cy.getDataTest("button-submit").click();
cy.get('td[label="Name"]').should('contain.text', 'Add test'); cy.get('td[label="Name"]').should("contain.text", "Add test");
cy.get('td[label="Domain"]').should('contain.text', 'addtest.com'); cy.get('td[label="Domain"]').should("contain.text", "addtest.com");
// clean-up data // clean-up data
cy.getDataTest('link-button-edit').first().click(); cy.getDataTest("link-button-edit").first().click();
cy.contains(/Details/i).should('be.visible'); cy.contains(/Details/i).should("be.visible");
cy.getDataTest('text-field-websiteId') cy.getDataTest("text-field-websiteId")
.find('input') .find("input")
.then($input => { .then(($input) => {
const websiteId = $input[0].value; const websiteId = $input[0].value;
cy.deleteWebsite(websiteId); cy.deleteWebsite(websiteId);
}); });
cy.visit('/settings/websites'); cy.visit("/settings/websites");
cy.contains(/Add test/i).should('not.exist'); cy.contains(/Add test/i).should("not.exist");
}); });
it('Edit a website', () => { it("Edit a website", () => {
// prep data // prep data
cy.addWebsite('Update test', 'updatetest.com'); cy.addWebsite("Update test", "updatetest.com");
cy.visit('/settings/websites'); cy.visit("/settings/websites");
// edit website // edit website
cy.getDataTest('link-button-edit').first().click(); cy.getDataTest("link-button-edit").first().click();
cy.contains(/Details/i).should('be.visible'); cy.contains(/Details/i).should("be.visible");
cy.getDataTest('input-name').find('input').click(); cy.getDataTest("input-name").find("input").click();
cy.getDataTest('input-name').find('input').clear(); cy.getDataTest("input-name").find("input").clear();
cy.getDataTest('input-name').find('input').type('Updated website', { delay: 0 }); cy.getDataTest("input-name").find("input").type("Updated website", { delay: 0 });
cy.getDataTest('input-domain').find('input').click(); cy.getDataTest("input-domain").find("input").click();
cy.getDataTest('input-domain').find('input').clear(); cy.getDataTest("input-domain").find("input").clear();
cy.getDataTest('input-domain').find('input').type('updatedwebsite.com', { delay: 0 }); cy.getDataTest("input-domain").find("input").type("updatedwebsite.com", { delay: 0 });
cy.getDataTest('button-submit').click({ force: true }); cy.getDataTest("button-submit").click({ force: true });
cy.getDataTest('input-name').find('input').should('have.value', 'Updated website'); cy.getDataTest("input-name").find("input").should("have.value", "Updated website");
cy.getDataTest('input-domain').find('input').should('have.value', 'updatedwebsite.com'); cy.getDataTest("input-domain").find("input").should("have.value", "updatedwebsite.com");
// verify tracking script // verify tracking script
cy.get('div') cy.get("div")
.contains(/Tracking code/i) .contains(/Tracking code/i)
.click(); .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 // clean-up data
cy.get('div') cy.get("div")
.contains(/Details/i) .contains(/Details/i)
.click(); .click();
cy.contains(/Details/i).should('be.visible'); cy.contains(/Details/i).should("be.visible");
cy.getDataTest('text-field-websiteId') cy.getDataTest("text-field-websiteId")
.find('input') .find("input")
.then($input => { .then(($input) => {
const websiteId = $input[0].value; const websiteId = $input[0].value;
cy.deleteWebsite(websiteId); cy.deleteWebsite(websiteId);
}); });
cy.visit('/settings/websites'); cy.visit("/settings/websites");
cy.contains(/Add test/i).should('not.exist'); cy.contains(/Add test/i).should("not.exist");
}); });
it('Delete a website', () => { it("Delete a website", () => {
// prep data // prep data
cy.addWebsite('Delete test', 'deletetest.com'); cy.addWebsite("Delete test", "deletetest.com");
cy.visit('/settings/websites'); cy.visit("/settings/websites");
// delete website // delete website
cy.getDataTest('link-button-edit').first().click(); cy.getDataTest("link-button-edit").first().click();
cy.contains(/Data/i).should('be.visible'); cy.contains(/Data/i).should("be.visible");
cy.get('div').contains(/Data/i).click(); cy.get("div").contains(/Data/i).click();
cy.contains(/All website data will be deleted./i).should('be.visible'); cy.contains(/All website data will be deleted./i).should("be.visible");
cy.getDataTest('button-delete').click(); cy.getDataTest("button-delete").click();
cy.contains(/Type DELETE in the box below to confirm./i).should('be.visible'); cy.contains(/Type DELETE in the box below to confirm./i).should("be.visible");
cy.get('input[name="confirm"').type('DELETE'); cy.get('input[name="confirm"').type("DELETE");
cy.get('button[type="submit"]').click(); 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" /> /// <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}]`); return cy.get(`[data-test=${value}]`);
}); });
Cypress.Commands.add('logout', () => { Cypress.Commands.add("logout", () => {
cy.getDataTest('button-profile').click(); cy.getDataTest("button-profile").click();
cy.getDataTest('item-logout').click(); cy.getDataTest("item-logout").click();
cy.url().should('eq', Cypress.config().baseUrl + '/login'); 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.session([username, password], () => {
cy.request({ cy.request({
method: 'POST', method: "POST",
url: '/api/auth/login', url: "/api/auth/login",
body: { body: {
username, username,
password, password,
}, },
}) })
.then(response => { .then((response) => {
Cypress.env('authorization', `bearer ${response.body.token}`); Cypress.env("authorization", `bearer ${response.body.token}`);
window.localStorage.setItem('umami.auth', JSON.stringify(response.body.token)); window.localStorage.setItem("syncfuse.auth", JSON.stringify(response.body.token));
}) })
.its('status') .its("status")
.should('eq', 200); .should("eq", 200);
}); });
}); });
Cypress.Commands.add('addWebsite', (name: string, domain: string) => { Cypress.Commands.add("addWebsite", (name: string, domain: string) => {
cy.request({ cy.request({
method: 'POST', method: "POST",
url: '/api/websites', url: "/api/websites",
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
body: { body: {
id: uuid(), id: uuid(),
createdBy: '41e2b680-648e-4b09-bcd7-3e2b10c06264', createdBy: "41e2b680-648e-4b09-bcd7-3e2b10c06264",
name: name, name: name,
domain: domain, domain: domain,
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
}); });
}); });
Cypress.Commands.add('deleteWebsite', (websiteId: string) => { Cypress.Commands.add("deleteWebsite", (websiteId: string) => {
cy.request({ cy.request({
method: 'DELETE', method: "DELETE",
url: `/api/websites/${websiteId}`, url: `/api/websites/${websiteId}`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); 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({ cy.request({
method: 'POST', method: "POST",
url: '/api/users', url: "/api/users",
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
body: { body: {
username: username, username: username,
password: password, password: password,
role: role, role: role,
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
}); });
}); });
Cypress.Commands.add('deleteUser', (userId: string) => { Cypress.Commands.add("deleteUser", (userId: string) => {
cy.request({ cy.request({
method: 'DELETE', method: "DELETE",
url: `/api/users/${userId}`, url: `/api/users/${userId}`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
}); });
}); });
Cypress.Commands.add('addTeam', (name: string) => { Cypress.Commands.add("addTeam", (name: string) => {
cy.request({ cy.request({
method: 'POST', method: "POST",
url: '/api/teams', url: "/api/teams",
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
body: { body: {
name: name, name: name,
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); expect(response.status).to.eq(200);
}); });
}); });
Cypress.Commands.add('deleteTeam', (teamId: string) => { Cypress.Commands.add("deleteTeam", (teamId: string) => {
cy.request({ cy.request({
method: 'DELETE', method: "DELETE",
url: `/api/teams/${teamId}`, url: `/api/teams/${teamId}`,
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
Authorization: Cypress.env('authorization'), Authorization: Cypress.env("authorization"),
}, },
}).then(response => { }).then((response) => {
expect(response.status).to.eq(200); 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"; ALTER TABLE "event_data" ADD COLUMN "job_id" UUID AFTER "created_at";
-- update event_data string -- update event_data string
alter table umami.event_data alter table syncfuse.event_data
update string_value = number_value update string_value = number_value
where data_type = 2 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') update string_value = replaceOne(concat(CAST(toDateTime(date_value, 'UTC'), 'String'),'Z'), ' ', 'T')
where data_type = 4 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, session_id UUID,
visit_id UUID, visit_id UUID,
@ -8,7 +8,7 @@ CREATE TABLE umami.website_event_join
ORDER BY (session_id, created_at) ORDER BY (session_id, created_at)
SETTINGS index_granularity = 8192; SETTINGS index_granularity = 8192;
INSERT INTO umami.website_event_join INSERT INTO syncfuse.website_event_join
SELECT DISTINCT SELECT DISTINCT
s.session_id, s.session_id,
generateUUIDv4() visit_id, generateUUIDv4() visit_id,
@ -18,7 +18,7 @@ FROM (SELECT DISTINCT session_id,
FROM website_event) s; FROM website_event) s;
-- create new table -- create new table
CREATE TABLE umami.website_event_new CREATE TABLE syncfuse.website_event_new
( (
website_id UUID, website_id UUID,
session_id UUID, session_id UUID,
@ -49,7 +49,7 @@ CREATE TABLE umami.website_event_new
ORDER BY (website_id, session_id, created_at) ORDER BY (website_id, session_id, created_at)
SETTINGS index_granularity = 8192; SETTINGS index_granularity = 8192;
INSERT INTO umami.website_event_new INSERT INTO syncfuse.website_event_new
SELECT we.website_id, SELECT we.website_id,
we.session_id, we.session_id,
j.visit_id, j.visit_id,
@ -74,17 +74,17 @@ SELECT we.website_id,
we.event_name, we.event_name,
we.created_at, we.created_at,
we.job_id we.job_id
FROM umami.website_event we FROM syncfuse.website_event we
JOIN umami.website_event_join j JOIN syncfuse.website_event_join j
ON we.session_id = j.session_id ON we.session_id = j.session_id
and date_trunc('hour', we.created_at) = j.created_at and date_trunc('hour', we.created_at) = j.created_at
RENAME TABLE umami.website_event TO umami.website_event_old; RENAME TABLE syncfuse.website_event TO syncfuse.website_event_old;
RENAME TABLE umami.website_event_new TO umami.website_event; RENAME TABLE syncfuse.website_event_new TO syncfuse.website_event;
/* /*
DROP TABLE umami.website_event_old DROP TABLE syncfuse.website_event_old
DROP TABLE umami.website_event_join 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, website_id UUID,
session_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) ORDER BY (website_id, event_id, data_key, created_at)
SETTINGS index_granularity = 8192; SETTINGS index_granularity = 8192;
INSERT INTO umami.event_data_new INSERT INTO syncfuse.event_data_new
SELECT website_id, SELECT website_id,
session_id, session_id,
event_id, event_id,
@ -30,9 +30,9 @@ SELECT website_id,
data_type, data_type,
created_at, created_at,
NULL NULL
FROM umami.event_data; FROM syncfuse.event_data;
CREATE TABLE umami.session_data CREATE TABLE syncfuse.session_data
( (
website_id UUID, website_id UUID,
session_id UUID, session_id UUID,
@ -48,10 +48,10 @@ CREATE TABLE umami.session_data
ORDER BY (website_id, session_id, data_key, created_at) ORDER BY (website_id, session_id, data_key, created_at)
SETTINGS index_granularity = 8192; SETTINGS index_granularity = 8192;
RENAME TABLE umami.event_data TO umami.event_data_old; RENAME TABLE syncfuse.event_data TO syncfuse.event_data_old;
RENAME TABLE umami.event_data_new TO umami.event_data; 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 -- add tag column
ALTER TABLE umami.website_event ADD COLUMN "tag" String AFTER "event_name"; ALTER TABLE syncfuse.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_stats_hourly ADD COLUMN "tag" SimpleAggregateFunction(groupArrayArray, Array(String)) AFTER "max_time";
-- update materialized view -- 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 CREATE MATERIALIZED VIEW syncfuse.website_event_stats_hourly_mv
TO umami.website_event_stats_hourly TO syncfuse.website_event_stats_hourly
AS AS
SELECT SELECT
website_id, website_id,
@ -60,7 +60,7 @@ FROM (SELECT
max(created_at) max_time, max(created_at) max_time,
arrayFilter(x -> x != '', groupArray(tag)) tag, arrayFilter(x -> x != '', groupArray(tag)) tag,
toStartOfHour(created_at) timestamp toStartOfHour(created_at) timestamp
FROM umami.website_event FROM syncfuse.website_event
GROUP BY website_id, GROUP BY website_id,
session_id, session_id,
visit_id, visit_id,

View file

@ -1,5 +1,5 @@
-- Create Event -- Create Event
CREATE TABLE umami.website_event_new CREATE TABLE syncfuse.website_event_new
( (
website_id UUID, website_id UUID,
session_id UUID, session_id UUID,
@ -49,7 +49,7 @@ ENGINE = MergeTree
SETTINGS index_granularity = 8192; SETTINGS index_granularity = 8192;
-- stats hourly -- stats hourly
CREATE TABLE umami.website_event_stats_hourly_new CREATE TABLE syncfuse.website_event_stats_hourly_new
( (
website_id UUID, website_id UUID,
session_id UUID, session_id UUID,
@ -99,8 +99,8 @@ ENGINE = AggregatingMergeTree
) )
SAMPLE BY cityHash64(visit_id); SAMPLE BY cityHash64(visit_id);
CREATE MATERIALIZED VIEW umami.website_event_stats_hourly_mv_new CREATE MATERIALIZED VIEW syncfuse.website_event_stats_hourly_mv_new
TO umami.website_event_stats_hourly_new TO syncfuse.website_event_stats_hourly_new
AS AS
SELECT SELECT
website_id, website_id,
@ -176,7 +176,7 @@ FROM (SELECT
max(created_at) max_time, max(created_at) max_time,
arrayFilter(x -> x != '', groupArray(tag)) tag, arrayFilter(x -> x != '', groupArray(tag)) tag,
toStartOfHour(created_at) timestamp toStartOfHour(created_at) timestamp
FROM umami.website_event_new FROM syncfuse.website_event_new
GROUP BY website_id, GROUP BY website_id,
session_id, session_id,
visit_id, visit_id,
@ -193,22 +193,22 @@ GROUP BY website_id,
timestamp); timestamp);
-- projections -- projections
ALTER TABLE umami.website_event_new ALTER TABLE syncfuse.website_event_new
ADD PROJECTION website_event_url_path_projection ( ADD PROJECTION website_event_url_path_projection (
SELECT * ORDER BY toStartOfDay(created_at), website_id, url_path, created_at 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 ( ADD PROJECTION website_event_referrer_domain_projection (
SELECT * ORDER BY toStartOfDay(created_at), website_id, referrer_domain, created_at 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 -- 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, 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_source=([^&]*)') AS utm_source,
extract(url_query, 'utm_medium=([^&]*)') AS utm_medium, 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, 'li_fat_id=([^&]*)') li_fat_id,
extract(url_query, 'twclid=([^&]*)') twclid, extract(url_query, 'twclid=([^&]*)') twclid,
event_type, event_name, tag, created_at, job_id event_type, event_name, tag, created_at, job_id
FROM umami.website_event FROM syncfuse.website_event
-- rename tables -- rename tables
RENAME TABLE umami.website_event TO umami.website_event_old; RENAME TABLE syncfuse.website_event TO syncfuse.website_event_old;
RENAME TABLE umami.website_event_new TO umami.website_event; 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 syncfuse.website_event_stats_hourly TO syncfuse.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_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 syncfuse.website_event_stats_hourly_mv TO syncfuse.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_new TO syncfuse.website_event_stats_hourly_mv;
-- recreate view -- 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 CREATE MATERIALIZED VIEW syncfuse.website_event_stats_hourly_mv
TO umami.website_event_stats_hourly TO syncfuse.website_event_stats_hourly
AS AS
SELECT SELECT
website_id, website_id,
@ -315,7 +315,7 @@ FROM (SELECT
max(created_at) max_time, max(created_at) max_time,
arrayFilter(x -> x != '', groupArray(tag)) tag, arrayFilter(x -> x != '', groupArray(tag)) tag,
toStartOfHour(created_at) timestamp toStartOfHour(created_at) timestamp
FROM umami.website_event FROM syncfuse.website_event
GROUP BY website_id, GROUP BY website_id,
session_id, session_id,
visit_id, visit_id,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,16 +1,16 @@
# Rename this file to .env and modify the values # 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. # 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 (e.g. postgresql)
DATABASE_TYPE=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 APP_SECRET=replace-me-with-a-random-string
# Postgres container defaults. # Postgres container defaults.
POSTGRES_DB=umami POSTGRES_DB=syncfuse
POSTGRES_USER=umami POSTGRES_USER=syncfuse
POSTGRES_PASSWORD=replace-me-with-a-random-string POSTGRES_PASSWORD=replace-me-with-a-random-string

View file

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

View file

@ -1,8 +1,8 @@
version: "3.8" version: "3.8"
services: services:
umami: syncfuse:
container_name: umami container_name: syncfuse
image: ghcr.io/umami-software/umami:postgresql-latest image: ghcr.io/umami-software/umami:postgresql-latest
ports: ports:
- "127.0.0.1:3000:3000" - "127.0.0.1:3000:3000"
@ -22,14 +22,14 @@ services:
retries: 5 retries: 5
db: db:
container_name: umami-db container_name: syncfuse-db
image: docker.io/library/postgres:15-alpine image: docker.io/library/postgres:15-alpine
environment: environment:
POSTGRES_DB: ${POSTGRES_DB} POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER} POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes: volumes:
- umami-db-data:/var/lib/postgresql/data:Z - syncfuse-db-data:/var/lib/postgresql/data:Z
restart: always restart: always
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] 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": [ "label.access-code": [
{ {
"type": 0, "type": 0,
@ -1990,7 +1990,7 @@
"message.new-version-available": [ "message.new-version-available": [
{ {
"type": 0, "type": 0,
"value": "A new version of Umami " "value": "A new version of Syncfuse "
}, },
{ {
"type": 1, "type": 1,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,4 @@
{ {
"label.access-code": [ "label.access-code": [
{ {
"type": 0, "type": 0,
@ -1652,7 +1652,7 @@
"message.new-version-available": [ "message.new-version-available": [
{ {
"type": 0, "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, "type": 1,

View file

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

View file

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

View file

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

40
src/declaration.d.ts vendored
View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "Pogrešno korisničko ime i/ili šifra.", "message.incorrect-username-password": "Pogrešno korisničko ime i/ili šifra.",
"message.invalid-domain": "Nevalidna domena. Ne uključujte http/https.", "message.invalid-domain": "Nevalidna domena. Ne uključujte http/https.",
"message.min-password-length": "Minimalna dužina od {n} karaktera", "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-data-available": "Nema dostupnih podataka.",
"message.no-event-data": "Nema dostupnih podataka o događajima.", "message.no-event-data": "Nema dostupnih podataka o događajima.",
"message.no-match-password": "Šifre se ne poklapaju.", "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.incorrect-username-password": "Nom d'usuari o contrasenya incorrectes.",
"message.invalid-domain": "Domini invàlid", "message.invalid-domain": "Domini invàlid",
"message.min-password-length": "Longitud mínima de {n} caràcters", "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-data-available": "No hi ha dades disponibles.",
"message.no-event-data": "No hi ha dades d'esdeveniments disponibles.", "message.no-event-data": "No hi ha dades d'esdeveniments disponibles.",
"message.no-match-password": "Les contrasenyes no coincideixen", "message.no-match-password": "Les contrasenyes no coincideixen",

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "Nesprávné jméno/heslo.", "message.incorrect-username-password": "Nesprávné jméno/heslo.",
"message.invalid-domain": "Neplatná doména", "message.invalid-domain": "Neplatná doména",
"message.min-password-length": "Minimum length of {n} characters", "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-data-available": "Žádná data.",
"message.no-event-data": "No event data is available.", "message.no-event-data": "No event data is available.",
"message.no-match-password": "Hesla se neschodují", "message.no-match-password": "Hesla se neschodují",

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "Ugyldigt brugernavn/adgangskode.", "message.incorrect-username-password": "Ugyldigt brugernavn/adgangskode.",
"message.invalid-domain": "Ugyldigt domæne", "message.invalid-domain": "Ugyldigt domæne",
"message.min-password-length": "Minimum length of {n} characters", "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-data-available": "Ingen data tilgængelig.",
"message.no-event-data": "No event data is available.", "message.no-event-data": "No event data is available.",
"message.no-match-password": "Adgangskoderne matcher ikke", "message.no-match-password": "Adgangskoderne matcher ikke",

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "Falsches Passwort oder Benutzername.", "message.incorrect-username-password": "Falsches Passwort oder Benutzername.",
"message.invalid-domain": "Ungültigi Domain", "message.invalid-domain": "Ungültigi Domain",
"message.min-password-length": "Miminamli längi vo {n} Zeiche", "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-data-available": "Kei Date vorhande.",
"message.no-event-data": "Es sind kei Event Date verfügbar.", "message.no-event-data": "Es sind kei Event Date verfügbar.",
"message.no-match-password": "Passwörter stimmed ned überi", "message.no-match-password": "Passwörter stimmed ned überi",

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "Falsches Passwort oder Benutzername.", "message.incorrect-username-password": "Falsches Passwort oder Benutzername.",
"message.invalid-domain": "Ungültige Domain", "message.invalid-domain": "Ungültige Domain",
"message.min-password-length": "Minimale Länge von {n} Zeichen", "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-data-available": "Keine Daten vorhanden.",
"message.no-event-data": "Es sind keine Ereignisdaten verfügbar.", "message.no-event-data": "Es sind keine Ereignisdaten verfügbar.",
"message.no-match-password": "Passwörter stimmen nicht überein", "message.no-match-password": "Passwörter stimmen nicht überein",

View file

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

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "Incorrect username/password.", "message.incorrect-username-password": "Incorrect username/password.",
"message.invalid-domain": "Invalid domain", "message.invalid-domain": "Invalid domain",
"message.min-password-length": "Minimum length of {n} characters", "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-data-available": "No data available.",
"message.no-event-data": "No event data is available.", "message.no-event-data": "No event data is available.",
"message.no-match-password": "Passwords don't match", "message.no-match-password": "Passwords don't match",

View file

@ -307,7 +307,7 @@
"message.incorrect-username-password": "Incorrect username and/or password.", "message.incorrect-username-password": "Incorrect username and/or password.",
"message.invalid-domain": "Invalid domain. Do not include http/https.", "message.invalid-domain": "Invalid domain. Do not include http/https.",
"message.min-password-length": "Minimum length of {n} characters", "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-data-available": "No data available.",
"message.no-event-data": "No event data is available.", "message.no-event-data": "No event data is available.",
"message.no-match-password": "Passwords do not match.", "message.no-match-password": "Passwords do not match.",

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