Merge pull request #1052 from MITx/feature/victor/actual-askbot-removal
Removing Askbot
2
.gitignore
vendored
@@ -9,8 +9,6 @@
|
||||
.AppleDouble
|
||||
database.sqlite
|
||||
courseware/static/js/mathjax/*
|
||||
db.newaskbot
|
||||
db.oldaskbot
|
||||
flushdb.sh
|
||||
build
|
||||
.coverage
|
||||
|
||||
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
||||
[submodule "askbot"]
|
||||
path = askbot
|
||||
url = git@github.com:MITx/askbot-devel.git
|
||||
|
||||
12
.hgignore
@@ -1,12 +0,0 @@
|
||||
syntax: glob
|
||||
*.pyc
|
||||
*~
|
||||
*.scssc
|
||||
*.swp
|
||||
*.orig
|
||||
*.DS_Store
|
||||
database.sqlite
|
||||
courseware/static/js/mathjax/*
|
||||
db.newaskbot
|
||||
db.oldaskbot
|
||||
flushdb.sh
|
||||
1
askbot
157
common/djangoapps/student/migrations/0021_remove_askbot.py
Normal file
@@ -0,0 +1,157 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
ASKBOT_AUTH_USER_COLUMNS = (
|
||||
'website',
|
||||
'about',
|
||||
'gold',
|
||||
'email_isvalid',
|
||||
'real_name',
|
||||
'location',
|
||||
'reputation',
|
||||
'gravatar',
|
||||
'bronze',
|
||||
'last_seen',
|
||||
'silver',
|
||||
'questions_per_page',
|
||||
'new_response_count',
|
||||
'seen_response_count',
|
||||
)
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
"Kill the askbot"
|
||||
# For MySQL, we're batching the alters together for performance reasons
|
||||
if db.backend_name == 'mysql':
|
||||
drops = ["drop `{0}`".format(col) for col in ASKBOT_AUTH_USER_COLUMNS]
|
||||
statement = "alter table `auth_user` {0};".format(", ".join(drops))
|
||||
db.execute(statement)
|
||||
else:
|
||||
for column in ASKBOT_AUTH_USER_COLUMNS:
|
||||
db.delete_column('auth_user', column)
|
||||
|
||||
def backwards(self, orm):
|
||||
raise RuntimeError("Cannot reverse this migration: there's no going back to Askbot.")
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'student.courseenrollment': {
|
||||
'Meta': {'unique_together': "(('user', 'course_id'),)", 'object_name': 'CourseEnrollment'},
|
||||
'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'student.pendingemailchange': {
|
||||
'Meta': {'object_name': 'PendingEmailChange'},
|
||||
'activation_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'new_email': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'})
|
||||
},
|
||||
'student.pendingnamechange': {
|
||||
'Meta': {'object_name': 'PendingNameChange'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'new_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'rationale': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'})
|
||||
},
|
||||
'student.registration': {
|
||||
'Meta': {'object_name': 'Registration', 'db_table': "'auth_registration'"},
|
||||
'activation_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'})
|
||||
},
|
||||
'student.testcenteruser': {
|
||||
'Meta': {'object_name': 'TestCenterUser'},
|
||||
'address_1': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
|
||||
'address_2': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}),
|
||||
'address_3': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}),
|
||||
'candidate_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'db_index': 'True'}),
|
||||
'city': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}),
|
||||
'client_candidate_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}),
|
||||
'company_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
|
||||
'country': ('django.db.models.fields.CharField', [], {'max_length': '3', 'db_index': 'True'}),
|
||||
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'extension': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '8', 'blank': 'True'}),
|
||||
'fax': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}),
|
||||
'fax_country_code': ('django.db.models.fields.CharField', [], {'max_length': '3', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}),
|
||||
'middle_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'phone': ('django.db.models.fields.CharField', [], {'max_length': '35'}),
|
||||
'phone_country_code': ('django.db.models.fields.CharField', [], {'max_length': '3', 'db_index': 'True'}),
|
||||
'postal_code': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '16', 'blank': 'True'}),
|
||||
'salutation': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
|
||||
'state': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '20', 'blank': 'True'}),
|
||||
'suffix': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['auth.User']", 'unique': 'True'}),
|
||||
'user_updated_at': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'})
|
||||
},
|
||||
'student.userprofile': {
|
||||
'Meta': {'object_name': 'UserProfile', 'db_table': "'auth_userprofile'"},
|
||||
'courseware': ('django.db.models.fields.CharField', [], {'default': "'course.xml'", 'max_length': '255', 'blank': 'True'}),
|
||||
'gender': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '6', 'null': 'True', 'blank': 'True'}),
|
||||
'goals': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'language': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
|
||||
'level_of_education': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '6', 'null': 'True', 'blank': 'True'}),
|
||||
'location': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
|
||||
'mailing_address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'meta': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"}),
|
||||
'year_of_birth': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'student.usertestgroup': {
|
||||
'Meta': {'object_name': 'UserTestGroup'},
|
||||
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}),
|
||||
'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.User']", 'db_index': 'True', 'symmetrical': 'False'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['student']
|
||||
@@ -3,6 +3,8 @@ Models for Student Information
|
||||
|
||||
Replication Notes
|
||||
|
||||
TODO: Update this to be consistent with reality (no portal servers, no more askbot)
|
||||
|
||||
In our live deployment, we intend to run in a scenario where there is a pool of
|
||||
Portal servers that hold the canoncial user information and that user
|
||||
information is replicated to slave Course server pools. Each Course has a set of
|
||||
|
||||
@@ -388,7 +388,7 @@ class XModuleDescriptor(Plugin, HTMLSnippet, ResourceTemplates):
|
||||
entry_point = "xmodule.v1"
|
||||
module_class = XModule
|
||||
|
||||
# Attributes for inpsection of the descriptor
|
||||
# Attributes for inspection of the descriptor
|
||||
stores_state = False # Indicates whether the xmodule state should be
|
||||
# stored in a database (independent of shared state)
|
||||
has_score = False # This indicates whether the xmodule is a problem-type.
|
||||
|
||||
@@ -72,12 +72,6 @@ clone_repos() {
|
||||
git clone git@github.com:MITx/mitx.git
|
||||
fi
|
||||
|
||||
if [[ ! -d "$BASE/mitx/askbot/.git" ]]; then
|
||||
output "Cloning askbot as a submodule of mitx"
|
||||
cd "$BASE/mitx"
|
||||
git submodule update --init
|
||||
fi
|
||||
|
||||
# By default, dev environments start with a copy of 6.002x
|
||||
cd "$BASE"
|
||||
mkdir -p "$BASE/data"
|
||||
@@ -334,9 +328,6 @@ pip install -r mitx/pre-requirements.txt
|
||||
output "Installing MITx requirements"
|
||||
cd mitx
|
||||
pip install -r requirements.txt
|
||||
output "Installing askbot requirements"
|
||||
pip install -r askbot/askbot_requirements.txt
|
||||
pip install -r askbot/askbot_requirements_dev.txt
|
||||
|
||||
mkdir "$BASE/log" || true
|
||||
mkdir "$BASE/db" || true
|
||||
|
||||
@@ -27,7 +27,7 @@ You should be familiar with the following. If you're not, go read some docs...
|
||||
|
||||
- CMS -- Course Management System. The instructor-facing parts of the system. Allows instructors to see and modify their course, add lectures, problems, reorder things, etc.
|
||||
|
||||
- Askbot -- the discussion forums. We have a custom fork of this project. We're also hoping to replace it with something better later. (e.g. need support for multiple classes, etc)
|
||||
- Forums -- this is a ruby on rails service that runs on Heroku. Contributed by berkeley folks. The LMS has a wrapper lib that talks to it.
|
||||
|
||||
- Data. In the data/ dir. There is currently a single `course.xml` file that describes an entire course. Speaking of which...
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ There is also a script "create-dev-env.sh" that automates these steps.
|
||||
mkdir ~/mitx_all
|
||||
cd ~/mitx_all
|
||||
git clone git@github.com:MITx/mitx.git
|
||||
git clone git@github.com:MITx/askbot-devel
|
||||
hg clone ssh://hg-content@gp.mitx.mit.edu/data
|
||||
|
||||
2) Install OSX dependencies (Mac users only)
|
||||
@@ -49,8 +48,6 @@ There is also a script "create-dev-env.sh" that automates these steps.
|
||||
|
||||
source ~/mitx_all/python/bin/activate
|
||||
cd ~/mitx_all
|
||||
pip install -r askbot-devel/askbot_requirements.txt
|
||||
pip install -r askbot-devel/askbot_requirements_dev.txt
|
||||
pip install -r mitx/pre-requirements.txt
|
||||
pip install -r mitx/requirements.txt
|
||||
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
=============================
|
||||
Customization of Askbot skins
|
||||
=============================
|
||||
|
||||
The default skin at the moment is in the development, however
|
||||
it is already possible to start customizing your site without
|
||||
incurring much maintenance overhead.
|
||||
|
||||
Current status of templates
|
||||
===========================
|
||||
The two busiest templates are - the "main" page and the "question" page,
|
||||
the main page is more or less complete. "Question" page will be significantly
|
||||
refactored in the near future.
|
||||
|
||||
How skins work in Askbot
|
||||
========================
|
||||
|
||||
The skins reside in up to two directories:
|
||||
|
||||
* `askbot/skins` in the source code (contains any stock skins)
|
||||
* directory pointed to by a ASKBOT_EXTRA_SKINS_DIR in your settings.py
|
||||
with any other skins
|
||||
|
||||
Currently, the skin is selected by the site administrator in the live settings.
|
||||
Also, at the moment skin default is special - it serves any resources
|
||||
absent in other skins. In a way - all other skins inherit from the "default".
|
||||
|
||||
Templates and media are resolved in the following way:
|
||||
* check in skin named as in settings.ASKBOT_DEFAULT_SKIN
|
||||
* then skin named 'default'
|
||||
|
||||
How to customize a skin
|
||||
=======================
|
||||
|
||||
There are three options:
|
||||
|
||||
* edit custom css via the settings interface - good for small tweaks
|
||||
(no need to directly log in to the server)
|
||||
* create a new skin in separate files (need direct access to the server
|
||||
files, more maintenance overhead)
|
||||
* directly modify the "default" skin (as in the previous option - need
|
||||
direct access to the server, less maintenance overhead, some
|
||||
knowledge of git system is required)
|
||||
|
||||
The first option only allows to modify css and add custom javascript.
|
||||
The latter two options allow changing the templates as well.
|
||||
|
||||
If you wish to follow the second option, create a directory named the same
|
||||
way as the skin you are building and start adding files with the same names
|
||||
and relative locations as those in the "default" skin.
|
||||
|
||||
NO NEED TO CREATE ALL TEMPLATES/MEDIA FILES AT ONCE as your skin will inherit
|
||||
pieces from the "default".
|
||||
|
||||
The disadvantage of thil second approach is that you will be on your own maintaining
|
||||
the synchrony of your template, stylesheet and the core code.
|
||||
|
||||
Third approach is the best, but it requires (the most basic) use of
|
||||
git source code management software. With git you will easily merge the updates
|
||||
from the development repository.
|
||||
|
||||
Structure of the skin directories
|
||||
=================================
|
||||
Todo.
|
||||
|
||||
To simplify maintenance of the css as the skin is being developed,
|
||||
populate css file `media/style/extra.css` with any rules that will
|
||||
override those in the `media/style/style.css` file. If you do that
|
||||
|
||||
media does not have to be composed of files named the same way as in default skin
|
||||
whatever media you link to from your templates - will be in operation
|
||||
|
Before Width: | Height: | Size: 687 B |
|
Before Width: | Height: | Size: 263 B |
|
Before Width: | Height: | Size: 236 B |
|
Before Width: | Height: | Size: 593 B |
|
Before Width: | Height: | Size: 69 B |
|
Before Width: | Height: | Size: 64 B |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 226 B |
|
Before Width: | Height: | Size: 337 B |
|
Before Width: | Height: | Size: 293 B |
|
Before Width: | Height: | Size: 714 B |
|
Before Width: | Height: | Size: 44 B |
|
Before Width: | Height: | Size: 419 B |
|
Before Width: | Height: | Size: 603 B |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 61 B |
|
Before Width: | Height: | Size: 56 B |
|
Before Width: | Height: | Size: 758 B |
|
Before Width: | Height: | Size: 126 B |
|
Before Width: | Height: | Size: 135 B |
|
Before Width: | Height: | Size: 78 B |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 669 B |
|
Before Width: | Height: | Size: 371 B |
|
Before Width: | Height: | Size: 361 B |
|
Before Width: | Height: | Size: 369 B |
|
Before Width: | Height: | Size: 361 B |
|
Before Width: | Height: | Size: 369 B |
|
Before Width: | Height: | Size: 370 B |
|
Before Width: | Height: | Size: 363 B |
|
Before Width: | Height: | Size: 368 B |
|
Before Width: | Height: | Size: 244 B |
|
Before Width: | Height: | Size: 366 B |
|
Before Width: | Height: | Size: 365 B |
|
Before Width: | Height: | Size: 361 B |
|
Before Width: | Height: | Size: 378 B |
|
Before Width: | Height: | Size: 365 B |
|
Before Width: | Height: | Size: 376 B |
|
Before Width: | Height: | Size: 370 B |
|
Before Width: | Height: | Size: 363 B |
|
Before Width: | Height: | Size: 368 B |
|
Before Width: | Height: | Size: 361 B |
|
Before Width: | Height: | Size: 359 B |
|
Before Width: | Height: | Size: 358 B |
|
Before Width: | Height: | Size: 360 B |
|
Before Width: | Height: | Size: 367 B |
|
Before Width: | Height: | Size: 374 B |
|
Before Width: | Height: | Size: 368 B |
|
Before Width: | Height: | Size: 367 B |
|
Before Width: | Height: | Size: 373 B |
|
Before Width: | Height: | Size: 359 B |
|
Before Width: | Height: | Size: 367 B |
|
Before Width: | Height: | Size: 351 B |
|
Before Width: | Height: | Size: 377 B |
|
Before Width: | Height: | Size: 376 B |
|
Before Width: | Height: | Size: 364 B |
|
Before Width: | Height: | Size: 361 B |
|
Before Width: | Height: | Size: 368 B |
|
Before Width: | Height: | Size: 376 B |
|
Before Width: | Height: | Size: 238 B |
|
Before Width: | Height: | Size: 371 B |
|
Before Width: | Height: | Size: 243 B |
|
Before Width: | Height: | Size: 364 B |
|
Before Width: | Height: | Size: 359 B |
|
Before Width: | Height: | Size: 332 B |
|
Before Width: | Height: | Size: 368 B |
|
Before Width: | Height: | Size: 362 B |
|
Before Width: | Height: | Size: 364 B |
|
Before Width: | Height: | Size: 369 B |
|
Before Width: | Height: | Size: 366 B |
|
Before Width: | Height: | Size: 353 B |
|
Before Width: | Height: | Size: 359 B |
|
Before Width: | Height: | Size: 364 B |
|
Before Width: | Height: | Size: 367 B |
|
Before Width: | Height: | Size: 367 B |
|
Before Width: | Height: | Size: 363 B |
|
Before Width: | Height: | Size: 365 B |
|
Before Width: | Height: | Size: 362 B |
|
Before Width: | Height: | Size: 362 B |
|
Before Width: | Height: | Size: 369 B |
|
Before Width: | Height: | Size: 374 B |
|
Before Width: | Height: | Size: 368 B |
|
Before Width: | Height: | Size: 362 B |
|
Before Width: | Height: | Size: 370 B |
|
Before Width: | Height: | Size: 362 B |
|
Before Width: | Height: | Size: 364 B |
|
Before Width: | Height: | Size: 363 B |