Skip to content

Commit

Permalink
Refactor from segment.personal to segment.type
Browse files Browse the repository at this point in the history
  • Loading branch information
apata committed Nov 14, 2024
1 parent c88b9c8 commit 514db19
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 85 deletions.
35 changes: 21 additions & 14 deletions assets/js/dashboard/segments/segment-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {
EditingSegmentState,
formatSegmentIdAsLabelKey,
parseApiSegmentData,
SavedSegment
SavedSegment,
SegmentType
} from './segments'
import { CreateSegmentModal, UpdateSegmentModal } from './segment-modals'
import { useUserContext } from '../user-context'
Expand Down Expand Up @@ -44,11 +45,11 @@ export const SaveSegmentAction = ({ options }: { options: O[] }) => {
const createSegment = useMutation({
mutationFn: ({
name,
personal,
type,
segment_data
}: {
name: string
personal: boolean
type: 'personal' | 'site'
segment_data: {
filters: DashboardQuery['filters']
labels: DashboardQuery['labels']
Expand All @@ -60,7 +61,7 @@ export const SaveSegmentAction = ({ options }: { options: O[] }) => {
method: 'POST',
body: JSON.stringify({
name,
personal,
type,
segment_data: {
filters: remapToApiFilters(segment_data.filters),
labels: cleanLabels(segment_data.filters, segment_data.labels)
Expand Down Expand Up @@ -99,12 +100,12 @@ export const SaveSegmentAction = ({ options }: { options: O[] }) => {
mutationFn: ({
id,
name,
personal,
type,
segment_data
}: {
id: number
name?: string
personal?: boolean
type?: SegmentType
segment_data?: {
filters: DashboardQuery['filters']
labels: DashboardQuery['labels']
Expand All @@ -116,7 +117,7 @@ export const SaveSegmentAction = ({ options }: { options: O[] }) => {
method: 'PATCH',
body: JSON.stringify({
name,
personal,
type,
...(segment_data && {
segment_data: {
filters: remapToApiFilters(segment_data.filters),
Expand Down Expand Up @@ -189,8 +190,9 @@ export const SaveSegmentAction = ({ options }: { options: O[] }) => {
}
if (o.type === 'update segment') {
const canEdit =
(o.segment.personal && o.segment.owner_id === user.id) ||
(!o.segment.personal &&
(o.segment.type === SegmentType.personal &&
o.segment.owner_id === user.id) ||
(o.segment.type === SegmentType.site &&
['admin', 'owner', 'super_admin'].includes(user.role))

return (
Expand All @@ -207,14 +209,16 @@ export const SaveSegmentAction = ({ options }: { options: O[] }) => {
})}
{modal === 'create segment' && (
<CreateSegmentModal
canTogglePersonal={['admin', 'owner', 'super_admin'].includes(user.role)}
canTogglePersonal={['admin', 'owner', 'super_admin'].includes(
user.role
)}
segment={options.find((o) => o.type === 'update segment')?.segment}
namePlaceholder={segmentNamePlaceholder}
close={close}
onSave={({ name, personal }) =>
onSave={({ name, type }) =>
createSegment.mutate({
name,
personal,
type,
segment_data: {
filters: query.filters,
labels: query.labels
Expand All @@ -225,14 +229,17 @@ export const SaveSegmentAction = ({ options }: { options: O[] }) => {
)}
{option?.type === 'update segment' && (
<UpdateSegmentModal
canTogglePersonal={['admin', 'owner', 'super_admin'].includes(
user.role
)}
segment={option.segment}
namePlaceholder={segmentNamePlaceholder}
close={close}
onSave={({ id, name, personal }) =>
onSave={({ id, name, type }) =>
patchSegment.mutate({
id,
name,
personal,
type,
segment_data: {
filters: query.filters,
labels: query.labels
Expand Down
52 changes: 38 additions & 14 deletions assets/js/dashboard/segments/segment-modals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import React, { useState } from 'react'
import ModalWithRouting from '../stats/modals/modal'
import classNames from 'classnames'
import { SavedSegment } from './segments'
import { SavedSegment, SegmentType } from './segments'

const buttonClass =
'h-12 text-md font-medium py-2 px-3 rounded border dark:border-gray-100 dark:text-gray-100'
Expand All @@ -17,14 +17,14 @@ export const CreateSegmentModal = ({
}: {
segment?: SavedSegment
close: () => void
onSave: (input: { name: string; personal: boolean }) => void
onSave: (input: Pick<SavedSegment, 'name' | 'type'>) => void
canTogglePersonal: boolean
namePlaceholder: string
}) => {
const [name, setName] = useState(
segment?.name ? `Copy of ${segment.name}` : ''
)
const [personal, setPersonal] = useState(true)
const [type, setType] = useState<SegmentType>(SegmentType.personal)

return (
<ModalWithRouting maxWidth="460px" className="p-6 min-h-fit" close={close}>
Expand Down Expand Up @@ -53,16 +53,27 @@ export const CreateSegmentModal = ({
<button
className={classNames(
'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full transition-colors ease-in-out duration-200 focus:outline-none focus:ring',
personal ? 'bg-gray-200 dark:bg-gray-700' : 'bg-indigo-600',
type === SegmentType.personal
? 'bg-gray-200 dark:bg-gray-700'
: 'bg-indigo-600',
!canTogglePersonal && 'cursor-not-allowed'
)}
onClick={canTogglePersonal ? () => setPersonal((current) => !current) : () => {}}
onClick={
canTogglePersonal
? () =>
setType((current) =>
current === SegmentType.personal
? SegmentType.site
: SegmentType.personal
)
: () => {}
}
>
<span
aria-hidden="true"
className={classNames(
'inline-block h-5 w-5 rounded-full bg-white dark:bg-gray-800 shadow transform transition ease-in-out duration-200',
personal ? 'translate-x-0' : 'translate-x-5'
type === SegmentType.personal ? 'translate-x-0' : 'translate-x-5'
)}
/>
</button>
Expand All @@ -81,7 +92,7 @@ export const CreateSegmentModal = ({
const saveableName = trimmedName.length
? trimmedName
: namePlaceholder
onSave({ name: saveableName, personal })
onSave({ name: saveableName, type })
}}
>
Save
Expand All @@ -95,15 +106,17 @@ export const UpdateSegmentModal = ({
close,
onSave,
segment,
canTogglePersonal,
namePlaceholder
}: {
close: () => void
onSave: (input: { id: number; name: string; personal: boolean }) => void
onSave: (input: Pick<SavedSegment, 'id' | 'name' | 'type'>) => void
segment: SavedSegment
canTogglePersonal: boolean
namePlaceholder: string
}) => {
const [name, setName] = useState(segment.name)
const [personal, setPersonal] = useState<boolean>(segment.personal)
const [type, setType] = useState<SegmentType>(SegmentType.personal)

return (
<ModalWithRouting maxWidth="460px" className="p-6 min-h-fit" close={close}>
Expand Down Expand Up @@ -131,16 +144,27 @@ export const UpdateSegmentModal = ({
<button
className={classNames(
'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full transition-colors ease-in-out duration-200 focus:outline-none focus:ring',
personal ? 'bg-gray-200 dark:bg-gray-700' : 'bg-indigo-600',
false && 'cursor-not-allowed'
type === SegmentType.personal
? 'bg-gray-200 dark:bg-gray-700'
: 'bg-indigo-600',
!canTogglePersonal && 'cursor-not-allowed'
)}
onClick={() => setPersonal((current) => !current)}
onClick={
canTogglePersonal
? () =>
setType((current) =>
current === SegmentType.personal
? SegmentType.site
: SegmentType.personal
)
: () => {}
}
>
<span
aria-hidden="true"
className={classNames(
'inline-block h-5 w-5 rounded-full bg-white dark:bg-gray-800 shadow transform transition ease-in-out duration-200',
personal ? 'translate-x-0' : 'translate-x-5'
type === SegmentType.personal ? 'translate-x-0' : 'translate-x-5'
)}
/>
</button>
Expand All @@ -159,7 +183,7 @@ export const UpdateSegmentModal = ({
const saveableName = trimmedName.length
? trimmedName
: namePlaceholder
onSave({ id: segment.id, name: saveableName, personal })
onSave({ id: segment.id, name: saveableName, type })
}}
>
Save
Expand Down
22 changes: 15 additions & 7 deletions assets/js/dashboard/segments/segments-dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import {
isSegmentFilter,
parseApiSegmentData,
SavedSegment,
SegmentData
SegmentData,
SegmentType
} from './segments'
import {
QueryFunction,
Expand Down Expand Up @@ -90,7 +91,14 @@ export const SegmentsList = ({ closeList }: { closeList: () => void }) => {
key={s.id}
info={
<div>
<div>{s.personal ? 'Personal segment' : 'Segment'}</div>
<div>
{
{
[SegmentType.personal]: 'Personal segment',
[SegmentType.site]: 'Segment'
}[s.type]
}
</div>
<div className="font-normal text-xs">
{`Created at ${formatDayShort(parseUTCDate(s.inserted_at))}`}
{!showUpdatedAt && !!authorLabel && ` by ${authorLabel}`}
Expand Down Expand Up @@ -120,7 +128,7 @@ export const SegmentsList = ({ closeList }: { closeList: () => void }) => {
const SegmentLink = ({
id,
name,
personal,
type,
owner_id,
appliedSegmentIds,
closeList
Expand All @@ -129,8 +137,8 @@ const SegmentLink = ({
const canSeeActions = user.loggedIn
const canDeleteSegment =
user.loggedIn &&
((owner_id === user.id && personal === true) ||
(personal === false &&
((owner_id === user.id && type === SegmentType.personal) ||
(type === SegmentType.site &&
['admin', 'owner', 'super_admin'].includes(user.role)))
const site = useSiteContext()
const { query } = useQueryContext()
Expand Down Expand Up @@ -193,7 +201,7 @@ const SegmentLink = ({
editingSegment: {
id: data.id,
name: data.name,
personal: data.personal,
type: data.type,
owner_id: data.owner_id
}
} as EditingSegmentState
Expand Down Expand Up @@ -246,7 +254,7 @@ const SegmentLink = ({
<DeleteSegment
disabled={!canDeleteSegment}
className="ml-2"
segment={{ id, name, personal, owner_id }}
segment={{ id, name, type, owner_id }}
/>
</>
)
Expand Down
7 changes: 6 additions & 1 deletion assets/js/dashboard/segments/segments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
import { Filter } from '../query'
import { remapFromApiFilters } from '../util/filters'

export enum SegmentType {
personal = 'personal',
site = 'site'
}

export type SavedSegment = {
id: number
name: string
personal: boolean
type: SegmentType
owner_id: number
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ defmodule PlausibleWeb.Api.Internal.SegmentsController do
from(segment in Plausible.Segment,
where: segment.site_id == ^site_id,
where: segment.id == ^segment_id,
where: segment.personal == false or segment.owner_id == ^user_id
where: segment.type == :site or segment.owner_id == ^user_id
)

Repo.one(query)
Expand All @@ -31,7 +31,7 @@ defmodule PlausibleWeb.Api.Internal.SegmentsController do
fields_in_index = [
:id,
:name,
:personal,
:type,
:inserted_at,
:updated_at,
:owner_id
Expand All @@ -40,7 +40,7 @@ defmodule PlausibleWeb.Api.Internal.SegmentsController do
from(segment in Plausible.Segment,
select: ^fields_in_index,
where: segment.site_id == ^site_id,
where: segment.personal == false or segment.owner_id == ^user_id,
where: segment.type == :site or segment.owner_id == ^user_id,
order_by: [asc: segment.name]
)
end
Expand Down Expand Up @@ -80,7 +80,7 @@ defmodule PlausibleWeb.Api.Internal.SegmentsController do

changeset = Plausible.Segment.changeset(%Plausible.Segment{}, segment_definition)

if changeset.changes.personal == false and
if changeset.changes.type == :site and
not has_capability_to_toggle_site_segment?(conn.assigns.current_user_role) do
H.not_enough_permissions(conn, "Not enough permissions to create site segments")
else
Expand All @@ -101,7 +101,7 @@ defmodule PlausibleWeb.Api.Internal.SegmentsController do
site_id = conn.assigns.site.id
segment_id = normalize_segment_id_param(params["segment_id"])

if not is_nil(params["personal"]) and
if not is_nil(params["type"]) and
not has_capability_to_toggle_site_segment?(conn.assigns.current_user_role) do
H.not_enough_permissions(conn, "Not enough permissions to set segment visibility")
else
Expand Down Expand Up @@ -129,7 +129,7 @@ defmodule PlausibleWeb.Api.Internal.SegmentsController do

existing_segment = get_one_segment(user_id, site_id, segment_id)

if not existing_segment.personal and
if existing_segment.type == :site and
not has_capability_to_toggle_site_segment?(conn.assigns.current_user_role) do
H.not_enough_permissions(conn, "Not enough permissions to delete site segments")
else
Expand Down
Loading

0 comments on commit 514db19

Please sign in to comment.