Skip to content

Commit

Permalink
Merge pull request #1389 from the-deep/project/auto-extraction
Browse files Browse the repository at this point in the history
Project/auto extraction
  • Loading branch information
AdityaKhatri authored Dec 21, 2023
2 parents 17ba540 + ffb969b commit d98368a
Show file tree
Hide file tree
Showing 50 changed files with 2,521 additions and 2,727 deletions.
33 changes: 8 additions & 25 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
name: 🚴 Build + Test 🚴 # Match the name below (8398a7/action-slack).
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@master

- name: 🐳 Prepare Docker
id: prep
Expand All @@ -24,17 +24,8 @@ jobs:
id: buildx
uses: docker/setup-buildx-action@master

- name: 🐳 Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.ref }}
restore-keys: |
${{ runner.os }}-buildx-refs/develop
${{ runner.os }}-buildx-
- name: 🐳 Build image
uses: docker/build-push-action@v2
uses: docker/build-push-action@v4
with:
context: .
builder: ${{ steps.buildx.outputs.name }}
Expand All @@ -43,8 +34,9 @@ jobs:
load: true
target: worker # this has all the dep
tags: ${{ steps.prep.outputs.tagged_image }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new
# Using experimental GH api: https://docs.docker.com/build/ci/github-actions/cache/#cache-backend-api
cache-from: type=gha
cache-to: type=gha,mode=max

- name: 🕮 Validate latest graphql schema.
env:
Expand All @@ -67,7 +59,7 @@ jobs:
}
- name: 🤞 Run Test 🧪 & Publish coverage to code climate
uses: paambaati/codeclimate-action@v2.7.5
uses: paambaati/codeclimate-action@v5.0.0
env:
CC_TEST_REPORTER_ID: ${{ secrets.CODE_CLIMATE_ID }}
DOCKER_IMAGE_SERVER: ${{ steps.prep.outputs.tagged_image }}
Expand All @@ -77,19 +69,10 @@ jobs:
${{github.workspace}}/coverage/coverage.xml:coverage.py
- name: Publish coverage to code cov
uses: codecov/codecov-action@v2

# Temp fix
# https://github.com/docker/build-push-action/blob/master/docs/advanced/cache.md#github-cache
# https://github.com/docker/build-push-action/issues/252
# https://github.com/moby/buildkit/issues/1896
- name: 🐳 Move docker cache (🧙 Hack fix)
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
uses: codecov/codecov-action@v3

- name: Deploy coverage to GH Pages 🚀
uses: JamesIves/github-pages-deploy-action@4.1.4
uses: JamesIves/github-pages-deploy-action@v4
if: github.ref == 'refs/heads/develop' && github.event_name == 'push'
with:
branch: gh-pages
Expand Down
6 changes: 6 additions & 0 deletions apps/analysis_framework/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from .models import (
AnalysisFramework,
AnalysisFrameworkTag,
AnalysisFrameworkRole,
AnalysisFrameworkMembership,
Section,
Expand Down Expand Up @@ -113,3 +114,8 @@ class AnalysisFrameworkRoleAdmin(admin.ModelAdmin):

def has_add_permission(self, request, obj=None):
return False


@admin.register(AnalysisFrameworkTag)
class AnalysisFrameworkTagAdmin(admin.ModelAdmin):
list_display = ('id', 'title',)
16 changes: 16 additions & 0 deletions apps/analysis_framework/dataloaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
Filter,
Exportable,
AnalysisFrameworkMembership,
AnalysisFramework,
)


Expand Down Expand Up @@ -90,6 +91,17 @@ def batch_load_fn(self, keys):
return Promise.resolve([_map[key] for key in keys])


class AnalysisFrameworkTagsLoader(DataLoaderWithContext):
def batch_load_fn(self, keys):
qs = AnalysisFramework.tags.through.objects.filter(
analysisframework__in=keys,
).select_related('analysisframeworktag')
_map = defaultdict(list)
for row in qs:
_map[row.analysisframework_id].append(row.analysisframeworktag)
return Promise.resolve([_map[key] for key in keys])


class DataLoaders(WithContextMixin):
@cached_property
def secondary_widgets(self):
Expand All @@ -114,3 +126,7 @@ def exportables(self):
@cached_property
def members(self):
return MembershipLoader(context=self.context)

@cached_property
def af_tags(self):
return AnalysisFrameworkTagsLoader(context=self.context)
25 changes: 25 additions & 0 deletions apps/analysis_framework/factories.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,47 @@
import factory
from factory import fuzzy
from factory.django import DjangoModelFactory
from django.core.files.base import ContentFile

from .models import (
AnalysisFramework,
AnalysisFrameworkTag,
Section,
Widget,
Filter,
)


class AnalysisFrameworkTagFactory(DjangoModelFactory):
title = factory.Sequence(lambda n: f'AF-Tag-{n}')
description = factory.Faker('sentence', nb_words=20)
icon = factory.LazyAttribute(
lambda n: ContentFile(
factory.django.ImageField()._make_data(
{'width': 100, 'height': 100}
), f'example_{n.title}.png'
)
)

class Meta:
model = AnalysisFrameworkTag


class AnalysisFrameworkFactory(DjangoModelFactory):
title = factory.Sequence(lambda n: f'AF-{n}')
description = factory.Faker('sentence', nb_words=20)

class Meta:
model = AnalysisFramework

@factory.post_generation
def tags(self, create, extracted, **_):
if not create:
return
if extracted:
for tag in extracted:
self.tags.add(tag)


class SectionFactory(DjangoModelFactory):
title = factory.Sequence(lambda n: f'Section-{n}')
Expand Down
19 changes: 19 additions & 0 deletions apps/analysis_framework/filter_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
UserResourceFilterSet,
UserResourceGqlFilterSet,
)
from utils.graphene.filters import IDListFilter

from .models import (
AnalysisFramework,
AnalysisFrameworkTag,
)
from entry.models import Entry
from django.utils import timezone
Expand All @@ -28,7 +31,22 @@ class Meta:
},
}


# ----------------------------- Graphql Filters ---------------------------------------
class AnalysisFrameworkTagGqFilterSet(django_filters.FilterSet):
search = django_filters.CharFilter(method='search_filter')

class Meta:
model = AnalysisFrameworkTag
fields = ['id']

def search_filter(self, qs, _, value):
if value:
return qs.filter(
models.Q(title__icontains=value) |
models.Q(description__icontains=value)
)
return qs


class AnalysisFrameworkGqFilterSet(UserResourceGqlFilterSet):
Expand All @@ -39,6 +57,7 @@ class AnalysisFrameworkGqFilterSet(UserResourceGqlFilterSet):
method='filter_recently_used',
label='Recently Used',
)
tags = IDListFilter(distinct=True)

class Meta:
model = AnalysisFramework
Expand Down
27 changes: 27 additions & 0 deletions apps/analysis_framework/migrations/0040_auto_20231109_1208.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 3.2.17 on 2023-11-09 12:08

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('analysis_framework', '0039_analysisframework_cloned_from'),
]

operations = [
migrations.CreateModel(
name='AnalysisFrameworkTag',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=255)),
('description', models.TextField(blank=True)),
('icon', models.FileField(max_length=255, upload_to='af-tag-icon/')),
],
),
migrations.AddField(
model_name='analysisframework',
name='tags',
field=models.ManyToManyField(blank=True, related_name='_analysis_framework_analysisframework_tags_+', to='analysis_framework.AnalysisFrameworkTag'),
),
]
10 changes: 10 additions & 0 deletions apps/analysis_framework/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@
from .widgets import store as widgets_store


class AnalysisFrameworkTag(models.Model):
title = models.CharField(max_length=255)
description = models.TextField(blank=True)
icon = models.FileField(upload_to='af-tag-icon/', max_length=255)

def __str__(self):
return self.title


class AnalysisFramework(UserResource):
"""
Analysis framework defining framework to do analysis
Expand All @@ -19,6 +28,7 @@ class AnalysisFramework(UserResource):
"""
title = models.CharField(max_length=255)
description = models.TextField(blank=True, null=True)
tags = models.ManyToManyField(AnalysisFrameworkTag, related_name='+', blank=True)

is_private = models.BooleanField(default=False)
assisted_tagging_enabled = models.BooleanField(default=False)
Expand Down
42 changes: 39 additions & 3 deletions apps/analysis_framework/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from assisted_tagging.models import PredictionTagAnalysisFrameworkWidgetMapping
from .models import (
AnalysisFramework,
AnalysisFrameworkTag,
Section,
Widget,
Filter,
Expand All @@ -29,7 +30,7 @@
AnalysisFrameworkRoleTypeEnum,
)
from .serializers import AnalysisFrameworkPropertiesGqlSerializer
from .filter_set import AnalysisFrameworkGqFilterSet
from .filter_set import AnalysisFrameworkGqFilterSet, AnalysisFrameworkTagGqFilterSet
from .public_schema import PublicAnalysisFrameworkListType


Expand Down Expand Up @@ -84,6 +85,18 @@ def resolve_widgets(root, info):
return info.context.dl.analysis_framework.sections_widgets.load(root.id)


class AnalysisFrameworkTagType(DjangoObjectType):
class Meta:
model = AnalysisFrameworkTag
only_fields = (
'id',
'title',
'description',
)

icon = graphene.Field(FileFieldType, required=False)


# NOTE: We have AnalysisFrameworkDetailType for detailed AF Type.
class AnalysisFrameworkType(DjangoObjectType):
class Meta:
Expand All @@ -96,12 +109,19 @@ class Meta:
current_user_role = graphene.Field(AnalysisFrameworkRoleTypeEnum)
preview_image = graphene.Field(FileFieldType)
export = graphene.Field(FileFieldType)
cloned_from = graphene.ID(source='cloned_from_id')
allowed_permissions = graphene.List(
graphene.NonNull(
graphene.Enum.from_enum(AfP.Permission),
), required=True
),
required=True,
)
tags = graphene.List(
graphene.NonNull(
AnalysisFrameworkTagType,
),
required=True,
)
cloned_from = graphene.ID(source='cloned_from_id')

@staticmethod
def get_custom_node(_, info, id):
Expand All @@ -123,6 +143,10 @@ def resolve_allowed_permissions(root, info):
is_public=not root.is_private,
)

@staticmethod
def resolve_tags(root, info):
return info.context.dl.analysis_framework.af_tags.load(root.id)


class AnalysisFrameworkRoleType(DjangoObjectType):
class Meta:
Expand Down Expand Up @@ -251,6 +275,12 @@ class Meta:
filterset_class = AnalysisFrameworkGqFilterSet


class AnalysisFrameworkTagListType(CustomDjangoListObjectType):
class Meta:
model = AnalysisFrameworkTag
filterset_class = AnalysisFrameworkTagGqFilterSet


class Query:
analysis_framework = DjangoObjectField(AnalysisFrameworkDetailType)
analysis_frameworks = DjangoPaginatedListObjectField(
Expand All @@ -265,6 +295,12 @@ class Query:
page_size_query_param='pageSize'
)
)
analysis_framework_tags = DjangoPaginatedListObjectField(
AnalysisFrameworkTagListType,
pagination=PageGraphqlPagination(
page_size_query_param='pageSize'
)
)

@staticmethod
def resolve_analysis_frameworks(root, info, **kwargs) -> QuerySet:
Expand Down
Loading

0 comments on commit d98368a

Please sign in to comment.