Ejemplo n.º 1
0
class ControlPanelUserApi(BaseApi):

    resource_name = 'cp/user'
    form_service = FormService()

    @expose('/', methods=['POST'])
    def register(self):
        """

        :return:
        """
        user = request.json.copy()
        form = self.form_service.add_new_user(user)
        return jsonify(form.asdict())

    @expose('/collaborators/add', methods=['GET'])
    def add_collaborators(self, username):
        username = request.json['username']
        form_id = request.json['form_id']
        collaboration_user = self.form_service.add_new_collaboration_user(
            username, form_id)
        return jsonify(collaboration_user.asdict())

    @expose('/collaborators/list/<form_id>', methods=['GET'])
    def get_collaborators_list(self, form_id):
        collaboration_users = self.form_service.fetch_collaboration_users(
            form_id, PageRequest.create(request.args))
        return jsonify(collaboration_users.asdict())

    @expose('/collaborators/<c_id>', methods=['DELETE'])
    def delete(self, c_id):
        collaboration_user = self.form_service.remove_collaboration_user(c_id)
        return jsonify(collaboration_user.asdict())
Ejemplo n.º 2
0
class ControlPanelValueApi(BaseApi):
    resource_name = "cp/value"
    form_service: FormService = FormService()

    @expose('<form_id>')
    def get(self, form_id):
        data = self.form_service.fetch_values(1, 1, 50)
        return jsonify(data)
Ejemplo n.º 3
0
class ControlPanelFieldApi(BaseApi):

    resource_name = 'cp/field'

    form_service: FormService = FormService()

    @expose('', methods=['POST'])
    def create(self):
        """Create a field
        ---
        post:
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Field'
          responses:
            200:
              description: Create a field
              content:
                application/json:
                schema:
                    $ref: '#/components/schemas/Field'
        """

        field = self.form_service.add_new_field(request.json)
        return jsonify(field.asdict()), 201

    @expose('<field_id>', methods=['PUT'])
    def update(self, field_id):
        changed = self.form_service.change_field(field_id, request.json)
        return jsonify(changed.asdict())

    @expose('<field_id>', methods=['DELETE'])
    def delete(self, field_id):
        field = self.form_service.remove_field(field_id)
        return jsonify(field.asdict())

    @expose('<field_id>')
    def get(self, field_id):
        """Get a form
        ---
        get:
          
          responses:
            200:
              description: Get a form
              content:
                application/json:
                schema:
                    $ref: '#/components/schemas/Field'
        """

        field = self.form_service.fetch_field(field_id)
        return jsonify(field.asdict())
Ejemplo n.º 4
0
class FormApi(BaseApi):
    resource_name = 'form'
    apispec_parameter_schemas = SCHEMAS

    form_service = FormService()

    @expose('<form_id>', methods=['GET'])
    def get(self, form_id):
        """Get a form 
        ---
        get:
          parameters:
          - name: form_id
            description: "表单ID"
            required: true
            type: integer
            format: int64
          responses:
            '200':
              description: Get a form
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Form'
        """
        user_agent = to_user_agent(request)
        form = self.form_service.fetch_form(form_id, current_user)

        return jsonify(
            form.asdict(follow={
                'fields': {
                    "follow": {
                        "options": {},
                        "constraints": {},
                    }
                }
            }))

    @expose('/{id}/value', methods=['POST'])
    def submit(self):
        """Submit a form 
        ---
        post:
          description: "提交表单数据"
          responses:
            200:
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/Value"
        """
        pass
Ejemplo n.º 5
0
class FormApi(BaseApi):
    resource_name = 'form'
    apispec_parameter_schemas = SCHEMAS

    form_service = FormService()

    @expose('<form_id>', methods=['GET'])
    def get(self, form_id):
        """Get a form 
        ---
        get:
          responses:
            '200':
              description: Get a form
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Form'
        """
        user_agent = to_user_agent(request)
        form = self.form_service.fetch_form(form_id, current_user, user_agent)
        return jsonify(
            form.asdict(follow={
                'fields': {
                    "follow": {
                        "options": {},
                        "constraints": {},
                    }
                }
            }))

    @expose('/{id}/value', methods=['POST'])
    def submit(self):
        """Submit a form 
        ---
        post:
          responses:
            200:
              description: Submit form list
              content:
                application/json:
                schema:
                  type: object
                  properties:
                    message:
                      type: string
        """
        pass
Ejemplo n.º 6
0
    def test_create(self):
        service = FormService(self.db)
        form = service.add_new_form(MVP_FORM)
        for f in form.fields:
            print(f.id)

        v = service.submit(1, {"name": None, 2: 1, 3: "18621068396"})

        i = 1
        for opt in form.fields[1].options:
            self.assertEquals(i, opt.value)
            i += 1

        service.change_form(form.id, CHANGED_FORM)
        changed = service.fetch_form(form.id)

        self.assertEquals("在 JotForm 上测试 openform MVP Changed", changed.title)
        for field in changed.fields:
            if field.id == 3:
                self.assertTrue(False)

            if field.id == 2:
                for option in field.options:
                    if option.id == 7:
                        self.assertTrue(False)

        mobile = changed.fields[-1]
        self.assertEquals("手机号码", mobile.title)
        print(changed.fields)
        from app import db
        for i in db.session.query(models.Field).all():
            print(i.to_json())

        v = service.submit(1, {"name": "魏琮举", 2: 1, 3: "18621068396"})
        v = service.submit(1, {"name": None, 2: 1, 3: "18621068396"})
        print(changed.fields[0].title)
        print(changed.fields[0].errors)
Ejemplo n.º 7
0
class FormView(BaseView):
    form_service = FormService()
    route_base = '/form'
    assembler = FormViewModelAssembler()

    @expose('/<form_id>', methods=["GET", "POST"])
    def form(self, form_id):
        user_agent = to_user_agent(request)
        form = self.form_service.fetch_form(form_id, g.user, user_agent)
        form_view = self.assembler.to_view_model(form, request.form)

        if "POST" == request.method:

            user_agent = to_user_agent(request)

            if self.form_service.submit(form, user_agent):
                return self.render_template('openform/form_success.html')

        return self.render_template("openform/form.html",
                                    form_view=form_view,
                                    form=form)
Ejemplo n.º 8
0
class FormView(BaseView):
    form_service = FormService()
    route_base = '/form'
    assembler = FormViewModelAssembler()

    @expose('/<form_id>', methods=["GET", "POST"])
    def form(self, form_id):
        user_agent = to_user_agent(request)
        form = self.form_service.fetch_form(form_id, g.user, user_agent)
        form_view = self.assembler.to_view_model(form, ParameterContainer())

        if "POST" == request.method:
            
            user_agent = to_user_agent(request)

            if self.form_service.submit(form, g.user, user_agent):
                return redirect(
                    url_for("FormView.success_redirect", form_id=form_id)
                )

        return self.render_template(
            "openform/form.html",
            form_view = form_view,
            form = form
        )

    @expose('/<form_id>/success_redirect', methods=['GET'])
    def success_redirect(self, form_id):

        return redirect(
            url_for("FormView.form_success", form_id=form_id)
        )

    @expose('/<form_id>/success', methods=['GET'])
    def form_success(self, form_id):

        return self.render_template(
            'openform/form_success.html'
        )
Ejemplo n.º 9
0
class ControlPanelFormRoleApi(BaseApi):
    resource_name = 'cp/form/role'

    def __init__(self):
        super().__init__()

        self.form_service = FormService()

    @expose('')
    def get(self):
        """Get a form
        ---
        get:
          responses:
            200:
              description: 查询表单协作的角色
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/Form"
        """
        roles = self.form_service.all_roles()
        return jsonify([role.asdict() for role in roles])
Ejemplo n.º 10
0
class ControlPanelFormApi(BaseApi):

    resource_name = 'cp/form'
    form_service = FormService()

    def __init__(self):
        super().__init__()

        self.event_repository = EventRepository(db)
        self.value_repository = ValueRepository(db)
        self.form_repository = FormRepository(db)
  
    @jwt_required
    @expose('/', methods=['POST'])
    def create(self):
        """Create a form
        ---
        post:
          summary: 创建表单
          description: 创建表单
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Form'
          responses:
            200:
              description: Create a form
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Form'
        """
        form = request.json.copy()
        form["user_id"] = current_user.id
        form = self.form_service.add_new_form(form)
        
        return jsonify(form.asdict()), 201

    @expose('/{id}', methods=['PUT'])
    def update(self):
        """Create a form
        ---
        put:
          summary: 更新表单
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Form'
          responses:
            200:
              description: Create a form
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Form'
        """
        
        return self.response(200, **{})

    @expose('/{id}/publish', methods=['POST'])
    def publish(self):
        """Publish a form
        ---
        post:
          summary: 发布表单
          responses:
            200:
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Form'
        """
        
        return self.response(200, **{})

    @expose('/{id}/publish', methods=['DELETE'])
    def unpublish(self):
        """Delete a form
        ---
        delete:
          summary: 取消表单发布
          responses:
            200:
              description: Delete a form
              content:
                application/json:
                schema:
                  type: object
                  properties:
                    message:
                      type: string
        """
        
        return self.response(200, **{})

    @jwt_required
    @expose('/', methods=['GET'])
    def get_list(self):
        """Get form list
        ---
        get:
          summary: 查询表单列表
          responses:
            200:
              content:
                application/json:
                  schema:
                    type: array
                    items:
                      $ref: "#/components/schemas/Form"
        """
        forms = self.form_service.fetch_forms(
            current_user.id, PageRequest.create(request.args)
        )
        return jsonify(forms.asdict())

    @expose('/{id}', methods=['GET'])
    def get_detail(self):
        """Get a form
        ---
        get:
          responses:
            200:
              description: Get a form
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/Form"
        """
        
        return self.response(200, **{})

    @jwt_required
    @expose("/<form_id>/summary", methods=["GET"])
    def summary(self, form_id):
        user = current_user
        submit_count_by_days = self.value_repository.count_by_8_days(user.id, form_id)
        form = self.form_repository.find_one(form_id)

        return jsonify({
            "submit_count": self.value_repository.count_all(user.id, form_id),
            "submit_count_today": self.value_repository.count_today(
                user.id, form_id),
            "reads_today": self.event_repository.count_today(form_id, EventType.VIEW_FORM),
            "submit_count_by_days": submit_count_by_days,
            "read_count_by_days": self.event_repository.count_by_8_days(form_id, EventType.VIEW_FORM),
            "submit_count_by_mintes": self.value_repository.count_by_24_minute(
                user.id, form_id),
            "form": form.asdict(),
        })

    @expose('/<form_id>/value', methods=['GET'])
    def value(self, form_id):
        page_request = PageRequest.create(request.args)
        value = self.form_service.fetch_values(
            form_id, page_request
        )
        return jsonify(value.asdict())

    @jwt_required
    @expose("/<form_id>/export", methods=["GET"])
    def export(self, form_id):
        """
        ---
        get:
          description: "导出CSV文件"
          responses:
            200:
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/Form"
        """
        # TODO: 根据 Request Content Type 来导出返回的内容,例如JSON
        form_id = int(form_id)
        count = self.value_repository.count(form_id)
        form = self.form_repository.find_one(form_id)
        db.session.commit()
        fields_map = {}
        for field in form.fields:
            fields_map[int(field.id)] = field

        def to_export(row):
            ex = {}

            for field_id, value in row['values'].items():
                field = fields_map[int(field_id)]
                ex[field.title] = field.to_text_value(value)
            ex['id'] = row['sequence']
            ex['created_at'] = row['created_at']
            ex['updated_at'] = row['updated_at']

            return ex
        
        def generate():
            paginator = PageRequest.create(request.args)
            args = [int(form_id), paginator]
            i = 0
            position = 0
            while i < paginator.page_size:
                print(i)
                args[1].page = i + 1
                values = self.value_repository.find(*args)
                if i == 0:
                    iostream = io.StringIO()
                    first = to_export(values[0].asdict())
                    keys = first.keys()
                    csv_writer = csv.DictWriter(iostream, fieldnames=keys)
                    csv_writer.writeheader()

                for value in values:
                    csv_writer.writerow(to_export(value.asdict()))
                
                iostream.seek(position)
                for line in iostream.readline():
                    yield line
                position = iostream.tell()
                i += 1

        response = Response(stream_with_context(generate()))
        response.headers["Content-Type"] = "text/csv"

        return response
    
        @jwt_required
    @expose("/excel", methods=['GET'])
    def from_excel(self):
        book = xlwt.Workbook()
        sheet = book.add_sheet('form')
        title = ['%s' % item for item in ff.Form.__dict__.keys() if not str(item).startswith("_")]
        i = 0
        for h in title:
            sheet.write(0, i, h)
            i = 1

        forms = self.form_service.fetch_forms_not_page(current_user.id)

        for row, form in enumerate(forms):
            for col in range(0, len(title)):
                sheet.write(row  1, col, form[title[col]])

        bio = BytesIO()
        book.save(bio)
        return bio.getvalue()

    @jwt_required
    @expose("/statement", methods=['GET'])
    def statement(self):
         """
            表单报表
        :return:
        """
        field_num = self.form_service.count_field()
        select_field_num = self.form_service.count_select_field()
        return self.response(200, **{"statement": round(select_field_num / field_num, 2)})
Ejemplo n.º 11
0
class ControlPanelValueApi(BaseApi):
    resource_name = "cp/value"

    def __init__(self):
        super(ControlPanelValueApi, self).__init__()
        self.form_service = FormService()

    @expose('')
    def get(self, form_id):
        """
        ---
        get:
          summary: "查询表格数据"
          description: "查询表格数据"
          responses:
            200:
              description: Get a form
              content:
                application/json:
                  schema:
                    type: array
                    items:
                      $ref: "#/components/schemas/Value"
        """
        data = self.form_service.fetch_values(1, 1, 50)
        return jsonify(data)

    @expose("", methods=["POST"])
    def create(self, values):
        """
        ---
        post:
          summary: "创建表格数据"
          description: "创建表格数据"
          responses:
            200:
              description: Get a form
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/Value"
        """
        return jsonify({})

    @expose('/<value_id>')
    def fetch_one(self, value_id):
        """
        ---
        get:
          summary: "查询表格数据"
          description: "查询表格数据"
          parameters:
          - name: value_id
            in: path
            type: integer
            format: int64
            description: "Value 主键ID"
          responses:
            200:
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/Value"
        """
        return jsonify({})

    @expose('/<value_id>', methods=["PUT"])
    def update(self, value_id):
        """
        ---
        put:
          summary: "更新表格数据"
          description: "更新表格数据"
          parameters:
          - name: value_id
            in: path
            type: integer
            format: int64
            description: "Value 主键ID"
          requestBody:
            content:
              application/json:
                schema:
                  $ref: "#/components/schemas/Value"
          responses:
            200:
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/Value"
        """
        return jsonify({})

    @expose('/<value_id>', methods=["DELETE"])
    def delete(self, value_id):
        """
        ---
        delete:
          summary: "删除表格数据"
          description: "删除表格数据"
          parameters:
          - name: value_id
            in: path
            type: integer
            format: int64
            description: "Value 主键ID"
          responses:
            200:
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/Value"
        """
        return jsonify({})

    @expose('/<value_id>')
    def duplicate(self, value_id):
        return jsonify({})
Ejemplo n.º 12
0
 def __init__(self):
     super(ControlPanelValueApi, self).__init__()
     self.form_service = FormService()
Ejemplo n.º 13
0
    def __init__(self):
        super().__init__()

        self.form_service = FormService()
Ejemplo n.º 14
0
class ControlPanelFieldApi(BaseApi):
    
    resource_name = 'cp/field'

    form_service : FormService = FormService()

    @expose('', methods=['POST'])
    def create(self):
        """Create a field
        ---
        post:
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Field'
          responses:
            200:
              description: Create a field
              content:
                application/json:
                schema:
                    $ref: '#/components/schemas/Field'
        """

        field = self.form_service.add_new_field(request.json)
        return jsonify(field.asdict()), 201

    @expose('<field_id>', methods=['PUT'])
    def update(self, field_id):
        changed = self.form_service.change_field(field_id, request.json)
        return jsonify(changed.asdict())

    @expose('<field_id>', methods=['DELETE'])
    def delete(self, field_id):
        field = self.form_service.remove_field(field_id)
        return jsonify(field.asdict())

    @expose('<field_id>')
    def get(self, field_id):
        """Get a form
        ---
        get:
          
          responses:
            200:
              description: Get a form
              content:
                application/json:
                schema:
                    $ref: '#/components/schemas/Field'
        """

        field = self.form_service.fetch_field(field_id)
        return jsonify(field.asdict())

    @expose('/list_by_form_id/<from_id>', methods=['GET'])
    def get_list(self, form_id):
        """
            表单数据查询接口,包括排序
        :param form_id:
        :return:
        """

        fields = self.form_service.fetch_fields(form_id, PageRequest.create(request.args))
        return jsonify(fields.asdict())

    @expose('/add_by_form_id/<from_id>', methods=['POST'])
    def add_by_form_id(self, form_id):
        """
            插入提条数据到表单
        :param form_id:
        :return:
        """
        field = request.json.copy()
        field["form_id"] = form_id
        form = self.form_service.add_new_field(field)
        return jsonify(form.asdict()), 200
Ejemplo n.º 15
0
class ControlPanelFormApi(BaseApi):

    resource_name = 'cp/form'
    form_service = FormService()

    def __init__(self):
        super().__init__()

        self.event_repository = EventRepository(db)
        self.value_repository = ValueRepository(db)
        self.form_repository = FormRepository(db)

    @jwt_required
    @expose('', methods=['POST'])
    def create(self):
        """Create a form
        ---
        post:
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Form'
          responses:
            200:
              description: Create a form
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Form'
        """
        form = request.json.copy()
        form["user_id"] = current_user.id
        form = self.form_service.add_new_form(form)

        return jsonify(form.asdict()), 201

    @expose('/{id}', methods=['PUT'])
    def update(self):
        """Create a form
        ---
        put:
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Form'
          responses:
            200:
              description: Create a form
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Form'
        """

        return self.response(200, **{})

    @expose('/{id}/publish', methods=['DELETE'])
    def publish(self):
        """Publish a form
        ---
        delete:
          responses:
            200:
              description: Publish a form
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Form'
        """

        return self.response(200, **{})

    @expose('/{id}/publish', methods=['DELETE'])
    def unpublish(self):
        """Delete a form
        ---
        delete:
          responses:
            200:
              description: Delete a form
              content:
                application/json:
                schema:
                  type: object
                  properties:
                    message:
                      type: string
        """

        return self.response(200, **{})

    @jwt_required
    @expose('/', methods=['GET'])
    def get_list(self):
        """Get form list
        ---
        get:
          responses:
            200:
              description: Get form list
              content:
                application/json:
                schema:
                  type: object
                  properties:
                    message:
                      type: string
        """
        forms = self.form_service.fetch_forms(current_user.id,
                                              PageRequest.create(request.args))
        return jsonify(forms.asdict())

    @expose('/{id}', methods=['GET'])
    def get_detail(self):
        """Get a form
        ---
        get:
          responses:
            200:
              description: Get a form
              content:
                application/json:
                schema:
                  type: object
                  properties:
                    message:
                      type: string
        """

        return self.response(200, **{})

    @jwt_required
    @expose("/<form_id>/summary", methods=["GET"])
    def summary(self, form_id):
        user = current_user
        submit_count_by_days = self.value_repository.count_by_8_days(
            user.id, form_id)
        form = self.form_repository.find_one(form_id)

        return jsonify({
            "submit_count":
            self.value_repository.count_all(user.id, form_id),
            "submit_count_today":
            self.value_repository.count_today(user.id, form_id),
            "reads_today":
            self.event_repository.count_today(form_id, EventType.VIEW_FORM),
            "submit_count_by_days":
            submit_count_by_days,
            "read_count_by_days":
            self.event_repository.count_by_8_days(form_id,
                                                  EventType.VIEW_FORM),
            "submit_count_by_mintes":
            self.value_repository.count_by_24_minute(user.id, form_id),
            "form":
            form.asdict(),
        })

    @jwt_required
    @expose("/<form_id>/export", methods=["GET"])
    def export(self, form_id):
        # TODO: 根据 Request Content Type 来导出返回的内容,例如JSON
        form_id = int(form_id)
        count = self.value_repository.count(form_id)
        form = self.form_repository.find_one(form_id)
        db.session.commit()
        fields_map = {}
        for field in form.fields:
            fields_map[int(field.id)] = field

        def to_export(row):
            ex = {}

            for field_id, value in row['values'].items():
                field = fields_map[int(field_id)]
                ex[field.title] = field.to_text_value(value)
            ex['id'] = row['sequence']
            ex['created_at'] = row['created_at']
            ex['updated_at'] = row['updated_at']

            return ex

        def generate():
            args = [int(form_id), PageRequest.create(request.args)]
            i = 0
            position = 0
            while i < count:
                args[1].page = i + 1
                values = self.value_repository.find(*args)
                if i == 0:
                    iostream = io.StringIO()
                    first = to_export(values[0].asdict())
                    keys = first.keys()
                    csv_writer = csv.DictWriter(iostream, fieldnames=keys)
                    csv_writer.writeheader()

                for value in values:
                    csv_writer.writerow(to_export(value.asdict()))

                iostream.seek(position)
                for line in iostream.readline():
                    print(line)
                    yield line
                position = iostream.tell()
                i += 1

        response = Response(stream_with_context(generate()))
        response.headers["Content-Type"] = "text/csv"

        return response
Ejemplo n.º 16
0
class ControlPanelFormApi(BaseApi):

    resource_name = 'cp/form'
    form_service = FormService()

    def __init__(self):
        super().__init__()

        self.event_repository = EventRepository(db)
        self.value_repository = ValueRepository(db)
        self.form_repository = FormRepository(db)
        self.logger = logging.getLogger('ControlPanelFormApi')

    @jwt_required
    @expose('', methods=['POST'])
    def create(self):
        """Create a form
        ---
        post:
          summary: 创建表单
          description: 创建表单
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/FormCreation'
          responses:
            200:
              description: Create a form
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Form'
        """
        form = request.json.copy()
        form["user_id"] = current_user.id
        form = self.form_service.add_new_form(form)

        return jsonify(
            form.asdict(follow={
                'fields': {
                    "follow": {
                        "options": {},
                        "constraints": {},
                    }
                }
            })), 201

    @jwt_required
    @expose('/<int:form_id>', methods=['PUT'])
    def update(self, form_id: int):
        """Create a form
        ---
        put:
          summary: 更新表单
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/FormEdition'
          responses:
            200:
            description: Create a form
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Form'
        """

        form_guard(int(form_id), ['Manager'])

        form_dto = request.json.copy()
        form_dto['id'] = int(form_id)
        form = self.form_service.change_form(form_id, form_dto)
        return jsonify(
            form.asdict(follow={
                'fields': {
                    "follow": {
                        "options": {},
                        "constraints": {},
                    }
                }
            }))

    @expose('/{id}/publish', methods=['POST'])
    def publish(self):
        """Publish a form
        ---
        post:
          summary: 发布表单
          responses:
            200:
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Form'
        """

        return self.response(200, **{})

    @expose('/{id}/publish', methods=['DELETE'])
    def unpublish(self):
        """Delete a form
        ---
        delete:
          summary: 取消表单发布
          responses:
            200:
              description: Delete a form
              content:
                application/json:
                schema:
                  type: object
                  properties:
                    message:
                      type: string
        """

        return self.response(200, **{})

    @jwt_required
    @expose('/', methods=['GET'])
    def get_list(self):
        """Get form list
        ---
        get:
          summary: 查询表单列表
          responses:
            200:
              content:
                application/json:
                  schema:
                    type: array
                    items:
                      $ref: "#/components/schemas/Form"
        """
        forms = self.form_service.fetch_forms(current_user.id,
                                              PageRequest.create(request.args))
        return jsonify(forms.asdict())

    @jwt_required
    @expose('/<int:form_id>', methods=['GET'])
    def get_detail(self, form_id: int):
        """Get a form
        ---
        get:
          responses:
            200:
              description: Get a form
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/Form"
        """
        form_guard(form_id, ['Viewer', 'Editor', 'Manager'])
        form = self.form_service.fetch_form(form_id, current_user)
        return jsonify(
            form.asdict(follow={
                'fields': {
                    "follow": {
                        "options": {},
                        "constraints": {},
                    }
                }
            }))

    @jwt_required
    @expose("/<int:form_id>/summary", methods=["GET"])
    def summary(self, form_id: int):
        form_guard(form_id, ['Viewer', 'Editor', 'Manager'])

        user = current_user
        submit_count_by_days = self.value_repository.count_by_8_days(
            user.id, form_id)
        form = self.form_repository.find_one(form_id)

        return jsonify({
            "submit_count":
            self.value_repository.count_all(user.id, form_id),
            "submit_count_today":
            self.value_repository.count_today(user.id, form_id),
            "reads_today":
            self.event_repository.count_today(form_id, EventType.VIEW_FORM),
            "submit_count_by_days":
            submit_count_by_days,
            "read_count_by_days":
            self.event_repository.count_by_8_days(form_id,
                                                  EventType.VIEW_FORM),
            "submit_count_by_mintes":
            self.value_repository.count_by_24_minute(user.id, form_id),
            "form":
            form.asdict(),
        })

    @jwt_required
    @expose('/<int:form_id>/value', methods=['GET'])
    def value(self, form_id: int):
        form_guard(form_id, ['Viewer', 'Editor', 'Manager'])

        page_request = PageRequest.create(request.args)
        page_request.order("created_at", "desc")

        value = self.form_service.fetch_values(form_id, page_request)
        return jsonify(value.asdict())

    @jwt_required
    @expose("/<form_id>/export", methods=["GET"])
    def export(self, form_id):
        """
        ---
        get:
          description: "导出CSV文件"
          responses:
            200:
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/Form"
        """
        # TODO: 根据 Request Content Type 来导出返回的内容,例如JSON
        form_id = int(form_id)
        count = self.value_repository.count(form_id)
        form = self.form_repository.find_one(form_id)
        db.session.commit()
        fields_map = {}
        for field in form.fields:
            fields_map[int(field.id)] = field

        def to_export(row):
            ex = {}

            for field_id, value in row['values'].items():
                field = fields_map[int(field_id)]
                ex[field.title] = field.to_text_value(value)
            ex['id'] = row['sequence']
            ex['created_at'] = row['created_at']
            ex['updated_at'] = row['updated_at']

            return ex

        def generate():
            paginator = PageRequest.create(request.args)
            args = [int(form_id), paginator]
            i = 0
            position = 0
            while i < paginator.page_size:
                print(i)
                args[1].page = i + 1
                values = self.value_repository.find(*args)
                if i == 0:
                    iostream = io.StringIO()
                    first = to_export(values[0].asdict())
                    keys = first.keys()
                    csv_writer = csv.DictWriter(iostream, fieldnames=keys)
                    csv_writer.writeheader()

                for value in values:
                    csv_writer.writerow(to_export(value.asdict()))

                iostream.seek(position)
                for line in iostream.readline():
                    yield line
                position = iostream.tell()
                i += 1

        response = Response(stream_with_context(generate()))
        response.headers["Content-Type"] = "text/csv"

        return response