commit
079e3add5e
19 changed files with 142 additions and 210 deletions
|
|
@ -22,13 +22,6 @@ app = Blueprint(__name__)
|
|||
_overrides.chalice_app(app)
|
||||
|
||||
|
||||
@app.route('/signedups', methods=['GET'], authorizer=None)
|
||||
def signed_ups():
|
||||
return {
|
||||
'data': tenants.get_tenants()
|
||||
}
|
||||
|
||||
|
||||
@app.route('/login', methods=['POST'], authorizer=None)
|
||||
def login():
|
||||
data = app.current_request.json_body
|
||||
|
|
@ -52,7 +45,7 @@ def login():
|
|||
c = tenants.get_by_tenant_id(tenant_id)
|
||||
c.pop("createdAt")
|
||||
c["projects"] = projects.get_projects(tenant_id=tenant_id, recording_state=True, recorded=True,
|
||||
stack_integrations=True)
|
||||
stack_integrations=True, version=True)
|
||||
c["smtp"] = helper.has_smtp()
|
||||
return {
|
||||
'jwt': r.pop('jwt'),
|
||||
|
|
@ -83,7 +76,7 @@ def get_account(context):
|
|||
@app.route('/projects', methods=['GET'])
|
||||
def get_projects(context):
|
||||
return {"data": projects.get_projects(tenant_id=context["tenantId"], recording_state=True, gdpr=True, recorded=True,
|
||||
stack_integrations=True)}
|
||||
stack_integrations=True, version=True)}
|
||||
|
||||
|
||||
@app.route('/projects', methods=['POST', 'PUT'])
|
||||
|
|
@ -127,7 +120,7 @@ def get_client(context):
|
|||
if r is not None:
|
||||
r.pop("createdAt")
|
||||
r["projects"] = projects.get_projects(tenant_id=context['tenantId'], recording_state=True, recorded=True,
|
||||
stack_integrations=True)
|
||||
stack_integrations=True, version=True)
|
||||
return {
|
||||
'data': r
|
||||
}
|
||||
|
|
@ -148,7 +141,7 @@ def put_client(context):
|
|||
|
||||
@app.route('/signup', methods=['GET'], authorizer=None)
|
||||
def get_all_signup():
|
||||
return {"data": signup.get_signed_ups()}
|
||||
return {"data": tenants.tenants_exists()}
|
||||
|
||||
|
||||
@app.route('/signup', methods=['POST', 'PUT'], authorizer=None)
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ def __create(tenant_id, name):
|
|||
|
||||
|
||||
@dev.timed
|
||||
def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, stack_integrations=False):
|
||||
def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, stack_integrations=False,version=False):
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute(f"""\
|
||||
SELECT
|
||||
|
|
@ -49,6 +49,7 @@ def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, st
|
|||
{',s.gdpr' if gdpr else ''}
|
||||
{',COALESCE((SELECT TRUE FROM public.sessions WHERE sessions.project_id = s.project_id LIMIT 1), FALSE) AS recorded' if recorded else ''}
|
||||
{',stack_integrations.count>0 AS stack_integrations' if stack_integrations else ''}
|
||||
{',(SELECT tracker_version FROM public.sessions WHERE sessions.project_id = s.project_id ORDER BY start_ts DESC LIMIT 1) AS tracker_version' if version else ''}
|
||||
FROM public.projects AS s
|
||||
{'LEFT JOIN LATERAL (SELECT COUNT(*) AS count FROM public.integrations WHERE s.project_id = integrations.project_id LIMIT 1) AS stack_integrations ON TRUE' if stack_integrations else ''}
|
||||
where s.deleted_at IS NULL
|
||||
|
|
|
|||
|
|
@ -1,39 +1,31 @@
|
|||
from chalicelib.utils import helper
|
||||
from chalicelib.utils import pg_client
|
||||
from chalicelib.core import users, telemetry
|
||||
from chalicelib.core import users, telemetry, tenants
|
||||
from chalicelib.utils import captcha
|
||||
import json
|
||||
from chalicelib.utils.TimeUTC import TimeUTC
|
||||
from chalicelib.utils.helper import environ
|
||||
|
||||
|
||||
def get_signed_ups():
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute("SELECT tenant_id, name FROM public.tenants;")
|
||||
rows = cur.fetchall()
|
||||
return helper.list_to_camel_case(rows)
|
||||
|
||||
|
||||
def create_step1(data):
|
||||
print(f"===================== SIGNUP STEP 1 AT {TimeUTC.to_human_readable(TimeUTC.now())} UTC")
|
||||
errors = []
|
||||
if tenants.tenants_exists():
|
||||
return {"errors": ["tenants already registered"]}
|
||||
|
||||
email = data.get("email")
|
||||
print(f"=====================> {email}")
|
||||
password = data.get("password")
|
||||
|
||||
print("Verifying email validity")
|
||||
email_exists = False
|
||||
if email is None or len(email) < 5 or not helper.is_valid_email(email):
|
||||
errors.append("Invalid email address.")
|
||||
else:
|
||||
print("Verifying email existance")
|
||||
if users.email_exists(email):
|
||||
# errors.append("Email address already in use.")
|
||||
email_exists = True
|
||||
errors.append("Email address already in use.")
|
||||
if users.get_deleted_user_by_email(email) is not None:
|
||||
# errors.append("Email address previously deleted.")
|
||||
email_exists = True
|
||||
errors.append("Email address previously deleted.")
|
||||
|
||||
print("Verifying captcha")
|
||||
if helper.allow_captcha() and not captcha.is_valid(data["g-recaptcha-response"]):
|
||||
|
|
@ -57,12 +49,6 @@ def create_step1(data):
|
|||
project_name = data.get("projectName")
|
||||
if project_name is None or len(project_name) < 1:
|
||||
project_name = "my first project"
|
||||
signed_ups = get_signed_ups()
|
||||
if len(signed_ups) > 0 and data.get("tenantId") is None:
|
||||
errors.append("Tenant already exists, please select it from dropdown")
|
||||
elif len(signed_ups) == 0 and data.get("tenantId") is not None \
|
||||
or len(signed_ups) > 0 and data.get("tenantId") not in [t['tenantId'] for t in signed_ups]:
|
||||
errors.append("Tenant not found")
|
||||
|
||||
if len(errors) > 0:
|
||||
print("==> error")
|
||||
|
|
@ -77,41 +63,7 @@ def create_step1(data):
|
|||
"organizationName": company_name,
|
||||
"versionNumber": environ["version_number"]
|
||||
}
|
||||
if data.get("tenantId") is not None:
|
||||
update_user = """
|
||||
u AS (
|
||||
UPDATE public.users
|
||||
SET name = %(fullname)s, deleted_at=NULL
|
||||
WHERE email=%(email)s
|
||||
RETURNING user_id,email, role, name
|
||||
)
|
||||
UPDATE public.basic_authentication
|
||||
SET password= crypt(%(password)s, gen_salt('bf', 12))
|
||||
WHERE user_id = (SELECT user_id FROM u)"""
|
||||
insert_user = """
|
||||
a AS (
|
||||
UPDATE public.users
|
||||
SET role='admin'
|
||||
WHERE role ='owner'
|
||||
),
|
||||
u AS (
|
||||
INSERT INTO public.users (email, role, name, data)
|
||||
VALUES (%(email)s, 'owner', %(fullname)s,%(data)s)
|
||||
RETURNING user_id,email,role,name
|
||||
)
|
||||
INSERT INTO public.basic_authentication (user_id, password, generated_password)
|
||||
VALUES ((SELECT user_id FROM u), crypt(%(password)s, gen_salt('bf', 12)), FALSE)"""
|
||||
query = f"""\
|
||||
WITH t AS (
|
||||
UPDATE public.tenants
|
||||
SET name = %(organizationName)s,
|
||||
version_number = %(versionNumber)s
|
||||
RETURNING api_key
|
||||
),
|
||||
{update_user if email_exists else insert_user}
|
||||
RETURNING (SELECT api_key FROM t) AS api_key,(SELECT project_id FROM projects LIMIT 1) AS project_id;"""
|
||||
else:
|
||||
query = f"""\
|
||||
query = f"""\
|
||||
WITH t AS (
|
||||
INSERT INTO public.tenants (name, version_number, edition)
|
||||
VALUES (%(organizationName)s, %(versionNumber)s, 'fos')
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ def update(tenant_id, user_id, data):
|
|||
return edit_client(tenant_id=tenant_id, changes=changes)
|
||||
|
||||
|
||||
def get_tenants():
|
||||
def tenants_exists():
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute(f"SELECT name FROM public.tenants")
|
||||
return helper.list_to_camel_case(cur.fetchall())
|
||||
cur.execute(f"SELECT EXISTS(SELECT 1 FROM public.tenants)")
|
||||
return cur.fetchone()["exists"]
|
||||
|
|
|
|||
|
|
@ -22,13 +22,6 @@ app = Blueprint(__name__)
|
|||
_overrides.chalice_app(app)
|
||||
|
||||
|
||||
@app.route('/signedups', methods=['GET'], authorizer=None)
|
||||
def signed_ups():
|
||||
return {
|
||||
'data': tenants.get_tenants()
|
||||
}
|
||||
|
||||
|
||||
@app.route('/login', methods=['POST'], authorizer=None)
|
||||
def login():
|
||||
data = app.current_request.json_body
|
||||
|
|
@ -54,7 +47,7 @@ def login():
|
|||
c = tenants.get_by_tenant_id(tenant_id)
|
||||
c.pop("createdAt")
|
||||
c["projects"] = projects.get_projects(tenant_id=tenant_id, recording_state=True, recorded=True,
|
||||
stack_integrations=True)
|
||||
stack_integrations=True, version=True)
|
||||
return {
|
||||
'jwt': r.pop('jwt'),
|
||||
'data': {
|
||||
|
|
@ -85,7 +78,7 @@ def get_account(context):
|
|||
@app.route('/projects', methods=['GET'])
|
||||
def get_projects(context):
|
||||
return {"data": projects.get_projects(tenant_id=context["tenantId"], recording_state=True, gdpr=True, recorded=True,
|
||||
stack_integrations=True)}
|
||||
stack_integrations=True, version=True)}
|
||||
|
||||
|
||||
@app.route('/projects', methods=['POST', 'PUT'])
|
||||
|
|
@ -129,7 +122,7 @@ def get_client(context):
|
|||
if r is not None:
|
||||
r.pop("createdAt")
|
||||
r["projects"] = projects.get_projects(tenant_id=context['tenantId'], recording_state=True, recorded=True,
|
||||
stack_integrations=True)
|
||||
stack_integrations=True, version=True)
|
||||
return {
|
||||
'data': r
|
||||
}
|
||||
|
|
@ -148,10 +141,9 @@ def put_client(context):
|
|||
return tenants.update(tenant_id=context["tenantId"], user_id=context["userId"], data=data)
|
||||
|
||||
|
||||
# TODO: delete this for production; it is used for dev only
|
||||
@app.route('/signup', methods=['GET'], authorizer=None)
|
||||
def get_all_signup():
|
||||
return {"data": signup.get_signed_ups()}
|
||||
return {"data": tenants.tenants_exists()}
|
||||
|
||||
|
||||
@app.route('/signup', methods=['POST', 'PUT'], authorizer=None)
|
||||
|
|
@ -391,7 +383,8 @@ def change_password_by_invitation():
|
|||
if user["expiredChange"]:
|
||||
return {"errors": ["expired change, please re-use the invitation link"]}
|
||||
|
||||
return users.set_password_invitation(new_password=data["password"], user_id=user["userId"])
|
||||
return users.set_password_invitation(new_password=data["password"], user_id=user["userId"],
|
||||
tenant_id=user["tenantId"])
|
||||
|
||||
|
||||
@app.route('/client/members/{memberId}', methods=['PUT', 'POST'])
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ def __create(tenant_id, name):
|
|||
return get_project(tenant_id=tenant_id, project_id=project_id, include_gdpr=True)
|
||||
|
||||
|
||||
def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, stack_integrations=False):
|
||||
def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, stack_integrations=False, version=False):
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute(
|
||||
cur.mogrify(f"""\
|
||||
|
|
@ -49,6 +49,7 @@ def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, st
|
|||
{',s.gdpr' if gdpr else ''}
|
||||
{',COALESCE((SELECT TRUE FROM public.sessions WHERE sessions.project_id = s.project_id LIMIT 1), FALSE) AS recorded' if recorded else ''}
|
||||
{',stack_integrations.count>0 AS stack_integrations' if stack_integrations else ''}
|
||||
{',(SELECT tracker_version FROM public.sessions WHERE sessions.project_id = s.project_id ORDER BY start_ts DESC LIMIT 1) AS tracker_version' if version else ''}
|
||||
FROM public.projects AS s
|
||||
{'LEFT JOIN LATERAL (SELECT COUNT(*) AS count FROM public.integrations WHERE s.project_id = integrations.project_id LIMIT 1) AS stack_integrations ON TRUE' if stack_integrations else ''}
|
||||
where s.tenant_id =%(tenant_id)s
|
||||
|
|
|
|||
|
|
@ -1,22 +1,17 @@
|
|||
from chalicelib.utils import helper
|
||||
from chalicelib.utils import pg_client
|
||||
from chalicelib.core import users, telemetry
|
||||
from chalicelib.core import users, telemetry, tenants
|
||||
from chalicelib.utils import captcha
|
||||
import json
|
||||
from chalicelib.utils.TimeUTC import TimeUTC
|
||||
from chalicelib.utils.helper import environ
|
||||
|
||||
|
||||
def get_signed_ups():
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute("SELECT tenant_id, name FROM public.tenants;")
|
||||
rows = cur.fetchall()
|
||||
return helper.list_to_camel_case(rows)
|
||||
|
||||
|
||||
def create_step1(data):
|
||||
print(f"===================== SIGNUP STEP 1 AT {TimeUTC.to_human_readable(TimeUTC.now())} UTC")
|
||||
errors = []
|
||||
if tenants.tenants_exists():
|
||||
return {"errors":["tenants already registered"]}
|
||||
|
||||
email = data.get("email")
|
||||
print(f"=====================> {email}")
|
||||
|
|
@ -54,64 +49,37 @@ def create_step1(data):
|
|||
project_name = data.get("projectName")
|
||||
if project_name is None or len(project_name) < 1:
|
||||
project_name = "my first project"
|
||||
signed_ups = get_signed_ups()
|
||||
|
||||
if len(signed_ups) == 0 and data.get("tenantId") is not None \
|
||||
or len(signed_ups) > 0 and data.get("tenantId") is not None\
|
||||
and data.get("tenantId") not in [t['tenantId'] for t in signed_ups]:
|
||||
errors.append("Tenant not found")
|
||||
if len(errors) > 0:
|
||||
print("==> error")
|
||||
print(errors)
|
||||
return {"errors": errors}
|
||||
print("No errors detected")
|
||||
print("Decomposed infos")
|
||||
tenant_id = data.get("tenantId")
|
||||
|
||||
params = {"email": email, "password": password,
|
||||
"fullname": fullname, "companyName": company_name,
|
||||
"projectName": project_name,
|
||||
"versionNumber": environ["version_number"],
|
||||
"data": json.dumps({"lastAnnouncementView": TimeUTC.now()})}
|
||||
if tenant_id is not None:
|
||||
query = """\
|
||||
WITH t AS (
|
||||
UPDATE public.tenants
|
||||
SET name = %(companyName)s,
|
||||
version_number = %(versionNumber)s
|
||||
WHERE tenant_id=%(tenant_id)s
|
||||
query = """\
|
||||
WITH t AS (
|
||||
INSERT INTO public.tenants (name, version_number, edition)
|
||||
VALUES (%(companyName)s, %(versionNumber)s, 'ee')
|
||||
RETURNING tenant_id, api_key
|
||||
),
|
||||
u AS (
|
||||
UPDATE public.users
|
||||
SET email = %(email)s,
|
||||
name = %(fullname)s,
|
||||
WHERE role ='owner' AND tenant_id=%(tenant_id)s
|
||||
RETURNING user_id,email, role, name
|
||||
)
|
||||
UPDATE public.basic_authentication
|
||||
SET password= crypt(%(password)s, gen_salt('bf', 12))
|
||||
WHERE user_id = (SELECT user_id FROM u)
|
||||
RETURNING %(tenant_id)s AS tenant_id"""
|
||||
else:
|
||||
query = """\
|
||||
WITH t AS (
|
||||
INSERT INTO public.tenants (name, version_number, edition)
|
||||
VALUES (%(companyName)s, %(versionNumber)s, 'ee')
|
||||
RETURNING tenant_id, api_key
|
||||
),
|
||||
u AS (
|
||||
INSERT INTO public.users (tenant_id, email, role, name, data)
|
||||
VALUES ((SELECT tenant_id FROM t), %(email)s, 'owner', %(fullname)s,%(data)s)
|
||||
RETURNING user_id,email,role,name
|
||||
),
|
||||
au AS (
|
||||
INSERT INTO public.basic_authentication (user_id, password, generated_password)
|
||||
VALUES ((SELECT user_id FROM u), crypt(%(password)s, gen_salt('bf', 12)), FALSE)
|
||||
)
|
||||
INSERT INTO public.projects (tenant_id, name, active)
|
||||
VALUES ((SELECT t.tenant_id FROM t), %(projectName)s, TRUE)
|
||||
RETURNING tenant_id,project_id, (SELECT api_key FROM t) AS api_key;"""
|
||||
),
|
||||
u AS (
|
||||
INSERT INTO public.users (tenant_id, email, role, name, data)
|
||||
VALUES ((SELECT tenant_id FROM t), %(email)s, 'owner', %(fullname)s,%(data)s)
|
||||
RETURNING user_id,email,role,name
|
||||
),
|
||||
au AS (
|
||||
INSERT INTO public.basic_authentication (user_id, password, generated_password)
|
||||
VALUES ((SELECT user_id FROM u), crypt(%(password)s, gen_salt('bf', 12)), FALSE)
|
||||
)
|
||||
INSERT INTO public.projects (tenant_id, name, active)
|
||||
VALUES ((SELECT t.tenant_id FROM t), %(projectName)s, TRUE)
|
||||
RETURNING tenant_id,project_id, (SELECT api_key FROM t) AS api_key;"""
|
||||
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute(cur.mogrify(query, params))
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ def update(tenant_id, user_id, data):
|
|||
return edit_client(tenant_id=tenant_id, changes=changes)
|
||||
|
||||
|
||||
def get_tenants():
|
||||
def tenants_exists():
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute(f"SELECT name FROM public.tenants")
|
||||
return helper.list_to_camel_case(cur.fetchall())
|
||||
cur.execute(f"SELECT EXISTS(SELECT 1 FROM public.tenants)")
|
||||
return cur.fetchone()["exists"]
|
||||
|
|
|
|||
|
|
@ -440,11 +440,11 @@ def change_password(tenant_id, user_id, email, old_password, new_password):
|
|||
"jwt": authenticate(email, new_password)["jwt"]}
|
||||
|
||||
|
||||
def set_password_invitation(user_id, new_password):
|
||||
def set_password_invitation(tenant_id, user_id, new_password):
|
||||
changes = {"password": new_password, "generatedPassword": False,
|
||||
"invitationToken": None, "invitedAt": None,
|
||||
"changePwdExpireAt": None, "changePwdToken": None}
|
||||
user = update(tenant_id=-1, user_id=user_id, changes=changes)
|
||||
user = update(tenant_id=tenant_id, user_id=user_id, changes=changes)
|
||||
r = authenticate(user['email'], new_password)
|
||||
|
||||
tenant_id = r.pop("tenantId")
|
||||
|
|
|
|||
|
|
@ -53,21 +53,16 @@ export default class PlayerBlockHeader extends React.PureComponent {
|
|||
);
|
||||
|
||||
backHandler = () => {
|
||||
const { funnelRef, history, siteId } = this.props;
|
||||
const { history, siteId } = this.props;
|
||||
if (history.action !== 'POP')
|
||||
history.goBack();
|
||||
else
|
||||
history.push(withSiteId(SESSIONS_ROUTE), siteId);
|
||||
// if (funnelRef) {
|
||||
// history.push(withSiteId(funnelIssueRoute(funnelRef.funnelId, funnelRef.issueId), funnelRef.siteId));
|
||||
// } else {
|
||||
// history.push(withSiteId(SESSIONS_ROUTE), siteId);
|
||||
// }
|
||||
history.push(withSiteId(SESSIONS_ROUTE), siteId);
|
||||
}
|
||||
|
||||
toggleFavorite = () => {
|
||||
const { session } = this.props;
|
||||
this.props.toggleFavorite(session);
|
||||
this.props.toggleFavorite(session.sessionId);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
@ -123,8 +118,7 @@ export default class PlayerBlockHeader extends React.PureComponent {
|
|||
tooltip="Bookmark"
|
||||
onClick={ this.toggleFavorite }
|
||||
loading={ loading }
|
||||
icon={ favorite ? 'star-solid' : 'star' }
|
||||
// label={ favorite ? 'Favourited' : 'Favourite' }
|
||||
icon={ favorite ? 'star-solid' : 'star' }
|
||||
plain
|
||||
/>
|
||||
<SharePopup
|
||||
|
|
@ -135,8 +129,7 @@ export default class PlayerBlockHeader extends React.PureComponent {
|
|||
className="mr-2"
|
||||
tooltip="Share Session"
|
||||
disabled={ disabled }
|
||||
icon={ 'share-alt' }
|
||||
//label="Share"
|
||||
icon={ 'share-alt' }
|
||||
plain
|
||||
/>
|
||||
}
|
||||
|
|
|
|||
26
frontend/app/components/shared/Bookmark/Bookmark.tsx
Normal file
26
frontend/app/components/shared/Bookmark/Bookmark.tsx
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import React, { useState } from 'react'
|
||||
import stl from './bookmark.css'
|
||||
import { Icon } from 'UI'
|
||||
import { toggleFavorite } from 'Duck/sessions'
|
||||
import { connect } from 'react-redux'
|
||||
// import Session from 'Types/session';
|
||||
|
||||
interface Props {
|
||||
toggleFavorite: (session) => void,
|
||||
favorite: Boolean,
|
||||
sessionId: any
|
||||
}
|
||||
function Bookmark({ toggleFavorite, sessionId, favorite } : Props ) {
|
||||
|
||||
return (
|
||||
<div
|
||||
className={ stl.favoriteWrapper }
|
||||
onClick={ () => toggleFavorite(sessionId) }
|
||||
data-favourite={ favorite }
|
||||
>
|
||||
<Icon name={ favorite ? 'star-solid' : 'star' } size="20" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default connect(null, { toggleFavorite })(Bookmark)
|
||||
14
frontend/app/components/shared/Bookmark/bookmark.css
Normal file
14
frontend/app/components/shared/Bookmark/bookmark.css
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
.favoriteWrapper {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/* opacity: 0; */
|
||||
margin: 0 15px;
|
||||
|
||||
&[data-favourite=true] {
|
||||
opacity: 1;
|
||||
& svg {
|
||||
fill: $teal;
|
||||
}
|
||||
}
|
||||
}
|
||||
1
frontend/app/components/shared/Bookmark/index.js
Normal file
1
frontend/app/components/shared/Bookmark/index.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { default } from './Bookmark'
|
||||
|
|
@ -15,7 +15,7 @@ import { session as sessionRoute } from 'App/routes';
|
|||
import { durationFormatted, formatTimeOrDate } from 'App/date';
|
||||
import stl from './sessionItem.css';
|
||||
import LiveTag from 'Shared/LiveTag';
|
||||
import { session } from '../../../routes';
|
||||
import Bookmark from 'Shared/Bookmark';
|
||||
import Counter from './Counter'
|
||||
|
||||
const Label = ({ label = '', color = 'color-gray-medium'}) => (
|
||||
|
|
@ -25,15 +25,6 @@ const Label = ({ label = '', color = 'color-gray-medium'}) => (
|
|||
timezone: state.getIn(['sessions', 'timezone'])
|
||||
}), { toggleFavorite })
|
||||
export default class SessionItem extends React.PureComponent {
|
||||
state = { favouriting: false };
|
||||
|
||||
toggleFavorite = () => {
|
||||
this.setState({ favouriting: true });
|
||||
this.props.toggleFavorite(this.props.session).then(() => {
|
||||
this.setState({ favouriting: false });
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line complexity
|
||||
render() {
|
||||
const {
|
||||
|
|
@ -114,14 +105,8 @@ export default class SessionItem extends React.PureComponent {
|
|||
|
||||
{ live && <LiveTag isLive={true} /> }
|
||||
|
||||
<div className={ cn(stl.iconDetails, 'px-4') }>
|
||||
<div
|
||||
className={ stl.favoriteWrapper }
|
||||
onClick={ this.toggleFavorite }
|
||||
data-favourite={ favorite }
|
||||
>
|
||||
<Icon name={ favorite ? 'star-solid' : 'star' } size="20" />
|
||||
</div>
|
||||
<div className={ cn(stl.iconDetails, stl.favorite, 'px-4') } data-favourite={favorite} >
|
||||
<Bookmark sessionId={sessionId} favorite={favorite} />
|
||||
</div>
|
||||
|
||||
<div className={ stl.playLink } id="play-button" data-viewed={ viewed }>
|
||||
|
|
|
|||
|
|
@ -20,13 +20,20 @@
|
|||
align-items: center;
|
||||
border: solid thin #EEEEEE;
|
||||
|
||||
& .favorite {
|
||||
opacity: 0;
|
||||
&[data-favourite=true] {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
& .playLink {
|
||||
transition: all 0.4s;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
& .favoriteWrapper {
|
||||
& .favorite {
|
||||
transition: all 0.4s;
|
||||
opacity: 1;
|
||||
}
|
||||
|
|
@ -81,21 +88,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.favoriteWrapper {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
opacity: 0;
|
||||
margin: 0 15px;
|
||||
|
||||
&[data-favourite=true] {
|
||||
opacity: 1;
|
||||
& svg {
|
||||
fill: $teal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.playLink {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
|||
|
|
@ -120,9 +120,10 @@ const reducer = (state = initialState, action = {}) => {
|
|||
return state
|
||||
.set('list', list)
|
||||
.set('sessionIds', list.map(({ sessionId }) => sessionId ).toJS())
|
||||
.set('favoriteList', list.filter(({ favorite }) => favorite))
|
||||
.set('total', total)
|
||||
.set('keyMap', keyMap)
|
||||
.set('wdTypeCount', wdTypeCount);
|
||||
.set('wdTypeCount', wdTypeCount);
|
||||
case SET_AUTOPLAY_VALUES: {
|
||||
const sessionIds = state.get('sessionIds')
|
||||
const currentSessionId = state.get('current').sessionId
|
||||
|
|
@ -179,13 +180,15 @@ const reducer = (state = initialState, action = {}) => {
|
|||
.set('visitedEvents', visitedEvents)
|
||||
.set('host', visitedEvents[0] && visitedEvents[0].host);
|
||||
}
|
||||
case FETCH_FAVORITE_LIST.SUCCESS:
|
||||
case FETCH_FAVORITE_LIST.SUCCESS:
|
||||
return state
|
||||
.set('favoriteList', List(action.data).map(Session));
|
||||
case TOGGLE_FAVORITE.SUCCESS: {
|
||||
const id = action.session.sessionId;
|
||||
const id = action.sessionId;
|
||||
const session = state.get('list').find(({sessionId}) => sessionId === id)
|
||||
const wasInFavorite = state
|
||||
.get('favoriteList').findIndex(({ sessionId }) => sessionId === id) > -1;
|
||||
|
||||
return state
|
||||
.update('list', list => list
|
||||
.map(session => (session.sessionId === id
|
||||
|
|
@ -193,7 +196,7 @@ const reducer = (state = initialState, action = {}) => {
|
|||
: session)))
|
||||
.update('favoriteList', list => (wasInFavorite
|
||||
? list.filter(({ sessionId }) => sessionId !== id)
|
||||
: list.push(action.session.set('favorite', true))))
|
||||
: list.push(session.set('favorite', true))))
|
||||
.update('current', session => (session.sessionId === id
|
||||
? session.set('favorite', !wasInFavorite)
|
||||
: session));
|
||||
|
|
@ -283,11 +286,11 @@ export const fetch = (sessionId) => (dispatch, getState) => {
|
|||
});
|
||||
}
|
||||
|
||||
export function toggleFavorite(session) {
|
||||
export function toggleFavorite(sessionId) {
|
||||
return {
|
||||
types: TOGGLE_FAVORITE.toArray(),
|
||||
call: client => client.get(`/sessions2/${ session.sessionId }/favorite`),
|
||||
session,
|
||||
call: client => client.get(`/sessions2/${ sessionId }/favorite`),
|
||||
sessionId,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@openreplay/tracker-assist",
|
||||
"description": "Tracker plugin for screen assistance through the WebRTC",
|
||||
"version": "3.0.2",
|
||||
"version": "3.0.3",
|
||||
"keywords": [
|
||||
"WebRTC",
|
||||
"assistance",
|
||||
|
|
|
|||
|
|
@ -101,15 +101,22 @@ export default class CallWindow {
|
|||
|
||||
}
|
||||
|
||||
private aRemote: HTMLAudioElement | null = null;
|
||||
private localStream: MediaStream | null = null;
|
||||
private remoteStream: MediaStream | null = null;
|
||||
private setLocalVideoStream: (MediaStream) => void = () => {};
|
||||
private videoRequested: boolean = true; // TODO: green camera light
|
||||
private _trySetStreams() {
|
||||
if (this.vRemote && this.remoteStream) {
|
||||
if (this.vRemote && !this.vRemote.srcObject && this.remoteStream) {
|
||||
this.vRemote.srcObject = this.remoteStream;
|
||||
// Hack for audio (doesen't work in iframe because of some magical reasons)
|
||||
this.aRemote = document.createElement("audio");
|
||||
this.aRemote.autoplay = true;
|
||||
this.aRemote.style.display = "none"
|
||||
this.aRemote.srcObject = this.remoteStream;
|
||||
document.body.appendChild(this.aRemote)
|
||||
}
|
||||
if (this.vLocal && this.localStream) {
|
||||
if (this.vLocal && !this.vLocal.srcObject && this.localStream) {
|
||||
this.vLocal.srcObject = this.localStream;
|
||||
}
|
||||
}
|
||||
|
|
@ -195,6 +202,9 @@ export default class CallWindow {
|
|||
if (this.iframe.parentElement) {
|
||||
document.body.removeChild(this.iframe);
|
||||
}
|
||||
if (this.aRemote && this.aRemote.parentElement) {
|
||||
document.body.removeChild(this.aRemote);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -164,20 +164,20 @@ export default function(opts: Partial<Options> = {}) {
|
|||
});
|
||||
call.on('stream', function(rStream) {
|
||||
callUI.setRemoteStream(rStream);
|
||||
dataConn.on('data', (data: any) => {
|
||||
if (data === "call_end") {
|
||||
//console.log('receiving callend on call')
|
||||
onCallEnd();
|
||||
return;
|
||||
}
|
||||
if (data && typeof data.name === 'string') {
|
||||
//console.log("name",data)
|
||||
callUI.setAssistentName(data.name);
|
||||
}
|
||||
if (data && typeof data.x === 'number' && typeof data.y === 'number') {
|
||||
mouse.move(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
dataConn.on('data', (data: any) => {
|
||||
if (data === "call_end") {
|
||||
//console.log('receiving callend on call')
|
||||
onCallEnd();
|
||||
return;
|
||||
}
|
||||
if (data && typeof data.name === 'string') {
|
||||
//console.log("name",data)
|
||||
callUI.setAssistentName(data.name);
|
||||
}
|
||||
if (data && typeof data.x === 'number' && typeof data.y === 'number') {
|
||||
mouse.move(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue