mirror of
https://github.com/kremalicious/umami.git
synced 2024-06-30 13:41:50 +02:00
Updated search queries.
This commit is contained in:
parent
80a58cbdd1
commit
e971f2533d
|
@ -12,14 +12,14 @@ import useDashboard from 'store/dashboard';
|
||||||
|
|
||||||
export function Dashboard() {
|
export function Dashboard() {
|
||||||
const { formatMessage, labels, messages } = useMessages();
|
const { formatMessage, labels, messages } = useMessages();
|
||||||
const { teamId } = useTeamContext();
|
const { teamId, renderTeamUrl } = useTeamContext();
|
||||||
const { showCharts, editing } = useDashboard();
|
const { showCharts, editing } = useDashboard();
|
||||||
const { dir } = useLocale();
|
const { dir } = useLocale();
|
||||||
const pageSize = 10;
|
const pageSize = 10;
|
||||||
|
|
||||||
const { result, query, params, setParams } = useWebsites({}, { pageSize });
|
const { result, query, params, setParams } = useWebsites({ teamId }, { pageSize });
|
||||||
const { page } = params;
|
const { page } = params;
|
||||||
const hasData = !!result?.data;
|
const hasData = !!result?.data?.length;
|
||||||
|
|
||||||
const handlePageChange = (page: number) => {
|
const handlePageChange = (page: number) => {
|
||||||
setParams({ ...params, page });
|
setParams({ ...params, page });
|
||||||
|
@ -36,7 +36,7 @@ export function Dashboard() {
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
{!hasData && (
|
{!hasData && (
|
||||||
<EmptyPlaceholder message={formatMessage(messages.noWebsitesConfigured)}>
|
<EmptyPlaceholder message={formatMessage(messages.noWebsitesConfigured)}>
|
||||||
<Link href="/settings/websites">
|
<Link href={renderTeamUrl('/settings/websites')}>
|
||||||
<Button>
|
<Button>
|
||||||
<Icon rotate={dir === 'rtl' ? 180 : 0}>
|
<Icon rotate={dir === 'rtl' ? 180 : 0}>
|
||||||
<Icons.ArrowRight />
|
<Icons.ArrowRight />
|
||||||
|
|
|
@ -8,7 +8,7 @@ export default function Websites({ teamId }: { teamId: string }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<WebsitesHeader showActions={user.role !== 'view-only'} />
|
<WebsitesHeader teamId={teamId} showActions={user.role !== 'view-only'} />
|
||||||
<WebsitesDataTable teamId={teamId} userId={user.id} allowEdit={true} />
|
<WebsitesDataTable teamId={teamId} userId={user.id} allowEdit={true} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { Metadata } from 'next';
|
||||||
export default function WebsitesPage({ params: { teamId, userId } }) {
|
export default function WebsitesPage({ params: { teamId, userId } }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<WebsitesHeader showActions={false} />
|
<WebsitesHeader teamId={teamId} showActions={false} />
|
||||||
<WebsitesBrowse teamId={teamId} userId={userId} />
|
<WebsitesBrowse teamId={teamId} userId={userId} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,8 +6,8 @@ import { useMessages } from 'components/hooks';
|
||||||
import { useLogin } from 'components/hooks';
|
import { useLogin } from 'components/hooks';
|
||||||
import { useLocale } from 'components/hooks';
|
import { useLocale } from 'components/hooks';
|
||||||
import { CURRENT_VERSION } from 'lib/constants';
|
import { CURRENT_VERSION } from 'lib/constants';
|
||||||
import styles from './ProfileButton.module.css';
|
|
||||||
import Avatar from 'components/common/Avatar';
|
import Avatar from 'components/common/Avatar';
|
||||||
|
import styles from './ProfileButton.module.css';
|
||||||
|
|
||||||
export function ProfileButton() {
|
export function ProfileButton() {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
@ -17,6 +17,7 @@ export * from 'components/hooks/useMessages';
|
||||||
export * from 'components/hooks/useNavigation';
|
export * from 'components/hooks/useNavigation';
|
||||||
export * from 'components/hooks/useSticky';
|
export * from 'components/hooks/useSticky';
|
||||||
export * from 'components/hooks/useTheme';
|
export * from 'components/hooks/useTheme';
|
||||||
|
export * from 'components/hooks/useTeamContext';
|
||||||
export * from 'components/hooks/useTimezone';
|
export * from 'components/hooks/useTimezone';
|
||||||
|
|
||||||
export * from './app/(main)/settings/teams/[teamId]/TeamEditForm';
|
export * from './app/(main)/settings/teams/[teamId]/TeamEditForm';
|
||||||
|
@ -60,3 +61,6 @@ export * from 'components/common/HoverTooltip';
|
||||||
export * from 'components/common/LinkButton';
|
export * from 'components/common/LinkButton';
|
||||||
export * from 'components/common/MobileMenu';
|
export * from 'components/common/MobileMenu';
|
||||||
export * from 'components/common/Pager';
|
export * from 'components/common/Pager';
|
||||||
|
|
||||||
|
export * from 'components/input/TeamsButton';
|
||||||
|
export * from 'components/input/ThemeButton';
|
||||||
|
|
|
@ -17,27 +17,23 @@ export function getDatabaseType(url = process.env.DATABASE_URL) {
|
||||||
return POSTGRESQL;
|
return POSTGRESQL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.env.CLICKHOUSE_URL) {
|
|
||||||
return CLICKHOUSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function runQuery(queries: any) {
|
export async function runQuery(queries: any) {
|
||||||
const db = getDatabaseType(process.env.CLICKHOUSE_URL || process.env.DATABASE_URL);
|
if (process.env.CLICKHOUSE_URL) {
|
||||||
|
|
||||||
if (db === POSTGRESQL || db === MYSQL) {
|
|
||||||
return queries[PRISMA]();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (db === CLICKHOUSE) {
|
|
||||||
if (queries[KAFKA]) {
|
if (queries[KAFKA]) {
|
||||||
return queries[KAFKA]();
|
return queries[KAFKA]();
|
||||||
}
|
}
|
||||||
|
|
||||||
return queries[CLICKHOUSE]();
|
return queries[CLICKHOUSE]();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const db = getDatabaseType();
|
||||||
|
|
||||||
|
if (db === POSTGRESQL || db === MYSQL) {
|
||||||
|
return queries[PRISMA]();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function notImplemented() {
|
export function notImplemented() {
|
||||||
|
|
|
@ -24,7 +24,7 @@ const POSTGRESQL_DATE_FORMATS = {
|
||||||
};
|
};
|
||||||
|
|
||||||
function getAddIntervalQuery(field: string, interval: string): string {
|
function getAddIntervalQuery(field: string, interval: string): string {
|
||||||
const db = getDatabaseType(process.env.DATABASE_URL);
|
const db = getDatabaseType();
|
||||||
|
|
||||||
if (db === POSTGRESQL) {
|
if (db === POSTGRESQL) {
|
||||||
return `${field} + interval '${interval}'`;
|
return `${field} + interval '${interval}'`;
|
||||||
|
@ -36,7 +36,7 @@ function getAddIntervalQuery(field: string, interval: string): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDayDiffQuery(field1: string, field2: string): string {
|
function getDayDiffQuery(field1: string, field2: string): string {
|
||||||
const db = getDatabaseType(process.env.DATABASE_URL);
|
const db = getDatabaseType();
|
||||||
|
|
||||||
if (db === POSTGRESQL) {
|
if (db === POSTGRESQL) {
|
||||||
return `${field1}::date - ${field2}::date`;
|
return `${field1}::date - ${field2}::date`;
|
||||||
|
@ -48,7 +48,7 @@ function getDayDiffQuery(field1: string, field2: string): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCastColumnQuery(field: string, type: string): string {
|
function getCastColumnQuery(field: string, type: string): string {
|
||||||
const db = getDatabaseType(process.env.DATABASE_URL);
|
const db = getDatabaseType();
|
||||||
|
|
||||||
if (db === POSTGRESQL) {
|
if (db === POSTGRESQL) {
|
||||||
return `${field}::${type}`;
|
return `${field}::${type}`;
|
||||||
|
@ -92,7 +92,7 @@ function getTimestampDiffQuery(field1: string, field2: string): string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapFilter(column, operator, name, type = 'varchar') {
|
function mapFilter(column: string, operator: string, name: string, type = 'varchar') {
|
||||||
switch (operator) {
|
switch (operator) {
|
||||||
case OPERATORS.equals:
|
case OPERATORS.equals:
|
||||||
return `${column} = {{${name}::${type}}}`;
|
return `${column} = {{${name}::${type}}}`;
|
||||||
|
@ -208,16 +208,44 @@ function getQueryMode(): Prisma.QueryMode {
|
||||||
return 'default';
|
return 'default';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSearchParameters(query: string, filters: { [key: string]: any }[]) {
|
||||||
|
if (!query) return;
|
||||||
|
|
||||||
|
const mode = getQueryMode();
|
||||||
|
const parseFilter = (filter: { [key: string]: any }) => {
|
||||||
|
const [[key, value]] = Object.entries(filter);
|
||||||
|
|
||||||
|
return {
|
||||||
|
[key]:
|
||||||
|
typeof value === 'string'
|
||||||
|
? {
|
||||||
|
[value]: query,
|
||||||
|
mode,
|
||||||
|
}
|
||||||
|
: parseFilter(value),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const params = filters.map(filter => parseFilter(filter));
|
||||||
|
|
||||||
|
return {
|
||||||
|
AND: {
|
||||||
|
OR: params,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
...prisma,
|
...prisma,
|
||||||
getAddIntervalQuery,
|
getAddIntervalQuery,
|
||||||
getDayDiffQuery,
|
|
||||||
getCastColumnQuery,
|
getCastColumnQuery,
|
||||||
|
getDayDiffQuery,
|
||||||
getDateQuery,
|
getDateQuery,
|
||||||
getTimestampDiffQuery,
|
|
||||||
getFilterQuery,
|
getFilterQuery,
|
||||||
parseFilters,
|
getSearchParameters,
|
||||||
|
getTimestampDiffQuery,
|
||||||
getQueryMode,
|
getQueryMode,
|
||||||
rawQuery,
|
|
||||||
pagedQuery,
|
pagedQuery,
|
||||||
|
parseFilters,
|
||||||
|
rawQuery,
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,9 +3,10 @@ import { useAuth, useCors, useValidate } from 'lib/middleware';
|
||||||
import { NextApiRequestQueryBody } from 'lib/types';
|
import { NextApiRequestQueryBody } from 'lib/types';
|
||||||
import { pageInfo } from 'lib/schema';
|
import { pageInfo } from 'lib/schema';
|
||||||
import { NextApiResponse } from 'next';
|
import { NextApiResponse } from 'next';
|
||||||
import { methodNotAllowed, ok } from 'next-basics';
|
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||||
import { createReport, getReports } from 'queries';
|
import { createReport, getReports } from 'queries';
|
||||||
import * as yup from 'yup';
|
import * as yup from 'yup';
|
||||||
|
import { canViewTeam, canViewWebsite } from 'lib/auth';
|
||||||
|
|
||||||
export interface ReportRequestBody {
|
export interface ReportRequestBody {
|
||||||
websiteId: string;
|
websiteId: string;
|
||||||
|
@ -51,16 +52,23 @@ export default async (
|
||||||
const { page, query, pageSize, websiteId, teamId } = req.query;
|
const { page, query, pageSize, websiteId, teamId } = req.query;
|
||||||
const filters = {
|
const filters = {
|
||||||
page,
|
page,
|
||||||
pageSize: +pageSize || undefined,
|
pageSize,
|
||||||
query,
|
query,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (
|
||||||
|
(websiteId && !(await canViewWebsite(req.auth, websiteId))) ||
|
||||||
|
(teamId && !(await canViewTeam(req.auth, teamId)))
|
||||||
|
) {
|
||||||
|
return unauthorized(res);
|
||||||
|
}
|
||||||
|
|
||||||
const data = await getReports(
|
const data = await getReports(
|
||||||
{
|
{
|
||||||
where: {
|
where: {
|
||||||
|
userId: !teamId && !websiteId ? userId : undefined,
|
||||||
|
websiteId,
|
||||||
website: {
|
website: {
|
||||||
id: websiteId,
|
|
||||||
userId: !websiteId && !teamId ? userId : undefined,
|
|
||||||
teamId,
|
teamId,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -20,68 +20,30 @@ export async function getReports(
|
||||||
criteria: ReportFindManyArgs,
|
criteria: ReportFindManyArgs,
|
||||||
filters: ReportSearchFilter = {},
|
filters: ReportSearchFilter = {},
|
||||||
): Promise<FilterResult<Report[]>> {
|
): Promise<FilterResult<Report[]>> {
|
||||||
const mode = prisma.getQueryMode();
|
const { query } = filters;
|
||||||
const { query, userId, websiteId } = filters;
|
|
||||||
|
|
||||||
const where: Prisma.ReportWhereInput = {
|
const where: Prisma.ReportWhereInput = {
|
||||||
userId,
|
|
||||||
websiteId,
|
|
||||||
...criteria.where,
|
...criteria.where,
|
||||||
AND: [
|
...prisma.getSearchParameters(query, [
|
||||||
|
{ name: 'contains' },
|
||||||
|
{ description: 'contains' },
|
||||||
|
{ type: 'contains' },
|
||||||
{
|
{
|
||||||
OR: [
|
user: {
|
||||||
{
|
username: 'contains',
|
||||||
userId,
|
},
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
OR: [
|
website: {
|
||||||
{
|
name: 'contains',
|
||||||
name: {
|
},
|
||||||
contains: query,
|
|
||||||
mode,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: {
|
|
||||||
contains: query,
|
|
||||||
mode,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: {
|
|
||||||
contains: query,
|
|
||||||
mode,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
user: {
|
|
||||||
username: {
|
|
||||||
contains: query,
|
|
||||||
mode,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
website: {
|
|
||||||
name: {
|
|
||||||
contains: query,
|
|
||||||
mode,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
website: {
|
|
||||||
domain: {
|
|
||||||
contains: query,
|
|
||||||
mode,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
],
|
{
|
||||||
|
website: {
|
||||||
|
domain: 'contains',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
};
|
};
|
||||||
|
|
||||||
return prisma.pagedQuery('report', { ...criteria, where }, filters);
|
return prisma.pagedQuery('report', { ...criteria, where }, filters);
|
||||||
|
|
|
@ -24,41 +24,12 @@ export async function getTeams(
|
||||||
criteria: TeamFindManyArgs,
|
criteria: TeamFindManyArgs,
|
||||||
filters: TeamSearchFilter = {},
|
filters: TeamSearchFilter = {},
|
||||||
): Promise<FilterResult<Team[]>> {
|
): Promise<FilterResult<Team[]>> {
|
||||||
const mode = prisma.getQueryMode();
|
const { getSearchParameters } = prisma;
|
||||||
const { userId, query } = filters;
|
const { query } = filters;
|
||||||
|
|
||||||
const where: Prisma.TeamWhereInput = {
|
const where: Prisma.TeamWhereInput = {
|
||||||
...criteria.where,
|
...criteria.where,
|
||||||
...(userId && {
|
...getSearchParameters(query, [{ name: 'contains' }]),
|
||||||
teamUser: {
|
|
||||||
some: { userId },
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
...(query && {
|
|
||||||
AND: {
|
|
||||||
OR: [
|
|
||||||
{
|
|
||||||
name: {
|
|
||||||
startsWith: query,
|
|
||||||
mode,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
teamUser: {
|
|
||||||
some: {
|
|
||||||
role: ROLES.teamOwner,
|
|
||||||
user: {
|
|
||||||
username: {
|
|
||||||
startsWith: query,
|
|
||||||
mode,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return prisma.pagedQuery<TeamFindManyArgs>(
|
return prisma.pagedQuery<TeamFindManyArgs>(
|
||||||
|
|
|
@ -18,18 +18,10 @@ export async function getTeamUsers(
|
||||||
filters?: TeamUserSearchFilter,
|
filters?: TeamUserSearchFilter,
|
||||||
): Promise<FilterResult<TeamUser[]>> {
|
): Promise<FilterResult<TeamUser[]>> {
|
||||||
const { query } = filters;
|
const { query } = filters;
|
||||||
const mode = prisma.getQueryMode();
|
|
||||||
|
|
||||||
const where: Prisma.TeamUserWhereInput = {
|
const where: Prisma.TeamUserWhereInput = {
|
||||||
...criteria.where,
|
...criteria.where,
|
||||||
user: {
|
...prisma.getSearchParameters(query, [{ user: { username: 'contains' } }]),
|
||||||
username: query
|
|
||||||
? {
|
|
||||||
contains: query,
|
|
||||||
mode,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return prisma.pagedQuery(
|
return prisma.pagedQuery(
|
||||||
|
|
|
@ -52,29 +52,11 @@ export async function getUsers(
|
||||||
criteria: UserFindManyArgs,
|
criteria: UserFindManyArgs,
|
||||||
filters?: UserSearchFilter,
|
filters?: UserSearchFilter,
|
||||||
): Promise<FilterResult<User[]>> {
|
): Promise<FilterResult<User[]>> {
|
||||||
const { teamId, query } = filters;
|
const { query } = filters;
|
||||||
const mode = prisma.getQueryMode();
|
|
||||||
|
|
||||||
const where: Prisma.UserWhereInput = {
|
const where: Prisma.UserWhereInput = {
|
||||||
...(teamId && {
|
...criteria.where,
|
||||||
teamUser: {
|
...prisma.getSearchParameters(query, [{ username: 'contains' }]),
|
||||||
some: {
|
|
||||||
teamId,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
...(query && {
|
|
||||||
AND: {
|
|
||||||
OR: [
|
|
||||||
{
|
|
||||||
username: {
|
|
||||||
contains: query,
|
|
||||||
mode,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
deletedAt: null,
|
deletedAt: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user