Merge branch 'dev' of github.com:openreplay/openreplay into dev

This commit is contained in:
MauricioGarciaS 2023-01-26 19:40:57 +01:00
commit 2dddf05871
13 changed files with 157 additions and 86 deletions

View file

@ -170,7 +170,7 @@ def make_chart(project_id, user_id, metric_id, data: schemas.CardChartSchema,
def get_sessions(project_id, user_id, metric_id, data: schemas.CardSessionsSchema):
# raw_metric = get_card(metric_id=metric_id, project_id=project_id, user_id=user_id, flatten=False, include_data=True)
raw_metric = get_card(metric_id=metric_id, project_id=project_id, user_id=user_id, flatten=False)
raw_metric: dict = get_card(metric_id=metric_id, project_id=project_id, user_id=user_id, flatten=False)
if raw_metric is None:
return None
metric: schemas.CreateCardSchema = schemas.CreateCardSchema(**raw_metric)
@ -197,7 +197,7 @@ def get_sessions(project_id, user_id, metric_id, data: schemas.CardSessionsSchem
def get_funnel_issues(project_id, user_id, metric_id, data: schemas.CardSessionsSchema):
raw_metric = get_card(metric_id=metric_id, project_id=project_id, user_id=user_id, flatten=False)
raw_metric: dict = get_card(metric_id=metric_id, project_id=project_id, user_id=user_id, flatten=False)
if raw_metric is None:
return None
metric: schemas.CreateCardSchema = schemas.CreateCardSchema(**raw_metric)
@ -214,7 +214,7 @@ def get_funnel_issues(project_id, user_id, metric_id, data: schemas.CardSessions
def get_errors_list(project_id, user_id, metric_id, data: schemas.CardSessionsSchema):
raw_metric = get_card(metric_id=metric_id, project_id=project_id, user_id=user_id, flatten=False)
raw_metric: dict = get_card(metric_id=metric_id, project_id=project_id, user_id=user_id, flatten=False)
if raw_metric is None:
return None
metric: schemas.CreateCardSchema = schemas.CreateCardSchema(**raw_metric)
@ -569,13 +569,13 @@ def get_funnel_sessions_by_issue(user_id, project_id, metric_id, issue_id,
def make_chart_from_card(project_id, user_id, metric_id, data: schemas.CardChartSchema):
raw_metric = get_card(metric_id=metric_id, project_id=project_id, user_id=user_id, include_data=True)
raw_metric: dict = get_card(metric_id=metric_id, project_id=project_id, user_id=user_id, include_data=True)
if raw_metric is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="card not found")
metric: schemas.CreateCardSchema = schemas.CreateCardSchema(**raw_metric)
if metric.is_template:
return get_predefined_metric(key=metric.metric_of, project_id=project_id, data=data.dict())
elif __is_click_map(raw_metric) and raw_metric["data"]:
elif __is_click_map(metric) and raw_metric["data"]:
keys = sessions_mobs. \
__get_mob_keys(project_id=project_id, session_id=raw_metric["data"]["sessionId"])
mob_exists = False

View file

@ -66,8 +66,8 @@ def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, st
LIMIT 1) AS stack_integrations ON TRUE"""
query = cur.mogrify(f"""{"SELECT *, first_recorded IS NOT NULL AS recorded FROM (" if recorded else ""}
SELECT s.project_id, s.name, s.project_key, s.save_request_payloads, s.first_recorded_session_at
{extra_projection}
SELECT s.project_id, s.name, s.project_key, s.save_request_payloads, s.first_recorded_session_at,
created_at {extra_projection}
FROM public.projects AS s
{extra_join}
WHERE s.deleted_at IS NULL
@ -79,6 +79,7 @@ def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, st
u_values = []
params = {}
for i, r in enumerate(rows):
r["created_at"] = TimeUTC.datetime_to_timestamp(r["created_at"])
if r["first_recorded_session_at"] is None:
u_values.append(f"(%(project_id_{i})s,to_timestamp(%(first_recorded_{i})s/1000))")
params[f"project_id_{i}"] = r["project_id"]
@ -91,7 +92,9 @@ def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, st
FROM (VALUES {",".join(u_values)}) AS u(project_id,first_recorded)
WHERE projects.project_id=u.project_id;""", params)
cur.execute(query)
else:
for r in rows:
r["created_at"] = TimeUTC.datetime_to_timestamp(r["created_at"])
if recording_state and len(rows) > 0:
project_ids = [f'({r["project_id"]})' for r in rows]
query = cur.mogrify(f"""SELECT projects.project_id, COALESCE(MAX(start_ts), 0) AS last

View file

@ -37,7 +37,7 @@ function build_crons(){
docker push ${DOCKER_REPO:-'local'}/crons:${tag}latest
}
[[ $SIGN_IMAGE -eq 1 ]] && {
cosign sign --key $SIGN_KEY ${DOCKER_REPO:-'local'}/crons:${image_tag}
cosign sign --key $SIGN_KEY ${DOCKER_REPO:-'local'}/crons:${git_sha1}
}
echo "completed crons build"
}

View file

@ -198,7 +198,8 @@ def make_chart(project_id, user_id, metric_id, data: schemas.CardChartSchema,
def get_sessions(project_id, user_id, metric_id, data: schemas.CardSessionsSchema):
raw_metric = get_card(metric_id=metric_id, project_id=project_id, user_id=user_id, flatten=False, include_data=True)
raw_metric: dict = get_card(metric_id=metric_id, project_id=project_id, user_id=user_id, flatten=False,
include_data=True)
if raw_metric is None:
return None
metric: schemas_ee.CreateCardSchema = schemas_ee.CreateCardSchema(**raw_metric)
@ -225,7 +226,7 @@ def get_sessions(project_id, user_id, metric_id, data: schemas.CardSessionsSchem
def get_funnel_issues(project_id, user_id, metric_id, data: schemas.CardSessionsSchema):
raw_metric = get_card(metric_id=metric_id, project_id=project_id, user_id=user_id, flatten=False)
raw_metric: dict = get_card(metric_id=metric_id, project_id=project_id, user_id=user_id, flatten=False)
if raw_metric is None:
return None
metric: schemas_ee.CreateCardSchema = schemas_ee.CreateCardSchema(**raw_metric)
@ -242,7 +243,7 @@ def get_funnel_issues(project_id, user_id, metric_id, data: schemas.CardSessions
def get_errors_list(project_id, user_id, metric_id, data: schemas.CardSessionsSchema):
raw_metric = get_card(metric_id=metric_id, project_id=project_id, user_id=user_id, flatten=False)
raw_metric: dict = get_card(metric_id=metric_id, project_id=project_id, user_id=user_id, flatten=False)
if raw_metric is None:
return None
metric: schemas_ee.CreateCardSchema = schemas_ee.CreateCardSchema(**raw_metric)
@ -622,13 +623,13 @@ def get_funnel_sessions_by_issue(user_id, project_id, metric_id, issue_id,
def make_chart_from_card(project_id, user_id, metric_id, data: schemas.CardChartSchema):
raw_metric = get_card(metric_id=metric_id, project_id=project_id, user_id=user_id, include_data=True)
raw_metric: dict = get_card(metric_id=metric_id, project_id=project_id, user_id=user_id, include_data=True)
if raw_metric is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="card not found")
metric: schemas_ee.CreateCardSchema = schemas_ee.CreateCardSchema(**raw_metric)
if metric.is_template:
return get_predefined_metric(key=metric.metric_of, project_id=project_id, data=data.dict())
elif __is_click_map(raw_metric) and raw_metric["data"]:
elif __is_click_map(metric) and raw_metric["data"]:
keys = sessions_mobs. \
__get_mob_keys(project_id=project_id, session_id=raw_metric["data"]["sessionId"])
mob_exists = False

View file

@ -76,8 +76,8 @@ def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, st
LIMIT 1) AS stack_integrations ON TRUE"""
query = cur.mogrify(f"""{"SELECT *, first_recorded IS NOT NULL AS recorded FROM (" if recorded else ""}
SELECT s.project_id, s.name, s.project_key, s.save_request_payloads, s.first_recorded_session_at
{extra_projection}
SELECT s.project_id, s.name, s.project_key, s.save_request_payloads, s.first_recorded_session_at,
created_at {extra_projection}
FROM public.projects AS s
{extra_join}
{role_query if user_id is not None else ""}
@ -92,6 +92,7 @@ def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, st
u_values = []
params = {}
for i, r in enumerate(rows):
r["created_at"] = TimeUTC.datetime_to_timestamp(r["created_at"])
if r["first_recorded_session_at"] is None:
u_values.append(f"(%(project_id_{i})s,to_timestamp(%(first_recorded_{i})s/1000))")
params[f"project_id_{i}"] = r["project_id"]
@ -104,7 +105,9 @@ def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, st
FROM (VALUES {",".join(u_values)}) AS u(project_id,first_recorded)
WHERE projects.project_id=u.project_id;""", params)
cur.execute(query)
else:
for r in rows:
r["created_at"] = TimeUTC.datetime_to_timestamp(r["created_at"])
if recording_state and len(rows) > 0:
project_ids = [f'({r["project_id"]})' for r in rows]
query = cur.mogrify(f"""SELECT projects.project_id, COALESCE(MAX(start_ts), 0) AS last

View file

@ -12,9 +12,15 @@ import BugReportModal from './BugReport/BugReportModal';
import { PlayerContext } from 'App/components/Session/playerContext';
import { observer } from 'mobx-react-lite';
import AutoplayToggle from 'Shared/AutoplayToggle';
import { connect } from 'react-redux'
const localhostWarn = (project) => project + '_localhost_warn'
function SubHeader(props) {
const { player, store } = React.useContext(PlayerContext)
const localhostWarnKey = localhostWarn(props.siteId)
const defaultLocalhostWarn = localStorage.getItem(localhostWarnKey) !== '1'
const [showWarningModal, setWarning] = React.useState(defaultLocalhostWarn);
const { player, store } = React.useContext(PlayerContext);
const {
width,
height,
@ -25,19 +31,19 @@ function SubHeader(props) {
exceptionsList,
eventList: eventsList,
endTime,
} = store.get()
} = store.get();
const mappedResourceList = resourceList
.filter((r) => r.isRed || r.isYellow)
.concat(fetchList.filter((i) => parseInt(i.status) >= 400))
.concat(graphqlList.filter((i) => parseInt(i.status) >= 400))
.concat(graphqlList.filter((i) => parseInt(i.status) >= 400));
const [isCopied, setCopied] = React.useState(false);
const { showModal, hideModal } = useModal();
const location =
currentLocation && currentLocation.length > 60
? `${currentLocation.slice(0, 60)}...`
currentLocation && currentLocation.length > 70
? `${currentLocation.slice(0, 25)}...${currentLocation.slice(-40)}`
: currentLocation;
const showReportModal = () => {
@ -48,68 +54,104 @@ function SubHeader(props) {
exceptionsList: exceptionsList,
eventsList: eventsList,
endTime: endTime,
}
showModal(<BugReportModal width={width} height={height} xrayProps={xrayProps} hideModal={hideModal} />, { right: true, width: 620 });
};
showModal(
<BugReportModal width={width} height={height} xrayProps={xrayProps} hideModal={hideModal} />,
{ right: true, width: 620 }
);
};
const showWarning =
location && /(localhost)|(127.0.0.1)|(0.0.0.0)/.test(location) && showWarningModal;
const closeWarning = () => {
localStorage.setItem(localhostWarnKey, '1')
setWarning(false)
}
return (
<div className="w-full px-4 py-2 flex items-center border-b">
{location && (
<div className="w-full px-4 py-2 flex items-center border-b relative">
{showWarning ? (
<div
className="flex items-center cursor-pointer color-gray-medium text-sm p-1 hover:bg-gray-light-shade rounded-md"
onClick={() => {
copy(currentLocation);
setCopied(true);
setTimeout(() => setCopied(false), 5000);
className="px-3 py-1 border border-gray-light drop-shadow-md rounded bg-active-blue flex items-center justify-between"
style={{
zIndex: 999,
position: 'absolute',
left: '50%',
bottom: '-24px',
transform: 'translate(-50%, 0)',
fontWeight: 500,
}}
>
<Icon size="20" name="event/link" className="mr-1" />
<Tooltip title={isCopied ? 'URL Copied to clipboard' : 'Click to copy'}>
{location}
</Tooltip>
</div>
)}
<div
className="ml-auto text-sm flex items-center color-gray-medium gap-2"
style={{ width: 'max-content' }}
>
<Button icon="file-pdf" variant="text" onClick={showReportModal}>
Create Bug Report
</Button>
<NotePopup />
<Issues sessionId={props.sessionId} />
<SharePopup
entity="sessions"
id={props.sessionId}
showCopyLink={true}
trigger={
<div className="relative">
<Button icon="share-alt" variant="text" className="relative">
Share
</Button>
</div>
}
/>
<ItemMenu
items={[
{
key: 1,
component: <AutoplayToggle />,
},
{
key: 2,
component: <Bookmark noMargin sessionId={props.sessionId} />,
},
]}
/>
<div>
<QueueControls />
Some assets may load incorrectly on localhost.
<a
href="https://docs.openreplay.com/en/troubleshooting/session-recordings/#testing-in-localhost"
target="_blank"
rel="noreferrer"
className="link ml-1"
>
Learn More
</a>
<div className="py-1 ml-3 cursor-pointer" onClick={closeWarning}>
<Icon name="close" size={16} color="black" />
</div>
</div>
) : null}
{location && (
<>
<div
className="flex items-center cursor-pointer color-gray-medium text-sm p-1 hover:bg-gray-light-shade rounded-md"
onClick={() => {
copy(currentLocation);
setCopied(true);
setTimeout(() => setCopied(false), 5000);
}}
>
<Icon size="20" name="event/link" className="mr-1" />
<Tooltip title={isCopied ? 'URL Copied to clipboard' : 'Click to copy'}>
{location}
</Tooltip>
</div>
</>
)}
<div
className="ml-auto text-sm flex items-center color-gray-medium gap-2"
style={{ width: 'max-content' }}
>
<Button icon="file-pdf" variant="text" onClick={showReportModal}>
Create Bug Report
</Button>
<NotePopup />
<Issues sessionId={props.sessionId} />
<SharePopup
entity="sessions"
id={props.sessionId}
showCopyLink={true}
trigger={
<div className="relative">
<Button icon="share-alt" variant="text" className="relative">
Share
</Button>
</div>
}
/>
<ItemMenu
items={[
{
key: 1,
component: <AutoplayToggle />,
},
{
key: 2,
component: <Bookmark noMargin sessionId={props.sessionId} />,
},
]}
/>
<div>
<QueueControls />
</div>
</div>
</div>
);
}
export default observer(SubHeader);
export default connect((state) => ({ siteId: state.getIn(['site', 'siteId']) }))(observer(SubHeader));

View file

@ -59,7 +59,7 @@ function SavedSearchModal(props: Props) {
setTimeout(() => setshowModal(true), 0);
};
const shownItems = props.list.filter((item) => item.name.includes(filterQuery));
const shownItems = props.list.filter((item) => item.name.toLocaleLowerCase().includes(filterQuery.toLocaleLowerCase()));
return (
<div className="bg-white box-shadow h-screen">

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg">
<svg width="210" height="160" viewBox="0 0 210 160" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="13" y="7.86084" width="88.2438" height="80.702" rx="4" fill="#FDF9F3"/>
<rect x="103.398" y="31.9722" width="88.2438" height="80.702" rx="40.351" fill="#E4EDF6"/>
<g clip-path="url(#clip0_299_2)">

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 16 16">
<path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/>
</svg>

After

Width:  |  Height:  |  Size: 293 B

View file

@ -108,6 +108,7 @@ log info '
Usage: openreplay [ -h | --help ]
[ -s | --status ]
[ -u | --upgrade ]
[ -U | --deprecated-upgrade /path/to/old_vars.yaml]
[ -r | --restart ]
[ -R | --Reload ]
[ -p | --install-packages ]
@ -157,6 +158,14 @@ function or_helm_upgrade() {
}
function upgrade_old() {
old_vars_path="$1"
or_version=$(busybox awk '/fromVersion/{print $2}' < "${old_vars_path}")
sudo cp "${old_vars_path}" ${OR_DIR}/vars.yaml.backup."${or_version//\"}"_"$(date +%Y%m%d-%H%M%S)" || log err "Not able to copy old vars.yaml"
sudo cp "${old_vars_path}" ${OR_DIR}/vars.yaml || log err "Not able to copy old vars.yaml"
upgrade
}
function upgrade() {
# TODO:
# 1. store vars.yaml in central place.
@ -166,10 +175,10 @@ function upgrade() {
exists git || log err "Git not found. Please install"
log info "Working directory $tmp_dir"
err_cd "$tmp_dir"
or_version=$(awk '/fromVersion/{print $2}' < "${OR_DIR}/vars.yaml")
or_version=$(busybox awk '/fromVersion/{print $2}' < "${OR_DIR}/vars.yaml")
# Creating backup dir of current installation
[[ -d "$OR_DIR/openreplay" ]] && sudo cp -b "$OR_DIR/openreplay" "$OR_DIR/openreplay_${or_version//\"}" && sudo rm -rf ${OR_DIR}/openreplay
[[ -d "$OR_DIR/openreplay" ]] && sudo cp -rfb "$OR_DIR/openreplay" "$OR_DIR/openreplay_${or_version//\"}" && sudo rm -rf ${OR_DIR}/openreplay
git clone "${OR_REPO}" --depth 1
err_cd openreplay/scripts/helmcharts
@ -188,7 +197,8 @@ function upgrade() {
sudo mv ./openreplay-cli /bin/
sudo mv ./vars.yaml "$OR_DIR"
sudo cp -rf ../../../openreplay $OR_DIR/
log info All the configuration has been stored to $OR_DIR/vars.yaml file
log info "Configuration file is saved in /var/lib/openreplay/vars.yaml"
log info "Run ${BWHITE}openreplay -h${GREEN} to see the cli information to manage OpenReplay."
err_cd -
return
@ -210,7 +220,7 @@ function clean_tmp_dir() {
install_packages
}
PARSED_ARGUMENTS=$(busybox getopt -a -n openreplay -o Rrvpiuhsl: --long reload,restart,verbose,install-packages,install,upgrade,help,status,logs: -- "$@")
PARSED_ARGUMENTS=$(busybox getopt -a -n openreplay -o Rrvpiuhsl:U: --long reload,restart,verbose,install-packages,install,upgrade,help,status,logs,deprecated-upgrade: -- "$@")
VALID_ARGUMENTS=$?
if [[ "$VALID_ARGUMENTS" != "0" ]]; then
help
@ -233,6 +243,12 @@ do
clean_tmp_dir
exit 0
;;
-U | --deprecated-upgrade)
log title "[Deprected] Upgrading OpenReplay"
upgrade_old "$2"
clean_tmp_dir
exit 0
;;
-r | --restart)
log title "Restarting OpenReplay Components"
kubectl rollout restart deployment -n "${APP_NS}"

View file

@ -7,10 +7,12 @@ metadata:
"helm.sh/hook": post-install, post-upgrade
"helm.sh/hook-weight": "4" # Higher precidence, so the first the config map will get created.
spec:
validationFailureAction: enforce
# validationFailureAction: enforce
validationFailureAction: audit
background: false
webhookTimeoutSeconds: 30
failurePolicy: Fail
# failurePolicy: Fail
failurePolicy: Ignore
rules:
- name: openreplay-image-signature
match:

View file

@ -333,9 +333,9 @@ export default class App {
return undefined
}
const ingest = this.options.ingestPoint
const isSaas = ingest === DEFAULT_INGEST_POINT
const isSaas = /api.openreplay.com/.test(ingest)
const projectPath = isSaas ? ingest.replace('api', 'app') : ingest
const projectPath = isSaas ? 'https://openreplay.com/ingest' : ingest
const url = projectPath.replace(/ingest$/, `${projectID}/session/${sessionID}`)