Ejemplo n.º 1
0
class MyLiveView(ModelView):
    column_list = ('speaker', 'title', 'live_description', 'seats_count',
                   'price')
    column_labels = dict(speaker='作者',
                         title='标题',
                         live_description='描述',
                         seats_count='售出',
                         price='价格')
    column_sortable_list = ('speaker', 'seats_count', 'price')
    column_editable_list = ['title']
    can_create = False
    inline_models = (LiveContent, )

    def _format_price(view, context, model, name):
        price = int(model['price']) / 100
        return Markup("¥{}".format(price))

    column_formatters = {'price': _format_price}
    column_extra_row_actions = [
        EndpointLinkRowAction(
            'glyphicon glyphicon-download',
            'tools.crawl',
        ),
        EndpointLinkRowAction(
            'glyphicon glyphicon-transfer',
            'tools.transform_live',
        )
    ]
Ejemplo n.º 2
0
class WatcherView(AuthModelView):
    can_view_details = True

    column_list = ('game', 'info', 'config')
    column_details_list = ('game', 'info', 'config', 'events')
    form_excluded_columns = ['events']
    inline_models = [WatcherConfig]

    form_args = {
        'threadClass': {
            'label':
            'Watcher Type',
            'choices':
            [('lamon.watcher.plugin.source_engine.SourceEngineWatcher',
              'Source Engine Watcher'),
             ('lamon.watcher.plugin.quake3.Quake3Watcher', 'Quake3 Watcher'),
             ('lamon.watcher.plugin.minecraft.MinecraftWatcher',
              'Minecraft Watcher'),
             ('tests.watcher.ValueWatcher', 'Fake Value Watcher')]
        }
    }

    form_overrides = {'threadClass': SelectField, 'config': HiddenField}

    column_extra_row_actions = [
        EndpointLinkRowAction('glyphicon glyphicon-play', 'watchers.start'),
        EndpointLinkRowAction('glyphicon glyphicon-stop', 'watchers.stop'),
        EndpointLinkRowAction('glyphicon glyphicon-refresh',
                              'watchers.restart')
    ]
Ejemplo n.º 3
0
class UserAdmin(BaseAdminView):
    # def is_visible(self):
    #     return False

    column_list = ['id', 'full_name', 'email']
    column_searchable_list = ('id', "full_name", 'email')
    column_filters = ("id", "full_name", "email")

    form_create_rules = ('email', "is_active")
    form_edit_rules = ('email', "is_active")

    column_extra_row_actions = [
        EndpointLinkRowAction('glyphicon glyphicon-user',
                              'user.action_play',
                              title="Login as User"),
    ]

    @expose('impersonate/<id>', methods=('Get', ))
    def action_play(self, *args, **kwargs):
        user = User.query.get(kwargs['id'])
        login_user(user)

        if user.corporate != None:
            corporate_id = user.corporate.id
            CookieHelper.set_corporate_cookie(corporate_id)
        return self.handle_action()
Ejemplo n.º 4
0
class UserModelView(BaseModelView):
    can_delete = False  # disable model deletion
    can_create = False
    can_view_details = True
    can_export = True
    column_searchable_list = ["email"]
    form_excluded_columns = [
        "password",
        "subscriptions",
        "export_requests",
        "created_at",
        "bulk_search_requests",
        "api_keys",
        "features",
    ]
    column_exclude_list = [
        "password",
        "first_name",
        "last_name",
    ]
    column_details_list = [
        "id",
        "plan_slug",
        "feature_slugs",
        "created_at",
        "first_name",
        "last_name",
        "is_active",
        "is_admin",
    ]
    column_export_exclude_list = [
        "password",
    ]
    column_default_sort = ("created_at", True)
    column_list = [
        "email",
        "plan_slug",
        "created_at",
        "is_active",
        "is_admin",
    ]
    column_extra_row_actions = [
        EndpointLinkRowAction(
            "fa fa-sign-in-alt", "admin.user.login_as", id_arg="user_id",
        )
    ]

    @expose("/login-as/<user_id>")
    def login_as(self, user_id):
        from .models.accounts import User

        user = User.query.filter_by(id=user_id).first_or_404()
        login_user(user, remember=False)
        identity_changed.send(
            current_app._get_current_object(), identity=Identity(user.id)
        )
        flash(f"You are logged in as {user.email}.", "success")
        redirect_url = url_for("public.home")
        return redirect(redirect_url)
Ejemplo n.º 5
0
class StorageView(AuthModelView):
    """
    存储管理模块
    """

    can_create = True
    can_edit = True
    can_delete = False
    can_view_details = True
    details_modal = True
    column_exclude_list = ["id", "uid", "path"]
    form_excluded_columns = [
        "saved",
        "uid",
        "path",
        "created",
        "modified",
        "deleted",
        "filetype",
    ]
    column_filters = ["created", "modified", "storetype", "filetype"]
    form_extra_fields = {"file": JustUploadField("文件")}
    column_extra_row_actions = [
        EndpointLinkRowAction(
            icon_class="fas fa-download",
            endpoint="admin.views.storages.storage_file",
            id_arg="file_id",
        )
    ]

    @expose("file/<int:file_id>", methods=["GET"])
    def storage_file(self, file_id):
        """访问文件"""
        storage = self.model.get_by_id(file_id)

        return send_file(
            storage.store.stream,
            attachment_filename=storage.name,
            mimetype=storage.store.content_type,
            as_attachment=False,
        )

    def on_model_change(self, form, model, is_created):
        """保存文件处理"""
        if "file" in form:
            model.store = form["file"].data
        if is_created:
            model.save()
        elif model.deleted is True:
            model.delete()
        else:
            # TODO 当发生更新时检查文件是否发生改变
            model.update()
        super().on_model_change(form, model, is_created)
Ejemplo n.º 6
0
class UserAdmin(BaseUserAdmin):
    list_template = 'canella/admin/user/list.html'
    can_create = False
    column_exclude_list = ['password', 'slug', 'profile']
    form_excluded_columns = [
        'password', 'posts', 'profile', 'confirmed_at', 'slug'
    ]
    column_extra_row_actions = [
        EndpointLinkRowAction(icon_class="fa fa-lock",
                              endpoint='.change_password',
                              title=lazy_gettext("Change Password"),
                              id_arg='pk'),
    ]

    @expose('/<int:pk>/change-password/', methods=['GET', 'POST'])
    def change_password(self, pk):
        user = self.get_one(str(pk))
        form = CanellaChangePasswordForm(user=user)
        if form.validate_on_submit():
            change_password(user, form.password.data)
            db.session.commit()
            if user.email == current_user.email:
                logout_user()
            flash(gettext('Password changed successfully'))
            return redirect(url_for('.index_view'))
        return self.render('admin/model/create.html', form=form)

    @expose('/<int:pk>/deactivate/', methods=['GET', 'POST'])
    def deactivate_user(self, pk):
        if user.is_active:
            user = self.get_one(str(pk))
            user.is_active = False
            db.session.commit()
            flash(gettext('Account deactivated successfully'))
        return redirect(url_for('.index_view'))

    @expose('/<int:pk>/activate/', methods=['GET', 'POST'])
    def activate_user(self, pk):
        user = self.get_one(str(pk))
        if not user.is_active:
            user.is_active = True
            db.session.commit()
            flash(gettext('Account activated successfully'))
        return redirect(url_for('.index_view'))

    @expose('/register/', methods=['GET', 'POST'])
    def register(self):
        form = CanellaRegisterForm()
        if form.validate_on_submit():
            should_confirm = form.send_confirmation.data
            del form.send_confirmation
            register_user(should_confirm=should_confirm, **form.to_dict())
            return redirect(url_for('.index_view'))
        return self.render('admin/model/create.html', form=form)
Ejemplo n.º 7
0
class TranscriptAdminModelView(AdminModelView):
    column_searchable_list = ['id', 'student_name', 'user_id', 'user.email']
    inline_models = [Year]
    inline_model_form_converter = TranscriptInlineModelConverter
    column_extra_row_actions = [
        EndpointLinkRowAction("glyphicon icon-print", 'transcript.print'),
        EndpointLinkRowAction("glyphicon icon-cog",
                              'transcriptsettings.edit_view')
    ]

    def __init__(self, db, *args, **kwargs):
        super().__init__(Transcript, db._session, *args, **kwargs)
        self.transcript_service = TranscriptService(db)

    @expose('/print/<int:id>')
    def print(self, id):
        transcript = self.transcript_service.get(id)
        if transcript is None:
            return abort(404)
        transcript_grader = GradingService.get_transcript_grader(
            transcript.grading_scale, transcript.ap_grading_scale)

        return render_pdf(transcript, transcript_grader)
Ejemplo n.º 8
0
class FormAdmin(PageAdmin):
    inline_models = [(Field, dict(
            form_columns=['id', 'name', 'label', 'description', 'type', 'choices', 'default', 'required', 'max_length'],
                form_extra_fields={'type': SelectField(label=Field.type.info['label'], description=Field.type.info['description'], choices=sorted(Field.type.info['choices']))}
            ),),]
    column_extra_row_actions = list(PageAdmin.column_extra_row_actions)
    column_extra_row_actions.append(EndpointLinkRowAction(icon_class='fa fa-download', endpoint='.export_entries', title=lazy_gettext('Export Entries as CSV'), id_arg='pk'))
    form_excluded_columns = ["children", "contenttype", "slug_path"]
    form_rules = list(PageAdmin.form_rules)
    form_rules.insert(6, 'fields')
    form_rules.insert(7, 'submit_text')
    form_rules.insert(8, 'submit_message')
    form_overrides = dict(PageAdmin.form_overrides)
    form_overrides.update({
        'submit_message': RichTextAreaField,
    })

    @expose('/export-entries/<int:pk>')
    def export_entries(self, pk):
        """Taken from Flask-Admin with some modifications, no shame!"""
        form = self.get_one(str(pk))
        filename = "attachment; filename=%s.csv" %("%s-%s" %(form.slug, date_stamp(form.updated)))
        class Echo(object):
            """
            An object that implements just the write method of the file-like
            interface.
            """
            def write(self, value):
                """
                Write the value by returning it, instead of storing
                in a buffer.
                """
                return value
        writer = csv.writer(Echo())
        def generate():
            # Append the column titles at the beginning
            titles = [csv_encode('date')] + [csv_encode(field.name) for field in form.fields]
            yield writer.writerow(titles)
            for entry in form.entries:
                vals = [csv_encode(entry.created.isoformat())] + [csv_encode(field.value) for field in entry.fields]
                yield writer.writerow(vals)
        return Response(
            stream_with_context(generate()),
            headers={'Content-Disposition': filename},
            mimetype='text/csv'
        )
Ejemplo n.º 9
0
class TestBedView(MyObjectView):
    column_list = [
        'name',
        'owner',
        'rigs',
    ]
    form_excluded_columns = ['connect_chart', ]

    column_extra_row_actions = [
        LinkRowAction('icon-eye-open', './{row_id}'),
        EndpointLinkRowAction('', 'testbed.index_view')
    ]

    @expose('/<testbed_id>')
    def show_chart(self, testbed_id):
        tb = Testbed.query.filter_by(id=testbed_id).first()
        rigs = tb.rigs
        rig_names = [rig.name for rig in rigs]
        hosts = tb.hosts
        host_names = [host.name for host in hosts]
        rig_names.extend(host_names)
        if tb.connect_chart is None:
            relation_sample = []
        else:
            relation_sample = json.loads(tb.connect_chart)
        rig_connects = RigConnection.query.all()
        rig_connect_names = [rig_connect.name for rig_connect in rig_connects]
        host_usages = HostUsage.query.all()
        host_usage_names = [host_usage.name for host_usage in host_usages]
        rig_connect_names.extend(host_usage_names)
        return self.render('testbed2.html', rig_names=rig_names, tb_name=tb.name,
                           rig_connect_names=rig_connect_names,
                           relation=relation_sample)

    @expose('/save/<tb_name>', methods=['GET', 'POST'])
    def save(self, tb_name):
        print(tb_name)
        content = request.form.get('content')
        print(content)
        # print(Testbed.query.filter_by(name=tb_name).first())
        tb = Testbed.query.filter_by(name=tb_name).first()
        tb.connect_chart = content
        tb.save()
        return 'saved'
Ejemplo n.º 10
0
class UserModelView(BaseModelView):
    column_list = ('id', 'name', 'username')
    column_default_sort = 'id'

    can_delete = False

    column_extra_row_actions = [
        EndpointLinkRowAction('glyphicon glyphicon-envelope', '.chat')
    ]

    @expose('/chat', methods=['GET', 'POST'])
    def chat(self):
        id = request.args.get('id')
        recipient = User.query.get(id)
        if recipient is None:
            flash('user_id is error.', 'error')
            return redirect(url_for('.index_view'))

        form = ChatInputForm()
        if request.method == 'POST' and form.validate():
            msg = Message(sender=current_user, recipient=recipient,
                          body=form.message.data)
            db.session.add(msg)
            db.session.commit()
            # flash('发送消息成功')

        messages = Message.query.filter(
            or_(
                and_(
                    Message.sender == current_user,
                    Message.recipient == recipient
                ),
                and_(
                    Message.sender == recipient,
                    Message.recipient == current_user
                ),
            )
        ).all()
        return self.render('/chat.html',
                           sender=current_user,
                           recipient=recipient,
                           form=form,
                           messages=messages)
Ejemplo n.º 11
0
class LiveContentView(ModelView):
    column_list = ('sender', 'content', 'likes', 'type', 'created_at',
                   'image_or_audio')
    column_labels = dict(sender='作者',
                         content='内容',
                         likes='顶',
                         type='类型',
                         created_at='时间',
                         image_or_audio='语音播放')
    column_sortable_list = ('sender', 'likes', 'type', 'created_at')
    column_editable_list = ['content']
    column_searchable_list = ('content', )
    column_filters = (ReferenceObjectIdFilter(
        column=LiveContent.live_title,
        name='live_title',
        options=_get_live_title_option()), 'type')

    def _list_thumbnail(view, context, model, name):
        if model['type'] == 'image':
            imgurl = str(model['id']) + '.png'
            return Markup("<a href='%s' target='_blank'>查看图片</a>" %
                          url_for('static', filename=imgurl))
        elif model['type'] == 'audio':
            return Markup('<audio controls height="100" width="100">'
                          '<source src="%s" type="audio/aac" />'
                          '</audio>' % model['url'])
        else:
            return ''

    column_formatters = {'image_or_audio': _list_thumbnail}
    can_edit = True
    edit_modal = True
    can_export = True
    export_types = ['xls']
    column_extra_row_actions = [
        EndpointLinkRowAction(
            'glyphicon glyphicon-transfer',
            'tools.transform',
        )
    ]
Ejemplo n.º 12
0
class ResultModelView(AuthRequiredView):
    column_extra_row_actions = [
        EndpointLinkRowAction('glyphicon icon-eye-open', 'studentresults.index')
    ]
    column_list = ["user", "grade", "n_correct", "n_total", "datetime"]
    column_labels = {
        "n_correct": "Правильных ответов",
        "n_total": "Всего вопросов",
        "grade": "Оценка",
        "datetime": "Время окончания",
        "de_0": "Освоение ДЕ №1",
        "de_1": "Освоение ДЕ №2",
        "de_2": "Освоение ДЕ №3",
        "de_3": "Освоение ДЕ №4",
        "de_4": "Освоение ДЕ №5",
        "de_5": "Освоение ДЕ №6",
        "user": "******",
        "user.name": "Пользователь / ФИО",
        "user.group": "Пользователь / Группа",
        "user.login": "******",
        "user.attempts": "Пользователь / Число попыток",
    }
    column_formatters = {
        "datetime": lambda v, c, m, p: m.datetime.strftime("%H:%M:%S %d.%m.%Y"),
        "user": lambda v, c, m, p: f"{m.user.name} ({m.user.group})",
        "grade": lambda v, c, m, p: "отл." if m.n_correct / m.n_total >= app.config["GRADE_RATIOS"][2] else "хор." if m.n_correct / m.n_total >= app.config["GRADE_RATIOS"][1] else "удов." if m.n_correct / m.n_total >= app.config["GRADE_RATIOS"][0] else "неуд."
    }
    column_filters = ["user.name", "user.login", "user.group", "user.attempts",
                      "n_correct", "n_total", "datetime"]
    column_exclude_list = ["variant"]
    form_excluded_columns = ["variant"]

    column_sortable_list = [("user", "user.name"), "n_correct",
                            "n_total", "datetime"]
    column_default_sort = ("datetime", True)

    def is_editable(self, name):
        return False
Ejemplo n.º 13
0
class RigView(MyObjectView):
    inline_models = [(RigInfo, inline_form_options), ]
    column_exclude_list = ['io_interfaces', 'iscsi_interfaces', 'replication_async_interfaces',
                           'replication_sync_interfaces', 'state', 'status']
    column_editable_list = ['model', 'owner', 'device']
    inline_models = [(RigInfo, inline_form_options), ]
    column_extra_row_actions = [
        LinkRowAction('icon-eye-open', './{row_id}'),
        EndpointLinkRowAction('', 'rig.index_view')
    ]

    @expose('/<rig_id>')
    def show_chart(self, rig_id):
        rig = Rig.query.filter_by(id=rig_id).first()
        tbs = Testbed.query.all()
        rig_map_tb = []
        for item in tbs:
            print(f'tb_name :{item.name}')
            rigs = item.rigs
            for checked_rig in rigs:
                if rig.name == checked_rig.name:
                    rig_map_tb.append([rig.name, item.name, 'Used'])
        return self.render('rig.html', relation=rig_map_tb)
Ejemplo n.º 14
0
class UserView(CVAdminModelView):
    can_create = True
    can_edit = True
    can_delete = True
    # inline_models = [(Role, dict(form_columns=['id', 'name']))]
    column_list = ('id', 'username', 'password', 'email', 'roles', 'active',
                   'create_at', 'update_at', 'remark')
    column_labels = dict(id='用户ID',
                         username='******',
                         password='******',
                         email='邮箱地址',
                         roles='角色',
                         active='启用',
                         create_at='创建时间',
                         update_at='更新时间',
                         remark='备注')
    column_filters = ('roles.name', )
    column_formatters = dict(
        password=lambda v, c, m, p: '••••••',
        active=lambda v, c, m, p: get_yesno_display(m.active),
        create_at=lambda v, c, m, p: display_datetime(m.create_at),
        update_at=lambda v, c, m, p: display_datetime(m.update_at))

    # def get_action_url(self):
    #     self.get_url('.edit_view', id = self.get_pk_value(self.row),
    #                  url = get_redirect_target() or self.get_url('.index_view'))

    column_extra_row_actions = [
        # LinkRowAction('fa fa-key','/admin/user/edit/?id={row_id}&amp;url=%2Fadmin%2Fuser%2F'),
        EndpointLinkRowAction('fa fa-key', 'user.resetpass_view', title='重置密码')
    ]

    form_args = dict(roles=dict(validators=[DataRequired()]))
    form_create_rules = (
        rules.FieldSet(('username', 'email', 'remark'), '基本信息'),
        # rules.FieldSet(('roles', 'apikey', 'active'), 'Permission'),
        rules.FieldSet(('roles', 'active'), '权限设置'),
        # rules.FieldSet(('password', 'password_confirm'), '账号安全')
    )

    form_edit_rules = (
        rules.FieldSet(('username', 'email', 'remark'), '基本信息'),
        rules.FieldSet(('roles', 'active'), '权限设置'),
        # rules.Header('重置密码'),
        # rules.FieldSet(('new_password', 'new_password_confirm'), '重置密码')
        # rules.Field()
    )

    def __init__(self, model, session):
        CVAdminModelView.__init__(self, model, session, '用户', '系统设置')

    def is_accessible(self):
        from common.login import admin_permission
        if request.endpoint == 'user.resetpass_view':
            if (login.current_user.id == int(
                    request.values.get('id'))) or admin_permission.can():
                return login.current_user.is_authenticated
            else:
                return False
        else:
            if admin_permission.can():
                return login.current_user.is_authenticated
            else:
                return False

    def get_create_form(self):
        form = self.scaffold_form()
        form.username = fields.StringField(
            '用户名', [validators.required(message='用户名是必填字段')])
        # form.password = fields.PasswordField('密码', [validators.required(message = '密码是必填字段')])
        # form.password_confirm = fields.PasswordField('密码确认',
        #                                              [validators.required(message = '密码是必填字段'),
        #                                               validators.equal_to(fieldname = 'password',
        #                                                                   message = '确认密码须一致')])
        form.active = fields.BooleanField(
            '启用状态', [validators.required(message='启用状态是必填字段')], default=True)
        return form

    def get_edit_form(self):
        form = self.scaffold_form()
        delattr(form, 'password')
        # form.new_password = fields.PasswordField('新密码')
        # form.new_password_confirm = fields.PasswordField('密码确认',
        #                                                  [validators.equal_to(fieldname = 'new_password',
        #                                                                       message = '确认密码须一致')])
        form.active = fields.BooleanField(
            '启用状态', [validators.required(message='启用状态是必填字段')], default=True)
        return form

    def on_model_change(self, form, model, is_created):
        if not is_created:
            if hasattr(form, 'new_password'):
                model.password = generate_password_hash(form.new_password.data)
        else:
            model.password = generate_password_hash(model.password)

    def get_action_form(self):
        '''
            定制Action
        :return: 
        '''
        class ResetpassForm(self.form_base_class):
            form_widget_args = {}
            form_edit_rules = [
                rules.Field('new_password'),
                rules.Field('new_password_confirm')
            ]
            _form_edit_rules = rules.RuleSet(self, form_edit_rules)
            action = HiddenField('')
            url = HiddenField('')
            new_password = fields.PasswordField(
                '新密码', [validators.required(message='密码是必填字段')])
            new_password_confirm = fields.PasswordField(
                '密码确认', [
                    validators.equal_to(fieldname='new_password',
                                        message='确认密码须一致')
                ])

        return ResetpassForm

    @expose('/resetpass/', methods=('GET', 'POST'))
    def resetpass_view(self):
        """
            Reset password view
        """
        return_url = get_redirect_target() or self.get_url('.index_view')

        if not self.can_edit:
            return redirect(return_url)

        id = get_mdict_item_or_list(request.args, 'id')
        if id is None:
            return redirect(return_url)

        model = self.get_one(id)

        if model is None:
            flash(gettext('Record does not exist.'), 'error')
            return redirect(return_url)

        form = self.action_form(obj=model)

        if not hasattr(form,
                       '_validated_ruleset') or not form._validated_ruleset:
            self._validate_form_instance(ruleset=form._form_edit_rules,
                                         form=form)

        if self.validate_form(form):
            if self.update_model(form, model):
                flash(gettext('Record was successfully saved.'), 'success')
                if '_add_another' in request.form:
                    return redirect(
                        self.get_url('.create_view', url=return_url))
                elif '_continue_editing' in request.form:
                    return redirect(request.url)
                else:
                    # save button
                    return redirect(
                        self.get_save_return_url(model, is_created=False))

        if request.method == 'GET' or form.errors:
            self.on_form_prefill(form, id)

        form_opts = FormOpts(widget_args=form.form_widget_args,
                             form_rules=form._form_edit_rules)

        template = 'model/resetpass.html'

        return self.render(template,
                           model=model,
                           form=form,
                           form_opts=form_opts,
                           return_url=return_url)
Ejemplo n.º 15
0
class ExternalObjectView(DefaultView):
    def __init__(self, *args, **kwargs):
        kwargs['category'] = 'External Objects'
        kwargs['endpoint'] = kwargs['name'].lower() + 'object'
        super(ExternalObjectView, self).__init__(ExternalObject, *args,
                                                 **kwargs)

    can_view_details = True
    can_export = True
    # TODO: Export formatters
    export_types = ['csv', 'xls']

    column_details_list = ('id', 'type', 'attributes_list', 'links_list')
    column_formatters = {
        'name':
        attribute_formatter(partial(eq, ValueType.NAME)),
        'title':
        attribute_formatter(partial(eq, ValueType.TITLE)),
        'date':
        attribute_formatter(partial(eq, ValueType.DATE),
                            filter=lambda t: len(t) == 4),
        'genres':
        attribute_formatter(partial(eq, ValueType.GENRES), limit=3),
        'country':
        attribute_formatter(partial(eq, ValueType.COUNTRY),
                            filter=lambda t: len(t) == 2),
        'duration':
        attribute_formatter(partial(eq, ValueType.DURATION),
                            filter=lambda t: t.replace('.', '').isdigit(),
                            limit=1),
        'attributes':
        attribute_formatter(show_score=True),
        'attributes_list':
        macro('attributes_list'),
        'links_list':
        macro('links_list'),
        'links':
        count_formatter
    }

    column_extra_row_actions = [
        EndpointLinkRowAction('glyphicon icon-search',
                              'allobject.index_view',
                              id_arg='flt0_0')
    ]

    inline_models = ((Value, dict(form_columns=('id', 'type', 'text'))),
                     (ObjectLink,
                      dict(form_columns=('id', 'platform', 'external_id'))))

    column_filters = [
        ExternalObjectSimilarFilter(name='Similar'),
        ExternalObjectPlatformFilter(
            column=Platform.country,
            name='Platform',
            options=[(c[0], str(c[0]).upper())
                     for c in db.session.query(Platform.country).distinct()]),
        ExternalObjectPlatformFilter(column=Platform.type,
                                     name='Platform',
                                     options=[(t.name, t.name)
                                              for t in PlatformType]),
        ExternalObjectPlatformFilter(
            column=Platform.slug,
            name='Platform',
            options=[(p.slug, p.name)
                     for p in db.session.query(Platform.slug, Platform.name)]),
        ExternalObjectPlatformFilter(
            column=Platform.slug,
            invert=True,
            name='Platform',
            options=[(p.slug, p.name)
                     for p in db.session.query(Platform.slug, Platform.name)]),
    ]

    def get_query(self):
        q = super(ExternalObjectView, self).get_query()
        if hasattr(self, 'external_object_type'):
            q = q.filter(ExternalObject.type == self.external_object_type)
        return q

    def get_count_query(self):
        q = super(ExternalObjectView, self).get_count_query()
        if hasattr(self, 'external_object_type'):
            q = q.filter(ExternalObject.type == self.external_object_type)
        return q
Ejemplo n.º 16
0
class PendingApprovedModelView(ModelView):

    edit_modal = True

    column_editable_list = ('task', 'calculated_time', 'kind', 'approved')

    column_searchable_list = ('id', 'number', 'task', 'date')

    column_sortable_list = ('task', 'calculated_time')

    column_labels = dict(id=u'主键',
                         name=u'工作者',
                         number=u'工号',
                         date=u'日期',
                         airplane=u'飞机',
                         task=u'项目',
                         standard_time=u'标准工时',
                         worker_number=u'标准人数',
                         calculated_time=u'计算工时',
                         completed=u'完成情况',
                         role=u'角色',
                         note=u'说明',
                         belongto_team=u'班组',
                         kind=u'工作类别',
                         approved=u'是否审核')

    column_extra_row_actions = [
        EndpointLinkRowAction(
            'off glyphicon glyphicon-check',
            'timesheet.approve_view',
        )
    ]

    # def get_query(self):
    #     return self.session.query(
    #         self.model).filter(self.model.approved == u'否')

    # def get_count_query(self):
    #     return self.session.query(
    #         func.count('*')).filter(Timesheet.approved == u'否')

    def get_filters(self):
        _dynamic_filters = getattr(self, 'dynamic_filters', None)
        if _dynamic_filters:
            return (super(PendingApprovedModelView, self).get_filters()
                    or []) + _dynamic_filters
        else:
            return super(PendingApprovedModelView, self).get_filters()

    @expose('/')
    def index_view(self):
        self.dynamic_filters = []
        self.dynamic_filters.extend([
            FilterEqual(column=Timesheet.belongto_team,
                        name=u'班组',
                        options=get_all_team_names),
            # Add further dynamic filters here
        ])
        self._refresh_filters_cache()
        return super(PendingApprovedModelView, self).index_view()

    @expose('/approve/', methods=('GET', ))
    def approve_view(self):
        """
            Approve user model view. Only GET method is allowed.
        """
        return_url = get_redirect_target() or self.get_url(
            'timesheet.details_view')

        id = request.args["id"]
        model = self.get_one(id)

        if model is None:
            flash(u'用户不存在', u'error')
            return redirect(return_url)

        if model.approved == u'是':
            flash(u'已经审核, 无需重复审核.', u'warning')
            return redirect(return_url)

        model.approved = u'是'
        self.session.add(model)
        self.session.commit()

        flash(u'已审核', u'success')
        return redirect(return_url)

    @action('approve', u'审核', u'你确定要将所选择的项目设置为已审核?')
    def action_approve(self, ids):
        redirect_response = redirect(url_for('timesheet.index_view'))
        try:
            query = Timesheet.query.filter(Timesheet.id.in_(ids))

            count = 0
            for timesheet in query.all():
                if timesheet.approved == u'是':
                    pass
                else:
                    timesheet.approved = u'是'
                    count += 1
            db.session.commit()
            flash(u'审核 {} 个工时成功.'.format(count), 'success')
            return redirect_response
        except Exception as e:
            if not self.handle_view_exception(e):
                raise
            flash(u'审核失败:{}'.format(str(e)), 'error')
Ejemplo n.º 17
0
class ExternalObjectView(DefaultView):
    def __init__(self, *args, **kwargs):
        kwargs["category"] = "External Objects"
        kwargs["endpoint"] = kwargs["name"].lower().replace(" ", "")
        super(ExternalObjectView, self).__init__(ExternalObject, *args,
                                                 **kwargs)

    can_view_details = True
    can_export = True
    # TODO: Export formatters
    export_types = ["csv", "xls"]

    column_details_list = ("id", "type", "values_list", "links_list")
    column_formatters = {
        "name":
        attribute_formatter(partial(eq, ValueType.NAME)),
        "title":
        attribute_formatter(partial(eq, ValueType.TITLE)),
        "date":
        attribute_formatter(partial(eq, ValueType.DATE),
                            filter=lambda t: len(t) == 4),
        "genres":
        attribute_formatter(partial(eq, ValueType.GENRES), limit=3),
        "country":
        attribute_formatter(partial(eq, ValueType.COUNTRY),
                            filter=lambda t: len(t) == 2),
        "duration":
        attribute_formatter(
            partial(eq, ValueType.DURATION),
            filter=lambda t: t.replace(".", "").isdigit(),
            limit=1,
        ),
        "series":
        series_formatter,
        "season":
        meta_formatter("season"),
        "episode":
        meta_formatter("episode"),
        "episode_details":
        macro("episode_details"),
        "episodes":
        episodes_formatter,
        "episodes_list":
        macro("episodes_list"),
        "values":
        attribute_formatter(show_score=True),
        "values_list":
        macro("values_list"),
        "links_list":
        macro("links_list"),
        "links":
        count_formatter,
    }

    column_extra_row_actions = [
        EndpointLinkRowAction("glyphicon icon-search",
                              "allobjects.index_view",
                              id_arg="flt0_0")
    ]

    inline_models = (
        (Value, dict(form_columns=("id", "type", "text"))),
        (ObjectLink, dict(form_columns=("id", "platform", "external_id"))),
    )

    column_filters = [
        ExternalObjectSimilarFilter(name="Similar"),
        ExternalObjectPlatformFilter(
            column=Platform.country,
            name="Platform",
            options=[(c[0], str(c[0]).upper())
                     for c in db.session.query(Platform.country).distinct()],
        ),
        ExternalObjectPlatformFilter(
            column=Platform.type,
            name="Platform",
            options=[(t.name, t.name) for t in PlatformType],
        ),
        ExternalObjectPlatformFilter(
            column=Platform.slug,
            name="Platform",
            options=[(p.slug, p.name)
                     for p in db.session.query(Platform.slug, Platform.name)],
        ),
        ExternalObjectPlatformFilter(
            column=Platform.slug,
            invert=True,
            name="Platform",
            options=[(p.slug, p.name)
                     for p in db.session.query(Platform.slug, Platform.name)],
        ),
    ]

    def get_query(self):
        q = (super(ExternalObjectView, self).get_query().options(
            joinedload(ExternalObject.values).joinedload(Value.sources)))
        if hasattr(self, "external_object_type"):
            q = q.filter(ExternalObject.type == self.external_object_type)
        return q

    def get_count_query(self):
        q = super(ExternalObjectView, self).get_count_query()
        if hasattr(self, "external_object_type"):
            q = q.filter(ExternalObject.type == self.external_object_type)
        return q
Ejemplo n.º 18
0
class APIKeyView(CVAdminModelView):
    can_create = True
    can_edit = False
    can_delete = True

    column_labels = dict(id='ID',
                         botid='机器人',
                         key='API Key',
                         secret='API Secret',
                         create_at='创建时间',
                         update_at='更新时间')
    column_formatters = dict(
        botid=lambda v, c, m, p: get_botname(m.botid),
        create_at=lambda v, c, m, p: display_datetime(m.create_at),
        update_at=lambda v, c, m, p: display_datetime(m.update_at))

    column_extra_row_actions = [
        EndpointLinkRowAction('fa fa-refresh',
                              'apikey.refresh_view',
                              title='更新Key和Secret')
    ]

    form_create_rules = ('botid', )

    form_edit_rules = ('botid', 'new_key', 'new_secret')

    def __init__(self, model, session):
        CVAdminModelView.__init__(self, model, session, 'API密钥', '系统设置')

    def is_accessible(self):
        from common.login import admin_permission
        if admin_permission.can():
            return login.current_user.is_authenticated
        else:
            return False

    def get_create_form(self):
        form = self.scaffold_form()

        def query_factory():
            return [r.id for r in Bot.findall()]

        def get_pk(obj):
            return obj

        def get_label(obj):
            return Bot.find(obj).name

        from wtforms.ext.sqlalchemy.fields import QuerySelectField
        form.botid = QuerySelectField(
            '机器人', [validators.required(message='机器人是必填字段')],
            query_factory=query_factory,
            get_label=get_label,
            get_pk=get_pk,
            widget=Select2Widget())
        return form

    def get_edit_form(self):
        form = self.scaffold_form()
        delattr(form, 'key')
        delattr(form, 'secret')
        form.botid = StringField('机器人', render_kw={'readonly': True})
        form.new_key = StringField('新API Key', render_kw={'readonly': True})
        form.new_secret = StringField('新API Secret',
                                      render_kw={'readonly': True})
        return form

    def on_form_prefill(self, form, id):
        form.new_key.data = generate_key(32, True, False, True)
        form.new_secret.data = generate_key(12, False, True, True)

    def on_model_change(self, form, model, is_created):
        if not is_created:
            if form.new_key.data:
                model.key = form.new_key.data
                model.secret = form.new_secret.data

    @expose('/refresh/', methods=('GET', 'POST'))
    def refresh_view(self):
        """
            Refresh key and secret
        """
        return_url = get_redirect_target() or self.get_url('.index_view')

        id = get_mdict_item_or_list(request.args, 'id')
        if id is not None:
            self.get_one(id).refresh()

        return redirect(return_url)
Ejemplo n.º 19
0
class Tes(BaseModelView):
    can_create = False
    can_edit = True
    can_delete = False
    page_size = 10

    column_list = ['station_id', 'country', 'state', 'series', 'lat', 'lon']

    column_default_sort = ('station_id', True)
    column_sortable_list = ['station_id']

    column_labels = dict(station_id='Station Name',
                         country='Country',
                         state='State',
                         series='Series',
                         lat='Latitude',
                         lon='Longitude')  # Rename 'title' column in list view
    column_searchable_list = ['station_id']

    can_export = True
    export_max_rows = 1000
    export_types = ['csv', 'xls']

    column_extra_row_actions = [
        #LinkRowAction('icon-edit', 'http://direct.link/?id={row_id}'),
        EndpointLinkRowAction(
            icon_class='icon-search glyphicon glyphicon-search',
            endpoint='dataview.series',
            title="View Details",
            id_arg='station_name')
    ]

    def create_model(self, **kwargs):
        pass

    def delete_model(self, **kwargs):
        pass

    def get_pk_value(self, model):
        return model.station_id

    def get_list(self, page, sort_field, sort_desc, search, filters, **kwargs):
        station_dao, series_dao, _ = setup_daos()
        count = station_dao.count()
        stations = station_dao.get_limited(limit=self.page_size,
                                           offset=page * self.page_size)
        ret = list()
        for station in stations:
            ret.append(
                Station(station_id=station[0],
                        country=station[6],
                        state=station[1],
                        series=series_dao.count(station_id=station[0]),
                        lat=station[3],
                        lon=station[4]))

        return count, ret

    def get_one(self, id, **kwargs):
        station_dao, _, _ = setup_daos()
        station = station_dao.get_for_name(station_name=id)

        return Station(station_id=station[0],
                       country=station[6],
                       state=station[1],
                       series=0,
                       lat=station[3],
                       lon=station[4])

    # def scaffold_list_columns(self):
    #    return ['name', 'field']

    # def scaffold_sortable_columns(self):
    #    return None

    def scaffold_form(self):
        class MyForm(form.Form):
            station_id = StringField('Station Name')
            country = StringField('Country')
            lat = FloatField('Latitude')
            lon = FloatField('Longitude')

        return MyForm

    def update_model(self, form, model):
        print('Currently not supported')
        return True
Ejemplo n.º 20
0
class FormAdmin(PageAdmin):
    column_extra_row_actions = [
        EndpointLinkRowAction(
            icon_class="fa fa-download",
            endpoint=".export_entries",
            title=lazy_gettext("Export Entries as CSV"),
            id_arg="pk",
        ),
        EndpointLinkRowAction(
            icon_class="fa fa-table",
            endpoint=".view_entries",
            title=lazy_gettext("View Entries"),
            id_arg="pk",
        ),
    ]
    form_excluded_columns = list(PageAdmin.form_excluded_columns) + [
        "author",
        "created",
        "updated",
        "entries",
    ]
    form_columns = list(PageAdmin.form_columns)
    form_columns.insert(6, "fields")
    form_columns.insert(7, "submit_text")
    form_columns.insert(8, "submit_message")
    form_overrides = {"submit_message": CkeditorTextAreaField}
    inline_models = [
        (
            Field,
            dict(
                form_columns=[
                    "id",
                    "name",
                    "label",
                    "description",
                    "type",
                    "choices",
                    "default",
                    "required",
                    "max_length",
                ],
                form_extra_fields={
                    "type": SelectField(
                        label=Field.type.info["label"],
                        description=Field.type.info["description"],
                        choices=field_type_choices,
                    )
                },
            ),
        )
    ]

    @expose("/export-entries/<int:pk>")
    def export_entries(self, pk):
        """Taken from Flask-Admin with some modifications, no shame!"""
        form = self.get_one(str(pk))
        filename = "attachment; filename=%s" % _gen_csv_file_name(form)

        class Echo(object):
            """
            An object that implements just the write method of the file-like
            interface.
            """

            def write(self, value):
                """
                Write the value by returning it, instead of storing
                in a buffer.
                """
                return value

        writer = csv.writer(Echo())

        def generate():
            # Append the column titles at the beginning
            titles = [csv_encode("date")] + [
                csv_encode(field.name) for field in form.fields
            ]
            yield writer.writerow(titles)
            for entry in form.entries:
                vals = [csv_encode(entry.created.isoformat())] + [
                    csv_encode(_process_field_value(field)) for field in entry.fields
                ]
                yield writer.writerow(vals)

        return Response(
            stream_with_context(generate()),
            headers={"Content-Disposition": filename},
            mimetype="text/csv",
        )

    @expose("/view-entries/<int:pk>")
    def view_entries(self, pk):
        """View form entries"""
        form = self.get_one(str(pk))
        entries = FormEntry.query.filter_by(form=form)
        paginator = paginate_with_args(entries)
        return self.render(
            "oy_admin/form-entries.html",
            form=form,
            paginator=paginator,
            val_proc=_process_field_value,
        )
Ejemplo n.º 21
0
                                "meta_description",
                                "has_auto_desc",
                                "keywords",
                            ),
                            form_excluded_columns=("site", "created",
                                                   "updated", "versions",
                                                   'author'),
                            form_extra_fields={
                                'status':
                                SelectField(label=lazy_gettext('Status'),
                                            choices=Displayable.STATUS_CHOICES)
                            })

default_row_actions = (EndpointLinkRowAction(
    icon_class="fa fa-clock-o",
    endpoint='.versioning_index',
    title=lazy_gettext("Manage Versions"),
    id_arg='pk'), )


class SiteAdmin(CanellaModelView):
    can_view_details = True
    # Edit in a dialog not in a new page.
    edit_modal = True
    details_modal = True
    # Enable CSRF protection.
    form_base_class = SecureForm
    form_excluded_columns = ['settings']
    # How many entries to display per page?
    page_size = 5
    # Column formatters.
Ejemplo n.º 22
0
class Report1View(ModelView):

    column_extra_row_actions = [
        EndpointLinkRowAction('fa fa-file glyphicon icon-file', 'report1.create_report'),
    ]

    can_create = False
    can_delete = False
    can_edit = True
    can_view_details = False
    can_export = True

    column_list = ('user_id', 'course', 'per_start', 'per_end')
    form_columns = ('user_id', 'course', 'per_start', 'per_end')

    column_labels = dict(
        user_id=u'Имя пользователя',
        course=u'Идентификатор курса',
        per_start=u'Начало промежутка',
        per_end=u'Конец промежутка'
    )

    column_formatters = dict(
        user_id=lambda v, c, m, p: db.session.query(Users.username).filter(Users.id == m.user_id).one_or_none()[0] if m.user_id else '',
        per_start=lambda v, c, m, p: datetime.strftime(m.per_start, '%d.%m.%Y') if m.per_start else '',
        per_end=lambda v, c, m, p: datetime.strftime(m.per_end, '%d.%m.%Y') if m.per_end else ''
    )

    column_display_pk = False

    @expose('/report')
    def create_report(self):
        data={}
        user_id = db.session.query(Report1.user_id)\
                .filter(Report1.id == request.args.get('id')).one_or_none()[0]
        data['username'] = db.session.query(Users.username)\
                .filter(Users.id == user_id).one_or_none()[0]
        data['lastseen'] = datetime.strftime(
            db.session.query(Others.event_time)\
            .filter(Others.user_id == user_id)\
            .order_by(Others.event_time.desc()).first()[0],
            '%d.%m.%Y %H:%M:%S')
        courses = db.session.query(EnrollmentEvents.course, EnrollmentEvents.event_time)\
                .filter(and_(EnrollmentEvents.user_id == user_id,
                            EnrollmentEvents.type == 'enrollment_activated'))
        data['courses'] = []
        count = 1
        for c in courses.all():
            row = {}
            row['pp'] = count
            row['course'] = c.course
            count += 1
            row['reg_time'] = datetime.strftime(c.event_time, '%d.%m.%Y %H:%M:%S')
            deact_time = db.session.query(EnrollmentEvents.event_time)\
                .filter(and_(EnrollmentEvents.user_id == user_id,
                        EnrollmentEvents.type == 'enrollment_deactivated')).first()
            row['deact_time'] = datetime.strftime(deact_time[0], '%d.%m.%Y %H:%M:%S') if deact_time else u'---'
            cert_time = db.session.query(CertificateEvents.event_time)\
                .filter(and_(CertificateEvents.course == c.course,
                        CertificateEvents.user_id == user_id)).first()
            row['cert_time'] = datetime.strftime(cert_time[0], '%d.%m.%Y %H:%M:%S') if cert_time else u'---'
            right = db.session.query(CheckAnswerEvents.event_time)\
                .filter(and_(CheckAnswerEvents.type == 'problem_check',
                            CheckAnswerEvents.success == True,
                            CheckAnswerEvents.user_id == user_id)).all()
            false = db.session.query(CheckAnswerEvents.event_time)\
                .filter(and_(CheckAnswerEvents.type == 'problem_check',
                            CheckAnswerEvents.success == False,
                            CheckAnswerEvents.user_id == user_id)).all()
            row['rf'] = str(len(right)) + u'/' + str(len(false))

            data['courses'].append(row)

        #second plot
        plt.rcdefaults()
        fig, ax = plt.subplots()
        events = (u'Серт.',
                u'Пров. отв.',
                u'Докум.',
                u'Регистр.',
                u'Сылки',
                u'Навиг.',
                u'Видео')
        y_pos = range(len(events))
        plot_values = (
            len(db.session.query(CertificateEvents.id).filter(CertificateEvents.user_id == user_id).all()),
            len(db.session.query(CheckAnswerEvents.id).filter(CheckAnswerEvents.user_id == user_id).all()),
            len(db.session.query(DocumentEvents.id).filter(DocumentEvents.user_id == user_id).all()),
            len(db.session.query(EnrollmentEvents.id).filter(EnrollmentEvents.user_id == user_id).all()),
            len(db.session.query(LinkEvents.id).filter(LinkEvents.user_id == user_id).all()),
            len(db.session.query(SequenceEvents.id).filter(SequenceEvents.user_id == user_id).all()),
            len(db.session.query(VideoEvents.id).filter(VideoEvents.user_id == user_id).all())
        )

        ax.barh(y_pos, plot_values, xerr=None, align='center', color='orange', ecolor='black')
        ax.set_yticks(y_pos)
        ax.set_yticklabels(events)
        ax.invert_yaxis()
        ax.set_xlabel(u'Количество событий')
        ax.set_title(u'Количество собыий по группам')
        plt.savefig(os_join(app.config['REPORT_PATH'], 'plt2.png'))
        data['plt2_path'] = os_join(app.config['REPORT_PATH'], 'plt2.png')

        #third plot
        plt.rcdefaults()
        fig, ax = plt.subplots()
        events = (u'Докум.',
                u'Курс',
                u'Видео')
        y_pos = range(len(events))
        plot_values = (
            len(db.session.query(DocumentEvents.id).filter(DocumentEvents.user_id == user_id).all()),
            len(db.session.query(LinkEvents.id).filter(LinkEvents.user_id == user_id).all())+\
            len(db.session.query(SequenceEvents.id).filter(SequenceEvents.user_id == user_id).all()),
            len(db.session.query(VideoEvents.id).filter(VideoEvents.user_id == user_id).all())
        )

        ax.barh(y_pos, plot_values, xerr=None, align='center', color='blue', ecolor='black')
        ax.set_yticks(y_pos)
        ax.set_yticklabels(events)
        ax.invert_yaxis()
        ax.set_xlabel(u'Количество собыий')
        ax.set_title(u'Предпочитаемые материалы')
        plt.savefig(os_join(app.config['REPORT_PATH'], 'plt3.png'))
        data['plt3_path'] = os_join(app.config['REPORT_PATH'], 'plt3.png')

        f_name = os_join(app.config['REPORT_PATH'], 'report_res.odt')
        if exists(f_name):
            remove(f_name)
        Renderer(
            os_join(app.config['REPORT_PATH'], "user_report.odt"),
            data,
            f_name,
            pythonWithUnoPath='/usr/bin/python3'
        ).run()

        return send_file(
            filename_or_fp=f_name,
            as_attachment=True,
            attachment_filename=basename(f_name),
            mimetype='application/vnd.oasis.opendocument.text'
        )
Ejemplo n.º 23
0
class AinView(BaseModelView):
    statuses = dict(Statuses.__dict__)

    column_filters = ('Status', 'AlienID', 'Zipcode', 'Last Step Error')
    named_filter_urls = True

    can_set_page_size = True
    page_size = 20

    can_view_details = True

    create_modal = True
    details_modal = True
    edit_modal = True

    export_max_rows = 1000
    can_export = True
    export_types = ['csv', 'xlsx', 'json']

    #column_editable_list = ('Status',)
    column_exclude_list = (
        'CallID',
        'CallUploadUrl',
        'CallTimestamp',
        'TranscribeTimestamp',
        'CallTranscript',
    )

    column_extra_row_actions = [
        EndpointLinkRowAction('glyphicon glyphicon-headphones', 'audio')
    ]

    form_create_rules = [
        Field('PartitionKey'),
    ]

    form_edit_rules = [
        Field('Status'),
    ]

    form_args = dict(
        Status=dict(label='Status', validators=[DataRequired()]),
        PartitionKey=dict(label='AlienID', validators=[DataRequired()]),
    )

    column_labels = dict(
        PartitionKey='Alien ID',
        LastErrorStep='Last Error Step',
        CallTranscript='Call Transcript',
        CallID='Call ID',
        LastModified='Last Modified',
        CallTimestamp='Call Timestamp',
        TranscribeTimestamp='Transcribe Timestamp',
        CallUploadUrl='Call Upload Url',
    )

    def get_pk_value(self, model):
        return model.PartitionKey

    def scaffold_list_columns(self):
        return [
            'PartitionKey',
            'Status',
            'Confidence_location',
            'City',
            'State',
            'Zipcode',
            'day',
            'hour',
            'minute',
            'month',
            'year',
            'CallTranscript',
            'LastErrorStep',
            'CallID',
            'CallUploadUrl',
            'CallTimestamp',
            'LastModified',
            'TranscribeTimestamp',
        ]

    def scaffold_sortable_columns(self):
        return None

    def init_search(self):
        return False

    def scaffold_filters(self, name):
        return [EqualFilter(name, name)]

    def get_list(self,
                 page,
                 sort_field,
                 sort_desc,
                 search,
                 filters,
                 page_size=20):
        if len(filters) > 0:
            filter_col, filter_val = filters[0][1], filters[0][2]
            results = db.query(filter_col, filter_val, page_size)
        else:
            results = db.raw_table(limit=page_size)
        results = list(results)
        return len(results), results

    def get_one(self, id):
        return db.get_ain(id)

    def delete_model(self, model):
        return db.delete_ain(model.PartitionKey)

    def create_model(self, form):
        ain = form.PartitionKey.data
        db.upload_new_requests([ain])
        return self.get_one(ain)

    def update_model(self, form, model):
        status = form.Status.data
        model.Status = status
        db._update_entity(model)
        return True

    def scaffold_form(self):
        class AinForm(BaseForm):
            PartitionKey = StringField('Alien ID')
            Status = SelectField('Status', choices=self.statuses)
            CallTranscript = StringField('CallTranscript')

        return AinForm

    @action('reset_status', 'Reset Status',
            'Are you sure you want to reset the selected records?')
    def action_upload(self, ids):
        try:
            flash('Not implemented yet')
        except Exception as ex:
            flash('Failed to reset the status', 'error')