Skip to content

Commit

Permalink
Merge branch 'main' into typo
Browse files Browse the repository at this point in the history
  • Loading branch information
iamahens authored Oct 19, 2023
2 parents 24d3c1f + 43286f9 commit 8ba591e
Show file tree
Hide file tree
Showing 44 changed files with 1,018 additions and 868 deletions.
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ copilot:walkthrough

## Checklist ✅
- [ ] Label appropriately with `Feature`, `Improvement`, or `Bug`.
- [ ] Add screehshots to the PR description for relevant FE changes
- [ ] Add screenshots to the PR description for relevant FE changes
- [ ] New backend functionality has been unit-tested.
- [ ] API documentation has been updated (if necessary) (see [docs on API documentation](https://docs.crowd.dev/docs/updating-api-documentation)).
- [ ] [Quality standards](https://github.com/CrowdDotDev/crowd-github-test-public/blob/main/CONTRIBUTING.md#quality-standards) are met.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

<!-- BODY -->

<img src="https://user-images.githubusercontent.com/41432658/198830271-cbe6d3c7-0c46-4539-98cc-b13c495ddedf.png" alt="UI Home screen">
<img src="https://github.com/CrowdDotDev/crowd.dev/assets/22342669/845fc5b0-aba7-40fe-950e-85ef567cec65" alt="UI Home screen">


## Table of Contents
Expand All @@ -51,7 +51,7 @@ crowd.dev is open-source, built with developers in mind, available for both host

**To our developer community:**
- You can self-host crowd.dev to centralize data for your community or company while keeping full control over your data.
- Our product is built for extensibilty. If you can think of any use cases that you want to build with the data we collect and store for you, please go ahead and build it! We will be here to help out if you need us.
- Our product is built for extensibility. If you can think of any use cases that you want to build with the data we collect and store for you, please go ahead and build it! We will be here to help out if you need us.
- You can actively contribute to crowd.dev (e.g. integrations), and we will be supporting you along the journey. Just take a look at our [Contributing guide](https://github.com/CrowdDotDev/crowd.dev/blob/main/CONTRIBUTING.md).

## ✨ Features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@ SELECT
WHEN (a.sentiment->>'sentiment')::integer < 34 THEN 'negative'
WHEN (a.sentiment->>'sentiment')::integer > 66 THEN 'positive'
ELSE 'neutral'
END::VARCHAR(8) AS "sentimentMood"
END::VARCHAR(8) AS "sentimentMood",
a."organizationId",
a."segmentId",
a."conversationId"
FROM activities a
WHERE a."deletedAt" IS NULL
;

DROP MATERIALIZED VIEW IF EXISTS mv_organizations_cube;
Expand All @@ -57,6 +61,7 @@ FROM segments

CREATE INDEX IF NOT EXISTS mv_members_cube_tenant ON mv_members_cube ("tenantId");
CREATE INDEX IF NOT EXISTS mv_activities_cube_timestamp ON mv_activities_cube (timestamp);
CREATE INDEX IF NOT EXISTS mv_activities_cube_org_id ON mv_activities_cube ("organizationId");

CREATE UNIQUE INDEX IF NOT EXISTS mv_members_cube_id ON mv_members_cube (id);
CREATE UNIQUE INDEX IF NOT EXISTS mv_activities_cube_id ON mv_activities_cube (id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ async function createActivitiesForMembers(memberIds: string[], organizationId: s
neutral: 0.02,
mixed: 0.0,
label: 'positive',
sentiment: 0.98,
sentiment: 98,
},
isContribution: true,
username: 'test',
Expand Down Expand Up @@ -256,6 +256,9 @@ describe('OrganizationRepository tests', () => {
mockIRepositoryOptions,
)
await createActivitiesForMembers(memberIds, organizationCreated.id, mockIRepositoryOptions)
await mockIRepositoryOptions.database.sequelize.query(
'REFRESH MATERIALIZED VIEW mv_activities_cube',
)

organizationCreated = await OrganizationRepository.findById(
organizationCreated.id,
Expand Down
1 change: 1 addition & 0 deletions backend/src/database/repositories/memberRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3142,6 +3142,7 @@ class MemberRepository {

output.activities = await record.getActivities({
order: [['timestamp', 'DESC']],
limit: 20,
transaction,
})

Expand Down
157 changes: 83 additions & 74 deletions backend/src/database/repositories/organizationRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1972,90 +1972,99 @@ class OrganizationRepository {
}

// query for all leaf segment ids
let segmentsSubQuery = `
select id
from segments
where "tenantId" = :tenantId and "parentSlug" is not null and "grandparentSlug" is not null
let extraCTEs = `
leaf_segment_ids AS (
select id
from segments
where "tenantId" = :tenantId and "parentSlug" is not null and "grandparentSlug" is not null
),
`

if (segmentId) {
// we load data for a specific segment (can be leaf, parent or grand parent id)
replacements.segmentId = segmentId
segmentsSubQuery = `
with input_segment as (select id,
slug,
"parentSlug",
"grandparentSlug"
from segments
where id = :segmentId
and "tenantId" = :tenantId),
segment_level as (select case
when "parentSlug" is not null and "grandparentSlug" is not null
then 'child'
when "parentSlug" is not null and "grandparentSlug" is null
then 'parent'
when "parentSlug" is null and "grandparentSlug" is null
then 'grandparent'
end as level,
id,
slug,
"parentSlug",
"grandparentSlug"
from input_segment)
select s.id
from segments s
join
segment_level sl
on
(sl.level = 'child' and s.id = sl.id) or
(sl.level = 'parent' and s."parentSlug" = sl.slug and s."grandparentSlug" is not null) or
(sl.level = 'grandparent' and s."grandparentSlug" = sl.slug)`
extraCTEs = `
input_segment AS (
select
id,
slug,
"parentSlug",
"grandparentSlug"
from segments
where id = :segmentId
and "tenantId" = :tenantId
),
segment_level AS (
select
case
when "parentSlug" is not null and "grandparentSlug" is not null
then 'child'
when "parentSlug" is not null and "grandparentSlug" is null
then 'parent'
when "parentSlug" is null and "grandparentSlug" is null
then 'grandparent'
end as level,
id,
slug,
"parentSlug",
"grandparentSlug"
from input_segment
),
leaf_segment_ids AS (
select s.id
from segments s
join segment_level sl on (sl.level = 'child' and s.id = sl.id)
or (sl.level = 'parent' and s."parentSlug" = sl.slug and s."grandparentSlug" is not null)
or (sl.level = 'grandparent' and s."grandparentSlug" = sl.slug)
),
`
}

const query = `
with leaf_segment_ids as (${segmentsSubQuery}),
member_data as (select a."organizationId",
count(distinct a."memberId") as "memberCount",
count(distinct a.id) as "activityCount",
case
when array_agg(distinct a.platform) = array [null] then array []::text[]
else array_agg(distinct a.platform) end as "activeOn",
max(a.timestamp) as "lastActive",
min(a.timestamp) filter ( where a.timestamp <> '1970-01-01T00:00:00.000Z' ) as "joinedAt"
from leaf_segment_ids ls
join activities a
on a."segmentId" = ls.id and a."organizationId" = :id and
a."deletedAt" is null
join "organizationSegments" os on a."segmentId" = os."segmentId" and os."organizationId" = :id
join members m on a."memberId" = m.id and m."deletedAt" is null
join "memberOrganizations" mo on m.id = mo."memberId" and mo."organizationId" = :id and mo."dateEnd" is null
group by a."organizationId"),
organization_segments as (select "organizationId", array_agg("segmentId") as "segments"
WITH
${extraCTEs}
member_data AS (
select
a."organizationId",
count(distinct a."memberId") as "memberCount",
count(distinct a.id) as "activityCount",
case
when array_agg(distinct a.platform::TEXT) = array [null] then array []::text[]
else array_agg(distinct a.platform::TEXT) end as "activeOn",
max(a.timestamp) as "lastActive",
min(a.timestamp) filter ( where a.timestamp <> '1970-01-01T00:00:00.000Z' ) as "joinedAt"
from leaf_segment_ids ls
join mv_activities_cube a on a."segmentId" = ls.id and a."organizationId" = :id
group by a."organizationId"
),
organization_segments as (
select "organizationId", array_agg("segmentId") as "segments"
from "organizationSegments"
where "organizationId" = :id
group by "organizationId"),
identities as (
SELECT oi."organizationId", jsonb_agg(oi) AS "identities"
FROM "organizationIdentities" oi
WHERE oi."organizationId" = :id
GROUP BY "organizationId"
)
select
o.*,
coalesce(md."activityCount", 0)::integer as "activityCount",
coalesce(md."memberCount", 0)::integer as "memberCount",
coalesce(md."activeOn", '{}') as "activeOn",
coalesce(i.identities, '{}') as identities,
coalesce(os.segments, '{}') as segments,
md."lastActive",
md."joinedAt"
from organizations o
left join member_data md on md."organizationId" = o.id
left join organization_segments os on os."organizationId" = o.id
left join identities i on i."organizationId" = o.id
where o.id = :id
and o."tenantId" = :tenantId;
`
group by "organizationId"
),
identities as (
SELECT oi."organizationId", jsonb_agg(oi) AS "identities"
FROM "organizationIdentities" oi
WHERE oi."organizationId" = :id
GROUP BY "organizationId"
)
select
o.*,
coalesce(md."activityCount", 0)::integer as "activityCount",
coalesce(md."memberCount", 0)::integer as "memberCount",
coalesce(md."activeOn", '{}') as "activeOn",
coalesce(i.identities, '{}') as identities,
coalesce(os.segments, '{}') as segments,
md."lastActive",
md."joinedAt"
from organizations o
left join member_data md on md."organizationId" = o.id
left join organization_segments os on os."organizationId" = o.id
left join identities i on i."organizationId" = o.id
where o.id = :id
and o."tenantId" = :tenantId;
`

const results = await sequelize.query(query, {
replacements,
Expand Down
1 change: 1 addition & 0 deletions frontend/src/i18n/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ const en = {
cubejs: {
tooltip: {
Activities: 'Activity',
Contacts: 'Contact',
Members: 'Contact',
Conversations: 'Conversation',
Organizations: 'Organization',
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/modules/organization/organization-model.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import JsonField from '@/shared/fields/json-field';
import StringArrayField from '@/shared/fields/string-array-field';
import IntegerField from '@/shared/fields/integer-field';
import BooleanField from '@/shared/fields/boolean-field';
import GenericField from '@/shared/fields/generic-field';
import OrganizationHeadcountField from './organization-headcount-field';
import OrganizationEmployeesField from './organization-employees-field';
import OrganizationTypeField from './organization-type-field';
Expand Down Expand Up @@ -107,7 +108,7 @@ const fields = {
allSubsidiaries: new StringArrayField('allSubsidiaries', 'All Subsidiaries'),
alternativeDomains: new StringArrayField('alternativeDomains', 'Alternative Domains'),
alternativeNames: new StringArrayField('alternativeNames', 'Alternative Names'),
averageEmployeeTenure: new IntegerField('averageEmployeeTenure', 'Average Employee Tenure'),
averageEmployeeTenure: new GenericField('averageEmployeeTenure', 'Average Employee Tenure'),
averageTenureByLevel: new JsonField('averageTenureByLevel', 'Average Tenure by Level'),
averageTenureByRole: new JsonField('averageTenureByRole', 'Average Tenure by Role'),
directSubsidiaries: new StringArrayField('directSubsidiaries', 'Direct Subsidiaries'),
Expand Down
12 changes: 0 additions & 12 deletions frontend/src/modules/report/components/report-create-dialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ import {
} from 'vue';
import { useRouter } from 'vue-router';
import { ReportService } from '@/modules/report/report-service';
import { ReportModel } from '@/modules/report/report-model';
import { FormSchema } from '@/shared/form/form-schema';
const router = useRouter();
const props = defineProps({
Expand All @@ -73,16 +71,6 @@ const props = defineProps({
});
const emit = defineEmits('update:modelValue');
const { fields } = ReportModel;
const formSchema = new FormSchema([
fields.name,
fields.widgets,
fields.settings,
fields.public,
]);
const rules = reactive(formSchema.rules());
const visible = computed({
get() {
return props.modelValue;
Expand Down
39 changes: 13 additions & 26 deletions frontend/src/modules/report/components/report-form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@
v-if="record"
ref="form"
:model="model"
:rules="rules"
class="report-form"
>
<el-input
ref="focus"
v-model="model[fields.name.name]"
:placeholder="fields.name.placeholder"
v-model="model.name"
class="report-form-title"
@input="onTitleUpdate"
/>
<ReportGridLayout
v-model="model"
Expand All @@ -23,11 +22,9 @@
</template>

<script setup>
import { defineProps, reactive, watch } from 'vue';
import { defineProps, reactive } from 'vue';
import debounce from 'lodash/debounce';
import { mapActions } from '@/shared/vuex/vuex.helpers';
import { FormSchema } from '@/shared/form/form-schema';
import { ReportModel } from '@/modules/report/report-model';
import ReportGridLayout from './report-grid-layout.vue';
const props = defineProps({
Expand All @@ -37,31 +34,21 @@ const props = defineProps({
},
});
const { fields } = ReportModel;
const formSchema = new FormSchema([
fields.name,
fields.widgets,
fields.settings,
fields.public,
]);
const { doUpdate } = mapActions('report');
const rules = formSchema.rules();
const model = reactive(
JSON.parse(JSON.stringify(props.record)),
);
const model = reactive(props.record);
const { doUpdate } = mapActions('report');
const onTitleUpdate = debounce(async (value) => {
model.name = value;
const debouncedChange = debounce(async () => {
await doUpdate({
id: props.record && props.record.id,
values: formSchema.cast(model),
id: props.record.id,
values: {
...model,
widgets: model.widgets.map((w) => w.id),
},
});
}, 1000);
watch(model, () => {
debouncedChange();
});
}, 500);
</script>

<script>
Expand Down
Loading

0 comments on commit 8ba591e

Please sign in to comment.