pulled main branch and resovled coonflicts
This commit is contained in:
commit
cedabd0579
25 changed files with 166 additions and 74 deletions
33
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
33
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Report an issue and help improve OpenReplay
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: estradino
|
||||
|
||||
---
|
||||
|
||||
**Describe the issue**
|
||||
A short description of what the issue is.
|
||||
|
||||
**Steps to reproduce the issue**
|
||||
1. Step 1
|
||||
2. Step 2
|
||||
3. You got it :)
|
||||
|
||||
**Expected behavior**
|
||||
What you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If possible, that would be make our life easier.
|
||||
|
||||
**OpenReplay Environment**
|
||||
- Frontend stack: [e.g. React/Axios/MobX, Next]
|
||||
- OpenReplay version: [e.g. 1.6.0]
|
||||
- Tracker version: [e.g. 3.5.10]
|
||||
- Plugins used: [e.g. Fetch, Redux]
|
||||
- Cloud provider: [e.g. AWS, GCP]
|
||||
- System specs: [e.g. 2vCPU/16Gb with 50Gb of storage]
|
||||
|
||||
**Additional context**
|
||||
Add additional information you think might be relevant for this behavior.
|
||||
11
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
11
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Documentation Request
|
||||
url: https://github.com/openreplay/documentation/issues
|
||||
about: Report a mistake or suggest anything we might be missing in the docs
|
||||
- name: Discussions
|
||||
url: https://github.com/openreplay/openreplay/discussions
|
||||
about: Ask and answer various questions on GitHub Discussions
|
||||
- name: Join our Slack Community
|
||||
url: https://slack.openreplay.com
|
||||
about: Take the discussion further by joining our community on Slack
|
||||
10
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
10
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea or a feature to improve OpenReplay
|
||||
title: ''
|
||||
labels: feature-request
|
||||
assignees: estradino
|
||||
|
||||
---
|
||||
|
||||
Briefly describe the feature you would like to see shipped with the upcoming versions of OpenReplay, the use-case (very important to us) and the alternative solutions you've considered so far.
|
||||
1
.github/workflows/api.yaml
vendored
1
.github/workflows/api.yaml
vendored
|
|
@ -4,7 +4,6 @@ on:
|
|||
push:
|
||||
branches:
|
||||
- dev
|
||||
- api-v1.5.5
|
||||
paths:
|
||||
- api/**
|
||||
|
||||
|
|
|
|||
13
README.md
13
README.md
|
|
@ -31,7 +31,7 @@
|
|||
</a>
|
||||
</p>
|
||||
|
||||
OpenReplay is a session replay stack that lets you see what users do on your web app, helping you troubleshoot issues faster. It's the only open-source alternative to products such as FullStory and LogRocket.
|
||||
OpenReplay is a session replay suite you can host yourself, that lets you see what users do on your web app, helping you troubleshoot issues faster. It's the only open-source alternative to products such as FullStory and LogRocket.
|
||||
|
||||
- **Session replay.** OpenReplay replays what users do, but not only. It also shows you what went under the hood, how your website or app behaves by capturing network activity, console logs, JS errors, store actions/state, page speed metrics, cpu/memory usage and much more.
|
||||
- **Low footprint**. With a ~18KB (.gz) tracker that asynchronously sends minimal data for a very limited impact on performance.
|
||||
|
|
@ -59,6 +59,7 @@ OpenReplay can be deployed anywhere. Follow our step-by-step guides for deployin
|
|||
- [Azure](https://docs.openreplay.com/deployment/deploy-azure)
|
||||
- [Digital Ocean](https://docs.openreplay.com/deployment/deploy-digitalocean)
|
||||
- [Scaleway](https://docs.openreplay.com/deployment/deploy-scaleway)
|
||||
- [OVHcloud](https://docs.openreplay.com/deployment/deploy-ovhcloud)
|
||||
- [Kubernetes](https://docs.openreplay.com/deployment/deploy-kubernetes)
|
||||
|
||||
## OpenReplay Cloud
|
||||
|
|
@ -69,7 +70,7 @@ For those who want to simply use OpenReplay as a service, [sign up](https://app.
|
|||
|
||||
Please refer to the [official OpenReplay documentation](https://docs.openreplay.com/). That should help you troubleshoot common issues. For additional help, you can reach out to us on one of these channels:
|
||||
|
||||
- [Discord](https://discord.openreplay.com) (Connect with our engineers and community)
|
||||
- [Slack](https://slack.openreplay.com) (Connect with our engineers and community)
|
||||
- [GitHub](https://github.com/openreplay/openreplay/issues) (Bug and issue reports)
|
||||
- [Twitter](https://twitter.com/OpenReplayHQ) (Product updates, Great content)
|
||||
- [Website chat](https://openreplay.com) (Talk to us)
|
||||
|
|
@ -80,7 +81,7 @@ We're always on the lookout for contributions to OpenReplay, and we're glad you'
|
|||
|
||||
See our [Contributing Guide](CONTRIBUTING.md) for more details.
|
||||
|
||||
Also, feel free to join our [Discord](https://discord.openreplay.com) to ask questions, discuss ideas or connect with our contributors.
|
||||
Also, feel free to join our [Slack](https://slack.openreplay.com) to ask questions, discuss ideas or connect with our contributors.
|
||||
|
||||
## Roadmap
|
||||
|
||||
|
|
@ -89,3 +90,9 @@ Check out our [roadmap](https://www.notion.so/openreplay/Roadmap-889d2c3d968b478
|
|||
## License
|
||||
|
||||
This repo is under the Elastic License 2.0 (ELv2), with the exception of the `ee` directory.
|
||||
|
||||
## Contributors
|
||||
|
||||
<a href="https://github.com/openreplay/openreplay/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=openreplay/openreplay" />
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ func (c *cacher) cacheURL(requestURL string, sessionID uint64, depth byte, urlCo
|
|||
|
||||
strData := string(data)
|
||||
if isCSS {
|
||||
strData = c.rewriter.RewriteCSS(sessionID, requestURL, strData) // TODO: one method for reqrite and return list
|
||||
strData = c.rewriter.RewriteCSS(sessionID, requestURL, strData) // TODO: one method for rewrite and return list
|
||||
}
|
||||
|
||||
// TODO: implement in streams
|
||||
|
|
|
|||
0
backend/services/db/messages.go
Normal file
0
backend/services/db/messages.go
Normal file
|
|
@ -1,4 +1,4 @@
|
|||
The OpenReplay Enterprise license (the “Enterprise License”)
|
||||
Copyright (c) 2022 Asayer SAS.
|
||||
Copyright (c) 2022 Asayer, Inc.
|
||||
|
||||
To license the Enterprise Edition of OpenReplay, and take advantage of its additional features, functionality and support, you must agree to the terms of the OpenReplay Enterprise License Agreement. Please contact OpenReplay at [sales@openreplay.com](mailto:sales@openreplay.com).
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ import SessionsMenu from './SessionsMenu/SessionsMenu';
|
|||
import NoSessionsMessage from 'Shared/NoSessionsMessage';
|
||||
import SessionSearch from 'Shared/SessionSearch';
|
||||
import MainSearchBar from 'Shared/MainSearchBar';
|
||||
import { clearSearch, fetchSessions } from 'Duck/search';
|
||||
import { clearSearch, fetchSessions, addFilterByKeyAndValue } from 'Duck/search';
|
||||
import { FilterKey } from 'Types/filter/filterType';
|
||||
|
||||
const weakEqual = (val1, val2) => {
|
||||
if (!!val1 === false && !!val2 === false) return true;
|
||||
|
|
@ -62,6 +63,7 @@ const allowedQueryKeys = [
|
|||
setActiveTab,
|
||||
clearSearch,
|
||||
fetchSessions,
|
||||
addFilterByKeyAndValue,
|
||||
})
|
||||
@withPageTitle("Sessions - OpenReplay")
|
||||
export default class BugFinder extends React.PureComponent {
|
||||
|
|
@ -88,7 +90,11 @@ export default class BugFinder extends React.PureComponent {
|
|||
|
||||
const queryFilter = this.props.query.all(allowedQueryKeys);
|
||||
if (queryFilter.hasOwnProperty('userId')) {
|
||||
props.addAttribute({ label: 'User Id', key: KEYS.USERID, type: KEYS.USERID, operator: 'is', value: queryFilter.userId })
|
||||
props.addFilterByKeyAndValue(FilterKey.USERID, queryFilter.userId);
|
||||
} else {
|
||||
if (props.sessions.size === 0) {
|
||||
props.fetchSessions();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { useObserver } from 'mobx-react-lite';
|
|||
import { Icon } from 'UI';
|
||||
import cn from 'classnames';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { Loader } from 'UI';
|
||||
|
||||
function WidgetCategoryItem({ category, isSelected, onClick, selectedWidgetIds }) {
|
||||
const selectedCategoryWidgetsCount = useObserver(() => {
|
||||
|
|
@ -32,7 +33,8 @@ interface IProps {
|
|||
|
||||
function DashboardMetricSelection(props: IProps) {
|
||||
const { dashboardStore } = useStore();
|
||||
const widgetCategories: any[] = useObserver(() => dashboardStore.widgetCategories);
|
||||
let widgetCategories: any[] = useObserver(() => dashboardStore.widgetCategories);
|
||||
const loadingTemplates = useObserver(() => dashboardStore.loadingTemplates);
|
||||
const [activeCategory, setActiveCategory] = React.useState<any>();
|
||||
const [selectAllCheck, setSelectAllCheck] = React.useState(false);
|
||||
const selectedWidgetIds = useObserver(() => dashboardStore.selectedWidgets.map((widget: any) => widget.metricId));
|
||||
|
|
@ -65,7 +67,7 @@ function DashboardMetricSelection(props: IProps) {
|
|||
}
|
||||
|
||||
return useObserver(() => (
|
||||
<div>
|
||||
<Loader loading={loadingTemplates}>
|
||||
<div className="grid grid-cols-12 gap-4 my-3 items-end">
|
||||
<div className="col-span-3">
|
||||
<div className="uppercase color-gray-medium text-lg">Type</div>
|
||||
|
|
@ -137,7 +139,7 @@ function DashboardMetricSelection(props: IProps) {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Loader>
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { Button } from 'UI';
|
|||
import { withRouter } from 'react-router-dom';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { useModal } from 'App/components/Modal';
|
||||
import { dashboardMetricCreate, withSiteId } from 'App/routes';
|
||||
import { dashboardMetricCreate, withSiteId, dashboardSelected } from 'App/routes';
|
||||
|
||||
interface Props {
|
||||
history: any
|
||||
|
|
@ -19,13 +19,14 @@ function DashboardModal(props) {
|
|||
const { dashboardStore } = useStore();
|
||||
const selectedWidgetsCount = useObserver(() => dashboardStore.selectedWidgets.length);
|
||||
const { hideModal } = useModal();
|
||||
const loadingTemplates = useObserver(() => dashboardStore.loadingTemplates);
|
||||
const dashboard = useObserver(() => dashboardStore.dashboardInstance);
|
||||
const loading = useObserver(() => dashboardStore.isSaving);
|
||||
|
||||
const onSave = () => {
|
||||
dashboardStore.save(dashboard).then(async (syncedDashboard) => {
|
||||
if (dashboard.exists()) {
|
||||
await dashboardStore.fetch(dashboard.dashboardId)
|
||||
await dashboardStore.fetch(dashboard.dashboardId)
|
||||
}
|
||||
dashboardStore.selectDashboardById(syncedDashboard.dashboardId);
|
||||
history.push(withSiteId(`/dashboard/${syncedDashboard.dashboardId}`, siteId))
|
||||
|
|
@ -45,7 +46,7 @@ function DashboardModal(props) {
|
|||
<div style={{ width: '85vw' }}>
|
||||
<div
|
||||
className="border-r shadow p-4 h-screen"
|
||||
style={{ backgroundColor: '#FAFAFA', zIndex: 999, width: '100%' }}
|
||||
style={{ backgroundColor: '#FAFAFA', zIndex: 999, width: '85%', maxWidth: '1300px' }}
|
||||
>
|
||||
<div className="mb-6 flex items-end justify-between">
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ function WidgetWrapper(props: Props & RouteComponentProps) {
|
|||
onClick={props.onClick ? props.onClick : () => {}}
|
||||
id={`widget-${widget.widgetId}`}
|
||||
>
|
||||
{!isTemplate && isWidget && isPredefined &&
|
||||
{!isTemplate && isWidget && isPredefined &&
|
||||
<div
|
||||
className={cn(
|
||||
stl.drillDownMessage,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import { debounce } from 'App/utils';
|
|||
import Select from 'Shared/Select';
|
||||
import EmptyStateSvg from '../../../svg/no-results.svg';
|
||||
|
||||
const PER_PAGE = 10;
|
||||
const sortOptionsMap = {
|
||||
'occurrence-desc': 'Last Occurrence',
|
||||
'occurrence-desc': 'First Occurrence',
|
||||
|
|
@ -31,6 +30,7 @@ const sortOptions = Object.entries(sortOptionsMap)
|
|||
ignoreLoading: state.getIn([ "errors", "ignore", "loading" ]),
|
||||
mergeLoading: state.getIn([ "errors", "merge", "loading" ]),
|
||||
currentPage: state.getIn(["errors", "currentPage"]),
|
||||
limit: state.getIn(["errors", "limit"]),
|
||||
total: state.getIn([ 'errors', 'totalCount' ]),
|
||||
sort: state.getIn([ 'errors', 'options', 'sort' ]),
|
||||
order: state.getIn([ 'errors', 'options', 'order' ]),
|
||||
|
|
@ -56,9 +56,7 @@ export default class List extends React.PureComponent {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.list.size === 0) {
|
||||
this.props.applyFilter({ });
|
||||
}
|
||||
this.props.applyFilter({ });
|
||||
}
|
||||
|
||||
check = ({ errorId }) => {
|
||||
|
|
@ -146,6 +144,7 @@ export default class List extends React.PureComponent {
|
|||
total,
|
||||
sort,
|
||||
order,
|
||||
limit,
|
||||
} = this.props;
|
||||
const {
|
||||
checkedAll,
|
||||
|
|
@ -234,9 +233,9 @@ export default class List extends React.PureComponent {
|
|||
>
|
||||
<Loader loading={ loading }>
|
||||
{ list.map(e =>
|
||||
<div key={e.errorId}>
|
||||
<div key={e.errorId} style={{ opacity: e.disabled ? 0.5 : 1}}>
|
||||
<ListItem
|
||||
disabled={someLoading}
|
||||
disabled={someLoading || e.disabled}
|
||||
key={e.errorId}
|
||||
error={e}
|
||||
checked={ checkedIds.contains(e.errorId) }
|
||||
|
|
@ -248,9 +247,9 @@ export default class List extends React.PureComponent {
|
|||
<div className="w-full flex items-center justify-center mt-4">
|
||||
<Pagination
|
||||
page={currentPage}
|
||||
totalPages={Math.ceil(total / PER_PAGE)}
|
||||
totalPages={Math.ceil(total / limit)}
|
||||
onPageChange={(page) => this.props.updateCurrentPage(page)}
|
||||
limit={PER_PAGE}
|
||||
limit={limit}
|
||||
debounceRequest={500}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||
import { connect } from 'react-redux';
|
||||
import { setSiteId } from 'Duck/site';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { hasSiteId, siteChangeAvaliable } from 'App/routes';
|
||||
import { hasSiteId, siteChangeAvaliable, isRoute } from 'App/routes';
|
||||
import { STATUS_COLOR_MAP, GREEN } from 'Types/site';
|
||||
import { Icon, SlideModal } from 'UI';
|
||||
import { pushNewSite } from 'Duck/user'
|
||||
|
|
@ -42,10 +42,10 @@ export default class SiteDropdown extends React.PureComponent {
|
|||
}
|
||||
|
||||
switchSite = (siteId) => {
|
||||
const { mstore } = this.props
|
||||
const { mstore, location } = this.props
|
||||
|
||||
this.props.setSiteId(siteId);
|
||||
this.props.clearSearch();
|
||||
this.props.clearSearch(location.pathname.includes('/sessions'));
|
||||
this.props.fetchIntegrationVariables();
|
||||
|
||||
mstore.initClient();
|
||||
|
|
@ -59,7 +59,7 @@ export default class SiteDropdown extends React.PureComponent {
|
|||
const disabled = !siteChangeAvaliable(pathname);
|
||||
const showCurrent = hasSiteId(pathname) || siteChangeAvaliable(pathname);
|
||||
// const canAddSites = isAdmin && account.limits.projects && account.limits.projects.remaining !== 0;
|
||||
|
||||
|
||||
return (
|
||||
<div className={ styles.wrapper }>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ function MyApp() {
|
|||
//...
|
||||
}`
|
||||
|
||||
function InstallDocs({ siteId, sites }) {
|
||||
function InstallDocs({ siteId, sites }) {
|
||||
const site = sites.find(s => s.id === siteId);
|
||||
const _usageCode = usageCode.replace('PROJECT_KEY', site.projectKey)
|
||||
const _usageCodeSST = usageCodeSST.replace('PROJECT_KEY', site.projectKey)
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ function LiveSessionList(props: Props) {
|
|||
show={ !loading && list.size === 0}
|
||||
>
|
||||
<div className="bg-white p-3 rounded border">
|
||||
|
||||
|
||||
{list.map(session => (
|
||||
<>
|
||||
<SessionItem
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export default {
|
|||
BL: 'Saint Barthélemy',
|
||||
BM: 'Bermuda',
|
||||
BN: 'Brunei Darussalam',
|
||||
BO: 'Bolivia, Plurinational State Of',
|
||||
BO: 'Bolivia',
|
||||
BQ: 'Bonaire, Saint Eustatius And Saba',
|
||||
BR: 'Brazil',
|
||||
BS: 'Bahamas',
|
||||
|
|
@ -41,10 +41,10 @@ export default {
|
|||
BY: 'Belarus',
|
||||
BZ: 'Belize',
|
||||
CA: 'Canada',
|
||||
CC: 'Cocos (Keeling) Islands',
|
||||
CD: 'Democratic Republic Of Congo',
|
||||
CC: 'Cocos Islands',
|
||||
CD: 'Congo',
|
||||
CF: 'Central African Republic',
|
||||
CG: 'Republic Of Congo',
|
||||
CG: 'Congo',
|
||||
CH: 'Switzerland',
|
||||
CI: "Côte d'Ivoire",
|
||||
CK: 'Cook Islands',
|
||||
|
|
@ -62,7 +62,7 @@ export default {
|
|||
CX: 'Christmas Island',
|
||||
CY: 'Cyprus',
|
||||
CZ: 'Czech Republic',
|
||||
DD: 'German Democratic Republic',
|
||||
DD: 'Germany',
|
||||
DE: 'Germany',
|
||||
DG: 'Diego Garcia',
|
||||
DJ: 'Djibouti',
|
||||
|
|
@ -82,7 +82,7 @@ export default {
|
|||
FI: 'Finland',
|
||||
FJ: 'Fiji',
|
||||
FK: 'Falkland Islands',
|
||||
FM: 'Micronesia, Federated States Of',
|
||||
FM: 'Micronesia',
|
||||
FO: 'Faroe Islands',
|
||||
FQ: 'French Southern and Antarctic Territories',
|
||||
FR: 'France',
|
||||
|
|
@ -121,7 +121,7 @@ export default {
|
|||
IN: 'India',
|
||||
IO: 'British Indian Ocean Territory',
|
||||
IQ: 'Iraq',
|
||||
IR: 'Iran, Islamic Republic Of',
|
||||
IR: 'Iran',
|
||||
IS: 'Iceland',
|
||||
IT: 'Italy',
|
||||
JE: 'Jersey',
|
||||
|
|
@ -135,12 +135,12 @@ export default {
|
|||
KI: 'Kiribati',
|
||||
KM: 'Comoros',
|
||||
KN: 'Saint Kitts And Nevis',
|
||||
KP: "Korea, Democratic People's Republic Of",
|
||||
KR: 'Korea, Republic Of',
|
||||
KP: "Korea",
|
||||
KR: 'Korea',
|
||||
KW: 'Kuwait',
|
||||
KY: 'Cayman Islands',
|
||||
KZ: 'Kazakhstan',
|
||||
LA: "Lao People's Democratic Republic",
|
||||
LA: "Laos",
|
||||
LB: 'Lebanon',
|
||||
LC: 'Saint Lucia',
|
||||
LI: 'Liechtenstein',
|
||||
|
|
@ -159,7 +159,7 @@ export default {
|
|||
MG: 'Madagascar',
|
||||
MH: 'Marshall Islands',
|
||||
MI: 'Midway Islands',
|
||||
MK: 'Macedonia, The Former Yugoslav Republic Of',
|
||||
MK: 'Macedonia',
|
||||
ML: 'Mali',
|
||||
MM: 'Myanmar',
|
||||
MN: 'Mongolia',
|
||||
|
|
@ -192,7 +192,7 @@ export default {
|
|||
NZ: 'New Zealand',
|
||||
OM: 'Oman',
|
||||
PA: 'Panama',
|
||||
PC: 'Pacific Islands, Trust Territory of the',
|
||||
PC: 'Pacific Islands',
|
||||
PE: 'Peru',
|
||||
PF: 'French Polynesia',
|
||||
PG: 'Papua New Guinea',
|
||||
|
|
@ -202,7 +202,7 @@ export default {
|
|||
PM: 'Saint Pierre And Miquelon',
|
||||
PN: 'Pitcairn',
|
||||
PR: 'Puerto Rico',
|
||||
PS: 'Palestinian Territory, Occupied',
|
||||
PS: 'Palestine',
|
||||
PT: 'Portugal',
|
||||
PU: 'U.S. Miscellaneous Pacific Islands',
|
||||
PW: 'Palau',
|
||||
|
|
@ -245,7 +245,7 @@ export default {
|
|||
TH: 'Thailand',
|
||||
TJ: 'Tajikistan',
|
||||
TK: 'Tokelau',
|
||||
TL: 'Timor-Leste, Democratic Republic of',
|
||||
TL: 'Timor-Leste',
|
||||
TM: 'Turkmenistan',
|
||||
TN: 'Tunisia',
|
||||
TO: 'Tonga',
|
||||
|
|
@ -254,7 +254,7 @@ export default {
|
|||
TT: 'Trinidad And Tobago',
|
||||
TV: 'Tuvalu',
|
||||
TW: 'Taiwan',
|
||||
TZ: 'Tanzania, United Republic Of',
|
||||
TZ: 'Tanzania',
|
||||
UA: 'Ukraine',
|
||||
UG: 'Uganda',
|
||||
UM: 'United States Minor Outlying Islands',
|
||||
|
|
@ -263,17 +263,17 @@ export default {
|
|||
UZ: 'Uzbekistan',
|
||||
VA: 'Vatican City State',
|
||||
VC: 'Saint Vincent And The Grenadines',
|
||||
VD: 'Viet-Nam, Democratic Republic of',
|
||||
VE: 'Venezuela, Bolivarian Republic Of',
|
||||
VD: 'VietNam',
|
||||
VE: 'Venezuela',
|
||||
VG: 'Virgin Islands (British)',
|
||||
VI: 'Virgin Islands (US)',
|
||||
VN: 'Viet Nam',
|
||||
VN: 'VietNam',
|
||||
VU: 'Vanuatu',
|
||||
WF: 'Wallis And Futuna',
|
||||
WK: 'Wake Island',
|
||||
WS: 'Samoa',
|
||||
XK: 'Kosovo',
|
||||
YD: 'Yemen, Democratic',
|
||||
YD: 'Yemen',
|
||||
YE: 'Yemen',
|
||||
YT: 'Mayotte',
|
||||
YU: 'Yugoslavia',
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ const initialState = Map({
|
|||
stats: Map(),
|
||||
sourcemapUploaded: true,
|
||||
currentPage: 1,
|
||||
limit: PER_PAGE,
|
||||
options: Map({
|
||||
sort: DEFAULT_SORT,
|
||||
order: DEFAULT_ORDER,
|
||||
|
|
@ -57,7 +58,7 @@ function reducer(state = initialState, action = {}) {
|
|||
let updError;
|
||||
switch (action.type) {
|
||||
case EDIT_OPTIONS:
|
||||
return state.mergeIn(["options"], action.instance);
|
||||
return state.mergeIn(["options"], action.instance).set('currentPage', 1);
|
||||
case success(FETCH):
|
||||
if (state.get("list").find(e => e.get("errorId") === action.id)) {
|
||||
return updateItemInList(state, { errorId: action.data.errorId, viewed: true })
|
||||
|
|
@ -73,15 +74,15 @@ function reducer(state = initialState, action = {}) {
|
|||
.set("totalCount", data ? data.total : 0)
|
||||
.set("list", List(data && data.errors).map(ErrorInfo)
|
||||
.filter(e => e.parentErrorId == null)
|
||||
.map(e => e.update("chart", chartWrapper)));
|
||||
.map(e => e.update("chart", chartWrapper)))
|
||||
case success(RESOLVE):
|
||||
updError = { errorId: action.id, status: RESOLVED };
|
||||
updError = { errorId: action.id, status: RESOLVED, disabled: true };
|
||||
return updateItemInList(updateInstance(state, updError), updError);
|
||||
case success(UNRESOLVE):
|
||||
updError = { errorId: action.id, status: UNRESOLVED };
|
||||
updError = { errorId: action.id, status: UNRESOLVED, disabled: true };
|
||||
return updateItemInList(updateInstance(state, updError), updError);
|
||||
case success(IGNORE):
|
||||
updError = { errorId: action.id, status: IGNORED };
|
||||
updError = { errorId: action.id, status: IGNORED, disabled: true };
|
||||
return updateItemInList(updateInstance(state, updError), updError);
|
||||
case success(TOGGLE_FAVORITE):
|
||||
return state.mergeIn([ "instance" ], { favorite: !state.getIn([ "instance", "favorite" ]) })
|
||||
|
|
@ -163,28 +164,43 @@ export function fetchBookmarks() {
|
|||
}
|
||||
}
|
||||
|
||||
export function resolve(id) {
|
||||
return {
|
||||
export const resolve = (id) => (dispatch, getState) => {
|
||||
const list = getState().getIn(['errors', 'list']);
|
||||
const index = list.findIndex(e => e.get('errorId') === id);
|
||||
const error = list.get(index);
|
||||
if (error.get('status') === RESOLVED) return;
|
||||
|
||||
return dispatch({
|
||||
types: array(RESOLVE),
|
||||
id,
|
||||
call: client => client.get(`/errors/${ id }/solve`),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function unresolve(id) {
|
||||
return {
|
||||
export const unresolve = (id) => (dispatch, getState) => {
|
||||
const list = getState().getIn(['errors', 'list']);
|
||||
const index = list.findIndex(e => e.get('errorId') === id);
|
||||
const error = list.get(index);
|
||||
if (error.get('status') === UNRESOLVED) return;
|
||||
|
||||
return dispatch({
|
||||
types: array(UNRESOLVE),
|
||||
id,
|
||||
call: client => client.get(`/errors/${ id }/unsolve`),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function ignore(id) {
|
||||
return {
|
||||
export const ignore = (id) => (dispatch, getState) => {
|
||||
const list = getState().getIn(['errors', 'list']);
|
||||
const index = list.findIndex(e => e.get('errorId') === id);
|
||||
const error = list.get(index);
|
||||
if (error.get('status') === IGNORED) return;
|
||||
|
||||
return dispatch({
|
||||
types: array(IGNORE),
|
||||
id,
|
||||
call: client => client.get(`/errors/${ id }/ignore`),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function merge(ids) {
|
||||
|
|
|
|||
|
|
@ -180,6 +180,11 @@ export const edit = reduceThenFetchResource((instance) => ({
|
|||
instance,
|
||||
}));
|
||||
|
||||
export const editDefault = (instance) => ({
|
||||
type: EDIT,
|
||||
instance,
|
||||
});
|
||||
|
||||
export const setActiveTab = reduceThenFetchResource((tab) => ({
|
||||
type: SET_ACTIVE_TAB,
|
||||
tab,
|
||||
|
|
|
|||
|
|
@ -108,9 +108,9 @@ export default class DashboardStore implements IDashboardSotre {
|
|||
isLoading: boolean = true;
|
||||
isSaving: boolean = false;
|
||||
isDeleting: boolean = false;
|
||||
loadingTemplates: boolean = false
|
||||
fetchingDashboard: boolean = false;
|
||||
sessionsLoading: boolean = false;
|
||||
|
||||
showAlertModal: boolean = false;
|
||||
|
||||
constructor() {
|
||||
|
|
@ -379,6 +379,7 @@ export default class DashboardStore implements IDashboardSotre {
|
|||
};
|
||||
|
||||
fetchTemplates(hardRefresh): Promise<any> {
|
||||
this.loadingTemplates = true
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.widgetCategories.length > 0 && !hardRefresh) {
|
||||
resolve(this.widgetCategories);
|
||||
|
|
@ -389,11 +390,7 @@ export default class DashboardStore implements IDashboardSotre {
|
|||
const categories: any[] = [];
|
||||
response.forEach((category: any) => {
|
||||
const widgets: any[] = [];
|
||||
// TODO speed_location is not supported yet
|
||||
category.widgets
|
||||
.filter(
|
||||
(w: any) => w.predefinedKey !== "speed_locations"
|
||||
)
|
||||
.forEach((widget: any) => {
|
||||
const w = new Widget().fromJson(widget);
|
||||
widgets.push(w);
|
||||
|
|
@ -409,6 +406,8 @@ export default class DashboardStore implements IDashboardSotre {
|
|||
})
|
||||
.catch((error) => {
|
||||
reject(error);
|
||||
}).finally(() => {
|
||||
this.loadingTemplates = false
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -30,7 +30,11 @@ export default class FilterItem {
|
|||
merge: action
|
||||
})
|
||||
|
||||
|
||||
if (Array.isArray(data.filters)) {
|
||||
data.filters = data.filters.map(function (i) {
|
||||
return new FilterItem(i);
|
||||
});
|
||||
}
|
||||
|
||||
this.merge(data)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,9 +209,9 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
case "set_input_value":
|
||||
node = this.nl[ msg.id ]
|
||||
if (!node) { logger.error("Node not found", msg); return }
|
||||
if (!(node instanceof HTMLInputElement || node instanceof HTMLTextAreaElement)) {
|
||||
logger.error("Trying to set value of non-Input element", msg)
|
||||
return
|
||||
if (!(node instanceof HTMLInputElement || node instanceof HTMLTextAreaElement)) {
|
||||
logger.error("Trying to set value of non-Input element", msg)
|
||||
return
|
||||
}
|
||||
const val = msg.mask > 0 ? '*'.repeat(msg.mask) : msg.value
|
||||
doc = this.screen.document
|
||||
|
|
@ -281,7 +281,7 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
logger.warn("No iframe doc", msg, node, node.contentDocument);
|
||||
return;
|
||||
}
|
||||
this.nl[ msg.id ] = doc
|
||||
this.nl[ msg.id ] = doc.documentElement
|
||||
return;
|
||||
} else if (node instanceof Element) { // shadow DOM
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ const ErrorInfo = Record({
|
|||
chart30: [],
|
||||
tags: [],
|
||||
lastHydratedSession: Session(),
|
||||
disabled: false,
|
||||
}, {
|
||||
fromJS: ({ stack, lastHydratedSession, ...other }) => ({
|
||||
...other,
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ export default Record({
|
|||
filters: List(filters)
|
||||
.map(i => {
|
||||
const filter = NewFilter(i).toData();
|
||||
if (i.hasOwnProperty('filters')) {
|
||||
if (Array.isArray(i.filters)) {
|
||||
filter.filters = i.filters.map(f => NewFilter({...f, subFilter: i.type}).toData());
|
||||
}
|
||||
return filter;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ kafka: &kafka
|
|||
|
||||
|
||||
redis: &redis
|
||||
# For enterpriseEdition
|
||||
# enabled: false
|
||||
redisHost: "redis-master.db.svc.cluster.local"
|
||||
redisPort: "6379"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue