• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

chiefonboarding / ChiefOnboarding / 6514526390

14 Oct 2023 12:54AM UTC coverage: 93.465% (+0.05%) from 93.412%
6514526390

push

github

web-flow
Sync users and update user info (#371)

5964 of 6381 relevant lines covered (93.46%)

0.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.06
back/admin/integrations/forms.py
1
import json
1✔
2

3
from crispy_forms.helper import FormHelper
1✔
4
from django import forms
1✔
5
from django.contrib.auth import get_user_model
1✔
6

7
from admin.integrations.utils import get_value_from_notation
1✔
8

9
from .models import Integration
1✔
10

11

12
class IntegrationConfigForm(forms.ModelForm):
1✔
13
    def _expected_example(self, form_item):
1✔
14
        def _add_items(form_item):
1✔
15
            items = []
1✔
16
            # Add two example items
17
            for item in range(2):
1✔
18
                items.append(
1✔
19
                    {
20
                        form_item.get("choice_value", "id"): item,
21
                        form_item.get("choice_name", "name"): f"name {item}",
22
                    }
23
                )
24
            return items
1✔
25

26
        inner = form_item.get("data_from", "")
1✔
27
        if inner == "":
1✔
28
            return _add_items(form_item)
1✔
29

30
        # This is pretty ugly, but we are building a json string first
31
        # and then convert it to a real json object to avoid nested loops
32
        notations = inner.split(".")
1✔
33
        stringified_json = "{"
1✔
34
        for idx, notation in enumerate(notations):
1✔
35
            stringified_json += f'"{notation}":'
1✔
36
            if idx + 1 == len(notations):
1✔
37
                stringified_json += json.dumps(_add_items(form_item))
1✔
38
                stringified_json += "}" * len(notations)
1✔
39
            else:
40
                stringified_json += "{"
1✔
41

42
        return json.loads(stringified_json)
1✔
43

44
    def __init__(self, *args, **kwargs):
1✔
45
        super().__init__(*args, **kwargs)
1✔
46
        integration = Integration.objects.get(id=self.instance.id)
1✔
47
        form = self.instance.manifest["form"]
1✔
48
        self.helper = FormHelper()
1✔
49
        self.helper.form_tag = False
1✔
50
        self.error = None
1✔
51
        for item in form:
1✔
52
            if item["type"] == "input":
1✔
53
                self.fields[item["id"]] = forms.CharField(
1✔
54
                    label=item["name"],
55
                    required=False,
56
                )
57

58
            if item["type"] in ["choice", "multiple_choice"]:
1✔
59
                # If there is a url to fetch the items from then do so
60
                if "url" in item:
1✔
61
                    success, response = integration.run_request(item)
1✔
62
                    if not success:
1✔
63
                        self.error = response
×
64
                        return
×
65

66
                    option_data = response.json()
1✔
67
                else:
68
                    # No url, so get the static items
69
                    option_data = item["items"]
1✔
70

71
                # Can we select one or multiple?
72
                if item["type"] == "choice":
1✔
73
                    field = forms.ChoiceField
1✔
74
                else:
75
                    field = forms.MultipleChoiceField
×
76

77
                try:
1✔
78
                    self.fields[item["id"]] = field(
1✔
79
                        label=item["name"],
80
                        widget=forms.CheckboxSelectMultiple
81
                        if item["type"] == "multiple_choice"
82
                        else forms.Select,
83
                        choices=[
84
                            (
85
                                get_value_from_notation(
86
                                    item.get("choice_value", "id"), x
87
                                ),
88
                                get_value_from_notation(
89
                                    item.get("choice_name", "name"), x
90
                                ),
91
                            )
92
                            for x in get_value_from_notation(
93
                                item.get("data_from", ""), option_data
94
                            )
95
                        ],
96
                        required=False,
97
                    )
98
                except Exception:
1✔
99
                    expected = self._expected_example(item)
1✔
100

101
                    self.error = (
1✔
102
                        f"Form item ({item['name']}) could not be rendered. Format "
103
                        "was different than expected.<br><h2>Expected format:"
104
                        f"</h2><pre>{json.dumps(expected, indent=4)}</pre><br><h2>"
105
                        "Got from server:</h2><pre>"
106
                        f"{json.dumps(option_data, indent=4)}</pre>"
107
                    )
108
                    break
1✔
109

110
    class Meta:
1✔
111
        model = Integration
1✔
112
        fields = ()
1✔
113

114

115
# Credits: https://stackoverflow.com/a/72256767
116
# Removed the sort options
117
class PrettyJSONEncoder(json.JSONEncoder):
1✔
118
    def __init__(self, *args, indent, **kwargs):
1✔
119
        super().__init__(*args, indent=4, **kwargs)
1✔
120

121

122
class IntegrationForm(forms.ModelForm):
1✔
123
    manifest = forms.JSONField(encoder=PrettyJSONEncoder)
1✔
124

125
    class Meta:
1✔
126
        model = Integration
1✔
127
        fields = ("name", "manifest_type", "manifest")
1✔
128

129
    def __init__(self, *args, **kwargs):
1✔
130
        super().__init__(*args, **kwargs)
1✔
131
        self.fields["manifest_type"].required = True
1✔
132
        if self.instance.id:
1✔
133
            # disable manifest_type when updating field
134
            self.fields["manifest_type"].disabled = True
1✔
135

136

137
class IntegrationExtraArgsForm(forms.ModelForm):
1✔
138
    def __init__(self, *args, **kwargs):
1✔
139
        super().__init__(*args, **kwargs)
1✔
140
        initial_data = self.instance.extra_args
1✔
141
        for item in self.instance.manifest["initial_data_form"]:
1✔
142
            self.fields[item["id"]] = forms.CharField(
1✔
143
                label=item["name"], help_text=item["description"]
144
            )
145
            # Check if item was already saved - load data back in form
146
            if item["id"] in initial_data:
1✔
147
                self.fields[item["id"]].initial = initial_data[item["id"]]
1✔
148
            # If field is secret field, then hide it - values are generated on the fly
149
            if "name" in item and item["name"] == "generate":
1✔
150
                self.fields[item["id"]].required = False
1✔
151
                self.fields[item["id"]].widget = forms.HiddenInput()
1✔
152

153
    def save(self):
1✔
154
        integration = self.instance
1✔
155
        integration.extra_args = self.cleaned_data
1✔
156
        integration.save()
1✔
157
        return integration
1✔
158

159
    class Meta:
1✔
160
        model = Integration
1✔
161
        fields = ()
1✔
162

163

164
class IntegrationExtraUserInfoForm(forms.ModelForm):
1✔
165
    def __init__(self, missing_info=None, *args, **kwargs):
1✔
166
        super().__init__(*args, **kwargs)
1✔
167
        if missing_info is None:
1✔
168
            missing_info = self.instance.missing_extra_info
1✔
169

170
        for item in missing_info:
1✔
171
            self.fields[item["id"]] = forms.CharField(
1✔
172
                label=item["name"], help_text=item["description"]
173
            )
174

175
    def save(self):
1✔
176
        user = self.instance
1✔
177
        user.extra_fields |= self.cleaned_data
1✔
178
        user.save()
1✔
179
        return user
1✔
180

181
    class Meta:
1✔
182
        model = get_user_model()
1✔
183
        fields = ()
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc